203 {
204 int iArg;
205 char *freqUnits;
206 char *indepQuantity, **depenQuantity, **exclude, **realQuan = NULL, **imagQuan = NULL;
207 long depenQuantities, excludes;
208 char *input, *output;
209 long i, readCode, noWarnings, complexInput, inverse, spectrumFoldParExist = 0;
210 int64_t rows, rowsToUse, sampleInterval;
211 int32_t spectrumFolded = 0, page = 0;
212 unsigned long flags, pipeFlags, complexInputFlags = 0, fullOutputFlags = 0, majorOrderFlag;
213 long windowType = -1;
214 SCANNED_ARG *scanned;
216 double *tdata, rintegCutOffFreq, unwrapLimit = 0;
217 long padFactor, correctWindowEffects = 0;
218 short columnMajorOrder = -1;
219
221 argc =
scanargs(&scanned, argc, argv);
222 if (argc < 3 || argc > (3 + N_OPTIONS)) {
223 fprintf(stderr, "%s%s", USAGE1, USAGE2);
224 exit(EXIT_FAILURE);
225
226 }
227 rintegCutOffFreq = 0;
228 output = input = NULL;
229 flags = pipeFlags = excludes = complexInput = inverse = 0;
230 sampleInterval = 1;
231 indepQuantity = NULL;
232 depenQuantity = exclude = NULL;
233 depenQuantities = 0;
234 noWarnings = 0;
235 padFactor = 0;
236 for (iArg = 1; iArg < argc; iArg++) {
237 if (scanned[iArg].arg_type == OPTION) {
238
239 switch (
match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
240 case SET_NORMALIZE:
241 flags |= FL_NORMALIZE;
242 break;
243 case SET_WINDOW:
244 if (scanned[iArg].n_items != 1) {
245 if ((i =
match_string(scanned[iArg].list[1], window_type, N_WINDOW_TYPES, 0)) < 0)
247 windowType = i;
248 if (scanned[iArg].n_items > 2) {
249 if (strncmp(scanned[iArg].list[2], "correct", strlen(scanned[iArg].list[2])) == 0)
250 correctWindowEffects = 1;
251 else
253 }
254 } else
255 windowType = 0;
256 break;
257 case SET_PADWITHZEROES:
258 flags |= FL_PADWITHZEROES;
259 if (scanned[iArg].n_items != 1) {
260 if (scanned[iArg].n_items != 2 || sscanf(scanned[iArg].list[1], "%ld", &padFactor) != 1 || padFactor < 1)
261 SDDS_Bomb(
"invalid -padwithzeroes syntax");
262 }
263 break;
264 case SET_TRUNCATE:
265 flags |= FL_TRUNCATE;
266 break;
267 case SET_SUPPRESSAVERAGE:
268 flags |= FL_SUPPRESSAVERAGE;
269 break;
270 case SET_SAMPLEINTERVAL:
271 if (scanned[iArg].n_items != 2 || sscanf(scanned[iArg].list[1], "%" SCNd64, &sampleInterval) != 1 || sampleInterval <= 0)
272 SDDS_Bomb(
"invalid -sampleinterval syntax");
273 break;
274 case SET_COLUMNS:
275 if (indepQuantity)
276 SDDS_Bomb(
"only one -columns option may be given");
277 if (scanned[iArg].n_items < 2)
279 indepQuantity = scanned[iArg].list[1];
280 if (scanned[iArg].n_items >= 2) {
281 depenQuantity =
tmalloc(
sizeof(*depenQuantity) * (depenQuantities = scanned[iArg].n_items - 2));
282 for (i = 0; i < depenQuantities; i++)
283 depenQuantity[i] = scanned[iArg].list[i + 2];
284 }
285 break;
286 case SET_FULLOUTPUT:
287 flags |= FL_FULLOUTPUT;
288 if (scanned[iArg].n_items >= 2) {
289 scanned[iArg].n_items--;
290 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))
292 scanned[iArg].n_items++;
293 if (fullOutputFlags & FL_FULLOUTPUT_UNFOLDED)
294 flags |= FL_FULLOUTPUT_UNFOLDED;
295 else
296 flags |= FL_FULLOUTPUT_FOLDED;
297 if (fullOutputFlags & FL_UNWRAP_PHASE)
298 flags |= FL_UNWRAP_PHASE;
299 }
300 break;
301 case SET_PIPE:
302 if (!
processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags))
304 break;
305 case SET_PSDOUTPUT:
306 if (scanned[iArg].n_items -= 1) {
307 unsigned long tmpFlags;
308 if (strchr(scanned[iArg].list[1], '=') <= 0) {
309 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))
311 } else {
312 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))
314 }
315 flags |= tmpFlags;
316 } else
317 flags |= FL_PSDOUTPUT;
318 if (flags & FL_PSDINTEGOUTPUT && flags & FL_PSDRINTEGOUTPUT)
319 SDDS_Bomb(
"invalid -psdOutput syntax: give only one of integrated or rintegrated");
320 break;
321 case SET_EXCLUDE:
322 if (scanned[iArg].n_items < 2)
324 moveToStringArray(&exclude, &excludes, scanned[iArg].list + 1, scanned[iArg].n_items - 1);
325 break;
326 case SET_NOWARNINGS:
327 noWarnings = 1;
328 break;
329 case SET_COMPLEXINPUT:
330 complexInput = 1;
331 if (scanned[iArg].n_items == 2) {
332 scanned[iArg].n_items--;
333 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))
334 SDDS_Bomb(
"Invalid -complexInput syntax");
335 scanned[iArg].n_items++;
336 }
337 break;
338 case SET_INVERSE:
339 inverse = 1;
340 break;
341 case SET_MAJOR_ORDER:
342 majorOrderFlag = 0;
343 scanned[iArg].n_items--;
344 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)))
345 SDDS_Bomb(
"invalid -majorOrder syntax/values");
346 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
347 columnMajorOrder = 1;
348 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
349 columnMajorOrder = 0;
350 break;
351 default:
352 fprintf(stderr, "error: unknown/ambiguous option: %s\n", scanned[iArg].list[0]);
353 exit(EXIT_FAILURE);
354 break;
355 }
356 } else {
357 if (!input)
358 input = scanned[iArg].list[0];
359 else if (!output)
360 output = scanned[iArg].list[0];
361 else
363 }
364 }
365 if (!complexInput) {
366 if (!noWarnings && inverse)
367 fprintf(stderr, "Warning: the inverse option is ignored since it only works with -complexInput.\n");
368 inverse = 0;
369 }
370 if (!noWarnings && inverse && flags & FL_FULLOUTPUT_FOLDED)
371 fprintf(stderr, "Warning: the -inverse -fullOutput=folded will be changed to -inverse -fullOutput=unfolded.\n");
372
374
375 if (!indepQuantity)
376 SDDS_Bomb(
"Supply the independent quantity name with the -columns option.");
377
378 if (flags & FL_TRUNCATE && flags & FL_PADWITHZEROES)
379 SDDS_Bomb(
"Specify only one of -padwithzeroes and -truncate.");
380
383
385 exit(EXIT_FAILURE);
386
387 excludes = appendToStringArray(&exclude, excludes, indepQuantity);
388 if (!depenQuantities)
389 depenQuantities = appendToStringArray(&depenQuantity, depenQuantities, "*");
390
391 if (!complexInput) {
392 if ((depenQuantities = expandColumnPairNames(&SDDSin, &depenQuantity, NULL, depenQuantities, exclude, excludes, FIND_NUMERIC_TYPE, 0)) <= 0) {
394 SDDS_Bomb(
"No quantities selected to FFT.");
395 }
396 } else {
397 if ((depenQuantities = expandComplexColumnPairNames(&SDDSin, depenQuantity, &realQuan, &imagQuan, depenQuantities, exclude, excludes, FIND_NUMERIC_TYPE, 0)) <= 0) {
399 SDDS_Bomb(
"No quantities selected to FFT.");
400 }
401 }
402
403#if 0
404 fprintf(stderr, "%ld dependent quantities:\n", depenQuantities);
405 for (i = 0; i < depenQuantities; i++)
406 fprintf(stderr, " %s\n", depenQuantity[i]);
407#endif
408
409 if (!(freqUnits = makeFrequencyUnits(&SDDSin, indepQuantity)) ||
411 !create_fft_frequency_column(&SDDSout, &SDDSin, indepQuantity, freqUnits, inverse) ||
415 if (columnMajorOrder != -1)
416 SDDSout.layout.data_mode.column_major = columnMajorOrder;
417 else
418 SDDSout.layout.data_mode.column_major = SDDSin.layout.data_mode.column_major;
419
422 if (complexInput) {
423 if (!complexInputFlags) {
425 spectrumFoldParExist = 1;
426 } else if (complexInputFlags & FL_COMPLEXINPUT_UNFOLDED)
427 flags |= FL_COMPLEXINPUT_UNFOLDED;
428 else
429 flags |= FL_COMPLEXINPUT_FOLDED;
430 }
431 for (i = 0; i < depenQuantities; i++) {
432 if (!complexInput)
433 create_fft_columns(&SDDSout, &SDDSin, depenQuantity[i], indepQuantity, freqUnits,
434 flags & FL_FULLOUTPUT,
435 flags & (FL_PSDOUTPUT + FL_PSDINTEGOUTPUT + FL_PSDRINTEGOUTPUT),
436 0, inverse, flags & FL_UNWRAP_PHASE);
437 else
438 create_fft_columns(&SDDSout, &SDDSin, realQuan[i], indepQuantity, freqUnits,
439 flags & FL_FULLOUTPUT,
440 flags & (FL_PSDOUTPUT + FL_PSDINTEGOUTPUT + FL_PSDRINTEGOUTPUT),
441 1, inverse, flags & FL_UNWRAP_PHASE);
442 }
443
447
449 page++;
452 if (page == 1 && spectrumFoldParExist) {
455 if (spectrumFolded)
456 flags |= FL_COMPLEXINPUT_FOLDED;
457 else
458 flags |= FL_COMPLEXINPUT_UNFOLDED;
459 }
460 if (rows) {
461 int64_t primeRows, pow2Rows;
462 rowsToUse = rows;
463 primeRows = greatestProductOfSmallPrimes(rows);
464 if (rows != primeRows || padFactor) {
465 if (flags & FL_PADWITHZEROES) {
466 pow2Rows =
ipow(2., ((int64_t)(log((
double)rows) / log(2.0F))) + (padFactor ? padFactor : 1.0));
467 if ((primeRows = greatestProductOfSmallPrimes(pow2Rows)) > rows)
468 rowsToUse = primeRows;
469 else
470 rowsToUse = pow2Rows;
471 } else if (flags & FL_TRUNCATE)
472 rowsToUse = greatestProductOfSmallPrimes(rows);
474 fputs("Warning: number of points has large prime factors.\nThis could take a very long time.\nConsider using the -truncate option.\n", stderr);
475 }
480 for (i = 0; i < depenQuantities; i++)
481 if (!process_data(&SDDSout, &SDDSin, tdata, rows, rowsToUse,
482 complexInput ? realQuan[i] : depenQuantity[i],
483 complexInput ? imagQuan[i] : NULL,
484 flags | (i == 0 ? FL_MAKEFREQDATA : 0),
485 windowType, sampleInterval, correctWindowEffects, inverse,
486 rintegCutOffFreq, unwrapLimit)) {
488 exit(EXIT_FAILURE);
489 }
490 free(tdata);
491 } else {
494 }
497 }
498
501 exit(EXIT_FAILURE);
502 }
505 exit(EXIT_FAILURE);
506 }
507
508 return EXIT_SUCCESS;
509}
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.