SDDS ToolKit Programs and Libraries for C and Python
Loading...
Searching...
No Matches
sddssinefit.c File Reference

Detailed Description

Performs a sinusoidal fit on input data.

This program reads input data from an SDDS (Self Describing Data Sets) file, fits the data to one of two sinusoidal models:

\[
    y(n) = a_0 + a_1 \sin(2\pi a_2 x(n) + a_3)
    \]

or

\[
    y(n) = a_0 + a_1 \sin(2\pi a_2 x(n) + a_3) + a_5 x(n)
    \]

or

\[
    y(n) = a_0 + a_1 \sin(2\pi a_2 x(n) + a_3)*exp(x(n)*a_5) + a_6 x(n)
    \]

Based on user-provided parameters and options, the program performs fitting and outputs the fitted data along with residuals to an output SDDS file.

Usage

sddssinefit [<inputfile>] [<outputfile>]
[-pipe=<input>[,<output>]]
[-fulloutput]
-columns=<x-name>,<y-name>
[-tolerance=<value>]
[-limits=evaluations=<number>,passes=<number>]
[-verbosity=<integer>]
[-guess=constant=<constant>,factor=<factor>,frequency=<freq>,phase=<phase>,slope=<slope>,rate=<value>]
[-lockFrequency]
[-addSlope]
[-addExponential={grow|decay}]
[-majorOrder=row|column]

Options

Required Description
-columns Specifies the x and y data column names.
Optional Description
-pipe Use standard input/output for data streams.
-fulloutput Includes full output with residuals.
-tolerance Sets the tolerance for the fitting algorithm (default: 1e-6).
-limits=evaluations Sets maximum number of evaluations and passes (default: 5000 evaluations, 25 passes).
-verbosity Sets verbosity level (default: 0).
-guess Provides initial guesses for fit parameters.
-lockFrequency Locks the frequency parameter during fitting.
-addSlope Includes a slope term in the fit.
-addExponential Includes decaying expontential factor in the fit.
-majorOrder Specifies the major order for data processing.

Incompatibilities

  • -lockFrequency cannot be used with -guess=frequency=<freq>.

Requirements

  • For -guess, at least one of the guess parameters (constant, factor, frequency, phase, rate, slope) is required.
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Author
M. Borland, C. Saunders, R. Soliday, L. Emery, H. Shang, N. Kuklev

Definition in file sddssinefit.c.

#include "mdb.h"
#include "SDDS.h"
#include "scan.h"

Go to the source code of this file.

Functions

double fitFunction (double *a, long *invalid)
 
void report (double res, double *a, long pass, long n_eval, long n_dimen)
 
void setupOutputFile (SDDS_DATASET *OutputTable, int32_t *xIndex, int32_t *yIndex, int32_t *fitIndex, int32_t *residualIndex, char *output, long fullOutput, SDDS_DATASET *InputTable, char *xName, char *yName, short columnMajorOrder, short addSlope, short addExponential)
 
char * makeInverseUnits (char *units)
 
int main (int argc, char **argv)
 

Function Documentation

◆ fitFunction()

double fitFunction ( double * a,
long * invalid )

Definition at line 571 of file sddssinefit.c.

571 {
572 int64_t i;
573 double chi, min_chi, fitValue;
574
575 min_chi = DBL_MAX;
576
577 *invalid = 0;
578 if (verbosity>5) {
579 fprintf(stderr, "Trial: a = %e, %e, %e, %e, %e, %e\n", a[0], a[1], a[2], a[3], a[4], a[5]);
580 }
581 for (i = chi = 0; i < nData; i++) {
582 fitValue = a[1] * sin(PIx2 * a[2] * xData[i] + a[3]);
583 if (addExponential)
584 fitValue *= exp(xData[i]*a[5]);
585 if (addSlope)
586 fitValue += a[4] * xData[i];
587 fitValue += a[0];
588 fitData[i] = fitValue;
589 residualData[i] = yData[i] - fitValue;
590 chi += sqr(residualData[i]);
591 }
592 if (isnan(chi) || isinf(chi))
593 *invalid = 1;
594 if (verbosity > 5)
595 fprintf(stderr, " --> chi = %e, invalid = %ld\n", chi, *invalid);
596 if (min_chi > chi) {
597 min_chi = chi;
598 fit[0] = a[0];
599 fit[1] = a[1];
600 fit[2] = a[2];
601 fit[3] = a[3];
602 fit[4] = a[4];
603 fit[5] = a[5];
604 if (verbosity > 2)
605 fprintf(stderr, "New best chi = %e: a = %e, %e, %e, %e, %e, %e\n",
606 chi, fit[0], fit[1], fit[2], fit[3], fit[4], fit[5]);
607 }
608 return chi;
609}

