148 {
149 char *indepQuantity, **depenQuantity, **exclude, **depenQuantityPair;
150 long depenQuantities, excludes;
151 char *input, *output;
152 long iArg, readCode, noWarnings, items;
153 int64_t i, rows, rowsToUse;
154 unsigned long flags, pairFlags, tmpFlags, pipeFlags, majorOrderFlag;
155 SCANNED_ARG *scArg;
157 double *tdata, t0, dt;
158 double **dataArray = NULL, **pairDataArray = NULL;
159 double fracRMSChangeLimit, fracFreqAccuracyLimit;
160 int32_t frequenciesDesired, maxFrequencies, freqCycleLimit;
161 short truncate;
162 double *frequency, *amplitude = NULL, *phase = NULL, *significance = NULL, *phase1 = NULL, *amplitude1 = NULL, *significance1 = NULL;
163 long *frequencyIndex, *amplitudeIndex, *phaseIndex, *significanceIndex, pairs;
164 long *amplitudeIndex1, *phaseIndex1, *significanceIndex1;
165 short columnMajorOrder = -1;
166 int threads = 1;
167
169
170#ifdef DEBUG
171 if (1) {
172 long code;
173 double x, y;
174 x = 1.1;
175 code = OneDFunctionOptimize(&y, &x, 0.07, -4, 4, trialFn, 50, 1e-6, 0, 1);
176 fprintf(stderr, "code: %ld x=%e, y=%e\n", code, x, y);
177
178 x = .9;
179 code = OneDFunctionOptimize(&y, &x, 0.15, -4, 4, trialFn, 50, 1e-6, 0, 1);
180 fprintf(stderr, "code: %ld x=%e, y=%e\n", code, x, y);
181
182 x = .999;
183 code = OneDFunctionOptimize(&y, &x, 0.11, -4, 4, trialFn, 50, 1e-6, 0, 1);
184 fprintf(stderr, "code: %ld x=%e, y=%e\n", code, x, y);
185 exit(EXIT_SUCCESS);
186 }
187#endif
188
189 argc =
scanargs(&scArg, argc, argv);
190 if (argc < 3) {
191 fprintf(stderr, "%s%s", USAGE1, USAGE2);
192 exit(EXIT_FAILURE);
193 }
194 output = input = NULL;
195 flags = pipeFlags = excludes = truncate = pairFlags = 0;
196 indepQuantity = NULL;
197 depenQuantity = exclude = depenQuantityPair = NULL;
198 depenQuantities = 0;
199 noWarnings = 0;
200 fracRMSChangeLimit = 0.0;
201 fracFreqAccuracyLimit = 0.00001;
202 frequenciesDesired = 1;
203 maxFrequencies = 4;
204 freqCycleLimit = 100;
205 pairs = 0;
206
207 for (iArg = 1; iArg < argc; iArg++) {
208 if (scArg[iArg].arg_type == OPTION) {
209
210 switch (
match_string(scArg[iArg].list[0], option, N_OPTIONS, 0)) {
211 case SET_MAJOR_ORDER:
212 majorOrderFlag = 0;
213 scArg[iArg].n_items--;
214 if (scArg[iArg].n_items > 0 &&
215 (!
scanItemList(&majorOrderFlag, scArg[iArg].list + 1, &scArg[iArg].n_items, 0,
216 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
217 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL))) {
218 SDDS_Bomb(
"invalid -majorOrder syntax/values");
219 }
220 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
221 columnMajorOrder = 1;
222 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
223 columnMajorOrder = 0;
224 break;
225
226 case SET_THREADS:
227 if (scArg[iArg].n_items != 2 ||
228 sscanf(scArg[iArg].list[1], "%d", &threads) != 1 || threads < 1)
230 break;
231
232 case SET_TRUNCATE:
233 truncate = 1;
234 break;
235
236 case SET_PAIR:
237 if (depenQuantities)
238 SDDS_Bomb(
"Invalid -pair option, the depen-quantity is provided by -columns option already.");
239 if (scArg[iArg].n_items != 3)
241 depenQuantity =
SDDS_Realloc(depenQuantity,
sizeof(*depenQuantity) * (pairs + 1));
242 depenQuantityPair =
SDDS_Realloc(depenQuantityPair,
sizeof(*depenQuantityPair) * (pairs + 1));
243 depenQuantity[pairs] = scArg[iArg].list[1];
244 depenQuantityPair[pairs] = scArg[iArg].list[2];
245 pairs++;
246 break;
247
248 case SET_COLUMN:
249 if (indepQuantity)
250 SDDS_Bomb(
"only one -columns option may be given");
251 if (scArg[iArg].n_items < 2)
253 indepQuantity = scArg[iArg].list[1];
254 if (scArg[iArg].n_items >= 2) {
255 if (pairs)
256 SDDS_Bomb(
"Invalid -columns syntax, the depen-quantity is provided by -pair option already.");
257 depenQuantity =
tmalloc(
sizeof(*depenQuantity) * (depenQuantities = scArg[iArg].n_items - 2));
258 for (i = 0; i < depenQuantities; i++)
259 depenQuantity[i] = scArg[iArg].list[i + 2];
260 }
261 break;
262
263 case SET_PIPE:
264 if (!
processPipeOption(scArg[iArg].list + 1, scArg[iArg].n_items - 1, &pipeFlags))
266 break;
267
268 case SET_EXCLUDE:
269 if (scArg[iArg].n_items < 2)
271 moveToStringArray(&exclude, &excludes, scArg[iArg].list + 1, scArg[iArg].n_items - 1);
272 break;
273
274 case SET_NOWARNINGS:
275 noWarnings = 1;
276 break;
277
278 case SET_TERM_SEARCH:
279 items = scArg[iArg].n_items - 1;
280 flags &= ~(NAFF_RMS_CHANGE_LIMIT | NAFF_FREQS_DESIRED | NAFF_MAX_FREQUENCIES);
281 fracRMSChangeLimit = 0;
282 frequenciesDesired = 0;
283 maxFrequencies = 10;
284 if (!
scanItemList(&tmpFlags, scArg[iArg].list + 1, &items, 0,
285 "changelimit",
SDDS_DOUBLE, &fracRMSChangeLimit, 1, NAFF_RMS_CHANGE_LIMIT,
286 "maxfrequencies",
SDDS_LONG, &maxFrequencies, 1, NAFF_MAX_FREQUENCIES,
287 "frequencies",
SDDS_LONG, &frequenciesDesired, 1, NAFF_FREQS_DESIRED, NULL) ||
288 (tmpFlags & NAFF_RMS_CHANGE_LIMIT && tmpFlags & NAFF_FREQS_DESIRED) ||
289 maxFrequencies < 1) {
290 SDDS_Bomb(
"invalid -terminateSearch syntax");
291 }
292 flags |= tmpFlags;
293 if (frequenciesDesired)
294 maxFrequencies = frequenciesDesired;
295 break;
296
297 case SET_ITERATE_FREQ:
298 items = scArg[iArg].n_items - 1;
299 flags &= ~(NAFF_FREQ_CYCLE_LIMIT | NAFF_FREQ_ACCURACY_LIMIT);
300 if (!
scanItemList(&tmpFlags, scArg[iArg].list + 1, &items, 0,
301 "cyclelimit",
SDDS_LONG, &freqCycleLimit, 1, NAFF_FREQ_CYCLE_LIMIT,
302 "accuracylimit",
SDDS_DOUBLE, &fracFreqAccuracyLimit, 1, NAFF_FREQ_ACCURACY_LIMIT, NULL) ||
304 freqCycleLimit < 2) {
305 SDDS_Bomb(
"invalid -iterateFrequency syntax");
306 }
307 flags |= tmpFlags;
308 break;
309
310 default:
311 fprintf(stderr, "Error: unknown or ambiguous option: %s\n", scArg[iArg].list[0]);
312 exit(EXIT_FAILURE);
313 break;
314 }
315 } else {
316 if (!input)
317 input = scArg[iArg].list[0];
318 else if (!output)
319 output = scArg[iArg].list[0];
320 else
321 SDDS_Bomb(
"too many filenames provided");
322 }
323 }
324
326
327 if (!indepQuantity)
328 SDDS_Bomb(
"Supply the independent quantity name with the -columns option");
329
332
334 exit(EXIT_FAILURE);
335
336 excludes = appendToStringArray(&exclude, excludes, indepQuantity);
337 if (pairs) {
338 pairFlags = flags | NAFF_FREQ_FOUND;
339 depenQuantities = pairs;
340 }
341 if (!depenQuantities)
342 depenQuantities = appendToStringArray(&depenQuantity, depenQuantities, "*");
343 if (!pairs) {
344 if ((depenQuantities = expandColumnPairNames(&SDDSin, &depenQuantity, NULL, depenQuantities, exclude, excludes, FIND_NUMERIC_TYPE, 0)) <= 0) {
346 SDDS_Bomb(
"No quantities selected to FFT");
347 }
348 }
349
350 if (!SetupNAFFOutput(&SDDSout, output, &SDDSin, indepQuantity, depenQuantities, depenQuantity,
351 &frequencyIndex, &litudeIndex, &phaseIndex, &significanceIndex,
352 depenQuantityPair, &litudeIndex1, &phaseIndex1, &significanceIndex1,
353 columnMajorOrder)) {
355 }
356
357 if (!(frequency =
SDDS_Malloc(
sizeof(*frequency) * depenQuantities * maxFrequencies)) ||
358 !(amplitude =
SDDS_Malloc(
sizeof(*amplitude) * depenQuantities * maxFrequencies)) ||
359 !(phase =
SDDS_Malloc(
sizeof(*phase) * depenQuantities * maxFrequencies)) ||
360 !(significance =
SDDS_Malloc(
sizeof(*significance) * depenQuantities * maxFrequencies))) {
362 }
363 if (pairs) {
364 if (!(amplitude1 =
SDDS_Malloc(
sizeof(*amplitude1) * depenQuantities * maxFrequencies)) ||
365 !(phase1 =
SDDS_Malloc(
sizeof(*phase1) * depenQuantities * maxFrequencies)) ||
366 !(significance1 =
SDDS_Malloc(
sizeof(*significance1) * depenQuantities * maxFrequencies))) {
368 }
369 }
370
374 if (rows) {
375 int64_t primeRows;
376 rowsToUse = rows;
377 primeRows = greatestProductOfSmallPrimes(rows);
378 if (rows != primeRows) {
379 if (truncate)
380 rowsToUse = greatestProductOfSmallPrimes(rows);
382 fputs("Warning: Number of points has large prime factors.\n"
383 "This could take a very long time.\nConsider using the -truncate option.\n",
384 stderr);
385 }
389 }
392 for (i = 1; i < rowsToUse; i++)
393 if (tdata[i] <= tdata[i - 1])
394 SDDS_Bomb(
"Independent data is not monotonically increasing");
395 dt = (tdata[rowsToUse - 1] - tdata[0]) / (rowsToUse - 1.0);
396 t0 = tdata[0];
397 free(tdata);
398 tdata = NULL;
399 dataArray =
SDDS_Malloc(
sizeof(*dataArray) * depenQuantities);
400 if (pairs)
401 pairDataArray =
SDDS_Malloc(
sizeof(*pairDataArray) * depenQuantities);
402 for (i = 0; i < depenQuantities; i++) {
407 }
408#pragma omp parallel for if (threads > 1) num_threads(threads)
409 for (i = 0; i < depenQuantities; i++) {
410 long j;
411 double *frequency1 = frequency + i * maxFrequencies;
412 double *amplitude0 = amplitude + i * maxFrequencies;
413 double *phase0 = phase + i * maxFrequencies;
414 double *significance0 = significance + i * maxFrequencies;
415 double *amplitude1p = pairs ? amplitude1 + i * maxFrequencies : NULL;
416 double *phase1p = pairs ? phase1 + i * maxFrequencies : NULL;
417 double *significance1p = pairs ? significance1 + i * maxFrequencies : NULL;
418
419 for (j = 0; j < maxFrequencies; j++)
420 frequency1[j] = amplitude0[j] = phase0[j] = significance0[j] = -1;
421 PerformNAFF(frequency1, amplitude0, phase0, significance0, t0, dt, dataArray[i], rowsToUse, flags,
422 fracRMSChangeLimit, maxFrequencies, freqCycleLimit, fracFreqAccuracyLimit, 0, 0);
423#ifdef DEBUG
424 fprintf(stderr, "Column %s: ", depenQuantity[i]);
425 fprintf(stderr, "f=%10.3e a=%10.3e p=%10.3e s=%10.3e\n", frequency1[0], amplitude0[0], phase0[0], significance0[0]);
426#endif
427 if (pairs) {
428 for (j = 0; j < maxFrequencies; j++)
429 amplitude1p[j] = phase1p[j] = significance1p[j] = -1;
430 PerformNAFF(frequency1, amplitude1p, phase1p, significance1p, t0, dt, pairDataArray[i], rowsToUse,
431 pairFlags, fracRMSChangeLimit, maxFrequencies, freqCycleLimit, fracFreqAccuracyLimit, 0, 0);
432
433 for (j = 0; j < maxFrequencies; j++)
434 if (frequency1[j] != -1)
435 frequency1[j] = adjustFrequencyHalfPlane(frequency1[j], phase0[j], phase1p[j], dt);
436 }
437 }
438 for (i = 0; i < depenQuantities; i++) {
439 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, frequency + i * maxFrequencies, maxFrequencies, frequencyIndex[i]) ||
440 !
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, amplitude + i * maxFrequencies, maxFrequencies, amplitudeIndex[i]) ||
441 !
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, phase + i * maxFrequencies, maxFrequencies, phaseIndex[i]) ||
442 !
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, significance + i * maxFrequencies, maxFrequencies, significanceIndex[i])) {
444 }
445 if (pairs) {
446 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, amplitude1 + i * maxFrequencies, maxFrequencies, amplitudeIndex1[i]) ||
447 !
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, phase1 + i * maxFrequencies, maxFrequencies, phaseIndex1[i]) ||
448 !
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, significance1 + i * maxFrequencies, maxFrequencies, significanceIndex1[i])) {
450 }
451 }
452 free(dataArray[i]);
453 if (pairs)
454 free(pairDataArray[i]);
455 }
456 free(dataArray);
457 dataArray = NULL;
458 if (pairs) {
459 free(pairDataArray);
460 pairDataArray = NULL;
461 }
462 } else {
465 }
466 }
469 }
470
473 exit(EXIT_FAILURE);
474 }
477 exit(EXIT_FAILURE);
478 }
479 free(frequency);
480 free(amplitude);
481 free(phase);
482 free(significance);
483 if (pairs) {
484 free(amplitude1);
485 free(phase1);
486 free(significance1);
487 free(amplitudeIndex1);
488 free(phaseIndex1);
489 free(significanceIndex1);
490 free(depenQuantityPair);
491 }
492 free(depenQuantity);
493 free(frequencyIndex);
494 free(amplitudeIndex);
495 free(phaseIndex);
496 free(significanceIndex);
497 return EXIT_SUCCESS;
498}
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_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_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
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.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
#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.
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
long bitsSet(unsigned long data)
Counts the number of set bits (1s) in the given data.
int64_t largest_prime_factor(int64_t number)
Find the largest prime factor of a number.
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
long processPipeOption(char **item, long items, unsigned long *flags)
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.