231 {
232 double **y = NULL, **yFit = NULL, **sy = NULL, **diff = NULL;
233 double *x = NULL, *sx = NULL;
234 double xOffset, xScaleFactor;
235 double *xOrig = NULL, **yOrig = NULL, **yFitOrig = NULL, *sxOrig = NULL, **syOrig = NULL, **sy0 = NULL;
236 long coeffs, breaks, normTerm, ySigmasValid;
237 long orderGiven, coeffsGiven, breaksGiven;
238 int64_t i, j, points, pointsOrig;
239 double sigmas;
240 long sigmasMode, sparseInterval;
241 double *chi = NULL, xLow, xHigh, *rmsResidual = NULL;
242 char *xName = NULL, *yName = NULL, **yNames = NULL, *xSigmaName = NULL;
243 char **ySigmaNames = NULL, *ySigmaControlString = NULL;
244 char *input = NULL, *output = NULL;
246 long *isFit = NULL, iArg, modifySigmas;
247 long generateSigmas, verbose, ignoreSigmas;
248 long outputInitialized, copyParameters = 0;
249 long int order;
250 SCANNED_ARG *s_arg;
251 double xMin, xMax, revpowThreshold;
252 double rms_average(double *d_x, int64_t d_n);
253 char *infoFile = NULL;
254 unsigned long pipeFlags, reviseOrders;
256 long rangeFitOnly = 0;
257
258 long colIndex;
259 long cloDependentIndex = -1, numDependentItems;
260 int32_t numYNames;
261
262
263 gsl_bspline_workspace *bw;
264 gsl_vector *B;
265 gsl_vector *c, *yGsl, *wGsl;
266 gsl_matrix *X, *cov;
267 gsl_multifit_linear_workspace *mw;
268 long degreesOfFreedom;
269 double totalSumSquare, Rsq;
270
272 argc =
scanargs(&s_arg, argc, argv);
273 if (argc < 2 || argc > (3 + N_OPTIONS)) {
274 fprintf(stderr, "usage: %s\n", USAGE);
275 fprintf(stderr, "%s%s", additional_help, additional_help2);
276 exit(EXIT_FAILURE);
277 }
278
279 input = output = NULL;
280 xName = yName = xSigmaName = ySigmaControlString = NULL;
281 yNames = ySigmaNames = NULL;
282 numDependentItems = 0;
283 modifySigmas = reviseOrders = 0;
284
285 coeffs = 8;
286 xMin = xMax = 0;
287 generateSigmas = 0;
288 sigmasMode = -1;
289 sigmas = 1;
290 sparseInterval = 1;
291 verbose = ignoreSigmas = 0;
292 normTerm = -1;
293 xOffset = 0;
294 xScaleFactor = 1;
295 pipeFlags = 0;
296 evalParameters.file = NULL;
297 infoFile = NULL;
298 orderGiven = 0;
299 coeffsGiven = 0;
300 breaksGiven = 0;
301
302 for (iArg = 1; iArg < argc; iArg++) {
303 if (s_arg[iArg].arg_type == OPTION) {
304 switch (
match_string(s_arg[iArg].list[0], option, N_OPTIONS, 0)) {
305 case CLO_MODIFYSIGMAS:
306 modifySigmas = 1;
307 break;
308 case CLO_ORDER:
309 if (s_arg[iArg].n_items != 2 || sscanf(s_arg[iArg].list[1], "%ld", &order) != 1)
311 orderGiven = 1;
312 break;
313 case CLO_COEFFICIENTS:
314 if (s_arg[iArg].n_items != 2 || sscanf(s_arg[iArg].list[1], "%ld", &coeffs) != 1)
315 SDDS_Bomb(
"invalid -coefficients syntax");
316 coeffsGiven = 1;
317 break;
318 case CLO_BREAKPOINTS:
319 if (s_arg[iArg].n_items != 2 || sscanf(s_arg[iArg].list[1], "%ld", &breaks) != 1)
320 SDDS_Bomb(
"invalid -breakpoints syntax");
321 breaksGiven = 1;
322 break;
323 case CLO_RANGE:
324 rangeFitOnly = 0;
325 if ((s_arg[iArg].n_items != 3 && s_arg[iArg].n_items != 4) ||
326 1 != sscanf(s_arg[iArg].list[1], "%lf", &xMin) ||
327 1 != sscanf(s_arg[iArg].list[2], "%lf", &xMax) ||
328 xMin >= xMax)
330 if (s_arg[iArg].n_items == 4) {
331 if (strncmp(
str_tolower(s_arg[iArg].list[3]),
"fitonly", strlen(s_arg[iArg].list[3])) == 0) {
332 rangeFitOnly = 1;
333 } else
335 }
336 break;
337 case CLO_GENERATESIGMAS:
338 generateSigmas = FLGS_GENERATESIGMAS;
339 if (s_arg[iArg].n_items > 1) {
340 if (s_arg[iArg].n_items != 2)
341 SDDS_Bomb(
"incorrect -generateSigmas syntax");
342 if (strncmp(s_arg[iArg].list[1], "keepsmallest", strlen(s_arg[iArg].list[1])) == 0)
343 generateSigmas |= FLGS_KEEPSMALLEST;
344 if (strncmp(s_arg[iArg].list[1], "keeplargest", strlen(s_arg[iArg].list[1])) == 0)
345 generateSigmas |= FLGS_KEEPLARGEST;
346 if ((generateSigmas & FLGS_KEEPSMALLEST) && (generateSigmas & FLGS_KEEPLARGEST))
347 SDDS_Bomb(
"ambiguous -generateSigmas syntax");
348 }
349 break;
350 case CLO_XOFFSET:
351 if (s_arg[iArg].n_items != 2 || sscanf(s_arg[iArg].list[1], "%lf", &xOffset) != 1)
353 break;
354 case CLO_SIGMAS:
355 if (s_arg[iArg].n_items != 3)
357 if (sscanf(s_arg[iArg].list[1], "%lf", &sigmas) != 1)
358 SDDS_Bomb(
"couldn't scan value for -sigmas");
359 if ((sigmasMode =
match_string(s_arg[iArg].list[2], sigmas_options, N_SIGMAS_OPTIONS, 0)) < 0)
361 break;
362 case CLO_SPARSE:
363 if (s_arg[iArg].n_items != 2)
365 if (sscanf(s_arg[iArg].list[1], "%ld", &sparseInterval) != 1)
366 SDDS_Bomb(
"couldn't scan value for -sparse");
367 if (sparseInterval < 1)
369 break;
370 case CLO_VERBOSE:
371 verbose = 1;
372 break;
373 case CLO_NORMALIZE:
374 normTerm = 0;
375 if (s_arg[iArg].n_items > 2 ||
376 (s_arg[iArg].n_items == 2 && sscanf(s_arg[iArg].list[1], "%ld", &normTerm) != 1) ||
377 normTerm < 0)
379 break;
380 case CLO_REVISEORDERS:
381 revpowThreshold = 0.1;
382 s_arg[iArg].n_items -= 1;
383 if (!
scanItemList(&reviseOrders, s_arg[iArg].list + 1, &s_arg[iArg].n_items, 0,
385 "verbose", -1, NULL, 1, REVPOW_VERBOSE, NULL))
386 SDDS_Bomb(
"invalid -reviseOrders syntax");
387 s_arg[iArg].n_items += 1;
388 reviseOrders |= REVPOW_ACTIVE;
389 revpowThreshold = fabs(revpowThreshold);
390 break;
391 case CLO_XFACTOR:
392 if (s_arg[iArg].n_items != 2 ||
393 sscanf(s_arg[iArg].list[1], "%lf", &xScaleFactor) != 1 || xScaleFactor == 0)
395 break;
396 case CLO_INDEPENDENT:
397 if (s_arg[iArg].n_items != 2)
398 SDDS_Bomb(
"invalid -independent syntax");
399 xName = s_arg[iArg].list[1];
400 break;
401 case CLO_DEPENDENT:
402 numDependentItems = s_arg[iArg].n_items - 1;
403 cloDependentIndex = iArg;
404 if (numDependentItems < 1)
406 break;
407 case CLO_SIGMAINDEPENDENT:
408 if (s_arg[iArg].n_items != 2)
409 SDDS_Bomb(
"invalid -sigmaIndependent syntax");
410 xSigmaName = s_arg[iArg].list[1];
411 break;
412 case CLO_SIGMADEPENDENT:
413 if (s_arg[iArg].n_items != 2)
414 SDDS_Bomb(
"invalid -sigmaDependent syntax");
415 ySigmaControlString = s_arg[iArg].list[1];
416 break;
417 case CLO_PIPE:
418 if (!
processPipeOption(s_arg[iArg].list + 1, s_arg[iArg].n_items - 1, &pipeFlags))
420 break;
421 case CLO_INFOFILE:
422 if (s_arg[iArg].n_items != 2)
424 infoFile = s_arg[iArg].list[1];
425 break;
426 case CLO_EVALUATE:
427 if (s_arg[iArg].n_items < 2)
429 evalParameters.file = s_arg[iArg].list[1];
430 s_arg[iArg].n_items -= 2;
431 s_arg[iArg].list += 2;
432 evalParameters.begin = 0;
433 evalParameters.end = 0;
434 evalParameters.nderiv = 0;
435 evalParameters.number = 0;
436 if (!
scanItemList(&evalParameters.flags, s_arg[iArg].list, &s_arg[iArg].n_items, 0,
437 "begin",
SDDS_DOUBLE, &evalParameters.begin, 1, EVAL_BEGIN_GIVEN,
438 "end",
SDDS_DOUBLE, &evalParameters.end, 1, EVAL_END_GIVEN,
439 "derivatives",
SDDS_LONG64, &evalParameters.nderiv, 1, EVAL_DERIVATIVES,
440 "basis", -1, NULL, 0, EVAL_PROVIDEBASIS,
441 "number",
SDDS_LONG64, &evalParameters.number, 1, EVAL_NUMBER_GIVEN, NULL))
443 s_arg[iArg].n_items += 2;
444 s_arg[iArg].list -= 2;
445 break;
446 case CLO_COPYPARAMETERS:
447 copyParameters = 1;
448 break;
449 default:
450 bomb(
"unknown switch", USAGE);
451 break;
452 }
453 } else {
454 if (input == NULL)
455 input = s_arg[iArg].list[0];
456 else if (output == NULL)
457 output = s_arg[iArg].list[0];
458 else
460 }
461 }
462
463 if (!orderGiven)
464 order = 4;
465 if (!breaksGiven)
466 breaks = coeffs + 2 - order;
467 if (!coeffsGiven)
468 coeffs = breaks - 2 + order;
469 if (breaksGiven && coeffsGiven)
470 SDDS_Bomb(
"You must specify only one of breakpoints or coefficients");
471
473
474 if (!xName || !numDependentItems)
475 SDDS_Bomb(
"you must specify a column name for x and y");
476 if (modifySigmas && !xSigmaName)
477 SDDS_Bomb(
"you must specify x sigmas with -modifySigmas");
478 if (generateSigmas) {
479 if (modifySigmas)
480 SDDS_Bomb(
"you can't specify both -generateSigmas and -modifySigmas");
481 }
482 if (ySigmaControlString) {
483 if (sigmasMode != -1)
484 SDDS_Bomb(
"you can't specify both -sigmas and a y sigma name");
485 }
486 ySigmasValid = 0;
487 if (sigmasMode != -1 || generateSigmas || ySigmaControlString || modifySigmas)
488 ySigmasValid = 1;
489
492 outputInitialized = 0;
493 yNames = ResolveColumnNames(&SDDSin, s_arg[cloDependentIndex].list + 1, numDependentItems, &numYNames);
494 if (ySigmaControlString != NULL)
495 ySigmaNames = GenerateYSigmaNames(ySigmaControlString, yNames, numYNames);
496
497 checkInputFile(&SDDSin, xName, yNames, xSigmaName, ySigmaNames, numYNames);
498 sy0 =
tmalloc(
sizeof(
double *) * numYNames);
499 y =
tmalloc(
sizeof(
double *) * numYNames);
500 yFit =
tmalloc(
sizeof(
double *) * numYNames);
501 sy =
tmalloc(
sizeof(
double *) * numYNames);
502 isFit =
tmalloc(
sizeof(
long) * numYNames);
503 chi =
tmalloc(
sizeof(
double) * numYNames);
504 iCoefficient =
tmalloc(
sizeof(
long) * numYNames);
505 iCoefficientSigma =
tmalloc(
sizeof(
long) * numYNames);
506 iCoefficientUnits =
tmalloc(
sizeof(
long) * numYNames);
507
510
511 continue;
512 }
513 if (verbose)
514 fprintf(stdout, "number of points %" PRId64 "\n", points);
516 fprintf(stderr, "error: unable to read column %s\n", xName);
518 }
519 for (i = 0; i < numYNames; i++) {
521 fprintf(stderr, "error: unable to read column %s\n", yNames[i]);
523 }
524 }
525 sx = NULL;
527 fprintf(stderr, "error: unable to read column %s\n", xSigmaName);
529 }
530 for (colIndex = 0; colIndex < numYNames; colIndex++) {
531 sy0[colIndex] =
tmalloc(
sizeof(
double) * points);
532 yFit[colIndex] =
tmalloc(
sizeof(
double) * points);
533 }
534
535 if (ySigmaNames) {
536 for (i = 0; i < numYNames; i++) {
538 fprintf(stderr, "error: unable to read column %s\n", ySigmaNames[i]);
540 }
541 }
542 }
543
544 if (xMin != xMax || sparseInterval != 1) {
545 xOrig =
tmalloc(
sizeof(*xOrig) * points);
546 yOrig =
tmalloc(
sizeof(*yOrig) * numYNames);
547 yFitOrig =
tmalloc(
sizeof(*yFitOrig) * numYNames);
548 for (colIndex = 0; colIndex < numYNames; colIndex++) {
549 if (verbose)
550 fprintf(stdout, "Setting up a separate array for range or sparsing for column %s because of range option ...\n", yNames[colIndex]);
551 yOrig[colIndex] =
tmalloc(
sizeof(
double) * points);
552 yFitOrig[colIndex] =
tmalloc(
sizeof(
double) * points);
553 }
554 if (sx)
555 sxOrig =
tmalloc(
sizeof(*sxOrig) * points);
556 if (ySigmasValid) {
557 syOrig =
tmalloc(
sizeof(*syOrig) * numYNames);
558 for (colIndex = 0; colIndex < numYNames; colIndex++)
559 syOrig[colIndex] =
tmalloc(
sizeof(
double) * points);
560 }
561 pointsOrig = points;
562 for (i = j = 0; i < points; i++) {
563 xOrig[i] = x[i];
564 if (sx)
565 sxOrig[i] = sx[i];
566 for (colIndex = 0; colIndex < numYNames; colIndex++) {
567 yOrig[colIndex][i] = y[colIndex][i];
568 if (ySigmasValid)
569 syOrig[colIndex][i] = sy0[colIndex][i];
570 }
571 }
572 if (xMin != xMax) {
573 for (i = j = 0; i < points; i++) {
574 if (xOrig[i] <= xMax && xOrig[i] >= xMin) {
575 x[j] = xOrig[i];
576 for (colIndex = 0; colIndex < numYNames; colIndex++) {
577 y[colIndex][j] = yOrig[colIndex][i];
578 if (ySigmasValid)
579 sy0[colIndex][j] = syOrig[colIndex][i];
580 }
581 if (sx)
582 sx[j] = sxOrig[i];
583 j++;
584 }
585 }
586 points = j;
587 }
588 if (sparseInterval != 1) {
589 for (i = j = 0; i < points; i++) {
590 if (i % sparseInterval == 0) {
591 x[j] = x[i];
592 for (colIndex = 0; colIndex < numYNames; colIndex++) {
593 y[colIndex][j] = y[colIndex][i];
594 if (ySigmasValid)
595 sy0[colIndex][j] = sy0[colIndex][i];
596 }
597 if (sx)
598 sx[j] = sx[i];
599 j++;
600 }
601 }
602 points = j;
603 }
604 } else {
605
606 xOrig = x;
607 yOrig = y;
608 sxOrig = sx;
609 syOrig = sy0;
610 pointsOrig = points;
611 }
612
614 if (verbose)
615 fprintf(stdout, "Range: xLow %lf; xHigh %lf; points %" PRId64 "\n", xLow, xHigh, points);
616 if (sigmasMode == ABSOLUTE_SIGMAS) {
617 for (colIndex = 0; colIndex < numYNames; colIndex++) {
618 for (i = 0; i < points; i++)
619 sy0[colIndex][i] = sigmas;
620 if (sy0[colIndex] != syOrig[colIndex])
621 for (i = 0; i < pointsOrig; i++)
622 syOrig[colIndex][i] = sigmas;
623 }
624 } else if (sigmasMode == FRACTIONAL_SIGMAS) {
625 for (colIndex = 0; colIndex < numYNames; colIndex++) {
626 for (i = 0; i < points; i++)
627 sy0[colIndex][i] = sigmas * fabs(y[colIndex][i]);
628 if (sy0[colIndex] != syOrig[colIndex])
629 for (i = 0; i < pointsOrig; i++)
630 syOrig[colIndex][i] = fabs(yOrig[colIndex][i]) * sigmas;
631 }
632 }
633
634 if (!ySigmasValid || generateSigmas)
635 for (colIndex = 0; colIndex < numYNames; colIndex++) {
636 for (i = 0; i < points; i++)
637 sy0[colIndex][i] = 1;
638 }
639 else
640 for (i = 0; i < points; i++)
641 for (colIndex = 0; colIndex < numYNames; colIndex++) {
642 if (sy0[colIndex][i] == 0)
643 SDDS_Bomb(
"y sigma = 0 for one or more points.");
644 }
645
646 diff =
tmalloc(
sizeof(*diff) * numYNames);
647 sy =
tmalloc(
sizeof(*sy) * numYNames);
648 for (colIndex = 0; colIndex < numYNames; colIndex++) {
649 diff[colIndex] =
tmalloc(
sizeof(
double) * points);
650 sy[colIndex] =
tmalloc(
sizeof(
double) * points);
651 }
652
653 for (i = 0; i < points; i++) {
654 for (colIndex = 0; colIndex < numYNames; colIndex++)
655 sy[colIndex][i] = sy0[colIndex][i];
656 }
657
658
659
660
661
662
663 bw = gsl_bspline_alloc(order, breaks);
664 B = gsl_vector_alloc(coeffs);
665
666
667 X = gsl_matrix_alloc(points, coeffs);
668 c = gsl_vector_alloc(coeffs);
669 yGsl = gsl_vector_alloc(points);
670 wGsl = gsl_vector_alloc(points);
671 cov = gsl_matrix_alloc(coeffs, coeffs);
672 mw = gsl_multifit_linear_alloc(points, coeffs);
673 degreesOfFreedom = points - coeffs;
674 if (verbose)
675 fprintf(stdout, "Order %ld\ncoefficients %ld\nbreak points %ld\n", order, coeffs, breaks);
676 if (generateSigmas || modifySigmas)
677 fprintf(stderr, "generate sigmas or modify sigmas are not a feature in spline fitting.\n");
678
679 if (reviseOrders & REVPOW_ACTIVE)
680 fprintf(stderr, "revise orders is not a feature in spline fitting.\n");
681
682 if (!outputInitialized) {
683 initializeOutputFile(&SDDSout, &SDDSoutInfo, output, infoFile, &SDDSin, input, xName, yNames,
684 xSigmaName, ySigmaNames, ySigmasValid, order, coeffs, breaks, numYNames, copyParameters);
685
686 outputInitialized = 1;
687
688 if (evalParameters.file) {
689
690 if (evalParameters.nderiv >= order) {
691 evalParameters.nderiv = order - 1;
692 if (verbose)
693 fprintf(stderr, "Spline derivative order reduced to %" PRId64 " (i.e. order - 1)\n", evalParameters.nderiv);
694 }
695 evalParameters.bw = bw;
696 setupEvaluationFile(&evalParameters, xName, yNames, numYNames, &SDDSin);
697 }
698 }
699
700 rmsResidual =
tmalloc(
sizeof(
double) * numYNames);
701
702 if (outputInitialized) {
703 if (!
SDDS_StartPage(&SDDSout, rangeFitOnly ? pointsOrig : points) ||
706 if (copyParameters) {
711 }
712
713 if (!
SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_INDEX, rangeFitOnly ? xOrig : x, rangeFitOnly ? pointsOrig : points, ix))
715 for (colIndex = 0; colIndex < numYNames; colIndex++) {
716
717 double Bj;
718 for (i = 0; i < points; i++) {
719 gsl_vector_set(yGsl, i, y[colIndex][i]);
720
721 gsl_vector_set(wGsl, i, 1.0 /
ipower(sy[colIndex][i], 2));
722 }
723
724
725 gsl_bspline_knots_uniform(xLow, xHigh, bw);
726
727
728
729
730
731 for (i = 0; i < points; ++i) {
732
733
734 gsl_bspline_eval(x[i], B, bw);
735
736 for (j = 0; j < coeffs; ++j) {
737 Bj = gsl_vector_get(B, j);
738
739 gsl_matrix_set(X, i, j, Bj);
740 }
741 }
742
743 if (verbose == 2) {
744 fprintf(stderr, "X matrix %s:\n", yNames[colIndex]);
745 print_matrix(stderr, X);
746 }
747
748 gsl_multifit_wlinear(X, wGsl, yGsl, c, cov, &chi[colIndex], mw);
749 if (verbose)
750 fprintf(stdout, "conventionally-defined chi = sum( sqr(diff) * weight): %e\n", chi[colIndex]);
751
752 if (verbose == 2) {
753 fprintf(stderr, "Covariance matrix for %s:\n", yNames[colIndex]);
754 print_matrix(stderr, cov);
755 }
756
757 totalSumSquare = gsl_stats_wtss(wGsl->data, 1, yGsl->data, 1, yGsl->size);
758 Rsq = 1.0 - chi[colIndex] / totalSumSquare;
759 if (verbose)
760 fprintf(stdout, "(reduced) chisq/dof = %e, Rsq = %f\n", chi[colIndex] / degreesOfFreedom, Rsq);
761
762 double y_err;
763 for (i = 0; i < points; i++) {
764 gsl_bspline_eval(x[i], B, bw);
765
766 gsl_multifit_linear_est(B, c, cov, &yFit[colIndex][i], &y_err);
767 }
768 if (rangeFitOnly) {
769 for (i = 0; i < pointsOrig; i++) {
770 diff[colIndex][i] = yOrig[colIndex][i] - yFitOrig[colIndex][i];
771 }
772 rmsResidual[colIndex] = rms_average(diff[colIndex], points);
773
778 } else {
779 for (i = 0; i < points; i++) {
780 diff[colIndex][i] = y[colIndex][i] - yFit[colIndex][i];
781 }
782 rmsResidual[colIndex] = rms_average(diff[colIndex], points);
783
788 }
789 if (infoFile)
792 if (evalParameters.file) {
793 evalParameters.bw = bw;
794 makeEvaluationTable(&evalParameters, x, points, B, cov, c, xName, yNames, numYNames, colIndex, order);
795 }
796 }
797
798 if (ixSigma != -1 &&
799 !
SDDS_SetColumnFromDoubles(&SDDSout, SDDS_SET_BY_INDEX, rangeFitOnly ? sxOrig : sx, rangeFitOnly ? pointsOrig : points, ixSigma))
801 if (infoFile) {
802 {
803 int32_t *Indices;
804 Indices = malloc(sizeof(*Indices) * coeffs);
805 for (i = 0; i < coeffs; i++)
806 Indices[i] = i;
807 if (!
SDDS_SetColumn(&SDDSoutInfo, SDDS_SET_BY_NAME, Indices, coeffs,
"Index"))
809 }
810 }
811 for (colIndex = 0; colIndex < numYNames; colIndex++) {
812 if (ySigmasValid && iySigma[colIndex] != -1 &&
814 rangeFitOnly ? pointsOrig : points, iySigma[colIndex]))
816
817
818
819
820 if (infoFile) {
822 iRmsResidual[colIndex], rmsResidual[colIndex],
823 iChiSq[colIndex], (chi[colIndex] / degreesOfFreedom),
824 iSigLevel[colIndex],
ChiSqrSigLevel(chi[colIndex], points - coeffs),
825 iOffset, xOffset, iFactor, xScaleFactor, iFitIsValid[colIndex], isFit[colIndex] ? 'y' : 'n', -1))
827 }
828
829
831 iRmsResidualO[colIndex], rmsResidual[colIndex],
832 iChiSqO[colIndex], (chi[colIndex] / degreesOfFreedom),
833 iSigLevelO[colIndex],
ChiSqrSigLevel(chi[colIndex], points - coeffs),
834 iOffsetO, xOffset, iFactorO, xScaleFactor, iFitIsValidO[colIndex], isFit[colIndex] ? 'y' : 'n', -1))
836 }
839 }
840
841
842 if (xOrig != x)
843 free(xOrig);
844 if (sxOrig != sx)
845 free(sxOrig);
846 free(x);
847 free(sx);
848 for (colIndex = 0; colIndex < numYNames; colIndex++) {
849 free(diff[colIndex]);
850 free(sy[colIndex]);
851 if (yOrig[colIndex] != y[colIndex])
852 free(yOrig[colIndex]);
853 if (syOrig && sy0 && syOrig[colIndex] != sy0[colIndex])
854 free(syOrig[colIndex]);
855 free(y[colIndex]);
856 if (sy0 && sy0[colIndex])
857 free(sy0[colIndex]);
858 if (yFit && yFit[colIndex])
859 free(yFit[colIndex]);
860 }
861 gsl_bspline_free(bw);
862 gsl_vector_free(B);
863 gsl_matrix_free(X);
864 gsl_vector_free(yGsl);
865 gsl_vector_free(wGsl);
866
867 gsl_matrix_free(cov);
868 gsl_multifit_linear_free(mw);
869 }
870
871 if (yFit)
872 free(yFit);
873 if (outputInitialized) {
876 }
877 if (infoFile) {
880 }
881 }
882 if (evalParameters.file) {
885 }
886 }
887 }
890 }
892
893 return EXIT_SUCCESS;
894}
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.