265 {
266 double **y = NULL, **yFit = NULL, **sy = NULL, **diff = NULL;
267 double *x = NULL, *sx = NULL;
268 double xOffset, xScaleFactor;
269 double *xOrig = NULL, **yOrig = NULL, **yFitOrig = NULL, *sxOrig = NULL, **syOrig = NULL, **sy0 = NULL;
270 long coeffs, breaks, normTerm, ySigmasValid;
271 long orderGiven, coeffsGiven, breaksGiven;
272 int64_t i, j, points, pointsOrig;
273 double sigmas;
274 long sigmasMode, sparseInterval;
275 double *chi = NULL, xLow, xHigh, *rmsResidual = NULL;
276 char *xName = NULL, *yName = NULL, **yNames = NULL, *xSigmaName = NULL;
277 char **ySigmaNames = NULL, *ySigmaControlString = NULL;
278 char *input = NULL, *output = NULL;
280 long *isFit = NULL, iArg, modifySigmas;
281 long generateSigmas, verbose, ignoreSigmas;
282 long outputInitialized, copyParameters = 0;
283 long int order;
284 SCANNED_ARG *s_arg;
285 double xMin, xMax, revpowThreshold;
286 double rms_average(double *d_x, int64_t d_n);
287 char *infoFile = NULL;
288 unsigned long pipeFlags, reviseOrders;
290 long rangeFitOnly = 0;
291
292 long colIndex;
293 long cloDependentIndex = -1, numDependentItems;
294 int32_t numYNames;
295
296
297 gsl_bspline_workspace *bw;
298 gsl_vector *B;
299 gsl_vector *c, *yGsl, *wGsl;
300 gsl_matrix *X, *cov;
301 gsl_multifit_linear_workspace *mw;
302 long degreesOfFreedom;
303 double totalSumSquare, Rsq;
304
306 argc =
scanargs(&s_arg, argc, argv);
307 if (argc < 2 || argc > (3 + N_OPTIONS)) {
308 fprintf(stderr, "usage: %s\n", USAGE);
309 fprintf(stderr, "%s%s", additional_help, additional_help2);
310 exit(EXIT_FAILURE);
311 }
312
313 input = output = NULL;
314 xName = yName = xSigmaName = ySigmaControlString = NULL;
315 yNames = ySigmaNames = NULL;
316 numDependentItems = 0;
317 modifySigmas = reviseOrders = 0;
318
319 coeffs = 8;
320 xMin = xMax = 0;
321 generateSigmas = 0;
322 sigmasMode = -1;
323 sigmas = 1;
324 sparseInterval = 1;
325 verbose = ignoreSigmas = 0;
326 normTerm = -1;
327 xOffset = 0;
328 xScaleFactor = 1;
329 pipeFlags = 0;
330 evalParameters.file = NULL;
331 infoFile = NULL;
332 orderGiven = 0;
333 coeffsGiven = 0;
334 breaksGiven = 0;
335
336 for (iArg = 1; iArg < argc; iArg++) {
337 if (s_arg[iArg].arg_type == OPTION) {
338 switch (
match_string(s_arg[iArg].list[0], option, N_OPTIONS, 0)) {
339 case CLO_MODIFYSIGMAS:
340 modifySigmas = 1;
341 break;
342 case CLO_ORDER:
343 if (s_arg[iArg].n_items != 2 || sscanf(s_arg[iArg].list[1], "%ld", &order) != 1)
345 orderGiven = 1;
346 break;
347 case CLO_COEFFICIENTS:
348 if (s_arg[iArg].n_items != 2 || sscanf(s_arg[iArg].list[1], "%ld", &coeffs) != 1)
349 SDDS_Bomb(
"invalid -coefficients syntax");
350 coeffsGiven = 1;
351 break;
352 case CLO_BREAKPOINTS:
353 if (s_arg[iArg].n_items != 2 || sscanf(s_arg[iArg].list[1], "%ld", &breaks) != 1)
354 SDDS_Bomb(
"invalid -breakpoints syntax");
355 breaksGiven = 1;
356 break;
357 case CLO_RANGE:
358 rangeFitOnly = 0;
359 if ((s_arg[iArg].n_items != 3 && s_arg[iArg].n_items != 4) ||
360 1 != sscanf(s_arg[iArg].list[1], "%lf", &xMin) ||
361 1 != sscanf(s_arg[iArg].list[2], "%lf", &xMax) ||
362 xMin >= xMax)
364 if (s_arg[iArg].n_items == 4) {
365 if (strncmp(
str_tolower(s_arg[iArg].list[3]),
"fitonly", strlen(s_arg[iArg].list[3])) == 0) {
366 rangeFitOnly = 1;
367 } else
369 }
370 break;
371 case CLO_GENERATESIGMAS:
372 generateSigmas = FLGS_GENERATESIGMAS;
373 if (s_arg[iArg].n_items > 1) {
374 if (s_arg[iArg].n_items != 2)
375 SDDS_Bomb(
"incorrect -generateSigmas syntax");
376 if (strncmp(s_arg[iArg].list[1], "keepsmallest", strlen(s_arg[iArg].list[1])) == 0)
377 generateSigmas |= FLGS_KEEPSMALLEST;
378 if (strncmp(s_arg[iArg].list[1], "keeplargest", strlen(s_arg[iArg].list[1])) == 0)
379 generateSigmas |= FLGS_KEEPLARGEST;
380 if ((generateSigmas & FLGS_KEEPSMALLEST) && (generateSigmas & FLGS_KEEPLARGEST))
381 SDDS_Bomb(
"ambiguous -generateSigmas syntax");
382 }
383 break;
384 case CLO_XOFFSET:
385 if (s_arg[iArg].n_items != 2 || sscanf(s_arg[iArg].list[1], "%lf", &xOffset) != 1)
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_SPARSE:
397 if (s_arg[iArg].n_items != 2)
399 if (sscanf(s_arg[iArg].list[1], "%ld", &sparseInterval) != 1)
400 SDDS_Bomb(
"couldn't scan value for -sparse");
401 if (sparseInterval < 1)
403 break;
404 case CLO_VERBOSE:
405 verbose = 1;
406 break;
407 case CLO_NORMALIZE:
408 normTerm = 0;
409 if (s_arg[iArg].n_items > 2 ||
410 (s_arg[iArg].n_items == 2 && sscanf(s_arg[iArg].list[1], "%ld", &normTerm) != 1) ||
411 normTerm < 0)
413 break;
414 case CLO_REVISEORDERS:
415 revpowThreshold = 0.1;
416 s_arg[iArg].n_items -= 1;
417 if (!
scanItemList(&reviseOrders, s_arg[iArg].list + 1, &s_arg[iArg].n_items, 0,
419 "verbose", -1, NULL, 1, REVPOW_VERBOSE, NULL))
420 SDDS_Bomb(
"invalid -reviseOrders syntax");
421 s_arg[iArg].n_items += 1;
422 reviseOrders |= REVPOW_ACTIVE;
423 revpowThreshold = fabs(revpowThreshold);
424 break;
425 case CLO_XFACTOR:
426 if (s_arg[iArg].n_items != 2 ||
427 sscanf(s_arg[iArg].list[1], "%lf", &xScaleFactor) != 1 || xScaleFactor == 0)
429 break;
430 case CLO_INDEPENDENT:
431 if (s_arg[iArg].n_items != 2)
432 SDDS_Bomb(
"invalid -independent syntax");
433 xName = s_arg[iArg].list[1];
434 break;
435 case CLO_DEPENDENT:
436 numDependentItems = s_arg[iArg].n_items - 1;
437 cloDependentIndex = iArg;
438 if (numDependentItems < 1)
440 break;
441 case CLO_SIGMAINDEPENDENT:
442 if (s_arg[iArg].n_items != 2)
443 SDDS_Bomb(
"invalid -sigmaIndependent syntax");
444 xSigmaName = s_arg[iArg].list[1];
445 break;
446 case CLO_SIGMADEPENDENT:
447 if (s_arg[iArg].n_items != 2)
448 SDDS_Bomb(
"invalid -sigmaDependent syntax");
449 ySigmaControlString = s_arg[iArg].list[1];
450 break;
451 case CLO_PIPE:
452 if (!
processPipeOption(s_arg[iArg].list + 1, s_arg[iArg].n_items - 1, &pipeFlags))
454 break;
455 case CLO_INFOFILE:
456 if (s_arg[iArg].n_items != 2)
458 infoFile = s_arg[iArg].list[1];
459 break;
460 case CLO_EVALUATE:
461 if (s_arg[iArg].n_items < 2)
463 evalParameters.file = s_arg[iArg].list[1];
464 s_arg[iArg].n_items -= 2;
465 s_arg[iArg].list += 2;
466 evalParameters.begin = 0;
467 evalParameters.end = 0;
468 evalParameters.nderiv = 0;
469 evalParameters.number = 0;
470 if (!
scanItemList(&evalParameters.flags, s_arg[iArg].list, &s_arg[iArg].n_items, 0,
471 "begin",
SDDS_DOUBLE, &evalParameters.begin, 1, EVAL_BEGIN_GIVEN,
472 "end",
SDDS_DOUBLE, &evalParameters.end, 1, EVAL_END_GIVEN,
473 "derivatives",
SDDS_LONG64, &evalParameters.nderiv, 1, EVAL_DERIVATIVES,
474 "basis", -1, NULL, 0, EVAL_PROVIDEBASIS,
475 "number",
SDDS_LONG64, &evalParameters.number, 1, EVAL_NUMBER_GIVEN, NULL))
477 s_arg[iArg].n_items += 2;
478 s_arg[iArg].list -= 2;
479 break;
480 case CLO_COPYPARAMETERS:
481 copyParameters = 1;
482 break;
483 default:
484 bomb(
"unknown switch", USAGE);
485 break;
486 }
487 } else {
488 if (input == NULL)
489 input = s_arg[iArg].list[0];
490 else if (output == NULL)
491 output = s_arg[iArg].list[0];
492 else
494 }
495 }
496
497 if (!orderGiven)
498 order = 4;
499 if (!breaksGiven)
500 breaks = coeffs + 2 - order;
501 if (!coeffsGiven)
502 coeffs = breaks - 2 + order;
503 if (breaksGiven && coeffsGiven)
504 SDDS_Bomb(
"You must specify only one of breakpoints or coefficients");
505
507
508 if (!xName || !numDependentItems)
509 SDDS_Bomb(
"you must specify a column name for x and y");
510 if (modifySigmas && !xSigmaName)
511 SDDS_Bomb(
"you must specify x sigmas with -modifySigmas");
512 if (generateSigmas) {
513 if (modifySigmas)
514 SDDS_Bomb(
"you can't specify both -generateSigmas and -modifySigmas");
515 }
516 if (ySigmaControlString) {
517 if (sigmasMode != -1)
518 SDDS_Bomb(
"you can't specify both -sigmas and a y sigma name");
519 }
520 ySigmasValid = 0;
521 if (sigmasMode != -1 || generateSigmas || ySigmaControlString || modifySigmas)
522 ySigmasValid = 1;
523
526 outputInitialized = 0;
527 yNames = ResolveColumnNames(&SDDSin, s_arg[cloDependentIndex].list + 1, numDependentItems, &numYNames);
528 if (ySigmaControlString != NULL)
529 ySigmaNames = GenerateYSigmaNames(ySigmaControlString, yNames, numYNames);
530
531 checkInputFile(&SDDSin, xName, yNames, xSigmaName, ySigmaNames, numYNames);
532 sy0 =
tmalloc(
sizeof(
double *) * numYNames);
533 y =
tmalloc(
sizeof(
double *) * numYNames);
534 yFit =
tmalloc(
sizeof(
double *) * numYNames);
535 sy =
tmalloc(
sizeof(
double *) * numYNames);
536 isFit =
tmalloc(
sizeof(
long) * numYNames);
537 chi =
tmalloc(
sizeof(
double) * numYNames);
538 iCoefficient =
tmalloc(
sizeof(
long) * numYNames);
539 iCoefficientSigma =
tmalloc(
sizeof(
long) * numYNames);
540 iCoefficientUnits =
tmalloc(
sizeof(
long) * numYNames);
541
544
545 continue;
546 }
547 if (verbose)
548 fprintf(stdout, "number of points %" PRId64 "\n", points);
550 fprintf(stderr, "error: unable to read column %s\n", xName);
552 }
553 for (i = 0; i < numYNames; i++) {
555 fprintf(stderr, "error: unable to read column %s\n", yNames[i]);
557 }
558 }
559 sx = NULL;
561 fprintf(stderr, "error: unable to read column %s\n", xSigmaName);
563 }
564 for (colIndex = 0; colIndex < numYNames; colIndex++) {
565 sy0[colIndex] =
tmalloc(
sizeof(
double) * points);
566 yFit[colIndex] =
tmalloc(
sizeof(
double) * points);
567 }
568
569 if (ySigmaNames) {
570 for (i = 0; i < numYNames; i++) {
572 fprintf(stderr, "error: unable to read column %s\n", ySigmaNames[i]);
574 }
575 }
576 }
577
578 if (xMin != xMax || sparseInterval != 1) {
579 xOrig =
tmalloc(
sizeof(*xOrig) * points);
580 yOrig =
tmalloc(
sizeof(*yOrig) * numYNames);
581 yFitOrig =
tmalloc(
sizeof(*yFitOrig) * numYNames);
582 for (colIndex = 0; colIndex < numYNames; colIndex++) {
583 if (verbose)
584 fprintf(stdout, "Setting up a separate array for range or sparsing for column %s because of range option ...\n", yNames[colIndex]);
585 yOrig[colIndex] =
tmalloc(
sizeof(
double) * points);
586 yFitOrig[colIndex] =
tmalloc(
sizeof(
double) * points);
587 }
588 if (sx)
589 sxOrig =
tmalloc(
sizeof(*sxOrig) * points);
590 if (ySigmasValid) {
591 syOrig =
tmalloc(
sizeof(*syOrig) * numYNames);
592 for (colIndex = 0; colIndex < numYNames; colIndex++)
593 syOrig[colIndex] =
tmalloc(
sizeof(
double) * points);
594 }
595 pointsOrig = points;
596 for (i = j = 0; i < points; i++) {
597 xOrig[i] = x[i];
598 if (sx)
599 sxOrig[i] = sx[i];
600 for (colIndex = 0; colIndex < numYNames; colIndex++) {
601 yOrig[colIndex][i] = y[colIndex][i];
602 if (ySigmasValid)
603 syOrig[colIndex][i] = sy0[colIndex][i];
604 }
605 }
606 if (xMin != xMax) {
607 for (i = j = 0; i < points; i++) {
608 if (xOrig[i] <= xMax && xOrig[i] >= xMin) {
609 x[j] = xOrig[i];
610 for (colIndex = 0; colIndex < numYNames; colIndex++) {
611 y[colIndex][j] = yOrig[colIndex][i];
612 if (ySigmasValid)
613 sy0[colIndex][j] = syOrig[colIndex][i];
614 }
615 if (sx)
616 sx[j] = sxOrig[i];
617 j++;
618 }
619 }
620 points = j;
621 }
622 if (sparseInterval != 1) {
623 for (i = j = 0; i < points; i++) {
624 if (i % sparseInterval == 0) {
625 x[j] = x[i];
626 for (colIndex = 0; colIndex < numYNames; colIndex++) {
627 y[colIndex][j] = y[colIndex][i];
628 if (ySigmasValid)
629 sy0[colIndex][j] = sy0[colIndex][i];
630 }
631 if (sx)
632 sx[j] = sx[i];
633 j++;
634 }
635 }
636 points = j;
637 }
638 } else {
639
640 xOrig = x;
641 yOrig = y;
642 sxOrig = sx;
643 syOrig = sy0;
644 pointsOrig = points;
645 }
646
648 if (verbose)
649 fprintf(stdout, "Range: xLow %lf; xHigh %lf; points %" PRId64 "\n", xLow, xHigh, points);
650 if (sigmasMode == ABSOLUTE_SIGMAS) {
651 for (colIndex = 0; colIndex < numYNames; colIndex++) {
652 for (i = 0; i < points; i++)
653 sy0[colIndex][i] = sigmas;
654 if (sy0[colIndex] != syOrig[colIndex])
655 for (i = 0; i < pointsOrig; i++)
656 syOrig[colIndex][i] = sigmas;
657 }
658 } else if (sigmasMode == FRACTIONAL_SIGMAS) {
659 for (colIndex = 0; colIndex < numYNames; colIndex++) {
660 for (i = 0; i < points; i++)
661 sy0[colIndex][i] = sigmas * fabs(y[colIndex][i]);
662 if (sy0[colIndex] != syOrig[colIndex])
663 for (i = 0; i < pointsOrig; i++)
664 syOrig[colIndex][i] = fabs(yOrig[colIndex][i]) * sigmas;
665 }
666 }
667
668 if (!ySigmasValid || generateSigmas)
669 for (colIndex = 0; colIndex < numYNames; colIndex++) {
670 for (i = 0; i < points; i++)
671 sy0[colIndex][i] = 1;
672 }
673 else
674 for (i = 0; i < points; i++)
675 for (colIndex = 0; colIndex < numYNames; colIndex++) {
676 if (sy0[colIndex][i] == 0)
677 SDDS_Bomb(
"y sigma = 0 for one or more points.");
678 }
679
680 diff =
tmalloc(
sizeof(*diff) * numYNames);
681 sy =
tmalloc(
sizeof(*sy) * numYNames);
682 for (colIndex = 0; colIndex < numYNames; colIndex++) {
683 diff[colIndex] =
tmalloc(
sizeof(
double) * points);
684 sy[colIndex] =
tmalloc(
sizeof(
double) * points);
685 }
686
687 for (i = 0; i < points; i++) {
688 for (colIndex = 0; colIndex < numYNames; colIndex++)
689 sy[colIndex][i] = sy0[colIndex][i];
690 }
691
692
693
694
695
696
697 bw = gsl_bspline_alloc(order, breaks);
698 B = gsl_vector_alloc(coeffs);
699
700
701 X = gsl_matrix_alloc(points, coeffs);
702 c = gsl_vector_alloc(coeffs);
703 yGsl = gsl_vector_alloc(points);
704 wGsl = gsl_vector_alloc(points);
705 cov = gsl_matrix_alloc(coeffs, coeffs);
706 mw = gsl_multifit_linear_alloc(points, coeffs);
707 degreesOfFreedom = points - coeffs;
708 if (verbose)
709 fprintf(stdout, "Order %ld\ncoefficients %ld\nbreak points %ld\n", order, coeffs, breaks);
710 if (generateSigmas || modifySigmas)
711 fprintf(stderr, "generate sigmas or modify sigmas are not a feature in spline fitting.\n");
712
713 if (reviseOrders & REVPOW_ACTIVE)
714 fprintf(stderr, "revise orders is not a feature in spline fitting.\n");
715
716 if (!outputInitialized) {
717 initializeOutputFile(&SDDSout, &SDDSoutInfo, output, infoFile, &SDDSin, input, xName, yNames,
718 xSigmaName, ySigmaNames, ySigmasValid, order, coeffs, breaks, numYNames, copyParameters);
719
720 outputInitialized = 1;
721
722 if (evalParameters.file) {
723
724 if (evalParameters.nderiv >= order) {
725 evalParameters.nderiv = order - 1;
726 if (verbose)
727 fprintf(stderr, "Spline derivative order reduced to %" PRId64 " (i.e. order - 1)\n", evalParameters.nderiv);
728 }
729 evalParameters.bw = bw;
730 setupEvaluationFile(&evalParameters, xName, yNames, numYNames, &SDDSin);
731 }
732 }
733
734 rmsResidual =
tmalloc(
sizeof(
double) * numYNames);
735
736 if (outputInitialized) {
737 if (!
SDDS_StartPage(&SDDSout, rangeFitOnly ? pointsOrig : points) ||
740 if (copyParameters) {
745 }
746
747 if (!
SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_INDEX, rangeFitOnly ? xOrig : x, rangeFitOnly ? pointsOrig : points, ix))
749 for (colIndex = 0; colIndex < numYNames; colIndex++) {
750
751 double Bj;
752 for (i = 0; i < points; i++) {
753 gsl_vector_set(yGsl, i, y[colIndex][i]);
754
755 gsl_vector_set(wGsl, i, 1.0 /
ipower(sy[colIndex][i], 2));
756 }
757
758
759 gsl_bspline_knots_uniform(xLow, xHigh, bw);
760
761
762
763
764
765 for (i = 0; i < points; ++i) {
766
767
768 gsl_bspline_eval(x[i], B, bw);
769
770 for (j = 0; j < coeffs; ++j) {
771 Bj = gsl_vector_get(B, j);
772
773 gsl_matrix_set(X, i, j, Bj);
774 }
775 }
776
777 if (verbose == 2) {
778 fprintf(stderr, "X matrix %s:\n", yNames[colIndex]);
779 print_matrix(stderr, X);
780 }
781
782 gsl_multifit_wlinear(X, wGsl, yGsl, c, cov, &chi[colIndex], mw);
783 if (verbose)
784 fprintf(stdout, "conventionally-defined chi = sum( sqr(diff) * weight): %e\n", chi[colIndex]);
785
786 if (verbose == 2) {
787 fprintf(stderr, "Covariance matrix for %s:\n", yNames[colIndex]);
788 print_matrix(stderr, cov);
789 }
790
791 totalSumSquare = gsl_stats_wtss(wGsl->data, 1, yGsl->data, 1, yGsl->size);
792 Rsq = 1.0 - chi[colIndex] / totalSumSquare;
793 if (verbose)
794 fprintf(stdout, "(reduced) chisq/dof = %e, Rsq = %f\n", chi[colIndex] / degreesOfFreedom, Rsq);
795
796 double y_err;
797 for (i = 0; i < points; i++) {
798 gsl_bspline_eval(x[i], B, bw);
799
800 gsl_multifit_linear_est(B, c, cov, &yFit[colIndex][i], &y_err);
801 }
802 if (rangeFitOnly) {
803 for (i = 0; i < pointsOrig; i++) {
804 diff[colIndex][i] = yOrig[colIndex][i] - yFitOrig[colIndex][i];
805 }
806 rmsResidual[colIndex] = rms_average(diff[colIndex], points);
807
812 } else {
813 for (i = 0; i < points; i++) {
814 diff[colIndex][i] = y[colIndex][i] - yFit[colIndex][i];
815 }
816 rmsResidual[colIndex] = rms_average(diff[colIndex], points);
817
822 }
823 if (infoFile)
826 if (evalParameters.file) {
827 evalParameters.bw = bw;
828 makeEvaluationTable(&evalParameters, x, points, B, cov, c, xName, yNames, numYNames, colIndex, order);
829 }
830 }
831
832 if (ixSigma != -1 &&
833 !
SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_INDEX, rangeFitOnly ? sxOrig : sx, rangeFitOnly ? pointsOrig : points, ixSigma))
835 if (infoFile) {
836 {
837 int32_t *Indices;
838 Indices = malloc(sizeof(*Indices) * coeffs);
839 for (i = 0; i < coeffs; i++)
840 Indices[i] = i;
841 if (!
SDDS_SetColumn(&SDDSoutInfo, SDDS_SET_BY_NAME, Indices, coeffs,
"Index"))
843 }
844 }
845 for (colIndex = 0; colIndex < numYNames; colIndex++) {
846 if (ySigmasValid && iySigma[colIndex] != -1 &&
848 rangeFitOnly ? pointsOrig : points, iySigma[colIndex]))
850
851
852
853
854 if (infoFile) {
856 iRmsResidual[colIndex], rmsResidual[colIndex],
857 iChiSq[colIndex], (chi[colIndex] / degreesOfFreedom),
858 iSigLevel[colIndex],
ChiSqrSigLevel(chi[colIndex], points - coeffs),
859 iOffset, xOffset, iFactor, xScaleFactor, iFitIsValid[colIndex], isFit[colIndex] ? 'y' : 'n', -1))
861 }
862
863
865 iRmsResidualO[colIndex], rmsResidual[colIndex],
866 iChiSqO[colIndex], (chi[colIndex] / degreesOfFreedom),
867 iSigLevelO[colIndex],
ChiSqrSigLevel(chi[colIndex], points - coeffs),
868 iOffsetO, xOffset, iFactorO, xScaleFactor, iFitIsValidO[colIndex], isFit[colIndex] ? 'y' : 'n', -1))
870 }
873 }
874
875
876 if (xOrig != x)
877 free(xOrig);
878 if (sxOrig != sx)
879 free(sxOrig);
880 free(x);
881 free(sx);
882 for (colIndex = 0; colIndex < numYNames; colIndex++) {
883 free(diff[colIndex]);
884 free(sy[colIndex]);
885 if (yOrig[colIndex] != y[colIndex])
886 free(yOrig[colIndex]);
887 if (syOrig && sy0 && syOrig[colIndex] != sy0[colIndex])
888 free(syOrig[colIndex]);
889 free(y[colIndex]);
890 if (sy0 && sy0[colIndex])
891 free(sy0[colIndex]);
892 if (yFit && yFit[colIndex])
893 free(yFit[colIndex]);
894 }
895 gsl_bspline_free(bw);
896 gsl_vector_free(B);
897 gsl_matrix_free(X);
898 gsl_vector_free(yGsl);
899 gsl_vector_free(wGsl);
900
901 gsl_matrix_free(cov);
902 gsl_multifit_linear_free(mw);
903 }
904
905 if (yFit)
906 free(yFit);
907 if (outputInitialized) {
910 }
911 if (infoFile) {
914 }
915 }
916 if (evalParameters.file) {
919 }
920 }
921 }
924 }
926
927 return EXIT_SUCCESS;
928}
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_SetColumn(SDDS_DATASET *SDDS_dataset, int32_t mode, void *data, int64_t rows,...)
Sets the values for one data column in the current data table of an SDDS dataset.
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 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)
void free_scanargs(SCANNED_ARG **scanned, int argc)
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.
double ipower(double x, long n)
Evaluate a power function x^n.
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.