SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sddsgenericfit.c File Reference

Detailed Description

Performs fitting using a generic form supplied by the user.

The sddsgenericfit program uses the Simplex optimization method to fit user-defined equations to a dataset. The equation is provided in Reverse Polish Notation (RPN) or optionally algebraic form. The program allows detailed configuration of the optimization process and outputs results in SDDS format.

Usage

sddsgenericfit [<inputfile>] [<outputfile>]
[-pipe=[input][,output]]
-equation=<rpnString>[,algebraic]
[-expression=<string>[,<columnName>]]
[-expression=...]
[-target=<value>]
[-tolerance=<value>]
[-simplex=[restarts=<nRestarts>][,cycles=<nCycles>,][evaluations=<nEvals>][,no1DScans]]
-variable=name=<name>,lowerLimit=<value|parameter-name>,upperLimit=<value|parameter-name>,stepsize=<value|parameter-name>,startingValue=<value|parameter-name>[,units=<string>][,heat=<value|parameter-name>]
[-variable=...]
[-verbosity=<integer>]
[-startFromPrevious]
[-majorOrder=row|column]
[-copy=<list of column names>]
[-ycolumn=<ycolumn_name>[,ySigma=<sy-name>]]
[-logFile=<filename>[,<flushInterval(500)>]]

Options

Required Option Description
-equation The equation to fit, in RPN or optionally algebraic format.
-variable Specifies fitting variables with limits, step size, and initial values.
-ycolumn The dependent variable column name, optionally with uncertainty column.
Optional Options Description
-pipe Use pipes for input and/or output.
-expression RPN expression(s) for pre-processing or data preparation.
-target Target RMS residual for an acceptable fit.
-tolerance Minimum significant change in RMS residual to continue optimization.
-simplex Parameters for simplex optimization.
-verbosity Sets verbosity of output during optimization.
-startFromPrevious Initializes variables from the previous fit.
-majorOrder Specifies row-major or column-major output order.
-copy Copies specific columns from the input file to the output file.
-logFile Logs intermediate fitting results.

Incompatibilities

  • The following options cannot be used together:
    • -simplex=no1DScans with simplex cycles or evaluations specified.
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Authors
M. Borland, L. Emery, R. Soliday, H. Shang

Definition in file sddsgenericfit.c.

#include "mdb.h"
#include "SDDS.h"
#include "SDDSaps.h"
#include "scan.h"
#include "rpn.h"
#include <time.h>
#include <signal.h>

Go to the source code of this file.

Functions

void report (double res, double *a, long pass, long n_eval, long n_dimen)
 
void setupOutputFile (SDDS_DATASET *OutputTable, long *fitIndex, long *residualIndex, char *output, SDDS_DATASET *InputTable, char *xName, char *yName, char *syName, char **variableName, char **variableUnits, long variables, char **colMatch, int32_t colMatches, char **expression, char **expressionColumn, long nExpressions, SDDS_DATASET *logData, char *logFile, short columnMajorOrder)
 
double fitFunction (double *a, long *invalid)
 
void optimizationInterruptHandler (int signal)
 
int main (int argc, char **argv)
 

Function Documentation

◆ fitFunction()

double fitFunction ( double * a,
long * invalid )

Definition at line 689 of file sddsgenericfit.c.

