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