175 {
176
177 long binsGiven, lowerLimitGiven, upperLimitGiven;
179 double *data;
180 double *filterData;
181 double *weightData;
182 double *hist, *hist1;
183 double *CDF, *CDF1;
184 double sum;
185 double *indep;
186 double lowerLimit, upperLimit;
187 double givenLowerLimit, givenUpperLimit;
188 double range, binSize;
189 int64_t bins;
190 long doStats;
191 double mean, rms, standDev, mad;
192 char *filterColumn, *dataColumn, *weightColumn;
193 double lowerFilter = 0, upperFilter = 0;
194 int64_t points;
195 SCANNED_ARG *scanned;
196 char *inputfile, *outputfile;
197 double dx;
198 int64_t i;
199 long pointsBinned;
200 long normalizeMode, doSides, verbose, readCode;
201 int64_t rows;
202 unsigned long pipeFlags, majorOrderFlag, regionFlags = 0;
203 char *cdf;
204 double expansionFactor = 0;
205 short columnMajorOrder = -1;
206 char *regionFilename = NULL, *regionPositionColumn = NULL, *regionNameColumn = NULL;
207 double *regionPosition = NULL;
208 int64_t nRegions = 0;
209 char **regionName = NULL;
211 int threads = 1;
212
214 argc =
scanargs(&scanned, argc, argv);
215 if (argc < 3) {
216 fprintf(stderr, "%s\n", USAGE);
217 exit(EXIT_FAILURE);
218 }
219
220 binsGiven = lowerLimitGiven = upperLimitGiven = 0;
221 binSize = doSides = 0;
222 inputfile = outputfile = NULL;
223 dataColumn = filterColumn = weightColumn = NULL;
224 doStats = verbose = 0;
225 normalizeMode = NORMALIZE_NO;
226 pipeFlags = 0;
227 dx = 0;
228 cdfOnly = 0;
229 freOnly = 1;
230
231 for (i = 1; i < argc; i++) {
232 if (scanned[i].arg_type == OPTION) {
233 switch (
match_string(scanned[i].list[0], option, N_OPTIONS, 0)) {
234 case SET_MAJOR_ORDER:
235 majorOrderFlag = 0;
236 scanned[i].n_items--;
237 if (scanned[i].n_items > 0 && (!
scanItemList(&majorOrderFlag, scanned[i].list + 1, &scanned[i].n_items, 0,
"row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
"column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
238 SDDS_Bomb(
"invalid -majorOrder syntax/values");
239 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
240 columnMajorOrder = 1;
241 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
242 columnMajorOrder = 0;
243 break;
244 case SET_BINS:
245 if (binsGiven)
246 SDDS_Bomb(
"-bins specified more than once");
247 binsGiven = 1;
248 if (sscanf(scanned[i].list[1], "%" SCNd64, &bins) != 1 || bins <= 0)
250 break;
251 case SET_LOWERLIMIT:
252 if (lowerLimitGiven)
253 SDDS_Bomb(
"-lowerLimit specified more than once");
254 lowerLimitGiven = 1;
255 if (sscanf(scanned[i].list[1], "%lf", &givenLowerLimit) != 1)
256 SDDS_Bomb(
"invalid value for lowerLimit");
257 break;
258 case SET_UPPERLIMIT:
259 if (upperLimitGiven)
260 SDDS_Bomb(
"-upperLimit specified more than once");
261 upperLimitGiven = 1;
262 if (sscanf(scanned[i].list[1], "%lf", &givenUpperLimit) != 1)
263 SDDS_Bomb(
"invalid value for upperLimit");
264 break;
265 case SET_EXPAND:
266 expansionFactor = 0;
267 if (sscanf(scanned[i].list[1], "%lf", &expansionFactor) != 1 || expansionFactor <= 0)
269 break;
270 case SET_DATACOLUMN:
271 if (dataColumn)
272 SDDS_Bomb(
"-dataColumn specified more than once");
273 if (scanned[i].n_items != 2)
274 SDDS_Bomb(
"invalid -dataColumn syntax---supply name");
275 dataColumn = scanned[i].list[1];
276 break;
277 case SET_FILTER:
278 if (filterColumn)
279 SDDS_Bomb(
"multiple filter specifications not allowed");
280 if (scanned[i].n_items != 4 || sscanf(scanned[i].list[2], "%lf", &lowerFilter) != 1 ||
281 sscanf(scanned[i].list[3], "%lf", &upperFilter) != 1 || lowerFilter > upperFilter)
282 SDDS_Bomb(
"invalid -filter syntax/values");
283 filterColumn = scanned[i].list[1];
284 break;
285 case SET_WEIGHTCOLUMN:
286 if (weightColumn)
287 SDDS_Bomb(
"multiple weighting columns not allowed");
288 if (scanned[i].n_items != 2)
289 SDDS_Bomb(
"-weightColumn requires a column name");
290 weightColumn = scanned[i].list[1];
291 break;
292 case SET_NORMALIZE:
293 if (scanned[i].n_items == 1)
294 normalizeMode = NORMALIZE_SUM;
295 else if (scanned[i].n_items != 2 || (normalizeMode =
match_string(scanned[i].list[1], normalize_option, N_NORMALIZE_OPTIONS, 0)) < 0)
297 break;
298 case SET_STATISTICS:
299 doStats = 1;
300 break;
301 case SET_SIDES:
302 if (scanned[i].n_items == 1)
303 doSides = 1;
304 else if (scanned[i].n_items > 2 || (sscanf(scanned[i].list[1], "%ld", &doSides) != 1 || doSides <= 0))
306 break;
307 case SET_VERBOSE:
308 verbose = 1;
309 break;
310 case SET_BINSIZE:
311 if (sscanf(scanned[i].list[1], "%le", &binSize) != 1 || binSize <= 0)
313 break;
314 case SET_PIPE:
317 break;
318 case SET_CDF:
319 if (scanned[i].n_items == 1)
320 cdfOnly = 0;
321 else {
322 if (scanned[i].n_items != 2)
324 cdf = scanned[i].list[1];
325 if (strcmp(cdf, "only") != 0)
326 SDDS_Bomb(
"invalid -cdf value, it should be -cdf or -cdf=only");
327 cdfOnly = 1;
328 }
329 freOnly = 0;
330 break;
331 case SET_REGION_FILE:
332 if (scanned[i].n_items != 4)
334 regionFlags = 0;
335 scanned[i].n_items -= 1;
336 if (!
scanItemList(®ionFlags, scanned[i].list + 1, &scanned[i].n_items, 0,
338 "position",
SDDS_STRING, ®ionPositionColumn, 1, 2,
339 "name",
SDDS_STRING, ®ionNameColumn, 1, 4, NULL) ||
340 regionFlags != (1 + 2 + 4) || !regionFilename || !regionPositionColumn || !regionNameColumn)
342 break;
343 case SET_THREADS:
344 if (scanned[i].n_items != 2 ||
345 !sscanf(scanned[i].list[1], "%d", &threads) || threads < 1)
347 break;
348 default:
349 fprintf(stderr, "Error: option %s not recognized\n", scanned[i].list[0]);
350 exit(EXIT_FAILURE);
351 break;
352 }
353 } else {
354
355 if (!inputfile)
356 inputfile = scanned[i].list[0];
357 else if (!outputfile)
358 outputfile = scanned[i].list[0];
359 else
361 }
362 }
363
365
366 if (binSize && binsGiven && regionFlags)
367 SDDS_Bomb(
"Provide only one of -bins, -sizeOfBins, or -regions");
368 if (!binsGiven)
369 bins = 20;
370 if (!dataColumn)
371 SDDS_Bomb(
"-dataColumn must be specified");
372
373 if (regionFlags) {
374 if (!(nRegions = readRegionFile(&SDDSregion, regionFilename, regionPositionColumn, regionNameColumn, ®ionPosition, ®ionName)))
375 SDDS_Bomb(
"Problem with region file. Check existence and type of columns");
376 doSides = 0;
377 bins = nRegions + 1;
378 }
379
380 hist =
tmalloc(
sizeof(*hist) * (bins + 2 * doSides));
381 CDF = CDF1 =
tmalloc(
sizeof(*hist) * (bins + 2 * doSides));
382 indep =
tmalloc(
sizeof(*indep) * (bins + 2 * doSides));
383 pointsBinned = 0;
384
390 if (!setupOutputFile(&outTable, outputfile, &inTable, inputfile, dataColumn, weightColumn, filterColumn, lowerFilter, upperFilter, &SDDSregion, regionNameColumn, doStats, bins, binSize, normalizeMode, columnMajorOrder))
392
393 data = weightData = filterData = NULL;
401
402 if (rows && filterColumn)
403 points = filter(data, weightData, filterData, rows, lowerFilter, upperFilter);
404 else
405 points = rows;
406
407 pointsBinned = 0;
408 if (points) {
409 if (doStats) {
410 if (!weightColumn)
412 else
414 }
415
416 if (regionFlags) {
417 classifyByRegion(data, weightData, points, hist, regionPosition, bins);
418 hist1 = hist;
419 } else {
420 if (!lowerLimitGiven) {
421 lowerLimit = (points > 0) ? data[0] : 0;
422 for (i = 0; i < points; i++)
423 if (lowerLimit > data[i])
424 lowerLimit = data[i];
425 } else {
426 lowerLimit = givenLowerLimit;
427 }
428 if (!upperLimitGiven) {
429 upperLimit = (points > 0) ? data[0] : 0;
430 for (i = 0; i < points; i++)
431 if (upperLimit < data[i])
432 upperLimit = data[i];
433 } else {
434 upperLimit = givenUpperLimit;
435 }
436
437 range = upperLimit - lowerLimit;
438 if (!lowerLimitGiven)
439 lowerLimit -= range * 1e-7;
440 if (!upperLimitGiven)
441 upperLimit += range * 1e-7;
442 if (upperLimit == lowerLimit) {
443 if (binSize) {
444 upperLimit += binSize / 2;
445 lowerLimit -= binSize / 2;
446 } else if (fabs(upperLimit) < sqrt(DBL_MIN)) {
447 upperLimit = sqrt(DBL_MIN);
448 lowerLimit = -sqrt(DBL_MIN);
449 } else {
450 upperLimit += upperLimit * (1 + 2 * DBL_EPSILON);
451 lowerLimit -= upperLimit * (1 - 2 * DBL_EPSILON);
452 }
453 }
454 if (expansionFactor > 0) {
455 double center = (upperLimit + lowerLimit) / 2;
456 range = expansionFactor * (upperLimit - lowerLimit);
457 lowerLimit = center - range / 2;
458 upperLimit = center + range / 2;
459 }
460 dx = (upperLimit - lowerLimit) / bins;
461
462 if (binSize) {
463 double middle;
464 range = ((range / binSize) + 1) * binSize;
465 middle = (lowerLimit + upperLimit) / 2;
466 lowerLimit = middle - range / 2;
467 upperLimit = middle + range / 2;
468 dx = binSize;
469 bins = range / binSize + 0.5;
470 if (bins < 1 && !doSides)
471 bins = 2 * doSides;
472 indep =
trealloc(indep,
sizeof(*indep) * (bins + 2 * doSides));
473 hist =
trealloc(hist,
sizeof(*hist) * (bins + 2 * doSides));
474 CDF =
trealloc(CDF,
sizeof(*hist) * (bins + 2 * doSides));
475 }
476
477 for (i = -doSides; i < bins + doSides; i++)
478 indep[i + doSides] = (i + 0.5) * dx + lowerLimit;
479 hist1 = hist + doSides;
480 CDF1 = CDF + doSides;
481 if (doSides) {
482 hist[0] = hist[bins + doSides] = 0;
483 }
484
485 if (!weightColumn)
486 pointsBinned = make_histogram_threaded(hist1, bins, lowerLimit, upperLimit, data, points, 1, threads);
487 else
488 pointsBinned = make_histogram_weighted_threaded(hist1, bins, lowerLimit, upperLimit, data, points, 1, weightData, threads);
489 }
490
491 sum = 0;
492 for (i = 0; i < bins + doSides; i++) {
493 sum += hist1[i];
494 }
495 CDF1[0] = hist1[0] / sum;
496 for (i = 1; i < bins + doSides; i++) {
497 CDF1[i] = CDF1[i - 1] + hist1[i] / sum;
498 }
499
500 if (verbose)
501 fprintf(stderr, "%ld points of %" PRId64 " from page %ld histogrammed in %" PRId64 " bins\n", pointsBinned, rows, readCode, bins);
502 if (!cdfOnly) {
503 if (normalizeMode != NORMALIZE_NO) {
504 double norm = 0;
505 switch (normalizeMode) {
506 case NORMALIZE_PEAK:
508 break;
509 case NORMALIZE_AREA:
510 case NORMALIZE_SUM:
511 for (i = 0; i < bins; i++)
512 norm += hist1[i];
513 if (normalizeMode == NORMALIZE_AREA)
514 norm *= dx;
515 break;
516 default:
517 SDDS_Bomb(
"invalid normalize mode--consult programmer.");
518 break;
519 }
520 if (norm)
521 for (i = 0; i < bins; i++)
522 hist1[i] /= norm;
523 }
524 }
525 }
526
527 if (regionFlags) {
530 !
SDDS_SetParameters(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iBins, bins, iBinSize, dx, iPoints, pointsBinned, -1))
532 if (points) {
533 if (!
SDDS_SetColumn(&outTable, SDDS_SET_BY_INDEX, regionPosition, bins, iIndep) ||
534 !
SDDS_SetColumn(&outTable, SDDS_SET_BY_NAME, regionName, bins, regionNameColumn))
536 if (!freOnly && !
SDDS_SetColumn(&outTable, SDDS_SET_BY_INDEX, CDF, bins, iCdf))
538 if (!cdfOnly && !
SDDS_SetColumn(&outTable, SDDS_SET_BY_INDEX, hist, bins, iFreq))
540 }
541 } else {
544 (points && (!
SDDS_SetColumn(&outTable, SDDS_SET_BY_INDEX, indep, bins + 2 * doSides, iIndep))) ||
545 !
SDDS_SetParameters(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iBins, bins, iBinSize, dx, iPoints, pointsBinned, -1))
547 if (!freOnly) {
548 if (points && !
SDDS_SetColumn(&outTable, SDDS_SET_BY_INDEX, CDF, bins + 2 * doSides, iCdf))
550 }
551 if (!cdfOnly) {
552 if (points && !
SDDS_SetColumn(&outTable, SDDS_SET_BY_INDEX, hist, bins + 2 * doSides, iFreq))
554 }
555 }
556
557 if (filterColumn && points &&
558 !
SDDS_SetParameters(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iLoFilter, lowerFilter, iUpFilter, upperFilter, -1))
560 if (doStats && points &&
561 !
SDDS_SetParameters(&outTable, SDDS_SET_BY_INDEX | SDDS_PASS_BY_VALUE, iMean, mean, iRMS, rms, iStDev, standDev, -1))
563
566 if (data)
567 free(data);
568 if (weightData)
569 free(weightData);
570 if (filterData)
571 free(filterData);
572 data = weightData = filterData = NULL;
573 }
574
577 exit(EXIT_FAILURE);
578 }
581 exit(EXIT_FAILURE);
582 }
583 return EXIT_SUCCESS;
584}
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_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.
int32_t SDDS_GetColumnIndex(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the index of a named column in the SDDS dataset.
void SDDS_PrintErrors(FILE *fp, int32_t mode)
Prints recorded error messages to a specified file stream.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
#define SDDS_STRING
Identifier for the string data type.
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
double max_in_array(double *array, long n)
Finds the maximum value in an array 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.
long computeWeightedMomentsThreaded(double *mean, double *rms, double *standDev, double *meanAbsoluteDev, double *x, double *w, long n, long numThreads)
Computes weighted statistical moments of an array using multiple threads.
long computeMomentsThreaded(double *mean, double *rms, double *standDev, double *meanAbsoluteDev, double *x, long n, long numThreads)
Computes the mean, RMS, standard deviation, and mean absolute deviation of an array using multiple th...
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)
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.