97#include "../../2d_interpolate/nn/nan.h"
99void print_coefs(FILE *fprec,
double x_offset,
double x_scale,
long chebyshev,
100 double *coef,
double *s_coef, int32_t *order,
long n_terms,
101 double chi,
long norm_term,
char *prepend);
102char **makeCoefficientUnits(
SDDS_DATASET *SDDSout,
char *xName,
char *yName,
103 int32_t *order,
long terms);
104long setCoefficientData(
SDDS_DATASET *SDDSout,
double *coef,
double *coefSigma,
105 char **coefUnits, int32_t *order,
long terms,
long chebyshev,
106 char *fitLabelFormat,
char *rpnSeqBuffer);
107char **initializeOutputFile(
SDDS_DATASET *SDDSout,
char *output,
109 char *yName,
char *xSigmaName,
char *ySigmaName,
110 long sigmasValid, int32_t *order,
long terms,
111 long chebyshev,
long copyParameters,
long repeatFits);
112void checkInputFile(
SDDS_DATASET *SDDSin,
char *xName,
char *yName,
113 char *xSigmaName,
char *ySigmaName);
114long coefficient_index(int32_t *order,
long terms,
long order_of_interest);
115void makeFitLabel(
char *buffer,
long bufsize,
char *fitLabelFormat,
116 double *coef,
double *coefSigma, int32_t *order,
long terms,
long chebyshev);
117void createRpnSequence(
char *buffer,
long bufsize,
double *coef, int32_t *order,
120double tcheby(
double x,
long n);
121double dtcheby(
double x,
long n);
122double ipower(
double x,
long n);
123double dipower(
double x,
long n);
124long reviseFitOrders(
double *x,
double *y,
double *sy, int64_t points,
125 long terms, int32_t *order,
double *coef,
126 double *coefSigma,
double *diff,
127 double (*basis_fn)(
double xa,
long ordera),
128 unsigned long reviseOrders,
double xOffset,
129 double xScaleFactor,
long normTerm,
long ySigmasValid,
130 long chebyshev,
double revpowThreshold,
131 double revpowCompleteThres,
double goodEnoughChi);
132long reviseFitOrders1(
double *x,
double *y,
double *sy, int64_t points,
133 long terms, int32_t *order,
double *coef,
134 double *coefSigma,
double *diff,
135 double (*basis_fn)(
double xa,
long ordera),
136 unsigned long reviseOrders,
double xOffset,
137 double xScaleFactor,
long normTerm,
long ySigmasValid,
138 long chebyshev,
double revpowThreshold,
139 double goodEnoughChi);
140void compareOriginalToFit(
double *x,
double *y,
double **residual,
141 int64_t points,
double *rmsResidual,
double *coef,
142 int32_t *order,
long terms);
149CHEBYSHEV_COEF *makeChebyshevCoefficients(
long maxOrder,
long *nPoly);
150void convertFromChebyshev(
long termsT, int32_t *orderT,
double *coefT,
double *coefSigmaT,
151 long *termsOrdinaryRet, int32_t **orderOrdinaryRet,
double **coefOrdinaryRet,
double **coefSigmaOrdinaryRet);
180char *option[N_OPTIONS] = {
206 "sddspfit [<inputfile>] [<outputfile>] [-pipe=[input][,output]]\n\
207 -columns=<xname>,<yname>[,xSigma=<name>][,ySigma=<name>]\n\
208 [ {-terms=<number> [-symmetry={none|odd|even}] | -orders=<number>[,...]} ]\n\
209 [-reviseOrders [=threshold=<chiValue>] [,verbose] [,complete=<chiThreshold>] [,goodEnough=<chiValue>]]\n\
210 [-chebyshev [=convert]]\n\
211 [-xOffset=<value>] [-autoOffset] [-xFactor=<value>]\n\
212 [-sigmas=<value>,{absolute|fractional}] \n\
213 [-modifySigmas] [-generateSigmas[={keepLargest|keepSmallest}]]\n\
214 [-sparse=<interval>] [-range=<lower>,<upper>[,fitOnly]]\n\
215 [-normalize[=<termNumber>]] [-verbose]\n\
216 [-evaluate=<filename>[,begin=<value>] [,end=<value>] [,number=<integer>] \n\
217 [,valuesFile=<filename>,valuesColumn=<string>[,reusePage]]]\n\
218 [-fitLabelFormat=<sprintf-string>] [-copyParameters] [-majorOrder={row|column}]\n\n\
219Program by Michael Borland. (" __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")\n";
221static char *additional_help1 =
"\n\
222sddspfit fits data to the form y = SUM(i){ A[i] * P(x - x_offset, i) }, where P(x, i) is the ith basis\n\
223function evaluated at x. By default, P(x, i) = x^i. Chebyshev T polynomials can also be selected as the basis functions.\n\n\
224 -columns Specify names of data columns to use.\n\
225 -terms Number of terms desired in fit.\n\
226 -symmetry Symmetry of desired fit about x_offset.\n\
227 -orders Orders (P[i]) to use in fitting.\n\
228 -reviseOrders Modify the orders used in the fit to eliminate poorly-determined coefficients based on fitting\n\
229 of the first data page. The algorithm adds one order at a time, terminating when the reduced\n\
230 chi-squared is less than the 'goodEnough' value (default: 1) or when the new term does not improve\n\
231 the reduced chi-squared by more than the threshold value (default: 0.1). It next tries removing terms one at a time.\n\
232 Finally, if the resulting best reduced chi-squared is greater than the threshold given with the 'complete' option,\n\
233 it also tries all possible combinations of allowed terms.\n\
234 -chebyshev Use Chebyshev T polynomials (xOffset is set automatically).\n\
235 Giving the `convert` option causes the fit to be written out in terms of ordinary polynomials.\n\
236 -majorOrder Specify output file in row or column major order.\n\
237 -xOffset Desired value of x to fit about.\n";
239static char *additional_help2 =
240" -autoOffset Automatically offset x values by the mean x value for fitting.\n\
241 Helpful if x values are very large in magnitude.\n\
242 -xFactor Desired factor to multiply x values by before fitting.\n\
243 -sigmas Specify absolute or fractional sigma for all points.\n\
244 -modifySigmas Modify the y sigmas using the x sigmas and an initial fit.\n\
245 -generateSigmas Generate y sigmas from the RMS deviation from an initial fit.\n\
246 Optionally keep the sigmas from the data if larger/smaller than RMS deviation.\n\
247 -repeatFits Repeats the fit <number> times with resampling (bootstrap) to estimate RMS errors in fit coefficients.\n\
248 -sparse Specify integer interval at which to sample data.\n\
249 -range Specify range of independent variable over which to perform fit and evaluation.\n\
250 If 'fitOnly' is given, then fit is compared to data over the original range.\n\
251 -normalize Normalize so that the specified term is unity.\n\
252 -verbose Generates extra output that may be useful.\n\
253 -evaluate Specify evaluation of fit over a selected range of equispaced points,\n\
254 or at values listed in a file.\n\
255 -copyParameters If given, program copies all parameters from the input file into the main output file.\n\
256 By default, no parameters are copied.\n\n";
259#define EVEN_SYMMETRY 1
260#define ODD_SYMMETRY 2
261#define N_SYMMETRY_OPTIONS 3
262char *symmetry_options[N_SYMMETRY_OPTIONS] = {
"none",
"even",
"odd"};
264#define ABSOLUTE_SIGMAS 0
265#define FRACTIONAL_SIGMAS 1
266#define N_SIGMAS_OPTIONS 2
267char *sigmas_options[N_SIGMAS_OPTIONS] = {
"absolute",
"fractional"};
269#define FLGS_GENERATESIGMAS 1
270#define FLGS_KEEPLARGEST 2
271#define FLGS_KEEPSMALLEST 4
273#define REVPOW_ACTIVE 0x0001
274#define REVPOW_VERBOSE 0x0002
275#define REVPOW_COMPLETE 0x0004
278static long iIntercept = -1, iInterceptSigma = -1;
279static long iSlope = -1, iSlopeSigma = -1;
280static long iCurvature = -1, iCurvatureSigma = -1;
281static long *iTerm = NULL, *iTermSig = NULL;
282static long iOffset = -1, iFactor = -1;
283static long iChiSq = -1, iRmsResidual = -1, iSigLevel = -1;
284static long iFitIsValid = -1, iFitLabel = -1, iTerms = -1;
285static long iRpnSequence;
287static long ix = -1, iy = -1, ixSigma = -1, iySigma = -1;
288static long iFit = -1, iResidual = -1;
290static char *xSymbol, *ySymbol;
292#define EVAL_BEGIN_GIVEN 0x0001U
293#define EVAL_END_GIVEN 0x0002U
294#define EVAL_NUMBER_GIVEN 0x0004U
295#define EVAL_VALUESFILE_GIVEN 0x0008U
296#define EVAL_VALUESCOLUMN_GIVEN 0x0010U
297#define EVAL_REUSE_PAGE_GIVEN 0x0020U
306 short inputInitialized;
307 char *valuesFile, *valuesColumn;
310void makeEvaluationTable(
EVAL_PARAMETERS *evalParameters,
double *x, int64_t n,
311 double *coef, int32_t *order,
long terms,
314static double (*basis_fn)(
double xa,
long ordera);
315static double (*basis_dfn)(
double xa,
long ordera);
317int main(
int argc,
char **argv) {
318 double *x = NULL, *y = NULL, *sy = NULL, *sx = NULL, *diff = NULL, xOffset,
320 double *xOrig = NULL, *yOrig = NULL, *sxOrig, *syOrig, *sy0 = NULL;
321 long terms, normTerm, ySigmasValid;
322 int64_t i, j, points, pointsOrig;
323 long symmetry, chebyshev, autoOffset, copyParameters = 0;
325 long sigmasMode, sparseInterval;
327 double *coef, *coefSigma;
328 double chi, xLow, xHigh, rmsResidual;
329 char *xName, *yName, *xSigmaName, *ySigmaName;
330 char *input, *output, **coefUnits;
332 long isFit, iArg, modifySigmas;
333 long generateSigmas, verbose, ignoreSigmas;
338 double xMin, xMax, revpowThreshold, revpowCompleteThres, goodEnoughChi;
339 long rangeFitOnly = 0;
340 double rms_average(
double *d_x, int64_t d_n);
341 char *fitLabelFormat =
"%g";
342 static char rpnSeqBuffer[SDDS_MAXLINE];
343 unsigned long pipeFlags, reviseOrders, majorOrderFlag;
345 short columnMajorOrder = -1;
348 sxOrig = syOrig = NULL;
352 argc =
scanargs(&s_arg, argc, argv);
353 if (argc < 2 || argc > (3 + N_OPTIONS)) {
354 fprintf(stderr,
"usage: %s%s%s\n", USAGE, additional_help1,
359 input = output = NULL;
360 xName = yName = xSigmaName = ySigmaName = NULL;
361 modifySigmas = reviseOrders = chebyshev = 0;
363 symmetry = NO_SYMMETRY;
371 verbose = ignoreSigmas = 0;
379 evalParameters.file = evalParameters.valuesFile = evalParameters.valuesColumn = NULL;
380 evalParameters.initialized = evalParameters.inputInitialized = 0;
382 for (iArg = 1; iArg < argc; iArg++) {
383 if (s_arg[iArg].arg_type == OPTION) {
384 switch (
match_string(s_arg[iArg].list[0], option, N_OPTIONS, 0)) {
386 if (s_arg[iArg].n_items != 2 || sscanf(s_arg[iArg].list[1],
"%ld", &repeatFits) != 1 || repeatFits < 1)
389 SDDS_Bomb(
"The number of repeats should be at least 10");
391 case CLO_MAJOR_ORDER:
393 s_arg[iArg].n_items--;
394 if (s_arg[iArg].n_items > 0 &&
396 &s_arg[iArg].n_items, 0,
"row", -1, NULL, 0,
397 SDDS_ROW_MAJOR_ORDER,
"column", -1, NULL, 0,
398 SDDS_COLUMN_MAJOR_ORDER, NULL)))
399 SDDS_Bomb(
"invalid -majorOrder syntax/values");
400 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
401 columnMajorOrder = 1;
402 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
403 columnMajorOrder = 0;
405 case CLO_MODIFYSIGMAS:
412 if (s_arg[iArg].n_items < 2)
414 order =
tmalloc(
sizeof(*order) * (terms = s_arg[iArg].n_items - 1));
415 for (i = 1; i < s_arg[iArg].n_items; i++) {
416 if (sscanf(s_arg[iArg].list[i],
"%" SCNd32, order + i - 1) != 1)
417 SDDS_Bomb(
"unable to scan order from -orders list");
422 if ((s_arg[iArg].n_items != 3 && s_arg[iArg].n_items != 4) ||
423 1 != sscanf(s_arg[iArg].list[1],
"%lf", &xMin) ||
424 1 != sscanf(s_arg[iArg].list[2],
"%lf", &xMax) || xMin >= xMax)
426 if (s_arg[iArg].n_items == 4) {
427 if (strncmp(
str_tolower(s_arg[iArg].list[3]),
"fitonly",
428 strlen(s_arg[iArg].list[3])) == 0) {
434 case CLO_GENERATESIGMAS:
435 generateSigmas = FLGS_GENERATESIGMAS;
436 if (s_arg[iArg].n_items > 1) {
437 if (s_arg[iArg].n_items != 2)
438 SDDS_Bomb(
"incorrect -generateSigmas syntax");
439 if (strncmp(s_arg[iArg].list[1],
"keepsmallest",
440 strlen(s_arg[iArg].list[1])) == 0)
441 generateSigmas |= FLGS_KEEPSMALLEST;
442 if (strncmp(s_arg[iArg].list[1],
"keeplargest",
443 strlen(s_arg[iArg].list[1])) == 0)
444 generateSigmas |= FLGS_KEEPLARGEST;
445 if ((generateSigmas & FLGS_KEEPSMALLEST) &&
446 (generateSigmas & FLGS_KEEPLARGEST))
447 SDDS_Bomb(
"ambiguous -generateSigmas syntax");
451 if (s_arg[iArg].n_items != 2 ||
452 sscanf(s_arg[iArg].list[1],
"%ld", &terms) != 1)
456 if (s_arg[iArg].n_items != 2 ||
457 sscanf(s_arg[iArg].list[1],
"%lf", &xOffset) != 1)
461 if (s_arg[iArg].n_items == 2) {
462 if ((symmetry =
match_string(s_arg[iArg].list[1], symmetry_options,
463 N_SYMMETRY_OPTIONS, 0)) < 0)
464 SDDS_Bomb(
"unknown option used with -symmetry");
469 if (s_arg[iArg].n_items != 3)
471 if (sscanf(s_arg[iArg].list[1],
"%lf", &sigmas) != 1)
472 SDDS_Bomb(
"couldn't scan value for -sigmas");
473 if ((sigmasMode =
match_string(s_arg[iArg].list[2], sigmas_options,
474 N_SIGMAS_OPTIONS, 0)) < 0)
478 if (s_arg[iArg].n_items != 2)
480 if (sscanf(s_arg[iArg].list[1],
"%ld", &sparseInterval) != 1)
481 SDDS_Bomb(
"couldn't scan value for -sparse");
482 if (sparseInterval < 1)
490 if (s_arg[iArg].n_items > 2 ||
491 (s_arg[iArg].n_items == 2 &&
492 sscanf(s_arg[iArg].list[1],
"%ld", &normTerm) != 1) ||
496 case CLO_REVISEORDERS:
497 revpowThreshold = 0.1;
498 revpowCompleteThres = 10;
500 s_arg[iArg].n_items -= 1;
502 &s_arg[iArg].n_items, 0,
504 "complete",
SDDS_DOUBLE, &revpowCompleteThres, 1, REVPOW_COMPLETE,
506 "verbose", -1, NULL, 1, REVPOW_VERBOSE, NULL) ||
507 revpowThreshold < 0 || revpowCompleteThres < 0 || goodEnoughChi < 0)
508 SDDS_Bomb(
"invalid -reviseOrders syntax");
509 reviseOrders |= REVPOW_ACTIVE;
512 if (s_arg[iArg].n_items > 2 ||
513 (s_arg[iArg].n_items == 2 &&
514 strncmp(s_arg[iArg].list[1],
"convert",
515 strlen(s_arg[iArg].list[1])) != 0))
517 chebyshev = s_arg[iArg].n_items;
522 if (s_arg[iArg].n_items != 2 ||
523 sscanf(s_arg[iArg].list[1],
"%lf", &xScaleFactor) != 1 ||
528 if (s_arg[iArg].n_items < 3 || s_arg[iArg].n_items > 5)
530 xName = s_arg[iArg].list[1];
531 yName = s_arg[iArg].list[2];
532 s_arg[iArg].n_items -= 3;
533 if (!
scanItemList(&flags, s_arg[iArg].list + 3, &s_arg[iArg].n_items, 0,
534 "xsigma",
SDDS_STRING, &xSigmaName, 1, 0,
"ysigma",
538 case CLO_FITLABELFORMAT:
539 if (s_arg[iArg].n_items != 2)
540 SDDS_Bomb(
"invalid -fitLabelFormat syntax");
541 fitLabelFormat = s_arg[iArg].list[1];
549 if (s_arg[iArg].n_items < 2)
551 evalParameters.file = s_arg[iArg].list[1];
552 s_arg[iArg].n_items -= 2;
553 s_arg[iArg].list += 2;
554 if (!
scanItemList(&evalParameters.flags, s_arg[iArg].list,
555 &s_arg[iArg].n_items, 0,
556 "begin",
SDDS_DOUBLE, &evalParameters.begin, 1, EVAL_BEGIN_GIVEN,
557 "end",
SDDS_DOUBLE, &evalParameters.end, 1, EVAL_END_GIVEN,
558 "number",
SDDS_LONG64, &evalParameters.number, 1, EVAL_NUMBER_GIVEN,
559 "valuesfile",
SDDS_STRING, &evalParameters.valuesFile, 1, EVAL_VALUESFILE_GIVEN,
560 "valuescolumn",
SDDS_STRING, &evalParameters.valuesColumn, 1, EVAL_VALUESCOLUMN_GIVEN,
561 "reusepage", 0, NULL, 0, EVAL_REUSE_PAGE_GIVEN,
564 if (evalParameters.flags & EVAL_VALUESFILE_GIVEN || evalParameters.flags & EVAL_VALUESCOLUMN_GIVEN) {
565 if (evalParameters.flags & (EVAL_BEGIN_GIVEN | EVAL_END_GIVEN | EVAL_NUMBER_GIVEN))
566 SDDS_Bomb(
"invalid -evaluate syntax: given begin/end/number or valuesFile/valuesColumn, not a mixture.");
567 if (!(evalParameters.flags & EVAL_VALUESFILE_GIVEN && evalParameters.flags & EVAL_VALUESCOLUMN_GIVEN))
568 SDDS_Bomb(
"invalid -evaluate syntax: give both valuesFile and valuesColumn, not just one");
570 evalParameters.initialized = 0;
572 case CLO_COPY_PARAMETERS:
576 bomb(
"unknown switch", USAGE);
581 input = s_arg[iArg].list[0];
582 else if (output == NULL)
583 output = s_arg[iArg].list[0];
591 if (symmetry && order)
592 SDDS_Bomb(
"can't specify both -symmetry and -orders");
593 if (chebyshev && order)
594 SDDS_Bomb(
"can't specify both -chebyshev and -orders");
595 if (chebyshev && symmetry)
596 SDDS_Bomb(
"can't specify both -chebyshev and -symmetry");
597 if (!xName || !yName)
598 SDDS_Bomb(
"you must specify a column name for x and y");
600 if (modifySigmas && !xSigmaName)
601 SDDS_Bomb(
"you must specify x sigmas with -modifySigmas");
602 if (generateSigmas) {
604 SDDS_Bomb(
"you can't specify both -generateSigmas and -modifySigmas");
607 if (sigmasMode != -1)
608 SDDS_Bomb(
"you can't specify both -sigmas and a y sigma name");
611 if (sigmasMode != -1 || generateSigmas || ySigmaName || modifySigmas)
614 if (normTerm >= 0 && normTerm >= terms)
615 SDDS_Bomb(
"can't normalize to that term--not that many terms");
616 if (reviseOrders && !(sigmasMode != -1 || generateSigmas || ySigmaName))
617 SDDS_Bomb(
"can't use -reviseOrders unless a y sigma or -generateSigmas is given");
619 if (symmetry == EVEN_SYMMETRY) {
620 order =
tmalloc(
sizeof(*order) * terms);
621 for (i = 0; i < terms; i++)
623 }
else if (symmetry == ODD_SYMMETRY) {
624 order =
tmalloc(
sizeof(*order) * terms);
625 for (i = 0; i < terms; i++)
626 order[i] = 2 * i + 1;
628 order =
tmalloc(
sizeof(*order) * terms);
629 for (i = 0; i < terms; i++)
632 coef =
tmalloc(
sizeof(*coef) * terms);
633 coefSigma =
tmalloc(
sizeof(*coefSigma) * terms);
634 iTerm =
tmalloc(
sizeof(*iTerm) * terms);
635 iTermSig =
tmalloc(
sizeof(*iTermSig) * terms);
639 checkInputFile(&SDDSin, xName, yName, xSigmaName, ySigmaName);
640 coefUnits = initializeOutputFile(&SDDSout, output, &SDDSin, input, xName,
641 yName, xSigmaName, ySigmaName, ySigmasValid,
642 order, terms, chebyshev, copyParameters, repeatFits);
643 if (columnMajorOrder != -1)
644 SDDSout.layout.data_mode.column_major = columnMajorOrder;
646 SDDSout.layout.data_mode.column_major =
647 SDDSin.layout.data_mode.column_major;
657 fprintf(stderr,
"error: unable to read column %s\n", xName);
659 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
662 fprintf(stderr,
"error: unable to read column %s\n", yName);
664 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
668 fprintf(stderr,
"error: unable to read column %s\n", xSigmaName);
670 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
674 fprintf(stderr,
"error: unable to read column %s\n", ySigmaName);
676 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
679 sy0 =
tmalloc(
sizeof(*sy0) * points);
681 if (xMin != xMax || sparseInterval != 1) {
682 xOrig =
tmalloc(
sizeof(*xOrig) * points);
683 yOrig =
tmalloc(
sizeof(*yOrig) * points);
685 sxOrig =
tmalloc(
sizeof(*sxOrig) * points);
687 syOrig =
tmalloc(
sizeof(*syOrig) * points);
689 for (i = j = 0; i < points; i++) {
698 for (i = j = 0; i < points; i++) {
699 if (xOrig[i] <= xMax && xOrig[i] >= xMin) {
711 if (sparseInterval != 1) {
712 for (i = j = 0; i < points; i++) {
713 if (i % sparseInterval == 0) {
735 if (sigmasMode == ABSOLUTE_SIGMAS) {
736 for (i = 0; i < points; i++)
739 for (i = 0; i < pointsOrig; i++)
741 }
else if (sigmasMode == FRACTIONAL_SIGMAS) {
742 for (i = 0; i < points; i++)
743 sy0[i] = sigmas * fabs(y[i]);
745 for (i = 0; i < pointsOrig; i++)
746 syOrig[i] = fabs(yOrig[i]) * sigmas;
749 if (!ySigmasValid || generateSigmas)
750 for (i = 0; i < points; i++)
753 for (i = 0; i < points; i++)
755 SDDS_Bomb(
"y sigma = 0 for one or more points.");
757 diff =
tmalloc(
sizeof(*x) * points);
758 sy =
tmalloc(
sizeof(*sy) * points);
759 for (i = 0; i < points; i++)
770 xScaleFactor = MAX(fabs(xHigh - xOffset), fabs(xLow - xOffset));
773 xOffset = (xHigh + xLow) / 2;
774 xScaleFactor = (xHigh - xLow) / 2;
780 if (generateSigmas || modifySigmas) {
782 isFit =
lsfg(x, y, sy, points, terms, order, coef, coefSigma, &chi,
787 fputs(
"initial_fit:", stdout);
788 print_coefs(stdout, xOffset, xScaleFactor, chebyshev, coef, NULL,
789 order, terms, chi, normTerm,
"");
790 fprintf(stdout,
"unweighted rms deviation from fit: %21.15e\n",
791 rms_average(diff, points));
795 for (i = 0; i < points; i++)
797 fabs(
eval_sum(basis_dfn, coef, order, terms, x[i]) * sx[i]);
799 for (i = 0; i < points; i++) {
802 sqr(
eval_sum(basis_dfn, coef, order, terms, x[i]) * sx[i]));
805 if (generateSigmas) {
807 for (i = sigma = 0; i < points; i++) {
808 sigma += sqr(diff[i]);
810 sigma = sqrt(sigma / (points - terms));
811 for (i = 0; i < points; i++) {
812 if (generateSigmas & FLGS_KEEPSMALLEST) {
815 }
else if (generateSigmas & FLGS_KEEPLARGEST) {
822 for (i = 0; i < pointsOrig; i++) {
823 if (generateSigmas & FLGS_KEEPSMALLEST) {
826 }
else if (generateSigmas & FLGS_KEEPLARGEST) {
836 if (reviseOrders & REVPOW_ACTIVE) {
837 terms = reviseFitOrders(
838 x, y, sy, points, terms, order, coef, coefSigma, diff, basis_fn,
839 reviseOrders, xOffset, xScaleFactor, normTerm, ySigmasValid,
840 chebyshev, revpowThreshold, revpowCompleteThres, goodEnoughChi);
844 if (repeatFits <= 1) {
845 isFit =
lsfg(x, y, sy, points, terms, order, coef, coefSigma, &chi, diff,
848 double *coefRepeat =
tmalloc(
sizeof(*coefRepeat) * terms * repeatFits);
849 double *coefSigmaRepeat =
tmalloc(
sizeof(*coefSigmaRepeat) * terms * repeatFits);
853 for (fitIdx = 0; fitIdx < repeatFits; fitIdx++) {
855 int64_t *indices =
tmalloc(
sizeof(*indices) * points);
856 for (i = 0; i < points; i++) indices[i] = rand() % points;
857 double *xSample =
tmalloc(
sizeof(*xSample) * points);
858 double *ySample =
tmalloc(
sizeof(*ySample) * points);
859 double *sySample =
tmalloc(
sizeof(*sySample) * points);
860 for (i = 0; i < points; i++) {
861 xSample[i] = x[indices[i]];
862 ySample[i] = y[indices[i]];
866 double *diffTmp =
tmalloc(
sizeof(*diffTmp) * points);
867 int fitOk =
lsfg(xSample, ySample, sySample, points, terms, order, coefRepeat + fitIdx * terms, coefSigmaRepeat + fitIdx * terms, &chiTmp, diffTmp, basis_fn);
876 for (i = 0; i < terms; i++) {
877 double sum = 0, sum2 = 0;
878 for (j = 0; j < repeatFits; j++) {
879 double v = coefRepeat[j * terms + i];
883 coef[i] = sum / repeatFits;
884 coefSigma[i] = sqrt(sum2 / repeatFits - (coef[i] * coef[i]));
887 free(coefSigmaRepeat);
890 for (i = 0; i < points; i++) {
891 double fitValue =
eval_sum(basis_fn, coef, order, terms, x[i]);
892 diff[i] = fitValue- y[i];
895 chi /= points - terms;
898 rmsResidual = rms_average(diff, points);
900 print_coefs(stdout, xOffset, xScaleFactor, chebyshev, coef,
901 (ySigmasValid ? coefSigma : NULL), order, terms, chi,
903 fprintf(stdout,
"unweighted rms deviation from fit: %21.15e\n",
907 fprintf(stdout,
"fit failed.\n");
909 if (evalParameters.file)
910 makeEvaluationTable(&evalParameters, x, points, coef, order, terms,
911 &SDDSin, xName, yName);
914 if (!
SDDS_StartPage(&SDDSout, rangeFitOnly ? pointsOrig : points))
916 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
919 setCoefficientData(&SDDSout, coef, ((repeatFits || ySigmasValid) ? coefSigma : NULL),
920 coefUnits, order, terms, chebyshev, fitLabelFormat,
924 compareOriginalToFit(xOrig, yOrig, &residual, pointsOrig, &rmsResidual,
932 pointsOrig, iResidual))
934 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
935 for (i = 0; i < pointsOrig; i++)
936 residual[i] = yOrig[i] - residual[i];
941 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
945 pointsOrig, ixSigma))
947 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
948 if (ySigmasValid && iySigma != -1 &&
950 pointsOrig, iySigma))
952 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
955 for (i = 0; i < points; i++)
965 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
966 for (i = 0; i < points; i++)
972 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
978 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
979 if (ySigmasValid && iySigma != -1 &&
983 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
989 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
991 &SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iRpnSequence,
992 invalid ?
"" : rpnSeqBuffer, iRmsResidual,
993 invalid ? NaN : rmsResidual, iChiSq, invalid ? NaN : chi, iTerms,
996 invalid ? NaN : xOffset, iFactor, invalid ? NaN : xScaleFactor,
997 iFitIsValid, isFit ?
'y' :
'n', -1) ||
1000 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1022 if (evalParameters.initialized && !
SDDS_Terminate(&(evalParameters.dataset)))
1023 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1032 return (EXIT_SUCCESS);
1035void print_coefs(FILE *fpo,
double xOffset,
double xScaleFactor,
long chebyshev,
1036 double *coef,
double *coefSigma, int32_t *order,
long terms,
1037 double chi,
long normTerm,
char *prepend) {
1041 fprintf(fpo,
"%s%ld-term Chebyshev T polynomial least-squares fit about "
1042 "x=%21.15e, scaled by %21.15e:\n",
1043 prepend, terms, xOffset, xScaleFactor);
1045 fprintf(fpo,
"%s%ld-term polynomial least-squares fit about x=%21.15e:\n",
1046 prepend, terms, xOffset);
1047 if (normTerm >= 0 && terms > normTerm) {
1048 if (coef[normTerm] != 0)
1049 fprintf(fpo,
"%s coefficients are normalized with factor %21.15e to "
1051 prepend, coef[normTerm], (order ? order[normTerm] : normTerm));
1053 fprintf(fpo,
"%s can't normalize coefficients as requested: a[%ld]==0\n",
1054 prepend, (order ? order[normTerm] : normTerm));
1060 for (i = 0; i < terms; i++) {
1061 fprintf(fpo,
"%sa[%ld] = %21.15e ", prepend, (order ? order[i] : i),
1062 (normTerm < 0 ? coef[i] : coef[i] / coef[normTerm]));
1065 fpo,
"+/- %21.15e\n",
1066 (normTerm < 0 ? coefSigma[i] : coefSigma[i] / fabs(coef[normTerm])));
1071 fprintf(fpo,
"%sreduced chi-squared = %21.15e\n", prepend, chi);
1074void makeFitLabel(
char *buffer,
long bufsize,
char *fitLabelFormat,
1075 double *coef,
double *coefSigma, int32_t *order,
long terms,
long chebyshev) {
1077 static char buffer1[SDDS_MAXLINE], buffer2[SDDS_MAXLINE], buffer3[SDDS_MAXLINE];
1079 sprintf(buffer,
"%s = ", ySymbol);
1080 for (i = 0; i < terms; i++) {
1084 if (order[i] == 0) {
1086 strcat(buffer1,
"+");
1087 sprintf(buffer1 + 1, fitLabelFormat, coef[i]);
1089 sprintf(buffer1, fitLabelFormat, coef[i]);
1091 strcat(buffer1,
"($sa$e");
1092 sprintf(buffer3, fitLabelFormat, coefSigma[i]);
1093 strcat(buffer1, buffer3);
1094 strcat(buffer1,
")");
1098 strcat(buffer1,
"+");
1099 sprintf(buffer1 + 1, fitLabelFormat, coef[i]);
1101 sprintf(buffer1, fitLabelFormat, coef[i]);
1103 strcat(buffer1,
"($sa$e");
1104 sprintf(buffer3, fitLabelFormat, coefSigma[i]);
1105 strcat(buffer1, buffer3);
1106 strcat(buffer1,
")");
1108 if (order[i] >= 1) {
1109 strcat(buffer1,
"*");
1110 if (chebyshev != 1) {
1111 strcat(buffer1, xSymbol);
1113 sprintf(buffer2,
"$a%d$n", order[i]);
1114 strcat(buffer1, buffer2);
1117 sprintf(buffer2,
"T$b%d$n(%s)", order[i], xSymbol);
1118 strcat(buffer1, buffer2);
1122 if ((
long)(strlen(buffer) + strlen(buffer1)) > (
long)(0.95 * bufsize)) {
1123 fprintf(stderr,
"buffer overflow making fit label!\n");
1126 strcat(buffer, buffer1);
1130double rms_average(
double *x, int64_t n) {
1134 for (i = sum2 = 0; i < n; i++)
1137 return (sqrt(sum2 / n));
1140long coefficient_index(int32_t *order,
long terms,
long order_of_interest) {
1142 for (i = 0; i < terms; i++)
1143 if (order[i] == order_of_interest)
1148void checkInputFile(
SDDS_DATASET *SDDSin,
char *xName,
char *yName,
1149 char *xSigmaName,
char *ySigmaName) {
1152 SDDS_Bomb(
"x column doesn't exist or is nonnumeric");
1156 SDDS_Bomb(
"y column doesn't exist or is nonnumeric");
1160 !(ptr =
SDDS_FindColumn(SDDSin, FIND_NUMERIC_TYPE, xSigmaName, NULL)))
1161 SDDS_Bomb(
"x sigma column doesn't exist or is nonnumeric");
1166 !(ptr =
SDDS_FindColumn(SDDSin, FIND_NUMERIC_TYPE, ySigmaName, NULL)))
1167 SDDS_Bomb(
"y sigma column doesn't exist or is nonnumeric");
1173char **initializeOutputFile(
SDDS_DATASET *SDDSout,
char *output,
1175 char *yName,
char *xSigmaName,
char *ySigmaName,
1176 long sigmasValid, int32_t *order,
long terms,
1177 long chebyshev,
long copyParameters,
long repeatFits) {
1178 char buffer[SDDS_MAXLINE], buffer1[SDDS_MAXLINE], *xUnits, *yUnits,
1193 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1205 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1207 sprintf(buffer,
"%sFit", yName);
1208 sprintf(buffer1,
"Fit[%s]", ySymbol);
1211 SDDS_SET_BY_NAME, buffer))
1212 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1214 SDDS_Bomb(
"unable to get index of just-defined fit output column");
1216 sprintf(buffer,
"%sResidual", yName);
1217 sprintf(buffer1,
"Residual[%s]", ySymbol);
1220 SDDS_SET_BY_NAME, buffer))
1221 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1224 SDDS_Bomb(
"unable to get index of just-defined residual output column");
1226 if (sigmasValid && !ySigmaName) {
1227 sprintf(buffer,
"%sSigma", yName);
1230 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1233 sprintf(buffer1,
"Sigma[%s]", ySymbol);
1235 SDDS_SET_BY_NAME, buffer))
1237 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1241 if (!(coefUnits = makeCoefficientUnits(SDDSout, xName, yName, order, terms)))
1242 SDDS_Bomb(
"unable to make coefficient units");
1245 NULL,
SDDS_LONG, 0, 1,
"FitResults") < 0 ||
1247 "Coefficient of term in fit", NULL,
SDDS_DOUBLE, 0, 1,
1248 "FitResults") < 0 ||
1249 ((sigmasValid || repeatFits) &&
1251 "[CoefficientUnits]",
1252 "Sigma of coefficient of term in fit", NULL,
1256 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1260 chebyshev ? (chebyshev == 1 ?
"Chebyshev T polynomials" :
"Converted Chebyshev T polynomials")
1261 :
"ordinary polynomials") < 0 ||
1263 SDDSout,
"ReducedChiSquared",
"$gh$r$a2$n/(N-M)", NULL,
1264 "Reduced chi-squared of fit", NULL,
SDDS_DOUBLE, NULL)) < 0 ||
1268 SDDSout,
"RmsResidual",
"$gs$r$bres$n", yUnits,
1269 "RMS residual of fit", NULL,
SDDS_DOUBLE, NULL)) < 0 ||
1272 "Probability that data is from fit function",
1275 "Rpn sequence to evaluate the fit",
1285 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1286 sprintf(buffer,
"%sOffset", xName);
1287 sprintf(buffer1,
"Offset of %s for fit", xName);
1290 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1291 sprintf(buffer,
"%sScale", xName);
1292 sprintf(buffer1,
"Scale factor of %s for fit", xName);
1295 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1300 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1303 "Number of terms in fit", NULL,
SDDS_LONG,
1305 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1310 if ((i = coefficient_index(order, terms, 0)) >= 0) {
1314 if (sigmasValid || repeatFits)
1316 SDDSout,
"InterceptSigma",
"InterceptSigma", coefUnits[i],
1317 "Sigma of intercept of fit", NULL,
SDDS_DOUBLE, NULL);
1319 if ((i = coefficient_index(order, terms, 1)) >= 0) {
1322 if (sigmasValid || repeatFits)
1324 coefUnits[i],
"Sigma of slope of fit",
1327 if ((i = coefficient_index(order, terms, 2)) >= 0) {
1331 if (sigmasValid || repeatFits)
1333 SDDSout,
"CurvatureSigma",
"CurvatureSigma", coefUnits[i],
1334 "Sigma of curvature of fit", NULL,
SDDS_DOUBLE, NULL);
1338 for (i = 0; i < terms; i++) {
1340 sprintf(s,
"Coefficient%02ld", (
long)order[i]);
1344 for (i = 0; i < terms; i++) {
1346 if (sigmasValid || repeatFits) {
1347 sprintf(s,
"Coefficient%02ldSigma", (
long)order[i]);
1356 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1358 if (copyParameters &&
1360 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1363 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1368long setCoefficientData(
SDDS_DATASET *SDDSout,
double *coef,
double *coefSigma,
1369 char **coefUnits, int32_t *order,
long terms,
long chebyshev,
1370 char *fitLabelFormat,
char *rpnSeqBuffer) {
1373 static char fitLabelBuffer[SDDS_MAXLINE];
1375 if (chebyshev != 2) {
1376 createRpnSequence(rpnSeqBuffer, SDDS_MAXLINE, coef, order, terms);
1383 coefSigma, terms)) ||
1386 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1388 termIndex = coefficient_index(order, terms, 0);
1390 if (iIntercept != -1 &&
1392 iIntercept, invalid ? NaN : coef[termIndex], -1))
1394 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1395 if (iInterceptSigma != -1 &&
1398 invalid ? NaN : coefSigma[termIndex], -1))
1400 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1402 termIndex = coefficient_index(order, terms, 1);
1405 iSlope, invalid ? NaN : coef[termIndex], -1))
1407 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1408 if (iSlopeSigma != -1 &&
1410 iSlopeSigma, invalid ? NaN : coefSigma[termIndex],
1413 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1415 termIndex = coefficient_index(order, terms, 2);
1416 if (iCurvature != -1 &&
1418 iCurvature, invalid ? NaN : coef[termIndex], -1))
1420 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1421 if (iCurvatureSigma != -1 &&
1424 invalid ? NaN : coefSigma[termIndex], -1))
1426 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1427 if (iFitLabel != -1 && !invalid) {
1428 makeFitLabel(fitLabelBuffer, SDDS_MAXLINE, fitLabelFormat, coef, coefSigma, order,
1431 iFitLabel, fitLabelBuffer, -1))
1433 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1435 for (i = 0; i < terms; i++) {
1437 iTerm[i], coef[i], -1))
1439 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1440 if (iTermSig[i] != -1)
1442 SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE,
1443 iTermSig[i], coefSigma[i], -1))
1445 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1450 double *coefC, *coefSigmaC;
1451 convertFromChebyshev(terms, order, coef, coefSigma, &termsC, &orderC, &coefC, &coefSigmaC);
1452 setCoefficientData(SDDSout, coefC, coefSigmaC, coefUnits, orderC, termsC, 0, fitLabelFormat,
1459char **makeCoefficientUnits(
SDDS_DATASET *SDDSout,
char *xName,
char *yName,
1460 int32_t *order,
long terms) {
1461 char *xUnits, *yUnits, buffer[SDDS_MAXLINE];
1462 char **coefUnits = NULL;
1469 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1471 coefUnits =
tmalloc(
sizeof(*coefUnits) * terms);
1475 for (i = 0; i < terms; i++)
1476 coefUnits[i] = yUnits;
1480 for (i = 0; i < terms; i++) {
1481 if (order[i] == 0) {
1482 if (strcmp(yUnits,
"1") != 0)
1486 }
else if (strcmp(xUnits, yUnits) == 0) {
1488 sprintf(buffer,
"1/%s$a%d$n", xUnits, order[i] - 1);
1494 sprintf(buffer,
"%s/%s$a%d$n", yUnits, xUnits, order[i]);
1496 sprintf(buffer,
"%s/%s", yUnits, xUnits);
1504void compareOriginalToFit(
double *x,
double *y,
double **residual,
1505 int64_t points,
double *rmsResidual,
double *coef,
1506 int32_t *order,
long terms) {
1508 double residualSum2, fit;
1510 *residual =
tmalloc(
sizeof(**residual) * points);
1513 for (i = 0; i < points; i++) {
1514 fit =
eval_sum(basis_fn, coef, order, terms, x[i]);
1515 (*residual)[i] = y[i] - fit;
1516 residualSum2 += sqr((*residual)[i]);
1518 *rmsResidual = sqrt(residualSum2 / points);
1522 int64_t points,
double *coef, int32_t *order,
1525 double *xEval, *yEval, delta;
1528 if (!evalParameters->initialized) {
1530 "sddspfit evaluation table",
1531 evalParameters->file) ||
1538 SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1539 evalParameters->initialized = 1;
1542 if (evalParameters->flags & EVAL_VALUESFILE_GIVEN) {
1543 if (!evalParameters->inputInitialized) {
1545 fprintf(stderr,
"error: unable to initialize %s\n", evalParameters->valuesFile);
1546 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1549 fprintf(stderr,
"error: unable to read page from %s\n", evalParameters->valuesFile);
1550 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1552 evalParameters->inputInitialized = 1;
1554 if (!(evalParameters->flags & EVAL_REUSE_PAGE_GIVEN) &&
1556 fprintf(stderr,
"error: unable to read page from %s\n", evalParameters->valuesFile);
1557 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1561 fprintf(stderr,
"error: unable to read column %s from %s\n", evalParameters->valuesColumn, evalParameters->valuesFile);
1562 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1566 if (!(evalParameters->flags & EVAL_BEGIN_GIVEN) ||
1567 !(evalParameters->flags & EVAL_END_GIVEN)) {
1570 if (!(evalParameters->flags & EVAL_BEGIN_GIVEN))
1571 evalParameters->begin = min;
1572 if (!(evalParameters->flags & EVAL_END_GIVEN))
1573 evalParameters->end = max;
1575 if (!(evalParameters->flags & EVAL_NUMBER_GIVEN))
1576 evalParameters->number = points;
1577 if (evalParameters->number > 1)
1578 delta = (evalParameters->end - evalParameters->begin) /
1579 (evalParameters->number - 1);
1583 if (!(xEval = (
double *)malloc(
sizeof(*xEval) * evalParameters->number)))
1586 for (i = 0; i < evalParameters->number; i++)
1587 xEval[i] = evalParameters->begin + i * delta;
1590 if (!(yEval = (
double *)malloc(
sizeof(*yEval) * evalParameters->number)))
1592 for (i = 0; i < evalParameters->number; i++)
1593 yEval[i] =
eval_sum(basis_fn, coef, order, terms, xEval[i]);
1595 if (!
SDDS_StartPage(&evalParameters->dataset, evalParameters->number) ||
1597 xEval, evalParameters->number, xName) ||
1599 yEval, evalParameters->number, yName) ||
1601 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1606long reviseFitOrders(
double *x,
double *y,
double *sy, int64_t points,
1607 long terms, int32_t *order,
double *coef,
1608 double *coefSigma,
double *diff,
1609 double (*basis_fn)(
double xa,
long ordera),
1610 unsigned long reviseOrders,
double xOffset,
1611 double xScaleFactor,
long normTerm,
long ySigmasValid,
1612 long chebyshev,
double revpowThreshold,
1613 double revpowCompleteThreshold,
double goodEnoughChi) {
1614 double bestChi, chi;
1615 long bestTerms, newTerms, newBest, *termUsed;
1616 int32_t *newOrder, *bestOrder;
1618 long origTerms, *origOrder;
1620 bestOrder =
tmalloc(
sizeof(*bestOrder) * terms);
1621 newOrder =
tmalloc(
sizeof(*newOrder) * terms);
1622 termUsed =
tmalloc(
sizeof(*termUsed) * terms);
1623 origOrder =
tmalloc(
sizeof(*origOrder) * terms);
1625 for (i = 0; i < terms; i++)
1626 origOrder[i] = order[i];
1627 qsort((
void *)order, terms,
sizeof(*order),
long_cmpasc);
1628 bestOrder[0] = newOrder[0] = order[0];
1630 newTerms = bestTerms = 1;
1632 if (!
lsfg(x, y, sy, points, newTerms, newOrder, coef, coefSigma, &bestChi,
1635 if (reviseOrders & REVPOW_VERBOSE) {
1636 fputs(
"fit to revise orders:", stdout);
1637 print_coefs(stdout, xOffset, xScaleFactor, chebyshev, coef,
1638 (ySigmasValid ? coefSigma : NULL), bestOrder, bestTerms,
1639 bestChi, normTerm,
"");
1640 fprintf(stdout,
"unweighted rms deviation from fit: %21.15e\n",
1641 rms_average(diff, points));
1646 newTerms = newTerms + 1;
1647 for (ip = 1; ip < terms; ip++) {
1650 newOrder[newTerms - 1] = order[ip];
1651 if (!
lsfg(x, y, sy, points, newTerms, newOrder, coef, coefSigma, &chi,
1654 if (reviseOrders & REVPOW_VERBOSE) {
1655 fputs(
"trial fit:", stdout);
1656 print_coefs(stdout, xOffset, xScaleFactor, chebyshev, coef,
1657 (ySigmasValid ? coefSigma : NULL), newOrder, newTerms,
1659 fprintf(stdout,
"unweighted rms deviation from fit: %21.15e\n",
1660 rms_average(diff, points));
1662 if ((bestChi > goodEnoughChi && chi < bestChi) ||
1663 (chi + revpowThreshold < bestChi && newTerms < bestTerms)) {
1665 bestTerms = newTerms;
1668 for (i = 0; i < newTerms; i++)
1669 bestOrder[i] = newOrder[i];
1670 if (reviseOrders & REVPOW_VERBOSE) {
1671 fputs(
"new best fit:", stdout);
1672 print_coefs(stdout, xOffset, xScaleFactor, chebyshev, coef,
1673 (ySigmasValid ? coefSigma : NULL), bestOrder, bestTerms,
1674 bestChi, normTerm,
"");
1675 fprintf(stdout,
"unweighted rms deviation from fit: %21.15e\n",
1676 rms_average(diff, points));
1681 }
while (newBest && bestChi > goodEnoughChi);
1684 for (ip = 0; ip < terms; ip++)
1685 order[ip] = bestOrder[ip];
1690 for (ip = 0; ip < terms; ip++) {
1691 for (i = j = 0; i < terms; i++) {
1693 newOrder[j++] = order[i];
1695 newTerms = terms - 1;
1696 if (!
lsfg(x, y, sy, points, newTerms, newOrder, coef, coefSigma, &chi, diff,
1699 if ((bestChi > goodEnoughChi && chi < goodEnoughChi) ||
1700 (chi + revpowThreshold < bestChi && newTerms < terms)) {
1704 for (i = 0; i < newTerms; i++)
1705 order[i] = newOrder[i];
1706 if (reviseOrders & REVPOW_VERBOSE) {
1707 fputs(
"new best fit:", stdout);
1708 print_coefs(stdout, xOffset, xScaleFactor, chebyshev, coef,
1709 (ySigmasValid ? coefSigma : NULL), order, terms,
1710 bestChi, normTerm,
"");
1711 fprintf(stdout,
"unweighted rms deviation from fit: %21.15e\n",
1712 rms_average(diff, points));
1717 }
while (newBest && terms > 1 && bestChi > goodEnoughChi);
1724 if ((reviseOrders & REVPOW_COMPLETE) && bestChi > revpowCompleteThreshold) {
1726 for (i = 0; i < origTerms; i++)
1727 order[i] = origOrder[i];
1728 if (reviseOrders & REVPOW_VERBOSE)
1729 fprintf(stdout,
"Result unsatisfactory---attempting complete trials\n");
1730 return reviseFitOrders1(x, y, sy, points, terms, order, coef, coefSigma,
1731 diff, basis_fn, reviseOrders, xOffset, xScaleFactor,
1732 normTerm, ySigmasValid, chebyshev, revpowThreshold,
1740long reviseFitOrders1(
double *x,
double *y,
double *sy, int64_t points,
1741 long terms, int32_t *order,
double *coef,
1742 double *coefSigma,
double *diff,
1743 double (*basis_fn)(
double xa,
long ordera),
1744 unsigned long reviseOrders,
double xOffset,
1745 double xScaleFactor,
long normTerm,
long ySigmasValid,
1746 long chebyshev,
double revpowThreshold,
1747 double goodEnoughChi) {
1748 double bestChi, chi;
1749 long bestTerms, newTerms;
1750 int32_t *newOrder = NULL, *bestOrder;
1752 long *counter = NULL, *counterLim = NULL;
1754 if (!(bestOrder = malloc(
sizeof(*bestOrder) * terms)) ||
1755 !(newOrder = malloc(
sizeof(*newOrder) * terms)) ||
1756 !(counter = calloc(
sizeof(*counter), terms)) ||
1757 !(counterLim = calloc(
sizeof(*counterLim), terms))) {
1758 fprintf(stderr,
"Error: memory allocation failure (%ld terms)\n", terms);
1761 for (i = 0; i < terms; i++)
1763 qsort((
void *)order, terms,
sizeof(*order),
long_cmpasc);
1765 if (!
lsfg(x, y, sy, points, 2, order, coef, coefSigma, &bestChi, diff,
1768 for (i = 0; i < 2; i++)
1769 bestOrder[i] = order[i];
1771 if (reviseOrders & REVPOW_VERBOSE) {
1772 fputs(
"starting fit to revise orders:", stdout);
1773 print_coefs(stdout, xOffset, xScaleFactor, chebyshev, coef,
1774 (ySigmasValid ? coefSigma : NULL), order, 1, bestChi, normTerm,
1776 fprintf(stdout,
"unweighted rms deviation from fit: %21.15e\n",
1777 rms_average(diff, points));
1782 for (i = j = 0; i < terms; i++) {
1784 newOrder[j++] = order[i];
1787 if (!
lsfg(x, y, sy, points, newTerms, newOrder, coef, coefSigma, &chi, diff,
1790 if ((chi < goodEnoughChi && newTerms < bestTerms) ||
1791 (bestChi > goodEnoughChi && chi < bestChi)) {
1793 bestTerms = newTerms;
1794 for (i = 0; i < newTerms; i++)
1795 bestOrder[i] = newOrder[i];
1796 if (reviseOrders & REVPOW_VERBOSE) {
1797 fputs(
"new best fit:", stdout);
1798 print_coefs(stdout, xOffset, xScaleFactor, chebyshev, coef,
1799 (ySigmasValid ? coefSigma : NULL), bestOrder, bestTerms,
1800 bestChi, normTerm,
"");
1801 fprintf(stdout,
"unweighted rms deviation from fit: %21.15e\n",
1802 rms_average(diff, points));
1808 for (ip = 0; ip < terms; ip++)
1809 order[ip] = bestOrder[ip];
1818void createRpnSequence(
char *buffer,
long bufsize,
double *coef, int32_t *order,
1820 long i, j, maxOrder;
1821 static char buffer1[SDDS_MAXLINE];
1827 for (i = 0; i < terms; i++) {
1828 if (maxOrder < order[i])
1829 maxOrder = order[i];
1831 if (maxOrder == 0) {
1832 snprintf(buffer, SDDS_MAXLINE,
"%.15e", coef[0]);
1837 snprintf(buffer, SDDS_MAXLINE,
"%le - ", offset);
1838 for (i = 2; i <= maxOrder; i++) {
1839 strcat(buffer,
"= ");
1840 if ((strlen(buffer) + 2) > bufsize) {
1841 fprintf(stderr,
"buffer overflow making rpn expression!\n");
1845 for (i = maxOrder; i >= 0; i--) {
1846 for (j = 0; j < terms; j++) {
1855 snprintf(buffer1, SDDS_MAXLINE,
"%.15g * ", coef1);
1856 else if (i == 0 && order[j] == 0) {
1858 snprintf(buffer1, SDDS_MAXLINE,
"%.15g + ", coef1);
1863 strcpy(buffer1,
"* ");
1865 snprintf(buffer1, SDDS_MAXLINE,
"%.15g + * ", coef1);
1867 if ((strlen(buffer) + strlen(buffer1)) >= bufsize) {
1868 fprintf(stderr,
"buffer overflow making rpn expression!\n");
1871 strcat(buffer, buffer1);
1879CHEBYSHEV_COEF *makeChebyshevCoefficients(
long maxOrder,
long *nPoly) {
1886 *nPoly = maxOrder + 1;
1888 coef =
tmalloc(
sizeof(*coef) * (*nPoly));
1891 coef[0].coef =
tmalloc(
sizeof(*(coef[0].coef)) * coef[0].nTerms);
1892 coef[0].coef[0] = 1;
1895 coef[1].coef =
tmalloc(
sizeof(*(coef[1].coef)) * coef[1].nTerms);
1896 coef[1].coef[0] = 0;
1897 coef[1].coef[1] = 1;
1899 for (i = 2; i < *nPoly; i++) {
1900 coef[i].nTerms = coef[i - 1].nTerms + 1;
1901 coef[i].coef = calloc(coef[i].nTerms,
sizeof(*(coef[i].coef)));
1902 for (j = 0; j < coef[i - 2].nTerms; j++)
1903 coef[i].coef[j] = -coef[i - 2].coef[j];
1904 for (j = 0; j < coef[i - 1].nTerms; j++)
1905 coef[i].coef[j + 1] += 2 * coef[i - 1].coef[j];
1920void convertFromChebyshev(
long termsT, int32_t *orderT,
double *coefT,
double *coefSigmaT,
1921 long *termsOrdinaryRet, int32_t **orderOrdinaryRet,
double **coefOrdinaryRet,
double **coefSigmaOrdinaryRet) {
1924 int32_t *orderOrdinary;
1925 double *coefOrdinary, *coefSigmaOrdinary, scale;
1927 static long nChebyCoef = 0, chebyMaxOrder = 0;
1930 for (i = 0; i < termsT; i++)
1931 if (orderT[i] > maxOrder)
1932 maxOrder = orderT[i];
1934 termsOrdinary = maxOrder + 1;
1935 orderOrdinary =
tmalloc(
sizeof(*orderOrdinary) * termsOrdinary);
1936 coefOrdinary = calloc(termsOrdinary,
sizeof(*coefOrdinary));
1938 coefSigmaOrdinary = calloc(termsOrdinary,
sizeof(*coefSigmaOrdinary));
1940 coefSigmaOrdinary = NULL;
1942 if (chebyCoef == NULL || maxOrder > chebyMaxOrder) {
1944 for (i = 0; i < nChebyCoef; i++)
1945 free(chebyCoef[i].coef);
1948 chebyCoef = makeChebyshevCoefficients(chebyMaxOrder = maxOrder, &nChebyCoef);
1951 for (i = 0; i < termsT; i++) {
1953 for (j = 0; j < chebyCoef[orderT[i]].nTerms; j++) {
1954 coefOrdinary[j] += coefT[i] * chebyCoef[i].coef[j];
1956 coefSigmaOrdinary[j] += sqr(coefSigmaT[i] * chebyCoef[i].coef[j]);
1960 for (i = 0; i < termsOrdinary; i++) {
1962 coefSigmaOrdinary[i] = sqrt(coefSigmaOrdinary[i]) /
ipow(scale, i);
1963 orderOrdinary[i] = i;
1964 coefOrdinary[i] /=
ipow(scale, i);
1966 *termsOrdinaryRet = termsOrdinary;
1967 *orderOrdinaryRet = orderOrdinary;
1968 *coefOrdinaryRet = coefOrdinary;
1969 *coefSigmaOrdinaryRet = coefSigmaOrdinary;
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
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_SetArrayVararg(SDDS_DATASET *SDDS_dataset, char *array_name, int32_t mode, void *data_pointer,...)
Sets the values of an array variable in the SDDS dataset using variable arguments for dimensions.
int32_t SDDS_SetParameters(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
int32_t SDDS_SetColumnFromDoubles(SDDS_DATASET *SDDS_dataset, int32_t mode, double *data, int64_t rows,...)
Sets the values for a single data column using double-precision floating-point numbers.
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.
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.
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_DefineArray(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, int32_t dimensions, const char *group_name)
Defines a data array within the SDDS 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_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.
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.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
int32_t SDDS_NumberOfErrors()
Retrieves the number of errors recorded by SDDS library routines.
int32_t SDDS_StringIsBlank(char *s)
Checks if a string is blank (contains only whitespace characters).
char * SDDS_FindColumn(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
Finds the first column in the SDDS dataset that matches the specified criteria.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
#define SDDS_STRING
Identifier for the string data type.
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
#define SDDS_CHARACTER
Identifier for the character data type.
#define SDDS_DOUBLE
Identifier for the double data type.
#define SDDS_LONG64
Identifier for the signed 64-bit integer data type.
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
void bomb(char *error, char *usage)
Reports error messages to the terminal and aborts the program.
long advance_counter(long *counter, long *max_count, long n_indices)
Advances the counter array based on maximum counts.
int find_min_max(double *min, double *max, double *list, int64_t n)
Finds the minimum and maximum values in a list of doubles.
double ipow(const double x, const int64_t p)
Compute x raised to the power p (x^p).
double get_argument_offset()
Get the current argument offset applied before function evaluations.
double get_argument_scale()
Get the current argument scale factor used before function evaluations.
double eval_sum(double(*fn)(double x, long ord), double *coef, int32_t *order, long n_coefs, double x0)
Evaluate a sum of basis functions.
long lsfg(double *xd, double *yd, double *sy, long n_pts, long n_terms, int32_t *order, double *coef, double *s_coef, double *chi, double *diff, double(*fn)(double x, long ord))
Computes generalized least squares fits using a function passed by the caller.
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.
void set_argument_scale(double scale)
Set the scale factor applied to the input argument of basis functions.
void set_argument_offset(double offset)
Set the offset applied to the input argument of basis functions.
double dtcheby(double x, long n)
Evaluate the derivative of the Chebyshev polynomial T_n(x).
double ipower(double x, long n)
Evaluate a power function x^n.
double dipower(double x, long n)
Evaluate the derivative of x^n.
double tcheby(double x, long n)
Evaluate the Chebyshev polynomial of the first kind T_n(x).
double ChiSqrSigLevel(double ChiSquared0, long nu)
Computes the probability that a chi-squared variable exceeds a given value.
int long_cmpasc(const void *a, const void *b)
Compare two long integers in ascending order.
char * str_tolower(char *s)
Convert a string to lower case.