/*************************************************************************\ * Copyright (c) 2002 The University of Chicago, as Operator of Argonne * National Laboratory. * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * This file is distributed subject to a Software License Agreement found * in the file LICENSE that is included with this distribution. \*************************************************************************/ /* program: sddsmpfit * purpose: do nth order polynomial least squares fitting for SDDS files. * * Michael Borland, 1995. * Based on mpl program 'lsf'. $Log: sddsmpfit.c,v $ Revision 1.15 2006/10/19 17:55:39 soliday Updated to work with linux-x86_64. Revision 1.14 2005/11/07 21:48:10 soliday Updated to remove Linux compiler warnings. Revision 1.13 2005/11/04 22:46:15 soliday Updated code to be compiled by a 64 bit processor. Revision 1.12 2005/07/23 01:26:23 borland Fixed bug that showed up when using -generateSigmas. Some statements were outside of a loop that should have been inside. Revision 1.11 2004/04/21 20:11:02 shang added "NULL" argument to the end of SDDS_FindColumn(...) arguments to fix the core dump errors Revision 1.10 2004/02/08 03:39:16 borland Fixed spelling of "SignificanceLevel" (was "Signicance Level"). Revision 1.9 2002/08/14 17:12:49 soliday Added Open License Revision 1.8 2001/10/12 21:05:24 soliday Fixed usage message problem on WIN32. Revision 1.7 2001/09/07 18:31:09 soliday Fixed some problems that showed up when compiled in Linux. Revision 1.6 2001/08/08 22:00:59 borland Fixed code that creates units for parameters in output and info output file. Revision 1.5 2001/08/08 20:50:57 borland Fixed bug that resulted in program ignoring the sigma data. Revision 1.4 2001/07/23 20:28:14 borland Fixed some memory bugs (uninitialized variables, bad free'ing of arrays). Revision 1.3 1999/07/01 19:24:37 borland Now detects error of giving -terms and -orders options together. Revision 1.2 1999/02/16 22:22:11 borland Implemented -evaluate option. Revision 1.1 1998/07/24 17:54:38 borland First version per B. Dolin. Revision 1.9 1997/08/25 19:21:25 borland Fixed if statement that checks for proper sigma mode for revise-orders mode. Revision 1.8 1997/08/11 22:17:02 borland Removed unnecessary restriction that prevented using -sigma and -generate option together. Revision 1.7 1997/08/11 21:00:03 borland Fixed problems with -generateSigmas=keepX options. Now they do what the manual says they should (i.e., will run with sigmas from file, replacement is now based on point-by-point comparision). * Revision 1.6 1996/02/14 01:05:29 borland * Changed over from scan_item_list() to scanItemList(). * * Revision 1.5 1995/12/12 06:50:32 borland * Fixed bug in parsing of -sigmas option. * * Revision 1.4 1995/11/13 15:56:13 borland * Added long cast to strlen() in numerical comparison to satisfy Solaris compiler. * * Revision 1.3 1995/09/06 14:56:54 saunders * First test release of SDDS1.5 * */ #include "mdb.h" #include "SDDS.h" #include "scan.h" void print_coefs(FILE *fprec, double x_offset, double x_scale, long chebyshev, double *coef, double *s_coef, int32_t *order, long n_terms, double chi, long norm_term, char *prepend); char **makeCoefficientUnits(SDDS_DATASET *SDDSout, char *xName, char *yName, int32_t *order, long terms); long setCoefficientData(SDDS_DATASET *SDDSout, double *coef, double *coefSigma, char **coefUnits, long *order, long terms); char ***initializeOutputFile(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSoutInfo, char *output, char *outputInfo, SDDS_DATASET *SDDSin, char *input, char *xName, char **yNames, char *xSigmaName, char **ySigmaNames, long sigmasValid, int32_t *order, long terms, long isChebyshev, long numCols); void checkInputFile(SDDS_DATASET *SDDSin, char *xName, char **yNames, char *xSigmaName, char **ySigmaNames, long numYNames); long coefficient_index(int32_t *order, long terms, long order_of_interest); void makeFitLabel(char *buffer, long bufsize, char *fitLabelFormat, double *coef, int32_t *order, long terms, long colIndex); char **ResolveColumnNames(SDDS_DATASET *SDDSin, char **wildcardList, long length, int32_t *numYNames); char **GenerateYSigmaNames(char *controlString, char **yNames, long numYNames); void RemoveElementFromStringArray(char **array, long index, long length); char **RemoveNonNumericColumnsFromNameArray(SDDS_DATASET *SDDSin, char **columns, int32_t *numColumns); void set_argument_offset(double offset); void set_argument_scale(double scale); double tcheby(double x, long n); double dtcheby(double x, long n); double ipower(double x, long n); double dipower(double x, long n); #define CLO_DEPENDENT 0 #define CLO_ORDERS 1 #define CLO_TERMS 2 #define CLO_SYMMETRY 3 #define CLO_REVISEORDERS 4 #define CLO_CHEBYSHEV 5 #define CLO_MODIFYSIGMAS 6 #define CLO_SIGMAS 7 #define CLO_GENERATESIGMAS 8 #define CLO_RANGE 9 #define CLO_SPARSE 10 #define CLO_NORMALIZE 11 #define CLO_XFACTOR 12 #define CLO_XOFFSET 13 #define CLO_VERBOSE 14 #define CLO_FITLABELFORMAT 15 #define CLO_PIPE 16 #define CLO_EVALUATE 17 #define CLO_INDEPENDENT 18 #define CLO_SIGMAINDEPENDENT 19 #define CLO_SIGMADEPENDENT 20 #define CLO_INFOFILE 21 #define N_OPTIONS 22 char *option[N_OPTIONS] = { "dependent", "orders", "terms", "symmetry", "reviseorders", "chebyshev", "modifysigmas", "sigmas", "generatesigmas", "range", "sparse", "normalize", "xfactor", "xoffset", "verbose", "fitlabelformat", "pipe", "evaluate", "independent", "sigmaindependent", "sigmadependent", "infofile", }; char *USAGE="sddsmpfit [-pipe=[input][,output]] [] []\n\ -independent= -dependent=[,...]\n\ [-sigmaIndependent=] [-sigmaDependent=]\n\ {-terms= [-symmetry={`none' | `odd' | `even'}] | -orders=[,...] }\n\ [-reviseOrders[=threshold=][,verbose]] [-chebyshev[=convert]]\n\ [-xOffset=value] [-xFactor=value]\n\ [-sigmas=,{absolute | fractional}] \n\ [-modifySigmas] [-generateSigmas[={keepLargest, keepSmallest}]]\n\ [-sparse=] [-range=,]\n\ [-normalize[=]] [-verbose]\n\ [-evaluate=[,begin=][,end=][,number=]]\n\ [-fitLabelFormat=] [-infoFile=]\n\n\ Program by Michael Borland, revised by Brad Dolin. (This is version 1, July 1998.)\n"; static char *additional_help = "\n\ sddsmpfit does fits to the form y = SUM(i){ A[i] *P(x-x_offset, i)}, where P(x,i) is the ith basis\n\ function evaluated at x. sddspfit returns the A[i] and estimates of the errors in the values.\n\ By default P(x,i) = x^i. One can also select Chebyshev T polynomials as the basis functions.\n\n\ -independent specify name of independent data column to use.\n\ -dependent specify names of dependent data columns to use, using wildcards,\n\ separated by commas.\n\ -sigmaIndependent specify name of independent sigma values to use\n\ -sigmaDependent specify names of dependent sigma values to use by specifying a printf-style control\n\ string to generate the names from the independent variable names (e.g., %sSigma)\n\ -terms number of terms desired in fit.\n\ -symmetry symmetry of desired fit about x_offset.\n\ -orders orders (P[i]) to use in fitting.\n\ -reviseOrders the orders used in the fit are modified from the specified ones\n\ in order eliminate poorly-determined coefficients, based on fitting\n\ of the first data page.\n"; static char *additional_help2 = "-chebyshev use Chebyshev T polynomials (xOffset is set automatically).\n\ Giving the `convert' option causes the fit to be written out in\n\ terms of ordinary polynomials.\n\ -xOffset desired value of x to fit about.\n\ -xFactor desired factor to multiply x values by before fitting.\n\ -sigmas specify absolute or fractional sigma for all points.\n\ -modifySigmas modify the y sigmas using the x sigmas and an initial fit.\n\ -generateSigmas generate y sigmas from the rms deviation from an initial fit.\n\ optionally keep the sigmas from the data if larger/smaller than rms\n\ deviation.\n\ -sparse specify integer interval at which to sample data.\n\ -range specify range of independent variable to fit over.\n\ -normalize normalize so that specified term is unity.\n\ -evaluate specify evaluation of fit over a selected range of\n\ equispaced points.\n\ -infoFile specify name of optional information file containing coefficients and fit statistics.\n\ -verbose generates extra output that may be useful.\n\n"; #define NO_SYMMETRY 0 #define EVEN_SYMMETRY 1 #define ODD_SYMMETRY 2 #define N_SYMMETRY_OPTIONS 3 char *symmetry_options[N_SYMMETRY_OPTIONS] = {"none", "even", "odd"}; #define ABSOLUTE_SIGMAS 0 #define FRACTIONAL_SIGMAS 1 #define N_SIGMAS_OPTIONS 2 char *sigmas_options[N_SIGMAS_OPTIONS] = {"absolute", "fractional"}; #define FLGS_GENERATESIGMAS 1 #define FLGS_KEEPLARGEST 2 #define FLGS_KEEPSMALLEST 4 #define REVPOW_ACTIVE 0x0001 #define REVPOW_VERBOSE 0x0002 /* SDDS indices for output page */ static long *iIntercept = NULL, *iInterceptO = NULL, *iInterceptSigma = NULL, *iInterceptSigmaO = NULL; static long *iSlope = NULL, *iSlopeO = NULL, *iSlopeSigma = NULL, *iSlopeSigmaO = NULL; static long *iCurvature = NULL, *iCurvatureO = NULL, *iCurvatureSigma = NULL, *iCurvatureSigmaO = NULL; static long iOffset = -1, iOffsetO = -1, iFactor = -1, iFactorO = -1; static long *iChiSq = NULL, *iChiSqO = NULL, *iRmsResidual = NULL, *iRmsResidualO = NULL, *iSigLevel = NULL, *iSigLevelO = NULL; static long *iFitIsValid = NULL, *iFitIsValidO = NULL, *iFitLabel = NULL, *iFitLabelO = NULL, iTerms = -1, iTermsO = -1; static long ix = -1, ixSigma = -1; static long *iy = NULL, *iySigma = NULL; static long *iFit = NULL, *iResidual = NULL; static long iOrder = -1, *iCoefficient = NULL, *iCoefficientSigma = NULL, *iCoefficientUnits = NULL; static char *xSymbol, **ySymbols; #define EVAL_BEGIN_GIVEN 0x0001U #define EVAL_END_GIVEN 0x0002U #define EVAL_NUMBER_GIVEN 0x0004U #define MAX_Y_SIGMA_NAME_SIZE 1024 typedef struct { char *file; long initialized; int32_t number; unsigned long flags; double begin, end; SDDS_DATASET dataset; } EVAL_PARAMETERS; void setupEvaluationFile(EVAL_PARAMETERS *evalParameters, char *xName, char **yName, long yNames, SDDS_DATASET *SDDSin); void makeEvaluationTable(EVAL_PARAMETERS *evalParameters, double *x, long points, double *coef, int32_t *order, long terms, char *xName, char **yName, long yNames, long iYName); static double (*basis_fn)(double xa, long ordera); static double (*basis_dfn)(double xa, long ordera); int main(int argc, char **argv) { double **y=NULL, **sy=NULL, **diff=NULL; double *x=NULL, *sx=NULL; double xOffset, xScaleFactor; double *xOrig=NULL, **yOrig=NULL, *sxOrig=NULL, **syOrig=NULL, **sy0=NULL; long i, j, points, terms, normTerm, ip, pointsOrig, ySigmasValid; long symmetry, chebyshev, termsGiven; double sigmas; long sigmasMode, sparseInterval; double **coef = NULL, **coefSigma = NULL; double *chi = NULL, xLow, xHigh, *rmsResidual = NULL; char *xName=NULL, *yName=NULL, **yNames=NULL, *xSigmaName=NULL; char **ySigmaNames=NULL, *ySigmaControlString=NULL; char *input=NULL, *output=NULL, ***coefUnits=NULL; SDDS_DATASET SDDSin, SDDSout, SDDSoutInfo; long *isFit = NULL, iArg, modifySigmas, termIndex; long generateSigmas, verbose, ignoreSigmas; long outputInitialized; int32_t *order=NULL; SCANNED_ARG *s_arg; double xMin, xMax, revpowThreshold; double rms_average(double *d_x, int d_n); char *infoFile=NULL; char *fitLabelFormat = "%g"; static char fitLabelBuffer[SDDS_MAXLINE]; unsigned long pipeFlags, reviseOrders; EVAL_PARAMETERS evalParameters; long colIndex; long cloDependentIndex=-1, numDependentItems; int32_t numYNames; SDDS_RegisterProgramName(argv[0]); argc = scanargs(&s_arg, argc, argv); if (argc<2 || argc>(3+N_OPTIONS)) { fprintf(stderr, "usage: %s\n", USAGE); fprintf(stderr, "%s%s", additional_help, additional_help2); exit(1); } input = output = NULL; xName = yName = xSigmaName = ySigmaControlString = NULL; yNames = ySigmaNames = NULL; numDependentItems = 0; modifySigmas = reviseOrders = chebyshev = 0; order = NULL; symmetry = NO_SYMMETRY; xMin = xMax = 0; generateSigmas = 0; sigmasMode = -1; sigmas = 1; sparseInterval = 1; terms = 2; verbose = ignoreSigmas = 0; normTerm = -1; xOffset = 0; xScaleFactor = 1; coefUnits = NULL; basis_fn = ipower; basis_dfn = dipower; pipeFlags = 0; evalParameters.file = NULL; infoFile = NULL; termsGiven = 0; for (iArg=1; iArg=xMax) SDDS_Bomb("incorrect -range syntax"); break; case CLO_GENERATESIGMAS: generateSigmas = FLGS_GENERATESIGMAS; if (s_arg[iArg].n_items>1) { if (s_arg[iArg].n_items!=2) SDDS_Bomb("incorrect -generateSigmas synax"); if (strncmp(s_arg[iArg].list[1], "keepsmallest", strlen(s_arg[iArg].list[1]))==0) generateSigmas |= FLGS_KEEPSMALLEST; if (strncmp(s_arg[iArg].list[1], "keeplargest", strlen(s_arg[iArg].list[1]))==0) generateSigmas |= FLGS_KEEPLARGEST; if ((generateSigmas&FLGS_KEEPSMALLEST) && (generateSigmas&FLGS_KEEPLARGEST)) SDDS_Bomb("ambiguous -generateSigmas synax"); } break; case CLO_TERMS: if (order) SDDS_Bomb("give -order or -terms, not both"); if (s_arg[iArg].n_items!=2 || sscanf(s_arg[iArg].list[1], "%ld", &terms)!=1) SDDS_Bomb("invalid -terms syntax"); termsGiven = 1; break; case CLO_XOFFSET: if (s_arg[iArg].n_items!=2 || sscanf(s_arg[iArg].list[1], "%lf", &xOffset)!=1) SDDS_Bomb("invalid -xOffset syntax"); break; case CLO_SYMMETRY: if (s_arg[iArg].n_items==2) { if ((symmetry=match_string(s_arg[iArg].list[1], symmetry_options, N_SYMMETRY_OPTIONS, 0))<0) SDDS_Bomb("unknown option used with -symmetry"); } else SDDS_Bomb("incorrect -symmetry syntax"); break; case CLO_SIGMAS: if (s_arg[iArg].n_items!=3) SDDS_Bomb("incorrect -sigmas syntax"); if (sscanf(s_arg[iArg].list[1], "%lf", &sigmas)!=1) SDDS_Bomb("couldn't scan value for -sigmas"); if ((sigmasMode=match_string(s_arg[iArg].list[2], sigmas_options, N_SIGMAS_OPTIONS, 0))<0) SDDS_Bomb("unrecognized -sigmas mode"); break; case CLO_SPARSE: if (s_arg[iArg].n_items!=2) SDDS_Bomb("incorrect -sparse syntax"); if (sscanf(s_arg[iArg].list[1], "%ld", &sparseInterval)!=1) SDDS_Bomb("couldn't scan value for -sparse"); if (sparseInterval<1) SDDS_Bomb("invalid -sparse value"); break; case CLO_VERBOSE: verbose = 1; break; case CLO_NORMALIZE: normTerm = 0; if (s_arg[iArg].n_items>2 || (s_arg[iArg].n_items==2 && sscanf(s_arg[iArg].list[1], "%ld", &normTerm)!=1) || normTerm<0) SDDS_Bomb("invalid -normalize syntax"); break; case CLO_REVISEORDERS: revpowThreshold = 0.1; s_arg[iArg].n_items -= 1; if (!scanItemList(&reviseOrders, s_arg[iArg].list+1, &s_arg[iArg].n_items, 0, "threshold", SDDS_DOUBLE, &revpowThreshold, 1, 0, "verbose", -1, NULL, 1, REVPOW_VERBOSE, NULL)) SDDS_Bomb("invalid -reviseOrders syntax"); reviseOrders |= REVPOW_ACTIVE; revpowThreshold = fabs(revpowThreshold); break; case CLO_CHEBYSHEV: if (s_arg[iArg].n_items>2 || (s_arg[iArg].n_items==2 && strncmp(s_arg[iArg].list[1], "convert", strlen(s_arg[iArg].list[1]))!=0)) SDDS_Bomb("invalid -chebyshev syntax"); chebyshev = s_arg[iArg].n_items; basis_fn = tcheby; basis_dfn = dtcheby; break; case CLO_XFACTOR: if (s_arg[iArg].n_items!=2 || sscanf(s_arg[iArg].list[1], "%lf", &xScaleFactor)!=1 || xScaleFactor==0) SDDS_Bomb("invalid -xFactor syntax"); break; case CLO_INDEPENDENT: if (s_arg[iArg].n_items!=2) SDDS_Bomb("invalid -independent syntax"); xName = s_arg[iArg].list[1]; break; case CLO_DEPENDENT: numDependentItems = s_arg[iArg].n_items-1; cloDependentIndex = iArg; if (numDependentItems<1) SDDS_Bomb("invalid -dependent syntax"); break; case CLO_SIGMAINDEPENDENT: if (s_arg[iArg].n_items!=2) SDDS_Bomb("invalid -sigmaIndependent syntax"); xSigmaName = s_arg[iArg].list[1]; break; case CLO_SIGMADEPENDENT: if (s_arg[iArg].n_items!=2) SDDS_Bomb("invalid -sigmaDependent syntax"); ySigmaControlString = s_arg[iArg].list[1]; break; case CLO_FITLABELFORMAT: if (s_arg[iArg].n_items!=2) SDDS_Bomb("invalid -fitLabelFormat syntax"); fitLabelFormat = s_arg[iArg].list[1]; break; case CLO_PIPE: if (!processPipeOption(s_arg[iArg].list+1, s_arg[iArg].n_items-1, &pipeFlags)) SDDS_Bomb("invalid -pipe syntax"); break; case CLO_INFOFILE: if (s_arg[iArg].n_items!=2) SDDS_Bomb("invalid -infoFile syntax"); infoFile = s_arg[iArg].list[1]; break; case CLO_EVALUATE: if (s_arg[iArg].n_items<2) SDDS_Bomb("invalid -evaluate syntax"); evalParameters.file = s_arg[iArg].list[1]; s_arg[iArg].n_items -= 2; s_arg[iArg].list += 2; if (!scanItemList(&evalParameters.flags, s_arg[iArg].list, &s_arg[iArg].n_items, 0, "begin", SDDS_DOUBLE, &evalParameters.begin, 1, EVAL_BEGIN_GIVEN, "end", SDDS_DOUBLE, &evalParameters.end, 1, EVAL_END_GIVEN, "number", SDDS_LONG, &evalParameters.number, 1, EVAL_NUMBER_GIVEN, NULL)) SDDS_Bomb("invalid -evaluate syntax"); break; default: bomb("unknown switch", USAGE); break; } } else { if (input==NULL) input = s_arg[iArg].list[0]; else if (output==NULL) output = s_arg[iArg].list[0]; else SDDS_Bomb("too many filenames"); } } processFilenames("sddspfit", &input, &output, pipeFlags, 0, NULL); if (symmetry && order) SDDS_Bomb("can't specify both -symmetry and -orders"); if (!xName || !numDependentItems) SDDS_Bomb("you must specify a column name for x and y"); if (modifySigmas && !xSigmaName) SDDS_Bomb("you must specify x sigmas with -modifySigmas"); if (generateSigmas) { if (modifySigmas) SDDS_Bomb("you can't specify both -generateSigmas and -modifySigmas"); } if (ySigmaControlString) { if (sigmasMode!=-1) SDDS_Bomb("you can't specify both -sigmas and a y sigma name"); } ySigmasValid = 0; if (sigmasMode!=-1 || generateSigmas || ySigmaControlString || modifySigmas) ySigmasValid = 1; if (normTerm>=0 && normTerm>=terms) SDDS_Bomb("can't normalize to that term--not that many terms"); if (reviseOrders && !(sigmasMode!=-1 || generateSigmas || ySigmaNames)) SDDS_Bomb("can't use -reviseOrders unless a y sigma or -generateSigmas is given"); if (symmetry==EVEN_SYMMETRY) { order = tmalloc(sizeof(*order)*terms); for (i=0; i0) { if ((points = SDDS_CountRowsOfInterest(&SDDSin))=xMin) { x[j] = xOrig[i]; for (colIndex=0; colIndexsy[colIndex][i]) sy[colIndex][i] = sigma; } else { sy[colIndex][i] = sigma; } } for (i=0; isy0[colIndex][i]) sy0[colIndex][i] = sigma; } else { sy0[colIndex][i] = sigma; } } } } } if (reviseOrders&REVPOW_ACTIVE) { double bestChi; long bestTerms, newBest; int32_t *bestOrder; bestTerms = terms; bestOrder = tmalloc(sizeof(*bestOrder)*bestTerms); for (ip=0; ip=0; ip--) { for (i=j=0; i=0 && terms>normTerm) { if (coef[normTerm]!=0) fprintf(fpo, "%s coefficients are normalized with factor %21.15le to make a[%ld]==1\n", prepend, coef[normTerm], (order?order[normTerm]:normTerm)); else { fprintf(fpo, "%s can't normalize coefficients as requested: a[%ld]==0\n", prepend, (order?order[normTerm]:normTerm)); normTerm = -1; } } else normTerm = -1; for (i=0; i1) { sprintf(buffer2, "$a%" PRId32 "$n", order[i]); strcat(buffer1, buffer2); } } if ((long)(strlen(buffer)+strlen(buffer1))>(long)(0.95*bufsize)) { fprintf(stderr, "buffer overflow making fit label!\n"); return; } strcat(buffer, buffer1); } } double rms_average(double *x, int n) { double sum2; int i; for (i=sum2=0; i=0) { sprintf(buffer, "%sIntercept", yNames[colIndex]); iIntercept[colIndex]= SDDS_DefineParameter(SDDSoutInfo, buffer, buffer, coefUnits[colIndex][i], "Intercept of fit", NULL, SDDS_DOUBLE, NULL); sprintf(buffer, "%sInterceptSigma", yNames[colIndex]); if (sigmasValid) iInterceptSigma[colIndex] = SDDS_DefineParameter(SDDSoutInfo, buffer, buffer, coefUnits[colIndex][i], "Sigma of intercept of fit", NULL, SDDS_DOUBLE, NULL); } sprintf(buffer, "%sSlope", yNames[colIndex]); if ((i=coefficient_index(order, terms, 1))>=0) { iSlope[colIndex] = SDDS_DefineParameter(SDDSoutInfo, buffer, buffer, coefUnits[colIndex][i], "Slope of fit", NULL, SDDS_DOUBLE, NULL); if (sigmasValid) { sprintf(buffer, "%sSlopeSigma", yNames[colIndex]); iSlopeSigma[colIndex] = SDDS_DefineParameter(SDDSoutInfo, buffer, buffer, coefUnits[colIndex][i], "Sigma of slope of fit", NULL, SDDS_DOUBLE, NULL); } } if ((i=coefficient_index(order, terms, 2))>=0) { sprintf(buffer, "%sCurvature", yNames[colIndex]); iCurvature[colIndex] = SDDS_DefineParameter(SDDSoutInfo, buffer, buffer, coefUnits[colIndex][i], "Curvature of fit", NULL, SDDS_DOUBLE, NULL); if (sigmasValid) { sprintf(buffer, "%sCurvatureSigma", yNames[colIndex]); iCurvatureSigma[colIndex] = SDDS_DefineParameter(SDDSoutInfo, buffer, buffer, coefUnits[colIndex][i], "Sigma of curvature of fit", NULL, SDDS_DOUBLE, NULL); } } if (SDDS_NumberOfErrors()) SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); } } } if (SDDS_DefineParameter(SDDSout, "Basis", NULL, NULL, "Function basis for fit", NULL, SDDS_STRING, isChebyshev?"Chebyshev T polynomials":"ordinary polynomials")<0) SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); if ((iTermsO=SDDS_DefineParameter(SDDSout, "Terms", NULL, NULL, "Number of terms in fit", NULL, SDDS_LONG, NULL))<0) SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); if (SDDS_GetColumnInformation(SDDSout, "units", &xUnits, SDDS_GET_BY_NAME, xName) !=SDDS_STRING) SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); sprintf(buffer, "%sOffset", xName); sprintf(buffer1, "Offset of %s for fit", xName); if ((iOffsetO=SDDS_DefineParameter(SDDSout, buffer, NULL, xUnits, buffer1, NULL, SDDS_DOUBLE, NULL))<0) SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); sprintf(buffer, "%sScale", xName); sprintf(buffer1, "Scale factor of %s for fit", xName); if ((iFactorO=SDDS_DefineParameter(SDDSout, buffer, NULL, xUnits, buffer1, NULL, SDDS_DOUBLE, NULL))<0) SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); for (colIndex=0; colIndex=0) { sprintf(buffer, "%sIntercept", yNames[colIndex]); iInterceptO[colIndex]= SDDS_DefineParameter(SDDSout, buffer, buffer, coefUnits[colIndex][i], "Intercept of fit", NULL, SDDS_DOUBLE, NULL); sprintf(buffer, "%sInterceptSigma", yNames[colIndex]); if (sigmasValid) iInterceptSigmaO[colIndex] = SDDS_DefineParameter(SDDSout, buffer, buffer, coefUnits[colIndex][i], "Sigma of intercept of fit", NULL, SDDS_DOUBLE, NULL); } sprintf(buffer, "%sSlope", yNames[colIndex]); if ((i=coefficient_index(order, terms, 1))>=0) { iSlopeO[colIndex] = SDDS_DefineParameter(SDDSout, buffer, buffer, coefUnits[colIndex][i], "Slope of fit", NULL, SDDS_DOUBLE, NULL); if (sigmasValid) { sprintf(buffer, "%sSlopeSigma", yNames[colIndex]); iSlopeSigmaO[colIndex] = SDDS_DefineParameter(SDDSout, buffer, buffer, coefUnits[colIndex][i], "Sigma of slope of fit", NULL, SDDS_DOUBLE, NULL); } } if ((i=coefficient_index(order, terms, 2))>=0) { sprintf(buffer, "%sCurvature", yNames[colIndex]); iCurvatureO[colIndex] = SDDS_DefineParameter(SDDSout, buffer, buffer, coefUnits[colIndex][i], "Curvature of fit", NULL, SDDS_DOUBLE, NULL); if (sigmasValid) { sprintf(buffer, "%sCurvatureSigma", yNames[colIndex]); iCurvatureSigmaO[colIndex] = SDDS_DefineParameter(SDDSout, buffer, buffer, coefUnits[colIndex][i], "Sigma of curvature of fit", NULL, SDDS_DOUBLE, NULL); } } if (SDDS_NumberOfErrors()) SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); } } if ((outputInfo && !SDDS_WriteLayout(SDDSoutInfo)) || !SDDS_WriteLayout(SDDSout)) SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); return coefUnits; } char **makeCoefficientUnits(SDDS_DATASET *SDDSout, char *xName, char *yName, int32_t *order, long terms) { char *xUnits, *yUnits, buffer[SDDS_MAXLINE]; char **coefUnits = NULL; long i; if (!SDDS_GetColumnInformation(SDDSout, "units", &xUnits, SDDS_GET_BY_NAME, xName) || !SDDS_GetColumnInformation(SDDSout, "units", &yUnits, SDDS_GET_BY_NAME, yName) ) SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); coefUnits = tmalloc(sizeof(*coefUnits)*terms); if (!xUnits || SDDS_StringIsBlank(xUnits)) { if (!yUnits || SDDS_StringIsBlank(yUnits)) SDDS_CopyString(&yUnits, ""); for (i=0; i1) sprintf(buffer, "1/%s$a%" PRId32 "$n", xUnits, order[i]-1); else strcpy(buffer, ""); SDDS_CopyString(coefUnits+i, buffer); } else { if (order[i]>1) sprintf(buffer, "%s/%s$a%" PRId32 "$n", yUnits, xUnits, order[i]); else sprintf(buffer, "%s/%s", yUnits, xUnits); SDDS_CopyString(coefUnits+i, buffer); } } } return coefUnits; } void setupEvaluationFile(EVAL_PARAMETERS *evalParameters, char *xName, char **yName, long yNames, SDDS_DATASET *SDDSin) { long i; SDDS_DATASET *SDDSout; SDDSout = &evalParameters->dataset; if (!SDDS_InitializeOutput(SDDSout, SDDS_BINARY, 0, NULL, "sddsmpfit output: evaluation of fits", evalParameters->file) || !SDDS_TransferColumnDefinition(SDDSout, SDDSin, xName, NULL)) SDDS_Bomb("Problem setting up evaluation file"); for (i=0; iflags&EVAL_BEGIN_GIVEN) || !(evalParameters->flags&EVAL_END_GIVEN)) { double min, max; find_min_max(&min, &max, x, points); if (!(evalParameters->flags&EVAL_BEGIN_GIVEN)) evalParameters->begin = min; if (!(evalParameters->flags&EVAL_END_GIVEN)) evalParameters->end = max; } if (!(evalParameters->flags&EVAL_NUMBER_GIVEN)) evalParameters->number = points; if (evalParameters->number>1) delta = (evalParameters->end - evalParameters->begin)/(evalParameters->number-1); else delta = 0; if (!xEval || maxEvalsnumber) { if (!(xEval = (double*)SDDS_Realloc(xEval, sizeof(*xEval)*evalParameters->number)) || !(yEval = (double*)SDDS_Realloc(yEval, sizeof(*yEval)*evalParameters->number))) SDDS_Bomb("allocation failure"); maxEvals = evalParameters->number; } for (i=0; inumber; i++) { xEval[i] = evalParameters->begin + i*delta; yEval[i] = eval_sum(basis_fn, coef, order, terms, xEval[i]); } if ((iYName==0 && !SDDS_StartPage(&evalParameters->dataset, evalParameters->number)) || !SDDS_SetColumnFromDoubles(&evalParameters->dataset, SDDS_SET_BY_NAME, xEval, evalParameters->number, xName) || !SDDS_SetColumnFromDoubles(&evalParameters->dataset, SDDS_SET_BY_NAME, yEval, evalParameters->number, yName[iYName]) || (iYName==yNames-1 && !SDDS_WritePage(&evalParameters->dataset))) SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); }