/*************************************************************************\ * 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 sddsslopes1 * makes lsf subroutine calls * for columns across pages in a sddsexperiment output file. * The independent variable must be a defined column. * The output file contains one table of slopes and intercepts. * The independent column of the input file * is removed in the output file, but its name is * converted to a parameter string. * L. Emery with some code from M. Borland, ANL (1995) * added sigma for slopes and intercept 5/18/95 $Log: sddsslopes.c,v $ Revision 1.17 2005/11/04 22:46:18 soliday Updated code to be compiled by a 64 bit processor. Revision 1.16 2002/08/14 17:12:55 soliday Added Open License Revision 1.15 2001/01/10 19:35:47 soliday Standardized usage message. Revision 1.14 1999/05/25 19:15:52 soliday Removed compiler warning on linux. Revision 1.13 1999/01/06 19:54:57 borland Fixed the version number in the usage message. Revision 1.12 1998/08/04 20:56:09 emery Chnged to in usage message. * Revision 1.11 1996/04/28 22:22:39 emery * Corrected "grammar" of usage message. * * Revision 1.10 1996/04/24 08:42:56 emery * Added an absent malloc for array depVar. Put some statements inside of * an if (ipage==1) block. Put a SDDS_CopyPage outside of an if (ipage==1) block. * * Revision 1.9 1996/04/12 18:43:32 emery * Added -range=, option, which allows the fitting restricted * over a range of independent variable values. The residual data file * still uses all original independent variable values. * * Revision 1.8 1996/03/21 05:14:25 emery * Now repeats slope calculation for each data page. * * Revision 1.7 1995/11/26 17:59:42 borland * Fixed bug introduced in previous modification; was setting weights array * to all 1's, which wiped out any other data in the array. * * Revision 1.6 1995/11/07 00:38:56 emery * Fixed bug: array weight was not initialized in some cases. * * Revision 1.5 1995/10/18 22:35:03 borland * Added an SDDS_CheckColumn call to report problems with independent column * in more detail. * * Revision 1.4 1995/10/16 18:36:07 borland * Fixed bugs with -sigma option (not setting weights to 1 before prelimiary fit.) * Rewrote some constructs of the form if (x) { } else if (!x) { }, as * if (x) { } else { }. * * Revision 1.3 1995/09/06 14:57:12 saunders * First test release of SDDS1.5 * */ #include "mdb.h" #include "scan.h" #include "match_string.h" #include "SDDS.h" #define CLO_INDEPENDENT_COLUMN 0 #define CLO_COLUMNS 1 #define CLO_EXCLUDE 2 #define CLO_VERBOSE 3 #define CLO_SIGMA 4 #define CLO_ASCII 5 #define CLO_PIPE 6 #define CLO_RESIDUAL 7 #define CLO_RANGE 8 #define COMMANDLINE_OPTIONS 9 char *commandline_option[COMMANDLINE_OPTIONS] = { "independentVariable", "columns", "excludeColumns", "verbose", "sigma", "ascii", "pipe", "residual", "range" }; #define SIGMA_GENERATE 0 #define SIGMA_OPTIONS 1 char *sigma_option[SIGMA_OPTIONS] = { "generate" }; #define DEFAULT_EXCLUDED_COLUMNS 1 char *defaultExcludedColumn[DEFAULT_EXCLUDED_COLUMNS] = { "Time", }; static char *USAGE = "sddsslopes [-pipe=[input][,output]]\n\ -independentVariable= [-range=,]\n\ [-columns=] [-excludeColumns=] \n\ [-sigma[=generate]] [-residual=] [-ascii] [-verbose]\n\n\ Makes straight line fits of numerical column data in the input file, using one particular column\n\ as an independent variable.\n\ pipe reads input or output from a pipe.\n\ inputfile file with an independent variable column.\n\ outputfile file with the slope and intercept of each column of the SDDSinputfile.\n\ The selected numerical columns for fitting appear with the names Slopes\n\ and Intercept.\n\ independentVariable name of independent variable (default is the first numerical column)\n\ range specify range of independent variable to fit over.\n\ columns columns individually paired with independentVariable for straight line fitting.\n\ excludeColumns columns to exclude from fitting.\n\ sigma calculates errors by interpreting column names Sigma or Sigma as\n\ sigma of column . If these columns don't exist\n\ then the program generates a common sigma from the residual of a first fit,\n\ and refits with these sigmas. If option -sigma=generate is given,\n\ then sigmas are generated from the residual of a first fit for all columns,\n\ irrespective of the presence of columns Sigma or Sigma.\n\ residual file in which the deviation from the linear fit is written.\n\ ascii make slopes output file in ascii mode (binary is the default)\n\ verbose prints some output to stderr\n\ Program by Louis Emery, ANL (This is version 2, August 1998.)"; long set_multicolumn_flags(SDDS_TABLE *SDDSin, char ***column, int32_t *columns, char **exclude, long excludes); int main(int argc, char **argv) { SCANNED_ARG *scanned; SDDS_TABLE inputPage, outputPage, residualPage; char *inputfile, *outputfile; char **column, **excludeColumn; int32_t columns; long excludeColumns; char *indColumnName; long verbose; long iArg, i, j, ipage; double *indVar, *indVarOrig; char *indVarUnits; char **intColumn, **slopeColumn, **slopeSigmaColumn, **interceptSigmaColumn; char *Units,*slopeUnits; double *depVar, *depVarOrig; long order; double *coef, *coefsigma, *weight, *diff, *diffOrig, chi; long iCol, iRow; long rows, rowsOrig; double rmsResidual; double slopeSigma, interceptSigma; char **sigmaColumn, **chiSquaredColumn; long *sigmaColumnExists; long doSlopeSigma, generateSigma, doPreliminaryFit; long validSigmas; double sigmaSum, averageSigma; long ascii; char *residualFile; unsigned long pipeFlags; long tmpfile_used, noWarnings; double xMin, xMax; indVar = indVarOrig = depVar = depVarOrig = coef = coefsigma = weight = diff = NULL; intColumn = slopeColumn = slopeSigmaColumn = interceptSigmaColumn = sigmaColumn = chiSquaredColumn = NULL; slopeUnits = NULL; sigmaColumnExists = NULL; SDDS_RegisterProgramName(argv[0]); argc = scanargs(&scanned, argc, argv); if (argc == 1) bomb(NULL, USAGE); inputfile = outputfile = NULL; columns = excludeColumns = 0; column = excludeColumn = NULL; indColumnName = NULL; verbose = 0; doSlopeSigma = 0; generateSigma = 0; doPreliminaryFit = 0; ascii = 0; pipeFlags = 0; tmpfile_used=0; noWarnings=0; residualFile = NULL; xMin = xMax = 0; for (iArg = 1; iArg 1 ) { switch (match_string(scanned[iArg].list[1], sigma_option, SIGMA_OPTIONS, UNIQUE_MATCH)) { case SIGMA_GENERATE: generateSigma = 1; break; default: SDDS_Bomb("unrecognized sigma option given"); break; } } break; case CLO_RESIDUAL: if (!(residualFile=scanned[iArg].list[1])){ fprintf(stderr,"No file specified in -residual option.\n"); exit(1); } break; case CLO_RANGE: if (scanned[iArg].n_items!=3 || 1!=sscanf(scanned[iArg].list[1], "%lf", &xMin) || 1!=sscanf(scanned[iArg].list[2], "%lf", &xMax) || xMin>=xMax) SDDS_Bomb("incorrect -range syntax"); break; default: SDDS_Bomb("unrecognized option given"); break; } } else { if (!inputfile) inputfile = scanned[iArg].list[0]; else if (!outputfile) outputfile = scanned[iArg].list[0]; else SDDS_Bomb("too many filenames given"); } } if (residualFile && outputfile) { if (!strcmp( residualFile, outputfile)) { fprintf( stderr, "Residual file can't be the same as the output file.\n"); exit(1); } } processFilenames("sddsslopes", &inputfile, &outputfile, pipeFlags, noWarnings, &tmpfile_used); if (!indColumnName) { fprintf( stderr, "independentVariable not given\n"); exit(1); } if (!excludeColumns) { excludeColumn = defaultExcludedColumn; excludeColumns = DEFAULT_EXCLUDED_COLUMNS; } if (verbose) fprintf(stderr,"Reading file %s.\n",inputfile); if ( !SDDS_InitializeInput( &inputPage, inputfile) ) SDDS_PrintErrors( stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors); while (0 < (ipage=SDDS_ReadTable( &inputPage))) { if (verbose) { fprintf(stderr, "working on page %ld\n", ipage); } rows = SDDS_CountRowsOfInterest(&inputPage); rowsOrig = rows; /*************************************\ * make array of independent variable \*************************************/ if (ipage==1) { indVar = (double*) malloc( sizeof(*indVar) * rows); } else { indVar = (double*) realloc( indVar, sizeof(*indVar) * rows); } if (ipage==1) { if (!SDDS_FindColumn(&inputPage, FIND_NUMERIC_TYPE, indColumnName, NULL)){ fprintf(stderr,"Something wrong with column %s.\n", indColumnName); SDDS_CheckColumn(&inputPage, indColumnName, NULL, SDDS_ANY_NUMERIC_TYPE, stderr); exit(1); } } /* filter out the specified range in independent variable */ if (xMin!=xMax) { if (!(indVarOrig = SDDS_GetColumnInDoubles( &inputPage, indColumnName))) SDDS_PrintErrors( stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors); for (i=j=0; i=xMin) { indVar[j] = indVarOrig[i]; j++; } } rows = j; } else { if (!(indVar = SDDS_GetColumnInDoubles( &inputPage, indColumnName))) SDDS_PrintErrors( stderr, SDDS_EXIT_PrintErrors|SDDS_VERBOSE_PrintErrors); } if ( ipage == 1 ) { if (!SDDS_GetColumnInformation(&inputPage, "units", &indVarUnits, SDDS_GET_BY_NAME, indColumnName)) SDDS_PrintErrors( stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); if (!indVarUnits) { indVarUnits = (char *) malloc(sizeof(*indVarUnits)); indVarUnits[0] = 0; } } /************************************\ * initialize residual file \************************************/ if (residualFile) { if ( ipage == 1 ) { if(!SDDS_InitializeOutput(&residualPage,ascii?SDDS_ASCII:SDDS_BINARY,1, "Residual of 2-term fit",NULL,outputfile) || !SDDS_InitializeCopy(&residualPage, &inputPage, residualFile, "w") || !SDDS_WriteLayout(&residualPage) ) SDDS_PrintErrors(stderr,SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); } if (!SDDS_CopyPage(&residualPage,&inputPage)) SDDS_PrintErrors(stderr,SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); } /************************************\ * get columns of interest. use set_multicolumn_flags to simply * return new values for array column. \*************************************/ if (!set_multicolumn_flags(&inputPage, &column, &columns, excludeColumn, excludeColumns)) { SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors); exit(1); } /************************************\ * make column names for the output \*************************************/ if (ipage==1) { intColumn = (char**) malloc((sizeof(char*)*columns)); slopeColumn = (char**) malloc((sizeof(char*)*columns)); if (doSlopeSigma) { slopeSigmaColumn = (char**) malloc((sizeof(char*)*columns)); interceptSigmaColumn = (char**) malloc((sizeof(char*)*columns)); chiSquaredColumn = (char**) malloc((sizeof(char*)*columns)); } for (i=0; iSDDS_DefineParameter(&outputPage, "InputFile", "InputFile", NULL, "InputFile", NULL, SDDS_STRING, 0) || 0>SDDS_DefineColumn(&outputPage, "IndependentVariable", NULL, NULL, NULL, NULL, SDDS_STRING,0) ) SDDS_PrintErrors(stderr,SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); for (iCol=0; iColSDDS_DefineColumn(&outputPage, intColumn[iCol], NULL, Units, NULL, NULL, SDDS_DOUBLE,0)) SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); /* units for slopes columns */ if (strlen(indVarUnits) && strlen(Units) ) { slopeUnits = (char*)malloc(sizeof(*slopeUnits)*(strlen(Units)+strlen(indVarUnits)+2)); strcat( strcat( strcpy(slopeUnits, Units), "/"), indVarUnits); } if (strlen(indVarUnits) && !strlen(Units) ) { slopeUnits = (char*)malloc(sizeof(*slopeUnits)*(strlen(indVarUnits)+2)); strcat( strcpy( slopeUnits, "1/"), indVarUnits); } if (!strlen(indVarUnits) && strlen(Units) ) { slopeUnits = (char*)malloc(sizeof(*slopeUnits)*(strlen(Units)+2)); strcpy( slopeUnits, indVarUnits); } if (!strlen(indVarUnits) && !strlen(Units) ) { slopeUnits = (char*)malloc(sizeof(*slopeUnits)); strcpy( slopeUnits, ""); } if (0>SDDS_DefineColumn(&outputPage, slopeColumn[iCol], NULL, slopeUnits, NULL, NULL, SDDS_DOUBLE,0)) SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); if (doSlopeSigma) { if (0>SDDS_DefineColumn(&outputPage, interceptSigmaColumn[iCol], NULL, Units, NULL, NULL, SDDS_DOUBLE,0) || 0>SDDS_DefineColumn(&outputPage, slopeSigmaColumn[iCol], NULL, slopeUnits, NULL, NULL, SDDS_DOUBLE,0) || 0>SDDS_DefineColumn(&outputPage, chiSquaredColumn[iCol], NULL, NULL, NULL, NULL, SDDS_DOUBLE,0)) SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); } free(slopeUnits); } if ( !SDDS_WriteLayout(&outputPage)) SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); } if ( !SDDS_StartTable(&outputPage,1) || !SDDS_SetParameters(&outputPage, SDDS_SET_BY_NAME|SDDS_PASS_BY_VALUE, "InputFile",inputfile?inputfile:"pipe",NULL) || !SDDS_SetRowValues(&outputPage, SDDS_SET_BY_NAME|SDDS_PASS_BY_VALUE, 0, "IndependentVariable", indColumnName, NULL) ) SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); /* determine which included columns has a Sigma column defined in the input file */ if ( ipage == 1 ) { sigmaColumn = (char **) malloc( sizeof(*sigmaColumn)*columns); sigmaColumnExists = (long *) malloc(columns*sizeof(*sigmaColumnExists)); for (iCol=0; iCol