689 {
690 double sum, tmp;
691 int64_t i;
692 long j;
693
694 rpn_clear();
695 *invalid = 0;
696
697 for (i = 0; i < nVariables; i++)
698 rpn_store(a[i], NULL, variableMem[i]);
699
700 if (verbosity > 10)
701 fprintf(stderr, "Running fit function:\n");
702 if (!syData) {
703 for (i = sum = 0; i < nData; i++) {
704 if (!SDDS_StoreRowInRpnMemories(&InputTable, i))
705 SDDS_Bomb("Problem storing data in RPN memories");
706 rpn_clear();
707 for (j = 0; j < nExpressions; j++) {
708 expressionValue[j][i] = rpn(expression[j]);
709 if (verbosity > 10)
710 fprintf(stderr, "Expression %ld: %le\n", j, expressionValue[j][i]);
711 }
712 yFit[i] = rpn(equation);
713 if (rpn_check_error()) {
714 *invalid = 1;
715 return 0;
716 }
717 yResidual[i] = tmp = (yFit[i] - yData[i]);
718 if (verbosity > 10) {
719 if (xData)
720 fprintf(stderr, "i=%" PRId64 " x=%le y=%le fit=%le\n", i, xData[i], yData[i], yFit[i]);
721 else
722 fprintf(stderr, "i=%" PRId64 " y=%le fit=%le\n", i, yData[i], yFit[i]);
723 }
724 sum += sqr(tmp);
725 }
726 } else {
727 for (i = sum = 0; i < nData; i++) {
728 if (!SDDS_StoreRowInRpnMemories(&InputTable, i))
729 SDDS_Bomb("Problem storing data in RPN memories");
730 rpn_clear();
731 for (j = 0; j < nExpressions; j++)
732 expressionValue[j][i] = rpn(expression[j]);
733 yFit[i] = rpn(equation);
734 if (rpn_check_error()) {
735 *invalid = 1;
736 return 0;
737 }
738 yResidual[i] = tmp = (yFit[i] - yData[i]);
739 sum += sqr(tmp / syData[i]);
740 }
741 }
742 if (logFile) {
743 if (!step && !SDDS_StartPage(&logData, maxLogRows))
744 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
745 step++;
746 if (step && (step % maxLogRows) == 0) {
747 if (!SDDS_UpdatePage(&logData, FLUSH_TABLE))
748 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
749 }
750 if (!SDDS_SetRowValues(&logData, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, step - 1, "Step", step, "Chi", sum / nData, NULL))
751 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
752 for (i = 0; i < nVariables; i++) {
753 if (!SDDS_SetRowValues(&logData, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE, step - 1, variableName[i], a[i], NULL))
754 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
755 }
756 }
757 return (sum / nData);
758}
int32_t SDDS_SetRowValues(SDDS_DATASET *SDDS_dataset, int32_t mode, int64_t row,...)
int32_t SDDS_StartPage(SDDS_DATASET *SDDS_dataset, int64_t expected_n_rows)
int32_t SDDS_UpdatePage(SDDS_DATASET *SDDS_dataset, uint32_t mode)
Updates the current page of 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_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342

◆ main()

int main ( int argc,
char ** argv )

Definition at line 209 of file sddsgenericfit.c.

