SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sddsnaff.c
Go to the documentation of this file.
1/**
2 * @file sddsnaff.c
3 * @brief Analyzes signals in SDDS files to extract frequency components using Laskar's NAFF method.
4 *
5 * @details
6 * This program processes SDDS (Self Describing Data Sets) files to determine fundamental frequencies,
7 * amplitudes, phases, and significances of signal components. It uses the Numerical Analysis of
8 * Fundamental Frequencies (NAFF) method, offering configurable options for truncation, exclusion, paired column analysis,
9 * and FFT performance tuning. Outputs can be formatted in row-major or column-major order.
10 *
11 * @section Usage
12 * ```
13 * sddsnaff [<inputfile>] [<outputfile>]
14 * [-pipe=[input][,output]]
15 * [-columns=<indep-variable>[,<depen-quantity>[,...]]]
16 * [-pair=<column1>,<column2>]
17 * [-exclude=<depen-quantity>[,...]]
18 * [-terminateSearch={changeLimit=<fraction>[,maxFrequencies=<number>] | frequencies=<number>}]
19 * [-iterateFrequency=[cycleLimit=<number>][,accuracyLimit=<fraction>]]
20 * [-truncate]
21 * [-noWarnings]
22 * [-majorOrder=row|column]
23 * ```
24
25 * @section Options
26 * | Required | Description |
27 * |---------------------------------------|---------------------------------------------------------------------------------------|
28 * | `-columns` | Specify the independent variable and dependent quantities to analyze. Wildcards are allowed. |
29
30 * | Optional | Description |
31 * |---------------------------------------|---------------------------------------------------------------------------------------|
32 * | `-pipe` | Use SDDS pipe options for input/output redirection. |
33 * | `-pair` | Specify a column pair for frequency and phase analysis. |
34 * | `-exclude` | Exclude specified quantities from analysis using wildcards. |
35 * | `-terminateSearch` | Define termination criteria for frequency search, based on RMS change or count. |
36 * | `-iterateFrequency` | Configure iteration parameters for frequency computation accuracy and cycles. |
37 * | `-truncate` | Truncate data for FFT optimization. |
38 * | `-noWarnings` | Suppress warning messages. |
39 * | `-majorOrder` | Define the output format: row-major or column-major. |
40
41 * @subsection Incompatibilities
42 * - `-columns` and `-pair` cannot be used simultaneously to specify dependent quantities.
43 * - Only one of the following may be specified:
44 * - `-terminateSearch`
45 * - `-iterateFrequency`
46 *
47 * @subsection Requirements
48 * - `-terminateSearch` requires either `changeLimit` or `frequencies` to be defined.
49 * - `-iterateFrequency` requires at least one of `cycleLimit` or `accuracyLimit`.
50
51 * @copyright
52 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
53 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
54 *
55 * @license
56 * This file is distributed under the terms of the Software License Agreement
57 * found in the file LICENSE included with this distribution.
58 *
59 * @authors
60 * M. Borland,
61 * R. Soliday,
62 * H. Shang
63 */
64
65#include "mdb.h"
66#include "SDDS.h"
67#include "scan.h"
68#include "fftpackC.h"
69#include "SDDSutils.h"
70#include <ctype.h>
71
72/* Enumeration for option types */
73enum option_type {
74 SET_TRUNCATE,
75 SET_COLUMN,
76 SET_EXCLUDE,
77 SET_PIPE,
78 SET_NOWARNINGS,
79 SET_TERM_SEARCH,
80 SET_ITERATE_FREQ,
81 SET_PAIR,
82 SET_MAJOR_ORDER,
83 N_OPTIONS
84};
85
86char *option[N_OPTIONS] = {
87 "truncate",
88 "columns",
89 "exclude",
90 "pipe",
91 "nowarnings",
92 "terminatesearch",
93 "iteratefrequency",
94 "pair",
95 "majorOrder",
96};
97
98static char *USAGE1 =
99 "Usage: sddsnaff [<inputfile>] [<outputfile>]\n"
100 " [-pipe=[input][,output]]\n"
101 " [-columns=<indep-variable>[,<depen-quantity>[,...]]]\n"
102 " [-pair=<column1>,<column2>]\n"
103 " [-exclude=<depen-quantity>[,...]]\n"
104 " [-terminateSearch={changeLimit=<fraction>[,maxFrequencies=<number>] | frequencies=<number>}]\n"
105 " [-iterateFrequency=[cycleLimit=<number>][,accuracyLimit=<fraction>]]\n"
106 " [-truncate]\n"
107 " [-noWarnings]\n"
108 " [-majorOrder=row|column]\n\n"
109 "Determines frequency components of signals using Laskar's NAFF method.\n"
110 "FFTs are involved in this process, hence some parameters refer to FFT configurations.\n\n"
111 "Options:\n"
112 " -pipe Use standard SDDS Toolkit pipe option for input and/or output.\n"
113 " -columns Specify the independent variable and dependent quantities to analyze.\n"
114 " <depen-quantity> entries may include wildcards.\n"
115 " -pair Specify a pair of columns for frequency and phase analysis.\n"
116 " Multiple -pair options can be provided.\n"
117 " -exclude Exclude specified quantities from analysis using wildcard patterns.\n"
118 " -terminateSearch Terminate the search based on RMS change limit or a specific number of frequencies.\n"
119 " -iterateFrequency Configure iteration parameters for frequency determination.\n"
120 " -truncate Truncate data to optimize FFT performance.\n"
121 " -noWarnings Suppress warning messages.\n"
122 " -majorOrder Specify output file's data order as row-major or column-major.\n\n";
123
124static char *USAGE2 =
125 "Program by Michael Borland. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
126
127long SetupNAFFOutput(SDDS_DATASET *SDDSout, char *output, SDDS_DATASET *SDDSin,
128 char *indepQuantity, long depenQuantities, char **depenQuantity, long **frequencyIndex,
129 long **amplitudeIndex, long **phaseIndex, long **significanceIndex, char **depenQuantityPair,
130 long **amplitudeIndex1, long **phaseIndex1, long **significanceIndex1, short columnMajorOrder);
131
132#ifdef DEBUG
133double trialFn(double x, long *invalid) {
134 *invalid = 0;
135 x -= 1;
136 if (x == 0)
137 return 1;
138 return (sin(x) / x + sqr(x - 0.5) * x * 0.5);
139}
140#endif
141
142int main(int argc, char **argv) {
143 char *indepQuantity, **depenQuantity, **exclude, **depenQuantityPair;
144 long depenQuantities, excludes;
145 char *input, *output;
146 long iArg, j, readCode, noWarnings, items;
147 int64_t i, rows, rowsToUse;
148 unsigned long flags, pairFlags, tmpFlags, pipeFlags, majorOrderFlag;
149 SCANNED_ARG *scArg;
150 SDDS_DATASET SDDSin, SDDSout;
151 double *tdata, *data, t0, dt;
152 double fracRMSChangeLimit, fracFreqAccuracyLimit;
153 int32_t frequenciesDesired, maxFrequencies, freqCycleLimit;
154 short truncate;
155 double *frequency, *amplitude = NULL, *phase = NULL, *significance = NULL, *phase1 = NULL, *amplitude1 = NULL, *significance1 = NULL;
156 long *frequencyIndex, *amplitudeIndex, *phaseIndex, *significanceIndex, pairs;
157 long *amplitudeIndex1, *phaseIndex1, *significanceIndex1;
158 short columnMajorOrder = -1;
159
161
162#ifdef DEBUG
163 if (1) {
164 long code;
165 double x, y;
166 x = 1.1;
167 code = OneDFunctionOptimize(&y, &x, 0.07, -4, 4, trialFn, 50, 1e-6, 0, 1);
168 fprintf(stderr, "code: %ld x=%e, y=%e\n", code, x, y);
169
170 x = .9;
171 code = OneDFunctionOptimize(&y, &x, 0.15, -4, 4, trialFn, 50, 1e-6, 0, 1);
172 fprintf(stderr, "code: %ld x=%e, y=%e\n", code, x, y);
173
174 x = .999;
175 code = OneDFunctionOptimize(&y, &x, 0.11, -4, 4, trialFn, 50, 1e-6, 0, 1);
176 fprintf(stderr, "code: %ld x=%e, y=%e\n", code, x, y);
177 exit(EXIT_SUCCESS);
178 }
179#endif
180
181 argc = scanargs(&scArg, argc, argv);
182 if (argc < 3) {
183 fprintf(stderr, "%s%s", USAGE1, USAGE2);
184 exit(EXIT_FAILURE);
185 }
186 output = input = NULL;
187 flags = pipeFlags = excludes = truncate = pairFlags = 0;
188 indepQuantity = NULL;
189 depenQuantity = exclude = depenQuantityPair = NULL;
190 depenQuantities = 0;
191 noWarnings = 0;
192 fracRMSChangeLimit = 0.0;
193 fracFreqAccuracyLimit = 0.00001;
194 frequenciesDesired = 1;
195 maxFrequencies = 4;
196 freqCycleLimit = 100;
197 pairs = 0;
198
199 for (iArg = 1; iArg < argc; iArg++) {
200 if (scArg[iArg].arg_type == OPTION) {
201 /* Process options */
202 switch (match_string(scArg[iArg].list[0], option, N_OPTIONS, 0)) {
203 case SET_MAJOR_ORDER:
204 majorOrderFlag = 0;
205 scArg[iArg].n_items--;
206 if (scArg[iArg].n_items > 0 &&
207 (!scanItemList(&majorOrderFlag, scArg[iArg].list + 1, &scArg[iArg].n_items, 0,
208 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
209 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL))) {
210 SDDS_Bomb("invalid -majorOrder syntax/values");
211 }
212 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
213 columnMajorOrder = 1;
214 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
215 columnMajorOrder = 0;
216 break;
217
218 case SET_TRUNCATE:
219 truncate = 1;
220 break;
221
222 case SET_PAIR:
223 if (depenQuantities)
224 SDDS_Bomb("Invalid -pair option, the depen-quantity is provided by -columns option already.");
225 if (scArg[iArg].n_items != 3)
226 SDDS_Bomb("invalid -pair syntax");
227 depenQuantity = SDDS_Realloc(depenQuantity, sizeof(*depenQuantity) * (pairs + 1));
228 depenQuantityPair = SDDS_Realloc(depenQuantityPair, sizeof(*depenQuantityPair) * (pairs + 1));
229 depenQuantity[pairs] = scArg[iArg].list[1];
230 depenQuantityPair[pairs] = scArg[iArg].list[2];
231 pairs++;
232 break;
233
234 case SET_COLUMN:
235 if (indepQuantity)
236 SDDS_Bomb("only one -columns option may be given");
237 if (scArg[iArg].n_items < 2)
238 SDDS_Bomb("invalid -columns syntax");
239 indepQuantity = scArg[iArg].list[1];
240 if (scArg[iArg].n_items >= 2) {
241 if (pairs)
242 SDDS_Bomb("Invalid -columns syntax, the depen-quantity is provided by -pair option already.");
243 depenQuantity = tmalloc(sizeof(*depenQuantity) * (depenQuantities = scArg[iArg].n_items - 2));
244 for (i = 0; i < depenQuantities; i++)
245 depenQuantity[i] = scArg[iArg].list[i + 2];
246 }
247 break;
248
249 case SET_PIPE:
250 if (!processPipeOption(scArg[iArg].list + 1, scArg[iArg].n_items - 1, &pipeFlags))
251 SDDS_Bomb("invalid -pipe syntax");
252 break;
253
254 case SET_EXCLUDE:
255 if (scArg[iArg].n_items < 2)
256 SDDS_Bomb("invalid -exclude syntax");
257 moveToStringArray(&exclude, &excludes, scArg[iArg].list + 1, scArg[iArg].n_items - 1);
258 break;
259
260 case SET_NOWARNINGS:
261 noWarnings = 1;
262 break;
263
264 case SET_TERM_SEARCH:
265 items = scArg[iArg].n_items - 1;
266 flags &= ~(NAFF_RMS_CHANGE_LIMIT | NAFF_FREQS_DESIRED | NAFF_MAX_FREQUENCIES);
267 fracRMSChangeLimit = 0;
268 frequenciesDesired = 0;
269 maxFrequencies = 10;
270 if (!scanItemList(&tmpFlags, scArg[iArg].list + 1, &items, 0,
271 "changelimit", SDDS_DOUBLE, &fracRMSChangeLimit, 1, NAFF_RMS_CHANGE_LIMIT,
272 "maxfrequencies", SDDS_LONG, &maxFrequencies, 1, NAFF_MAX_FREQUENCIES,
273 "frequencies", SDDS_LONG, &frequenciesDesired, 1, NAFF_FREQS_DESIRED, NULL) ||
274 (tmpFlags & NAFF_RMS_CHANGE_LIMIT && tmpFlags & NAFF_FREQS_DESIRED) ||
275 maxFrequencies < 1) {
276 SDDS_Bomb("invalid -terminateSearch syntax");
277 }
278 flags |= tmpFlags;
279 if (frequenciesDesired)
280 maxFrequencies = frequenciesDesired;
281 break;
282
283 case SET_ITERATE_FREQ:
284 items = scArg[iArg].n_items - 1;
285 flags &= ~(NAFF_FREQ_CYCLE_LIMIT | NAFF_FREQ_ACCURACY_LIMIT);
286 if (!scanItemList(&tmpFlags, scArg[iArg].list + 1, &items, 0,
287 "cyclelimit", SDDS_LONG, &freqCycleLimit, 1, NAFF_FREQ_CYCLE_LIMIT,
288 "accuracylimit", SDDS_DOUBLE, &fracFreqAccuracyLimit, 1, NAFF_FREQ_ACCURACY_LIMIT, NULL) ||
289 !bitsSet(tmpFlags) ||
290 freqCycleLimit < 2) {
291 SDDS_Bomb("invalid -iterateFrequency syntax");
292 }
293 flags |= tmpFlags;
294 break;
295
296 default:
297 fprintf(stderr, "Error: unknown or ambiguous option: %s\n", scArg[iArg].list[0]);
298 exit(EXIT_FAILURE);
299 break;
300 }
301 } else {
302 if (!input)
303 input = scArg[iArg].list[0];
304 else if (!output)
305 output = scArg[iArg].list[0];
306 else
307 SDDS_Bomb("too many filenames provided");
308 }
309 }
310
311 processFilenames("sddsnaff", &input, &output, pipeFlags, 0, NULL);
312
313 if (!indepQuantity)
314 SDDS_Bomb("Supply the independent quantity name with the -columns option");
315
316 if (!SDDS_InitializeInput(&SDDSin, input))
317 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
318
319 if (SDDS_CheckColumn(&SDDSin, indepQuantity, NULL, SDDS_ANY_NUMERIC_TYPE, stderr) != SDDS_CHECK_OKAY)
320 exit(EXIT_FAILURE);
321
322 excludes = appendToStringArray(&exclude, excludes, indepQuantity);
323 if (pairs) {
324 pairFlags = flags | NAFF_FREQ_FOUND;
325 depenQuantities = pairs;
326 }
327 if (!depenQuantities)
328 depenQuantities = appendToStringArray(&depenQuantity, depenQuantities, "*");
329 if (!pairs) {
330 if ((depenQuantities = expandColumnPairNames(&SDDSin, &depenQuantity, NULL, depenQuantities, exclude, excludes, FIND_NUMERIC_TYPE, 0)) <= 0) {
331 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
332 SDDS_Bomb("No quantities selected to FFT");
333 }
334 }
335
336 if (!SetupNAFFOutput(&SDDSout, output, &SDDSin, indepQuantity, depenQuantities, depenQuantity,
337 &frequencyIndex, &amplitudeIndex, &phaseIndex, &significanceIndex,
338 depenQuantityPair, &amplitudeIndex1, &phaseIndex1, &significanceIndex1,
339 columnMajorOrder)) {
340 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
341 }
342
343 if (!(frequency = SDDS_Malloc(sizeof(*frequency) * maxFrequencies)) ||
344 !(amplitude = SDDS_Malloc(sizeof(*amplitude) * maxFrequencies)) ||
345 !(phase = SDDS_Malloc(sizeof(*phase) * maxFrequencies)) ||
346 !(significance = SDDS_Malloc(sizeof(*significance) * maxFrequencies))) {
347 SDDS_Bomb("Memory allocation failure");
348 }
349 if (pairs) {
350 if (!(amplitude1 = SDDS_Malloc(sizeof(*amplitude1) * maxFrequencies)) ||
351 !(phase1 = SDDS_Malloc(sizeof(*phase1) * maxFrequencies)) ||
352 !(significance1 = SDDS_Malloc(sizeof(*significance1) * maxFrequencies))) {
353 SDDS_Bomb("Memory allocation failure");
354 }
355 }
356
357 while ((readCode = SDDS_ReadPage(&SDDSin)) > 0) {
358 if ((rows = SDDS_CountRowsOfInterest(&SDDSin)) < 0)
359 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
360 if (rows) {
361 int64_t primeRows;
362 rowsToUse = rows;
363 primeRows = greatestProductOfSmallPrimes(rows);
364 if (rows != primeRows) {
365 if (truncate)
366 rowsToUse = greatestProductOfSmallPrimes(rows);
367 else if (largest_prime_factor(rows) > 100 && !noWarnings)
368 fputs("Warning: Number of points has large prime factors.\n"
369 "This could take a very long time.\nConsider using the -truncate option.\n",
370 stderr);
371 }
372 if (!SDDS_StartPage(&SDDSout, maxFrequencies) ||
373 !SDDS_CopyParameters(&SDDSout, &SDDSin)) {
374 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
375 }
376 if (!(tdata = SDDS_GetColumnInDoubles(&SDDSin, indepQuantity)))
377 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
378 for (i = 1; i < rowsToUse; i++)
379 if (tdata[i] <= tdata[i - 1])
380 SDDS_Bomb("Independent data is not monotonically increasing");
381 dt = (tdata[rowsToUse - 1] - tdata[0]) / (rowsToUse - 1.0);
382 t0 = tdata[0];
383 free(tdata);
384 tdata = NULL;
385 for (i = 0; i < depenQuantities; i++) {
386 if (!(data = SDDS_GetColumnInDoubles(&SDDSin, depenQuantity[i])))
387 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
388 for (j = 0; j < maxFrequencies; j++)
389 frequency[j] = amplitude[j] = phase[j] = significance[j] = -1;
390 PerformNAFF(frequency, amplitude, phase, significance, t0, dt, data, rowsToUse, flags,
391 fracRMSChangeLimit, maxFrequencies, freqCycleLimit, fracFreqAccuracyLimit, 0, 0);
392#ifdef DEBUG
393 fprintf(stderr, "Column %s: ", depenQuantity[i]);
394 fprintf(stderr, "f=%10.3e a=%10.3e p=%10.3e s=%10.3e\n", frequency[0], amplitude[0], phase[0], significance[0]);
395#endif
396 free(data);
397 data = NULL;
398 if (pairs) {
399 if (!(data = SDDS_GetColumnInDoubles(&SDDSin, depenQuantityPair[i])))
400 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
401 PerformNAFF(frequency, amplitude1, phase1, significance1, t0, dt, data, rowsToUse,
402 pairFlags, fracRMSChangeLimit, maxFrequencies, freqCycleLimit, fracFreqAccuracyLimit, 0, 0);
403
404 for (j = 0; j < maxFrequencies; j++)
405 if (frequency[j] != -1)
406 frequency[j] = adjustFrequencyHalfPlane(frequency[j], phase[j], phase1[j], dt);
407 free(data);
408 data = NULL;
409 }
410 if (!SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, frequency, maxFrequencies, frequencyIndex[i]) ||
411 !SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, amplitude, maxFrequencies, amplitudeIndex[i]) ||
412 !SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, phase, maxFrequencies, phaseIndex[i]) ||
413 !SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, significance, maxFrequencies, significanceIndex[i])) {
414 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
415 }
416 if (pairs) {
417 if (!SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, amplitude1, maxFrequencies, amplitudeIndex1[i]) ||
418 !SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, phase1, maxFrequencies, phaseIndex1[i]) ||
419 !SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, significance1, maxFrequencies, significanceIndex1[i])) {
420 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
421 }
422 }
423 }
424 } else {
425 if (!SDDS_StartPage(&SDDSout, 0) || !SDDS_CopyParameters(&SDDSout, &SDDSin)) {
426 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
427 }
428 }
429 if (!SDDS_WritePage(&SDDSout))
430 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
431 }
432
433 if (!SDDS_Terminate(&SDDSin)) {
434 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
435 exit(EXIT_FAILURE);
436 }
437 if (!SDDS_Terminate(&SDDSout)) {
438 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
439 exit(EXIT_FAILURE);
440 }
441 free(frequency);
442 free(amplitude);
443 free(phase);
444 free(significance);
445 if (pairs) {
446 free(amplitude1);
447 free(phase1);
448 free(significance1);
449 free(amplitudeIndex1);
450 free(phaseIndex1);
451 free(significanceIndex1);
452 free(depenQuantityPair);
453 }
454 free(depenQuantity);
455 free(frequencyIndex);
456 free(amplitudeIndex);
457 free(phaseIndex);
458 free(significanceIndex);
459 return EXIT_SUCCESS;
460}
461
462long SetupNAFFOutput(SDDS_DATASET *SDDSout, char *output, SDDS_DATASET *SDDSin,
463 char *indepQuantity, long depenQuantities, char **depenQuantity, long **frequencyIndex,
464 long **amplitudeIndex, long **phaseIndex, long **significanceIndex, char **depenQuantityPair,
465 long **amplitudeIndex1, long **phaseIndex1, long **significanceIndex1, short columnMajorOrder) {
466 char *freqUnits, *buffer, *ampUnits;
467 long i, maxBuffer, bufferNeeded;
468
469 if (!(*frequencyIndex = SDDS_Malloc(sizeof(**frequencyIndex) * depenQuantities)) ||
470 !(*amplitudeIndex = SDDS_Malloc(sizeof(**amplitudeIndex) * depenQuantities)) ||
471 !(*phaseIndex = SDDS_Malloc(sizeof(**phaseIndex) * depenQuantities)) ||
472 !(*significanceIndex = SDDS_Malloc(sizeof(**significanceIndex) * depenQuantities)) ||
473 !(buffer = SDDS_Malloc(sizeof(*buffer) * (maxBuffer = 1024)))) {
474 SDDS_SetError("Memory allocation failure");
475 return 0;
476 }
477 if (!(freqUnits = makeFrequencyUnits(SDDSin, indepQuantity)) ||
478 !SDDS_InitializeOutput(SDDSout, SDDS_BINARY, 0, NULL, "sddsnaff output", output)) {
479 return 0;
480 }
481 if (columnMajorOrder != -1)
482 SDDSout->layout.data_mode.column_major = columnMajorOrder;
483 else
484 SDDSout->layout.data_mode.column_major = SDDSin->layout.data_mode.column_major;
485
486 for (i = 0; i < depenQuantities; i++) {
487 if ((bufferNeeded = strlen(depenQuantity[i]) + 12) > maxBuffer &&
488 !(buffer = SDDS_Realloc(buffer, sizeof(*buffer) * bufferNeeded))) {
489 SDDS_Bomb("Memory allocation failure");
490 }
491 sprintf(buffer, "%sFrequency", depenQuantity[i]);
492 if (((*frequencyIndex)[i] = SDDS_DefineColumn(SDDSout, buffer, NULL, freqUnits, NULL, NULL, SDDS_DOUBLE, 0)) < 0 ||
493 SDDS_GetColumnInformation(SDDSin, "units", &ampUnits, SDDS_GET_BY_NAME, depenQuantity[i]) != SDDS_STRING) {
494 return 0;
495 }
496 sprintf(buffer, "%sAmplitude", depenQuantity[i]);
497 if (((*amplitudeIndex)[i] = SDDS_DefineColumn(SDDSout, buffer, NULL, ampUnits, NULL, NULL, SDDS_DOUBLE, 0)) < 0)
498 return 0;
499 sprintf(buffer, "%sPhase", depenQuantity[i]);
500 if (((*phaseIndex)[i] = SDDS_DefineColumn(SDDSout, buffer, NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0)) < 0)
501 return 0;
502 sprintf(buffer, "%sSignificance", depenQuantity[i]);
503 if (((*significanceIndex)[i] = SDDS_DefineColumn(SDDSout, buffer, NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0)) < 0)
504 return 0;
505 }
506 if (depenQuantityPair) {
507 if (!(*amplitudeIndex1 = SDDS_Malloc(sizeof(**amplitudeIndex1) * depenQuantities)) ||
508 !(*phaseIndex1 = SDDS_Malloc(sizeof(**phaseIndex1) * depenQuantities)) ||
509 !(*significanceIndex1 = SDDS_Malloc(sizeof(**significanceIndex1) * depenQuantities))) {
510 SDDS_SetError("Memory allocation failure");
511 return 0;
512 }
513 for (i = 0; i < depenQuantities; i++) {
514 if ((bufferNeeded = strlen(depenQuantityPair[i]) + 12) > maxBuffer &&
515 !(buffer = SDDS_Realloc(buffer, sizeof(*buffer) * bufferNeeded))) {
516 SDDS_Bomb("Memory allocation failure");
517 }
518 sprintf(buffer, "%sAmplitude", depenQuantityPair[i]);
519 if (((*amplitudeIndex1)[i] = SDDS_DefineColumn(SDDSout, buffer, NULL, ampUnits, NULL, NULL, SDDS_DOUBLE, 0)) < 0)
520 return 0;
521 sprintf(buffer, "%sPhase", depenQuantityPair[i]);
522 if (((*phaseIndex1)[i] = SDDS_DefineColumn(SDDSout, buffer, NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0)) < 0)
523 return 0;
524 sprintf(buffer, "%sSignificance", depenQuantityPair[i]);
525 if (((*significanceIndex1)[i] = SDDS_DefineColumn(SDDSout, buffer, NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0)) < 0)
526 return 0;
527 }
528 }
529 free(ampUnits);
530 free(freqUnits);
531
532 if (!SDDS_TransferAllParameterDefinitions(SDDSout, SDDSin, SDDS_TRANSFER_KEEPOLD) ||
533 !SDDS_WriteLayout(SDDSout)) {
534 return 0;
535 }
536 free(buffer);
537 return 1;
538}
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_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.
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_TransferAllParameterDefinitions(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, uint32_t mode)
Transfers all parameter definitions from a source dataset to a target dataset.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
Definition SDDS_utils.c:379
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
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677
#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
long bitsSet(unsigned long data)
Counts the number of set bits (1s) in the given data.
Definition binary.c:52
int64_t largest_prime_factor(int64_t number)
Find the largest prime factor of a number.
Definition factorize.c:83
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
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.