109char *option[N_OPTIONS] = {
131 "Usage: sddsmultihist [<inputfile>] [<outputfile>]\n"
132 " [-pipe=[input][,output]]\n"
133 " -columns=<name>[,...]\n"
134 " -abscissa=<name>[,...]\n"
135 " [-exclude=<name>[,...]]\n"
136 " [-bins=<integer>]\n"
137 " [-sizeOfBins=<value>]\n"
138 " [-autobins=target=<number>[,minimum=<integer>][,maximum=<integer>]]\n"
139 " [-boundaryData=<filename>,<column>]\n"
140 " [-sides[=close|against]]\n"
141 " [-expand=<fraction>]\n"
142 " [-lowerLimit=<value>[,...]]\n"
143 " [-upperLimit=<value>[,...]]\n"
146 " [-weightColumn=<name>]\n"
147 " [-majorOrder=row|column]\n"
148 " [-normalize={sum|peak|no}]\n"
149 " [-threads=<number>]\n"
151 " -pipe=[input][,output] The standard SDDS Toolkit pipe option.\n"
152 " -columns=<name>[,...] Specifies the names of columns from the input to be histogrammed.\n"
153 " Names may contain wildcards.\n"
154 " -abscissa=<name>[,...] Specifies the names of the abscissas in the output file.\n"
155 " When using column names as abscissa names,\n"
156 " the -abscissa option is not required (use -separate).\n"
157 " At least one abscissa name must be supplied if -separate is not used.\n"
158 " -exclude=<name>[,...] (Optional) Specifies column names to exclude from histogramming.\n"
159 " -bins=<integer> Sets the number of bins for the histogram.\n"
160 " -sizeOfBins=<value> Sets the size of each bin for the histogram.\n"
161 " -autobins=target=<number>[,minimum=<integer>][,maximum=<integer>]\n"
162 " Automatically determines the number of bins based on the target number of samples per bin.\n"
163 " Optionally specify minimum and maximum number of bins.\n"
164 " -boundaryData=<filename>,<column> Specifies irregular bin boundaries from a file.\n"
165 " Incompatible with -separate and -abscissa.\n"
166 " -sides[=close|against] Adds zero-height bins at the ends of the histogram.\n"
167 " 'close' centers the first and last bins.\n"
168 " 'against' aligns the first and last bins with the data range.\n"
169 " -expand=<fraction> Expands the range of the histogram by the given fraction.\n"
170 " -lowerLimit=<value>[,...] Sets lower limits for the histograms.\n"
171 " -upperLimit=<value>[,...] Sets upper limits for the histograms.\n"
172 " -separate Creates separate abscissas for each histogram in the output file.\n"
173 " -cdf=[only] Includes the Cumulative Distribution Function (CDF) in the output.\n"
174 " 'only' includes only the CDF, excluding the histogram.\n"
175 " -weightColumn=<name> Specifies a column to weight the histogram.\n"
176 " -majorOrder=row|column Sets the output file's data order to row-major or column-major.\n"
177 " -normalize={sum|peak|no} Normalizes the histogram.\n"
178 " 'sum' normalizes so that the sum of all bins equals 1.\n"
179 " 'peak' normalizes so that the peak bin equals 1.\n"
180 " 'no' applies no normalization.\n"
181 " -threads=<number> Number of threads for regular histogram binning.\n"
183 "Program by Michael Borland. (" __DATE__
" " __TIME__
", SVN revision: " SVN_VERSION
")\n";
186#define DO_CLOSE_SIDES 2
187#define DO_AGAINST_SIDES 3
189#define NORMALIZE_PEAK 0
190#define NORMALIZE_SUM 1
191#define NORMALIZE_NO 2
192#define N_NORMALIZE_OPTIONS 3
193char *normalize_option[N_NORMALIZE_OPTIONS] = {
194 "peak",
"sum",
"no"};
197 long **histogramIndex,
char *output,
char **columnName,
long columnNames,
198 char **abscissaName,
long abscissaNames,
char *boundaryColumn,
char *boundaryColumnUnits,
199 short columnMajorOrder,
short normMode);
200double *ReadBoundaryData(
char *file,
char *column, int64_t *n,
char **units);
201void MakeBoundaryHistogram(
double *histogram,
double *cdf,
double *boundaryValue, int64_t nBoundaryValues,
202 double *data,
double *weight, int64_t nData);
203void NormalizeHistogram(
double *hist, int64_t bins,
short mode);
204static long make_histogram_threaded(
double *hist,
long n_bins,
double lo,
double hi,
double *data,
205 int64_t n_pts,
long new_start,
int threads);
206static long make_histogram_weighted_threaded(
double *hist,
long n_bins,
double lo,
double hi,
double *data,
207 int64_t n_pts,
long new_start,
double *weight,
int threads);
209static short cdfOnly, freOnly;
211int main(
int argc,
char **argv) {
213 char *boundaryFile, *boundaryColumn, *boundaryColumnUnits;
214 double *boundaryValue;
215 int64_t nBoundaryValues;
216 char **abscissaName, **columnName, **excludeName;
217 long columnNames, excludeNames, abscissaNames, column, offset;
218 long givenLowerLimits, givenUpperLimits;
219 char *input, *output;
220 long readCode, binsGiven;
221 int64_t i, rows, bins, writeBins;
222 long lowerLimitGiven, upperLimitGiven, doSides, doSeparate;
223 double autoBinsTarget;
224 long autoBinsMinimum, autoBinsMaximum;
227 short normMode = NORMALIZE_NO;
228 unsigned long pipeFlags;
229 SCANNED_ARG *scanned;
231 double binSize, *lowerLimit = NULL, *upperLimit = NULL, *givenLowerLimit, *givenUpperLimit, *dx = NULL, range, middle;
232 double **inputData, *abscissa, *histogram, *minValue, *maxValue, transferLimit, *cdf, sum;
233 long *abscissaIndex, *histogramIndex, *cdfIndex;
234 double expandRange, maxRange;
236 unsigned long dummyFlags, majorOrderFlag;
237 short columnMajorOrder = -1;
241 argc =
scanargs(&scanned, argc, argv);
242 if (argc < 3 || argc > (3 + N_OPTIONS)) {
243 fprintf(stderr,
"%s", USAGE);
247 minValue = maxValue = NULL;
248 output = input = NULL;
251 boundaryFile = boundaryColumn = boundaryColumnUnits = NULL;
252 boundaryValue = NULL;
254 columnName = excludeName = NULL;
255 columnNames = excludeNames = abscissaNames = 0;
256 givenLowerLimits = givenUpperLimits = 0;
257 givenLowerLimit = givenUpperLimit = NULL;
258 bins = binsGiven = binSize = doSides = doSeparate = 0;
259 lowerLimitGiven = upperLimitGiven = 0;
264 autoBinsMinimum = autoBinsMaximum = 0;
268 for (iArg = 1; iArg < argc; iArg++) {
269 if (scanned[iArg].arg_type == OPTION) {
271 switch (
match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
272 case SET_MAJOR_ORDER:
274 scanned[iArg].n_items--;
275 if (scanned[iArg].n_items > 0 && (!
scanItemList(&majorOrderFlag, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
"row", -1, NULL, 0, SDDS_ROW_MAJOR_ORDER,
"column", -1, NULL, 0, SDDS_COLUMN_MAJOR_ORDER, NULL)))
276 SDDS_Bomb(
"invalid -majorOrder syntax/values");
277 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
278 columnMajorOrder = 1;
279 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
280 columnMajorOrder = 0;
283 if (!
processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags))
288 SDDS_Bomb(
"only one -columns option may be given");
289 if (scanned[iArg].n_items < 2)
291 if (!(columnName =
SDDS_Realloc(columnName,
sizeof(*columnName) * (columnNames + scanned[iArg].n_items - 1))))
293 for (i = 1; i < scanned[iArg].n_items; i++)
294 columnName[columnNames + i - 1] = scanned[iArg].list[i];
295 columnNames += scanned[iArg].n_items - 1;
299 SDDS_Bomb(
"only one -abscissa option may be given");
300 if (scanned[iArg].n_items >= 2) {
301 if (!(abscissaName =
SDDS_Realloc(abscissaName,
sizeof(*abscissaName) * (abscissaNames + scanned[iArg].n_items - 1))))
303 for (i = 1; i < scanned[iArg].n_items; i++)
304 abscissaName[abscissaNames + i - 1] = scanned[iArg].list[i];
305 abscissaNames += scanned[iArg].n_items - 1;
310 SDDS_Bomb(
"-bins specified more than once");
312 if (sscanf(scanned[iArg].list[1],
"%" SCNd64, &bins) != 1 || bins <= 0)
313 SDDS_Bomb(
"invalid value for bins---give a positive value");
316 if (sscanf(scanned[iArg].list[1],
"%le", &binSize) != 1 || binSize <= 0)
317 SDDS_Bomb(
"invalid value for bin size---give a positive value");
320 if (scanned[iArg].n_items < 2)
322 scanned[iArg].n_items -= 1;
323 autoBinsTarget = autoBinsMinimum = autoBinsMaximum = 0;
324 if (!
scanItemList(&dummyFlags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
326 "minimum",
SDDS_LONG, &autoBinsMinimum, 1, 0,
327 "maximum",
SDDS_LONG, &autoBinsMaximum, 1, 0, NULL) ||
328 autoBinsTarget <= 0 || autoBinsMinimum < 0 || autoBinsMaximum < 0)
329 SDDS_Bomb(
"incorrect -autoBins syntax or values");
333 SDDS_Bomb(
"only one -exclude option may be given");
334 if (scanned[iArg].n_items < 2)
336 if (!(excludeName =
SDDS_Realloc(excludeName,
sizeof(*excludeName) * (excludeNames + scanned[iArg].n_items - 1))))
338 for (i = 1; i < scanned[iArg].n_items; i++)
339 excludeName[excludeNames + i - 1] = scanned[iArg].list[i];
340 excludeNames += scanned[iArg].n_items - 1;
344 SDDS_Bomb(
"-lowerLimit specified more than once");
346 if (!(givenLowerLimit =
SDDS_Realloc(givenLowerLimit,
sizeof(*givenLowerLimit) * (givenLowerLimits + scanned[iArg].n_items - 1))))
347 SDDS_Bomb(
"SET_LOWERLIMIT: memory allocation failure");
348 for (i = 1; i < scanned[iArg].n_items; i++) {
349 if (sscanf(scanned[iArg].list[i],
"%lf", &transferLimit) != 1)
350 SDDS_Bomb(
"invalid value for -lowerLimit");
351 givenLowerLimit[givenLowerLimits + i - 1] = transferLimit;
353 givenLowerLimits += scanned[iArg].n_items - 1;
357 SDDS_Bomb(
"-upperLimit specified more than once");
359 if (!(givenUpperLimit =
SDDS_Realloc(givenUpperLimit,
sizeof(*givenUpperLimit) * (givenUpperLimits + scanned[iArg].n_items - 1))))
360 SDDS_Bomb(
"SET_UPPERLIMIT: memory allocation failure");
361 for (i = 1; i < scanned[iArg].n_items; i++) {
362 if (sscanf(scanned[iArg].list[i],
"%lf", &transferLimit) != 1)
363 SDDS_Bomb(
"invalid value for -upperLimit");
364 givenUpperLimit[givenUpperLimits + i - 1] = transferLimit;
366 givenUpperLimits += scanned[iArg].n_items - 1;
370 if (scanned[iArg].n_items == 2) {
371 static char *sideOpt[2] = {
"close",
"against"};
372 switch (
match_string(scanned[iArg].list[1], sideOpt, 2, 0)) {
374 doSides = DO_CLOSE_SIDES;
377 doSides = DO_AGAINST_SIDES;
389 if (scanned[iArg].n_items != 2 ||
390 sscanf(scanned[iArg].list[1],
"%lf", &expandRange) != 1 || expandRange <= 0)
394 if (scanned[iArg].n_items == 1)
397 if (scanned[iArg].n_items > 2)
399 CDFONLY = scanned[iArg].list[1];
400 if (strcmp(CDFONLY,
"only") != 0)
401 SDDS_Bomb(
"invalid -cdf value, it should be -cdf or -cdf=only");
406 case SET_BOUNDARYDATA:
407 if (scanned[iArg].n_items != 3 ||
408 !(boundaryFile = scanned[iArg].list[1]) ||
409 !strlen(boundaryFile) ||
410 !(boundaryColumn = scanned[iArg].list[2]) ||
411 !strlen(boundaryColumn))
412 SDDS_Bomb(
"invalid -boundaryData syntax or values");
415 if (scanned[iArg].n_items != 2 ||
416 !(weightColumn = scanned[iArg].list[1]) ||
417 !strlen(weightColumn))
418 SDDS_Bomb(
"invalid -weightColumn syntax or values");
421 if (scanned[iArg].n_items == 1)
422 normMode = NORMALIZE_SUM;
423 else if (scanned[iArg].n_items != 2 ||
424 (normMode =
match_string(scanned[iArg].list[1], normalize_option, N_NORMALIZE_OPTIONS, 0)) < 0)
428 if (scanned[iArg].n_items != 2 ||
429 sscanf(scanned[iArg].list[1],
"%d", &threads) != 1 || threads < 1)
433 fprintf(stderr,
"Error: unknown or ambiguous option: %s\n", scanned[iArg].list[0]);
434 fprintf(stderr,
"%s", USAGE);
440 input = scanned[iArg].list[0];
442 output = scanned[iArg].list[0];
448 if (boundaryColumn && (abscissaNames > 0 || doSeparate))
449 SDDS_Bomb(
"-boundaryData option is incompatible with -abscissa and -separate options");
451 if (columnNames <= 0)
452 SDDS_Bomb(
"Supply the names of columns to histogram with -columns");
461 if ((columnNames = expandColumnPairNames(&SDDSin, &columnName, NULL, columnNames, excludeName, excludeNames, FIND_NUMERIC_TYPE, 0)) <= 0) {
463 SDDS_Bomb(
"No quantities selected to histogram.");
467 if (abscissaNames <= 0) {
468 if (!(abscissaName =
SDDS_Realloc(abscissaName,
sizeof(*abscissaName) * (abscissaNames + columnNames))))
471 for (i = 0; i < columnNames; i++) {
472 abscissaName[abscissaNames + i] = columnName[i];
474 abscissaNames += columnNames;
476 if (columnNames > 1) {
477 if (abscissaNames > 0) {
478 if (columnNames != abscissaNames)
479 SDDS_Bomb(
"the number of abscissa names must match the number of columns");
481 if (givenLowerLimits)
482 if (columnNames != givenLowerLimits)
483 SDDS_Bomb(
"the number of lower limits must match the number of columns");
484 if (givenUpperLimits)
485 if (columnNames != givenUpperLimits)
486 SDDS_Bomb(
"the number of upper limits must match the number of columns");
489 if (abscissaNames > 0) {
490 if (columnNames != abscissaNames)
493 if (givenLowerLimits)
494 if (columnNames != givenLowerLimits)
495 givenLowerLimits = 1;
496 if (givenUpperLimits)
497 if (columnNames != givenUpperLimits)
498 givenUpperLimits = 1;
500 }
else if (boundaryFile) {
501 if (!(boundaryValue = ReadBoundaryData(boundaryFile, boundaryColumn, &nBoundaryValues, &boundaryColumnUnits))) {
502 SDDS_Bomb(
"Problem reading boundary data");
505 if (abscissaNames <= 0)
506 SDDS_Bomb(
"Supply the name of the abscissa with -abscissaName");
510 SetUpOutput(&SDDSout, &SDDSin, &abscissaIndex, &cdfIndex, &histogramIndex, output, columnName, columnNames, abscissaName, abscissaNames, boundaryColumn, boundaryColumnUnits, columnMajorOrder, normMode);
512 if (!(inputData = (
double **)malloc(columnNames *
sizeof(*inputData))) ||
513 !(minValue = (
double *)malloc(columnNames *
sizeof(*minValue))) ||
514 !(maxValue = (
double *)malloc(columnNames *
sizeof(*maxValue))))
517 if (((binSize ? 1 : 0) + (binsGiven ? 1 : 0) + (autoBinsTarget ? 1 : 0)) > 1)
518 SDDS_Bomb(
"Specify only one of -binSize, -bins, or -autoBins");
519 if (!binSize && !binsGiven && !autoBinsTarget) {
524 abscissa = histogram = cdf = NULL;
534 for (column = 0; column < columnNames; column++) {
539 if (!boundaryColumn) {
540 if (!(lowerLimit = (
double *)malloc(
sizeof(*lowerLimit) * columnNames)))
542 if (!(upperLimit = (
double *)malloc(
sizeof(*upperLimit) * columnNames)))
544 if (!(dx = (
double *)malloc(
sizeof(*dx) * columnNames)))
548 for (column = 0; column < columnNames; column++) {
549 find_min_max(&minValue[column], &maxValue[column], inputData[column], rows);
550 lowerLimit[column] = givenLowerLimits ? givenLowerLimit[column] : minValue[column];
551 upperLimit[column] = givenUpperLimits ? givenUpperLimit[column] : maxValue[column];
554 for (column = 0; column < columnNames; column++)
555 find_min_max(&minValue[column], &maxValue[column], inputData[column], rows);
556 lowerLimit[0] = givenLowerLimits ? givenLowerLimit[0] :
min_in_array(minValue, columnNames);
557 upperLimit[0] = givenUpperLimits ? givenUpperLimit[0] :
max_in_array(maxValue, columnNames);
558 for (column = 1; column < columnNames; column++) {
559 lowerLimit[column] = lowerLimit[0];
560 upperLimit[column] = upperLimit[0];
564 range = (1 + expandRange) * (upperLimit[0] - lowerLimit[0]);
565 if (autoBinsTarget) {
566 bins = (int64_t)(rows / autoBinsTarget);
567 if (autoBinsMinimum) {
568 if (bins < autoBinsMinimum)
569 bins = autoBinsMinimum;
570 }
else if (bins < 5) {
573 if (autoBinsMaximum) {
574 if (bins > autoBinsMaximum)
575 bins = autoBinsMaximum;
576 }
else if (bins > rows)
582 for (column = 0; column < columnNames; column++) {
583 range = (1 + expandRange) * (upperLimit[column] - lowerLimit[column]);
584 range = ((range / binSize) + 1) * binSize;
585 if (range > maxRange)
587 middle = (lowerLimit[column] + upperLimit[column]) / 2;
588 lowerLimit[column] = middle - range / 2;
589 upperLimit[column] = middle + range / 2;
597 bins = maxRange / binSize + 0.5;
598 if (bins < 1 && !doSides)
601 for (column = 0; column < columnNames; column++) {
602 range = upperLimit[column] - lowerLimit[column];
603 upperLimit[column] += (maxRange - range) / 2;
604 lowerLimit[column] -= (maxRange - range) / 2;
605 dx[column] = binSize;
609 for (column = 0; column < columnNames; column++) {
610 range = (1 + expandRange) * (upperLimit[column] - lowerLimit[column]);
611 middle = (upperLimit[column] + lowerLimit[column]) / 2;
612 upperLimit[column] = middle + range / 2;
613 lowerLimit[column] = middle - range / 2;
614 if (upperLimit[column] == lowerLimit[column]) {
615 if (fabs(upperLimit[column]) < sqrt(DBL_MIN)) {
616 upperLimit[column] = sqrt(DBL_MIN);
617 lowerLimit[column] = -sqrt(DBL_MIN);
619 lowerLimit[column] = upperLimit[column] * (1 - 10000 * DBL_EPSILON);
620 upperLimit[column] = upperLimit[column] * (1 + 10000 * DBL_EPSILON);
623 dx[column] = (upperLimit[column] - lowerLimit[column]) / bins;
626 range = (1 + expandRange) * (upperLimit[0] - lowerLimit[0]);
627 middle = (upperLimit[0] + lowerLimit[0]) / 2;
628 upperLimit[0] = middle + range / 2;
629 lowerLimit[0] = middle - range / 2;
630 if (upperLimit[0] == lowerLimit[0]) {
631 if (fabs(upperLimit[0]) < sqrt(DBL_MIN)) {
632 upperLimit[0] = sqrt(DBL_MIN);
633 lowerLimit[0] = -sqrt(DBL_MIN);
635 lowerLimit[0] = upperLimit[0] * (1 - 10000 * DBL_EPSILON);
636 upperLimit[0] = upperLimit[0] * (1 + 10000 * DBL_EPSILON);
639 dx[0] = (upperLimit[0] - lowerLimit[0]) / bins;
642 if (!binsGiven || !abscissa) {
643 if (!(abscissa =
SDDS_Realloc(abscissa,
sizeof(*abscissa) * (bins + 2))) ||
644 !(cdf =
SDDS_Realloc(cdf,
sizeof(*cdf) * (bins + 2))) ||
645 !(histogram =
SDDS_Realloc(histogram,
sizeof(*histogram) * (bins + 2))))
648 writeBins = bins + (doSides ? 2 : 0);
649 offset = doSides ? 0 : 1;
651 bins = writeBins = nBoundaryValues;
654 !(histogram =
SDDS_Realloc(histogram,
sizeof(*histogram) * bins)))
661 if (boundaryColumn) {
662 for (column = 0; column < columnNames; column++) {
663 MakeBoundaryHistogram(histogram, cdf, boundaryValue, nBoundaryValues, inputData[column], weightData, rows);
664 NormalizeHistogram(histogram, nBoundaryValues, normMode);
665 if (!cdfOnly && !
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, histogram, writeBins, histogramIndex[column]))
667 if (!freOnly && !
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, cdf, writeBins, cdfIndex[column]))
669 free(inputData[column]);
671 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_NAME, boundaryValue, writeBins, boundaryColumn))
673 }
else if (!doSeparate) {
674 for (i = -1; i < bins + 1; i++)
675 abscissa[i + 1] = (i + 0.5) * dx[0] + lowerLimit[0];
678 abscissa[0] = abscissa[1] - dx[0] / 2;
679 abscissa[bins + 1] = abscissa[bins] + dx[0] / 2;
681 case DO_AGAINST_SIDES:
682 abscissa[0] = abscissa[1];
683 abscissa[bins + 1] = abscissa[bins];
686 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, abscissa + offset, writeBins, abscissaIndex[0]))
688 for (column = 0; column < columnNames; column++) {
689 histogram[0] = histogram[bins + 1] = 0;
691 make_histogram_threaded(histogram + 1, bins, lowerLimit[0], upperLimit[0], inputData[column], rows, 1, threads);
693 make_histogram_weighted_threaded(histogram + 1, bins, lowerLimit[0], upperLimit[0], inputData[column], rows, 1, weightData, threads);
694 NormalizeHistogram(histogram, bins, normMode);
696 for (i = 0; i <= bins + 1; i++)
698 for (i = 0; i <= bins + 1; i++) {
700 cdf[i] = histogram[i] / sum;
702 cdf[i] = cdf[i - 1] + histogram[i] / sum;
705 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, histogram + offset, writeBins, histogramIndex[column]))
709 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, cdf + offset, writeBins, cdfIndex[column]))
712 free(inputData[column]);
715 for (column = 0; column < columnNames; column++) {
716 for (i = -1; i < bins + 1; i++)
717 abscissa[i + 1] = (i + 0.5) * dx[column] + lowerLimit[column];
720 abscissa[0] = abscissa[1] - dx[column] / 2;
721 abscissa[bins + 1] = abscissa[bins] + dx[column] / 2;
723 case DO_AGAINST_SIDES:
724 abscissa[0] = abscissa[1];
725 abscissa[bins + 1] = abscissa[bins];
728 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, abscissa + offset, writeBins, abscissaIndex[column]))
730 histogram[0] = histogram[bins + 1] = 0;
732 make_histogram_threaded(histogram + 1, bins, lowerLimit[column], upperLimit[column], inputData[column], rows, 1, threads);
734 make_histogram_weighted_threaded(histogram + 1, bins, lowerLimit[column], upperLimit[column], inputData[column], rows, 1, weightData, threads);
735 NormalizeHistogram(histogram, bins + 2, normMode);
737 for (i = 0; i <= bins + 1; i++)
739 for (i = 0; i <= bins + 1; i++) {
741 cdf[i] = histogram[i] / sum;
743 cdf[i] = cdf[i - 1] + histogram[i] / sum;
746 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, histogram + offset, writeBins, histogramIndex[column]))
750 if (!
SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, cdf + offset, writeBins, cdfIndex[column]))
753 free(inputData[column]);
795 long **histogramIndex,
char *output,
char **columnName,
long columnNames,
796 char **abscissaName,
long abscissaNames,
char *boundaryColumn,
char *boundaryUnits,
797 short columnMajorOrder,
short normMode) {
799 char s[SDDS_MAXLINE];
801 char *blankString =
"";
806 if (columnMajorOrder != -1)
807 SDDSout->layout.data_mode.column_major = columnMajorOrder;
809 SDDSout->layout.data_mode.column_major = SDDSin->layout.data_mode.column_major;
811 if (!(*cdfIndex = (
long *)malloc(
sizeof(**cdfIndex) * columnNames)))
814 if (!(*histogramIndex = (
long *)malloc(
sizeof(**histogramIndex) * columnNames)))
817 if (!boundaryColumn) {
818 if (!(*abscissaIndex = (
long *)malloc(
sizeof(**abscissaIndex) * columnNames)))
821 for (column = 0; column < abscissaNames; column++) {
826 if (strcmp(columnName[column], abscissaName[column]) != 0 &&
836 for (column = 0; column < columnNames; column++) {
838 sprintf(s,
"%sCdf", columnName[column]);
845 sprintf(s,
"%sRelativeFrequency", columnName[column]);
848 sprintf(s,
"%sFractionalFrequency", columnName[column]);
851 sprintf(s,
"%sFrequency", columnName[column]);
863double *ReadBoundaryData(
char *file,
char *column, int64_t *n,
char **units) {
880 *n = SDDS_RowCount(&SDDSin);
885 for (j = 1; j < (*n); j++) {
886 if (data[j] <= data[j - 1]) {
887 memmove(data + j, data + j + 1,
sizeof(*data) * ((*n) - 1 - j));
895void MakeBoundaryHistogram(
double *histogram,
double *cdf,
double *boundaryValue, int64_t nBoundaryValues,
896 double *data,
double *weight, int64_t nData) {
898 for (i = 0; i < nBoundaryValues; i++)
899 histogram[i] = cdf[i] = 0;
900 for (i = 0; i < nData; i++) {
902 if (j < nBoundaryValues && j >= 0)
903 histogram[j] += weight ? fabs(weight[i]) : 1;
905 cdf[0] = histogram[0];
906 for (j = 1; j < nBoundaryValues; j++) {
907 cdf[j] = cdf[j - 1] + histogram[j];
909 if (cdf[nBoundaryValues - 1] > 0)
910 for (j = 0; j < nBoundaryValues; j++)
911 cdf[j] /= cdf[nBoundaryValues - 1];
914void NormalizeHistogram(
double *hist, int64_t bins,
short mode) {
919 for (i = 0; i < bins; i++)
923 for (i = 0; i < bins; i++)
932 for (i = 0; i < bins; i++)
936static long make_histogram_threaded(
double *hist,
long n_bins,
double lo,
double hi,
double *data,
937 int64_t n_pts,
long new_start,
int threads) {
938 double bin_size, *partial;
939 long *counts, count = 0;
940 int activeThreads, thread;
943 if (threads <= 1 || n_pts <= 0 || n_bins <= 0)
944 return make_histogram(hist, n_bins, lo, hi, data, n_pts, new_start);
946 activeThreads = threads;
947 if (activeThreads > n_pts)
948 activeThreads = (int)n_pts;
949 if (activeThreads <= 1)
950 return make_histogram(hist, n_bins, lo, hi, data, n_pts, new_start);
953 for (i = 0; i < n_bins; i++)
955 bin_size = (hi - lo) / n_bins;
956 partial = calloc((
size_t)activeThreads * n_bins,
sizeof(*partial));
957 counts = calloc(activeThreads,
sizeof(*counts));
958 if (!partial || !counts)
961#pragma omp parallel for if (activeThreads > 1) num_threads(activeThreads)
962 for (thread = 0; thread < activeThreads; thread++) {
963 int64_t start = thread * (n_pts / activeThreads);
964 int64_t end = (thread == activeThreads - 1) ? n_pts : (thread + 1) * (n_pts / activeThreads);
965 double *local = partial + (size_t)thread * n_bins;
967 for (int64_t point = start; point < end; point++) {
968 double dbin = (data[point] - lo) / bin_size;
972 if (bin < 0 || bin >= n_bins)
977 counts[thread] = localCount;
980 for (thread = 0; thread < activeThreads; thread++) {
981 double *local = partial + (size_t)thread * n_bins;
982 count += counts[thread];
983 for (i = 0; i < n_bins; i++)
991static long make_histogram_weighted_threaded(
double *hist,
long n_bins,
double lo,
double hi,
double *data,
992 int64_t n_pts,
long new_start,
double *weight,
int threads) {
993 double bin_size, *partial;
994 long *counts, count = 0;
995 int activeThreads, thread;
998 if (threads <= 1 || n_pts <= 0 || n_bins <= 0)
1001 activeThreads = threads;
1002 if (activeThreads > n_pts)
1003 activeThreads = (int)n_pts;
1004 if (activeThreads <= 1)
1008 for (i = 0; i < n_bins; i++)
1010 bin_size = (hi - lo) / n_bins;
1011 partial = calloc((
size_t)activeThreads * n_bins,
sizeof(*partial));
1012 counts = calloc(activeThreads,
sizeof(*counts));
1013 if (!partial || !counts)
1016#pragma omp parallel for if (activeThreads > 1) num_threads(activeThreads)
1017 for (thread = 0; thread < activeThreads; thread++) {
1018 int64_t start = thread * (n_pts / activeThreads);
1019 int64_t end = (thread == activeThreads - 1) ? n_pts : (thread + 1) * (n_pts / activeThreads);
1020 double *local = partial + (size_t)thread * n_bins;
1021 long localCount = 0;
1022 for (int64_t point = start; point < end; point++) {
1023 double dbin = (data[point] - lo) / bin_size;
1027 if (bin < 0 || bin >= n_bins)
1029 local[bin] += weight[point];
1032 counts[thread] = localCount;
1035 for (thread = 0; thread < activeThreads; thread++) {
1036 double *local = partial + (size_t)thread * n_bins;
1037 count += counts[thread];
1038 for (i = 0; i < n_bins; i++)
1039 hist[i] += local[i];
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
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_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_ChangeColumnInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Modifies a specific field in a column definition within the SDDS dataset.
int32_t SDDS_GetColumnInformation(SDDS_DATASET *SDDS_dataset, char *field_name, void *memory, int32_t mode,...)
Retrieves information about a specified column in the SDDS dataset.
int32_t SDDS_InitializeOutput(SDDS_DATASET *SDDS_dataset, int32_t data_mode, int32_t lines_per_row, const char *description, const char *contents, const char *filename)
Initializes the SDDS output dataset.
int32_t SDDS_DefineSimpleColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *unit, int32_t type)
Defines a simple data column within the SDDS dataset.
int32_t SDDS_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
int32_t SDDS_DefineColumn(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, int32_t field_length)
Defines a data column within the SDDS dataset.
int32_t SDDS_WriteLayout(SDDS_DATASET *SDDS_dataset)
Writes the SDDS layout header to the output file.
int32_t SDDS_TransferColumnDefinition(SDDS_DATASET *target, SDDS_DATASET *source, char *name, char *newName)
Transfers a column definition from a source dataset to a target dataset.
int32_t SDDS_TransferAllParameterDefinitions(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source, uint32_t mode)
Transfers all parameter definitions from a source dataset to a target dataset.
void SDDS_SetError(char *error_text)
Records an error message in the SDDS error stack.
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.
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
#define SDDS_STRING
Identifier for the string data type.
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
#define SDDS_DOUBLE
Identifier for the double data type.
Utility functions for SDDS dataset manipulation and string array operations.
long binaryArraySearch(void *array, size_t elemSize, long members, void *key, int(*compare)(const void *c1, const void *c2), long bracket)
Searches for a key in a sorted array of data values using binary search.
int find_min_max(double *min, double *max, double *list, int64_t n)
Finds the minimum and maximum values in a list of doubles.
double max_in_array(double *array, long n)
Finds the maximum value in an array of doubles.
double min_in_array(double *array, long n)
Finds the minimum value in an array of doubles.
long make_histogram_weighted(double *hist, long n_bins, double lo, double hi, double *data, long n_pts, long new_start, double *weight)
Compiles a weighted histogram from data points.
long make_histogram(double *hist, long n_bins, double lo, double hi, double *data, int64_t n_pts, long new_start)
Compiles a histogram from data points.
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)
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.
int double_cmpasc(const void *a, const void *b)
Compare two doubles in ascending order.