235 {
236 int iArg;
237 char *freqUnits;
238 char *indepQuantity, **depenQuantity, **exclude, **realQuan = NULL, **imagQuan = NULL;
239 long depenQuantities, excludes;
240 char *input, *output;
241 long i, readCode, noWarnings, complexInput, inverse, spectrumFoldParExist = 0;
242 int64_t rows, rowsToUse, sampleInterval;
243 int32_t spectrumFolded = 0, page = 0;
244 unsigned long flags, pipeFlags, complexInputFlags = 0, fullOutputFlags = 0, majorOrderFlag;
245 long windowType = -1;
246 SCANNED_ARG *scanned;
248 double *tdata, rintegCutOffFreq, unwrapLimit = 0;
249 long padFactor, correctWindowEffects = 0;
250 short columnMajorOrder = -1;
251
253 argc =
scanargs(&scanned, argc, argv);
254 if (argc < 3 || argc > (3 + N_OPTIONS)) {
255 fprintf(stderr, "%s%s", USAGE1, USAGE2);
256 exit(EXIT_FAILURE);
257
258 }
259 rintegCutOffFreq = 0;
260 output = input = NULL;
261 flags = pipeFlags = excludes = complexInput = inverse = 0;
262 sampleInterval = 1;
263 indepQuantity = NULL;
264 depenQuantity = exclude = NULL;
265 depenQuantities = 0;
266 noWarnings = 0;
267 padFactor = 0;
268 for (iArg = 1; iArg < argc; iArg++) {
269 if (scanned[iArg].arg_type == OPTION) {
270
271 switch (
match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
272 case SET_NORMALIZE:
273 flags |= FL_NORMALIZE;
274 break;
275 case SET_WINDOW:
276 if (scanned[iArg].n_items != 1) {
277 if ((i =
match_string(scanned[iArg].list[1], window_type, N_WINDOW_TYPES, 0)) < 0)
279 windowType = i;
280 if (scanned[iArg].n_items > 2) {
281 if (strncmp(scanned[iArg].list[2], "correct", strlen(scanned[iArg].list[2])) == 0)
282 correctWindowEffects = 1;
283 else
285 }
286 } else
287 windowType = 0;
288 break;
289 case SET_PADWITHZEROES:
290 flags |= FL_PADWITHZEROES;
291 if (scanned[iArg].n_items != 1) {
292 if (scanned[iArg].n_items != 2 || sscanf(scanned[iArg].list[1], "%ld", &padFactor) != 1 || padFactor < 1)
293 SDDS_Bomb(
"invalid -padwithzeroes syntax");
294 }
295 break;
296 case SET_TRUNCATE:
297 flags |= FL_TRUNCATE;
298 break;
299 case SET_SUPPRESSAVERAGE:
300 flags |= FL_SUPPRESSAVERAGE;
301 break;
302 case SET_SAMPLEINTERVAL:
303 if (scanned[iArg].n_items != 2 || sscanf(scanned[iArg].list[1], "%" SCNd64, &sampleInterval) != 1 || sampleInterval <= 0)
304 SDDS_Bomb(
"invalid -sampleinterval syntax");
305 break;
306 case SET_COLUMNS:
307 if (indepQuantity)
308 SDDS_Bomb(
"only one -columns option may be given");
309 if (scanned[iArg].n_items < 2)
311 indepQuantity = scanned[iArg].list[1];
312 if (scanned[iArg].n_items >= 2) {
313 depenQuantity =
tmalloc(
sizeof(*depenQuantity) * (depenQuantities = scanned[iArg].n_items - 2));
314 for (i = 0; i < depenQuantities; i++)
315 depenQuantity[i] = scanned[iArg].list[i + 2];
316 }
317 break;
318 case SET_FULLOUTPUT:
319 flags |= FL_FULLOUTPUT;
320 if (scanned[iArg].n_items >= 2) {
321 scanned[iArg].n_items--;
322 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))
324 scanned[iArg].n_items++;
325 if (fullOutputFlags & FL_FULLOUTPUT_UNFOLDED)
326 flags |= FL_FULLOUTPUT_UNFOLDED;
327 else
328 flags |= FL_FULLOUTPUT_FOLDED;
329 if (fullOutputFlags & FL_UNWRAP_PHASE)
330 flags |= FL_UNWRAP_PHASE;
331 }
332 break;
333 case SET_PIPE:
334 if (!
processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags))
336 break;
337 case SET_PSDOUTPUT:
338 if (scanned[iArg].n_items -= 1) {
339 unsigned long tmpFlags;
340 if (strchr(scanned[iArg].list[1], '=') <= 0) {
341 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))
343 } else {
344 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))
346 }
347 flags |= tmpFlags;
348 } else
349 flags |= FL_PSDOUTPUT;
350 if (flags & FL_PSDINTEGOUTPUT && flags & FL_PSDRINTEGOUTPUT)
351 SDDS_Bomb(
"invalid -psdOutput syntax: give only one of integrated or rintegrated");
352 break;
353 case SET_EXCLUDE:
354 if (scanned[iArg].n_items < 2)
356 moveToStringArray(&exclude, &excludes, scanned[iArg].list + 1, scanned[iArg].n_items - 1);
357 break;
358 case SET_NOWARNINGS:
359 noWarnings = 1;
360 break;
361 case SET_COMPLEXINPUT:
362 complexInput = 1;
363 if (scanned[iArg].n_items == 2) {
364 scanned[iArg].n_items--;
365 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))
366 SDDS_Bomb(
"Invalid -complexInput syntax");
367 scanned[iArg].n_items++;
368 }
369 break;
370 case SET_INVERSE:
371 inverse = 1;
372 break;
373 case SET_MAJOR_ORDER:
374 majorOrderFlag = 0;
375 scanned[iArg].n_items--;
376 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)))
377 SDDS_Bomb(
"invalid -majorOrder syntax/values");
378 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
379 columnMajorOrder = 1;
380 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
381 columnMajorOrder = 0;
382 break;
383 default:
384 fprintf(stderr, "error: unknown/ambiguous option: %s\n", scanned[iArg].list[0]);
385 exit(EXIT_FAILURE);
386 break;
387 }
388 } else {
389 if (!input)
390 input = scanned[iArg].list[0];
391 else if (!output)
392 output = scanned[iArg].list[0];
393 else
395 }
396 }
397 if (!complexInput) {
398 if (!noWarnings && inverse)
399 fprintf(stderr, "Warning: the inverse option is ignored since it only works with -complexInput.\n");
400 inverse = 0;
401 }
402 if (!noWarnings && inverse && flags & FL_FULLOUTPUT_FOLDED)
403 fprintf(stderr, "Warning: the -inverse -fullOutput=folded will be changed to -inverse -fullOutput=unfolded.\n");
404
406
407 if (!indepQuantity)
408 SDDS_Bomb(
"Supply the independent quantity name with the -columns option.");
409
410 if (flags & FL_TRUNCATE && flags & FL_PADWITHZEROES)
411 SDDS_Bomb(
"Specify only one of -padwithzeroes and -truncate.");
412
415
417 exit(EXIT_FAILURE);
418
419 excludes = appendToStringArray(&exclude, excludes, indepQuantity);
420 if (!depenQuantities)
421 depenQuantities = appendToStringArray(&depenQuantity, depenQuantities, "*");
422
423 if (!complexInput) {
424 if ((depenQuantities = expandColumnPairNames(&SDDSin, &depenQuantity, NULL, depenQuantities, exclude, excludes, FIND_NUMERIC_TYPE, 0)) <= 0) {
426 SDDS_Bomb(
"No quantities selected to FFT.");
427 }
428 } else {
429 if ((depenQuantities = expandComplexColumnPairNames(&SDDSin, depenQuantity, &realQuan, &imagQuan, depenQuantities, exclude, excludes, FIND_NUMERIC_TYPE, 0)) <= 0) {
431 SDDS_Bomb(
"No quantities selected to FFT.");
432 }
433 }
434
435#if 0
436 fprintf(stderr, "%ld dependent quantities:\n", depenQuantities);
437 for (i = 0; i < depenQuantities; i++)
438 fprintf(stderr, " %s\n", depenQuantity[i]);
439#endif
440
441 if (!(freqUnits = makeFrequencyUnits(&SDDSin, indepQuantity)) ||
443 !create_fft_frequency_column(&SDDSout, &SDDSin, indepQuantity, freqUnits, inverse) ||
447 if (columnMajorOrder != -1)
448 SDDSout.layout.data_mode.column_major = columnMajorOrder;
449 else
450 SDDSout.layout.data_mode.column_major = SDDSin.layout.data_mode.column_major;
451
454 if (complexInput) {
455 if (!complexInputFlags) {
457 spectrumFoldParExist = 1;
458 } else if (complexInputFlags & FL_COMPLEXINPUT_UNFOLDED)
459 flags |= FL_COMPLEXINPUT_UNFOLDED;
460 else
461 flags |= FL_COMPLEXINPUT_FOLDED;
462 }
463 for (i = 0; i < depenQuantities; i++) {
464 if (!complexInput)
465 create_fft_columns(&SDDSout, &SDDSin, depenQuantity[i], indepQuantity, freqUnits,
466 flags & FL_FULLOUTPUT,
467 flags & (FL_PSDOUTPUT + FL_PSDINTEGOUTPUT + FL_PSDRINTEGOUTPUT),
468 0, inverse, flags & FL_UNWRAP_PHASE);
469 else
470 create_fft_columns(&SDDSout, &SDDSin, realQuan[i], indepQuantity, freqUnits,
471 flags & FL_FULLOUTPUT,
472 flags & (FL_PSDOUTPUT + FL_PSDINTEGOUTPUT + FL_PSDRINTEGOUTPUT),
473 1, inverse, flags & FL_UNWRAP_PHASE);
474 }
475
479
481 page++;
484 if (page == 1 && spectrumFoldParExist) {
487 if (spectrumFolded)
488 flags |= FL_COMPLEXINPUT_FOLDED;
489 else
490 flags |= FL_COMPLEXINPUT_UNFOLDED;
491 }
492 if (rows) {
493 int64_t primeRows, pow2Rows;
494 rowsToUse = rows;
495 primeRows = greatestProductOfSmallPrimes(rows);
496 if (rows != primeRows || padFactor) {
497 if (flags & FL_PADWITHZEROES) {
498 pow2Rows =
ipow(2., ((int64_t)(log((
double)rows) / log(2.0F))) + (padFactor ? padFactor : 1.0));
499 if ((primeRows = greatestProductOfSmallPrimes(pow2Rows)) > rows)
500 rowsToUse = primeRows;
501 else
502 rowsToUse = pow2Rows;
503 } else if (flags & FL_TRUNCATE)
504 rowsToUse = greatestProductOfSmallPrimes(rows);
506 fputs("Warning: number of points has large prime factors.\nThis could take a very long time.\nConsider using the -truncate option.\n", stderr);
507 }
512 for (i = 0; i < depenQuantities; i++)
513 if (!process_data(&SDDSout, &SDDSin, tdata, rows, rowsToUse,
514 complexInput ? realQuan[i] : depenQuantity[i],
515 complexInput ? imagQuan[i] : NULL,
516 flags | (i == 0 ? FL_MAKEFREQDATA : 0),
517 windowType, sampleInterval, correctWindowEffects, inverse,
518 rintegCutOffFreq, unwrapLimit)) {
520 exit(EXIT_FAILURE);
521 }
522 free(tdata);
523 } else {
526 }
529 }
530
533 exit(EXIT_FAILURE);
534 }
537 exit(EXIT_FAILURE);
538 }
539
540 return EXIT_SUCCESS;
541}
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_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_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_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_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
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.
#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.
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
int64_t largest_prime_factor(int64_t number)
Find the largest prime factor of a number.
double ipow(const double x, const int64_t p)
Compute x raised to the power p (x^p).
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
long processPipeOption(char **item, long items, unsigned long *flags)
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
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.