/*************************************************************************\ * 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: sddsrunstats * $Log: sddsrunstats.c,v $ Revision 1.18 2008/01/24 19:12:33 shang added -median option Revision 1.17 2006/12/14 22:22:00 soliday Updated a bunch of programs because SDDS_SaveLayout is now called by SDDS_WriteLayout and it is no longer required to be called directly. Also the AutoCheckMode is turned off by default now so I removed calls to SDDS_SetAutoCheckMode that would attempt to turn it off. It is now up to the programmer to turn it on in new programs until debugging is completed and then remove the call to SDDS_SetAutoCheckMode. Revision 1.16 2006/10/19 17:55:40 soliday Updated to work with linux-x86_64. Revision 1.15 2005/11/04 22:46:17 soliday Updated code to be compiled by a 64 bit processor. Revision 1.14 2004/03/16 23:44:24 borland Fixed parsing bug that caused problems when column named looked like an abbreviated tag name Revision 1.13 2004/03/16 23:25:38 borland Added option to scanItemList to prevent problems when a column is specified that happens to look like a qualifier name. Revision 1.12 2003/06/15 17:32:33 borland If number of points is 0, now does stats on the whole page. Revision 1.11 2002/08/14 17:12:53 soliday Added Open License Revision 1.10 2001/05/18 21:35:50 borland Fixed memory leak. Revision 1.9 2001/01/10 19:35:46 soliday Standardized usage message. Revision 1.8 1999/05/25 19:14:44 soliday Removed compiler warning on linux. Revision 1.7 1999/01/06 19:54:55 borland Fixed the version number in the usage message. Revision 1.6 1998/12/16 21:26:06 borland Brought up to date with new version of SDDS_TransferAllParameters. Now correctly transfers through parameters, but overwrites them if it needs to do so. Revision 1.5 1998/08/14 17:13:24 borland Improved the way the number of output rows is computed. Now allows statistics on partial segments, if -partialOk option is given. Revision 1.4 1998/01/10 18:26:13 borland Now works properly in overlap mode with -window option. Revision 1.3 1997/10/30 20:21:28 borland Added option to block the points using a window on a specified column. So, for example, one can now average points over specified time intervals. Revision 1.2 1996/11/13 18:17:13 borland Now actually does *running* statistics in addition to blocked statistics. Revision 1.1 1996/11/13 03:44:32 borland First version. * */ #include "mdb.h" #include "scan.h" #include "SDDS.h" #include "SDDSutils.h" #include /* if statistics are added, they must be added before the SET_POINTS item in this list and the following options array */ #define SET_MAXIMUM 0 #define SET_MINIMUM 1 #define SET_MEAN 2 #define SET_STANDARDDEVIATION 3 #define SET_RMS 4 #define SET_SUM 5 #define SET_SIGMA 6 #define SET_SAMPLE 7 #define SET_MEDIAN 8 #define N_STATS 9 #define SET_POINTS 9 #define SET_NOOVERLAP 10 #define SET_PIPE 11 #define SET_WINDOW 12 #define SET_PARTIALOK 13 #define N_OPTIONS 14 char *option[N_OPTIONS] = { "maximum", "minimum", "mean", "standarddeviation", "rms", "sum", "sigma", "sample", "median", "points", "nooverlap", "pipe", "window", "partialok", } ; char *statSuffix[N_STATS] = { "Max", "Min", "Mean", "StDev", "RMS", "Sum", "Sigma", "", "Median", } ; #define TOPLIMIT_GIVEN 0x0001U #define BOTTOMLIMIT_GIVEN 0x0002U /* this structure stores a command-line request for statistics computation */ /* individual elements of sourceColumn may contain wildcards */ typedef struct { char **sourceColumn; long sourceColumns, sumPower, optionCode; unsigned long flags; double topLimit, bottomLimit; } STAT_REQUEST; /* this structure stores data necessary for accessing/creating SDDS columns and * for computing a statistic */ typedef struct { char **sourceColumn, **resultColumn; long sourceColumns, optionCode, *resultIndex, sumPower; unsigned long flags; double topLimit, bottomLimit; } STAT_DEFINITION; long addStatRequests(STAT_REQUEST **statRequest, long requests, char **item, long items, long code, unsigned long flag); STAT_DEFINITION *compileStatDefinitions(SDDS_DATASET *inTable, STAT_REQUEST *request, long requests); long setupOutputFile(SDDS_DATASET *outTable, char *output, SDDS_DATASET *inTable, STAT_DEFINITION *stat, long stats); static char *USAGE="sddsrunstats [] [] [-pipe[=input][,output]]\n\ [{-points= | -window=column=,width=}] [-noOverlap]\n\ [-partialOk]\n\ [-mean=[],]\n\ [-median=[],]\n\ [-minimum=[],]\n\ [-maximum=[],]\n\ [-standardDeviation=[],]\n\ [-sigma=[],]\n\ [-sum=[][,power=],] \n\ [-sample=[],]]\n\n\ is of the form [topLimit=,][bottomLimit=]\n\n\ Computes running statistics of columns of data. The may contain\n\ wildcards, in which case an additional output column is produced for every matching\n\ column. By default, statistics are done with a sliding window, so the values are\n\ running statistics; for blocked statistics, use -noOverlap. For statistics on\n\ the entire page, use -points=0.\n\ The -partialOk option tells sddsrunstats to do computations even\n\ if the number of available rows is less than the number of points\n\ specified; by default, such data is simply ignored.\n\ Program by Michael Borland. (This is version 4, December 1998.)\n"; int main(int argc, char **argv) { STAT_DEFINITION *stat; long stats; STAT_REQUEST *request; long requests, count; SCANNED_ARG *scanned; SDDS_DATASET inData, outData; int32_t power; long pointsToStat, pointsToStat0, overlap, rows, outputRowsMax, outputRows, outputRow; long iArg, code, iStat, iColumn; long startRow, rowOffset; char *input, *output, *windowColumn; double *inputData, *outputData, topLimit, bottomLimit, *inputDataOffset, result, sum1, sum2, *newData; double windowWidth, *windowData; long windowIndex; unsigned long pipeFlags, scanFlags; char s[100]; long lastRegion, region, windowRef, partialOk; SDDS_RegisterProgramName(argv[0]); argc = scanargs(&scanned, argc, argv); if (argc<2) { bomb("too few arguments", USAGE); } newData = NULL; result = 0; input = output = NULL; stat = NULL; request = NULL; stats = requests = pipeFlags = 0; pointsToStat = -1; partialOk = 0; overlap = 1; windowColumn = NULL; windowData = NULL; for (iArg=1; iArg0) { rows = SDDS_CountRowsOfInterest(&inData); pointsToStat = pointsToStat0; if (pointsToStat==0) pointsToStat = rows; if (windowColumn && !(windowData = SDDS_GetColumnInDoubles(&inData, windowColumn))) { SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); } if (!windowColumn) { if (rowsoutputRowsMax && !(outputData = SDDS_Realloc(outputData, sizeof(*outputData)*(outputRowsMax=outputRows)))) SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors|SDDS_EXIT_PrintErrors); for (iStat=0; iStatrows) { pointsToStat = rows-startRow-1; if (pointsToStat<=0) break; } #ifdef DEBUG fprintf(stderr, "row=%ld pointsToStat=%ld delta=%.9lf (%.9lf -> %.9lf)\n", startRow, pointsToStat, windowData[startRow+pointsToStat-1] - windowData[startRow], windowData[startRow], windowData[startRow+pointsToStat-1]); #endif } inputDataOffset = inputData+startRow; switch (stat[iStat].optionCode) { case SET_MAXIMUM: result = -DBL_MAX; for (rowOffset=0; rowOffsetstat[iStat].topLimit) || (stat[iStat].flags&BOTTOMLIMIT_GIVEN && inputDataOffset[rowOffset]result) result = inputDataOffset[rowOffset]; } break; case SET_MINIMUM: result = DBL_MAX; for (rowOffset=0; rowOffsetstat[iStat].topLimit) || (stat[iStat].flags&BOTTOMLIMIT_GIVEN && inputDataOffset[rowOffset]stat[iStat].topLimit) || (stat[iStat].flags&BOTTOMLIMIT_GIVEN && inputDataOffset[rowOffset]stat[iStat].topLimit) || (stat[iStat].flags&BOTTOMLIMIT_GIVEN && inputDataOffset[rowOffset]stat[iStat].topLimit) || (stat[iStat].flags&BOTTOMLIMIT_GIVEN && inputDataOffset[rowOffset]1) { if ((result = sum2/count - sqr(sum1/count))<=0) result = 0; else result = sqrt(result*count/(count-1.0)); if (stat[iStat].optionCode==SET_SIGMA) result /= sqrt(count); } break; case SET_RMS: sum2 = count = 0; for (rowOffset=0; rowOffsetstat[iStat].topLimit) || (stat[iStat].flags&BOTTOMLIMIT_GIVEN && inputDataOffset[rowOffset]0) result = sqrt(sum2/count); else result = DBL_MAX; break; case SET_SUM: sum1 = count = 0; for (rowOffset=0; rowOffsetstat[iStat].topLimit) || (stat[iStat].flags&BOTTOMLIMIT_GIVEN && inputDataOffset[rowOffset]0) result = sum1; else result = DBL_MAX; break; case SET_SAMPLE: result = DBL_MAX; for (rowOffset=0; rowOffsetstat[iStat].topLimit) || (stat[iStat].flags&BOTTOMLIMIT_GIVEN && inputDataOffset[rowOffset]