64char *option[N_OPTIONS] = {
72 "Usage: sddsanalyticsignal [<inputfile>] [<outputfile>]\n"
73 " [-pipe=<input>,<output>]\n"
74 " [-unwrapLimit=<value>]\n"
75 " [-columns=<indep-variable>,<depen-quantity>[,...]]\n"
76 " [-majorOrder=row|column]\n\n"
78 " -pipe Use standard SDDS Toolkit pipe with optional input and output.\n"
79 " -columns Specify the independent variable and dependent quantities to analyze.\n"
80 " <depen-quantity> entries may include wildcards.\n"
81 " -unwrapLimit Set the relative magnitude limit for phase unwrapping.\n"
82 " Phase is only unwrapped when the relative magnitude exceeds this limit.\n"
83 " -majorOrder Define the output file's major order as either 'row' or 'column'.\n\n"
85 " sddsanalyticsignal computes the complex output of a real signal and generates the following columns:\n"
86 " Real<signal>, Imag<signal>, Mag<signal>, and Arg<signal>.\n"
87 " These represent the Real part, Imaginary part, Magnitude, and Phase of the signal, respectively.\n\n"
88 "Program by Hairong Shang and Louis Emery.\n"
89 "Compiled on " __DATE__
" at " __TIME__
", SVN revision: " SVN_VERSION
"\n";
91long process_data(
SDDS_DATASET *SDDSout,
SDDS_DATASET *SDDSin, int64_t rows,
char *depenQuantity,
double unwrapLimit);
95int main(
int argc,
char **argv) {
97 char *indepQuantity, **depenQuantity, **exclude = NULL;
98 long depenQuantities, excludes = 0;
103 unsigned long pipeFlags, majorOrderFlag;
104 SCANNED_ARG *scanned;
106 short columnMajorOrder = -1;
107 double unwrapLimit = 0;
110 argc =
scanargs(&scanned, argc, argv);
112 fprintf(stderr,
"%s\n", USAGE);
116 output = input = NULL;
118 indepQuantity = NULL;
119 depenQuantity = NULL;
122 for (iArg = 1; iArg < argc; iArg++) {
123 if (scanned[iArg].arg_type == OPTION) {
125 switch (
match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
128 SDDS_Bomb(
"Only one -columns option may be given");
129 if (scanned[iArg].n_items < 2)
131 indepQuantity = scanned[iArg].list[1];
132 if (scanned[iArg].n_items >= 2) {
133 depenQuantity =
tmalloc(
sizeof(*depenQuantity) * (depenQuantities = scanned[iArg].n_items - 2));
134 for (i = 0; i < depenQuantities; i++)
135 depenQuantity[i] = scanned[iArg].list[i + 2];
140 if (!
processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags))
144 case SET_MAJOR_ORDER:
146 scanned[iArg].n_items--;
147 if (scanned[iArg].n_items > 0 &&
148 !
scanItemList(&majorOrderFlag, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
149 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
150 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL))
151 SDDS_Bomb(
"Invalid -majorOrder syntax/values");
152 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
153 columnMajorOrder = 1;
154 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
155 columnMajorOrder = 0;
158 case SET_UNWRAP_LIMIT:
159 if (scanned[iArg].n_items != 2)
160 SDDS_Bomb(
"Invalid -unwrapLimit syntax/values");
161 if (!
get_double(&unwrapLimit, scanned[iArg].list[1]))
162 SDDS_Bomb(
"Invalid -unwrapLimit syntax/values");
166 fprintf(stderr,
"Error: Unknown or ambiguous option: %s\n", scanned[iArg].list[0]);
172 input = scanned[iArg].list[0];
174 output = scanned[iArg].list[0];
176 SDDS_Bomb(
"Too many filenames provided");
180 processFilenames(
"sddsanalyticsignal", &input, &output, pipeFlags, 0, NULL);
183 SDDS_Bomb(
"Supply the independent quantity name with the -columns option");
191 excludes = appendToStringArray(&exclude, excludes, indepQuantity);
193 if (!depenQuantities)
194 depenQuantities = appendToStringArray(&depenQuantity, depenQuantities,
"*");
196 if ((depenQuantities = expandColumnPairNames(&SDDSin, &depenQuantity, NULL, depenQuantities,
197 exclude, excludes, FIND_NUMERIC_TYPE, 0)) <= 0) {
199 SDDS_Bomb(
"No quantities selected to FFT");
203 fprintf(stderr,
"%ld dependent quantities:\n", depenQuantities);
204 for (i = 0; i < depenQuantities; i++)
205 fprintf(stderr,
" %s\n", depenQuantity[i]);
211 if (columnMajorOrder != -1)
212 SDDSout.layout.data_mode.column_major = columnMajorOrder;
214 SDDSout.layout.data_mode.column_major = SDDSin.layout.data_mode.column_major;
216 for (i = 0; i < depenQuantities; i++) {
217 if (!create_fft_columns(&SDDSout, &SDDSin, depenQuantity[i])) {
219 fprintf(stderr,
"Error creating output column for %s\n", depenQuantity[i]);
234 for (i = 0; i < depenQuantities; i++) {
235 if (!process_data(&SDDSout, &SDDSin, rows, depenQuantity[i], unwrapLimit)) {
263long process_data(
SDDS_DATASET *SDDSout,
SDDS_DATASET *SDDSin, int64_t rows,
char *depenQuantity,
double unwrapLimit) {
265 int64_t i, n_freq, fftrows, nhalf = 0;
266 double *real, *imag, *real_imag, *data, *magData, *arg, *unwrapped, delta, min, max, phase_correction;
275 real_imag =
tmalloc(
sizeof(
double) * (2 * fftrows + 2));
276 for (i = 0; i < fftrows; i++) {
277 real_imag[2 * i] = data[i];
278 real_imag[2 * i + 1] = 0;
280 complexFFT(real_imag, fftrows, 0);
282 nhalf = fftrows / 2 + 1;
285 for (i = nhalf; i < fftrows; i++) {
286 real_imag[2 * i] = 0;
287 real_imag[2 * i + 1] = 0;
291 for (i = 1; i < nhalf; i++) {
292 if (rows % 2 == 0 && i == rows / 2)
294 real_imag[2 * i] *= 2;
295 real_imag[2 * i + 1] *= 2;
299 complexFFT(real_imag, fftrows, INVERSE_FFT);
303 real =
tmalloc(
sizeof(
double) * n_freq);
304 imag =
tmalloc(
sizeof(
double) * n_freq);
305 magData =
tmalloc(
sizeof(
double) * n_freq);
306 arg =
tmalloc(
sizeof(*arg) * n_freq);
307 unwrapped =
tmalloc(
sizeof(*arg) * n_freq);
308 for (i = 0; i < n_freq; i++) {
309 real[i] = real_imag[2 * i];
310 imag[i] = real_imag[2 * i + 1];
311 magData[i] = sqrt(sqr(real[i]) + sqr(imag[i]));
312 if (real[i] || imag[i])
313 arg[i] = 180.0 / PI * atan2(imag[i], real[i]);
322 phase_correction = 0;
323 for (i = 0; i < n_freq; i++) {
324 if (i && magData[i] / max > unwrapLimit) {
325 delta = arg[i] - arg[i - 1];
327 phase_correction += 360.0;
328 else if (delta > 180.0)
329 phase_correction -= 360.0;
331 unwrapped[i] = arg[i] + phase_correction;
334 sprintf(s,
"Real%s", depenQuantity);
338 if (!
SDDS_SetColumn(SDDSout, SDDS_SET_BY_INDEX, real, n_freq, index1) ||
339 !
SDDS_SetColumn(SDDSout, SDDS_SET_BY_INDEX, imag, n_freq, index1 + 1) ||
340 !
SDDS_SetColumn(SDDSout, SDDS_SET_BY_INDEX, magData, n_freq, index1 + 2) ||
341 !
SDDS_SetColumn(SDDSout, SDDS_SET_BY_INDEX, arg, n_freq, index1 + 3) ||
342 !
SDDS_SetColumn(SDDSout, SDDS_SET_BY_INDEX, unwrapped, n_freq, index1 + 4))
356 char s[SDDS_MAXLINE];
357 char *origUnits, *origSymbol;
358 char *description, *name, *symbol;
365 sprintf(s,
"Real%s", origName);
369 sprintf(s,
"Re[%s]", origSymbol);
371 sprintf(s,
"Real part of %s", origSymbol);
381 sprintf(s,
"Imag%s", origName);
385 sprintf(s,
"Im[%s]", origSymbol);
387 sprintf(s,
"Imaginary part of %s", origSymbol);
397 sprintf(s,
"Mag%s", origName);
402 sprintf(s,
"Mag[%s]", origSymbol);
404 sprintf(s,
"Magnitude of %s", origSymbol);
413 sprintf(s,
"Arg%s", origName);
418 sprintf(s,
"Arg[%s]", origSymbol);
420 sprintf(s,
"Phase of %s", origSymbol);
429 sprintf(s,
"UnwrappedArg%s", origName);
434 sprintf(s,
"UnwrappedArg[%s]", origSymbol);
436 sprintf(s,
"Unwrapped Phase of %s", origSymbol);
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_CopyParameters(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
int32_t SDDS_InitializeCopy(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, char *filename, char *filemode)
int32_t SDDS_CopyPage(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_SetColumn(SDDS_DATASET *SDDS_dataset, int32_t mode, void *data, int64_t rows,...)
Sets the values for one data column in the current data table of an SDDS dataset.
int32_t SDDS_GetColumnInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Retrieves information about a specified column in the SDDS dataset.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_DefineColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, int32_t field_length)
Defines a data column within the SDDS dataset.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
int32_t SDDS_CheckColumn(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a column exists in the SDDS dataset with the specified name, units, and type.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
#define SDDS_STRING
Identifier for the string data type.
#define SDDS_ANY_NUMERIC_TYPE
Special identifier used by SDDS_Check*() routines to accept any numeric type.
#define SDDS_DOUBLE
Identifier for the double data type.
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
int get_double(double *dptr, char *s)
Parses a double value from the given string.
int find_min_max(double *min, double *max, double *list, int64_t n)
Finds the minimum and maximum values in a list of doubles.
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
long processPipeOption(char **item, long items, unsigned long *flags)
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.