99void print_coefs(FILE *fprec,
double x_offset,
double x_scale,
long chebyshev,
double *coef,
double *s_coef,
100 int32_t *order,
long n_terms,
double chi,
long norm_term,
char *prepend);
101char **makeCoefficientUnits(
SDDS_DATASET *SDDSout,
char *xName,
char *yName, int32_t *order,
long terms);
102long setCoefficientData(
SDDS_DATASET *SDDSout,
double *coef,
double *coefSigma,
char **coefUnits,
long *order,
long terms);
104 SDDS_DATASET *SDDSin,
char *input,
char *xName,
char **yNames,
char *xSigmaName,
105 char **ySigmaNames,
long sigmasValid, int32_t *order,
long terms,
long isChebyshev,
106 long numCols,
long copyParameters,
long repeatFits);
107void checkInputFile(
SDDS_DATASET *SDDSin,
char *xName,
char **yNames,
char *xSigmaName,
char **ySigmaNames,
long numYNames);
108long coefficient_index(int32_t *order,
long terms,
long order_of_interest);
109void makeFitLabel(
char *buffer,
long bufsize,
char *fitLabelFormat,
double *coef,
double *coefSigma, int32_t *order,
long terms,
long colIndex);
111char **ResolveColumnNames(
SDDS_DATASET *SDDSin,
char **wildcardList,
long length, int32_t *numYNames);
112char **GenerateYSigmaNames(
char *controlString,
char **yNames,
long numYNames);
113void RemoveElementFromStringArray(
char **array,
long index,
long length);
114char **RemoveNonNumericColumnsFromNameArray(
SDDS_DATASET *SDDSin,
char **columns, int32_t *numColumns);
115void compareOriginalToFit(
double *x,
double *y,
double **residual, int64_t points,
double *rmsResidual,
double *coef, int32_t *order,
long terms);
119double tcheby(
double x,
long n);
120double dtcheby(
double x,
long n);
121double ipower(
double x,
long n);
122double dipower(
double x,
long n);
145 CLO_SIGMAINDEPENDENT,
154char *option[N_OPTIONS] = {
183 "sddsmpfit [<inputfile>] [<outputfile>]\n"
184 " [-pipe=[input][,output]]\n"
185 " -independent=<xName>\n"
186 " -dependent=<yname1-wildcard>[,<yname2-wildcard>...]\n"
187 " [-sigmaIndependent=<xSigma>]\n"
188 " [-sigmaDependent=<ySigmaFormatString>]\n"
190 " -terms=<number> [-symmetry={none|odd|even}] | \n"
191 " -orders=<number>[,<number>...] \n"
193 " [-reviseOrders[=threshold=<value>][,verbose]]\n"
194 " [-chebyshev[=convert]]\n"
195 " [-xOffset=<value>] \n"
196 " [-xFactor=<value>]\n"
197 " [-sigmas=<value>,{absolute|fractional}] \n"
198 " [-minimumSigma=<value>]\n"
199 " [-modifySigmas] \n"
200 " [-generateSigmas={keepLargest|keepSmallest}]\n"
201 " [-repeatFits=<integer>]\n"
202 " [-sparse=<interval>] \n"
203 " [-range=<lower>,<upper>[,fitOnly]]\n"
204 " [-normalize[=<termNumber>]] \n"
206 " [-evaluate=<filename>[,begin=<value>][,end=<value>][,number=<integer>]]\n"
207 " [-fitLabelFormat=<sprintf-string>] \n"
208 " [-infoFile=<filename>]\n"
209 " [-copyParameters]\n"
210 "Program by Michael Borland, revised by Brad Dolin.\n"
211 "Compiled on " __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
"\n";
213static char *additional_help =
"\n\
214sddsmpfit does fits to the form y = SUM(i){ A[i] *P(x-x_offset, i)}, where P(x,i) is the ith basis\n\
215function evaluated at x. sddsmpfit returns the A[i] and estimates of the errors in the values.\n\
216By default P(x,i) = x^i. One can also select Chebyshev T polynomials as the basis functions.\n\n\
217-independent specify name of independent data column to use.\n\
218-dependent specify names of dependent data columns to use, using wildcards,\n\
219 separated by commas.\n\
220-sigmaIndependent specify name of independent sigma values to use\n\
221-sigmaDependent specify names of dependent sigma values to use by specifying a printf-style control\n\
222 string to generate the names from the independent variable names (e.g., %sSigma)\n\
223-terms number of terms desired in fit.\n\
224-symmetry symmetry of desired fit about x_offset.\n\
225-orders orders (P[i]) to use in fitting.\n\
226-reviseOrders the orders used in the fit are modified from the specified ones\n\
227 in order eliminate poorly-determined coefficients, based on fitting\n\
228 of the first data page.\n";
229static char *additional_help2 =
"-chebyshev use Chebyshev T polynomials (xOffset is set automatically).\n\
230 Giving the `convert' option causes the fit to be written out in\n\
231 terms of ordinary polynomials.\n\
232-xOffset desired value of x to fit about.\n\
233-xFactor desired factor to multiply x values by before fitting.\n\
234-sigmas specify absolute or fractional sigma for all points.\n\
235-minimumSigma specify minimum sigma value. If the value is less than this\n\
236 it is replaced by this value.\n\
237-modifySigmas modify the y sigmas using the x sigmas and an initial fit.\n\
238-generateSigmas generate y sigmas from the rms deviation from an initial fit.\n\
239 optionally keep the sigmas from the data if larger/smaller than rms\n\
241-repeatFits Perform repeated fits to get the coefficient sigmas (bootstrap method)\n\
242-sparse specify integer interval at which to sample data.\n\
243-range specify range of independent variable over which to perform fit and evaluation.\n\
244 If 'fitOnly' is given, then fit is compared to data over the original range.\n\
245-normalize normalize so that specified term is unity.\n\
246-evaluate specify evaluation of fit over a selected range of\n\
247 equispaced points.\n\
248-fitLabelFormat Give format string for fit labels.\n\
249-infoFile specify name of optional information file containing coefficients and fit statistics.\n\
250-copyParameters specify that parameters from input should be copied to output.\n\
251-verbose generates extra output that may be useful.\n\n";
254#define EVEN_SYMMETRY 1
255#define ODD_SYMMETRY 2
256#define N_SYMMETRY_OPTIONS 3
257char *symmetry_options[N_SYMMETRY_OPTIONS] = {
"none",
"even",
"odd"};
259#define ABSOLUTE_SIGMAS 0
260#define FRACTIONAL_SIGMAS 1
261#define N_SIGMAS_OPTIONS 2
262char *sigmas_options[N_SIGMAS_OPTIONS] = {
"absolute",
"fractional"};
264#define FLGS_GENERATESIGMAS 1
265#define FLGS_KEEPLARGEST 2
266#define FLGS_KEEPSMALLEST 4
268#define REVPOW_ACTIVE 0x0001
269#define REVPOW_VERBOSE 0x0002
271static long *iIntercept = NULL, *iInterceptO = NULL, *iInterceptSigma = NULL, *iInterceptSigmaO = NULL;
272static long *iSlope = NULL, *iSlopeO = NULL, *iSlopeSigma = NULL, *iSlopeSigmaO = NULL;
273static long *iCurvature = NULL, *iCurvatureO = NULL, *iCurvatureSigma = NULL, *iCurvatureSigmaO = NULL;
274static long iOffset = -1, iOffsetO = -1, iFactor = -1, iFactorO = -1;
275static long *iChiSq = NULL, *iChiSqO = NULL, *iRmsResidual = NULL, *iRmsResidualO = NULL, *iSigLevel = NULL, *iSigLevelO = NULL;
276static long *iFitIsValid = NULL, *iFitIsValidO = NULL, *iFitLabel = NULL, *iFitLabelO = NULL, iTerms = -1, iTermsO = -1;
278static long ix = -1, ixSigma = -1;
279static long *iy = NULL, *iySigma = NULL;
280static long *iFit = NULL, *iResidual = NULL;
282static long iOrder = -1, *iCoefficient = NULL, *iCoefficientSigma = NULL, *iCoefficientUnits = NULL;
284static char *xSymbol, **ySymbols;
286#define EVAL_BEGIN_GIVEN 0x0001U
287#define EVAL_END_GIVEN 0x0002U
288#define EVAL_NUMBER_GIVEN 0x0004U
290#define MAX_Y_SIGMA_NAME_SIZE 1024
302void makeEvaluationTable(
EVAL_PARAMETERS *evalParameters,
double *x, int64_t points,
double *coef, int32_t *order,
303 long terms,
char *xName,
char **yName,
long yNames,
long iYName);
305static double (*basis_fn)(
double xa,
long ordera);
306static double (*basis_dfn)(
double xa,
long ordera);
308int main(
int argc,
char **argv) {
309 double **y = NULL, **sy = NULL, **diff = NULL;
310 double *x = NULL, *sx = NULL;
311 double xOffset, xScaleFactor;
312 double *xOrig = NULL, **yOrig = NULL, *sxOrig = NULL, **syOrig = NULL, **sy0 = NULL;
313 long terms, normTerm, ip, ySigmasValid;
314 int64_t i, j, points, pointsOrig;
315 long symmetry, chebyshev, termsGiven;
316 double sigmas, minimumSigma;
317 long sigmasMode, sparseInterval;
318 double **coef = NULL, **coefSigma = NULL;
319 double *chi = NULL, xLow, xHigh, *rmsResidual = NULL;
320 char *xName = NULL, *yName = NULL, **yNames = NULL, *xSigmaName = NULL;
321 char **ySigmaNames = NULL, *ySigmaControlString = NULL;
322 char *input = NULL, *output = NULL;
324 long *isFit = NULL, iArg, modifySigmas, termIndex;
325 long generateSigmas, verbose, ignoreSigmas;
326 long outputInitialized, copyParameters = 0;
327 int32_t *order = NULL;
329 double xMin, xMax, revpowThreshold;
330 double rms_average(
double *d_x, int64_t d_n);
331 char *infoFile = NULL;
332 char *fitLabelFormat =
"%g";
333 static char fitLabelBuffer[SDDS_MAXLINE];
334 unsigned long pipeFlags, reviseOrders;
336 long rangeFitOnly = 0;
340 long cloDependentIndex = -1, numDependentItems;
344 argc =
scanargs(&s_arg, argc, argv);
345 if (argc < 2 || argc > (3 + N_OPTIONS)) {
346 fprintf(stderr,
"usage: %s\n", USAGE);
347 fprintf(stderr,
"%s%s", additional_help, additional_help2);
351 input = output = NULL;
352 xName = yName = xSigmaName = ySigmaControlString = NULL;
353 yNames = ySigmaNames = NULL;
354 numDependentItems = 0;
355 modifySigmas = reviseOrders = chebyshev = 0;
357 symmetry = NO_SYMMETRY;
365 verbose = ignoreSigmas = 0;
372 evalParameters.file = NULL;
376 for (iArg = 1; iArg < argc; iArg++) {
377 if (s_arg[iArg].arg_type == OPTION) {
378 switch (
match_string(s_arg[iArg].list[0], option, N_OPTIONS, 0)) {
380 if (s_arg[iArg].n_items != 2 || sscanf(s_arg[iArg].list[1],
"%ld", &repeatFits) != 1 || repeatFits < 1)
383 SDDS_Bomb(
"The number of repeats should be at least 10");
385 case CLO_MODIFYSIGMAS:
390 SDDS_Bomb(
"give -order or -terms, not both");
391 if (s_arg[iArg].n_items < 2)
393 order =
tmalloc(
sizeof(*order) * (terms = s_arg[iArg].n_items - 1));
394 for (i = 1; i < s_arg[iArg].n_items; i++) {
395 if (sscanf(s_arg[iArg].list[i],
"%" SCNd32, order + i - 1) != 1)
396 SDDS_Bomb(
"unable to scan order from -orders list");
401 if ((s_arg[iArg].n_items != 3 && s_arg[iArg].n_items != 4) || 1 != sscanf(s_arg[iArg].list[1],
"%lf", &xMin) || 1 != sscanf(s_arg[iArg].list[2],
"%lf", &xMax) || xMin >= xMax)
403 if (s_arg[iArg].n_items == 4) {
404 if (strncmp(
str_tolower(s_arg[iArg].list[3]),
"fitonly", strlen(s_arg[iArg].list[3])) == 0) {
410 case CLO_GENERATESIGMAS:
411 generateSigmas = FLGS_GENERATESIGMAS;
412 if (s_arg[iArg].n_items > 1) {
413 if (s_arg[iArg].n_items != 2)
414 SDDS_Bomb(
"incorrect -generateSigmas synax");
415 if (strncmp(s_arg[iArg].list[1],
"keepsmallest", strlen(s_arg[iArg].list[1])) == 0)
416 generateSigmas |= FLGS_KEEPSMALLEST;
417 if (strncmp(s_arg[iArg].list[1],
"keeplargest", strlen(s_arg[iArg].list[1])) == 0)
418 generateSigmas |= FLGS_KEEPLARGEST;
419 if ((generateSigmas & FLGS_KEEPSMALLEST) && (generateSigmas & FLGS_KEEPLARGEST))
420 SDDS_Bomb(
"ambiguous -generateSigmas synax");
425 SDDS_Bomb(
"give -order or -terms, not both");
426 if (s_arg[iArg].n_items != 2 || sscanf(s_arg[iArg].list[1],
"%ld", &terms) != 1)
431 if (s_arg[iArg].n_items != 2 || sscanf(s_arg[iArg].list[1],
"%lf", &xOffset) != 1)
435 if (s_arg[iArg].n_items == 2) {
436 if ((symmetry =
match_string(s_arg[iArg].list[1], symmetry_options, N_SYMMETRY_OPTIONS, 0)) < 0)
437 SDDS_Bomb(
"unknown option used with -symmetry");
442 if (s_arg[iArg].n_items != 3)
444 if (sscanf(s_arg[iArg].list[1],
"%lf", &sigmas) != 1)
445 SDDS_Bomb(
"couldn't scan value for -sigmas");
446 if ((sigmasMode =
match_string(s_arg[iArg].list[2], sigmas_options, N_SIGMAS_OPTIONS, 0)) < 0)
450 if (s_arg[iArg].n_items != 2)
451 SDDS_Bomb(
"incorrect -minimumSigma syntax");
452 if (sscanf(s_arg[iArg].list[1],
"%lf", &minimumSigma) != 1)
453 SDDS_Bomb(
"couldn't scan value for -minimumSigma");
456 if (s_arg[iArg].n_items != 2)
458 if (sscanf(s_arg[iArg].list[1],
"%ld", &sparseInterval) != 1)
459 SDDS_Bomb(
"couldn't scan value for -sparse");
460 if (sparseInterval < 1)
468 if (s_arg[iArg].n_items > 2 ||
469 (s_arg[iArg].n_items == 2 && sscanf(s_arg[iArg].list[1],
"%ld", &normTerm) != 1) ||
473 case CLO_REVISEORDERS:
474 revpowThreshold = 0.1;
475 s_arg[iArg].n_items -= 1;
476 if (!
scanItemList(&reviseOrders, s_arg[iArg].list + 1, &s_arg[iArg].n_items, 0,
478 "verbose", -1, NULL, 1, REVPOW_VERBOSE, NULL))
479 SDDS_Bomb(
"invalid -reviseOrders syntax");
480 reviseOrders |= REVPOW_ACTIVE;
481 revpowThreshold = fabs(revpowThreshold);
484 if (s_arg[iArg].n_items > 2 ||
485 (s_arg[iArg].n_items == 2 && strncmp(s_arg[iArg].list[1],
"convert", strlen(s_arg[iArg].list[1])) != 0))
487 chebyshev = s_arg[iArg].n_items;
492 if (s_arg[iArg].n_items != 2 ||
493 sscanf(s_arg[iArg].list[1],
"%lf", &xScaleFactor) != 1 || xScaleFactor == 0)
496 case CLO_INDEPENDENT:
497 if (s_arg[iArg].n_items != 2)
498 SDDS_Bomb(
"invalid -independent syntax");
499 xName = s_arg[iArg].list[1];
502 numDependentItems = s_arg[iArg].n_items - 1;
503 cloDependentIndex = iArg;
504 if (numDependentItems < 1)
507 case CLO_SIGMAINDEPENDENT:
508 if (s_arg[iArg].n_items != 2)
509 SDDS_Bomb(
"invalid -sigmaIndependent syntax");
510 xSigmaName = s_arg[iArg].list[1];
512 case CLO_SIGMADEPENDENT:
513 if (s_arg[iArg].n_items != 2)
514 SDDS_Bomb(
"invalid -sigmaDependent syntax");
515 ySigmaControlString = s_arg[iArg].list[1];
517 case CLO_FITLABELFORMAT:
518 if (s_arg[iArg].n_items != 2)
519 SDDS_Bomb(
"invalid -fitLabelFormat syntax");
520 fitLabelFormat = s_arg[iArg].list[1];
523 if (!
processPipeOption(s_arg[iArg].list + 1, s_arg[iArg].n_items - 1, &pipeFlags))
527 if (s_arg[iArg].n_items != 2)
529 infoFile = s_arg[iArg].list[1];
532 if (s_arg[iArg].n_items < 2)
534 evalParameters.file = s_arg[iArg].list[1];
535 s_arg[iArg].n_items -= 2;
536 s_arg[iArg].list += 2;
537 if (!
scanItemList(&evalParameters.flags, s_arg[iArg].list, &s_arg[iArg].n_items, 0,
538 "begin",
SDDS_DOUBLE, &evalParameters.begin, 1, EVAL_BEGIN_GIVEN,
539 "end",
SDDS_DOUBLE, &evalParameters.end, 1, EVAL_END_GIVEN,
540 "number",
SDDS_LONG64, &evalParameters.number, 1, EVAL_NUMBER_GIVEN, NULL))
543 case CLO_COPYPARAMETERS:
547 bomb(
"unknown switch", USAGE);
552 input = s_arg[iArg].list[0];
553 else if (output == NULL)
554 output = s_arg[iArg].list[0];
562 if (symmetry && order)
563 SDDS_Bomb(
"can't specify both -symmetry and -orders");
564 if (!xName || !numDependentItems)
565 SDDS_Bomb(
"you must specify a column name for x and y");
566 if (modifySigmas && !xSigmaName)
567 SDDS_Bomb(
"you must specify x sigmas with -modifySigmas");
568 if (generateSigmas) {
570 SDDS_Bomb(
"you can't specify both -generateSigmas and -modifySigmas");
572 if (ySigmaControlString) {
573 if (sigmasMode != -1)
574 SDDS_Bomb(
"you can't specify both -sigmas and a y sigma name");
577 if (sigmasMode != -1 || generateSigmas || ySigmaControlString || modifySigmas)
580 if (normTerm >= 0 && normTerm >= terms)
581 SDDS_Bomb(
"can't normalize to that term--not that many terms");
582 if (reviseOrders && !(sigmasMode != -1 || generateSigmas || ySigmaNames))
583 SDDS_Bomb(
"can't use -reviseOrders unless a y sigma or -generateSigmas is given");
585 if (symmetry == EVEN_SYMMETRY) {
586 order =
tmalloc(
sizeof(*order) * terms);
587 for (i = 0; i < terms; i++)
589 }
else if (symmetry == ODD_SYMMETRY) {
590 order =
tmalloc(
sizeof(*order) * terms);
591 for (i = 0; i < terms; i++)
592 order[i] = 2 * i + 1;
594 order =
tmalloc(
sizeof(*order) * terms);
595 for (i = 0; i < terms; i++)
601 outputInitialized = 0;
602 yNames = ResolveColumnNames(&SDDSin, s_arg[cloDependentIndex].list + 1, numDependentItems, &numYNames);
603 if (ySigmaControlString != NULL)
604 ySigmaNames = GenerateYSigmaNames(ySigmaControlString, yNames, numYNames);
606 checkInputFile(&SDDSin, xName, yNames, xSigmaName, ySigmaNames, numYNames);
607 sy0 =
tmalloc(
sizeof(
double *) * numYNames);
608 y =
tmalloc(
sizeof(
double *) * numYNames);
609 sy =
tmalloc(
sizeof(
double *) * numYNames);
610 isFit =
tmalloc(
sizeof(
long) * numYNames);
611 chi =
tmalloc(
sizeof(
double) * numYNames);
612 coef =
tmalloc(
sizeof(
double *) * numYNames);
613 coefSigma =
tmalloc(
sizeof(
double *) * numYNames);
614 for (colIndex = 0; colIndex < numYNames; colIndex++) {
615 coef[colIndex] =
tmalloc(
sizeof(
double) * terms);
616 coefSigma[colIndex] =
tmalloc(
sizeof(
double) * terms);
618 iCoefficient =
tmalloc(
sizeof(
long) * numYNames);
619 iCoefficientSigma =
tmalloc(
sizeof(
long) * numYNames);
620 iCoefficientUnits =
tmalloc(
sizeof(
long) * numYNames);
628 fprintf(stderr,
"error: unable to read column %s\n", xName);
631 for (i = 0; i < numYNames; i++) {
633 fprintf(stderr,
"error: unable to read column %s\n", yNames[i]);
639 fprintf(stderr,
"error: unable to read column %s\n", xSigmaName);
642 for (colIndex = 0; colIndex < numYNames; colIndex++)
643 sy0[colIndex] =
tmalloc(
sizeof(
double) * points);
645 for (i = 0; i < numYNames; i++) {
647 fprintf(stderr,
"error: unable to read column %s\n", ySigmaNames[i]);
653 if (minimumSigma > 0) {
655 for (i = 0; i < numYNames; i++) {
656 for (j = 0; j < points; j++)
657 if (sy0[i][j] < minimumSigma)
658 sy0[i][j] = minimumSigma;
662 if (xMin != xMax || sparseInterval != 1) {
663 xOrig =
tmalloc(
sizeof(*xOrig) * points);
664 yOrig =
tmalloc(
sizeof(*yOrig) * numYNames);
665 for (colIndex = 0; colIndex < numYNames; colIndex++)
666 yOrig[colIndex] =
tmalloc(
sizeof(
double) * points);
668 sxOrig =
tmalloc(
sizeof(*sxOrig) * points);
670 syOrig =
tmalloc(
sizeof(*syOrig) * numYNames);
671 for (colIndex = 0; colIndex < numYNames; colIndex++)
672 syOrig[colIndex] =
tmalloc(
sizeof(
double) * points);
675 for (i = j = 0; i < points; i++) {
679 for (colIndex = 0; colIndex < numYNames; colIndex++) {
680 yOrig[colIndex][i] = y[colIndex][i];
682 syOrig[colIndex][i] = sy0[colIndex][i];
686 for (i = j = 0; i < points; i++) {
687 if (xOrig[i] <= xMax && xOrig[i] >= xMin) {
689 for (colIndex = 0; colIndex < numYNames; colIndex++) {
690 y[colIndex][j] = yOrig[colIndex][i];
692 sy0[colIndex][j] = syOrig[colIndex][i];
701 if (sparseInterval != 1) {
702 for (i = j = 0; i < points; i++) {
703 if (i % sparseInterval == 0) {
705 for (colIndex = 0; colIndex < numYNames; colIndex++) {
706 y[colIndex][j] = y[colIndex][i];
708 sy0[colIndex][j] = sy0[colIndex][i];
727 if (sigmasMode == ABSOLUTE_SIGMAS) {
728 for (colIndex = 0; colIndex < numYNames; colIndex++) {
729 for (i = 0; i < points; i++)
730 sy0[colIndex][i] = sigmas;
731 if (sy0[colIndex] != syOrig[colIndex])
732 for (i = 0; i < pointsOrig; i++)
733 syOrig[colIndex][i] = sigmas;
735 }
else if (sigmasMode == FRACTIONAL_SIGMAS) {
736 for (colIndex = 0; colIndex < numYNames; colIndex++) {
737 for (i = 0; i < points; i++)
738 sy0[colIndex][i] = sigmas * fabs(y[colIndex][i]);
739 if (sy0[colIndex] != syOrig[colIndex])
740 for (i = 0; i < pointsOrig; i++)
741 syOrig[colIndex][i] = fabs(yOrig[colIndex][i]) * sigmas;
745 for (i = 0; i < numYNames; i++) {
746 if (minimumSigma > 0) {
748 for (j = 0; j < points; j++)
749 if (sy0[i][j] < minimumSigma)
750 sy0[i][j] = minimumSigma;
754 if (!ySigmasValid || generateSigmas)
755 for (colIndex = 0; colIndex < numYNames; colIndex++) {
756 for (i = 0; i < points; i++)
757 sy0[colIndex][i] = 1;
760 for (i = 0; i < points; i++)
761 for (colIndex = 0; colIndex < numYNames; colIndex++) {
762 if (sy0[colIndex][i] == 0)
763 SDDS_Bomb(
"y sigma = 0 for one or more points.");
766 diff =
tmalloc(
sizeof(*diff) * numYNames);
767 sy =
tmalloc(
sizeof(*sy) * numYNames);
768 for (colIndex = 0; colIndex < numYNames; colIndex++) {
769 diff[colIndex] =
tmalloc(
sizeof(
double) * points);
770 sy[colIndex] =
tmalloc(
sizeof(
double) * points);
773 for (i = 0; i < points; i++) {
774 for (colIndex = 0; colIndex < numYNames; colIndex++)
775 sy[colIndex][i] = sy0[colIndex][i];
781 xOffset = (xHigh + xLow) / 2;
786 if (generateSigmas || modifySigmas) {
788 for (colIndex = 0; colIndex < numYNames; colIndex++) {
789 isFit[colIndex] =
lsfg(x, y[colIndex], sy[colIndex], points, terms, order, coef[colIndex], coefSigma[colIndex], &chi[colIndex], diff[colIndex], basis_fn);
790 if (!isFit[colIndex]) {
791 fprintf(stderr,
"Column %s: ", yNames[colIndex]);
795 fprintf(stderr,
"Column %s: ", yNames[colIndex]);
796 fputs(
"initial_fit:", stderr);
797 print_coefs(stderr, xOffset, xScaleFactor, chebyshev, coef[colIndex], NULL, order, terms, chi[colIndex], normTerm,
"");
798 fprintf(stderr,
"unweighted rms deviation from fit: %21.15le\n", rms_average(diff[colIndex], points));
802 for (i = 0; i < points; i++)
803 sy[colIndex][i] = fabs(
eval_sum(basis_dfn, coef[colIndex], order, terms, x[i]) * sx[i]);
805 for (i = 0; i < points; i++) {
806 sy[colIndex][i] = sqrt(sqr(sy0[colIndex][i]) + sqr(
eval_sum(basis_dfn, coef[colIndex], order, terms, x[i]) * sx[i]));
809 if (generateSigmas) {
811 for (i = sigma = 0; i < points; i++) {
812 sigma += sqr(diff[colIndex][i]);
814 sigma = sqrt(sigma / (points - terms));
815 for (i = 0; i < points; i++) {
816 if (generateSigmas & FLGS_KEEPSMALLEST) {
817 if (sigma < sy[colIndex][i])
818 sy[colIndex][i] = sigma;
819 }
else if (generateSigmas & FLGS_KEEPLARGEST) {
820 if (sigma > sy[colIndex][i])
821 sy[colIndex][i] = sigma;
823 sy[colIndex][i] = sigma;
826 for (i = 0; i < pointsOrig; i++) {
827 if (generateSigmas & FLGS_KEEPSMALLEST) {
828 if (sigma < sy0[colIndex][i])
829 sy0[colIndex][i] = sigma;
830 }
else if (generateSigmas & FLGS_KEEPLARGEST) {
831 if (sigma > sy0[colIndex][i])
832 sy0[colIndex][i] = sigma;
834 sy0[colIndex][i] = sigma;
841 if (reviseOrders & REVPOW_ACTIVE) {
843 long bestTerms, newBest;
847 bestOrder =
tmalloc(
sizeof(*bestOrder) * bestTerms);
848 for (ip = 0; ip < terms; ip++)
849 bestOrder[ip] = order[ip];
851 for (colIndex = 0; colIndex < numYNames; colIndex++) {
852 isFit[colIndex] =
lsfg(x, y[colIndex], sy[colIndex], points, bestTerms, bestOrder, coef[colIndex], coefSigma[colIndex], &bestChi, diff[colIndex], basis_fn);
853 if (!isFit[colIndex]) {
854 fprintf(stderr,
"Column %s: ", yNames[colIndex]);
856 if (reviseOrders & REVPOW_VERBOSE) {
857 fprintf(stderr,
"Column %s: ", yNames[colIndex]);
858 fputs(
"fit to revise orders:", stderr);
859 print_coefs(stderr, xOffset, xScaleFactor, chebyshev, coef[colIndex], (ySigmasValid ? coefSigma[colIndex] : NULL), bestOrder, bestTerms, bestChi, normTerm,
"");
860 fprintf(stderr,
"unweighted rms deviation from fit: %21.15le\n", rms_average(diff[colIndex], points));
866 terms = bestTerms - 1;
867 for (ip = bestTerms - 1; ip >= 0; ip--) {
868 for (i = j = 0; i < bestTerms; i++)
870 order[j++] = bestOrder[i];
871 isFit[colIndex] =
lsfg(x, y[colIndex], sy[colIndex], points, terms, order, coef[colIndex], coefSigma[colIndex], &chi[colIndex], diff[colIndex], basis_fn);
872 if (!isFit[colIndex]) {
873 fprintf(stderr,
"Column %s: ", yNames[colIndex]);
876 if (reviseOrders & REVPOW_VERBOSE) {
877 fprintf(stderr,
"Column %s: ", yNames[colIndex]);
878 fputs(
"new trial fit:", stderr);
879 print_coefs(stderr, xOffset, xScaleFactor, chebyshev, coef[colIndex], (ySigmasValid ? coefSigma[colIndex] : NULL), order, terms, chi[colIndex], normTerm,
"");
880 fprintf(stderr,
"unweighted rms deviation from fit: %21.15le\n", rms_average(diff[colIndex], points));
882 if (chi[colIndex] - bestChi < revpowThreshold) {
883 bestChi = chi[colIndex];
886 for (i = 0; i < terms; i++)
887 bestOrder[i] = order[i];
888 if (reviseOrders & REVPOW_VERBOSE) {
889 fputs(
"new best fit:", stderr);
890 print_coefs(stderr, xOffset, xScaleFactor, chebyshev, coef[colIndex], (ySigmasValid ? coefSigma[colIndex] : NULL), bestOrder, bestTerms, bestChi, normTerm,
"");
891 fprintf(stderr,
"unweighted rms deviation from fit: %21.15le\n", rms_average(diff[colIndex], points));
900 for (ip = 0; ip < terms; ip++)
901 order[ip] = bestOrder[ip];
907 if (!outputInitialized) {
908 initializeOutputFile(&SDDSout, &SDDSoutInfo, output, infoFile, &SDDSin, input, xName, yNames, xSigmaName, ySigmaNames, ySigmasValid, order, terms, chebyshev, numYNames, copyParameters, repeatFits);
910 outputInitialized = 1;
912 if (evalParameters.file)
913 setupEvaluationFile(&evalParameters, xName, yNames, numYNames, &SDDSin);
915 rmsResidual =
tmalloc(
sizeof(
double) * numYNames);
916 for (colIndex = 0; colIndex < numYNames; colIndex++) {
918 isFit[colIndex] =
lsfg(x, y[colIndex], sy[colIndex], points, terms, order, coef[colIndex], coefSigma[colIndex], &chi[colIndex], diff[colIndex], basis_fn);
920 double *coefRepeat =
tmalloc(
sizeof(*coefRepeat) * terms * repeatFits);
921 double *coefSigmaRepeat =
tmalloc(
sizeof(*coefSigmaRepeat) * terms * repeatFits);
925 for (fitIdx = 0; fitIdx < repeatFits; fitIdx++) {
927 int64_t *indices =
tmalloc(
sizeof(*indices) * points);
928 for (i = 0; i < points; i++) indices[i] = rand() % points;
929 double *xSample =
tmalloc(
sizeof(*xSample) * points);
930 double *ySample =
tmalloc(
sizeof(*ySample) * points);
931 double *sySample =
tmalloc(
sizeof(*sySample) * points);
932 for (i = 0; i < points; i++) {
933 xSample[i] = x[indices[i]];
934 ySample[i] = y[colIndex][indices[i]];
935 sySample[i] = sy[colIndex][i];
938 double *diffTmp =
tmalloc(
sizeof(*diffTmp) * points);
939 int fitOk =
lsfg(xSample, ySample, sySample, points, terms, order, coefRepeat + fitIdx * terms, coefSigmaRepeat + fitIdx * terms, &chiTmp, diffTmp, basis_fn);
945 isFit[colIndex] *= fitOk;
948 for (i = 0; i < terms; i++) {
949 double sum = 0, sum2 = 0;
950 for (j = 0; j < repeatFits; j++) {
951 double v = coefRepeat[j * terms + i];
955 coef[colIndex][i] = sum / repeatFits;
956 coefSigma[colIndex][i] = sqrt(sum2 / repeatFits - (coef[colIndex][i] * coef[colIndex][i]));
959 free(coefSigmaRepeat);
962 for (i = 0; i < points; i++) {
963 double fitValue =
eval_sum(basis_fn, coef[colIndex], order, terms, x[i]);
964 diff[colIndex][i] = fitValue - y[colIndex][i];
965 chi[colIndex] += sqr(diff[colIndex][i]);
967 chi[colIndex] /= (points-terms);
969 if (isFit[colIndex]) {
970 rmsResidual[colIndex] = rms_average(diff[colIndex], points);
972 fprintf(stderr,
"Column: %s\n", yNames[colIndex]);
973 print_coefs(stderr, xOffset, xScaleFactor, chebyshev, coef[colIndex], (ySigmasValid ? coefSigma[colIndex] : NULL), order, terms, chi[colIndex], normTerm,
"");
974 fprintf(stderr,
"unweighted rms deviation from fit: %21.15le\n", rmsResidual[colIndex]);
977 fprintf(stderr,
"fit failed for %s.\n", yNames[colIndex]);
979 if (evalParameters.file)
980 makeEvaluationTable(&evalParameters, x, points, coef[colIndex], order, terms, xName, yNames, numYNames, colIndex);
983 if (outputInitialized) {
984 if (!
SDDS_StartPage(&SDDSout, rangeFitOnly ? pointsOrig : points) ||
987 if (copyParameters) {
993 if (!
SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_INDEX, rangeFitOnly ? xOrig : x, rangeFitOnly ? pointsOrig : points, ix) ||
996 for (colIndex = 0; colIndex < numYNames; colIndex++) {
998 double *residual, rmsResidual0;
999 compareOriginalToFit(xOrig, yOrig[colIndex], &residual, pointsOrig, &rmsResidual0, coef[colIndex], order, terms);
1003 for (i = 0; i < pointsOrig; i++)
1004 residual[i] = yOrig[colIndex][i] - residual[i];
1009 for (i = 0; i < points; i++)
1010 diff[colIndex][i] = -diff[colIndex][i];
1014 for (i = 0; i < points; i++)
1015 diff[colIndex][i] = y[colIndex][i] - diff[colIndex][i];
1020 if (ixSigma != -1 &&
1021 !
SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_INDEX, rangeFitOnly ? sxOrig : sx, rangeFitOnly ? pointsOrig : points, ixSigma))
1023 for (colIndex = 0; colIndex < numYNames; colIndex++) {
1024 if (ySigmasValid && iySigma[colIndex] != -1 &&
1025 !
SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_INDEX, rangeFitOnly ? syOrig[colIndex] : sy[colIndex], rangeFitOnly ? pointsOrig : points, iySigma[colIndex]))
1029 termIndex = coefficient_index(order, terms, 0);
1030 if (iIntercept[colIndex] != -1 &&
1031 !
SDDS_SetParameters(&SDDSoutInfo, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iIntercept[colIndex], coef[colIndex][termIndex], -1))
1033 if (iInterceptSigma[colIndex] != -1 &&
1034 !
SDDS_SetParameters(&SDDSoutInfo, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iInterceptSigma[colIndex], coefSigma[colIndex][termIndex], -1))
1037 termIndex = coefficient_index(order, terms, 1);
1038 if (iSlope[colIndex] != -1 &&
1039 !
SDDS_SetParameters(&SDDSoutInfo, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iSlope[colIndex], coef[colIndex][termIndex], -1))
1041 if (iSlopeSigma[colIndex] != -1 &&
1042 !
SDDS_SetParameters(&SDDSoutInfo, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iSlopeSigma[colIndex], coefSigma[colIndex][termIndex], -1))
1045 termIndex = coefficient_index(order, terms, 2);
1046 if (iCurvature[colIndex] != -1 &&
1047 !
SDDS_SetParameters(&SDDSoutInfo, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iCurvature[colIndex], coef[colIndex][termIndex], -1))
1049 if (iCurvatureSigma[colIndex] != -1 &&
1050 !
SDDS_SetParameters(&SDDSoutInfo, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iCurvatureSigma[colIndex], coefSigma[colIndex][termIndex], -1))
1052 if (iFitLabel[colIndex] != -1) {
1053 makeFitLabel(fitLabelBuffer, SDDS_MAXLINE, fitLabelFormat, coef[colIndex], (ySigmasValid || repeatFits)?coefSigma[colIndex]:NULL, order, terms, colIndex);
1054 if (!
SDDS_SetParameters(&SDDSoutInfo, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iFitLabel[colIndex], fitLabelBuffer, -1))
1062 iRmsResidual[colIndex], rmsResidual[colIndex], iChiSq[colIndex], chi[colIndex],
1063 iTerms, terms, iSigLevel[colIndex],
ChiSqrSigLevel(chi[colIndex], points - terms),
1064 iOffset, xOffset, iFactor, xScaleFactor, iFitIsValid[colIndex], isFit[colIndex] ?
'y' :
'n', -1))
1068 termIndex = coefficient_index(order, terms, 0);
1069 if (iInterceptO[colIndex] != -1 &&
1070 !
SDDS_SetParameters(&SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iInterceptO[colIndex], coef[colIndex][termIndex], -1))
1072 if (iInterceptSigmaO[colIndex] != -1 &&
1073 !
SDDS_SetParameters(&SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iInterceptSigmaO[colIndex], coefSigma[colIndex][termIndex], -1))
1076 termIndex = coefficient_index(order, terms, 1);
1077 if (iSlopeO[colIndex] != -1 &&
1078 !
SDDS_SetParameters(&SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iSlopeO[colIndex], coef[colIndex][termIndex], -1))
1080 if (iSlopeSigmaO[colIndex] != -1 &&
1081 !
SDDS_SetParameters(&SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iSlopeSigmaO[colIndex], coefSigma[colIndex][termIndex], -1))
1084 termIndex = coefficient_index(order, terms, 2);
1085 if (iCurvatureO[colIndex] != -1 &&
1086 !
SDDS_SetParameters(&SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iCurvatureO[colIndex], coef[colIndex][termIndex], -1))
1088 if (iCurvatureSigmaO[colIndex] != -1 &&
1089 !
SDDS_SetParameters(&SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iCurvatureSigmaO[colIndex], coefSigma[colIndex][termIndex], -1))
1091 if (iFitLabelO[colIndex] != -1) {
1092 makeFitLabel(fitLabelBuffer, SDDS_MAXLINE, fitLabelFormat, coef[colIndex], (ySigmasValid || repeatFits)?coefSigma[colIndex]:NULL, order, terms, colIndex);
1093 if (!
SDDS_SetParameters(&SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iFitLabelO[colIndex], fitLabelBuffer, -1))
1097 iRmsResidualO[colIndex], rmsResidual[colIndex], iChiSqO[colIndex], chi[colIndex],
1098 iTermsO, terms, iSigLevelO[colIndex],
ChiSqrSigLevel(chi[colIndex], points - terms),
1099 iOffsetO, xOffset, iFactorO, xScaleFactor, iFitIsValidO[colIndex], isFit[colIndex] ?
'y' :
'n', -1))
1111 for (colIndex = 0; colIndex < numYNames; colIndex++) {
1112 free(diff[colIndex]);
1114 if (yOrig[colIndex] != y[colIndex])
1115 free(yOrig[colIndex]);
1116 if (syOrig && sy0 && syOrig[colIndex] != sy0[colIndex])
1117 free(syOrig[colIndex]);
1119 if (sy0 && sy0[colIndex])
1120 free(sy0[colIndex]);
1123 return (EXIT_SUCCESS);
1126void print_coefs(FILE * fpo,
double xOffset,
double xScaleFactor,
long chebyshev,
double *coef,
double *coefSigma,
1127 int32_t *order,
long terms,
double chi,
long normTerm,
char *prepend) {
1131 fprintf(fpo,
"%s%ld-term Chebyshev T polynomial least-squares fit about x=%21.15le, scaled by %21.15le:\n", prepend, terms, xOffset, xScaleFactor);
1133 fprintf(fpo,
"%s%ld-term polynomial least-squares fit about x=%21.15le:\n", prepend, terms, xOffset);
1134 if (normTerm >= 0 && terms > normTerm) {
1135 if (coef[normTerm] != 0)
1136 fprintf(fpo,
"%s coefficients are normalized with factor %21.15le to make a[%ld]==1\n", prepend, coef[normTerm], (order ? order[normTerm] : normTerm));
1138 fprintf(fpo,
"%s can't normalize coefficients as requested: a[%ld]==0\n", prepend, (order ? order[normTerm] : normTerm));
1144 for (i = 0; i < terms; i++) {
1145 fprintf(fpo,
"%sa[%ld] = %21.15le ", prepend, (order ? order[i] : i), (normTerm < 0 ? coef[i] : coef[i] / coef[normTerm]));
1147 fprintf(fpo,
"+/- %21.15le\n", (normTerm < 0 ? coefSigma[i] : coefSigma[i] / fabs(coef[normTerm])));
1152 fprintf(fpo,
"%sreduced chi-squared = %21.15le\n", prepend, chi);
1155void RemoveElementFromStringArray(
char **array,
long index,
long length) {
1158 for (lh = index; lh < length - 1; lh++)
1159 array[lh] = array[lh + 1];
1162char **RemoveNonNumericColumnsFromNameArray(
SDDS_DATASET * SDDSin,
char **columns, int32_t *numColumns) {
1163 long i, numNumericColumns = *numColumns;
1165 for (i = 0; i < *numColumns; i++) {
1167 printf(
"Removing %s because not a numeric type.\n", columns[i]);
1168 RemoveElementFromStringArray(columns, i, *numColumns);
1169 numNumericColumns--;
1173 *numColumns = numNumericColumns;
1177char **ResolveColumnNames(
SDDS_DATASET * SDDSin,
char **wildcardList,
long length, int32_t *numYNames) {
1183 for (i = 0; i < length; i++) {
1188 bomb(
"Error matching columns in ResolveColumnNames: No matches.", NULL);
1190 result = RemoveNonNumericColumnsFromNameArray(SDDSin, result, numYNames);
1194char **GenerateYSigmaNames(
char *controlString,
char **yNames,
long numYNames) {
1196 char **result, sigmaName[MAX_Y_SIGMA_NAME_SIZE];
1198 result =
tmalloc(
sizeof(
char *) * numYNames);
1199 for (i = 0; i < numYNames; i++) {
1200 sprintf(sigmaName, controlString, yNames[i]);
1201 nameLength = strlen(sigmaName);
1202 result[i] =
tmalloc(
sizeof(
char) * (nameLength + 1));
1203 strcpy(result[i], sigmaName);
1208void makeFitLabel(
char *buffer,
long bufsize,
char *fitLabelFormat,
double *coef,
double *coefSigma, int32_t *order,
long terms,
long colIndex) {
1210 static char buffer1[SDDS_MAXLINE], buffer2[SDDS_MAXLINE], buffer3[SDDS_MAXLINE];
1212 sprintf(buffer,
"%s = ", ySymbols[colIndex]);
1213 for (i = 0; i < terms; i++) {
1214 if (order[i] == 0) {
1215 sprintf(buffer1, fitLabelFormat, coef[i]);
1217 strcat(buffer1,
"($sa$e");
1218 sprintf(buffer3, fitLabelFormat, coefSigma[i]);
1219 strcat(buffer1, buffer3);
1220 strcat(buffer1,
")");
1224 strcpy(buffer1,
" +");
1225 sprintf(buffer1 + 2, fitLabelFormat, coef[i]);
1227 sprintf(buffer1, fitLabelFormat, coef[i]);
1229 strcat(buffer1,
"($sa$e");
1230 sprintf(buffer3, fitLabelFormat, coefSigma[i]);
1231 strcat(buffer1, buffer3);
1232 strcat(buffer1,
")");
1234 strcat(buffer1,
"*");
1235 strcat(buffer1, xSymbol);
1237 sprintf(buffer2,
"$a%" PRId32
"$n", order[i]);
1238 strcat(buffer1, buffer2);
1241 if ((
long)(strlen(buffer) + strlen(buffer1)) > (
long)(0.95 * bufsize)) {
1242 fprintf(stderr,
"buffer overflow making fit label!\n");
1245 strcat(buffer, buffer1);
1249double rms_average(
double *x, int64_t n) {
1253 for (i = sum2 = 0; i < n; i++)
1256 return (sqrt(sum2 / n));
1259long coefficient_index(int32_t * order,
long terms,
long order_of_interest) {
1261 for (i = 0; i < terms; i++)
1262 if (order[i] == order_of_interest)
1267void checkInputFile(
SDDS_DATASET * SDDSin,
char *xName,
char **yNames,
char *xSigmaName,
char **ySigmaNames,
long numYNames) {
1272 SDDS_Bomb(
"x column doesn't exist or is nonnumeric");
1278 if (xSigmaName && !(ptr =
SDDS_FindColumn(SDDSin, FIND_NUMERIC_TYPE, xSigmaName, NULL)))
1279 SDDS_Bomb(
"x sigma column doesn't exist or is nonnumeric");
1284 for (i = 0; i < numYNames; i++) {
1286 if (!(ptr =
SDDS_FindColumn(SDDSin, FIND_NUMERIC_TYPE, ySigmaNames[i], NULL)))
1287 SDDS_Bomb(
"y sigma column doesn't exist or is nonnumeric");
1295 SDDS_DATASET *SDDSin,
char *input,
char *xName,
char **yNames,
char *xSigmaName,
1296 char **ySigmaNames,
long sigmasValid, int32_t *order,
long terms,
long isChebyshev,
1297 long numCols,
long copyParameters,
long repeatFits) {
1298 char buffer[SDDS_MAXLINE], buffer1[SDDS_MAXLINE], buffer2[SDDS_MAXLINE], buffer3[SDDS_MAXLINE];
1299 char *xUnits, *yUnits, ***coefUnits;
1304 coefUnits =
tmalloc(
sizeof(
char **) * numCols);
1305 ySymbols =
tmalloc(
sizeof(
char *) * numCols);
1306 iIntercept =
tmalloc(
sizeof(
long) * numCols);
1307 iInterceptO =
tmalloc(
sizeof(
long) * numCols);
1308 iInterceptSigma =
tmalloc(
sizeof(
long) * numCols);
1309 iInterceptSigmaO =
tmalloc(
sizeof(
long) * numCols);
1310 iSlope =
tmalloc(
sizeof(
long) * numCols);
1311 iSlopeO =
tmalloc(
sizeof(
long) * numCols);
1312 iSlopeSigma =
tmalloc(
sizeof(
long) * numCols);
1313 iSlopeSigmaO =
tmalloc(
sizeof(
long) * numCols);
1314 iCurvature =
tmalloc(
sizeof(
long) * numCols);
1315 iCurvatureO =
tmalloc(
sizeof(
long) * numCols);
1316 iCurvatureSigma =
tmalloc(
sizeof(
long) * numCols);
1317 iCurvatureSigmaO =
tmalloc(
sizeof(
long) * numCols);
1318 iChiSq =
tmalloc(
sizeof(
long) * numCols);
1319 iChiSqO =
tmalloc(
sizeof(
long) * numCols);
1320 iRmsResidual =
tmalloc(
sizeof(
long) * numCols);
1321 iRmsResidualO =
tmalloc(
sizeof(
long) * numCols);
1322 iSigLevel =
tmalloc(
sizeof(
long) * numCols);
1323 iSigLevelO =
tmalloc(
sizeof(
long) * numCols);
1324 iFitIsValid =
tmalloc(
sizeof(
long) * numCols);
1325 iFitIsValidO =
tmalloc(
sizeof(
long) * numCols);
1326 iFitLabel =
tmalloc(
sizeof(
long) * numCols);
1327 iFitLabelO =
tmalloc(
sizeof(
long) * numCols);
1328 iy =
tmalloc(
sizeof(
long) * numCols);
1329 iySigma =
tmalloc(
sizeof(
long) * numCols);
1330 iFit =
tmalloc(
sizeof(
long) * numCols);
1331 iResidual =
tmalloc(
sizeof(
long) * numCols);
1333 for (colIndex = 0; colIndex < numCols; colIndex++) {
1334 ySymbols[colIndex] = NULL;
1335 coefUnits[colIndex] =
tmalloc(
sizeof(
char *) * terms);
1336 iInterceptSigma[colIndex] = -1;
1337 iInterceptSigmaO[colIndex] = -1;
1338 iIntercept[colIndex] = -1;
1339 iInterceptO[colIndex] = -1;
1340 iInterceptSigma[colIndex] = -1;
1341 iInterceptSigmaO[colIndex] = -1;
1342 iSlope[colIndex] = -1;
1343 iSlopeO[colIndex] = -1;
1344 iSlopeSigma[colIndex] = -1;
1345 iSlopeSigmaO[colIndex] = -1;
1346 iCurvature[colIndex] = -1;
1347 iCurvatureO[colIndex] = -1;
1348 iCurvatureSigma[colIndex] = -1;
1349 iCurvatureSigmaO[colIndex] = -1;
1350 iChiSq[colIndex] = -1;
1351 iChiSqO[colIndex] = -1;
1352 iRmsResidual[colIndex] = -1;
1353 iRmsResidualO[colIndex] = -1;
1354 iSigLevel[colIndex] = -1;
1355 iSigLevelO[colIndex] = -1;
1356 iFitIsValid[colIndex] = -1;
1357 iFitIsValidO[colIndex] = -1;
1358 iFitLabel[colIndex] = -1;
1359 iFitLabelO[colIndex] = -1;
1361 iySigma[colIndex] = -1;
1362 iFit[colIndex] = -1;
1363 iResidual[colIndex] = -1;
1366 if (!
SDDS_InitializeOutput(SDDSout, SDDS_BINARY, 0, NULL,
"sddsmpfit output: fitted data", output) ||
1370 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1372 for (colIndex = 0; colIndex < numCols; colIndex++) {
1376 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1380 for (colIndex = 0; colIndex < numCols; colIndex++)
1382 ySymbols[colIndex] = yNames[colIndex];
1384 for (colIndex = 0; colIndex < numCols; colIndex++) {
1392 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1394 for (colIndex = 0; colIndex < numCols; colIndex++) {
1395 sprintf(buffer,
"%sFit", yNames[colIndex]);
1396 sprintf(buffer1,
"Fit[%s]", ySymbols[colIndex]);
1399 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1401 SDDS_Bomb(
"unable to get index of just-defined fit output column");
1403 sprintf(buffer,
"%sResidual", yNames[colIndex]);
1404 sprintf(buffer1,
"Residual[%s]", ySymbols[colIndex]);
1407 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1409 SDDS_Bomb(
"unable to get index of just-defined residual output column");
1411 if (sigmasValid && !ySigmaNames) {
1412 sprintf(buffer,
"%sSigma", yNames[colIndex]);
1414 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1417 sprintf(buffer1,
"Sigma[%s]", ySymbols[colIndex]);
1419 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1423 if (!(coefUnits[colIndex] = makeCoefficientUnits(SDDSout, xName, yNames[colIndex], order, terms)))
1424 SDDS_Bomb(
"unable to make coefficient units");
1427 if (outputInfo && !
SDDS_InitializeOutput(SDDSoutInfo, SDDS_BINARY, 0, NULL,
"sddsmpfit output: fit information", outputInfo))
1428 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1432 SDDS_DefineParameter(SDDSoutInfo,
"Basis", NULL, NULL,
"Function basis for fit", NULL,
SDDS_STRING, isChebyshev ?
"Chebyshev T polynomials" :
"ordinary polynomials") < 0)
1433 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1436 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1439 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1440 sprintf(buffer,
"%sOffset", xName);
1441 sprintf(buffer1,
"Offset of %s for fit", xName);
1443 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1444 sprintf(buffer,
"%sScale", xName);
1445 sprintf(buffer1,
"Scale factor of %s for fit", xName);
1447 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1449 for (colIndex = 0; colIndex < numCols; colIndex++) {
1451 sprintf(buffer1,
"%sCoefficient", yNames[colIndex]);
1452 sprintf(buffer2,
"%sCoefficientSigma", yNames[colIndex]);
1453 sprintf(buffer3,
"%sCoefficientUnits", yNames[colIndex]);
1456 ((sigmasValid || repeatFits) &&
SDDS_DefineColumn(SDDSoutInfo, buffer2,
"$gs$r$ba$n",
"[CoefficientUnits]",
"sigma of coefficient of term in fit", NULL,
SDDS_DOUBLE, 0) < 0))
1457 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1464 sprintf(buffer1,
"%sReducedChiSquared", yNames[colIndex]);
1465 sprintf(buffer2,
"%sRmsResidual", yNames[colIndex]);
1466 sprintf(buffer3,
"%sSignificanceLevel", yNames[colIndex]);
1469 "Reduced chi-squared of fit",
1472 (iRmsResidual[colIndex] =
1474 (iSigLevel[colIndex] =
SDDS_DefineParameter(SDDSoutInfo, buffer3, NULL, NULL,
"Probability that data is from fit function", NULL,
SDDS_DOUBLE, NULL)) < 0)
1475 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1479 sprintf(buffer,
"%sFitIsValid", yNames[colIndex]);
1481 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1485 sprintf(buffer,
"%sSddsmpfitlabel", yNames[colIndex]);
1487 if ((i = coefficient_index(order, terms, 0)) >= 0) {
1488 sprintf(buffer,
"%sIntercept", yNames[colIndex]);
1490 sprintf(buffer,
"%sInterceptSigma", yNames[colIndex]);
1491 if (sigmasValid || repeatFits)
1492 iInterceptSigma[colIndex] =
SDDS_DefineParameter(SDDSoutInfo, buffer, buffer, coefUnits[colIndex][i],
"Sigma of intercept of fit", NULL,
SDDS_DOUBLE, NULL);
1494 sprintf(buffer,
"%sSlope", yNames[colIndex]);
1495 if ((i = coefficient_index(order, terms, 1)) >= 0) {
1497 if (sigmasValid || repeatFits) {
1498 sprintf(buffer,
"%sSlopeSigma", yNames[colIndex]);
1502 if ((i = coefficient_index(order, terms, 2)) >= 0) {
1503 sprintf(buffer,
"%sCurvature", yNames[colIndex]);
1505 if (sigmasValid || repeatFits) {
1506 sprintf(buffer,
"%sCurvatureSigma", yNames[colIndex]);
1507 iCurvatureSigma[colIndex] =
SDDS_DefineParameter(SDDSoutInfo, buffer, buffer, coefUnits[colIndex][i],
"Sigma of curvature of fit", NULL,
SDDS_DOUBLE, NULL);
1511 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1516 if (
SDDS_DefineParameter(SDDSout,
"Basis", NULL, NULL,
"Function basis for fit", NULL,
SDDS_STRING, isChebyshev ?
"Chebyshev T polynomials" :
"ordinary polynomials") < 0)
1517 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1520 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1523 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1524 sprintf(buffer,
"%sOffset", xName);
1525 sprintf(buffer1,
"Offset of %s for fit", xName);
1527 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1528 sprintf(buffer,
"%sScale", xName);
1529 sprintf(buffer1,
"Scale factor of %s for fit", xName);
1531 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1533 for (colIndex = 0; colIndex < numCols; colIndex++) {
1535 sprintf(buffer1,
"%sReducedChiSquared", yNames[colIndex]);
1536 sprintf(buffer2,
"%sRmsResidual", yNames[colIndex]);
1537 sprintf(buffer3,
"%sSignificanceLevel", yNames[colIndex]);
1540 "Reduced chi-squared of fit",
1543 (iRmsResidualO[colIndex] =
1545 (iSigLevelO[colIndex] =
SDDS_DefineParameter(SDDSout, buffer3, NULL, NULL,
"Probability that data is from fit function", NULL,
SDDS_DOUBLE, NULL)) < 0)
1546 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1550 sprintf(buffer,
"%sFitIsValid", yNames[colIndex]);
1552 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1555 sprintf(buffer,
"%sSddsmpfitlabel", yNames[colIndex]);
1557 if ((i = coefficient_index(order, terms, 0)) >= 0) {
1558 sprintf(buffer,
"%sIntercept", yNames[colIndex]);
1560 sprintf(buffer,
"%sInterceptSigma", yNames[colIndex]);
1561 if (sigmasValid || repeatFits)
1562 iInterceptSigmaO[colIndex] =
SDDS_DefineParameter(SDDSout, buffer, buffer, coefUnits[colIndex][i],
"Sigma of intercept of fit", NULL,
SDDS_DOUBLE, NULL);
1564 sprintf(buffer,
"%sSlope", yNames[colIndex]);
1565 if ((i = coefficient_index(order, terms, 1)) >= 0) {
1567 if (sigmasValid || repeatFits) {
1568 sprintf(buffer,
"%sSlopeSigma", yNames[colIndex]);
1572 if ((i = coefficient_index(order, terms, 2)) >= 0) {
1573 sprintf(buffer,
"%sCurvature", yNames[colIndex]);
1575 if (sigmasValid || repeatFits) {
1576 sprintf(buffer,
"%sCurvatureSigma", yNames[colIndex]);
1577 iCurvatureSigmaO[colIndex] =
SDDS_DefineParameter(SDDSout, buffer, buffer, coefUnits[colIndex][i],
"Sigma of curvature of fit", NULL,
SDDS_DOUBLE, NULL);
1581 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1585 if (copyParameters) {
1587 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1589 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1593 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1598char **makeCoefficientUnits(
SDDS_DATASET * SDDSout,
char *xName,
char *yName, int32_t *order,
long terms) {
1599 char *xUnits, *yUnits, buffer[SDDS_MAXLINE];
1600 char **coefUnits = NULL;
1605 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1607 coefUnits =
tmalloc(
sizeof(*coefUnits) * terms);
1611 for (i = 0; i < terms; i++)
1612 coefUnits[i] = yUnits;
1616 for (i = 0; i < terms; i++) {
1617 if (order[i] == 0) {
1618 if (strcmp(yUnits,
"1") != 0)
1622 }
else if (strcmp(xUnits, yUnits) == 0) {
1624 sprintf(buffer,
"1/%s$a%" PRId32
"$n", xUnits, order[i] - 1);
1630 sprintf(buffer,
"%s/%s$a%" PRId32
"$n", yUnits, xUnits, order[i]);
1632 sprintf(buffer,
"%s/%s", yUnits, xUnits);
1643 SDDSout = &evalParameters->dataset;
1644 if (!
SDDS_InitializeOutput(SDDSout, SDDS_BINARY, 0, NULL,
"sddsmpfit output: evaluation of fits", evalParameters->file) ||
1646 SDDS_Bomb(
"Problem setting up evaluation file");
1647 for (i = 0; i < yNames; i++)
1649 SDDS_Bomb(
"Problem setting up evaluation file");
1651 SDDS_Bomb(
"Problem setting up evaluation file");
1654void makeEvaluationTable(
EVAL_PARAMETERS * evalParameters,
double *x, int64_t points,
double *coef, int32_t *order,
long terms,
1655 char *xName,
char **yName,
long yNames,
long iYName) {
1656 static double *xEval = NULL, *yEval = NULL;
1657 static int64_t maxEvals = 0;
1661 if (!(evalParameters->flags & EVAL_BEGIN_GIVEN) || !(evalParameters->flags & EVAL_END_GIVEN)) {
1664 if (!(evalParameters->flags & EVAL_BEGIN_GIVEN))
1665 evalParameters->begin = min;
1666 if (!(evalParameters->flags & EVAL_END_GIVEN))
1667 evalParameters->end = max;
1669 if (!(evalParameters->flags & EVAL_NUMBER_GIVEN))
1670 evalParameters->number = points;
1671 if (evalParameters->number > 1)
1672 delta = (evalParameters->end - evalParameters->begin) / (evalParameters->number - 1);
1676 if (!xEval || maxEvals < evalParameters->number) {
1677 if (!(xEval = (
double *)
SDDS_Realloc(xEval,
sizeof(*xEval) * evalParameters->number)) ||
1678 !(yEval = (
double *)
SDDS_Realloc(yEval,
sizeof(*yEval) * evalParameters->number)))
1680 maxEvals = evalParameters->number;
1683 for (i = 0; i < evalParameters->number; i++) {
1684 xEval[i] = evalParameters->begin + i * delta;
1685 yEval[i] =
eval_sum(basis_fn, coef, order, terms, xEval[i]);
1689 !
SDDS_StartPage(&evalParameters->dataset, evalParameters->number)) ||
1692 (iYName == yNames - 1 && !
SDDS_WritePage(&evalParameters->dataset)))
1693 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
1696void compareOriginalToFit(
double *x,
double *y,
double **residual, int64_t points,
double *rmsResidual,
double *coef, int32_t *order,
long terms) {
1698 double residualSum2, fit;
1700 *residual =
tmalloc(
sizeof(**residual) * points);
1703 for (i = 0; i < points; i++) {
1704 fit =
eval_sum(basis_fn, coef, order, terms, x[i]);
1705 (*residual)[i] = y[i] - fit;
1706 residualSum2 += sqr((*residual)[i]);
1708 *rmsResidual = sqrt(residualSum2 / points);
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_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_SetColumnFromLongs(SDDS_DATASET *SDDS_dataset, int32_t mode, int32_t *data, int64_t rows,...)
Sets the values for a single data column using long integer 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_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_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.
int32_t SDDS_CheckColumn(SDDS_DATASET *SDDS_dataset, char *name, char *units, int32_t type, FILE *fp_message)
Checks if a column exists in the SDDS dataset with the specified name, units, and type.
char ** SDDS_GetColumnNames(SDDS_DATASET *SDDS_dataset, int32_t *number)
Retrieves the names of all columns 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.
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
#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_ANY_NUMERIC_TYPE
Special identifier used by SDDS_Check*() routines to accept any numeric 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.
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 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.
double dtcheby(double x, long n)
Evaluate the derivative of the Chebyshev polynomial T_n(x).
void set_argument_offset(double offset)
Set the offset applied to the input argument of basis functions.
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.
char * str_tolower(char *s)
Convert a string to lower case.