SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sddssinefit.c
Go to the documentation of this file.
1/**
2 * @file sddssinefit.c
3 * @brief Performs a sinusoidal fit on input data.
4 *
5 * @details
6 * This program reads input data from an SDDS (Self Describing Data Sets) file,
7 * fits the data to one of two sinusoidal models:
8 *
9 * @f[
10 * y(n) = a_0 + a_1 \sin(2\pi a_2 x(n) + a_3)
11 * @f]
12 *
13 * or
14 *
15 * @f[
16 * y(n) = a_0 + a_1 \sin(2\pi a_2 x(n) + a_3) + a_4 x(n)
17 * @f]
18 *
19 * Based on user-provided parameters and options, the program performs fitting and outputs
20 * the fitted data along with residuals to an output SDDS file.
21 *
22 * @section Usage
23 * ```
24 * sddssinefit [<inputfile>] [<outputfile>]
25 * [-pipe=<input>[,<output>]]
26 * [-fulloutput]
27 * -columns=<x-name>,<y-name>
28 * [-tolerance=<value>]
29 * [-limits=evaluations=<number>,passes=<number>]
30 * [-verbosity=<integer>]
31 * [-guess=constant=<constant>,factor=<factor>,frequency=<freq>,phase=<phase>,slope=<slope>]
32 * [-lockFrequency]
33 * [-addSlope]
34 * [-majorOrder=row|column]
35 * ```
36 *
37 * @section Options
38 * | Required | Description |
39 * |---------------------------------------|---------------------------------------------------------------------------------------|
40 * | `-columns` | Specifies the x and y data column names. |
41 *
42 * | Optional | Description |
43 * |---------------------------------------|---------------------------------------------------------------------------------------|
44 * | `-pipe` | Use standard input/output for data streams. |
45 * | `-fulloutput` | Includes full output with residuals. |
46 * | `-tolerance` | Sets the tolerance for the fitting algorithm (default: 1e-6). |
47 * | `-limits=evaluations` | Sets maximum number of evaluations and passes (default: 5000 evaluations, 25 passes).|
48 * | `-verbosity` | Sets verbosity level (default: 0). |
49 * | `-guess` | Provides initial guesses for fit parameters. |
50 * | `-lockFrequency` | Locks the frequency parameter during fitting. |
51 * | `-addSlope` | Includes a slope term in the fit. |
52 * | `-majorOrder` | Specifies the major order for data processing. |
53 *
54 * @subsection Incompatibilities
55 * - `-lockFrequency` cannot be used with `-guess=frequency=<freq>`.
56 *
57 * @subsection Requirements
58 * - For `-guess`, at least one of the guess parameters (`constant`, `factor`, `frequency`, `phase`, `slope`) is required.
59 *
60 * @copyright
61 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
62 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
63 *
64 * @license
65 * This file is distributed under the terms of the Software License Agreement
66 * found in the file LICENSE included with this distribution.
67 *
68 * @author
69 * M. Borland, C. Saunders, R. Soliday, L. Emery, H. Shang, N. Kuklev
70 */
71
72#include "mdb.h"
73#include "SDDS.h"
74#include "scan.h"
75
76/* Enumeration for option types */
77enum option_type {
78 SET_TOLERANCE,
79 SET_VERBOSITY,
80 SET_CLUE,
81 SET_GUESS,
82 SET_COLUMNS,
83 SET_FULLOUTPUT,
84 SET_LIMITS,
85 SET_PIPE,
86 SET_MAJOR_ORDER,
87 SET_LOCK_FREQ,
88 SET_ADD_SLOPE,
89 N_OPTIONS
90};
91
92char *option[N_OPTIONS] = {
93 "tolerance",
94 "verbosity",
95 "clue",
96 "guess",
97 "columns",
98 "fulloutput",
99 "limits",
100 "pipe",
101 "majorOrder",
102 "lockFrequency",
103 "addSlope",
104};
105
106static char *USAGE =
107 "sddssinefit [<inputfile>] [<outputfile>] \n"
108 " [-pipe=<input>[,<output>]]\n"
109 " [-fulloutput]\n"
110 " [-columns=<x-name>,<y-name>]\n"
111 " [-tolerance=<value>]\n"
112 " [-limits=evaluations=<number>,passes=<number>]\n"
113 " [-verbosity=<integer>]\n"
114 " [-guess=constant=<constant>,factor=<factor>,frequency=<freq>,phase=<phase>,slope=<slope>]\n"
115 " [-lockFrequency]\n"
116 " [-addSlope]\n"
117 " [-majorOrder=row|column]\n\n"
118 "Description:\n"
119 " Performs a sinusoidal fit of the form:\n"
120 " y = <constant> + <factor>*sin(2*PI*<freq>*x + <phase>)\n"
121 " or\n"
122 " y = <constant> + <factor>*sin(2*PI*<freq>*x + <phase>) + <slope>*x\n\n"
123 "Options:\n"
124 " <inputfile> : Path to the input SDDS file.\n"
125 " <outputfile> : Path to the output SDDS file.\n"
126 " -pipe=<input>,<output> : Use standard input/output for data streams.\n"
127 " -fulloutput : Include full output with residuals.\n"
128 " -columns=<x-name>,<y-name> : Specify the names of the x and y data columns.\n"
129 " -tolerance=<value> : Set the tolerance for the fitting algorithm (default: 1e-6).\n"
130 " -limits=evaluations=<n>,passes=<m> : Set maximum number of evaluations and passes (default: 5000 evaluations, 25 passes).\n"
131 " -verbosity=<integer> : Set verbosity level (default: 0).\n"
132 " -guess=constant=<c>,factor=<f>,frequency=<freq>,phase=<p>,slope=<s> : Provide initial guesses for fit parameters.\n"
133 " -lockFrequency : Lock the frequency parameter during fitting.\n"
134 " -addSlope : Include a slope term in the fit.\n"
135 " -majorOrder=row|column : Specify the major order for data processing.\n\n"
136 "Author:\n"
137 " Michael Borland\n"
138 " (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
139
140static double *xData, *yData;
141static int64_t nData;
142static double yMin, yMax, xMin, xMax;
143static double fit[5];
144
145double fitFunction(double *a, long *invalid);
146double fitFunctionWithSlope(double *a, long *invalid);
147void report(double res, double *a, long pass, long n_eval, long n_dimen);
148void setupOutputFile(SDDS_DATASET *OutputTable, int32_t *xIndex, int32_t *yIndex, int32_t *fitIndex,
149 int32_t *residualIndex, char *output, long fullOutput, SDDS_DATASET *InputTable,
150 char *xName, char *yName, short columnMajorOrder, short addSlope);
151char *makeInverseUnits(char *units);
152
153long verbosity;
154
155#define GUESS_CONSTANT_GIVEN 0x0001
156#define GUESS_FACTOR_GIVEN 0x0002
157#define GUESS_FREQ_GIVEN 0x0004
158#define GUESS_PHASE_GIVEN 0x0008
159#define GUESS_SLOPE_GIVEN 0x0010
160
161int main(int argc, char **argv) {
162 double tolerance, result;
163 int32_t nEvalMax = 5000, nPassMax = 25;
164 double a[5], da[5];
165 double alo[5], ahi[5];
166 long n_dimen = 4;
167 int64_t zeroes;
168 SDDS_DATASET InputTable, OutputTable;
169 SCANNED_ARG *s_arg;
170 long i_arg, fullOutput;
171 int64_t i;
172 char *input, *output, *xName, *yName;
173 int32_t xIndex, yIndex, fitIndex, residualIndex;
174 long retval;
175 double *fitData, *residualData, rmsResidual;
176 unsigned long guessFlags, dummyFlags, pipeFlags;
177 double constantGuess, factorGuess, freqGuess, phaseGuess, slopeGuess;
178 double firstZero, lastZero;
179 unsigned long simplexFlags = 0, majorOrderFlag;
180 short columnMajorOrder = -1;
181 short lockFreq = 0;
182 short addSlope = 0;
183
185 argc = scanargs(&s_arg, argc, argv);
186 if (argc < 2 || argc > (2 + N_OPTIONS))
187 bomb(NULL, USAGE);
188
189 input = output = NULL;
190 tolerance = 1e-6;
191 verbosity = fullOutput = 0;
192 xName = yName = NULL;
193 guessFlags = 0;
194 pipeFlags = 0;
195
196 for (i_arg = 1; i_arg < argc; i_arg++) {
197 if (s_arg[i_arg].arg_type == OPTION) {
198 switch (match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
199 case SET_MAJOR_ORDER:
200 majorOrderFlag = 0;
201 s_arg[i_arg].n_items--;
202 if (s_arg[i_arg].n_items > 0 &&
203 (!scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
204 "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
205 "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
206 SDDS_Bomb("invalid -majorOrder syntax/values");
207 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
208 columnMajorOrder = 1;
209 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
210 columnMajorOrder = 0;
211 break;
212 case SET_TOLERANCE:
213 if (s_arg[i_arg].n_items != 2 || sscanf(s_arg[i_arg].list[1], "%lf", &tolerance) != 1)
214 SDDS_Bomb("incorrect -tolerance syntax");
215 break;
216 case SET_VERBOSITY:
217 if (s_arg[i_arg].n_items != 2 || sscanf(s_arg[i_arg].list[1], "%ld", &verbosity) != 1)
218 SDDS_Bomb("incorrect -verbosity syntax");
219 break;
220 case SET_GUESS:
221 if (s_arg[i_arg].n_items < 2)
222 SDDS_Bomb("incorrect -guess syntax");
223 s_arg[i_arg].n_items -= 1;
224 if (!scanItemList(&guessFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
225 "constant", SDDS_DOUBLE, &constantGuess, 1, GUESS_CONSTANT_GIVEN,
226 "factor", SDDS_DOUBLE, &factorGuess, 1, GUESS_FACTOR_GIVEN,
227 "frequency", SDDS_DOUBLE, &freqGuess, 1, GUESS_FREQ_GIVEN,
228 "phase", SDDS_DOUBLE, &phaseGuess, 1, GUESS_PHASE_GIVEN,
229 "slope", SDDS_DOUBLE, &slopeGuess, 1, GUESS_SLOPE_GIVEN, NULL))
230 SDDS_Bomb("invalid -guess syntax");
231 break;
232 case SET_COLUMNS:
233 if (s_arg[i_arg].n_items != 3)
234 SDDS_Bomb("invalid -columns syntax");
235 xName = s_arg[i_arg].list[1];
236 yName = s_arg[i_arg].list[2];
237 break;
238 case SET_FULLOUTPUT:
239 fullOutput = 1;
240 break;
241 case SET_LOCK_FREQ:
242 lockFreq = 1;
243 break;
244 case SET_ADD_SLOPE:
245 addSlope = 1;
246 n_dimen = 5;
247 break;
248 case SET_LIMITS:
249 if (s_arg[i_arg].n_items < 2)
250 SDDS_Bomb("incorrect -limits syntax");
251 s_arg[i_arg].n_items -= 1;
252 if (!scanItemList(&dummyFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
253 "evaluations", SDDS_LONG, &nEvalMax, 1, 0,
254 "passes", SDDS_LONG, &nPassMax, 1, 0, NULL) ||
255 nEvalMax <= 0 || nPassMax <= 0)
256 SDDS_Bomb("invalid -limits syntax");
257 break;
258 case SET_PIPE:
259 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
260 SDDS_Bomb("invalid -pipe syntax");
261 break;
262 default:
263 fprintf(stderr, "Error: Unknown or ambiguous option: %s\n", s_arg[i_arg].list[0]);
264 exit(EXIT_FAILURE);
265 break;
266 }
267 } else {
268 if (input == NULL)
269 input = s_arg[i_arg].list[0];
270 else if (output == NULL)
271 output = s_arg[i_arg].list[0];
272 else
273 SDDS_Bomb("Too many filenames provided.");
274 }
275 }
276
277 processFilenames("sddssinefit", &input, &output, pipeFlags, 0, NULL);
278
279 if (!xName || !yName)
280 SDDS_Bomb("-columns option must be specified.");
281
282 if (!SDDS_InitializeInput(&InputTable, input) ||
283 SDDS_GetColumnIndex(&InputTable, xName) < 0 ||
284 SDDS_GetColumnIndex(&InputTable, yName) < 0)
285 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
286
287 setupOutputFile(&OutputTable, &xIndex, &yIndex, &fitIndex, &residualIndex, output, fullOutput,
288 &InputTable, xName, yName, columnMajorOrder, addSlope);
289
290 fitData = residualData = NULL;
291
292 alo[0] = -(ahi[0] = DBL_MAX);
293 alo[1] = alo[2] = 0;
294 ahi[1] = ahi[2] = DBL_MAX;
295 alo[3] = -(ahi[3] = PIx2);
296 if (addSlope) {
297 alo[4] = -(ahi[4] = DBL_MAX);
298 }
299 firstZero = lastZero = 0;
300 while ((retval = SDDS_ReadPage(&InputTable)) > 0) {
301 if (!(xData = SDDS_GetColumnInDoubles(&InputTable, xName)) ||
302 !(yData = SDDS_GetColumnInDoubles(&InputTable, yName)))
303 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
304 if ((nData = SDDS_CountRowsOfInterest(&InputTable)) < 4)
305 continue;
306
307 find_min_max(&yMin, &yMax, yData, nData);
308 find_min_max(&xMin, &xMax, xData, nData);
309 zeroes = 0;
310 for (i = 1; i < nData; i++)
311 if (yData[i] * yData[i - 1] <= 0) {
312 i++;
313 if (!zeroes)
314 firstZero = (xData[i] + xData[i - 1]) / 2;
315 else
316 lastZero = (xData[i] + xData[i - 1]) / 2;
317 zeroes++;
318 }
319 a[0] = (yMin + yMax) / 2;
320 a[1] = (yMax - yMin) / 2;
321 if (!zeroes)
322 a[2] = 2 / fabs(xMax - xMin);
323 else
324 a[2] = zeroes / (2 * fabs(lastZero - firstZero));
325 a[3] = 0;
326 if (addSlope) {
327 a[4] = 0;
328 }
329 if (guessFlags & GUESS_CONSTANT_GIVEN)
330 a[0] = constantGuess;
331 if (guessFlags & GUESS_FACTOR_GIVEN)
332 a[1] = factorGuess;
333 if (guessFlags & GUESS_FREQ_GIVEN)
334 a[2] = freqGuess;
335 if (guessFlags & GUESS_PHASE_GIVEN)
336 a[3] = phaseGuess;
337 if (guessFlags & GUESS_SLOPE_GIVEN)
338 a[4] = slopeGuess;
339
340 alo[1] = a[1] / 2;
341 if (!(da[0] = a[0] * 0.1))
342 da[0] = 0.01;
343 if (!(da[1] = a[1] * 0.1))
344 da[1] = 0.01;
345 da[2] = a[2] * 0.25;
346 da[3] = 0.01;
347 if (addSlope) {
348 da[4] = 0.01;
349 }
350
351 if (lockFreq) {
352 alo[2] = ahi[2] = a[2];
353 da[2] = 0;
354 }
355
356 if (addSlope) {
357 simplexMin(&result, a, da, alo, ahi, NULL, n_dimen, -DBL_MAX, tolerance, fitFunctionWithSlope,
358 (verbosity > 0 ? report : NULL), nEvalMax, nPassMax, 12, 3, 1.0, simplexFlags);
359 } else {
360 simplexMin(&result, a, da, alo, ahi, NULL, n_dimen, -DBL_MAX, tolerance, fitFunction,
361 (verbosity > 0 ? report : NULL), nEvalMax, nPassMax, 12, 3, 1.0, simplexFlags);
362 }
363 fitData = trealloc(fitData, sizeof(*fitData) * nData);
364 residualData = trealloc(residualData, sizeof(*residualData) * nData);
365 if (addSlope) {
366 for (i = result = 0; i < nData; i++) {
367 fitData[i] = a[0] + a[1] * sin(PIx2 * a[2] * xData[i] + a[3]) + a[4] * xData[i];
368 residualData[i] = yData[i] - fitData[i];
369 result += sqr(residualData[i]);
370 }
371 } else {
372 for (i = result = 0; i < nData; i++) {
373 fitData[i] = a[0] + a[1] * sin(PIx2 * a[2] * xData[i] + a[3]);
374 residualData[i] = yData[i] - fitData[i];
375 result += sqr(residualData[i]);
376 }
377 }
378 rmsResidual = sqrt(result / nData);
379 if (verbosity > 1) {
380 fprintf(stderr, "RMS deviation: %.15e\n", rmsResidual);
381 fprintf(stderr, "(RMS deviation)/(largest value): %.15e\n", rmsResidual / MAX(fabs(yMin), fabs(yMax)));
382 }
383 if (verbosity > 0) {
384 if (addSlope) {
385 fprintf(stderr, "Coefficients of fit to the form y = a0 + a1*sin(2*PI*a2*x + a3) + a4*x, a = \n");
386 for (i = 0; i < 5; i++)
387 fprintf(stderr, "%.8e ", a[i]);
388 } else {
389 fprintf(stderr, "Coefficients of fit to the form y = a0 + a1*sin(2*PI*a2*x + a3), a = \n");
390 for (i = 0; i < 4; i++)
391 fprintf(stderr, "%.8e ", a[i]);
392 }
393 fprintf(stderr, "\n");
394 }
395
396 if (!SDDS_StartPage(&OutputTable, nData) ||
397 !SDDS_SetColumn(&OutputTable, SDDS_SET_BY_INDEX, xData, nData, xIndex) ||
398 !SDDS_SetColumn(&OutputTable, SDDS_SET_BY_INDEX, fitData, nData, fitIndex) ||
399 !SDDS_SetParameters(&OutputTable, SDDS_PASS_BY_VALUE | SDDS_SET_BY_NAME,
400 "sinefitConstant", a[0],
401 "sinefitFactor", a[1],
402 "sinefitFrequency", a[2],
403 "sinefitPhase", a[3],
404 "sinefitRmsResidual", rmsResidual,
405 NULL) ||
406 (addSlope &&
407 (!SDDS_SetParameters(&OutputTable, SDDS_PASS_BY_VALUE | SDDS_SET_BY_NAME,
408 "sinefitSlope", a[4], NULL))) ||
409 (fullOutput && (!SDDS_SetColumn(&OutputTable, SDDS_SET_BY_INDEX, yData, nData, yIndex) ||
410 !SDDS_SetColumn(&OutputTable, SDDS_SET_BY_INDEX, residualData, nData, residualIndex))) ||
411 !SDDS_WritePage(&OutputTable))
412 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
413 }
414
415 if (SDDS_Terminate(&InputTable) != 1) {
416 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
417 return EXIT_FAILURE;
418 }
419 if (SDDS_Terminate(&OutputTable) != 1) {
420 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
421 return EXIT_FAILURE;
422 }
423
424 return EXIT_SUCCESS;
425}
426
427void setupOutputFile(SDDS_DATASET *OutputTable, int32_t *xIndex, int32_t *yIndex, int32_t *fitIndex,
428 int32_t *residualIndex, char *output, long fullOutput, SDDS_DATASET *InputTable,
429 char *xName, char *yName, short columnMajorOrder, short addSlope) {
430 char *name, *yUnits, *description, *xUnits, *inverse_xUnits;
431 int32_t typeValue = SDDS_DOUBLE;
432 static char *residualNamePart = "Residual";
433 static char *residualDescriptionPart = "Residual of sinusoidal fit to ";
434
435 if (!SDDS_InitializeOutput(OutputTable, SDDS_BINARY, 0, NULL, "sddssinefit output", output) ||
436 !SDDS_TransferColumnDefinition(OutputTable, InputTable, xName, NULL) ||
437 !SDDS_ChangeColumnInformation(OutputTable, "type", &typeValue, SDDS_BY_NAME, xName) ||
438 (*xIndex = SDDS_GetColumnIndex(OutputTable, xName)) < 0 ||
439 !SDDS_GetColumnInformation(InputTable, "units", &xUnits, SDDS_BY_NAME, xName) ||
440 !SDDS_GetColumnInformation(InputTable, "units", &yUnits, SDDS_BY_NAME, yName)) {
441 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
442 exit(EXIT_FAILURE);
443 }
444 if (columnMajorOrder != -1)
445 OutputTable->layout.data_mode.column_major = columnMajorOrder;
446 else
447 OutputTable->layout.data_mode.column_major = InputTable->layout.data_mode.column_major;
448
449 name = tmalloc(sizeof(*name) * (strlen(yName) + strlen(residualNamePart) + 1));
450 description = tmalloc(sizeof(*description) * (strlen(yName) + strlen(residualDescriptionPart) + 1));
451
452 if (fullOutput) {
453 if (!SDDS_TransferColumnDefinition(OutputTable, InputTable, yName, NULL) ||
454 !SDDS_ChangeColumnInformation(OutputTable, "type", &typeValue, SDDS_BY_NAME, yName) ||
455 (*yIndex = SDDS_GetColumnIndex(OutputTable, yName)) < 0)
456 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
457 sprintf(name, "%s%s", yName, residualNamePart);
458 sprintf(description, "%s%s", yName, residualDescriptionPart);
459 if ((*residualIndex = SDDS_DefineColumn(OutputTable, name, NULL, yUnits, description, NULL, SDDS_DOUBLE, 0)) < 0)
460 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
461 }
462
463 sprintf(name, "%sFit", yName);
464 sprintf(description, "Sinusoidal fit to %s", yName);
465 if ((*fitIndex = SDDS_DefineColumn(OutputTable, name, NULL, yUnits, description, NULL, SDDS_DOUBLE, 0)) < 0)
466 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
467
468 inverse_xUnits = makeInverseUnits(xUnits);
469
470 if (SDDS_DefineParameter(OutputTable, "sinefitConstant", NULL, yUnits, "Constant term from sinusoidal fit",
471 NULL, SDDS_DOUBLE, 0) < 0 ||
472 SDDS_DefineParameter(OutputTable, "sinefitFactor", NULL, yUnits, "Factor from sinusoidal fit",
473 NULL, SDDS_DOUBLE, 0) < 0 ||
474 SDDS_DefineParameter(OutputTable, "sinefitFrequency", NULL, inverse_xUnits, "Frequency from sinusoidal fit",
475 NULL, SDDS_DOUBLE, 0) < 0 ||
476 SDDS_DefineParameter(OutputTable, "sinefitPhase", NULL, xUnits, "Phase from sinusoidal fit",
477 NULL, SDDS_DOUBLE, 0) < 0 ||
478 SDDS_DefineParameter(OutputTable, "sinefitRmsResidual", NULL, yUnits, "RMS residual from sinusoidal fit",
479 NULL, SDDS_DOUBLE, 0) < 0)
480 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
481
482 if (addSlope) {
483 if (SDDS_DefineParameter(OutputTable, "sinefitSlope", NULL, yUnits, "Slope term added to sinusoidal fit",
484 NULL, SDDS_DOUBLE, 0) < 0)
485 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
486 }
487 if (!SDDS_WriteLayout(OutputTable))
488 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
489
490 free(name);
491 free(description);
492}
493
494char *makeInverseUnits(char *units) {
495 char *inverseUnits;
496
497 if (!units || SDDS_StringIsBlank(units))
498 return NULL;
499 inverseUnits = tmalloc(sizeof(*inverseUnits) * (strlen(units) + 5));
500
501 if (strncmp(units, "1/(", 3) == 0 && units[strlen(units) - 1] == ')') {
502 /* Special case of "1/(<unit>)" */
503 strcpy(inverseUnits, units + 3);
504 inverseUnits[strlen(inverseUnits) - 1] = '\0';
505 } else if (!strchr(units, ' ')) {
506 /* Special case of units string without spaces */
507 sprintf(inverseUnits, "1/%s", units);
508 } else {
509 /* General case */
510 sprintf(inverseUnits, "1/(%s)", units);
511 }
512
513 return inverseUnits;
514}
515
516double fitFunction(double *a, long *invalid) {
517 int64_t i;
518 double chi;
519 static double min_chi;
520
521 min_chi = DBL_MAX;
522
523 *invalid = 0;
524 for (i = chi = 0; i < nData; i++)
525 chi += sqr(yData[i] - (a[0] + a[1] * sin(PIx2 * a[2] * xData[i] + a[3])));
526 if (isnan(chi) || isinf(chi))
527 *invalid = 1;
528 if (verbosity > 3)
529 fprintf(stderr, "Trial: a = %e, %e, %e, %e --> chi = %e, invalid = %ld\n", a[0], a[1], a[2], a[3], chi, *invalid);
530 if (min_chi > chi) {
531 min_chi = chi;
532 fit[0] = a[0];
533 fit[1] = a[1];
534 fit[2] = a[2];
535 fit[3] = a[3];
536 if (verbosity > 2)
537 fprintf(stderr, "New best chi = %e: a = %e, %e, %e, %e\n", chi, fit[0], fit[1], fit[2], fit[3]);
538 }
539 return chi;
540}
541
542double fitFunctionWithSlope(double *a, long *invalid) {
543 int64_t i;
544 double chi;
545 static double min_chi;
546
547 min_chi = DBL_MAX;
548
549 *invalid = 0;
550 for (i = chi = 0; i < nData; i++)
551 chi += sqr(yData[i] - (a[0] + a[1] * sin(PIx2 * a[2] * xData[i] + a[3]) + a[4] * xData[i]));
552 if (isnan(chi) || isinf(chi))
553 *invalid = 1;
554 if (verbosity > 3)
555 fprintf(stderr, "Trial: a = %e, %e, %e, %e, %e --> chi = %e, invalid = %ld\n",
556 a[0], a[1], a[2], a[3], a[4], chi, *invalid);
557 if (min_chi > chi) {
558 min_chi = chi;
559 fit[0] = a[0];
560 fit[1] = a[1];
561 fit[2] = a[2];
562 fit[3] = a[3];
563 fit[4] = a[4];
564 if (verbosity > 2)
565 fprintf(stderr, "New best chi = %e: a = %e, %e, %e, %e, %e\n",
566 chi, fit[0], fit[1], fit[2], fit[3], fit[4]);
567 }
568 return chi;
569}
570
571void report(double y, double *x, long pass, long nEval, long n_dimen) {
572 long i;
573
574 fprintf(stderr, "Pass %ld, after %ld evaluations: result = %.16e\n", pass, nEval, y);
575 fprintf(stderr, "a = ");
576 for (i = 0; i < n_dimen; i++)
577 fprintf(stderr, "%.8e ", x[i]);
578 fputc('\n', stderr);
579}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
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_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_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *SDDS_dataset)
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_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.
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:432
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
int32_t SDDS_StringIsBlank(char *s)
Checks if a string is blank (contains only whitespace characters).
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
#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 * trealloc(void *old_ptr, uint64_t size_of_block)
Reallocates a memory block to a new size.
Definition array.c:181
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:59
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:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
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:472