209 {
210 int64_t i;
211 SDDS_DATASET OutputTable;
212 SCANNED_ARG *s_arg;
213 long i_arg, ii;
214 char *input, *output, *xName, *yName, *syName, **colMatch;
215 long fitIndex, residualIndex, retval;
216 int32_t colMatches;
217 double rmsResidual, chiSqr, sigLevel;
218 unsigned long pipeFlags, dummyFlags, majorOrderFlag;
219 int32_t nEvalMax = 5000, nPassMax = 10, nRestartMax = 10;
220 long nEval, iRestart;
221 double tolerance, target;
222 char **variableUnits;
223 double *lowerLimit, *upperLimit, *stepSize, *startingValue, *paramValue, *paramDelta = NULL, *paramDelta0 = NULL;
224 char **startingPar = NULL, **lowerLimitPar = NULL, **upperLimitPar = NULL, **heatPar = NULL, **stepPar = NULL;
225 double *heat, *bestParamValue, bestResult = 0;
226 long iVariable, startFromPrevious = 0;
227 double result, lastResult = 0;
228 char pfix[IFPF_BUF_SIZE];
229 unsigned long simplexFlags = 0;
230 char *ptr;
231 short columnMajorOrder = -1;
232
233 signal(SIGINT, optimizationInterruptHandler);
234
236 argc = scanargs(&s_arg, argc, argv);
237 colMatches = 0;
238 colMatch = NULL;
239 if (argc <= 1) {
240 fprintf(stderr, "%s", USAGE);
241 exit(EXIT_FAILURE);
242 }
243 logFile = NULL;
244 input = output = equation = NULL;
245 variableName = variableUnits = NULL;
246 lowerLimit = upperLimit = stepSize = startingValue = heat = bestParamValue = NULL;
247 nVariables = 0;
248 pipeFlags = 0;
249 verbosity = startFromPrevious = 0;
250 xName = yName = syName = NULL;
251 tolerance = target = 1e-14;
252
253 for (i_arg = 1; i_arg < argc; i_arg++) {
254 if (s_arg[i_arg].arg_type == OPTION) {
255 switch (match_string(s_arg[i_arg].list[0], option, N_OPTIONS, 0)) {
256 case SET_MAJOR_ORDER:
257 majorOrderFlag = 0;
258 s_arg[i_arg].n_items--;
259 if (s_arg[i_arg].n_items > 0 && (!scanItemList(&majorOrderFlag, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0, "row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER, "column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
260 SDDS_Bomb("Invalid -majorOrder syntax/values");
261 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
262 columnMajorOrder = 1;
263 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
264 columnMajorOrder = 0;
265 break;
266 case SET_TOLERANCE:
267 if (s_arg[i_arg].n_items != 2 || sscanf(s_arg[i_arg].list[1], "%lf", &tolerance) != 1 || tolerance <= 0)
268 SDDS_Bomb("Incorrect -tolerance syntax");
269 break;
270 case SET_TARGET:
271 if (s_arg[i_arg].n_items != 2 || sscanf(s_arg[i_arg].list[1], "%lf", &target) != 1 || target <= 0)
272 SDDS_Bomb("Incorrect -target syntax");
273 break;
274 case SET_VERBOSITY:
275 if (s_arg[i_arg].n_items != 2 || sscanf(s_arg[i_arg].list[1], "%ld", &verbosity) != 1)
276 SDDS_Bomb("Incorrect -verbosity syntax");
277 break;
278 case SET_COLUMNS:
279 if (s_arg[i_arg].n_items != 3 && s_arg[i_arg].n_items != 4)
280 SDDS_Bomb("Invalid -columns syntax");
281 xName = s_arg[i_arg].list[1];
282 yName = s_arg[i_arg].list[2];
283 s_arg[i_arg].n_items -= 3;
284 if (!scanItemList(&dummyFlags, s_arg[i_arg].list + 3, &s_arg[i_arg].n_items, 0, "ysigma", SDDS_STRING, &syName, 1, 0, NULL))
285 SDDS_Bomb("Invalid -columns syntax");
286 break;
287 case SET_YCOLUMN:
288 if (s_arg[i_arg].n_items != 2 && s_arg[i_arg].n_items != 3)
289 SDDS_Bomb("Invalid -ycolumn syntax");
290 yName = s_arg[i_arg].list[1];
291 s_arg[i_arg].n_items -= 2;
292 if (!scanItemList(&dummyFlags, s_arg[i_arg].list + 2, &s_arg[i_arg].n_items, 0, "ysigma", SDDS_STRING, &syName, 1, 0, NULL))
293 SDDS_Bomb("Invalid -ycolumn syntax");
294 break;
295 case SET_COPYCOLUMNS:
296 if (s_arg[i_arg].n_items < 2)
297 SDDS_Bomb("Invalid -copycolumns syntax provided.");
298 colMatch = tmalloc(sizeof(*colMatch) * (colMatches = s_arg[i_arg].n_items - 1));
299 for (i = 0; i < colMatches; i++)
300 colMatch[i] = s_arg[i_arg].list[i + 1];
301 break;
302 case SET_PIPE:
303 if (!processPipeOption(s_arg[i_arg].list + 1, s_arg[i_arg].n_items - 1, &pipeFlags))
304 SDDS_Bomb("Invalid -pipe syntax");
305 break;
306 case SET_LOGFILE:
307 if (s_arg[i_arg].n_items != 2 && s_arg[i_arg].n_items != 3)
308 SDDS_Bomb("Invalid -logFile syntax");
309 logFile = s_arg[i_arg].list[1];
310 if (s_arg[i_arg].n_items == 3 && (sscanf(s_arg[i_arg].list[2], "%" SCNd32, &maxLogRows) != 1 || maxLogRows <= 0))
311 SDDS_Bomb("Invalid -logFile syntax");
312 break;
313 case SET_VARIABLE:
314 if (!(variableName = SDDS_Realloc(variableName, sizeof(*variableName) * (nVariables + 1))) ||
315 !(lowerLimit = SDDS_Realloc(lowerLimit, sizeof(*lowerLimit) * (nVariables + 1))) ||
316 !(upperLimit = SDDS_Realloc(upperLimit, sizeof(*upperLimit) * (nVariables + 1))) ||
317 !(stepSize = SDDS_Realloc(stepSize, sizeof(*stepSize) * (nVariables + 1))) ||
318 !(heat = SDDS_Realloc(heat, sizeof(*heat) * (nVariables + 1))) ||
319 !(bestParamValue = SDDS_Realloc(bestParamValue, sizeof(*bestParamValue) * (nVariables + 1))) ||
320 !(startingValue = SDDS_Realloc(startingValue, sizeof(*startingValue) * (nVariables + 1))) ||
321 !(startingPar = SDDS_Realloc(startingPar, sizeof(*startingPar) * (nVariables + 1))) ||
322 !(lowerLimitPar = SDDS_Realloc(lowerLimitPar, sizeof(*lowerLimitPar) * (nVariables + 1))) ||
323 !(upperLimitPar = SDDS_Realloc(upperLimitPar, sizeof(*upperLimitPar) * (nVariables + 1))) ||
324 !(heatPar = SDDS_Realloc(heatPar, sizeof(*heatPar) * (nVariables + 1))) ||
325 !(stepPar = SDDS_Realloc(stepPar, sizeof(*stepPar) * (nVariables + 1))) ||
326 !(variableUnits = SDDS_Realloc(variableUnits, sizeof(*variableUnits) * (nVariables + 1))))
327 SDDS_Bomb("Memory allocation failure");
328 variableUnits[nVariables] = NULL;
329 heat[nVariables] = 0;
330 startingPar[nVariables] = heatPar[nVariables] = lowerLimitPar[nVariables] = upperLimitPar[nVariables] = stepPar[nVariables] = NULL;
331 if ((s_arg[i_arg].n_items -= 1) < 5 ||
332 !scanItemList(&dummyFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
333 "name", SDDS_STRING, variableName + nVariables, 1, VARNAME_GIVEN,
334 "lowerlimit", SDDS_STRING, lowerLimitPar + nVariables, 1, LOWER_GIVEN,
335 "upperlimit", SDDS_STRING, upperLimitPar + nVariables, 1, UPPER_GIVEN,
336 "stepsize", SDDS_STRING, &(stepPar[nVariables]), 1, STEP_GIVEN,
337 "startingvalue", SDDS_STRING, startingPar + nVariables, 1, START_GIVEN,
338 "heat", SDDS_STRING, heatPar + nVariables, 1, 0,
339 "units", SDDS_STRING, variableUnits + nVariables, 1, VARUNITS_GIVEN, NULL))
340 SDDS_Bomb("Invalid -variable syntax or values");
341 if (startingPar[nVariables] && sscanf(startingPar[nVariables], "%lf", startingValue + nVariables) == 1) {
342 free(startingPar[nVariables]);
343 startingPar[nVariables] = NULL;
344 }
345 if (lowerLimitPar[nVariables] && sscanf(lowerLimitPar[nVariables], "%lf", lowerLimit + nVariables) == 1) {
346 free(lowerLimitPar[nVariables]);
347 lowerLimitPar[nVariables] = NULL;
348 }
349 if (upperLimitPar[nVariables] && sscanf(upperLimitPar[nVariables], "%lf", upperLimit + nVariables) == 1) {
350 free(upperLimitPar[nVariables]);
351 upperLimitPar[nVariables] = NULL;
352 }
353 if (heatPar[nVariables] && sscanf(heatPar[nVariables], "%lf", heat + nVariables) == 1) {
354 free(heatPar[nVariables]);
355 heatPar[nVariables] = NULL;
356 }
357 if (stepPar[nVariables] && sscanf(stepPar[nVariables], "%lf", stepSize + nVariables) == 1) {
358 free(stepPar[nVariables]);
359 stepPar[nVariables] = NULL;
360 }
361 if ((dummyFlags & (VARNAME_GIVEN | LOWER_GIVEN | UPPER_GIVEN | STEP_GIVEN | START_GIVEN)) != (VARNAME_GIVEN | LOWER_GIVEN | UPPER_GIVEN | STEP_GIVEN | START_GIVEN))
362 SDDS_Bomb("Insufficient information given for -variable");
363 if (!strlen(variableName[nVariables]))
364 SDDS_Bomb("Invalid blank variable name");
365 if (!lowerLimitPar[nVariables] && !upperLimitPar[nVariables] && lowerLimit[nVariables] >= upperLimit[nVariables])
366 SDDS_Bomb("Invalid limits value for variable");
367
368 if (!lowerLimitPar[nVariables] && !upperLimitPar[nVariables] && !startingPar[nVariables] &&
369 (startingValue[nVariables] <= lowerLimit[nVariables] || startingValue[nVariables] >= upperLimit[nVariables]))
370 SDDS_Bomb("Invalid limits or starting value for variable");
371 if (!stepPar[nVariables] && stepSize[nVariables] <= 0)
372 SDDS_Bomb("Invalid step size for variable");
373 nVariables++;
374 break;
375 case SET_SIMPLEX:
376 s_arg[i_arg].n_items -= 1;
377 if (!scanItemList(&simplexFlags, s_arg[i_arg].list + 1, &s_arg[i_arg].n_items, 0,
378 "restarts", SDDS_LONG, &nRestartMax, 1, 0,
379 "cycles", SDDS_LONG, &nPassMax, 1, 0,
380 "evaluations", SDDS_LONG, &nEvalMax, 1, 0,
381 "no1dscans", -1, NULL, 0, SIMPLEX_NO_1D_SCANS, NULL) ||
382 nRestartMax < 0 || nPassMax <= 0 || nEvalMax <= 0)
383 SDDS_Bomb("Invalid -simplex syntax/values");
384 break;
385 case SET_EQUATION:
386 if ((s_arg[i_arg].n_items < 2) || (s_arg[i_arg].n_items > 3))
387 SDDS_Bomb("Invalid -equation syntax");
388 if (s_arg[i_arg].n_items == 2) {
389 if (!strlen(equation = s_arg[i_arg].list[1])) {
390 SDDS_Bomb("Invalid -equation syntax");
391 }
392 } else if (s_arg[i_arg].n_items == 3) {
393 if (strncmp(s_arg[i_arg].list[2], "algebraic", strlen(s_arg[i_arg].list[2])) == 0) {
394 ptr = addOuterParentheses(s_arg[i_arg].list[1]);
395 if2pf(pfix, ptr, sizeof pfix);
396 free(ptr);
397 if (!SDDS_CopyString(&equation, pfix)) {
398 fprintf(stderr, "Error: Problem copying equation string\n");
399 exit(EXIT_FAILURE);
400 }
401 } else {
402 SDDS_Bomb("Invalid -equation syntax");
403 }
404 }
405 break;
406 case SET_EXPRESSION:
407 if (s_arg[i_arg].n_items != 2 && s_arg[i_arg].n_items != 3)
408 SDDS_Bomb("Invalid -expression syntax");
409 expression = trealloc(expression, sizeof(*expression) * (nExpressions + 1));
410 expression[nExpressions] = s_arg[i_arg].list[1];
411 expressionColumn = trealloc(expressionColumn, sizeof(*expressionColumn) * (nExpressions + 1));
412 if (s_arg[i_arg].n_items == 3)
413 expressionColumn[nExpressions] = s_arg[i_arg].list[2];
414 else
415 expressionColumn[nExpressions] = NULL;
416 nExpressions++;
417 break;
418 case SET_STARTFROMPREVIOUS:
419 startFromPrevious = 1;
420 break;
421 default:
422 fprintf(stderr, "Error: Unknown or ambiguous option: %s\n", s_arg[i_arg].list[0]);
423 exit(EXIT_FAILURE);
424 break;
425 }
426 } else {
427 if (input == NULL)
428 input = s_arg[i_arg].list[0];
429 else if (output == NULL)
430 output = s_arg[i_arg].list[0];
431 else
432 SDDS_Bomb("Too many filenames provided");
433 }
434 }
435
436 processFilenames("sddsgenericfit", &input, &output, pipeFlags, 0, NULL);
437
438 if (!yName)
439 SDDS_Bomb("-ycolumn option must be given");
440 if (nVariables == 0)
441 SDDS_Bomb("You must specify at least one -variable option");
442 if (equation == NULL)
443 SDDS_Bomb("You must specify an equation string");
444
445 rpn(getenv("RPN_DEFNS"));
446 if (rpn_check_error())
447 exit(EXIT_FAILURE);
448
449 if (!SDDS_InitializeInput(&InputTable, input))
450 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
451 if ((xName && !SDDS_FindColumn(&InputTable, FIND_NUMERIC_TYPE, xName, NULL)) ||
452 !SDDS_FindColumn(&InputTable, FIND_NUMERIC_TYPE, yName, NULL) ||
453 (syName && !SDDS_FindColumn(&InputTable, FIND_NUMERIC_TYPE, syName, NULL)))
454 SDDS_Bomb("One or more of the specified data columns does not exist or is non-numeric");
455
456 setupOutputFile(&OutputTable, &fitIndex, &residualIndex, output, &InputTable, xName, yName, syName,
457 variableName, variableUnits, nVariables, colMatch, colMatches,
458 expression, expressionColumn, nExpressions,
459 &logData, logFile, columnMajorOrder);
460
461 if (!(paramValue = SDDS_Malloc(sizeof(*paramValue) * nVariables)) ||
462 !(paramDelta = SDDS_Malloc(sizeof(*paramDelta) * nVariables)) ||
463 !(paramDelta0 = SDDS_Malloc(sizeof(*paramDelta0) * nVariables)) ||
464 !(variableMem = SDDS_Malloc(sizeof(*variableMem) * nVariables)))
465 SDDS_Bomb("Memory allocation failure");
466 for (iVariable = 0; iVariable < nVariables; iVariable++)
467 variableMem[iVariable] = rpn_create_mem(variableName[iVariable], 0);
468
469 while ((retval = SDDS_ReadPage(&InputTable)) > 0) {
470 if ((xName && !(xData = SDDS_GetColumnInDoubles(&InputTable, xName))) ||
471 !(yData = SDDS_GetColumnInDoubles(&InputTable, yName)))
472 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
473 if (syName && !(syData = SDDS_GetColumnInDoubles(&InputTable, syName)))
474 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
475
476 if ((nData = SDDS_CountRowsOfInterest(&InputTable)) <= nVariables)
477 continue;
478
479 for (iVariable = 0; iVariable < nVariables; iVariable++) {
480 if (startingPar[iVariable] && !SDDS_GetParameterAsDouble(&InputTable, startingPar[iVariable], &startingValue[iVariable]))
481 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
482 if (lowerLimitPar[iVariable] && !SDDS_GetParameterAsDouble(&InputTable, lowerLimitPar[iVariable], &lowerLimit[iVariable]))
483 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
484 if (upperLimitPar[iVariable] && !SDDS_GetParameterAsDouble(&InputTable, upperLimitPar[iVariable], &upperLimit[iVariable]))
485 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
486 if (heatPar[iVariable] && !SDDS_GetParameterAsDouble(&InputTable, heatPar[iVariable], &heat[iVariable]))
487 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
488 if (stepPar[iVariable] && !SDDS_GetParameterAsDouble(&InputTable, stepPar[iVariable], &stepSize[iVariable]))
489 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
490 if (SDDS_GetParameterIndex(&InputTable, variableName[iVariable]) >= 0) {
491 if (!SDDS_GetParameterAsDouble(&InputTable, variableName[iVariable], &paramValue[iVariable]))
492 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
493 } else if (retval == 1 || !startFromPrevious)
494 paramValue[iVariable] = startingValue[iVariable];
495 paramDelta[iVariable] = stepSize[iVariable];
496 }
497 if (verbosity > 2) {
498 /* Show starting values */
499 fprintf(stderr, "Starting values and step sizes:\n");
500 for (iVariable = 0; iVariable < nVariables; iVariable++)
501 fprintf(stderr, " %s = %le %le\n", variableName[iVariable], paramValue[iVariable], paramDelta[iVariable]);
502 }
503
504 if (!(yFit = SDDS_Realloc(yFit, sizeof(*yFit) * nData)) ||
505 !(yResidual = SDDS_Realloc(yResidual, sizeof(*yResidual) * nData)))
506 SDDS_Bomb("Memory allocation failure");
507 if (nExpressions) {
508 long j;
509 expressionValue = SDDS_Realloc(expressionValue, sizeof(*expressionValue) * nExpressions);
510 for (j = 0; j < nExpressions; j++)
511 expressionValue[j] = malloc(sizeof(**expressionValue) * nData);
512 }
513 SDDS_StoreParametersInRpnMemories(&InputTable);
514 memcpy(paramDelta0, paramDelta, sizeof(*paramDelta) * nVariables);
515 for (iRestart = nEval = 0; iRestart <= nRestartMax; iRestart++) {
516 memcpy(paramDelta, paramDelta0, sizeof(*paramDelta) * nVariables);
517 if (iRestart) {
518 if (iRestart == 1)
519 random_1(-labs(2 * ((long)time(NULL) / 2) + 1));
520 for (iVariable = 0; iVariable < nVariables; iVariable++) {
521 paramValue[iVariable] += gauss_rn_lim(0.0, heat[iVariable], 2, random_1);
522 if (paramValue[iVariable] < lowerLimit[iVariable])
523 paramValue[iVariable] = lowerLimit[iVariable] + paramDelta[iVariable];
524 if (paramValue[iVariable] > upperLimit[iVariable])
525 paramValue[iVariable] = upperLimit[iVariable] - paramDelta[iVariable];
526 }
527 }
528 nEval += simplexMin(&result, paramValue, paramDelta, lowerLimit, upperLimit, NULL, nVariables, target, tolerance, fitFunction, (verbosity > 0 ? report : NULL), nEvalMax, nPassMax, 12, 3, 1.0, simplexFlags);
529 if (iRestart != 0 && result > bestResult) {
530 result = bestResult;
531 for (iVariable = 0; iVariable < nVariables; iVariable++)
532 paramValue[iVariable] = bestParamValue[iVariable];
533 } else {
534 bestResult = result;
535 for (iVariable = 0; iVariable < nVariables; iVariable++)
536 bestParamValue[iVariable] = paramValue[iVariable];
537 }
538 if (verbosity > 0)
539 fprintf(stderr, "Result of simplex minimization: %le\n", result);
540 if (result < target || (iRestart != 0 && fabs(lastResult - result) < tolerance))
541 break;
542 lastResult = result;
543 if (abortRequested)
544 break;
545 if (verbosity > 0)
546 fprintf(stderr, "Performing restart %ld\n", iRestart + 1);
547 }
548
549 for (iVariable = 0; iVariable < nVariables; iVariable++)
550 paramValue[iVariable] = bestParamValue[iVariable];
551 result = fitFunction(paramValue, &ii);
552
553 if (verbosity > 3)
554 fprintf(stderr, "%ld evaluations of fit function required, giving result %e\n", nEval, result);
555 for (i = result = 0; i < nData; i++)
556 result += sqr(yResidual[i]);
557 rmsResidual = sqrt(result / nData);
558 if (syData) {
559 for (i = chiSqr = 0; i < nData; i++)
560 chiSqr += sqr(yResidual[i] / syData[i]);
561 } else {
562 double sy2;
563 sy2 = result / (nData - nVariables);
564 for (i = chiSqr = 0; i < nData; i++)
565 chiSqr += sqr(yResidual[i]) / sy2;
566 }
567 sigLevel = ChiSqrSigLevel(chiSqr, nData - nVariables);
568 if (verbosity > 1) {
569 if (syData)
570 fprintf(stderr, "Significance level: %.5e\n", sigLevel);
571 fprintf(stderr, "RMS deviation: %.15e\n", rmsResidual);
572 }
573
574 if (!SDDS_StartPage(&OutputTable, nData) ||
575 !SDDS_CopyPage(&OutputTable, &InputTable) ||
576 !SDDS_SetColumn(&OutputTable, SDDS_SET_BY_INDEX, yFit, nData, fitIndex) ||
577 !SDDS_SetColumn(&OutputTable, SDDS_SET_BY_INDEX, yResidual, nData, residualIndex))
578 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
579 for (i = 0; i < nExpressions; i++)
580 if (expressionColumn[i] &&
581 !SDDS_SetColumn(&OutputTable, SDDS_SET_BY_NAME, expressionValue[i], nData, expressionColumn[i]))
582 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
583 for (iVariable = 0; iVariable < nVariables; iVariable++)
584 if (!SDDS_SetParameters(&OutputTable, SDDS_PASS_BY_VALUE | SDDS_SET_BY_NAME, variableName[iVariable], paramValue[iVariable], NULL))
585 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
586 if (!SDDS_WritePage(&OutputTable))
587 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
588 if (logFile && !SDDS_WritePage(&logData))
589 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
590 step = 0;
591 free(xData);
592 free(yData);
593 if (syData)
594 free(syData);
595 }
596 if (!SDDS_Terminate(&InputTable) || !SDDS_Terminate(&OutputTable))
597 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
598 if (logFile && !SDDS_Terminate(&logData))
599 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
600 if (colMatches)
601 free(colMatch);
602 if (syName)
603 free(syName);
604 SDDS_FreeStringArray(variableName, nVariables);
605 free_scanargs(&s_arg, argc);
606 free(lowerLimit);
607 free(upperLimit);
608 free(stepSize);
609 free(heat);
610 free(bestParamValue);
611 free(startingValue);
612 free(startingPar);
613 free(lowerLimitPar);
614 free(upperLimitPar);
615 free(heatPar);
616 free(stepPar);
617 free(variableUnits);
618
619 return EXIT_SUCCESS;
620}
int32_t SDDS_CopyPage(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:578
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.
double * SDDS_GetParameterAsDouble(SDDS_DATASET *SDDS_dataset, char *parameter_name, double *memory)
Retrieves the value of a specified parameter as a double from the current data table of an SDDS datas...
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:49
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_FreeStringArray(char **string, int64_t strings)
Frees an array of strings by deallocating each individual string.
int32_t SDDS_GetParameterIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named parameter in the SDDS dataset.
void * SDDS_Malloc(size_t size)
Allocates memory of a specified size.
Definition SDDS_utils.c:639
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
char * SDDS_FindColumn(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
Finds the first column in the SDDS dataset that matches the specified criteria.
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
Definition SDDS_utils.c:856
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
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
double random_1(long iseed)
Generate a uniform random double in [0,1] using a custom seed initialization.
Definition drand.c:175
double gauss_rn_lim(double mean, double sigma, double limit_in_sigmas, double(*urandom)(long iseed))
Generate a Gaussian-distributed random number with specified mean, sigma, and optional cutoff.
Definition drand.c:378
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
void free_scanargs(SCANNED_ARG **scanned, int argc)
Definition scanargs.c:584
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.
double ChiSqrSigLevel(double ChiSquared0, long nu)
Computes the probability that a chi-squared variable exceeds a given value.
Definition sigLevel.c:64
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

◆ optimizationInterruptHandler()

void optimizationInterruptHandler ( int signal)

Definition at line 203 of file sddsgenericfit.c.

203 {
205 abortRequested = 1;
206 fprintf(stderr, "Aborting minimization\n");
207}
long simplexMinAbort(unsigned long abort)
Abort or query the status of the simplex optimization.
Definition simplex.c:34

◆ report()

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

Definition at line 760 of file sddsgenericfit.c.

760 {
761 long i;
762
763 fprintf(stderr, "pass %ld, after %ld evaluations: result = %.16e\na = ", pass, n_eval, y);
764 for (i = 0; i < n_dimen; i++)
765 fprintf(stderr, "%.8e ", x[i]);
766 fputc('\n', stderr);
767}

◆ setupOutputFile()

void setupOutputFile ( SDDS_DATASET * OutputTable,
long * fitIndex,
long * residualIndex,
char * output,
SDDS_DATASET * InputTable,
char * xName,
char * yName,
char * syName,
char ** variableName,
char ** variableUnits,
long variables,
char ** colMatch,
int32_t colMatches,
char ** expression,
char ** expressionColumn,
long nExpressions,
SDDS_DATASET * logData,
char * logFile,
short columnMajorOrder )

Definition at line 622 of file sddsgenericfit.c.

626 {
627 char *name, *yUnits = NULL, **col = NULL;
628 int32_t typeValue = SDDS_DOUBLE;
629 static char *residualNamePart = "Residual";
630 long i;
631 int32_t cols = 0;
632
633 if (!SDDS_InitializeOutput(OutputTable, SDDS_BINARY, 0, NULL, "sddsgfit output", output) ||
634 !SDDS_TransferColumnDefinition(OutputTable, InputTable, yName, NULL) ||
635 !SDDS_ChangeColumnInformation(OutputTable, "type", &typeValue, SDDS_BY_NAME, yName))
636 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
637 if (columnMajorOrder != -1)
638 OutputTable->layout.data_mode.column_major = columnMajorOrder;
639 else
640 OutputTable->layout.data_mode.column_major = InputTable->layout.data_mode.column_major;
641 if (logFile && !!SDDS_InitializeOutput(logData, SDDS_BINARY, 0, NULL, "sddsgenericfit log", logFile))
642 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
643 if (syName && (!SDDS_TransferColumnDefinition(OutputTable, InputTable, syName, NULL) ||
644 !SDDS_ChangeColumnInformation(OutputTable, "type", &typeValue, SDDS_BY_NAME, syName)))
645 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
646
647 if (xName && !SDDS_TransferColumnDefinition(OutputTable, InputTable, xName, NULL))
648 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
649 if (colMatches) {
650 col = getMatchingSDDSNames(InputTable, colMatch, colMatches, &cols, SDDS_MATCH_COLUMN);
651 for (i = 0; i < cols; i++) {
652 if (SDDS_GetColumnIndex(OutputTable, col[i]) < 0 &&
653 !SDDS_TransferColumnDefinition(OutputTable, InputTable, col[i], NULL))
654 SDDS_PrintErrors(stdout, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
655 }
656 SDDS_FreeStringArray(col, cols);
657 }
658 name = tmalloc(sizeof(*name) * (strlen(yName) + strlen(residualNamePart) + 1));
659 sprintf(name, "%s%s", yName, residualNamePart);
660 if ((*residualIndex = SDDS_DefineColumn(OutputTable, name, NULL, yUnits, NULL, NULL, SDDS_DOUBLE, 0)) < 0)
661 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
662 sprintf(name, "%sFit", yName);
663 if ((*fitIndex = SDDS_DefineColumn(OutputTable, name, NULL, yUnits, NULL, NULL, SDDS_DOUBLE, 0)) < 0)
664 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
665 free(name);
666
667 for (i = 0; i < variables; i++) {
668 if (SDDS_DefineParameter(OutputTable, variableName[i], NULL, variableUnits[i], NULL, NULL, SDDS_DOUBLE, 0) < 0)
669 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
670 if (logFile && SDDS_DefineColumn(logData, variableName[i], NULL, variableUnits[i], NULL, NULL, SDDS_DOUBLE, 0) < 0)
671 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
672 }
673
674 for (i = 0; i < nExpressions; i++) {
675 if (expressionColumn[i]) {
676 if (SDDS_DefineColumn(OutputTable, expressionColumn[i], NULL, NULL, expression[i], NULL, SDDS_DOUBLE, 0) < 0)
677 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
678 }
679 }
680 if (!SDDS_TransferAllParameterDefinitions(OutputTable, InputTable, SDDS_TRANSFER_KEEPOLD) ||
681 !SDDS_WriteLayout(OutputTable))
682 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
683 if (logFile && (!SDDS_DefineSimpleColumn(logData, "Step", NULL, SDDS_LONG) ||
684 !SDDS_DefineSimpleColumn(logData, "Chi", NULL, SDDS_DOUBLE) ||
685 !SDDS_WriteLayout(logData)))
686 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
687}
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_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_DefineSimpleColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type)
Defines a simple data column within the SDDS 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.
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.
char ** getMatchingSDDSNames(SDDS_DATASET *dataset, char **matchName, int32_t matches, int32_t *names, short type)
Retrieves an array of matching SDDS entity names based on specified criteria.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37