95char *option[N_OPTIONS] = {
112#define FL_TRUNCATE 0x0001
113#define FL_PADWITHZEROES 0x0002
114#define FL_NORMALIZE 0x0004
115#define FL_SUPPRESSAVERAGE 0x0008
116#define FL_FULLOUTPUT 0x0010
117#define FL_MAKEFREQDATA 0x0020
118#define FL_PSDOUTPUT 0x0040
119#define FL_PSDINTEGOUTPUT 0x0080
120#define FL_PSDRINTEGOUTPUT 0x0100
121#define FL_FULLOUTPUT_FOLDED 0x0200
122#define FL_FULLOUTPUT_UNFOLDED 0x0400
123#define FL_COMPLEXINPUT_FOLDED 0x0800
124#define FL_COMPLEXINPUT_UNFOLDED 0x1000
125#define FL_UNWRAP_PHASE 0x2000
128 "Usage: sdds2dfft [<inputfile>] [<outputfile>]\n"
129 " [-pipe=[input][,output]]\n"
130 " -columns=<indep-variable>[,<depen-quantity>[,...]]\n"
131 " [-complexInput[=unfolded|folded]]\n"
132 " [-exclude=<depen-quantity>[,...]]\n"
133 " [-sampleInterval=<number>]\n"
135 " [-fullOutput[=unfolded|folded],unwrapLimit=<value>]\n"
136 " [-psdOutput[=plain][,{integrated|rintegrated[=<cutoff>]}]]\n"
138 " [-padwithzeroes[=exponent]]\n"
140 " [-suppressaverage]\n"
142 " [-majorOrder=row|column]\n"
144 " -pipe=[input][,output]\n"
145 " The standard SDDS Toolkit pipe option.\n"
146 " -columns=<indep-variable>[,<depen-quantity>[,...]]\n"
147 " Specifies the independent variable and dependent quantities to Fourier analyze.\n"
148 " <depen-quantity> entries may contain wildcards.\n"
149 " -complexInput[=unfolded|folded]\n"
150 " Indicates that the input columns are in complex form.\n"
152 " unfolded - The input frequency space is unfolded and must include negative frequencies.\n"
153 " folded - The input frequency space is folded (default).\n"
155 " Produces the inverse Fourier transform. The output is always an unfolded spectrum.\n"
156 " If combined with -fullOutput=folded, it will be changed to -fullOutput=unfolded.\n"
157 " -exclude=<depen-quantity>[,...]\n"
158 " Specifies a list of wild-card patterns to exclude certain quantities from analysis.\n";
161 " -sampleInterval=<number>\n"
162 " Requests sampling of the input data points with the given interval.\n"
164 " Normalizes the output to a peak magnitude of 1.\n"
165 " -fullOutput[=unfolded|folded],unwrapLimit=<value>\n"
166 " Requests output of the real and imaginary parts of the FFT.\n"
168 " unfolded - Outputs the unfolded frequency-space (full FFT).\n"
169 " folded - Outputs the folded frequency-space (half FFT) (default).\n"
170 " Additional parameter:\n"
171 " unwrapLimit=<value> - Unwraps the phase where the relative magnitude exceeds this limit.\n"
172 " -psdOutput[=plain][,{integrated|rintegrated[=<cutoff>]}]\n"
173 " Requests output of the Power Spectral Density (PSD).\n"
175 " plain - Includes plain PSD output.\n"
176 " integrated - Includes integrated PSD.\n"
177 " rintegrated - Includes reverse-integrated PSD with an optional cutoff frequency.\n"
178 " -padwithzeroes[=exponent] | -truncate\n"
179 " -padwithzeroes: Pads the data with zeroes if the number of data points is not a product of small primes.\n"
180 " Optionally specify an exponent to determine the padding factor.\n"
181 " -truncate: Truncates the data if the number of data points is not a product of small primes.\n"
182 " -suppressaverage\n"
183 " Removes the average value of the data before performing the FFT.\n"
185 " Suppresses warning messages.\n"
186 " -majorOrder=row|column\n"
187 " Specifies the output file's data order.\n"
188 " row - Row-major order.\n"
189 " column - Column-major order.\n\n"
190 "Program by Hairong Shang. (" __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")\n";
192int64_t greatestProductOfSmallPrimes(int64_t rows);
193long create_fft_frequency_column(
SDDS_DATASET *SDDSout,
SDDS_DATASET *SDDSin,
char *timeName,
char *freqUnits,
long inverse);
196 char *freqUnits,
long full_output,
unsigned long psd_output,
long complexInput,
197 long inverse,
long unwrap_phase);
199char *makeFrequencyUnits(
SDDS_DATASET *SDDSin,
char *indepName);
200long expandComplexColumnPairNames(
SDDS_DATASET *SDDSin,
char **name,
char ***realName,
char ***imagName,
201 long names,
char **excludeName,
long excludeNames,
long typeMode,
long typeValue);
202void moveToStringArrayComplex(
char ***targetReal,
char ***targetImag,
long *targets,
char **sourceReal,
char **sourceImag,
long sources);
204int main(
int argc,
char **argv) {
207 char *indepQuantity, **depenQuantity, **exclude, **realQuan = NULL, **imagQuan = NULL;
208 long depenQuantities, excludes;
209 char *input, *output;
210 long sampleInterval, readCode, noWarnings, complexInput, inverse, spectrumFoldParExist = 0, colsToUse;
211 int64_t i, rows, rowsToUse, primeRows, pow2Rows, n_freq, fftrows;
212 int32_t spectrumFolded = 0, page = 0, index;
213 unsigned long flags, pipeFlags, complexInputFlags = 0, fullOutputFlags = 0, majorOrderFlag;
214 long primeCols, pow2Cols;
215 SCANNED_ARG *scanned;
217 double *tdata, rintegCutOffFreq, unwrapLimit = 0;
219 short columnMajorOrder = -1;
220 double length, *real_imag = NULL, **real = NULL, **imag = NULL, *real_imag1 = NULL, *fdata = NULL, df, t0, factor;
221 double dtf_real, dtf_imag, *arg = NULL, *magData = NULL;
222 char str[256], *tempStr = NULL;
225 argc =
scanargs(&scanned, argc, argv);
226 if (argc < 3 || argc > (3 + N_OPTIONS)) {
227 fprintf(stderr,
"%s%s", USAGE1, USAGE2);
230 rintegCutOffFreq = 0;
231 output = input = NULL;
232 flags = pipeFlags = excludes = complexInput = inverse = 0;
234 indepQuantity = NULL;
235 depenQuantity = exclude = NULL;
240 for (iArg = 1; iArg < argc; iArg++) {
241 if (scanned[iArg].arg_type == OPTION) {
243 switch (
match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
245 flags |= FL_NORMALIZE;
247 case SET_PADWITHZEROES:
248 flags |= FL_PADWITHZEROES;
249 if (scanned[iArg].n_items != 1) {
250 if (scanned[iArg].n_items != 2 || sscanf(scanned[iArg].list[1],
"%ld", &padFactor) != 1 || padFactor < 1)
251 SDDS_Bomb(
"invalid -padwithzeroes syntax");
255 flags |= FL_TRUNCATE;
257 case SET_SUPPRESSAVERAGE:
258 flags |= FL_SUPPRESSAVERAGE;
260 case SET_SAMPLEINTERVAL:
261 if (scanned[iArg].n_items != 2 || sscanf(scanned[iArg].list[1],
"%ld", &sampleInterval) != 1 || sampleInterval <= 0)
262 SDDS_Bomb(
"invalid -sampleinterval syntax");
266 SDDS_Bomb(
"only one -columns option may be given");
267 if (scanned[iArg].n_items < 2)
269 indepQuantity = scanned[iArg].list[1];
270 if (scanned[iArg].n_items >= 2) {
271 depenQuantity =
tmalloc(
sizeof(*depenQuantity) * (depenQuantities = scanned[iArg].n_items - 2));
272 for (i = 0; i < depenQuantities; i++)
277 flags |= FL_FULLOUTPUT;
278 if (scanned[iArg].n_items >= 2) {
279 scanned[iArg].n_items--;
280 if (!
scanItemList(&fullOutputFlags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
"folded", -1, NULL, 0, FL_FULLOUTPUT_FOLDED,
"unfolded", -1, NULL, 0, FL_FULLOUTPUT_UNFOLDED,
"unwrapLimit",
SDDS_DOUBLE, &unwrapLimit, 0, FL_UNWRAP_PHASE, NULL))
282 scanned[iArg].n_items++;
283 if (fullOutputFlags & FL_FULLOUTPUT_UNFOLDED)
284 flags |= FL_FULLOUTPUT_UNFOLDED;
286 flags |= FL_FULLOUTPUT_FOLDED;
287 if (fullOutputFlags & FL_UNWRAP_PHASE)
288 flags |= FL_UNWRAP_PHASE;
292 if (!
processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags))
296 if (scanned[iArg].n_items > 1) {
297 unsigned long tmpFlags;
298 if (strchr(scanned[iArg].list[1],
'=') == NULL) {
299 if (!
scanItemList(&tmpFlags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
"integrated", -1, NULL, 0, FL_PSDINTEGOUTPUT,
"rintegrated", -1, NULL, 0, FL_PSDRINTEGOUTPUT,
"plain", -1, NULL, 0, FL_PSDOUTPUT, NULL))
302 if (!
scanItemList(&tmpFlags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
"integrated", -1, NULL, 0, FL_PSDINTEGOUTPUT,
"rintegrated",
SDDS_DOUBLE, &rintegCutOffFreq, 0, FL_PSDRINTEGOUTPUT,
"plain", -1, NULL, 0, FL_PSDOUTPUT, NULL))
307 flags |= FL_PSDOUTPUT;
309 if ((flags & FL_PSDINTEGOUTPUT) && (flags & FL_PSDRINTEGOUTPUT))
310 SDDS_Bomb(
"invalid -psdOutput syntax: give only one of integrated or rintegrated");
313 if (scanned[iArg].n_items < 2)
315 moveToStringArray(&exclude, &excludes, scanned[iArg].list + 1, scanned[iArg].n_items - 1);
320 case SET_COMPLEXINPUT:
322 if (scanned[iArg].n_items == 2) {
323 scanned[iArg].n_items--;
324 if (!
scanItemList(&complexInputFlags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
"folded", -1, NULL, 0, FL_COMPLEXINPUT_FOLDED,
"unfolded", -1, NULL, 0, FL_COMPLEXINPUT_UNFOLDED, NULL))
325 SDDS_Bomb(
"Invalid -complexInput syntax");
326 scanned[iArg].n_items++;
332 case SET_MAJOR_ORDER:
334 scanned[iArg].n_items--;
335 if (scanned[iArg].n_items > 0 && (!
scanItemList(&majorOrderFlag, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
"row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
"column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
336 SDDS_Bomb(
"invalid -majorOrder syntax/values");
337 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
338 columnMajorOrder = 1;
339 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
340 columnMajorOrder = 0;
343 fprintf(stderr,
"error: unknown/ambiguous option: %s\n", scanned[iArg].list[0]);
349 input = scanned[iArg].list[0];
351 output = scanned[iArg].list[0];
357 if (!noWarnings && inverse)
358 fprintf(stderr,
"Warning: The inverse option is ignored since it only works with -complexInput.\n");
361 if (!noWarnings && inverse && (flags & FL_FULLOUTPUT_FOLDED))
362 fprintf(stderr,
"Warning: The combination of -inverse and -fullOutput=folded will be changed to -inverse -fullOutput=unfolded.\n");
367 SDDS_Bomb(
"Supply the independent quantity name with the -columns option");
369 if ((flags & FL_TRUNCATE) && (flags & FL_PADWITHZEROES))
370 SDDS_Bomb(
"Specify only one of -padwithzeroes and -truncate");
373 flags |= FL_FULLOUTPUT;
374 flags |= FL_FULLOUTPUT_UNFOLDED;
382 excludes = appendToStringArray(&exclude, excludes, indepQuantity);
383 if (!depenQuantities)
384 depenQuantities = appendToStringArray(&depenQuantity, depenQuantities,
"*");
387 if ((depenQuantities = expandColumnPairNames(&SDDSin, &depenQuantity, NULL, depenQuantities, exclude, excludes, FIND_NUMERIC_TYPE, 0)) <= 0) {
389 SDDS_Bomb(
"No quantities selected to FFT");
392 if ((depenQuantities = expandComplexColumnPairNames(&SDDSin, depenQuantity, &realQuan, &imagQuan, depenQuantities, exclude, excludes, FIND_NUMERIC_TYPE, 0)) <= 0) {
394 SDDS_Bomb(
"No quantities selected to FFT");
399 fprintf(stderr,
"%ld dependent quantities:\n", depenQuantities);
400 for (i = 0; i < depenQuantities; i++)
401 fprintf(stderr,
" %s\n", depenQuantity[i]);
404 if (!(freqUnits = makeFrequencyUnits(&SDDSin, indepQuantity)) ||
406 !create_fft_frequency_column(&SDDSout, &SDDSin, indepQuantity, freqUnits, inverse) ||
410 if (columnMajorOrder != -1)
411 SDDSout.layout.data_mode.column_major = columnMajorOrder;
413 SDDSout.layout.data_mode.column_major = SDDSin.layout.data_mode.column_major;
418 if (!complexInputFlags) {
420 spectrumFoldParExist = 1;
421 }
else if (complexInputFlags & FL_COMPLEXINPUT_UNFOLDED)
422 flags |= FL_COMPLEXINPUT_UNFOLDED;
424 flags |= FL_COMPLEXINPUT_FOLDED;
426 for (i = 0; i < depenQuantities; i++) {
428 create_fft_columns(&SDDSout, &SDDSin, depenQuantity[i], indepQuantity, freqUnits,
429 flags & FL_FULLOUTPUT, flags & (FL_PSDOUTPUT + FL_PSDINTEGOUTPUT + FL_PSDRINTEGOUTPUT),
430 0, inverse, flags & FL_UNWRAP_PHASE);
432 create_fft_columns(&SDDSout, &SDDSin, realQuan[i], indepQuantity, freqUnits,
433 flags & FL_FULLOUTPUT, flags & (FL_PSDOUTPUT + FL_PSDINTEGOUTPUT + FL_PSDRINTEGOUTPUT),
434 1, inverse, flags & FL_UNWRAP_PHASE);
440 colsToUse = depenQuantities;
441 primeCols = greatestProductOfSmallPrimes(depenQuantities);
442 if (depenQuantities != primeCols || padFactor) {
443 if (flags & FL_PADWITHZEROES) {
444 pow2Cols =
ipow(2., ((
long)(log((
double)depenQuantities) / log(2.0F))) + (padFactor ? padFactor : 1));
445 if ((primeCols = greatestProductOfSmallPrimes(pow2Cols)) > depenQuantities)
446 colsToUse = primeCols;
448 colsToUse = pow2Cols;
449 fprintf(stdout,
"Using %ld columns\n", colsToUse);
450 }
else if (flags & FL_TRUNCATE)
451 colsToUse = greatestProductOfSmallPrimes(depenQuantities);
453 fputs(
"Warning: Number of dependent columns has large prime factors.\nThis could take a very long time.\nConsider using the -truncate option.\n", stderr);
455 real_imag =
tmalloc(
sizeof(*real_imag) * (2 * colsToUse + 2));
456 real = malloc(
sizeof(*real) * colsToUse);
457 imag = malloc(
sizeof(*imag) * colsToUse);
463 if (page == 1 && spectrumFoldParExist) {
467 flags |= FL_COMPLEXINPUT_FOLDED;
469 flags |= FL_COMPLEXINPUT_UNFOLDED;
473 primeRows = greatestProductOfSmallPrimes(rows);
474 if (rows != primeRows || padFactor) {
475 if (flags & FL_PADWITHZEROES) {
476 pow2Rows =
ipow(2., ((
long)(log((
double)rows) / log(2.0F))) + (padFactor ? padFactor : 1));
477 if ((primeRows = greatestProductOfSmallPrimes(pow2Rows)) > rows)
478 rowsToUse = primeRows;
480 rowsToUse = pow2Rows;
481 fprintf(stdout,
"Using %" PRId64
" rows\n", rowsToUse);
482 }
else if (flags & FL_TRUNCATE)
483 rowsToUse = greatestProductOfSmallPrimes(rows);
485 fputs(
"Warning: Number of points has large prime factors.\nThis could take a very long time.\nConsider using the -truncate option.\n", stderr);
490 for (j = 0; j < colsToUse; j++) {
491 real[j] = imag[j] = NULL;
492 if (j < depenQuantities) {
500 imag[j] = calloc(
sizeof(**imag), rowsToUse);
502 if (rows < rowsToUse) {
503 real[j] =
SDDS_Realloc(real[j],
sizeof(**real) * rowsToUse);
504 imag[j] =
SDDS_Realloc(imag[j],
sizeof(**imag) * rowsToUse);
507 real[j] = calloc(
sizeof(**real), rowsToUse);
508 imag[j] = calloc(
sizeof(**imag), rowsToUse);
511 fdata = malloc(
sizeof(*fdata) * rowsToUse);
512 if (rows < rowsToUse) {
513 length = ((double)rows) * (tdata[rows - 1] - tdata[0]) / ((double)rows - 1.0);
515 length = tdata[rows - 1] - tdata[0];
517 df = factor = 1.0 / length;
519 for (i = 0; i < rows; i++)
521 for (i = rows; i < rowsToUse; i++) {
525 for (i = 0; i < rows; i++) {
526 for (j = 0; j < colsToUse; j++) {
527 real_imag[2 * j] = real_imag[2 * j + 1] = 0;
528 if (j < depenQuantities) {
529 real_imag[2 * j] = real[j][i];
531 real_imag[2 * j + 1] = imag[j][i];
533 real_imag[2 * j + 1] = 0;
536 complexFFT(real_imag, colsToUse, inverse);
537 for (j = 0; j < colsToUse; j++) {
538 real[j][i] = real_imag[2 * j];
539 imag[j][i] = real_imag[2 * j + 1];
545 arg = malloc(
sizeof(*arg) * rowsToUse);
546 magData = malloc(
sizeof(*magData) * rowsToUse);
547 real_imag1 = calloc(
sizeof(*real_imag1), 2 * fftrows + 2);
549 for (j = 0; j < depenQuantities; j++) {
550 for (i = 0; i < rowsToUse; i++) {
552 real_imag1[2 * i] = real[j][i];
553 real_imag1[2 * i + 1] = imag[j][i];
555 real_imag1[2 * i] = 0;
556 real_imag1[2 * i + 1] = 0;
559 complexFFT(real_imag1, rowsToUse, inverse);
560 for (i = 0; i < n_freq; i++) {
561 dtf_real = cos(-2 * PI * fdata[i] * t0);
562 dtf_imag = sin(-2 * PI * fdata[i] * t0);
563 real[j][i] = real_imag1[2 * i] * dtf_real - real_imag1[2 * i + 1] * dtf_imag;
564 imag[j][i] = real_imag1[2 * i + 1] * dtf_real + real_imag1[2 * i] * dtf_imag;
565 magData[i] = sqrt(sqr(real[j][i]) + sqr(imag[j][i]));
566 if (real[j][i] || imag[j][i])
567 arg[i] = 180.0 / PI * atan2(imag[j][i], real[j][i]);
571 if (flags & FL_NORMALIZE) {
573 for (i = 0; i < n_freq; i++)
574 if (magData[i] > factor)
576 if (factor != -DBL_MAX)
577 for (i = 0; i < n_freq; i++) {
578 real[j][i] /= factor;
579 imag[j][i] /= factor;
580 magData[i] /= factor;
584 sprintf(str,
"FFT%s", depenQuantity[j] + (imagQuan ? 4 : 0));
587 tempStr = realQuan[j];
589 tempStr = depenQuantity[j];
591 if (strncmp(tempStr,
"FFT", 3) == 0)
592 sprintf(str,
"%s", tempStr + 3);
593 else if (strncmp(tempStr,
"RealFFT", 7) == 0)
594 sprintf(str,
"%s", tempStr + 7);
596 sprintf(str,
"%s", tempStr);
602 !
SDDS_SetParameters(&SDDSout, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE,
"fftFrequencies", n_freq,
"fftFrequencySpacing", df, NULL))
604 if (flags & FL_FULLOUTPUT) {
605 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, magData, n_freq, index) ||
606 !
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, real[j], n_freq, index + 1) ||
607 !
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, imag[j], n_freq, index + 2) ||
608 !
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, arg, n_freq, index + 3))
611 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, real[j], n_freq, index))
615 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, fdata, n_freq, 0))
620 for (j = 0; j < colsToUse; j++) {
662static long psdOffset, argOffset, realOffset, imagOffset, fftOffset = -1, psdIntOffset, unwrappedArgOffset = -1;
664long create_fft_frequency_column(
SDDS_DATASET *SDDSout,
SDDS_DATASET *SDDSin,
char *timeName,
char *freqUnits,
long inverse) {
665 char s[SDDS_MAXLINE];
674 sprintf(s,
"Frequency for %s", timeSymbol);
683 sprintf(s,
"inverse for %s", timeSymbol);
697 char *freqUnits,
long full_output,
unsigned long psd_output,
long complexInput,
698 long inverse,
long unwrap_phase) {
699 char s[SDDS_MAXLINE];
700 char *origUnits, *origSymbol;
701 char *description, *name, *symbol, *units;
711 sprintf(s,
"FFT%s", origName + offset);
713 if (strncmp(origName,
"FFT", 3) == 0)
715 else if (strncmp(origName,
"RealFFT", 7) == 0)
719 sprintf(s,
"%s", origName + offset);
724 sprintf(s,
"FFT %s", origSymbol);
727 sprintf(s,
"Amplitude of FFT of %s", origSymbol);
740 if (psd_output & FL_PSDOUTPUT) {
743 sprintf(s,
"(%s)$a2$n/(%s)", origUnits, freqUnits);
745 sprintf(s,
"(%s)$a2$n", origUnits);
750 sprintf(s,
"PSD%s", origName + offset);
755 sprintf(s,
"PSD %s", origSymbol);
758 sprintf(s,
"PSD of %s", origSymbol);
764 psdOffset = index1 - index0;
772 if (psd_output & (FL_PSDINTEGOUTPUT + FL_PSDRINTEGOUTPUT)) {
778 sprintf(s,
"SqrtIntegPSD%s", origName + offset);
783 sprintf(s,
"Sqrt Integ PSD %s", origSymbol);
786 sprintf(s,
"Sqrt Integ PSD of %s", origSymbol);
792 psdIntOffset = index1 - index0;
802 sprintf(s,
"RealFFT%s", origName + offset);
804 sprintf(s,
"Real%s", origName + offset);
810 sprintf(s,
"Re[FFT %s]", origSymbol);
812 sprintf(s,
"Re[%s]", origSymbol);
816 sprintf(s,
"Real part of FFT of %s", origSymbol);
818 sprintf(s,
"Real part of %s", origSymbol);
824 realOffset = index1 - index0;
830 sprintf(s,
"ImagFFT%s", origName + offset);
832 sprintf(s,
"Imag%s", origName + offset);
838 sprintf(s,
"Im[FFT %s]", origSymbol);
840 sprintf(s,
"Im[%s]", origSymbol);
844 sprintf(s,
"Imaginary part of FFT of %s", origSymbol);
846 sprintf(s,
"Imaginary part of %s", origSymbol);
852 imagOffset = index1 - index0;
858 sprintf(s,
"ArgFFT%s", origName + offset);
860 sprintf(s,
"Arg%s", origName + offset);
866 sprintf(s,
"Arg[FFT %s]", origSymbol);
868 sprintf(s,
"Arg[%s]", origSymbol);
872 sprintf(s,
"Phase of FFT of %s", origSymbol);
874 sprintf(s,
"Phase of %s", origSymbol);
880 argOffset = index1 - index0;
886 sprintf(s,
"UnwrapArgFFT%s", origName + offset);
888 sprintf(s,
"UnwrapArg%s", origName + offset);
894 sprintf(s,
"UnwrapArg[FFT %s]", origSymbol);
896 sprintf(s,
"UnwrapArg[%s]", origSymbol);
900 sprintf(s,
"Unwrapped Phase of FFT of %s", origSymbol);
902 sprintf(s,
"Unwrapped Phase of %s", origSymbol);
908 unwrappedArgOffset = index1 - index0;
919long expandComplexColumnPairNames(
SDDS_DATASET *SDDSin,
char **name,
char ***realName,
char ***imagName,
long names,
920 char **excludeName,
long excludeNames,
long typeMode,
long typeValue) {
921 long i, j, k, realNames, imagNames, names2;
922 char **realName1, **imagName1, **realName2, **imagName2;
923 char *realPattern, *imagPattern = NULL;
928 realName1 = imagName1 = realName2 = imagName2 = NULL;
929 realNames = imagNames = names2 = 0;
930 for (i = longest = 0; i < names; i++) {
931 if (strlen(name[i]) > longest)
932 longest = strlen(name[i]);
935 if (!(realPattern =
SDDS_Malloc(
sizeof(*realPattern) * longest)) ||
936 !(imagPattern =
SDDS_Malloc(
sizeof(*imagPattern) * longest)))
939 for (i = 0; i < names; i++) {
940 for (j = 0; j < 2; j++) {
942 sprintf(realPattern,
"Real%s", name[i]);
943 sprintf(imagPattern,
"Imag%s", name[i]);
945 sprintf(realPattern,
"%sReal", name[i]);
946 sprintf(imagPattern,
"%sImag", name[i]);
950 case FIND_NUMERIC_TYPE:
951 case FIND_INTEGER_TYPE:
952 case FIND_FLOATING_TYPE:
953 realNames =
SDDS_MatchColumns(SDDSin, &realName1, SDDS_MATCH_STRING, typeMode, realPattern, SDDS_0_PREVIOUS | SDDS_OR);
954 imagNames =
SDDS_MatchColumns(SDDSin, &imagName1, SDDS_MATCH_STRING, typeMode, imagPattern, SDDS_0_PREVIOUS | SDDS_OR);
956 case FIND_SPECIFIED_TYPE:
958 SDDS_Bomb(
"Invalid type value in expandColumnPairNames");
959 realNames =
SDDS_MatchColumns(SDDSin, &realName1, SDDS_MATCH_STRING, typeMode, typeValue, realPattern, SDDS_0_PREVIOUS | SDDS_OR);
960 imagNames =
SDDS_MatchColumns(SDDSin, &imagName1, SDDS_MATCH_STRING, typeMode, typeValue, imagPattern, SDDS_0_PREVIOUS | SDDS_OR);
963 SDDS_Bomb(
"Invalid typeMode in expandColumnPairNames");
969 if (realNames == -1 || imagNames == -1) {
971 SDDS_Bomb(
"Unable to perform column name match in expandColumnPairNames");
973 if (realNames != imagNames)
974 SDDS_Bomb(
"Found different number of real and imaginary columns");
976 for (j = 0; j < excludeNames; j++)
977 for (k = 0; k < realNames; k++)
978 if (
wild_match(realName1[k], excludeName[j])) {
981 imagName1[k] = realName1[k] = NULL;
984 moveToStringArrayComplex(&realName2, &imagName2, &names2, realName1, imagName1, realNames);
993 *realName = realName2;
994 *imagName = imagName2;
998void moveToStringArrayComplex(
char ***targetReal,
char ***targetImag,
long *targets,
char **sourceReal,
char **sourceImag,
long sources) {
1002 if (!(*targetReal =
SDDS_Realloc(*targetReal,
sizeof(**targetReal) * (*targets + sources))) ||
1003 !(*targetImag =
SDDS_Realloc(*targetImag,
sizeof(**targetImag) * (*targets + sources))))
1005 for (i = 0; i < sources; i++) {
1006 if (sourceReal[i] == NULL || sourceImag[i] == NULL)
1008 for (j = 0; j < *targets; j++)
1009 if (strcmp(sourceReal[i], (*targetReal)[j]) == 0)
1011 if (j == *targets) {
1012 (*targetReal)[j] = sourceReal[i];
1013 (*targetImag)[j] = sourceImag[i];
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_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_SetParameters(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
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_InitializeOutput(SDDS_DATASET *SDDS_dataset, int32_t data_mode, int32_t lines_per_row, const char *description, const char *contents, const char *filename)
Initializes the SDDS output 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_DefineParameter(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, char *fixed_value)
Defines a data parameter with a fixed string value.
int32_t SDDS_TransferAllParameterDefinitions(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, uint32_t mode)
Transfers all parameter definitions from a source dataset to a target dataset.
int32_t SDDS_FreeStringArray(char **string, int64_t strings)
Frees an array of strings by deallocating each individual string.
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_Malloc(size_t size)
Allocates memory of a specified size.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
int32_t SDDS_NumberOfErrors()
Retrieves the number of errors recorded by SDDS library routines.
int32_t SDDS_StringIsBlank(char *s)
Checks if a string is blank (contains only whitespace characters).
int32_t SDDS_MatchColumns(SDDS_DATASET *SDDS_dataset, char ***nameReturn, int32_t matchMode, int32_t typeMode,...)
Matches and retrieves column names from an SDDS dataset based on specified criteria.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
int32_t SDDS_CheckParameter(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a parameter exists in the SDDS dataset with the specified name, units, and type.
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
#define SDDS_VALID_TYPE(type)
Validates whether the given type identifier is within the defined range of SDDS types.
#define SDDS_STRING
Identifier for the string data type.
#define SDDS_LONG
Identifier for the signed 32-bit integer 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.
Utility functions for SDDS dataset manipulation and string array operations.
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
int64_t largest_prime_factor(int64_t number)
Find the largest prime factor of a number.
double ipow(const double x, const int64_t p)
Compute x raised to the power p (x^p).
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)
void free_scanargs(SCANNED_ARG **scanned, int argc)
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.
int wild_match(char *string, char *template)
Determine whether one string is a wildcard match for another.