262 {
263 double **y = NULL, **sy = NULL, **diff = NULL;
264 double *x = NULL, *sx = NULL;
265 double xOffset, xScaleFactor;
266 double *xOrig = NULL, **yOrig = NULL, *sxOrig = NULL, **syOrig = NULL, **sy0 = NULL;
267 long terms, normTerm, ip, ySigmasValid;
268 int64_t i, j, points, pointsOrig;
269 long symmetry, chebyshev, termsGiven;
270 double sigmas, minimumSigma;
271 long sigmasMode, sparseInterval;
272 double **coef = NULL, **coefSigma = NULL;
273 double *chi = NULL, xLow, xHigh, *rmsResidual = NULL;
274 char *xName = NULL, *yName = NULL, **yNames = NULL, *xSigmaName = NULL;
275 char **ySigmaNames = NULL, *ySigmaControlString = NULL;
276 char *input = NULL, *output = NULL;
278 long *isFit = NULL, iArg, modifySigmas, termIndex;
279 long generateSigmas, verbose, ignoreSigmas;
280 long outputInitialized, copyParameters = 0;
281 int32_t *order = NULL;
282 SCANNED_ARG *s_arg;
283 double xMin, xMax, revpowThreshold;
284 double rms_average(double *d_x, int64_t d_n);
285 char *infoFile = NULL;
286 char *fitLabelFormat = "%g";
287 static char fitLabelBuffer[SDDS_MAXLINE];
288 unsigned long pipeFlags, reviseOrders;
290 long rangeFitOnly = 0;
291
292 long colIndex;
293 long cloDependentIndex = -1, numDependentItems;
294 int32_t numYNames;
295
297 argc =
scanargs(&s_arg, argc, argv);
298 if (argc < 2 || argc > (3 + N_OPTIONS)) {
299 fprintf(stderr, "usage: %s\n", USAGE);
300 fprintf(stderr, "%s%s", additional_help, additional_help2);
301 exit(EXIT_FAILURE);
302 }
303
304 input = output = NULL;
305 xName = yName = xSigmaName = ySigmaControlString = NULL;
306 yNames = ySigmaNames = NULL;
307 numDependentItems = 0;
308 modifySigmas = reviseOrders = chebyshev = 0;
309 order = NULL;
310 symmetry = NO_SYMMETRY;
311 xMin = xMax = 0;
312 generateSigmas = 0;
313 sigmasMode = -1;
314 sigmas = 1;
315 minimumSigma = 0;
316 sparseInterval = 1;
317 terms = 2;
318 verbose = ignoreSigmas = 0;
319 normTerm = -1;
320 xOffset = 0;
321 xScaleFactor = 1;
324 pipeFlags = 0;
325 evalParameters.file = NULL;
326 infoFile = NULL;
327 termsGiven = 0;
328
329 for (iArg = 1; iArg < argc; iArg++) {
330 if (s_arg[iArg].arg_type == OPTION) {
331 switch (
match_string(s_arg[iArg].list[0], option, N_OPTIONS, 0)) {
332 case CLO_MODIFYSIGMAS:
333 modifySigmas = 1;
334 break;
335 case CLO_ORDERS:
336 if (termsGiven)
337 SDDS_Bomb(
"give -order or -terms, not both");
338 if (s_arg[iArg].n_items < 2)
340 order =
tmalloc(
sizeof(*order) * (terms = s_arg[iArg].n_items - 1));
341 for (i = 1; i < s_arg[iArg].n_items; i++) {
342 if (sscanf(s_arg[iArg].list[i], "%" SCNd32, order + i - 1) != 1)
343 SDDS_Bomb(
"unable to scan order from -orders list");
344 }
345 break;
346 case CLO_RANGE:
347 rangeFitOnly = 0;
348 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)
350 if (s_arg[iArg].n_items == 4) {
351 if (strncmp(
str_tolower(s_arg[iArg].list[3]),
"fitonly", strlen(s_arg[iArg].list[3])) == 0) {
352 rangeFitOnly = 1;
353 } else
355 }
356 break;
357 case CLO_GENERATESIGMAS:
358 generateSigmas = FLGS_GENERATESIGMAS;
359 if (s_arg[iArg].n_items > 1) {
360 if (s_arg[iArg].n_items != 2)
361 SDDS_Bomb(
"incorrect -generateSigmas synax");
362 if (strncmp(s_arg[iArg].list[1], "keepsmallest", strlen(s_arg[iArg].list[1])) == 0)
363 generateSigmas |= FLGS_KEEPSMALLEST;
364 if (strncmp(s_arg[iArg].list[1], "keeplargest", strlen(s_arg[iArg].list[1])) == 0)
365 generateSigmas |= FLGS_KEEPLARGEST;
366 if ((generateSigmas & FLGS_KEEPSMALLEST) && (generateSigmas & FLGS_KEEPLARGEST))
367 SDDS_Bomb(
"ambiguous -generateSigmas synax");
368 }
369 break;
370 case CLO_TERMS:
371 if (order)
372 SDDS_Bomb(
"give -order or -terms, not both");
373 if (s_arg[iArg].n_items != 2 || sscanf(s_arg[iArg].list[1], "%ld", &terms) != 1)
375 termsGiven = 1;
376 break;
377 case CLO_XOFFSET:
378 if (s_arg[iArg].n_items != 2 || sscanf(s_arg[iArg].list[1], "%lf", &xOffset) != 1)
380 break;
381 case CLO_SYMMETRY:
382 if (s_arg[iArg].n_items == 2) {
383 if ((symmetry =
match_string(s_arg[iArg].list[1], symmetry_options, N_SYMMETRY_OPTIONS, 0)) < 0)
384 SDDS_Bomb(
"unknown option used with -symmetry");
385 } else
387 break;
388 case CLO_SIGMAS:
389 if (s_arg[iArg].n_items != 3)
391 if (sscanf(s_arg[iArg].list[1], "%lf", &sigmas) != 1)
392 SDDS_Bomb(
"couldn't scan value for -sigmas");
393 if ((sigmasMode =
match_string(s_arg[iArg].list[2], sigmas_options, N_SIGMAS_OPTIONS, 0)) < 0)
395 break;
396 case CLO_MINSIGMA:
397 if (s_arg[iArg].n_items != 2)
398 SDDS_Bomb(
"incorrect -minimumSigma syntax");
399 if (sscanf(s_arg[iArg].list[1], "%lf", &minimumSigma) != 1)
400 SDDS_Bomb(
"couldn't scan value for -minimumSigma");
401 break;
402 case CLO_SPARSE:
403 if (s_arg[iArg].n_items != 2)
405 if (sscanf(s_arg[iArg].list[1], "%ld", &sparseInterval) != 1)
406 SDDS_Bomb(
"couldn't scan value for -sparse");
407 if (sparseInterval < 1)
409 break;
410 case CLO_VERBOSE:
411 verbose = 1;
412 break;
413 case CLO_NORMALIZE:
414 normTerm = 0;
415 if (s_arg[iArg].n_items > 2 ||
416 (s_arg[iArg].n_items == 2 && sscanf(s_arg[iArg].list[1], "%ld", &normTerm) != 1) ||
417 normTerm < 0)
419 break;
420 case CLO_REVISEORDERS:
421 revpowThreshold = 0.1;
422 s_arg[iArg].n_items -= 1;
423 if (!
scanItemList(&reviseOrders, s_arg[iArg].list + 1, &s_arg[iArg].n_items, 0,
425 "verbose", -1, NULL, 1, REVPOW_VERBOSE, NULL))
426 SDDS_Bomb(
"invalid -reviseOrders syntax");
427 reviseOrders |= REVPOW_ACTIVE;
428 revpowThreshold = fabs(revpowThreshold);
429 break;
430 case CLO_CHEBYSHEV:
431 if (s_arg[iArg].n_items > 2 ||
432 (s_arg[iArg].n_items == 2 && strncmp(s_arg[iArg].list[1], "convert", strlen(s_arg[iArg].list[1])) != 0))
434 chebyshev = s_arg[iArg].n_items;
437 break;
438 case CLO_XFACTOR:
439 if (s_arg[iArg].n_items != 2 ||
440 sscanf(s_arg[iArg].list[1], "%lf", &xScaleFactor) != 1 || xScaleFactor == 0)
442 break;
443 case CLO_INDEPENDENT:
444 if (s_arg[iArg].n_items != 2)
445 SDDS_Bomb(
"invalid -independent syntax");
446 xName = s_arg[iArg].list[1];
447 break;
448 case CLO_DEPENDENT:
449 numDependentItems = s_arg[iArg].n_items - 1;
450 cloDependentIndex = iArg;
451 if (numDependentItems < 1)
453 break;
454 case CLO_SIGMAINDEPENDENT:
455 if (s_arg[iArg].n_items != 2)
456 SDDS_Bomb(
"invalid -sigmaIndependent syntax");
457 xSigmaName = s_arg[iArg].list[1];
458 break;
459 case CLO_SIGMADEPENDENT:
460 if (s_arg[iArg].n_items != 2)
461 SDDS_Bomb(
"invalid -sigmaDependent syntax");
462 ySigmaControlString = s_arg[iArg].list[1];
463 break;
464 case CLO_FITLABELFORMAT:
465 if (s_arg[iArg].n_items != 2)
466 SDDS_Bomb(
"invalid -fitLabelFormat syntax");
467 fitLabelFormat = s_arg[iArg].list[1];
468 break;
469 case CLO_PIPE:
470 if (!
processPipeOption(s_arg[iArg].list + 1, s_arg[iArg].n_items - 1, &pipeFlags))
472 break;
473 case CLO_INFOFILE:
474 if (s_arg[iArg].n_items != 2)
476 infoFile = s_arg[iArg].list[1];
477 break;
478 case CLO_EVALUATE:
479 if (s_arg[iArg].n_items < 2)
481 evalParameters.file = s_arg[iArg].list[1];
482 s_arg[iArg].n_items -= 2;
483 s_arg[iArg].list += 2;
484 if (!
scanItemList(&evalParameters.flags, s_arg[iArg].list, &s_arg[iArg].n_items, 0,
485 "begin",
SDDS_DOUBLE, &evalParameters.begin, 1, EVAL_BEGIN_GIVEN,
486 "end",
SDDS_DOUBLE, &evalParameters.end, 1, EVAL_END_GIVEN,
487 "number",
SDDS_LONG64, &evalParameters.number, 1, EVAL_NUMBER_GIVEN, NULL))
489 break;
490 case CLO_COPYPARAMETERS:
491 copyParameters = 1;
492 break;
493 default:
494 bomb(
"unknown switch", USAGE);
495 break;
496 }
497 } else {
498 if (input == NULL)
499 input = s_arg[iArg].list[0];
500 else if (output == NULL)
501 output = s_arg[iArg].list[0];
502 else
504 }
505 }
506
508
509 if (symmetry && order)
510 SDDS_Bomb(
"can't specify both -symmetry and -orders");
511 if (!xName || !numDependentItems)
512 SDDS_Bomb(
"you must specify a column name for x and y");
513 if (modifySigmas && !xSigmaName)
514 SDDS_Bomb(
"you must specify x sigmas with -modifySigmas");
515 if (generateSigmas) {
516 if (modifySigmas)
517 SDDS_Bomb(
"you can't specify both -generateSigmas and -modifySigmas");
518 }
519 if (ySigmaControlString) {
520 if (sigmasMode != -1)
521 SDDS_Bomb(
"you can't specify both -sigmas and a y sigma name");
522 }
523 ySigmasValid = 0;
524 if (sigmasMode != -1 || generateSigmas || ySigmaControlString || modifySigmas)
525 ySigmasValid = 1;
526
527 if (normTerm >= 0 && normTerm >= terms)
528 SDDS_Bomb(
"can't normalize to that term--not that many terms");
529 if (reviseOrders && !(sigmasMode != -1 || generateSigmas || ySigmaNames))
530 SDDS_Bomb(
"can't use -reviseOrders unless a y sigma or -generateSigmas is given");
531
532 if (symmetry == EVEN_SYMMETRY) {
533 order =
tmalloc(
sizeof(*order) * terms);
534 for (i = 0; i < terms; i++)
535 order[i] = 2 * i;
536 } else if (symmetry == ODD_SYMMETRY) {
537 order =
tmalloc(
sizeof(*order) * terms);
538 for (i = 0; i < terms; i++)
539 order[i] = 2 * i + 1;
540 } else if (!order) {
541 order =
tmalloc(
sizeof(*order) * terms);
542 for (i = 0; i < terms; i++)
543 order[i] = i;
544 }
545
548 outputInitialized = 0;
549 yNames = ResolveColumnNames(&SDDSin, s_arg[cloDependentIndex].list + 1, numDependentItems, &numYNames);
550 if (ySigmaControlString != NULL)
551 ySigmaNames = GenerateYSigmaNames(ySigmaControlString, yNames, numYNames);
552
553 checkInputFile(&SDDSin, xName, yNames, xSigmaName, ySigmaNames, numYNames);
554 sy0 =
tmalloc(
sizeof(
double *) * numYNames);
555 y =
tmalloc(
sizeof(
double *) * numYNames);
556 sy =
tmalloc(
sizeof(
double *) * numYNames);
557 isFit =
tmalloc(
sizeof(
long) * numYNames);
558 chi =
tmalloc(
sizeof(
double) * numYNames);
559 coef =
tmalloc(
sizeof(
double *) * numYNames);
560 coefSigma =
tmalloc(
sizeof(
double *) * numYNames);
561 for (colIndex = 0; colIndex < numYNames; colIndex++) {
562 coef[colIndex] =
tmalloc(
sizeof(
double) * terms);
563 coefSigma[colIndex] =
tmalloc(
sizeof(
double) * terms);
564 }
565 iCoefficient =
tmalloc(
sizeof(
long) * numYNames);
566 iCoefficientSigma =
tmalloc(
sizeof(
long) * numYNames);
567 iCoefficientUnits =
tmalloc(
sizeof(
long) * numYNames);
568
571
572 continue;
573 }
575 fprintf(stderr, "error: unable to read column %s\n", xName);
577 }
578 for (i = 0; i < numYNames; i++) {
580 fprintf(stderr, "error: unable to read column %s\n", yNames[i]);
582 }
583 }
584 sx = NULL;
586 fprintf(stderr, "error: unable to read column %s\n", xSigmaName);
588 }
589 for (colIndex = 0; colIndex < numYNames; colIndex++)
590 sy0[colIndex] =
tmalloc(
sizeof(
double) * points);
591 if (ySigmaNames) {
592 for (i = 0; i < numYNames; i++) {
594 fprintf(stderr, "error: unable to read column %s\n", ySigmaNames[i]);
596 }
597 }
598 }
599
600 if (minimumSigma > 0) {
601 int64_t j;
602 for (i = 0; i < numYNames; i++) {
603 for (j = 0; j < points; j++)
604 if (sy0[i][j] < minimumSigma)
605 sy0[i][j] = minimumSigma;
606 }
607 }
608
609 if (xMin != xMax || sparseInterval != 1) {
610 xOrig =
tmalloc(
sizeof(*xOrig) * points);
611 yOrig =
tmalloc(
sizeof(*yOrig) * numYNames);
612 for (colIndex = 0; colIndex < numYNames; colIndex++)
613 yOrig[colIndex] =
tmalloc(
sizeof(
double) * points);
614 if (sx)
615 sxOrig =
tmalloc(
sizeof(*sxOrig) * points);
616 if (ySigmasValid) {
617 syOrig =
tmalloc(
sizeof(*syOrig) * numYNames);
618 for (colIndex = 0; colIndex < numYNames; colIndex++)
619 syOrig[colIndex] =
tmalloc(
sizeof(
double) * points);
620 }
621 pointsOrig = points;
622 for (i = j = 0; i < points; i++) {
623 xOrig[i] = x[i];
624 if (sx)
625 sxOrig[i] = sx[i];
626 for (colIndex = 0; colIndex < numYNames; colIndex++) {
627 yOrig[colIndex][i] = y[colIndex][i];
628 if (ySigmasValid)
629 syOrig[colIndex][i] = sy0[colIndex][i];
630 }
631 }
632 if (xMin != xMax) {
633 for (i = j = 0; i < points; i++) {
634 if (xOrig[i] <= xMax && xOrig[i] >= xMin) {
635 x[j] = xOrig[i];
636 for (colIndex = 0; colIndex < numYNames; colIndex++) {
637 y[colIndex][j] = yOrig[colIndex][i];
638 if (ySigmasValid)
639 sy0[colIndex][j] = syOrig[colIndex][i];
640 }
641 if (sx)
642 sx[j] = sxOrig[i];
643 j++;
644 }
645 }
646 points = j;
647 }
648 if (sparseInterval != 1) {
649 for (i = j = 0; i < points; i++) {
650 if (i % sparseInterval == 0) {
651 x[j] = x[i];
652 for (colIndex = 0; colIndex < numYNames; colIndex++) {
653 y[colIndex][j] = y[colIndex][i];
654 if (ySigmasValid)
655 sy0[colIndex][j] = sy0[colIndex][i];
656 }
657 if (sx)
658 sx[j] = sx[i];
659 j++;
660 }
661 }
662 points = j;
663 }
664 } else {
665 xOrig = x;
666 yOrig = y;
667 sxOrig = sx;
668 syOrig = sy0;
669 pointsOrig = points;
670 }
671
673
674 if (sigmasMode == ABSOLUTE_SIGMAS) {
675 for (colIndex = 0; colIndex < numYNames; colIndex++) {
676 for (i = 0; i < points; i++)
677 sy0[colIndex][i] = sigmas;
678 if (sy0[colIndex] != syOrig[colIndex])
679 for (i = 0; i < pointsOrig; i++)
680 syOrig[colIndex][i] = sigmas;
681 }
682 } else if (sigmasMode == FRACTIONAL_SIGMAS) {
683 for (colIndex = 0; colIndex < numYNames; colIndex++) {
684 for (i = 0; i < points; i++)
685 sy0[colIndex][i] = sigmas * fabs(y[colIndex][i]);
686 if (sy0[colIndex] != syOrig[colIndex])
687 for (i = 0; i < pointsOrig; i++)
688 syOrig[colIndex][i] = fabs(yOrig[colIndex][i]) * sigmas;
689 }
690 }
691
692 for (i = 0; i < numYNames; i++) {
693 if (minimumSigma > 0) {
694 int64_t j;
695 for (j = 0; j < points; j++)
696 if (sy0[i][j] < minimumSigma)
697 sy0[i][j] = minimumSigma;
698 }
699 }
700
701 if (!ySigmasValid || generateSigmas)
702 for (colIndex = 0; colIndex < numYNames; colIndex++) {
703 for (i = 0; i < points; i++)
704 sy0[colIndex][i] = 1;
705 }
706 else
707 for (i = 0; i < points; i++)
708 for (colIndex = 0; colIndex < numYNames; colIndex++) {
709 if (sy0[colIndex][i] == 0)
710 SDDS_Bomb(
"y sigma = 0 for one or more points.");
711 }
712
713 diff =
tmalloc(
sizeof(*diff) * numYNames);
714 sy =
tmalloc(
sizeof(*sy) * numYNames);
715 for (colIndex = 0; colIndex < numYNames; colIndex++) {
716 diff[colIndex] =
tmalloc(
sizeof(
double) * points);
717 sy[colIndex] =
tmalloc(
sizeof(
double) * points);
718 }
719
720 for (i = 0; i < points; i++) {
721 for (colIndex = 0; colIndex < numYNames; colIndex++)
722 sy[colIndex][i] = sy0[colIndex][i];
723 }
724
727 if (chebyshev) {
728 xOffset = (xHigh + xLow) / 2;
731 }
732
733 if (generateSigmas || modifySigmas) {
734
735 for (colIndex = 0; colIndex < numYNames; colIndex++) {
736 isFit[colIndex] =
lsfg(x, y[colIndex], sy[colIndex], points, terms, order, coef[colIndex], coefSigma[colIndex], &chi[colIndex], diff[colIndex], basis_fn);
737 if (!isFit[colIndex]) {
738 fprintf(stderr, "Column %s: ", yNames[colIndex]);
740 }
741 if (verbose) {
742 fprintf(stderr, "Column %s: ", yNames[colIndex]);
743 fputs("initial_fit:", stderr);
744 print_coefs(stderr, xOffset, xScaleFactor, chebyshev, coef[colIndex], NULL, order, terms, chi[colIndex], normTerm, "");
745 fprintf(stderr, "unweighted rms deviation from fit: %21.15le\n", rms_average(diff[colIndex], points));
746 }
747 if (modifySigmas) {
748 if (!ySigmasValid) {
749 for (i = 0; i < points; i++)
750 sy[colIndex][i] = fabs(
eval_sum(basis_dfn, coef[colIndex], order, terms, x[i]) * sx[i]);
751 } else
752 for (i = 0; i < points; i++) {
753 sy[colIndex][i] = sqrt(sqr(sy0[colIndex][i]) + sqr(
eval_sum(basis_dfn, coef[colIndex], order, terms, x[i]) * sx[i]));
754 }
755 }
756 if (generateSigmas) {
757 double sigma;
758 for (i = sigma = 0; i < points; i++) {
759 sigma += sqr(diff[colIndex][i]);
760 }
761 sigma = sqrt(sigma / (points - terms));
762 for (i = 0; i < points; i++) {
763 if (generateSigmas & FLGS_KEEPSMALLEST) {
764 if (sigma < sy[colIndex][i])
765 sy[colIndex][i] = sigma;
766 } else if (generateSigmas & FLGS_KEEPLARGEST) {
767 if (sigma > sy[colIndex][i])
768 sy[colIndex][i] = sigma;
769 } else {
770 sy[colIndex][i] = sigma;
771 }
772 }
773 for (i = 0; i < pointsOrig; i++) {
774 if (generateSigmas & FLGS_KEEPSMALLEST) {
775 if (sigma < sy0[colIndex][i])
776 sy0[colIndex][i] = sigma;
777 } else if (generateSigmas & FLGS_KEEPLARGEST) {
778 if (sigma > sy0[colIndex][i])
779 sy0[colIndex][i] = sigma;
780 } else {
781 sy0[colIndex][i] = sigma;
782 }
783 }
784 }
785 }
786 }
787
788 if (reviseOrders & REVPOW_ACTIVE) {
789 double bestChi;
790 long bestTerms, newBest;
791 int32_t *bestOrder;
792
793 bestTerms = terms;
794 bestOrder =
tmalloc(
sizeof(*bestOrder) * bestTerms);
795 for (ip = 0; ip < terms; ip++)
796 bestOrder[ip] = order[ip];
797
798 for (colIndex = 0; colIndex < numYNames; colIndex++) {
799 isFit[colIndex] =
lsfg(x, y[colIndex], sy[colIndex], points, bestTerms, bestOrder, coef[colIndex], coefSigma[colIndex], &bestChi, diff[colIndex], basis_fn);
800 if (!isFit[colIndex]) {
801 fprintf(stderr, "Column %s: ", yNames[colIndex]);
803 if (reviseOrders & REVPOW_VERBOSE) {
804 fprintf(stderr, "Column %s: ", yNames[colIndex]);
805 fputs("fit to revise orders:", stderr);
806 print_coefs(stderr, xOffset, xScaleFactor, chebyshev, coef[colIndex], (ySigmasValid ? coefSigma[colIndex] : NULL), bestOrder, bestTerms, bestChi, normTerm, "");
807 fprintf(stderr, "unweighted rms deviation from fit: %21.15le\n", rms_average(diff[colIndex], points));
808 }
809 }
810
811 do {
812 newBest = 0;
813 terms = bestTerms - 1;
814 for (ip = bestTerms - 1; ip >= 0; ip--) {
815 for (i = j = 0; i < bestTerms; i++)
816 if (i != ip)
817 order[j++] = bestOrder[i];
818 isFit[colIndex] =
lsfg(x, y[colIndex], sy[colIndex], points, terms, order, coef[colIndex], coefSigma[colIndex], &chi[colIndex], diff[colIndex], basis_fn);
819 if (!isFit[colIndex]) {
820 fprintf(stderr, "Column %s: ", yNames[colIndex]);
822 }
823 if (reviseOrders & REVPOW_VERBOSE) {
824 fprintf(stderr, "Column %s: ", yNames[colIndex]);
825 fputs("new trial fit:", stderr);
826 print_coefs(stderr, xOffset, xScaleFactor, chebyshev, coef[colIndex], (ySigmasValid ? coefSigma[colIndex] : NULL), order, terms, chi[colIndex], normTerm, "");
827 fprintf(stderr, "unweighted rms deviation from fit: %21.15le\n", rms_average(diff[colIndex], points));
828 }
829 if (chi[colIndex] - bestChi < revpowThreshold) {
830 bestChi = chi[colIndex];
831 bestTerms = terms;
832 newBest = 1;
833 for (i = 0; i < terms; i++)
834 bestOrder[i] = order[i];
835 if (reviseOrders & REVPOW_VERBOSE) {
836 fputs("new best fit:", stderr);
837 print_coefs(stderr, xOffset, xScaleFactor, chebyshev, coef[colIndex], (ySigmasValid ? coefSigma[colIndex] : NULL), bestOrder, bestTerms, bestChi, normTerm, "");
838 fprintf(stderr, "unweighted rms deviation from fit: %21.15le\n", rms_average(diff[colIndex], points));
839 }
840 break;
841 }
842 }
843 if (bestTerms == 1)
844 break;
845 } while (newBest);
846 terms = bestTerms;
847 for (ip = 0; ip < terms; ip++)
848 order[ip] = bestOrder[ip];
849 free(bestOrder);
850 reviseOrders = 0;
851 }
852 }
853
854 if (!outputInitialized) {
855 initializeOutputFile(&SDDSout, &SDDSoutInfo, output, infoFile, &SDDSin, input, xName, yNames, xSigmaName, ySigmaNames, ySigmasValid, order, terms, chebyshev, numYNames, copyParameters);
856 free(output);
857 outputInitialized = 1;
858 }
859 if (evalParameters.file)
860 setupEvaluationFile(&evalParameters, xName, yNames, numYNames, &SDDSin);
861
862 rmsResidual =
tmalloc(
sizeof(
double) * numYNames);
863 for (colIndex = 0; colIndex < numYNames; colIndex++) {
864 isFit[colIndex] =
lsfg(x, y[colIndex], sy[colIndex], points, terms, order, coef[colIndex], coefSigma[colIndex], &chi[colIndex], diff[colIndex], basis_fn);
865 if (isFit[colIndex]) {
866 rmsResidual[colIndex] = rms_average(diff[colIndex], points);
867 if (verbose) {
868 fprintf(stderr, "Column: %s\n", yNames[colIndex]);
869 print_coefs(stderr, xOffset, xScaleFactor, chebyshev, coef[colIndex], (ySigmasValid ? coefSigma[colIndex] : NULL), order, terms, chi[colIndex], normTerm, "");
870 fprintf(stderr, "unweighted rms deviation from fit: %21.15le\n", rmsResidual[colIndex]);
871 }
872 } else if (verbose)
873 fprintf(stderr, "fit failed for %s.\n", yNames[colIndex]);
874
875 if (evalParameters.file)
876 makeEvaluationTable(&evalParameters, x, points, coef[colIndex], order, terms, xName, yNames, numYNames, colIndex);
877 }
878
879 if (outputInitialized) {
880 if (!
SDDS_StartPage(&SDDSout, rangeFitOnly ? pointsOrig : points) ||
883 if (copyParameters) {
888 }
889 if (!
SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_INDEX, rangeFitOnly ? xOrig : x, rangeFitOnly ? pointsOrig : points, ix) ||
892 for (colIndex = 0; colIndex < numYNames; colIndex++) {
893 if (rangeFitOnly) {
894 double *residual, rmsResidual0;
895 compareOriginalToFit(xOrig, yOrig[colIndex], &residual, pointsOrig, &rmsResidual0, coef[colIndex], order, terms);
899 for (i = 0; i < pointsOrig; i++)
900 residual[i] = yOrig[colIndex][i] - residual[i];
903 free(residual);
904 } else {
905 for (i = 0; i < points; i++)
906 diff[colIndex][i] = -diff[colIndex][i];
910 for (i = 0; i < points; i++)
911 diff[colIndex][i] = y[colIndex][i] - diff[colIndex][i];
914 }
915 }
916 if (ixSigma != -1 &&
917 !
SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_INDEX, rangeFitOnly ? sxOrig : sx, rangeFitOnly ? pointsOrig : points, ixSigma))
919 for (colIndex = 0; colIndex < numYNames; colIndex++) {
920 if (ySigmasValid && iySigma[colIndex] != -1 &&
921 !
SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_INDEX, rangeFitOnly ? syOrig[colIndex] : sy[colIndex], rangeFitOnly ? pointsOrig : points, iySigma[colIndex]))
923
924 if (infoFile) {
925 termIndex = coefficient_index(order, terms, 0);
926 if (iIntercept[colIndex] != -1 &&
927 !
SDDS_SetParameters(&SDDSoutInfo, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iIntercept[colIndex], coef[colIndex][termIndex], -1))
929 if (iInterceptSigma[colIndex] != -1 &&
930 !
SDDS_SetParameters(&SDDSoutInfo, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iInterceptSigma[colIndex], coefSigma[colIndex][termIndex], -1))
932
933 termIndex = coefficient_index(order, terms, 1);
934 if (iSlope[colIndex] != -1 &&
935 !
SDDS_SetParameters(&SDDSoutInfo, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iSlope[colIndex], coef[colIndex][termIndex], -1))
937 if (iSlopeSigma[colIndex] != -1 &&
938 !
SDDS_SetParameters(&SDDSoutInfo, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iSlopeSigma[colIndex], coefSigma[colIndex][termIndex], -1))
940
941 termIndex = coefficient_index(order, terms, 2);
942 if (iCurvature[colIndex] != -1 &&
943 !
SDDS_SetParameters(&SDDSoutInfo, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iCurvature[colIndex], coef[colIndex][termIndex], -1))
945 if (iCurvatureSigma[colIndex] != -1 &&
946 !
SDDS_SetParameters(&SDDSoutInfo, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iCurvatureSigma[colIndex], coefSigma[colIndex][termIndex], -1))
948 if (iFitLabel[colIndex] != -1) {
949 makeFitLabel(fitLabelBuffer, SDDS_MAXLINE, fitLabelFormat, coef[colIndex], order, terms, colIndex);
950 if (!
SDDS_SetParameters(&SDDSoutInfo, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iFitLabel[colIndex], fitLabelBuffer, -1))
952 }
954 (ySigmasValid &&
958 iRmsResidual[colIndex], rmsResidual[colIndex], iChiSq[colIndex], chi[colIndex],
959 iTerms, terms, iSigLevel[colIndex],
ChiSqrSigLevel(chi[colIndex], points - terms),
960 iOffset, xOffset, iFactor, xScaleFactor, iFitIsValid[colIndex], isFit[colIndex] ? 'y' : 'n', -1))
962 }
963
964 termIndex = coefficient_index(order, terms, 0);
965 if (iInterceptO[colIndex] != -1 &&
966 !
SDDS_SetParameters(&SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iInterceptO[colIndex], coef[colIndex][termIndex], -1))
968 if (iInterceptSigmaO[colIndex] != -1 &&
969 !
SDDS_SetParameters(&SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iInterceptSigmaO[colIndex], coefSigma[colIndex][termIndex], -1))
971
972 termIndex = coefficient_index(order, terms, 1);
973 if (iSlopeO[colIndex] != -1 &&
974 !
SDDS_SetParameters(&SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iSlopeO[colIndex], coef[colIndex][termIndex], -1))
976 if (iSlopeSigmaO[colIndex] != -1 &&
977 !
SDDS_SetParameters(&SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iSlopeSigmaO[colIndex], coefSigma[colIndex][termIndex], -1))
979
980 termIndex = coefficient_index(order, terms, 2);
981 if (iCurvatureO[colIndex] != -1 &&
982 !
SDDS_SetParameters(&SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iCurvatureO[colIndex], coef[colIndex][termIndex], -1))
984 if (iCurvatureSigmaO[colIndex] != -1 &&
985 !
SDDS_SetParameters(&SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iCurvatureSigmaO[colIndex], coefSigma[colIndex][termIndex], -1))
987 if (iFitLabelO[colIndex] != -1) {
988 makeFitLabel(fitLabelBuffer, SDDS_MAXLINE, fitLabelFormat, coef[colIndex], order, terms, colIndex);
989 if (!
SDDS_SetParameters(&SDDSout, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iFitLabelO[colIndex], fitLabelBuffer, -1))
991 }
993 iRmsResidualO[colIndex], rmsResidual[colIndex], iChiSqO[colIndex], chi[colIndex],
994 iTermsO, terms, iSigLevelO[colIndex],
ChiSqrSigLevel(chi[colIndex], points - terms),
995 iOffsetO, xOffset, iFactorO, xScaleFactor, iFitIsValidO[colIndex], isFit[colIndex] ? 'y' : 'n', -1))
997 }
1000 }
1001 if (xOrig != x)
1002 free(xOrig);
1003 if (sxOrig != sx)
1004 free(sxOrig);
1005 free(x);
1006 free(sx);
1007 for (colIndex = 0; colIndex < numYNames; colIndex++) {
1008 free(diff[colIndex]);
1009 free(sy[colIndex]);
1010 if (yOrig[colIndex] != y[colIndex])
1011 free(yOrig[colIndex]);
1012 if (syOrig && sy0 && syOrig[colIndex] != sy0[colIndex])
1013 free(syOrig[colIndex]);
1014 free(y[colIndex]);
1015 if (sy0 && sy0[colIndex])
1016 free(sy0[colIndex]);
1017 }
1018 }
1019 return (EXIT_SUCCESS);
1020}
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_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
#define SDDS_LONG64
Identifier for the signed 64-bit integer data type.
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.
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.