SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sdds2dfft.c
Go to the documentation of this file.
1/**
2 * @file sdds2dfft.c
3 * @brief SDDS-format 2D FFT program.
4 *
5 * @details
6 * This program performs a two-dimensional Fast Fourier Transform (FFT) on data formatted in the
7 * Self Describing Data Set (SDDS) format. It provides various options for normalization, padding, truncation,
8 * suppressing averages, and more to customize the FFT process.
9 *
10 * @section Usage
11 * ```
12 * sdds2dfft [<inputfile>] [<outputfile>]
13 * [-pipe=[input][,output]]
14 * -columns=<indep-variable>[,<depen-quantity>[,...]]
15 * [-complexInput[=unfolded|folded]]
16 * [-exclude=<depen-quantity>[,...]]
17 * [-sampleInterval=<number>]
18 * [-normalize]
19 * [-fullOutput[=unfolded|folded],unwrapLimit=<value>]
20 * [-psdOutput[=plain][,{integrated|rintegrated[=<cutoff>]}]]
21 * [-inverse]
22 * [-padwithzeroes[=exponent]]
23 * [-truncate]
24 * [-suppressaverage]
25 * [-noWarnings]
26 * [-majorOrder=row|column]
27 * ```
28 *
29 * @section Options
30 * | Required | Description |
31 * |---------------------------------------|---------------------------------------------------------------------------------------|
32 * | `-columns` | Specify independent and dependent variables for FFT analysis. |
33 *
34 * | Optional | Description |
35 * |---------------------|-----------------------------------------------------------------|
36 * | `-pipe` | Standard SDDS Toolkit pipe option. |
37 * | `-complexInput` | Indicates the input columns are in complex form. |
38 * | `-exclude` | Exclude quantities from analysis using wildcards. |
39 * | `-sampleInterval` | Request sampling of input data points at specified intervals. |
40 * | `-normalize` | Normalize output to a peak magnitude of 1. |
41 * | `-fullOutput` | Request real and imaginary parts of the FFT. |
42 * | `-psdOutput` | Request Power Spectral Density (PSD) output. |
43 * | `-inverse` | Perform inverse Fourier transform. |
44 * | `-padwithzeroes` | Pad data with zeroes to match required data points. |
45 * | `-truncate` | Truncate data to match required data points. |
46 * | `-suppressaverage` | Suppress the average value before FFT. |
47 * | `-noWarnings` | Suppress warning messages. |
48 * | `-majorOrder` | Specify output file's data order (row or column). |
49 *
50 * @subsection Incompatibilities
51 * - `-inverse` is incompatible with:
52 * - `-complexInput=folded`
53 * - `-padwithzeroes` is incompatible with `-truncate`.
54 * - For `-complexInput`:
55 * - Requires `-columns` specifying dependent quantities in pairs (real, imaginary).
56 *
57 * @copyright
58 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
59 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
60 *
61 * @license
62 * This file is distributed under the terms of the Software License Agreement
63 * found in the file LICENSE included with this distribution.
64 *
65 * @authors
66 * H. Shang, R. Soliday
67 */
68
69#include "mdb.h"
70#include "SDDS.h"
71#include "scan.h"
72#include "fftpackC.h"
73#include "SDDSutils.h"
74#include <ctype.h>
75
76/* Enumeration for option types */
77enum option_type {
78 SET_NORMALIZE,
79 SET_PADWITHZEROES,
80 SET_TRUNCATE,
81 SET_SUPPRESSAVERAGE,
82 SET_SAMPLEINTERVAL,
83 SET_COLUMNS,
84 SET_FULLOUTPUT,
85 SET_PIPE,
86 SET_PSDOUTPUT,
87 SET_EXCLUDE,
88 SET_NOWARNINGS,
89 SET_COMPLEXINPUT,
90 SET_INVERSE,
91 SET_MAJOR_ORDER,
92 N_OPTIONS
93};
94
95char *option[N_OPTIONS] = {
96 "normalize",
97 "padwithzeroes",
98 "truncate",
99 "suppressaverage",
100 "sampleinterval",
101 "columns",
102 "fulloutput",
103 "pipe",
104 "psdoutput",
105 "exclude",
106 "nowarnings",
107 "complexinput",
108 "inverse",
109 "majorOrder",
110};
111
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
126
127static char *USAGE1 =
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"
134 " [-normalize]\n"
135 " [-fullOutput[=unfolded|folded],unwrapLimit=<value>]\n"
136 " [-psdOutput[=plain][,{integrated|rintegrated[=<cutoff>]}]]\n"
137 " [-inverse]\n"
138 " [-padwithzeroes[=exponent]]\n"
139 " [-truncate]\n"
140 " [-suppressaverage]\n"
141 " [-noWarnings]\n"
142 " [-majorOrder=row|column]\n"
143 "Options:\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"
151 " Options:\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"
154 " -inverse\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";
159
160static char *USAGE2 =
161 " -sampleInterval=<number>\n"
162 " Requests sampling of the input data points with the given interval.\n"
163 " -normalize\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"
167 " Options:\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"
174 " Qualifiers:\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"
184 " -noWarnings\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";
191
192int64_t greatestProductOfSmallPrimes(int64_t rows);
193long create_fft_frequency_column(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, char *timeName, char *freqUnits, long inverse);
194
195long create_fft_columns(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, char *origName, char *indepName,
196 char *freqUnits, long full_output, unsigned long psd_output, long complexInput,
197 long inverse, long unwrap_phase);
198long create_fft_parameters(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, char *indepName, char *freqUnits);
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);
203
204int main(int argc, char **argv) {
205 int iArg, j;
206 char *freqUnits;
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;
216 SDDS_DATASET SDDSin, SDDSout;
217 double *tdata, rintegCutOffFreq, unwrapLimit = 0;
218 long padFactor;
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;
223
225 argc = scanargs(&scanned, argc, argv);
226 if (argc < 3 || argc > (3 + N_OPTIONS)) {
227 fprintf(stderr, "%s%s", USAGE1, USAGE2);
228 exit(EXIT_FAILURE);
229 }
230 rintegCutOffFreq = 0;
231 output = input = NULL;
232 flags = pipeFlags = excludes = complexInput = inverse = 0;
233 sampleInterval = 1;
234 indepQuantity = NULL;
235 depenQuantity = exclude = NULL;
236 depenQuantities = 0;
237 noWarnings = 0;
238 padFactor = 0;
239
240 for (iArg = 1; iArg < argc; iArg++) {
241 if (scanned[iArg].arg_type == OPTION) {
242 /* process options here */
243 switch (match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
244 case SET_NORMALIZE:
245 flags |= FL_NORMALIZE;
246 break;
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");
252 }
253 break;
254 case SET_TRUNCATE:
255 flags |= FL_TRUNCATE;
256 break;
257 case SET_SUPPRESSAVERAGE:
258 flags |= FL_SUPPRESSAVERAGE;
259 break;
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");
263 break;
264 case SET_COLUMNS:
265 if (indepQuantity)
266 SDDS_Bomb("only one -columns option may be given");
267 if (scanned[iArg].n_items < 2)
268 SDDS_Bomb("invalid -columns syntax");
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++)
273 SDDS_CopyString(&depenQuantity[i], scanned[iArg].list[i + 2]);
274 }
275 break;
276 case SET_FULLOUTPUT:
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))
281 SDDS_Bomb("Invalid -fullOutput syntax");
282 scanned[iArg].n_items++;
283 if (fullOutputFlags & FL_FULLOUTPUT_UNFOLDED)
284 flags |= FL_FULLOUTPUT_UNFOLDED;
285 else
286 flags |= FL_FULLOUTPUT_FOLDED;
287 if (fullOutputFlags & FL_UNWRAP_PHASE)
288 flags |= FL_UNWRAP_PHASE;
289 }
290 break;
291 case SET_PIPE:
292 if (!processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags))
293 SDDS_Bomb("invalid -pipe syntax");
294 break;
295 case SET_PSDOUTPUT:
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))
300 SDDS_Bomb("invalid -psdOutput syntax");
301 } else {
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))
303 SDDS_Bomb("invalid -psdOutput syntax");
304 }
305 flags |= tmpFlags;
306 } else {
307 flags |= FL_PSDOUTPUT;
308 }
309 if ((flags & FL_PSDINTEGOUTPUT) && (flags & FL_PSDRINTEGOUTPUT))
310 SDDS_Bomb("invalid -psdOutput syntax: give only one of integrated or rintegrated");
311 break;
312 case SET_EXCLUDE:
313 if (scanned[iArg].n_items < 2)
314 SDDS_Bomb("invalid -exclude syntax");
315 moveToStringArray(&exclude, &excludes, scanned[iArg].list + 1, scanned[iArg].n_items - 1);
316 break;
317 case SET_NOWARNINGS:
318 noWarnings = 1;
319 break;
320 case SET_COMPLEXINPUT:
321 complexInput = 1;
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++;
327 }
328 break;
329 case SET_INVERSE:
330 inverse = 1;
331 break;
332 case SET_MAJOR_ORDER:
333 majorOrderFlag = 0;
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;
341 break;
342 default:
343 fprintf(stderr, "error: unknown/ambiguous option: %s\n", scanned[iArg].list[0]);
344 exit(EXIT_FAILURE);
345 break;
346 }
347 } else {
348 if (!input)
349 input = scanned[iArg].list[0];
350 else if (!output)
351 output = scanned[iArg].list[0];
352 else
353 SDDS_Bomb("too many filenames seen");
354 }
355 }
356 if (!complexInput) {
357 if (!noWarnings && inverse)
358 fprintf(stderr, "Warning: The inverse option is ignored since it only works with -complexInput.\n");
359 inverse = 0;
360 }
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");
363
364 processFilenames("sdds2dfft", &input, &output, pipeFlags, 0, NULL);
365
366 if (!indepQuantity)
367 SDDS_Bomb("Supply the independent quantity name with the -columns option");
368
369 if ((flags & FL_TRUNCATE) && (flags & FL_PADWITHZEROES))
370 SDDS_Bomb("Specify only one of -padwithzeroes and -truncate");
371 if (!inverse) {
372 /* For 2D FFT, always use full output unfolded */
373 flags |= FL_FULLOUTPUT;
374 flags |= FL_FULLOUTPUT_UNFOLDED;
375 }
376 if (!SDDS_InitializeInput(&SDDSin, input))
377 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
378
379 if (SDDS_CheckColumn(&SDDSin, indepQuantity, NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OKAY)
380 exit(EXIT_FAILURE);
381
382 excludes = appendToStringArray(&exclude, excludes, indepQuantity);
383 if (!depenQuantities)
384 depenQuantities = appendToStringArray(&depenQuantity, depenQuantities, "*");
385
386 if (!complexInput) {
387 if ((depenQuantities = expandColumnPairNames(&SDDSin, &depenQuantity, NULL, depenQuantities, exclude, excludes, FIND_NUMERIC_TYPE, 0)) <= 0) {
388 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
389 SDDS_Bomb("No quantities selected to FFT");
390 }
391 } else {
392 if ((depenQuantities = expandComplexColumnPairNames(&SDDSin, depenQuantity, &realQuan, &imagQuan, depenQuantities, exclude, excludes, FIND_NUMERIC_TYPE, 0)) <= 0) {
393 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
394 SDDS_Bomb("No quantities selected to FFT");
395 }
396 }
397
398#if 0
399 fprintf(stderr, "%ld dependent quantities:\n", depenQuantities);
400 for (i = 0; i < depenQuantities; i++)
401 fprintf(stderr, " %s\n", depenQuantity[i]);
402#endif
403
404 if (!(freqUnits = makeFrequencyUnits(&SDDSin, indepQuantity)) ||
405 !SDDS_InitializeOutput(&SDDSout, SDDS_BINARY, 0, NULL, "sdds2dfft output", output) ||
406 !create_fft_frequency_column(&SDDSout, &SDDSin, indepQuantity, freqUnits, inverse) ||
407 SDDS_DefineParameter(&SDDSout, "fftFrequencies", NULL, NULL, NULL, NULL, SDDS_LONG, NULL) < 0 ||
408 SDDS_DefineParameter(&SDDSout, "fftFrequencySpacing", "$gD$rf", freqUnits, NULL, NULL, SDDS_DOUBLE, NULL) < 0)
409 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
410 if (columnMajorOrder != -1)
411 SDDSout.layout.data_mode.column_major = columnMajorOrder;
412 else
413 SDDSout.layout.data_mode.column_major = SDDSin.layout.data_mode.column_major;
414
415 if ((flags & FL_FULLOUTPUT) && SDDS_DefineParameter(&SDDSout, "SpectrumFolded", NULL, NULL, NULL, NULL, SDDS_LONG, NULL) < 0)
416 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
417 if (complexInput) {
418 if (!complexInputFlags) {
419 if (SDDS_CheckParameter(&SDDSin, "SpectrumFolded", NULL, SDDS_LONG, NULL) == SDDS_CHECK_OK)
420 spectrumFoldParExist = 1;
421 } else if (complexInputFlags & FL_COMPLEXINPUT_UNFOLDED)
422 flags |= FL_COMPLEXINPUT_UNFOLDED;
423 else
424 flags |= FL_COMPLEXINPUT_FOLDED;
425 }
426 for (i = 0; i < depenQuantities; i++) {
427 if (!complexInput)
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);
431 else
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);
435 }
436
437 if (!SDDS_TransferAllParameterDefinitions(&SDDSout, &SDDSin, SDDS_TRANSFER_KEEPOLD) || !SDDS_WriteLayout(&SDDSout))
438 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
439
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;
447 else
448 colsToUse = pow2Cols;
449 fprintf(stdout, "Using %ld columns\n", colsToUse);
450 } else if (flags & FL_TRUNCATE)
451 colsToUse = greatestProductOfSmallPrimes(depenQuantities);
452 else if (largest_prime_factor(depenQuantities) > 100 && !noWarnings)
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);
454 }
455 real_imag = tmalloc(sizeof(*real_imag) * (2 * colsToUse + 2));
456 real = malloc(sizeof(*real) * colsToUse);
457 imag = malloc(sizeof(*imag) * colsToUse);
458
459 while ((readCode = SDDS_ReadPage(&SDDSin)) > 0) {
460 page++;
461 if ((rows = SDDS_CountRowsOfInterest(&SDDSin)) < 0)
462 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
463 if (page == 1 && spectrumFoldParExist) {
464 if (!SDDS_GetParameterAsLong(&SDDSin, "SpectrumFolded", &spectrumFolded))
465 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
466 if (spectrumFolded)
467 flags |= FL_COMPLEXINPUT_FOLDED;
468 else
469 flags |= FL_COMPLEXINPUT_UNFOLDED;
470 }
471 if (rows) {
472 rowsToUse = rows;
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;
479 else
480 rowsToUse = pow2Rows;
481 fprintf(stdout, "Using %" PRId64 " rows\n", rowsToUse);
482 } else if (flags & FL_TRUNCATE)
483 rowsToUse = greatestProductOfSmallPrimes(rows);
484 else if (largest_prime_factor(rows) > 100 && !noWarnings)
485 fputs("Warning: Number of points has large prime factors.\nThis could take a very long time.\nConsider using the -truncate option.\n", stderr);
486 }
487 if (!(tdata = SDDS_GetColumnInDoubles(&SDDSin, indepQuantity)))
488 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
489
490 for (j = 0; j < colsToUse; j++) {
491 real[j] = imag[j] = NULL;
492 if (j < depenQuantities) {
493 if (complexInput) {
494 if (!(real[j] = (double *)SDDS_GetColumnInDoubles(&SDDSin, realQuan[j])) ||
495 !(imag[j] = (double *)SDDS_GetColumnInDoubles(&SDDSin, imagQuan[j])))
496 SDDS_PrintErrors(stderr, SDDS_EXIT_PrintErrors | SDDS_VERBOSE_PrintErrors);
497 } else {
498 if (!(real[j] = (double *)SDDS_GetColumnInDoubles(&SDDSin, depenQuantity[j])))
499 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
500 imag[j] = calloc(sizeof(**imag), rowsToUse);
501 }
502 if (rows < rowsToUse) {
503 real[j] = SDDS_Realloc(real[j], sizeof(**real) * rowsToUse);
504 imag[j] = SDDS_Realloc(imag[j], sizeof(**imag) * rowsToUse);
505 }
506 } else {
507 real[j] = calloc(sizeof(**real), rowsToUse);
508 imag[j] = calloc(sizeof(**imag), rowsToUse);
509 }
510 }
511 fdata = malloc(sizeof(*fdata) * rowsToUse);
512 if (rows < rowsToUse) {
513 length = ((double)rows) * (tdata[rows - 1] - tdata[0]) / ((double)rows - 1.0);
514 } else
515 length = tdata[rows - 1] - tdata[0];
516 t0 = tdata[0];
517 df = factor = 1.0 / length;
518 free(tdata);
519 for (i = 0; i < rows; i++)
520 fdata[i] = i * df;
521 for (i = rows; i < rowsToUse; i++) {
522 fdata[i] = i * df;
523 }
524 /* First perform FFT per row */
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];
530 if (imag[j])
531 real_imag[2 * j + 1] = imag[j][i];
532 else
533 real_imag[2 * j + 1] = 0;
534 }
535 }
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];
540 }
541 }
542 /* Then perform FFT by column */
543 n_freq = rowsToUse;
544 fftrows = rowsToUse;
545 arg = malloc(sizeof(*arg) * rowsToUse);
546 magData = malloc(sizeof(*magData) * rowsToUse);
547 real_imag1 = calloc(sizeof(*real_imag1), 2 * fftrows + 2);
548
549 for (j = 0; j < depenQuantities; j++) {
550 for (i = 0; i < rowsToUse; i++) {
551 if (i < rows) {
552 real_imag1[2 * i] = real[j][i];
553 real_imag1[2 * i + 1] = imag[j][i];
554 } else {
555 real_imag1[2 * i] = 0;
556 real_imag1[2 * i + 1] = 0;
557 }
558 }
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]);
568 else
569 arg[i] = 0;
570 }
571 if (flags & FL_NORMALIZE) {
572 factor = -DBL_MAX;
573 for (i = 0; i < n_freq; i++)
574 if (magData[i] > factor)
575 factor = magData[i];
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;
581 }
582 }
583 if (!inverse)
584 sprintf(str, "FFT%s", depenQuantity[j] + (imagQuan ? 4 : 0));
585 else {
586 if (complexInput)
587 tempStr = realQuan[j];
588 else
589 tempStr = depenQuantity[j];
590
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);
595 else
596 sprintf(str, "%s", tempStr);
597 }
598 if ((index = SDDS_GetColumnIndex(&SDDSout, str)) < 0)
599 exit(EXIT_FAILURE);
600 if (!SDDS_StartPage(&SDDSout, rowsToUse) ||
601 !SDDS_CopyParameters(&SDDSout, &SDDSin) ||
602 !SDDS_SetParameters(&SDDSout, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, "fftFrequencies", n_freq, "fftFrequencySpacing", df, NULL))
603 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
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))
609 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
610 } else {
611 if (!SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, real[j], n_freq, index))
612 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
613 }
614 }
615 if (!SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, fdata, n_freq, 0))
616 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
617 free(fdata);
618 free(arg);
619 free(magData);
620 for (j = 0; j < colsToUse; j++) {
621 if (real[j])
622 free(real[j]);
623 if (imag[j])
624 free(imag[j]);
625 }
626 free(real_imag1);
627 } else {
628 if (!SDDS_StartPage(&SDDSout, 0) || !SDDS_CopyParameters(&SDDSout, &SDDSin))
629 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
630 }
631 if (!SDDS_WritePage(&SDDSout))
632 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
633 }
634 if (!SDDS_Terminate(&SDDSin)) {
635 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
636 exit(EXIT_FAILURE);
637 }
638 if (!SDDS_Terminate(&SDDSout)) {
639 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
640 exit(EXIT_FAILURE);
641 }
642 if (excludes) {
643 SDDS_FreeStringArray(exclude, excludes);
644 free(exclude);
645 }
646 free(real);
647 free(imag);
648 if (realQuan) {
649 SDDS_FreeStringArray(realQuan, depenQuantities);
650 SDDS_FreeStringArray(imagQuan, depenQuantities);
651 free(realQuan);
652 free(imagQuan);
653 } else {
654 SDDS_FreeStringArray(depenQuantity, depenQuantities);
655 free(depenQuantity);
656 }
657 free(real_imag);
658 free_scanargs(&scanned, argc);
659 return EXIT_SUCCESS;
660}
661
662static long psdOffset, argOffset, realOffset, imagOffset, fftOffset = -1, psdIntOffset, unwrappedArgOffset = -1;
663
664long create_fft_frequency_column(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, char *timeName, char *freqUnits, long inverse) {
665 char s[SDDS_MAXLINE];
666 char *timeSymbol;
667 char *description;
668
669 if (SDDS_GetColumnInformation(SDDSin, "symbol", &timeSymbol, SDDS_GET_BY_NAME, timeName) != SDDS_STRING)
670 return 0;
671 if (!timeSymbol || SDDS_StringIsBlank(timeSymbol))
672 SDDS_CopyString(&timeSymbol, timeName);
673
674 sprintf(s, "Frequency for %s", timeSymbol);
675 SDDS_CopyString(&description, s);
676 if (!inverse) {
677 if (SDDS_DefineColumn(SDDSout, "f", NULL, freqUnits, description, NULL, SDDS_DOUBLE, 0) < 0) {
678 free(timeSymbol);
679 free(description);
680 return 0;
681 }
682 } else {
683 sprintf(s, "inverse for %s", timeSymbol);
684 SDDS_CopyString(&description, s);
685 if (SDDS_DefineColumn(SDDSout, "t", NULL, freqUnits, description, NULL, SDDS_DOUBLE, 0) < 0) {
686 free(timeSymbol);
687 free(description);
688 return 0;
689 }
690 }
691 free(timeSymbol);
692 free(description);
693 return 1;
694}
695
696long create_fft_columns(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, char *origName, char *indepName,
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;
702 long index0, index1;
703 long offset = 0;
704
705 if (complexInput)
706 offset = 4;
707 if (SDDS_GetColumnInformation(SDDSin, "units", &origUnits, SDDS_GET_BY_NAME, origName) != SDDS_STRING ||
708 SDDS_GetColumnInformation(SDDSin, "symbol", &origSymbol, SDDS_GET_BY_NAME, origName) != SDDS_STRING)
709 return 0;
710 if (!inverse)
711 sprintf(s, "FFT%s", origName + offset);
712 else {
713 if (strncmp(origName, "FFT", 3) == 0)
714 offset = 3;
715 else if (strncmp(origName, "RealFFT", 7) == 0)
716 offset = 7;
717 else
718 offset = 0;
719 sprintf(s, "%s", origName + offset);
720 }
721 SDDS_CopyString(&name, s);
722 if (!origSymbol)
723 SDDS_CopyString(&origSymbol, origName + offset);
724 sprintf(s, "FFT %s", origSymbol);
725 SDDS_CopyString(&symbol, s);
726
727 sprintf(s, "Amplitude of FFT of %s", origSymbol);
728 SDDS_CopyString(&description, s);
729
730 if (SDDS_NumberOfErrors() ||
731 (index0 = SDDS_DefineColumn(SDDSout, name, symbol, origUnits, description, NULL, SDDS_DOUBLE, 0)) < 0)
732 return 0;
733 free(name);
734 free(symbol);
735 free(description);
736
737 if (fftOffset == -1)
738 fftOffset = 0;
739
740 if (psd_output & FL_PSDOUTPUT) {
741 if (origUnits && !SDDS_StringIsBlank(origUnits)) {
742 if (freqUnits && !SDDS_StringIsBlank(freqUnits)) {
743 sprintf(s, "(%s)$a2$n/(%s)", origUnits, freqUnits);
744 } else
745 sprintf(s, "(%s)$a2$n", origUnits);
746 SDDS_CopyString(&units, s);
747 } else
748 units = NULL;
749
750 sprintf(s, "PSD%s", origName + offset);
751 SDDS_CopyString(&name, s);
752
753 if (!origSymbol)
754 SDDS_CopyString(&origSymbol, origName + offset);
755 sprintf(s, "PSD %s", origSymbol);
756 SDDS_CopyString(&symbol, s);
757
758 sprintf(s, "PSD of %s", origSymbol);
759 SDDS_CopyString(&description, s);
760
761 if (SDDS_NumberOfErrors() ||
762 (index1 = SDDS_DefineColumn(SDDSout, name, symbol, units, description, NULL, SDDS_DOUBLE, 0)) < 0)
763 return 0;
764 psdOffset = index1 - index0;
765 free(name);
766 if (units)
767 free(units);
768 free(symbol);
769 free(description);
770 }
771
772 if (psd_output & (FL_PSDINTEGOUTPUT + FL_PSDRINTEGOUTPUT)) {
773 if (origUnits && !SDDS_StringIsBlank(origUnits)) {
774 SDDS_CopyString(&units, origUnits);
775 } else
776 units = NULL;
777
778 sprintf(s, "SqrtIntegPSD%s", origName + offset);
779 SDDS_CopyString(&name, s);
780
781 if (!origSymbol)
782 SDDS_CopyString(&origSymbol, origName + offset);
783 sprintf(s, "Sqrt Integ PSD %s", origSymbol);
784 SDDS_CopyString(&symbol, s);
785
786 sprintf(s, "Sqrt Integ PSD of %s", origSymbol);
787 SDDS_CopyString(&description, s);
788
789 if (SDDS_NumberOfErrors() ||
790 (index1 = SDDS_DefineColumn(SDDSout, name, symbol, units, description, NULL, SDDS_DOUBLE, 0)) < 0)
791 return 0;
792 psdIntOffset = index1 - index0;
793 free(name);
794 if (units)
795 free(units);
796 free(symbol);
797 free(description);
798 }
799
800 if (full_output) {
801 if (!inverse)
802 sprintf(s, "RealFFT%s", origName + offset);
803 else
804 sprintf(s, "Real%s", origName + offset);
805 SDDS_CopyString(&name, s);
806
807 if (!origSymbol)
808 SDDS_CopyString(&origSymbol, origName + offset);
809 if (!inverse)
810 sprintf(s, "Re[FFT %s]", origSymbol);
811 else
812 sprintf(s, "Re[%s]", origSymbol);
813 SDDS_CopyString(&symbol, s);
814
815 if (!inverse)
816 sprintf(s, "Real part of FFT of %s", origSymbol);
817 else
818 sprintf(s, "Real part of %s", origSymbol);
819 SDDS_CopyString(&description, s);
820
821 if (SDDS_NumberOfErrors() ||
822 (index1 = SDDS_DefineColumn(SDDSout, name, symbol, origUnits, description, NULL, SDDS_DOUBLE, 0)) < 0)
823 return 0;
824 realOffset = index1 - index0;
825 free(name);
826 free(symbol);
827 free(description);
828
829 if (!inverse)
830 sprintf(s, "ImagFFT%s", origName + offset);
831 else
832 sprintf(s, "Imag%s", origName + offset);
833 SDDS_CopyString(&name, s);
834
835 if (!origSymbol)
836 SDDS_CopyString(&origSymbol, origName + offset);
837 if (!inverse)
838 sprintf(s, "Im[FFT %s]", origSymbol);
839 else
840 sprintf(s, "Im[%s]", origSymbol);
841 SDDS_CopyString(&symbol, s);
842
843 if (!inverse)
844 sprintf(s, "Imaginary part of FFT of %s", origSymbol);
845 else
846 sprintf(s, "Imaginary part of %s", origSymbol);
847 SDDS_CopyString(&description, s);
848
849 if (SDDS_NumberOfErrors() ||
850 (index1 = SDDS_DefineColumn(SDDSout, name, symbol, origUnits, description, NULL, SDDS_DOUBLE, 0)) < 0)
851 return 0;
852 imagOffset = index1 - index0;
853 free(name);
854 free(symbol);
855 free(description);
856
857 if (!inverse)
858 sprintf(s, "ArgFFT%s", origName + offset);
859 else
860 sprintf(s, "Arg%s", origName + offset);
861 SDDS_CopyString(&name, s);
862
863 if (!origSymbol)
864 SDDS_CopyString(&origSymbol, origName + offset);
865 if (!inverse)
866 sprintf(s, "Arg[FFT %s]", origSymbol);
867 else
868 sprintf(s, "Arg[%s]", origSymbol);
869 SDDS_CopyString(&symbol, s);
870
871 if (!inverse)
872 sprintf(s, "Phase of FFT of %s", origSymbol);
873 else
874 sprintf(s, "Phase of %s", origSymbol);
875 SDDS_CopyString(&description, s);
876
877 if (SDDS_NumberOfErrors() ||
878 (index1 = SDDS_DefineColumn(SDDSout, name, symbol, "degrees", description, NULL, SDDS_DOUBLE, 0)) < 0)
879 return 0;
880 argOffset = index1 - index0;
881 free(name);
882 free(symbol);
883 free(description);
884 if (unwrap_phase) {
885 if (!inverse)
886 sprintf(s, "UnwrapArgFFT%s", origName + offset);
887 else
888 sprintf(s, "UnwrapArg%s", origName + offset);
889 SDDS_CopyString(&name, s);
890
891 if (!origSymbol)
892 SDDS_CopyString(&origSymbol, origName + offset);
893 if (!inverse)
894 sprintf(s, "UnwrapArg[FFT %s]", origSymbol);
895 else
896 sprintf(s, "UnwrapArg[%s]", origSymbol);
897 SDDS_CopyString(&symbol, s);
898
899 if (!inverse)
900 sprintf(s, "Unwrapped Phase of FFT of %s", origSymbol);
901 else
902 sprintf(s, "Unwrapped Phase of %s", origSymbol);
903 SDDS_CopyString(&description, s);
904
905 if (SDDS_NumberOfErrors() ||
906 (index1 = SDDS_DefineColumn(SDDSout, name, symbol, "degrees", description, NULL, SDDS_DOUBLE, 0)) < 0)
907 return 0;
908 unwrappedArgOffset = index1 - index0;
909 free(name);
910 free(symbol);
911 free(description);
912 }
913 }
914
915 free(origSymbol);
916 return 1;
917}
918
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;
924 long longest;
925
926 if (!names || !name)
927 return 0;
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]);
933 }
934 longest += 10;
935 if (!(realPattern = SDDS_Malloc(sizeof(*realPattern) * longest)) ||
936 !(imagPattern = SDDS_Malloc(sizeof(*imagPattern) * longest)))
937 SDDS_Bomb("Memory allocation failure");
938
939 for (i = 0; i < names; i++) {
940 for (j = 0; j < 2; j++) {
941 if (j == 0) {
942 sprintf(realPattern, "Real%s", name[i]);
943 sprintf(imagPattern, "Imag%s", name[i]);
944 } else {
945 sprintf(realPattern, "%sReal", name[i]);
946 sprintf(imagPattern, "%sImag", name[i]);
947 }
948 switch (typeMode) {
949 case FIND_ANY_TYPE:
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);
955 break;
956 case FIND_SPECIFIED_TYPE:
957 if (!SDDS_VALID_TYPE(typeValue))
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);
961 break;
962 default:
963 SDDS_Bomb("Invalid typeMode in expandColumnPairNames");
964 exit(EXIT_FAILURE);
965 break;
966 }
967 if (realNames == 0)
968 continue;
969 if (realNames == -1 || imagNames == -1) {
970 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
971 SDDS_Bomb("Unable to perform column name match in expandColumnPairNames");
972 }
973 if (realNames != imagNames)
974 SDDS_Bomb("Found different number of real and imaginary columns");
975 if (excludeNames) {
976 for (j = 0; j < excludeNames; j++)
977 for (k = 0; k < realNames; k++)
978 if (wild_match(realName1[k], excludeName[j])) {
979 free(realName1[k]);
980 free(imagName1[k]);
981 imagName1[k] = realName1[k] = NULL;
982 }
983 }
984 moveToStringArrayComplex(&realName2, &imagName2, &names2, realName1, imagName1, realNames);
985 free(realName1);
986 free(imagName1);
987 }
988 }
989 free(realPattern);
990 free(imagPattern);
991 if (names2 == 0)
992 return 0;
993 *realName = realName2;
994 *imagName = imagName2;
995 return names2;
996}
997
998void moveToStringArrayComplex(char ***targetReal, char ***targetImag, long *targets, char **sourceReal, char **sourceImag, long sources) {
999 long i, j;
1000 if (!sources)
1001 return;
1002 if (!(*targetReal = SDDS_Realloc(*targetReal, sizeof(**targetReal) * (*targets + sources))) ||
1003 !(*targetImag = SDDS_Realloc(*targetImag, sizeof(**targetImag) * (*targets + sources))))
1004 SDDS_Bomb("Memory allocation failure");
1005 for (i = 0; i < sources; i++) {
1006 if (sourceReal[i] == NULL || sourceImag[i] == NULL)
1007 continue;
1008 for (j = 0; j < *targets; j++)
1009 if (strcmp(sourceReal[i], (*targetReal)[j]) == 0)
1010 break;
1011 if (j == *targets) {
1012 (*targetReal)[j] = sourceReal[i];
1013 (*targetImag)[j] = sourceImag[i];
1014 *targets += 1;
1015 }
1016 }
1017}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_CopyParameters(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:286
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_GetParameterAsLong(SDDS_DATASET *SDDS_dataset, char *parameter_name, int32_t *memory)
Retrieves the value of a specified parameter as a 32-bit integer from the current data table of a dat...
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
double * SDDS_GetColumnInDoubles(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of doubles, considering only rows mark...
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.
Definition SDDS_info.c:41
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *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.
Definition SDDS_utils.c:432
void * SDDS_Malloc(size_t size)
Allocates memory of a specified size.
Definition SDDS_utils.c:639
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
int32_t SDDS_NumberOfErrors()
Retrieves the number of errors recorded by SDDS library routines.
Definition SDDS_utils.c:304
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.
Definition SDDS_utils.c:342
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.
Definition SDDS_utils.c:856
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677
#define SDDS_VALID_TYPE(type)
Validates whether the given type identifier is within the defined range of SDDS types.
Definition SDDStypes.h:149
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_ANY_NUMERIC_TYPE
Special identifier used by SDDS_Check*() routines to accept any numeric type.
Definition SDDStypes.h:157
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
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.
Definition array.c:59
int64_t largest_prime_factor(int64_t number)
Find the largest prime factor of a number.
Definition factorize.c:83
double ipow(const double x, const int64_t p)
Compute x raised to the power p (x^p).
Definition ipow.c:33
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)
Definition scanargs.c:36
long processPipeOption(char **item, long items, unsigned long *flags)
Definition scanargs.c:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584
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.
Definition wild_match.c:49