98char *option[N_OPTIONS] = {
116#define FL_TRUNCATE 0x0001
117#define FL_PADWITHZEROES 0x0002
118#define FL_NORMALIZE 0x0004
119#define FL_SUPPRESSAVERAGE 0x0008
120#define FL_FULLOUTPUT 0x0010
121#define FL_MAKEFREQDATA 0x0020
122#define FL_PSDOUTPUT 0x0040
123#define FL_PSDINTEGOUTPUT 0x0080
124#define FL_PSDRINTEGOUTPUT 0x0100
125#define FL_FULLOUTPUT_FOLDED 0x0200
126#define FL_FULLOUTPUT_UNFOLDED 0x0400
127#define FL_COMPLEXINPUT_FOLDED 0x0800
128#define FL_COMPLEXINPUT_UNFOLDED 0x1000
129#define FL_UNWRAP_PHASE 0x2000
132 "Usage: sdds2dfft [<inputfile>] [<outputfile>]\n"
133 " [-pipe=[input][,output]]\n"
134 " -columns=<indep-variable>[,<depen-quantity>[,...]]\n"
135 " [-complexInput[=unfolded|folded]]\n"
136 " [-exclude=<depen-quantity>[,...]]\n"
137 " [-sampleInterval=<number>]\n"
139 " [-fullOutput[=unfolded|folded],unwrapLimit=<value>]\n"
140 " [-psdOutput[=plain][,{integrated|rintegrated[=<cutoff>]}]]\n"
142 " [-padwithzeroes[=exponent]]\n"
144 " [-suppressaverage]\n"
146 " [-majorOrder=row|column]\n"
147 " [-threads=<number>]\n"
149 " -pipe=[input][,output]\n"
150 " The standard SDDS Toolkit pipe option.\n"
151 " -columns=<indep-variable>[,<depen-quantity>[,...]]\n"
152 " Specifies the independent variable and dependent quantities to Fourier analyze.\n"
153 " <depen-quantity> entries may contain wildcards.\n"
154 " -complexInput[=unfolded|folded]\n"
155 " Indicates that the input columns are in complex form.\n"
157 " unfolded - The input frequency space is unfolded and must include negative frequencies.\n"
158 " folded - The input frequency space is folded (default).\n"
160 " Produces the inverse Fourier transform. The output is always an unfolded spectrum.\n"
161 " If combined with -fullOutput=folded, it will be changed to -fullOutput=unfolded.\n"
162 " -exclude=<depen-quantity>[,...]\n"
163 " Specifies a list of wild-card patterns to exclude certain quantities from analysis.\n";
166 " -sampleInterval=<number>\n"
167 " Requests sampling of the input data points with the given interval.\n"
169 " Normalizes the output to a peak magnitude of 1.\n"
170 " -fullOutput[=unfolded|folded],unwrapLimit=<value>\n"
171 " Requests output of the real and imaginary parts of the FFT.\n"
173 " unfolded - Outputs the unfolded frequency-space (full FFT).\n"
174 " folded - Outputs the folded frequency-space (half FFT) (default).\n"
175 " Additional parameter:\n"
176 " unwrapLimit=<value> - Unwraps the phase where the relative magnitude exceeds this limit.\n"
177 " -psdOutput[=plain][,{integrated|rintegrated[=<cutoff>]}]\n"
178 " Requests output of the Power Spectral Density (PSD).\n"
180 " plain - Includes plain PSD output.\n"
181 " integrated - Includes integrated PSD.\n"
182 " rintegrated - Includes reverse-integrated PSD with an optional cutoff frequency.\n"
183 " -padwithzeroes[=exponent] | -truncate\n"
184 " -padwithzeroes: Pads the data with zeroes if the number of data points is not a product of small primes.\n"
185 " Optionally specify an exponent to determine the padding factor.\n"
186 " -truncate: Truncates the data if the number of data points is not a product of small primes.\n"
187 " -suppressaverage\n"
188 " Removes the average value of the data before performing the FFT.\n"
190 " Suppresses warning messages.\n"
191 " -majorOrder=row|column\n"
192 " Specifies the output file's data order.\n"
193 " row - Row-major order.\n"
194 " column - Column-major order.\n"
195 " -threads=<number>\n"
196 " Number of threads for row-wise FFT work.\n\n"
197 "Program by Hairong Shang. (" __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")\n";
199int64_t greatestProductOfSmallPrimes(int64_t rows);
200long create_fft_frequency_column(
SDDS_DATASET *SDDSout,
SDDS_DATASET *SDDSin,
char *timeName,
char *freqUnits,
long inverse);
203 char *freqUnits,
long full_output,
unsigned long psd_output,
long complexInput,
204 long inverse,
long unwrap_phase);
206char *makeFrequencyUnits(
SDDS_DATASET *SDDSin,
char *indepName);
207long expandComplexColumnPairNames(
SDDS_DATASET *SDDSin,
char **name,
char ***realName,
char ***imagName,
208 long names,
char **excludeName,
long excludeNames,
long typeMode,
long typeValue);
209void moveToStringArrayComplex(
char ***targetReal,
char ***targetImag,
long *targets,
char **sourceReal,
char **sourceImag,
long sources);
211int main(
int argc,
char **argv) {
214 char *indepQuantity, **depenQuantity, **exclude, **realQuan = NULL, **imagQuan = NULL;
215 long depenQuantities, excludes;
216 char *input, *output;
217 long sampleInterval, readCode, noWarnings, complexInput, inverse, spectrumFoldParExist = 0, colsToUse;
218 int64_t i, rows, rowsToUse, primeRows, pow2Rows, n_freq, fftrows;
219 int32_t spectrumFolded = 0, page = 0, index;
220 unsigned long flags, pipeFlags, complexInputFlags = 0, fullOutputFlags = 0, majorOrderFlag;
221 long primeCols, pow2Cols;
222 SCANNED_ARG *scanned;
224 double *tdata, rintegCutOffFreq, unwrapLimit = 0;
226 short columnMajorOrder = -1;
228 double length, *real_imag = NULL, **real = NULL, **imag = NULL, *real_imag1 = NULL, *fdata = NULL, df, t0, factor;
229 double dtf_real, dtf_imag, *arg = NULL, *magData = NULL;
230 char str[256], *tempStr = NULL;
233 argc =
scanargs(&scanned, argc, argv);
234 if (argc < 3 || argc > (3 + N_OPTIONS)) {
235 fprintf(stderr,
"%s%s", USAGE1, USAGE2);
238 rintegCutOffFreq = 0;
239 output = input = NULL;
240 flags = pipeFlags = excludes = complexInput = inverse = 0;
242 indepQuantity = NULL;
243 depenQuantity = exclude = NULL;
248 for (iArg = 1; iArg < argc; iArg++) {
249 if (scanned[iArg].arg_type == OPTION) {
251 switch (
match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
253 flags |= FL_NORMALIZE;
255 case SET_PADWITHZEROES:
256 flags |= FL_PADWITHZEROES;
257 if (scanned[iArg].n_items != 1) {
258 if (scanned[iArg].n_items != 2 || sscanf(scanned[iArg].list[1],
"%ld", &padFactor) != 1 || padFactor < 1)
259 SDDS_Bomb(
"invalid -padwithzeroes syntax");
263 flags |= FL_TRUNCATE;
265 case SET_SUPPRESSAVERAGE:
266 flags |= FL_SUPPRESSAVERAGE;
268 case SET_SAMPLEINTERVAL:
269 if (scanned[iArg].n_items != 2 || sscanf(scanned[iArg].list[1],
"%ld", &sampleInterval) != 1 || sampleInterval <= 0)
270 SDDS_Bomb(
"invalid -sampleinterval syntax");
274 SDDS_Bomb(
"only one -columns option may be given");
275 if (scanned[iArg].n_items < 2)
277 indepQuantity = scanned[iArg].list[1];
278 if (scanned[iArg].n_items >= 2) {
279 depenQuantity =
tmalloc(
sizeof(*depenQuantity) * (depenQuantities = scanned[iArg].n_items - 2));
280 for (i = 0; i < depenQuantities; i++)
285 flags |= FL_FULLOUTPUT;
286 if (scanned[iArg].n_items >= 2) {
287 scanned[iArg].n_items--;
288 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))
290 scanned[iArg].n_items++;
291 if (fullOutputFlags & FL_FULLOUTPUT_UNFOLDED)
292 flags |= FL_FULLOUTPUT_UNFOLDED;
294 flags |= FL_FULLOUTPUT_FOLDED;
295 if (fullOutputFlags & FL_UNWRAP_PHASE)
296 flags |= FL_UNWRAP_PHASE;
300 if (!
processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags))
304 if (scanned[iArg].n_items > 1) {
305 unsigned long tmpFlags;
306 if (strchr(scanned[iArg].list[1],
'=') == NULL) {
307 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))
310 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))
315 flags |= FL_PSDOUTPUT;
317 if ((flags & FL_PSDINTEGOUTPUT) && (flags & FL_PSDRINTEGOUTPUT))
318 SDDS_Bomb(
"invalid -psdOutput syntax: give only one of integrated or rintegrated");
321 if (scanned[iArg].n_items < 2)
323 for (j = 1; j < scanned[iArg].n_items; j++)
324 excludes = appendToStringArray(&exclude, excludes, scanned[iArg].list[j]);
329 case SET_COMPLEXINPUT:
331 if (scanned[iArg].n_items == 2) {
332 scanned[iArg].n_items--;
333 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))
334 SDDS_Bomb(
"Invalid -complexInput syntax");
335 scanned[iArg].n_items++;
341 case SET_MAJOR_ORDER:
343 scanned[iArg].n_items--;
344 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)))
345 SDDS_Bomb(
"invalid -majorOrder syntax/values");
346 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
347 columnMajorOrder = 1;
348 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
349 columnMajorOrder = 0;
352 if (scanned[iArg].n_items != 2 ||
353 sscanf(scanned[iArg].list[1],
"%d", &threads) != 1 || threads < 1)
357 fprintf(stderr,
"error: unknown/ambiguous option: %s\n", scanned[iArg].list[0]);
363 input = scanned[iArg].list[0];
365 output = scanned[iArg].list[0];
371 if (!noWarnings && inverse)
372 fprintf(stderr,
"Warning: The inverse option is ignored since it only works with -complexInput.\n");
375 if (!noWarnings && inverse && (flags & FL_FULLOUTPUT_FOLDED))
376 fprintf(stderr,
"Warning: The combination of -inverse and -fullOutput=folded will be changed to -inverse -fullOutput=unfolded.\n");
381 SDDS_Bomb(
"Supply the independent quantity name with the -columns option");
383 if ((flags & FL_TRUNCATE) && (flags & FL_PADWITHZEROES))
384 SDDS_Bomb(
"Specify only one of -padwithzeroes and -truncate");
387 flags |= FL_FULLOUTPUT;
388 flags |= FL_FULLOUTPUT_UNFOLDED;
396 excludes = appendToStringArray(&exclude, excludes, indepQuantity);
397 if (!depenQuantities)
398 depenQuantities = appendToStringArray(&depenQuantity, depenQuantities,
"*");
401 if ((depenQuantities = expandColumnPairNames(&SDDSin, &depenQuantity, NULL, depenQuantities, exclude, excludes, FIND_NUMERIC_TYPE, 0)) <= 0) {
403 SDDS_Bomb(
"No quantities selected to FFT");
406 if ((depenQuantities = expandComplexColumnPairNames(&SDDSin, depenQuantity, &realQuan, &imagQuan, depenQuantities, exclude, excludes, FIND_NUMERIC_TYPE, 0)) <= 0) {
408 SDDS_Bomb(
"No quantities selected to FFT");
413 fprintf(stderr,
"%ld dependent quantities:\n", depenQuantities);
414 for (i = 0; i < depenQuantities; i++)
415 fprintf(stderr,
" %s\n", depenQuantity[i]);
418 if (!(freqUnits = makeFrequencyUnits(&SDDSin, indepQuantity)) ||
420 !create_fft_frequency_column(&SDDSout, &SDDSin, indepQuantity, freqUnits, inverse) ||
424 if (columnMajorOrder != -1)
425 SDDSout.layout.data_mode.column_major = columnMajorOrder;
427 SDDSout.layout.data_mode.column_major = SDDSin.layout.data_mode.column_major;
432 if (!complexInputFlags) {
434 spectrumFoldParExist = 1;
435 }
else if (complexInputFlags & FL_COMPLEXINPUT_UNFOLDED)
436 flags |= FL_COMPLEXINPUT_UNFOLDED;
438 flags |= FL_COMPLEXINPUT_FOLDED;
440 for (i = 0; i < depenQuantities; i++) {
442 create_fft_columns(&SDDSout, &SDDSin, depenQuantity[i], indepQuantity, freqUnits,
443 flags & FL_FULLOUTPUT, flags & (FL_PSDOUTPUT + FL_PSDINTEGOUTPUT + FL_PSDRINTEGOUTPUT),
444 0, inverse, flags & FL_UNWRAP_PHASE);
446 create_fft_columns(&SDDSout, &SDDSin, realQuan[i], indepQuantity, freqUnits,
447 flags & FL_FULLOUTPUT, flags & (FL_PSDOUTPUT + FL_PSDINTEGOUTPUT + FL_PSDRINTEGOUTPUT),
448 1, inverse, flags & FL_UNWRAP_PHASE);
454 colsToUse = depenQuantities;
455 primeCols = greatestProductOfSmallPrimes(depenQuantities);
456 if (depenQuantities != primeCols || padFactor) {
457 if (flags & FL_PADWITHZEROES) {
458 pow2Cols =
ipow(2., ((
long)(log((
double)depenQuantities) / log(2.0F))) + (padFactor ? padFactor : 1));
459 if ((primeCols = greatestProductOfSmallPrimes(pow2Cols)) > depenQuantities)
460 colsToUse = primeCols;
462 colsToUse = pow2Cols;
463 fprintf(stdout,
"Using %ld columns\n", colsToUse);
464 }
else if (flags & FL_TRUNCATE)
465 colsToUse = greatestProductOfSmallPrimes(depenQuantities);
467 fputs(
"Warning: Number of dependent columns has large prime factors.\nThis could take a very long time.\nConsider using the -truncate option.\n", stderr);
469 real_imag =
tmalloc(
sizeof(*real_imag) * (2 * colsToUse + 2));
470 real = malloc(
sizeof(*real) * colsToUse);
471 imag = malloc(
sizeof(*imag) * colsToUse);
477 if (page == 1 && spectrumFoldParExist) {
481 flags |= FL_COMPLEXINPUT_FOLDED;
483 flags |= FL_COMPLEXINPUT_UNFOLDED;
487 primeRows = greatestProductOfSmallPrimes(rows);
488 if (rows != primeRows || padFactor) {
489 if (flags & FL_PADWITHZEROES) {
490 pow2Rows =
ipow(2., ((
long)(log((
double)rows) / log(2.0F))) + (padFactor ? padFactor : 1));
491 if ((primeRows = greatestProductOfSmallPrimes(pow2Rows)) > rows)
492 rowsToUse = primeRows;
494 rowsToUse = pow2Rows;
495 fprintf(stdout,
"Using %" PRId64
" rows\n", rowsToUse);
496 }
else if (flags & FL_TRUNCATE)
497 rowsToUse = greatestProductOfSmallPrimes(rows);
499 fputs(
"Warning: Number of points has large prime factors.\nThis could take a very long time.\nConsider using the -truncate option.\n", stderr);
504 for (j = 0; j < colsToUse; j++) {
505 real[j] = imag[j] = NULL;
506 if (j < depenQuantities) {
514 imag[j] = calloc(
sizeof(**imag), rowsToUse);
516 if (rows < rowsToUse) {
517 real[j] =
SDDS_Realloc(real[j],
sizeof(**real) * rowsToUse);
518 imag[j] =
SDDS_Realloc(imag[j],
sizeof(**imag) * rowsToUse);
521 real[j] = calloc(
sizeof(**real), rowsToUse);
522 imag[j] = calloc(
sizeof(**imag), rowsToUse);
525 fdata = malloc(
sizeof(*fdata) * rowsToUse);
526 if (rows < rowsToUse) {
527 length = ((double)rows) * (tdata[rows - 1] - tdata[0]) / ((double)rows - 1.0);
529 length = tdata[rows - 1] - tdata[0];
531 df = factor = 1.0 / length;
533 for (i = 0; i < rows; i++)
535 for (i = rows; i < rowsToUse; i++) {
540 for (i = 0; i < rows; i++) {
541 for (j = 0; j < colsToUse; j++) {
542 real_imag[2 * j] = real_imag[2 * j + 1] = 0;
543 if (j < depenQuantities) {
544 real_imag[2 * j] = real[j][i];
546 real_imag[2 * j + 1] = imag[j][i];
548 real_imag[2 * j + 1] = 0;
551 complexFFT(real_imag, colsToUse, inverse);
552 for (j = 0; j < colsToUse; j++) {
553 real[j][i] = real_imag[2 * j];
554 imag[j][i] = real_imag[2 * j + 1];
558#pragma omp parallel if (threads > 1) num_threads(threads)
560 double *real_imag_thread =
tmalloc(
sizeof(*real_imag_thread) * (2 * colsToUse + 2));
562#pragma omp for private(j)
563 for (row = 0; row < rows; row++) {
564 for (j = 0; j < colsToUse; j++) {
565 real_imag_thread[2 * j] = real_imag_thread[2 * j + 1] = 0;
566 if (j < depenQuantities) {
567 real_imag_thread[2 * j] = real[j][row];
569 real_imag_thread[2 * j + 1] = imag[j][row];
571 real_imag_thread[2 * j + 1] = 0;
574 complexFFT(real_imag_thread, colsToUse, inverse);
575 for (j = 0; j < colsToUse; j++) {
576 real[j][row] = real_imag_thread[2 * j];
577 imag[j][row] = real_imag_thread[2 * j + 1];
580 free(real_imag_thread);
586 arg = malloc(
sizeof(*arg) * rowsToUse);
587 magData = malloc(
sizeof(*magData) * rowsToUse);
588 real_imag1 = calloc(
sizeof(*real_imag1), 2 * fftrows + 2);
590 for (j = 0; j < depenQuantities; j++) {
591 for (i = 0; i < rowsToUse; i++) {
593 real_imag1[2 * i] = real[j][i];
594 real_imag1[2 * i + 1] = imag[j][i];
596 real_imag1[2 * i] = 0;
597 real_imag1[2 * i + 1] = 0;
600 complexFFT(real_imag1, rowsToUse, inverse);
601 for (i = 0; i < n_freq; i++) {
602 dtf_real = cos(-2 * PI * fdata[i] * t0);
603 dtf_imag = sin(-2 * PI * fdata[i] * t0);
604 real[j][i] = real_imag1[2 * i] * dtf_real - real_imag1[2 * i + 1] * dtf_imag;
605 imag[j][i] = real_imag1[2 * i + 1] * dtf_real + real_imag1[2 * i] * dtf_imag;
606 magData[i] = sqrt(sqr(real[j][i]) + sqr(imag[j][i]));
607 if (real[j][i] || imag[j][i])
608 arg[i] = 180.0 / PI * atan2(imag[j][i], real[j][i]);
612 if (flags & FL_NORMALIZE) {
614 for (i = 0; i < n_freq; i++)
615 if (magData[i] > factor)
617 if (factor != -DBL_MAX)
618 for (i = 0; i < n_freq; i++) {
619 real[j][i] /= factor;
620 imag[j][i] /= factor;
621 magData[i] /= factor;
625 sprintf(str,
"FFT%s", depenQuantity[j] + (imagQuan ? 4 : 0));
628 tempStr = realQuan[j];
630 tempStr = depenQuantity[j];
632 if (strncmp(tempStr,
"FFT", 3) == 0)
633 sprintf(str,
"%s", tempStr + 3);
634 else if (strncmp(tempStr,
"RealFFT", 7) == 0)
635 sprintf(str,
"%s", tempStr + 7);
637 sprintf(str,
"%s", tempStr);
643 !
SDDS_SetParameters(&SDDSout, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE,
"fftFrequencies", n_freq,
"fftFrequencySpacing", df, NULL))
645 if (flags & FL_FULLOUTPUT) {
646 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, magData, n_freq, index) ||
647 !
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, real[j], n_freq, index + 1) ||
648 !
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, imag[j], n_freq, index + 2) ||
649 !
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, arg, n_freq, index + 3))
652 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, real[j], n_freq, index))
656 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, fdata, n_freq, 0))
661 for (j = 0; j < colsToUse; j++) {
703static long psdOffset, argOffset, realOffset, imagOffset, fftOffset = -1, psdIntOffset, unwrappedArgOffset = -1;
705long create_fft_frequency_column(
SDDS_DATASET *SDDSout,
SDDS_DATASET *SDDSin,
char *timeName,
char *freqUnits,
long inverse) {
706 char s[SDDS_MAXLINE];
715 sprintf(s,
"Frequency for %s", timeSymbol);
724 sprintf(s,
"inverse for %s", timeSymbol);
738 char *freqUnits,
long full_output,
unsigned long psd_output,
long complexInput,
739 long inverse,
long unwrap_phase) {
740 char s[SDDS_MAXLINE];
741 char *origUnits, *origSymbol;
742 char *description, *name, *symbol, *units;
752 sprintf(s,
"FFT%s", origName + offset);
754 if (strncmp(origName,
"FFT", 3) == 0)
756 else if (strncmp(origName,
"RealFFT", 7) == 0)
760 sprintf(s,
"%s", origName + offset);
765 sprintf(s,
"FFT %s", origSymbol);
768 sprintf(s,
"Amplitude of FFT of %s", origSymbol);
781 if (psd_output & FL_PSDOUTPUT) {
784 sprintf(s,
"(%s)$a2$n/(%s)", origUnits, freqUnits);
786 sprintf(s,
"(%s)$a2$n", origUnits);
791 sprintf(s,
"PSD%s", origName + offset);
796 sprintf(s,
"PSD %s", origSymbol);
799 sprintf(s,
"PSD of %s", origSymbol);
805 psdOffset = index1 - index0;
813 if (psd_output & (FL_PSDINTEGOUTPUT + FL_PSDRINTEGOUTPUT)) {
819 sprintf(s,
"SqrtIntegPSD%s", origName + offset);
824 sprintf(s,
"Sqrt Integ PSD %s", origSymbol);
827 sprintf(s,
"Sqrt Integ PSD of %s", origSymbol);
833 psdIntOffset = index1 - index0;
843 sprintf(s,
"RealFFT%s", origName + offset);
845 sprintf(s,
"Real%s", origName + offset);
851 sprintf(s,
"Re[FFT %s]", origSymbol);
853 sprintf(s,
"Re[%s]", origSymbol);
857 sprintf(s,
"Real part of FFT of %s", origSymbol);
859 sprintf(s,
"Real part of %s", origSymbol);
865 realOffset = index1 - index0;
871 sprintf(s,
"ImagFFT%s", origName + offset);
873 sprintf(s,
"Imag%s", origName + offset);
879 sprintf(s,
"Im[FFT %s]", origSymbol);
881 sprintf(s,
"Im[%s]", origSymbol);
885 sprintf(s,
"Imaginary part of FFT of %s", origSymbol);
887 sprintf(s,
"Imaginary part of %s", origSymbol);
893 imagOffset = index1 - index0;
899 sprintf(s,
"ArgFFT%s", origName + offset);
901 sprintf(s,
"Arg%s", origName + offset);
907 sprintf(s,
"Arg[FFT %s]", origSymbol);
909 sprintf(s,
"Arg[%s]", origSymbol);
913 sprintf(s,
"Phase of FFT of %s", origSymbol);
915 sprintf(s,
"Phase of %s", origSymbol);
921 argOffset = index1 - index0;
927 sprintf(s,
"UnwrapArgFFT%s", origName + offset);
929 sprintf(s,
"UnwrapArg%s", origName + offset);
935 sprintf(s,
"UnwrapArg[FFT %s]", origSymbol);
937 sprintf(s,
"UnwrapArg[%s]", origSymbol);
941 sprintf(s,
"Unwrapped Phase of FFT of %s", origSymbol);
943 sprintf(s,
"Unwrapped Phase of %s", origSymbol);
949 unwrappedArgOffset = index1 - index0;
960long expandComplexColumnPairNames(
SDDS_DATASET *SDDSin,
char **name,
char ***realName,
char ***imagName,
long names,
961 char **excludeName,
long excludeNames,
long typeMode,
long typeValue) {
962 long i, j, k, realNames, imagNames, names2;
963 char **realName1, **imagName1, **realName2, **imagName2;
964 char *realPattern, *imagPattern = NULL;
969 realName1 = imagName1 = realName2 = imagName2 = NULL;
970 realNames = imagNames = names2 = 0;
971 for (i = longest = 0; i < names; i++) {
972 if (strlen(name[i]) > longest)
973 longest = strlen(name[i]);
976 if (!(realPattern =
SDDS_Malloc(
sizeof(*realPattern) * longest)) ||
977 !(imagPattern =
SDDS_Malloc(
sizeof(*imagPattern) * longest)))
980 for (i = 0; i < names; i++) {
981 for (j = 0; j < 2; j++) {
983 sprintf(realPattern,
"Real%s", name[i]);
984 sprintf(imagPattern,
"Imag%s", name[i]);
986 sprintf(realPattern,
"%sReal", name[i]);
987 sprintf(imagPattern,
"%sImag", name[i]);
991 case FIND_NUMERIC_TYPE:
992 case FIND_INTEGER_TYPE:
993 case FIND_FLOATING_TYPE:
994 realNames =
SDDS_MatchColumns(SDDSin, &realName1, SDDS_MATCH_STRING, typeMode, realPattern, SDDS_0_PREVIOUS | SDDS_OR);
995 imagNames =
SDDS_MatchColumns(SDDSin, &imagName1, SDDS_MATCH_STRING, typeMode, imagPattern, SDDS_0_PREVIOUS | SDDS_OR);
997 case FIND_SPECIFIED_TYPE:
999 SDDS_Bomb(
"Invalid type value in expandColumnPairNames");
1000 realNames =
SDDS_MatchColumns(SDDSin, &realName1, SDDS_MATCH_STRING, typeMode, typeValue, realPattern, SDDS_0_PREVIOUS | SDDS_OR);
1001 imagNames =
SDDS_MatchColumns(SDDSin, &imagName1, SDDS_MATCH_STRING, typeMode, typeValue, imagPattern, SDDS_0_PREVIOUS | SDDS_OR);
1004 SDDS_Bomb(
"Invalid typeMode in expandColumnPairNames");
1010 if (realNames == -1 || imagNames == -1) {
1012 SDDS_Bomb(
"Unable to perform column name match in expandColumnPairNames");
1014 if (realNames != imagNames)
1015 SDDS_Bomb(
"Found different number of real and imaginary columns");
1017 for (j = 0; j < excludeNames; j++)
1018 for (k = 0; k < realNames; k++)
1019 if (
wild_match(realName1[k], excludeName[j])) {
1022 imagName1[k] = realName1[k] = NULL;
1025 moveToStringArrayComplex(&realName2, &imagName2, &names2, realName1, imagName1, realNames);
1034 *realName = realName2;
1035 *imagName = imagName2;
1039void moveToStringArrayComplex(
char ***targetReal,
char ***targetImag,
long *targets,
char **sourceReal,
char **sourceImag,
long sources) {
1043 if (!(*targetReal =
SDDS_Realloc(*targetReal,
sizeof(**targetReal) * (*targets + sources))) ||
1044 !(*targetImag =
SDDS_Realloc(*targetImag,
sizeof(**targetImag) * (*targets + sources))))
1046 for (i = 0; i < sources; i++) {
1047 if (sourceReal[i] == NULL || sourceImag[i] == NULL)
1049 for (j = 0; j < *targets; j++)
1050 if (strcmp(sourceReal[i], (*targetReal)[j]) == 0)
1052 if (j == *targets) {
1053 (*targetReal)[j] = sourceReal[i];
1054 (*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.