◆ main()

int main ( int argc,
char ** argv )

Definition at line 183 of file sddssinefit.c.

183 {
184 double tolerance, result;
185 int32_t nEvalMax = 5000, nPassMax = 25;
186 double a[6], da[6];
187 double alo[6], ahi[6];
188 int64_t zeroes;
189 SDDS_DATASET InputTable, OutputTable;
190 SCANNED_ARG *s_arg;
191 long i_arg, fullOutput;
192 int64_t i;
193 char *input, *output, *xName, *yName;
194 int32_t xIndex, yIndex, fitIndex, residualIndex;
195 long retval;
196 unsigned long guessFlags, dummyFlags, pipeFlags;
197 double constantGuess, factorGuess, freqGuess, phaseGuess, slopeGuess, rateGuess;
198 double firstZero, lastZero;
199 unsigned long simplexFlags = 0, majorOrderFlag;
200 short columnMajorOrder = -1;
201 short lockFreq = 0;
202
204 argc = scanargs(&s_arg, argc, argv);
205 if (argc < 2 || argc > (2 + N_OPTIONS))
206 bomb(NULL, USAGE);
207
208 input = output = NULL;
209 tolerance = 1e-6;
210 verbosity = fullOutput = 0;
211 xName = yName = NULL;
212 guessFlags = 0;
213 pipeFlags = 0;
214 constantGuess = factorGuess = freqGuess = phaseGuess = slopeGuess = rateGuess = 0;
215
216 for (i_arg = 1; i_arg < argc; i_arg++) {
217 if (s_arg[i_arg].arg_type == OPTION) {
218 switch (match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
219 case SET_MAJOR_ORDER:
220 majorOrderFlag = 0;
221 s_arg[i_arg].n_items--;
222 if (s_arg[i_arg].n_items > 0 &&
223 (!scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
224 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
225 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
226 SDDS_Bomb("invalid -majorOrder syntax/values");
227 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
228 columnMajorOrder = 1;
229 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
230 columnMajorOrder = 0;
231 break;
232 case SET_TOLERANCE:
233 if (s_arg[i_arg].n_items != 2 || sscanf(s_arg[i_arg].list[1], "%lf", &tolerance) != 1)
234 SDDS_Bomb("incorrect -tolerance syntax");
235 break;
236 case SET_VERBOSITY:
237 if (s_arg[i_arg].n_items != 2 || sscanf(s_arg[i_arg].list[1], "%ld", &verbosity) != 1)
238 SDDS_Bomb("incorrect -verbosity syntax");
239 break;
240 case SET_GUESS:
241 if (s_arg[i_arg].n_items < 2)
242 SDDS_Bomb("incorrect -guess syntax");
243 s_arg[i_arg].n_items -= 1;
244 if (!scanItemList(&guessFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
245 "constant", SDDS_DOUBLE, &constantGuess, 1, GUESS_CONSTANT_GIVEN,
246 "factor", SDDS_DOUBLE, &factorGuess, 1, GUESS_FACTOR_GIVEN,
247 "frequency", SDDS_DOUBLE, &freqGuess, 1, GUESS_FREQ_GIVEN,
248 "phase", SDDS_DOUBLE, &phaseGuess, 1, GUESS_PHASE_GIVEN,
249 "slope", SDDS_DOUBLE, &slopeGuess, 1, GUESS_SLOPE_GIVEN,
250 "rate", SDDS_DOUBLE, &rateGuess, 1, GUESS_RATE_GIVEN, NULL,
251 NULL))
252 SDDS_Bomb("invalid -guess syntax");
253 break;
254 case SET_COLUMNS:
255 if (s_arg[i_arg].n_items != 3)
256 SDDS_Bomb("invalid -columns syntax");
257 xName = s_arg[i_arg].list[1];
258 yName = s_arg[i_arg].list[2];
259 break;
260 case SET_FULLOUTPUT:
261 fullOutput = 1;
262 break;
263 case SET_LOCK_FREQ:
264 lockFreq = 1;
265 break;
266 case SET_ADD_SLOPE:
267 addSlope = 1;
268 break;
269 case SET_ADD_EXPONENTIAL:
270 if (s_arg[i_arg].n_items!=2)
271 SDDS_Bomb("incorrect -addExponential syntax");
272 switch (match_string(s_arg[i_arg].list[1], expotentialOptions, EXPONENTIAL_OPTIONS, 0)) {
273 case EXPONENTIAL_DECAY:
274 addExponential = -1;
275 break;
276 case EXPONENTIAL_GROW:
277 addExponential = 1;
278 break;
279 default:
280 SDDS_Bomb("incorrect -addExponential syntax");
281 break;
282 }
283 break;
284 case SET_LIMITS:
285 if (s_arg[i_arg].n_items < 2)
286 SDDS_Bomb("incorrect -limits syntax");
287 s_arg[i_arg].n_items -= 1;
288 if (!scanItemList(&dummyFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
289 "evaluations", SDDS_LONG, &nEvalMax, 1, 0,
290 "passes", SDDS_LONG, &nPassMax, 1, 0, NULL) ||
291 nEvalMax <= 0 || nPassMax <= 0)
292 SDDS_Bomb("invalid -limits syntax");
293 break;
294 case SET_PIPE:
295 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
296 SDDS_Bomb("invalid -pipe syntax");
297 break;
298 default:
299 fprintf(stderr, "Error: Unknown or ambiguous option: %s\n", s_arg[i_arg].list[0]);
300 exit(EXIT_FAILURE);
301 break;
302 }
303 } else {
304 if (input == NULL)
305 input = s_arg[i_arg].list[0];
306 else if (output == NULL)
307 output = s_arg[i_arg].list[0];
308 else
309 SDDS_Bomb("Too many filenames provided.");
310 }
311 }
312
313 if (addSlope)
314 disable[4] = 0;
315 if (addExponential)
316 disable[5] = 0;
317
318 if ((guessFlags & GUESS_SLOPE_GIVEN) && !addSlope)
319 SDDS_Bomb("-guess=slope given but -addSlope not given");
320
321 if ((guessFlags & GUESS_RATE_GIVEN) && !addExponential)
322 SDDS_Bomb("-guess=rate given but -addExponential not given");
323
324 processFilenames("sddssinefit", &input, &output, pipeFlags, 0, NULL);
325
326 if (!xName || !yName)
327 SDDS_Bomb("-columns option must be specified.");
328
329 if (!SDDS_InitializeInput(&InputTable, input) ||
330 SDDS_GetColumnIndex(&InputTable, xName) < 0 ||
331 SDDS_GetColumnIndex(&InputTable, yName) < 0)
332 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
333
334 setupOutputFile(&OutputTable, &xIndex, &yIndex, &fitIndex, &residualIndex, output, fullOutput,
335 &InputTable, xName, yName, columnMajorOrder, addSlope, addExponential);
336
337 fitData = residualData = NULL;
338
339 alo[0] = -(ahi[0] = DBL_MAX);
340 alo[1] = alo[2] = 0;
341 ahi[1] = ahi[2] = DBL_MAX;
342 alo[3] = -(ahi[3] = PIx2);
343 if (addSlope)
344 alo[4] = -(ahi[4] = DBL_MAX);
345 if (addExponential)
346 alo[5] = -(ahi[5] = DBL_MAX);
347
348 firstZero = lastZero = 0;
349 if (verbosity>5) {
350 simplexFlags = SIMPLEX_VERBOSE_LEVEL1;
351 }
352 while ((retval = SDDS_ReadPage(&InputTable)) > 0) {
353 if (!(xData = SDDS_GetColumnInDoubles(&InputTable, xName)) ||
354 !(yData = SDDS_GetColumnInDoubles(&InputTable, yName)))
355 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
356 if ((nData = SDDS_CountRowsOfInterest(&InputTable)) < 4)
357 continue;
358
359 fitData = SDDS_Realloc(fitData, sizeof(*fitData) * nData);
360 residualData = SDDS_Realloc(residualData, sizeof(*residualData) * nData);
361
362 find_min_max(&yMin, &yMax, yData, nData);
363 find_min_max(&xMin, &xMax, xData, nData);
364 zeroes = 0;
365 for (i = 1; i < nData; i++)
366 if (yData[i] * yData[i - 1] <= 0) {
367 i++;
368 if (!zeroes)
369 firstZero = (xData[i] + xData[i - 1]) / 2;
370 else
371 lastZero = (xData[i] + xData[i - 1]) / 2;
372 zeroes++;
373 if (zeroes>5)
374 break;
375 }
376 a[0] = (yMin + yMax) / 2;
377 a[1] = (yMax - yMin) / 2;
378 if (!zeroes)
379 a[2] = 2 / fabs(xMax - xMin);
380 else
381 a[2] = zeroes / (2 * fabs(lastZero - firstZero));
382 a[3] = 0;
383 a[4] = 0;
384 a[5] = 0;
385 if (guessFlags & GUESS_CONSTANT_GIVEN)
386 a[0] = constantGuess;
387 if (guessFlags & GUESS_FACTOR_GIVEN)
388 a[1] = factorGuess;
389 if (guessFlags & GUESS_FREQ_GIVEN)
390 a[2] = freqGuess;
391 if (guessFlags & GUESS_PHASE_GIVEN)
392 a[3] = phaseGuess;
393 if (guessFlags & GUESS_SLOPE_GIVEN)
394 a[4] = slopeGuess;
395 if (guessFlags & GUESS_RATE_GIVEN)
396 a[5] = rateGuess;
397
398 alo[1] = a[1] / 2;
399 if (!(da[0] = a[0] * 0.1))
400 da[0] = 0.01;
401 if (!(da[1] = a[1] * 0.1))
402 da[1] = 0.01;
403 da[2] = a[2] * 0.25;
404 da[3] = 0.01;
405 if (addSlope)
406 da[4] = 0.01;
407 if (addExponential) {
408 if (a[5])
409 da[5] = a[5]*0.01;
410 else
411 da[5] = 0.001;
412 }
413
414 if (lockFreq) {
415 alo[2] = ahi[2] = a[2];
416 da[2] = 0;
417 disable[2] = 1;
418 }
419
420 simplexMin(&result, a, da, alo, ahi, disable, 6, -DBL_MAX, tolerance, fitFunction,
421 (verbosity > 0 ? report : NULL), nEvalMax, nPassMax, 12, 3, 1.0, simplexFlags);
422
423 for (i = result = 0; i < nData; i++)
424 result += sqr(residualData[i]);
425 rmsResidual = sqrt(result / nData);
426 if (verbosity > 1) {
427 fprintf(stderr, "RMS deviation: %.15e\n", rmsResidual);
428 fprintf(stderr, "(RMS deviation)/(largest value): %.15e\n", rmsResidual / MAX(fabs(yMin), fabs(yMax)));
429 }
430 if (verbosity > 0) {
431 if (addSlope) {
432 fprintf(stderr, "Coefficients of fit to the form y = a0 + a1*sin(2*PI*a2*x + a3) + a4*x, a = \n");
433 for (i = 0; i < 5; i++)
434 fprintf(stderr, "%.8e ", a[i]);
435 } else {
436 fprintf(stderr, "Coefficients of fit to the form y = a0 + a1*sin(2*PI*a2*x + a3), a = \n");
437 for (i = 0; i < 4; i++)
438 fprintf(stderr, "%.8e ", a[i]);
439 }
440 fprintf(stderr, "\n");
441 }
442
443 if (!SDDS_StartPage(&OutputTable, nData) ||
444 !SDDS_SetColumn(&OutputTable, SDDS_SET_BY_INDEX, xData, nData, xIndex) ||
445 !SDDS_SetColumn(&OutputTable, SDDS_SET_BY_INDEX, fitData, nData, fitIndex) ||
446 !SDDS_SetParameters(&OutputTable, SDDS_PASS_BY_VALUE | SDDS_SET_BY_NAME,
447 "sinefitConstant", a[0],
448 "sinefitFactor", a[1],
449 "sinefitFrequency", a[2],
450 "sinefitPhase", a[3],
451 "sinefitRmsResidual", rmsResidual,
452 NULL) ||
453 (addSlope &&
454 (!SDDS_SetParameters(&OutputTable, SDDS_PASS_BY_VALUE | SDDS_SET_BY_NAME,
455 "sinefitSlope", a[4], NULL))) ||
456 (addExponential &&
457 (!SDDS_SetParameters(&OutputTable, SDDS_PASS_BY_VALUE | SDDS_SET_BY_NAME,
458 "sinefitRate", a[5], NULL))) ||
459 (fullOutput && (!SDDS_SetColumn(&OutputTable, SDDS_SET_BY_INDEX, yData, nData, yIndex) ||
460 !SDDS_SetColumn(&OutputTable, SDDS_SET_BY_INDEX, residualData, nData, residualIndex))) ||
461 !SDDS_WritePage(&OutputTable))
462 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
463 }
464
465 if (SDDS_Terminate(&InputTable) != 1) {
466 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
467 return EXIT_FAILURE;
468 }
469 if (SDDS_Terminate(&OutputTable) != 1) {
470 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
471 return EXIT_FAILURE;
472 }
473
474 return EXIT_SUCCESS;
475}
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_SetParameters(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
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_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:50
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
Definition SDDS_utils.c:474
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:318
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:380
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:743
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
Definition bomb.c:26
int find_min_max(double *min, double *max, double *list, int64_t n)
Finds the minimum and maximum values in a list of doubles.
Definition findMinMax.c:33
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:357
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:391
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.
long simplexMin(double *yReturn, double *xGuess, double *dxGuess, double *xLowerLimit, double *xUpperLimit, short *disable, long dimensions, double target, double tolerance, double(*func)(double *x, long *invalid), void(*report)(double ymin, double *xmin, long pass, long evals, long dims), long maxEvaluations, long maxPasses, long maxDivisions, double divisorFactor, double passRangeFactor, unsigned long flags)
Top-level convenience function for simplex-based minimization.
Definition simplex.c:502

◆ makeInverseUnits()

char * makeInverseUnits ( char * units)

Definition at line 549 of file sddssinefit.c.

549 {
550 char *inverseUnits;
551
552 if (!units || SDDS_StringIsBlank(units))
553 return NULL;
554 inverseUnits = tmalloc(sizeof(*inverseUnits) * (strlen(units) + 5));
555
556 if (strncmp(units, "1/(", 3) == 0 && units[strlen(units) - 1] == ')') {
557 /* Special case of "1/(<unit>)" */
558 strcpy(inverseUnits, units + 3);
559 inverseUnits[strlen(inverseUnits) - 1] = '\0';
560 } else if (!strchr(units, ' ')) {
561 /* Special case of units string without spaces */
562 sprintf(inverseUnits, "1/%s", units);
563 } else {
564 /* General case */
565 sprintf(inverseUnits, "1/(%s)", units);
566 }
567
568 return inverseUnits;
569}
int32_t SDDS_StringIsBlank(char *s)
Checks if a string is blank (contains only whitespace characters).
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:65

◆ report()

void report ( double res,
double * a,
long pass,
long n_eval,
long n_dimen )

Definition at line 611 of file sddssinefit.c.

611 {
612 long i;
613
614 fprintf(stderr, "Pass %ld, after %ld evaluations: result = %.16e\n", pass, nEval, y);
615 fprintf(stderr, "a = ");
616 for (i = 0; i < 6; i++)
617 fprintf(stderr, "%.8e ", x[i]);
618 fputc('\n', stderr);
619}

◆ setupOutputFile()

void setupOutputFile ( SDDS_DATASET * OutputTable,
int32_t * xIndex,
int32_t * yIndex,
int32_t * fitIndex,
int32_t * residualIndex,
char * output,
long fullOutput,
SDDS_DATASET * InputTable,
char * xName,
char * yName,
short columnMajorOrder,
short addSlope,
short addExponential )

Definition at line 477 of file sddssinefit.c.

479 {
480 char *name, *yUnits, *description, *xUnits, *inverse_xUnits;
481 int32_t typeValue = SDDS_DOUBLE;
482 static char *residualNamePart = "Residual";
483 static char *residualDescriptionPart = "Residual of sinusoidal fit to ";
484
485 if (!SDDS_InitializeOutput(OutputTable, SDDS_BINARY, 0, NULL, "sddssinefit output", output) ||
486 !SDDS_TransferColumnDefinition(OutputTable, InputTable, xName, NULL) ||
487 !SDDS_ChangeColumnInformation(OutputTable, "type", &typeValue, SDDS_BY_NAME, xName) ||
488 (*xIndex = SDDS_GetColumnIndex(OutputTable, xName)) < 0 ||
489 !SDDS_GetColumnInformation(InputTable, "units", &xUnits, SDDS_BY_NAME, xName) ||
490 !SDDS_GetColumnInformation(InputTable, "units", &yUnits, SDDS_BY_NAME, yName)) {
491 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
492 exit(EXIT_FAILURE);
493 }
494 if (columnMajorOrder != -1)
495 OutputTable->layout.data_mode.column_major = columnMajorOrder;
496 else
497 OutputTable->layout.data_mode.column_major = InputTable->layout.data_mode.column_major;
498
499 name = tmalloc(sizeof(*name) * (strlen(yName) + strlen(residualNamePart) + 1));
500 description = tmalloc(sizeof(*description) * (strlen(yName) + strlen(residualDescriptionPart) + 1));
501
502 if (fullOutput) {
503 if (!SDDS_TransferColumnDefinition(OutputTable, InputTable, yName, NULL) ||
504 !SDDS_ChangeColumnInformation(OutputTable, "type", &typeValue, SDDS_BY_NAME, yName) ||
505 (*yIndex = SDDS_GetColumnIndex(OutputTable, yName)) < 0)
506 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
507 sprintf(name, "%s%s", yName, residualNamePart);
508 sprintf(description, "%s%s", yName, residualDescriptionPart);
509 if ((*residualIndex = SDDS_DefineColumn(OutputTable, name, NULL, yUnits, description, NULL, SDDS_DOUBLE, 0)) < 0)
510 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
511 }
512
513 sprintf(name, "%sFit", yName);
514 sprintf(description, "Sinusoidal fit to %s", yName);
515 if ((*fitIndex = SDDS_DefineColumn(OutputTable, name, NULL, yUnits, description, NULL, SDDS_DOUBLE, 0)) < 0)
516 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
517
518 inverse_xUnits = makeInverseUnits(xUnits);
519
520 if (SDDS_DefineParameter(OutputTable, "sinefitConstant", NULL, yUnits, "Constant term from sinusoidal fit",
521 NULL, SDDS_DOUBLE, 0) < 0 ||
522 SDDS_DefineParameter(OutputTable, "sinefitFactor", NULL, yUnits, "Factor from sinusoidal fit",
523 NULL, SDDS_DOUBLE, 0) < 0 ||
524 SDDS_DefineParameter(OutputTable, "sinefitFrequency", NULL, inverse_xUnits, "Frequency from sinusoidal fit",
525 NULL, SDDS_DOUBLE, 0) < 0 ||
526 SDDS_DefineParameter(OutputTable, "sinefitPhase", NULL, xUnits, "Phase from sinusoidal fit",
527 NULL, SDDS_DOUBLE, 0) < 0 ||
528 SDDS_DefineParameter(OutputTable, "sinefitRmsResidual", NULL, yUnits, "RMS residual from sinusoidal fit",
529 NULL, SDDS_DOUBLE, 0) < 0)
530 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
531
532 if (addSlope) {
533 if (SDDS_DefineParameter(OutputTable, "sinefitSlope", NULL, yUnits, "Slope term added to sinusoidal fit",
534 NULL, SDDS_DOUBLE, 0) < 0)
535 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
536 }
537 if (addExponential) {
538 if (SDDS_DefineParameter(OutputTable, "sinefitRate", NULL, inverse_xUnits, "Exponential decay rate for sinusoidal fit",
539 NULL, SDDS_DOUBLE, 0) < 0)
540 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
541 }
542 if (!SDDS_WriteLayout(OutputTable))
543 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
544
545 free(name);
546 free(description);
547}
int32_t SDDS_ChangeColumnInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Modifies a specific field in a column definition within the SDDS dataset.
Definition SDDS_info.c:364
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_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_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_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_TransferColumnDefinition(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Transfers a column definition from a source dataset to a target dataset.