151 {
152 char *indepQuantity, **depenQuantity, **exclude, **depenQuantityPair;
153 long depenQuantities, excludes;
154 char *input, *output;
155 long iArg, j, readCode, noWarnings, items;
156 int64_t i, rows, rowsToUse;
157 unsigned long flags, pairFlags, tmpFlags, pipeFlags, majorOrderFlag;
158 SCANNED_ARG *scArg;
160 double *tdata, *data, t0, dt;
161 double fracRMSChangeLimit, fracFreqAccuracyLimit;
162 int32_t frequenciesDesired, maxFrequencies, freqCycleLimit;
163 short truncate;
164 double *frequency, *amplitude = NULL, *phase = NULL, *significance = NULL, *phase1 = NULL, *amplitude1 = NULL, *significance1 = NULL;
165 long *frequencyIndex, *amplitudeIndex, *phaseIndex, *significanceIndex, pairs;
166 long *amplitudeIndex1, *phaseIndex1, *significanceIndex1;
167 short columnMajorOrder = -1;
168
170
171#ifdef DEBUG
172 if (1) {
173 long code;
174 double x, y;
175 x = 1.1;
176 code = OneDFunctionOptimize(&y, &x, 0.07, -4, 4, trialFn, 50, 1e-6, 0, 1);
177 fprintf(stderr, "code: %ld x=%e, y=%e\n", code, x, y);
178
179 x = .9;
180 code = OneDFunctionOptimize(&y, &x, 0.15, -4, 4, trialFn, 50, 1e-6, 0, 1);
181 fprintf(stderr, "code: %ld x=%e, y=%e\n", code, x, y);
182
183 x = .999;
184 code = OneDFunctionOptimize(&y, &x, 0.11, -4, 4, trialFn, 50, 1e-6, 0, 1);
185 fprintf(stderr, "code: %ld x=%e, y=%e\n", code, x, y);
186 exit(EXIT_SUCCESS);
187 }
188#endif
189
190 argc =
scanargs(&scArg, argc, argv);
191 if (argc < 3) {
192 fprintf(stderr, "%s%s", USAGE1, USAGE2);
193 exit(EXIT_FAILURE);
194 }
195 output = input = NULL;
196 flags = pipeFlags = excludes = truncate = pairFlags = 0;
197 indepQuantity = NULL;
198 depenQuantity = exclude = depenQuantityPair = NULL;
199 depenQuantities = 0;
200 noWarnings = 0;
201 fracRMSChangeLimit = 0.0;
202 fracFreqAccuracyLimit = 0.00001;
203 frequenciesDesired = 1;
204 maxFrequencies = 4;
205 freqCycleLimit = 100;
206 pairs = 0;
207
208 for (iArg = 1; iArg < argc; iArg++) {
209 if (scArg[iArg].arg_type == OPTION) {
210
211 switch (
match_string(scArg[iArg].list[0], option, N_OPTIONS, 0)) {
212 case SET_MAJOR_ORDER:
213 majorOrderFlag = 0;
214 scArg[iArg].n_items--;
215 if (scArg[iArg].n_items > 0 &&
216 (!
scanItemList(&majorOrderFlag, scArg[iArg].list + 1, &scArg[iArg].n_items, 0,
217 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
218 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL))) {
219 SDDS_Bomb(
"invalid -majorOrder syntax/values");
220 }
221 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
222 columnMajorOrder = 1;
223 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
224 columnMajorOrder = 0;
225 break;
226
227 case SET_TRUNCATE:
228 truncate = 1;
229 break;
230
231 case SET_PAIR:
232 if (depenQuantities)
233 SDDS_Bomb(
"Invalid -pair option, the depen-quantity is provided by -columns option already.");
234 if (scArg[iArg].n_items != 3)
236 depenQuantity =
SDDS_Realloc(depenQuantity,
sizeof(*depenQuantity) * (pairs + 1));
237 depenQuantityPair =
SDDS_Realloc(depenQuantityPair,
sizeof(*depenQuantityPair) * (pairs + 1));
238 depenQuantity[pairs] = scArg[iArg].list[1];
239 depenQuantityPair[pairs] = scArg[iArg].list[2];
240 pairs++;
241 break;
242
243 case SET_COLUMN:
244 if (indepQuantity)
245 SDDS_Bomb(
"only one -columns option may be given");
246 if (scArg[iArg].n_items < 2)
248 indepQuantity = scArg[iArg].list[1];
249 if (scArg[iArg].n_items >= 2) {
250 if (pairs)
251 SDDS_Bomb(
"Invalid -columns syntax, the depen-quantity is provided by -pair option already.");
252 depenQuantity =
tmalloc(
sizeof(*depenQuantity) * (depenQuantities = scArg[iArg].n_items - 2));
253 for (i = 0; i < depenQuantities; i++)
254 depenQuantity[i] = scArg[iArg].list[i + 2];
255 }
256 break;
257
258 case SET_PIPE:
259 if (!
processPipeOption(scArg[iArg].list + 1, scArg[iArg].n_items - 1, &pipeFlags))
261 break;
262
263 case SET_EXCLUDE:
264 if (scArg[iArg].n_items < 2)
266 moveToStringArray(&exclude, &excludes, scArg[iArg].list + 1, scArg[iArg].n_items - 1);
267 break;
268
269 case SET_NOWARNINGS:
270 noWarnings = 1;
271 break;
272
273 case SET_TERM_SEARCH:
274 items = scArg[iArg].n_items - 1;
275 flags &= ~(NAFF_RMS_CHANGE_LIMIT | NAFF_FREQS_DESIRED | NAFF_MAX_FREQUENCIES);
276 fracRMSChangeLimit = 0;
277 frequenciesDesired = 0;
278 maxFrequencies = 10;
279 if (!
scanItemList(&tmpFlags, scArg[iArg].list + 1, &items, 0,
280 "changelimit",
SDDS_DOUBLE, &fracRMSChangeLimit, 1, NAFF_RMS_CHANGE_LIMIT,
281 "maxfrequencies",
SDDS_LONG, &maxFrequencies, 1, NAFF_MAX_FREQUENCIES,
282 "frequencies",
SDDS_LONG, &frequenciesDesired, 1, NAFF_FREQS_DESIRED, NULL) ||
283 (tmpFlags & NAFF_RMS_CHANGE_LIMIT && tmpFlags & NAFF_FREQS_DESIRED) ||
284 maxFrequencies < 1) {
285 SDDS_Bomb(
"invalid -terminateSearch syntax");
286 }
287 flags |= tmpFlags;
288 if (frequenciesDesired)
289 maxFrequencies = frequenciesDesired;
290 break;
291
292 case SET_ITERATE_FREQ:
293 items = scArg[iArg].n_items - 1;
294 flags &= ~(NAFF_FREQ_CYCLE_LIMIT | NAFF_FREQ_ACCURACY_LIMIT);
295 if (!
scanItemList(&tmpFlags, scArg[iArg].list + 1, &items, 0,
296 "cyclelimit",
SDDS_LONG, &freqCycleLimit, 1, NAFF_FREQ_CYCLE_LIMIT,
297 "accuracylimit",
SDDS_DOUBLE, &fracFreqAccuracyLimit, 1, NAFF_FREQ_ACCURACY_LIMIT, NULL) ||
299 freqCycleLimit < 2) {
300 SDDS_Bomb(
"invalid -iterateFrequency syntax");
301 }
302 flags |= tmpFlags;
303 break;
304
305 default:
306 fprintf(stderr, "Error: unknown or ambiguous option: %s\n", scArg[iArg].list[0]);
307 exit(EXIT_FAILURE);
308 break;
309 }
310 } else {
311 if (!input)
312 input = scArg[iArg].list[0];
313 else if (!output)
314 output = scArg[iArg].list[0];
315 else
316 SDDS_Bomb(
"too many filenames provided");
317 }
318 }
319
321
322 if (!indepQuantity)
323 SDDS_Bomb(
"Supply the independent quantity name with the -columns option");
324
327
329 exit(EXIT_FAILURE);
330
331 excludes = appendToStringArray(&exclude, excludes, indepQuantity);
332 if (pairs) {
333 pairFlags = flags | NAFF_FREQ_FOUND;
334 depenQuantities = pairs;
335 }
336 if (!depenQuantities)
337 depenQuantities = appendToStringArray(&depenQuantity, depenQuantities, "*");
338 if (!pairs) {
339 if ((depenQuantities = expandColumnPairNames(&SDDSin, &depenQuantity, NULL, depenQuantities, exclude, excludes, FIND_NUMERIC_TYPE, 0)) <= 0) {
341 SDDS_Bomb(
"No quantities selected to FFT");
342 }
343 }
344
345 if (!SetupNAFFOutput(&SDDSout, output, &SDDSin, indepQuantity, depenQuantities, depenQuantity,
346 &frequencyIndex, &litudeIndex, &phaseIndex, &significanceIndex,
347 depenQuantityPair, &litudeIndex1, &phaseIndex1, &significanceIndex1,
348 columnMajorOrder)) {
350 }
351
352 if (!(frequency =
SDDS_Malloc(
sizeof(*frequency) * maxFrequencies)) ||
353 !(amplitude =
SDDS_Malloc(
sizeof(*amplitude) * maxFrequencies)) ||
354 !(phase =
SDDS_Malloc(
sizeof(*phase) * maxFrequencies)) ||
355 !(significance =
SDDS_Malloc(
sizeof(*significance) * maxFrequencies))) {
357 }
358 if (pairs) {
359 if (!(amplitude1 =
SDDS_Malloc(
sizeof(*amplitude1) * maxFrequencies)) ||
360 !(phase1 =
SDDS_Malloc(
sizeof(*phase1) * maxFrequencies)) ||
361 !(significance1 =
SDDS_Malloc(
sizeof(*significance1) * maxFrequencies))) {
363 }
364 }
365
369 if (rows) {
370 int64_t primeRows;
371 rowsToUse = rows;
372 primeRows = greatestProductOfSmallPrimes(rows);
373 if (rows != primeRows) {
374 if (truncate)
375 rowsToUse = greatestProductOfSmallPrimes(rows);
377 fputs("Warning: Number of points has large prime factors.\n"
378 "This could take a very long time.\nConsider using the -truncate option.\n",
379 stderr);
380 }
384 }
387 for (i = 1; i < rowsToUse; i++)
388 if (tdata[i] <= tdata[i - 1])
389 SDDS_Bomb(
"Independent data is not monotonically increasing");
390 dt = (tdata[rowsToUse - 1] - tdata[0]) / (rowsToUse - 1.0);
391 t0 = tdata[0];
392 free(tdata);
393 tdata = NULL;
394 for (i = 0; i < depenQuantities; i++) {
397 for (j = 0; j < maxFrequencies; j++)
398 frequency[j] = amplitude[j] = phase[j] = significance[j] = -1;
399 PerformNAFF(frequency, amplitude, phase, significance, t0, dt, data, rowsToUse, flags,
400 fracRMSChangeLimit, maxFrequencies, freqCycleLimit, fracFreqAccuracyLimit, 0, 0);
401#ifdef DEBUG
402 fprintf(stderr, "Column %s: ", depenQuantity[i]);
403 fprintf(stderr, "f=%10.3e a=%10.3e p=%10.3e s=%10.3e\n", frequency[0], amplitude[0], phase[0], significance[0]);
404#endif
405 free(data);
406 data = NULL;
407 if (pairs) {
410 PerformNAFF(frequency, amplitude1, phase1, significance1, t0, dt, data, rowsToUse,
411 pairFlags, fracRMSChangeLimit, maxFrequencies, freqCycleLimit, fracFreqAccuracyLimit, 0, 0);
412
413 for (j = 0; j < maxFrequencies; j++)
414 if (frequency[j] != -1)
415 frequency[j] = adjustFrequencyHalfPlane(frequency[j], phase[j], phase1[j], dt);
416 free(data);
417 data = NULL;
418 }
419 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, frequency, maxFrequencies, frequencyIndex[i]) ||
420 !
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, amplitude, maxFrequencies, amplitudeIndex[i]) ||
421 !
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, phase, maxFrequencies, phaseIndex[i]) ||
422 !
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, significance, maxFrequencies, significanceIndex[i])) {
424 }
425 if (pairs) {
426 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, amplitude1, maxFrequencies, amplitudeIndex1[i]) ||
427 !
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, phase1, maxFrequencies, phaseIndex1[i]) ||
428 !
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, significance1, maxFrequencies, significanceIndex1[i])) {
430 }
431 }
432 }
433 } else {
436 }
437 }
440 }
441
444 exit(EXIT_FAILURE);
445 }
448 exit(EXIT_FAILURE);
449 }
450 free(frequency);
451 free(amplitude);
452 free(phase);
453 free(significance);
454 if (pairs) {
455 free(amplitude1);
456 free(phase1);
457 free(significance1);
458 free(amplitudeIndex1);
459 free(phaseIndex1);
460 free(significanceIndex1);
461 free(depenQuantityPair);
462 }
463 free(depenQuantity);
464 free(frequencyIndex);
465 free(amplitudeIndex);
466 free(phaseIndex);
467 free(significanceIndex);
468 return EXIT_SUCCESS;
469}
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.