SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sddsmultihist.c
Go to the documentation of this file.
1/**
2 * @file sddsmultihist.c
3 * @brief SDDS-format multi-column histogramming program.
4 *
5 * @details
6 * This program generates histograms for specified columns of an SDDS-formatted input file, offering customization
7 * options for bin sizing, normalization, boundaries, and more.
8 *
9 * @section Usage
10 * ```
11 * sddsmultihist [<inputfile>] [<outputfile>]
12 * [-pipe=[input][,output]]
13 * -columns=<name>[,...]
14 * -abscissa=<name>[,...]
15 * [-exclude=<name>[,...]]
16 * [-bins=<integer>]
17 * [-sizeOfBins=<value>]
18 * [-autobins=target=<number>[,minimum=<integer>][,maximum=<integer>]]
19 * [-boundaryData=<filename>,<column>]
20 * [-sides[=close|against]]
21 * [-expand=<fraction>]
22 * [-lowerLimit=<value>[,...]]
23 * [-upperLimit=<value>[,...]]
24 * [-separate]
25 * [-cdf=[only]]
26 * [-weightColumn=<name>]
27 * [-majorOrder=row|column]
28 * [-normalize={sum|peak|no}]
29 * ```
30 *
31 * @section Options
32 * | Required | Description |
33 * |---------------------------------------|---------------------------------------------------------------------------------------|
34 * | `-columns` | Names of columns from the input to be histogrammed. Supports wildcards. |
35 * | `-abscissa` | Names of abscissas in the output file. |
36 *
37 * | Optional | Description |
38 * |---------------------------------------|---------------------------------------------------------------------------------------|
39 * | `-pipe` | Use standard SDDS Toolkit pipe for input/output. |
40 * | `-exclude` | Column names to exclude from histogramming. |
41 * | `-bins` | Number of bins for the histogram. |
42 * | `-sizeOfBins` | Size of each bin for the histogram. |
43 * | `-autobins` | Auto-determine bin count based on target samples per bin. |
44 * | `-boundaryData` | Specifies irregular bin boundaries from a file. |
45 * | `-sides` | Adds zero-height bins at the histogram's ends. |
46 * | `-expand` | Expands histogram range by the given fraction. |
47 * | `-lowerLimit` | Sets lower limits for histograms. |
48 * | `-upperLimit` | Sets upper limits for histograms. |
49 * | `-separate` | Creates separate abscissas for each histogram. |
50 * | `-cdf` | Includes CDF in the output; "only" includes only CDF. |
51 * | `-weightColumn` | Specifies a column to weight the histogram. |
52 * | `-majorOrder` | Sets the output data order to row-major or column-major. |
53 * | `-normalize` | Normalizes the histogram based on sum, peak, or none. |
54 *
55 * @subsection Incompatibilities
56 * -boundaryData is incompatible with:
57 * - -separate
58 * - -abscissa
59 * - Only one of the following may be specified:
60 * - -bins
61 * - -sizeOfBins
62 * - -autobins
63 * - For -separate:
64 * - The number of -lowerLimit or -upperLimit values must match the number of columns.
65 *
66 * @copyright
67 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
68 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
69 *
70 * @license
71 * This file is distributed under the terms of the Software License Agreement
72 * found in the file LICENSE included with this distribution.
73 *
74 * @authors
75 * M. Borland, L. Emery, R. Soliday, H. Shang
76 */
77
78#include "mdb.h"
79#include "SDDS.h"
80#include "scan.h"
81#include "SDDSutils.h"
82#include <ctype.h>
83
84/* Enumeration for option types */
85enum option_type {
86 SET_COLUMNS,
87 SET_PIPE,
88 SET_EXCLUDE,
89 SET_ABSCISSA,
90 SET_BINS,
91 SET_SIZEOFBINS,
92 SET_LOWERLIMIT,
93 SET_UPPERLIMIT,
94 SET_SIDES,
95 SET_SEPARATE,
96 SET_EXPAND,
97 SET_CDF,
98 SET_AUTOBINS,
99 SET_MAJOR_ORDER,
100 SET_BOUNDARYDATA,
101 SET_WEIGHT,
102 SET_NORMALIZE,
103 N_OPTIONS
104};
105
106char *option[N_OPTIONS] = {
107 "columns",
108 "pipe",
109 "exclude",
110 "abscissa",
111 "bins",
112 "sizeofbins",
113 "lowerlimit",
114 "upperlimit",
115 "sides",
116 "separate",
117 "expand",
118 "cdf",
119 "autobins",
120 "majorOrder",
121 "boundaryData",
122 "weightColumn",
123 "normalize",
124};
125
126static char *USAGE =
127 "Usage: sddsmultihist [<inputfile>] [<outputfile>]\n"
128 " [-pipe=[input][,output]]\n"
129 " -columns=<name>[,...]\n"
130 " -abscissa=<name>[,...]\n"
131 " [-exclude=<name>[,...]]\n"
132 " [-bins=<integer>]\n"
133 " [-sizeOfBins=<value>]\n"
134 " [-autobins=target=<number>[,minimum=<integer>][,maximum=<integer>]]\n"
135 " [-boundaryData=<filename>,<column>]\n"
136 " [-sides[=close|against]]\n"
137 " [-expand=<fraction>]\n"
138 " [-lowerLimit=<value>[,...]]\n"
139 " [-upperLimit=<value>[,...]]\n"
140 " [-separate]\n"
141 " [-cdf=[only]]\n"
142 " [-weightColumn=<name>]\n"
143 " [-majorOrder=row|column]\n"
144 " [-normalize={sum|peak|no}]\n"
145 "Options:\n"
146 " -pipe=[input][,output] The standard SDDS Toolkit pipe option.\n"
147 " -columns=<name>[,...] Specifies the names of columns from the input to be histogrammed.\n"
148 " Names may contain wildcards.\n"
149 " -abscissa=<name>[,...] Specifies the names of the abscissas in the output file.\n"
150 " When using column names as abscissa names,\n"
151 " the -abscissa option is not required (use -separate).\n"
152 " At least one abscissa name must be supplied if -separate is not used.\n"
153 " -exclude=<name>[,...] (Optional) Specifies column names to exclude from histogramming.\n"
154 " -bins=<integer> Sets the number of bins for the histogram.\n"
155 " -sizeOfBins=<value> Sets the size of each bin for the histogram.\n"
156 " -autobins=target=<number>[,minimum=<integer>][,maximum=<integer>]\n"
157 " Automatically determines the number of bins based on the target number of samples per bin.\n"
158 " Optionally specify minimum and maximum number of bins.\n"
159 " -boundaryData=<filename>,<column> Specifies irregular bin boundaries from a file.\n"
160 " Incompatible with -separate and -abscissa.\n"
161 " -sides[=close|against] Adds zero-height bins at the ends of the histogram.\n"
162 " 'close' centers the first and last bins.\n"
163 " 'against' aligns the first and last bins with the data range.\n"
164 " -expand=<fraction> Expands the range of the histogram by the given fraction.\n"
165 " -lowerLimit=<value>[,...] Sets lower limits for the histograms.\n"
166 " -upperLimit=<value>[,...] Sets upper limits for the histograms.\n"
167 " -separate Creates separate abscissas for each histogram in the output file.\n"
168 " -cdf=[only] Includes the Cumulative Distribution Function (CDF) in the output.\n"
169 " 'only' includes only the CDF, excluding the histogram.\n"
170 " -weightColumn=<name> Specifies a column to weight the histogram.\n"
171 " -majorOrder=row|column Sets the output file's data order to row-major or column-major.\n"
172 " -normalize={sum|peak|no} Normalizes the histogram.\n"
173 " 'sum' normalizes so that the sum of all bins equals 1.\n"
174 " 'peak' normalizes so that the peak bin equals 1.\n"
175 " 'no' applies no normalization.\n"
176 "\n"
177 "Program by Michael Borland. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
178
179#define DO_SIDES 1
180#define DO_CLOSE_SIDES 2
181#define DO_AGAINST_SIDES 3
182
183#define NORMALIZE_PEAK 0
184#define NORMALIZE_SUM 1
185#define NORMALIZE_NO 2
186#define N_NORMALIZE_OPTIONS 3
187char *normalize_option[N_NORMALIZE_OPTIONS] = {
188 "peak", "sum", "no"};
189
190void SetUpOutput(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, long **abscissaIndex, long **cdfIndex,
191 long **histogramIndex, char *output, char **columnName, long columnNames,
192 char **abscissaName, long abscissaNames, char *boundaryColumn, char *boundaryColumnUnits,
193 short columnMajorOrder, short normMode);
194double *ReadBoundaryData(char *file, char *column, int64_t *n, char **units);
195void MakeBoundaryHistogram(double *histogram, double *cdf, double *boundaryValue, int64_t nBoundaryValues,
196 double *data, double *weight, int64_t nData);
197void NormalizeHistogram(double *hist, int64_t bins, short mode);
198
199static short cdfOnly, freOnly;
200
201int main(int argc, char **argv) {
202 int iArg;
203 char *boundaryFile, *boundaryColumn, *boundaryColumnUnits;
204 double *boundaryValue;
205 int64_t nBoundaryValues;
206 char **abscissaName, **columnName, **excludeName;
207 long columnNames, excludeNames, abscissaNames, column, offset;
208 long givenLowerLimits, givenUpperLimits;
209 char *input, *output;
210 long readCode, binsGiven;
211 int64_t i, rows, bins, writeBins;
212 long lowerLimitGiven, upperLimitGiven, doSides, doSeparate;
213 double autoBinsTarget;
214 long autoBinsMinimum, autoBinsMaximum;
215 char *weightColumn;
216 double *weightData;
217 short normMode = NORMALIZE_NO;
218 unsigned long pipeFlags;
219 SCANNED_ARG *scanned;
220 SDDS_DATASET SDDSin, SDDSout;
221 double binSize, *lowerLimit = NULL, *upperLimit = NULL, *givenLowerLimit, *givenUpperLimit, *dx = NULL, range, middle;
222 double **inputData, *abscissa, *histogram, *minValue, *maxValue, transferLimit, *cdf, sum;
223 long *abscissaIndex, *histogramIndex, *cdfIndex;
224 double expandRange, maxRange;
225 char *CDFONLY;
226 unsigned long dummyFlags, majorOrderFlag;
227 short columnMajorOrder = -1;
228
230 argc = scanargs(&scanned, argc, argv);
231 if (argc < 3 || argc > (3 + N_OPTIONS)) {
232 fprintf(stderr, "%s", USAGE);
233 exit(EXIT_FAILURE);
234 }
235
236 minValue = maxValue = NULL;
237 output = input = NULL;
238 pipeFlags = 0;
239 abscissaName = NULL;
240 boundaryFile = boundaryColumn = boundaryColumnUnits = NULL;
241 boundaryValue = NULL;
242 offset = 0;
243 columnName = excludeName = NULL;
244 columnNames = excludeNames = abscissaNames = 0;
245 givenLowerLimits = givenUpperLimits = 0;
246 givenLowerLimit = givenUpperLimit = NULL;
247 bins = binsGiven = binSize = doSides = doSeparate = 0;
248 lowerLimitGiven = upperLimitGiven = 0;
249 expandRange = 0;
250 cdfOnly = 0;
251 freOnly = 1;
252 autoBinsTarget = 0;
253 autoBinsMinimum = autoBinsMaximum = 0;
254 weightColumn = NULL;
255 weightData = NULL;
256
257 for (iArg = 1; iArg < argc; iArg++) {
258 if (scanned[iArg].arg_type == OPTION) {
259 /* process options here */
260 switch (match_string(scanned[iArg].list[0], option, N_OPTIONS, 0)) {
261 case SET_MAJOR_ORDER:
262 majorOrderFlag = 0;
263 scanned[iArg].n_items--;
264 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)))
265 SDDS_Bomb("invalid -majorOrder syntax/values");
266 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
267 columnMajorOrder = 1;
268 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
269 columnMajorOrder = 0;
270 break;
271 case SET_PIPE:
272 if (!processPipeOption(scanned[iArg].list + 1, scanned[iArg].n_items - 1, &pipeFlags))
273 SDDS_Bomb("invalid -pipe syntax");
274 break;
275 case SET_COLUMNS:
276 if (columnName)
277 SDDS_Bomb("only one -columns option may be given");
278 if (scanned[iArg].n_items < 2)
279 SDDS_Bomb("invalid -columns syntax");
280 if (!(columnName = SDDS_Realloc(columnName, sizeof(*columnName) * (columnNames + scanned[iArg].n_items - 1))))
281 SDDS_Bomb("memory allocation failure");
282 for (i = 1; i < scanned[iArg].n_items; i++)
283 columnName[columnNames + i - 1] = scanned[iArg].list[i];
284 columnNames += scanned[iArg].n_items - 1;
285 break;
286 case SET_ABSCISSA:
287 if (abscissaName)
288 SDDS_Bomb("only one -abscissa option may be given");
289 if (scanned[iArg].n_items >= 2) {
290 if (!(abscissaName = SDDS_Realloc(abscissaName, sizeof(*abscissaName) * (abscissaNames + scanned[iArg].n_items - 1))))
291 SDDS_Bomb("memory allocation failure");
292 for (i = 1; i < scanned[iArg].n_items; i++)
293 abscissaName[abscissaNames + i - 1] = scanned[iArg].list[i];
294 abscissaNames += scanned[iArg].n_items - 1;
295 }
296 break;
297 case SET_BINS:
298 if (binsGiven)
299 SDDS_Bomb("-bins specified more than once");
300 binsGiven = 1;
301 if (sscanf(scanned[iArg].list[1], "%" SCNd64, &bins) != 1 || bins <= 0)
302 SDDS_Bomb("invalid value for bins---give a positive value");
303 break;
304 case SET_SIZEOFBINS:
305 if (sscanf(scanned[iArg].list[1], "%le", &binSize) != 1 || binSize <= 0)
306 SDDS_Bomb("invalid value for bin size---give a positive value");
307 break;
308 case SET_AUTOBINS:
309 if (scanned[iArg].n_items < 2)
310 SDDS_Bomb("incorrect -autoBins syntax");
311 scanned[iArg].n_items -= 1;
312 autoBinsTarget = autoBinsMinimum = autoBinsMaximum = 0;
313 if (!scanItemList(&dummyFlags, scanned[iArg].list + 1, &scanned[iArg].n_items, 0,
314 "target", SDDS_DOUBLE, &autoBinsTarget, 1, 0,
315 "minimum", SDDS_LONG, &autoBinsMinimum, 1, 0,
316 "maximum", SDDS_LONG, &autoBinsMaximum, 1, 0, NULL) ||
317 autoBinsTarget <= 0 || autoBinsMinimum < 0 || autoBinsMaximum < 0)
318 SDDS_Bomb("incorrect -autoBins syntax or values");
319 break;
320 case SET_EXCLUDE:
321 if (excludeName)
322 SDDS_Bomb("only one -exclude option may be given");
323 if (scanned[iArg].n_items < 2)
324 SDDS_Bomb("invalid -exclude syntax");
325 if (!(excludeName = SDDS_Realloc(excludeName, sizeof(*excludeName) * (excludeNames + scanned[iArg].n_items - 1))))
326 SDDS_Bomb("memory allocation failure");
327 for (i = 1; i < scanned[iArg].n_items; i++)
328 excludeName[excludeNames + i - 1] = scanned[iArg].list[i];
329 excludeNames += scanned[iArg].n_items - 1;
330 break;
331 case SET_LOWERLIMIT:
332 if (lowerLimitGiven)
333 SDDS_Bomb("-lowerLimit specified more than once");
334 lowerLimitGiven = 1;
335 if (!(givenLowerLimit = SDDS_Realloc(givenLowerLimit, sizeof(*givenLowerLimit) * (givenLowerLimits + scanned[iArg].n_items - 1))))
336 SDDS_Bomb("SET_LOWERLIMIT: memory allocation failure");
337 for (i = 1; i < scanned[iArg].n_items; i++) {
338 if (sscanf(scanned[iArg].list[i], "%lf", &transferLimit) != 1)
339 SDDS_Bomb("invalid value for -lowerLimit");
340 givenLowerLimit[givenLowerLimits + i - 1] = transferLimit;
341 }
342 givenLowerLimits += scanned[iArg].n_items - 1;
343 break;
344 case SET_UPPERLIMIT:
345 if (upperLimitGiven)
346 SDDS_Bomb("-upperLimit specified more than once");
347 upperLimitGiven = 1;
348 if (!(givenUpperLimit = SDDS_Realloc(givenUpperLimit, sizeof(*givenUpperLimit) * (givenUpperLimits + scanned[iArg].n_items - 1))))
349 SDDS_Bomb("SET_UPPERLIMIT: memory allocation failure");
350 for (i = 1; i < scanned[iArg].n_items; i++) {
351 if (sscanf(scanned[iArg].list[i], "%lf", &transferLimit) != 1)
352 SDDS_Bomb("invalid value for -upperLimit");
353 givenUpperLimit[givenUpperLimits + i - 1] = transferLimit;
354 }
355 givenUpperLimits += scanned[iArg].n_items - 1;
356 break;
357 case SET_SIDES:
358 doSides = DO_SIDES;
359 if (scanned[iArg].n_items == 2) {
360 static char *sideOpt[2] = {"close", "against"};
361 switch (match_string(scanned[iArg].list[1], sideOpt, 2, 0)) {
362 case 0:
363 doSides = DO_CLOSE_SIDES;
364 break;
365 case 1:
366 doSides = DO_AGAINST_SIDES;
367 break;
368 default:
369 SDDS_Bomb("invalid value for -sides");
370 break;
371 }
372 }
373 break;
374 case SET_SEPARATE:
375 doSeparate = 1;
376 break;
377 case SET_EXPAND:
378 if (scanned[iArg].n_items != 2 ||
379 sscanf(scanned[iArg].list[1], "%lf", &expandRange) != 1 || expandRange <= 0)
380 SDDS_Bomb("invalid -expand syntax");
381 break;
382 case SET_CDF:
383 if (scanned[iArg].n_items == 1)
384 cdfOnly = 0;
385 else {
386 if (scanned[iArg].n_items > 2)
387 SDDS_Bomb("invalid -cdf syntax");
388 CDFONLY = scanned[iArg].list[1];
389 if (strcmp(CDFONLY, "only") != 0)
390 SDDS_Bomb("invalid -cdf value, it should be -cdf or -cdf=only");
391 cdfOnly = 1;
392 }
393 freOnly = 0;
394 break;
395 case SET_BOUNDARYDATA:
396 if (scanned[iArg].n_items != 3 ||
397 !(boundaryFile = scanned[iArg].list[1]) ||
398 !strlen(boundaryFile) ||
399 !(boundaryColumn = scanned[iArg].list[2]) ||
400 !strlen(boundaryColumn))
401 SDDS_Bomb("invalid -boundaryData syntax or values");
402 break;
403 case SET_WEIGHT:
404 if (scanned[iArg].n_items != 2 ||
405 !(weightColumn = scanned[iArg].list[1]) ||
406 !strlen(weightColumn))
407 SDDS_Bomb("invalid -weightColumn syntax or values");
408 break;
409 case SET_NORMALIZE:
410 if (scanned[iArg].n_items == 1)
411 normMode = NORMALIZE_SUM;
412 else if (scanned[iArg].n_items != 2 ||
413 (normMode = match_string(scanned[iArg].list[1], normalize_option, N_NORMALIZE_OPTIONS, 0)) < 0)
414 SDDS_Bomb("invalid -normalize syntax");
415 break;
416 default:
417 fprintf(stderr, "Error: unknown or ambiguous option: %s\n", scanned[iArg].list[0]);
418 fprintf(stderr, "%s", USAGE);
419 exit(EXIT_FAILURE);
420 break;
421 }
422 } else {
423 if (!input)
424 input = scanned[iArg].list[0];
425 else if (!output)
426 output = scanned[iArg].list[0];
427 else
428 SDDS_Bomb("too many filenames seen");
429 }
430 }
431
432 if (boundaryColumn && (abscissaNames > 0 || doSeparate))
433 SDDS_Bomb("-boundaryData option is incompatible with -abscissa and -separate options");
434
435 if (columnNames <= 0)
436 SDDS_Bomb("Supply the names of columns to histogram with -columns");
437
438 processFilenames("sddsmultihist", &input, &output, pipeFlags, 0, NULL);
439
440 if (!SDDS_InitializeInput(&SDDSin, input)) {
441 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
442 exit(EXIT_FAILURE);
443 }
444
445 if ((columnNames = expandColumnPairNames(&SDDSin, &columnName, NULL, columnNames, excludeName, excludeNames, FIND_NUMERIC_TYPE, 0)) <= 0) {
446 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
447 SDDS_Bomb("No quantities selected to histogram.");
448 }
449
450 if (doSeparate) {
451 if (abscissaNames <= 0) {
452 if (!(abscissaName = SDDS_Realloc(abscissaName, sizeof(*abscissaName) * (abscissaNames + columnNames))))
453 SDDS_Bomb("memory allocation failure");
454 abscissaNames = 0;
455 for (i = 0; i < columnNames; i++) {
456 abscissaName[abscissaNames + i] = columnName[i];
457 }
458 abscissaNames += columnNames;
459 }
460 if (columnNames > 1) {
461 if (abscissaNames > 0) {
462 if (columnNames != abscissaNames)
463 SDDS_Bomb("the number of abscissa names must match the number of columns");
464 }
465 if (givenLowerLimits)
466 if (columnNames != givenLowerLimits)
467 SDDS_Bomb("the number of lower limits must match the number of columns");
468 if (givenUpperLimits)
469 if (columnNames != givenUpperLimits)
470 SDDS_Bomb("the number of upper limits must match the number of columns");
471 } else {
472 /* Handle single column with multiple option names */
473 if (abscissaNames > 0) {
474 if (columnNames != abscissaNames)
475 abscissaNames = 1;
476 }
477 if (givenLowerLimits)
478 if (columnNames != givenLowerLimits)
479 givenLowerLimits = 1;
480 if (givenUpperLimits)
481 if (columnNames != givenUpperLimits)
482 givenUpperLimits = 1;
483 }
484 } else if (boundaryFile) {
485 if (!(boundaryValue = ReadBoundaryData(boundaryFile, boundaryColumn, &nBoundaryValues, &boundaryColumnUnits))) {
486 SDDS_Bomb("Problem reading boundary data");
487 }
488 } else {
489 if (abscissaNames <= 0)
490 SDDS_Bomb("Supply the name of the abscissa with -abscissaName");
491 abscissaNames = 1;
492 }
493
494 SetUpOutput(&SDDSout, &SDDSin, &abscissaIndex, &cdfIndex, &histogramIndex, output, columnName, columnNames, abscissaName, abscissaNames, boundaryColumn, boundaryColumnUnits, columnMajorOrder, normMode);
495
496 if (!(inputData = (double **)malloc(columnNames * sizeof(*inputData))) ||
497 !(minValue = (double *)malloc(columnNames * sizeof(*minValue))) ||
498 !(maxValue = (double *)malloc(columnNames * sizeof(*maxValue))))
499 SDDS_Bomb("memory allocation failure");
500
501 if (((binSize ? 1 : 0) + (binsGiven ? 1 : 0) + (autoBinsTarget ? 1 : 0)) > 1)
502 SDDS_Bomb("Specify only one of -binSize, -bins, or -autoBins");
503 if (!binSize && !binsGiven && !autoBinsTarget) {
504 binsGiven = 1;
505 bins = 20;
506 }
507
508 abscissa = histogram = cdf = NULL;
509
510 while ((readCode = SDDS_ReadPage(&SDDSin)) > 0) {
511 if ((rows = SDDS_CountRowsOfInterest(&SDDSin)) < 0)
512 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
513
514 if (rows) {
515 if (weightColumn && !(weightData = SDDS_GetColumnInDoubles(&SDDSin, weightColumn)))
516 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
517
518 for (column = 0; column < columnNames; column++) {
519 if (!(inputData[column] = SDDS_GetColumnInDoubles(&SDDSin, columnName[column])))
520 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
521 }
522
523 if (!boundaryColumn) {
524 if (!(lowerLimit = (double *)malloc(sizeof(*lowerLimit) * columnNames)))
525 SDDS_Bomb("memory allocation failure");
526 if (!(upperLimit = (double *)malloc(sizeof(*upperLimit) * columnNames)))
527 SDDS_Bomb("memory allocation failure");
528 if (!(dx = (double *)malloc(sizeof(*dx) * columnNames)))
529 SDDS_Bomb("memory allocation failure");
530
531 if (doSeparate) {
532 for (column = 0; column < columnNames; column++) {
533 find_min_max(&minValue[column], &maxValue[column], inputData[column], rows);
534 lowerLimit[column] = givenLowerLimits ? givenLowerLimit[column] : minValue[column];
535 upperLimit[column] = givenUpperLimits ? givenUpperLimit[column] : maxValue[column];
536 }
537 } else {
538 for (column = 0; column < columnNames; column++)
539 find_min_max(&minValue[column], &maxValue[column], inputData[column], rows);
540 lowerLimit[0] = givenLowerLimits ? givenLowerLimit[0] : min_in_array(minValue, columnNames);
541 upperLimit[0] = givenUpperLimits ? givenUpperLimit[0] : max_in_array(maxValue, columnNames);
542 for (column = 1; column < columnNames; column++) {
543 lowerLimit[column] = lowerLimit[0];
544 upperLimit[column] = upperLimit[0];
545 }
546 }
547
548 range = (1 + expandRange) * (upperLimit[0] - lowerLimit[0]);
549 if (autoBinsTarget) {
550 bins = (int64_t)(rows / autoBinsTarget);
551 if (autoBinsMinimum) {
552 if (bins < autoBinsMinimum)
553 bins = autoBinsMinimum;
554 } else if (bins < 5) {
555 bins = 5;
556 }
557 if (autoBinsMaximum) {
558 if (bins > autoBinsMaximum)
559 bins = autoBinsMaximum;
560 } else if (bins > rows)
561 bins = rows;
562 }
563
564 if (binSize) {
565 maxRange = range;
566 for (column = 0; column < columnNames; column++) {
567 range = (1 + expandRange) * (upperLimit[column] - lowerLimit[column]);
568 range = ((range / binSize) + 1) * binSize;
569 if (range > maxRange)
570 maxRange = range;
571 middle = (lowerLimit[column] + upperLimit[column]) / 2;
572 lowerLimit[column] = middle - range / 2;
573 upperLimit[column] = middle + range / 2;
574 }
575 range = maxRange;
576 if (!doSeparate) {
577 lowerLimit[0] = min_in_array(lowerLimit, columnNames);
578 upperLimit[0] = max_in_array(upperLimit, columnNames);
579 dx[0] = binSize;
580 }
581 bins = maxRange / binSize + 0.5;
582 if (bins < 1 && !doSides)
583 bins = 2;
584 if (doSeparate)
585 for (column = 0; column < columnNames; column++) {
586 range = upperLimit[column] - lowerLimit[column];
587 upperLimit[column] += (maxRange - range) / 2;
588 lowerLimit[column] -= (maxRange - range) / 2;
589 dx[column] = binSize;
590 }
591 } else {
592 if (doSeparate) {
593 for (column = 0; column < columnNames; column++) {
594 range = (1 + expandRange) * (upperLimit[column] - lowerLimit[column]);
595 middle = (upperLimit[column] + lowerLimit[column]) / 2;
596 upperLimit[column] = middle + range / 2;
597 lowerLimit[column] = middle - range / 2;
598 if (upperLimit[column] == lowerLimit[column]) {
599 if (fabs(upperLimit[column]) < sqrt(DBL_MIN)) {
600 upperLimit[column] = sqrt(DBL_MIN);
601 lowerLimit[column] = -sqrt(DBL_MIN);
602 } else {
603 lowerLimit[column] = upperLimit[column] * (1 - 10000 * DBL_EPSILON);
604 upperLimit[column] = upperLimit[column] * (1 + 10000 * DBL_EPSILON);
605 }
606 }
607 dx[column] = (upperLimit[column] - lowerLimit[column]) / bins;
608 }
609 } else {
610 range = (1 + expandRange) * (upperLimit[0] - lowerLimit[0]);
611 middle = (upperLimit[0] + lowerLimit[0]) / 2;
612 upperLimit[0] = middle + range / 2;
613 lowerLimit[0] = middle - range / 2;
614 if (upperLimit[0] == lowerLimit[0]) {
615 if (fabs(upperLimit[0]) < sqrt(DBL_MIN)) {
616 upperLimit[0] = sqrt(DBL_MIN);
617 lowerLimit[0] = -sqrt(DBL_MIN);
618 } else {
619 lowerLimit[0] = upperLimit[0] * (1 - 10000 * DBL_EPSILON);
620 upperLimit[0] = upperLimit[0] * (1 + 10000 * DBL_EPSILON);
621 }
622 }
623 dx[0] = (upperLimit[0] - lowerLimit[0]) / bins;
624 }
625 }
626 if (!binsGiven || !abscissa) {
627 if (!(abscissa = SDDS_Realloc(abscissa, sizeof(*abscissa) * (bins + 2))) ||
628 !(cdf = SDDS_Realloc(cdf, sizeof(*cdf) * (bins + 2))) ||
629 !(histogram = SDDS_Realloc(histogram, sizeof(*histogram) * (bins + 2))))
630 SDDS_Bomb("memory allocation failure");
631 }
632 writeBins = bins + (doSides ? 2 : 0);
633 offset = doSides ? 0 : 1;
634 } else {
635 bins = writeBins = nBoundaryValues;
636 abscissa = NULL;
637 if (!(cdf = SDDS_Realloc(cdf, sizeof(*cdf) * bins)) ||
638 !(histogram = SDDS_Realloc(histogram, sizeof(*histogram) * bins)))
639 SDDS_Bomb("memory allocation failure");
640 }
641
642 if (!SDDS_StartPage(&SDDSout, writeBins) || !SDDS_CopyParameters(&SDDSout, &SDDSin))
643 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
644
645 if (boundaryColumn) {
646 for (column = 0; column < columnNames; column++) {
647 MakeBoundaryHistogram(histogram, cdf, boundaryValue, nBoundaryValues, inputData[column], weightData, rows);
648 NormalizeHistogram(histogram, nBoundaryValues, normMode);
649 if (!cdfOnly && !SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, histogram, writeBins, histogramIndex[column]))
650 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
651 if (!freOnly && !SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, cdf, writeBins, cdfIndex[column]))
652 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
653 free(inputData[column]);
654 }
655 if (!SDDS_SetColumn(&SDDSout, SDDS_SET_BY_NAME, boundaryValue, writeBins, boundaryColumn))
656 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
657 } else if (!doSeparate) {
658 for (i = -1; i < bins + 1; i++)
659 abscissa[i + 1] = (i + 0.5) * dx[0] + lowerLimit[0];
660 switch (doSides) {
661 case DO_CLOSE_SIDES:
662 abscissa[0] = abscissa[1] - dx[0] / 2;
663 abscissa[bins + 1] = abscissa[bins] + dx[0] / 2;
664 break;
665 case DO_AGAINST_SIDES:
666 abscissa[0] = abscissa[1];
667 abscissa[bins + 1] = abscissa[bins];
668 break;
669 }
670 if (!SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, abscissa + offset, writeBins, abscissaIndex[0]))
671 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
672 for (column = 0; column < columnNames; column++) {
673 histogram[0] = histogram[bins + 1] = 0;
674 if (!weightColumn)
675 make_histogram(histogram + 1, bins, lowerLimit[0], upperLimit[0], inputData[column], rows, 1);
676 else
677 make_histogram_weighted(histogram + 1, bins, lowerLimit[0], upperLimit[0], inputData[column], rows, 1, weightData);
678 NormalizeHistogram(histogram, bins, normMode);
679 sum = 0;
680 for (i = 0; i <= bins + 1; i++)
681 sum += histogram[i];
682 for (i = 0; i <= bins + 1; i++) {
683 if (!i)
684 cdf[i] = histogram[i] / sum;
685 else
686 cdf[i] = cdf[i - 1] + histogram[i] / sum;
687 }
688 if (!cdfOnly) {
689 if (!SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, histogram + offset, writeBins, histogramIndex[column]))
690 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
691 }
692 if (!freOnly) {
693 if (!SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, cdf + offset, writeBins, cdfIndex[column]))
694 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
695 }
696 free(inputData[column]);
697 }
698 } else {
699 for (column = 0; column < columnNames; column++) {
700 for (i = -1; i < bins + 1; i++)
701 abscissa[i + 1] = (i + 0.5) * dx[column] + lowerLimit[column];
702 switch (doSides) {
703 case DO_CLOSE_SIDES:
704 abscissa[0] = abscissa[1] - dx[column] / 2;
705 abscissa[bins + 1] = abscissa[bins] + dx[column] / 2;
706 break;
707 case DO_AGAINST_SIDES:
708 abscissa[0] = abscissa[1];
709 abscissa[bins + 1] = abscissa[bins];
710 break;
711 }
712 if (!SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, abscissa + offset, writeBins, abscissaIndex[column]))
713 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
714 histogram[0] = histogram[bins + 1] = 0;
715 if (!weightColumn)
716 make_histogram(histogram + 1, bins, lowerLimit[column], upperLimit[column], inputData[column], rows, 1);
717 else
718 make_histogram_weighted(histogram + 1, bins, lowerLimit[column], upperLimit[column], inputData[column], rows, 1, weightData);
719 NormalizeHistogram(histogram, bins + 2, normMode);
720 sum = 0;
721 for (i = 0; i <= bins + 1; i++)
722 sum += histogram[i];
723 for (i = 0; i <= bins + 1; i++) {
724 if (!i)
725 cdf[i] = histogram[i] / sum;
726 else
727 cdf[i] = cdf[i - 1] + histogram[i] / sum;
728 }
729 if (!cdfOnly) {
730 if (!SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, histogram + offset, writeBins, histogramIndex[column]))
731 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
732 }
733 if (!freOnly) {
734 if (!SDDS_SetColumn(&SDDSout, SDDS_SET_BY_INDEX, cdf + offset, writeBins, cdfIndex[column]))
735 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
736 }
737 free(inputData[column]);
738 }
739 }
740 } else {
741 if (!SDDS_StartPage(&SDDSout, rows ? bins : 0))
742 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
743 }
744 if (weightData) {
745 free(weightData);
746 weightData = NULL;
747 }
748 if (!SDDS_WritePage(&SDDSout))
749 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
750 }
751
752 if (!SDDS_Terminate(&SDDSin)) {
753 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
754 exit(EXIT_FAILURE);
755 }
756 if (!SDDS_Terminate(&SDDSout)) {
757 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
758 exit(EXIT_FAILURE);
759 }
760
761 free(histogram);
762 free(cdf);
763 free(abscissa);
764 if (minValue)
765 free(minValue);
766 if (maxValue)
767 free(maxValue);
768 if (lowerLimit)
769 free(lowerLimit);
770 if (upperLimit)
771 free(upperLimit);
772 if (dx)
773 free(dx);
774
775 return EXIT_SUCCESS;
776}
777
778void SetUpOutput(SDDS_DATASET *SDDSout, SDDS_DATASET *SDDSin, long **abscissaIndex, long **cdfIndex,
779 long **histogramIndex, char *output, char **columnName, long columnNames,
780 char **abscissaName, long abscissaNames, char *boundaryColumn, char *boundaryUnits,
781 short columnMajorOrder, short normMode) {
782 long column;
783 char s[SDDS_MAXLINE];
784 int32_t outputType = SDDS_DOUBLE;
785 char *blankString = "";
786
787 if (!SDDS_InitializeOutput(SDDSout, SDDS_BINARY, 0, NULL, "sddsmultihist output", output))
788 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
789
790 if (columnMajorOrder != -1)
791 SDDSout->layout.data_mode.column_major = columnMajorOrder;
792 else
793 SDDSout->layout.data_mode.column_major = SDDSin->layout.data_mode.column_major;
794
795 if (!(*cdfIndex = (long *)malloc(sizeof(**cdfIndex) * columnNames)))
796 SDDS_Bomb("memory allocation failure");
797 if (!cdfOnly) {
798 if (!(*histogramIndex = (long *)malloc(sizeof(**histogramIndex) * columnNames)))
799 SDDS_Bomb("memory allocation failure");
800 }
801 if (!boundaryColumn) {
802 if (!(*abscissaIndex = (long *)malloc(sizeof(**abscissaIndex) * columnNames)))
803 SDDS_Bomb("memory allocation failure");
804
805 for (column = 0; column < abscissaNames; column++) {
806 if (!SDDS_TransferColumnDefinition(SDDSout, SDDSin, columnName[column], abscissaName[column]) ||
807 !SDDS_ChangeColumnInformation(SDDSout, "type", &outputType, SDDS_BY_NAME, abscissaName[column]) ||
808 ((*abscissaIndex)[column] = SDDS_GetColumnIndex(SDDSout, abscissaName[column])) < 0)
809 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
810 if (strcmp(columnName[column], abscissaName[column]) != 0 &&
811 (!SDDS_ChangeColumnInformation(SDDSout, "description", blankString, SDDS_BY_NAME, abscissaName[column]) ||
812 !SDDS_ChangeColumnInformation(SDDSout, "symbol", blankString, SDDS_BY_NAME, abscissaName[column])))
813 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
814 }
815 } else {
816 if (!SDDS_DefineSimpleColumn(SDDSout, boundaryColumn, boundaryUnits, SDDS_DOUBLE))
817 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
818 }
819
820 for (column = 0; column < columnNames; column++) {
821 if (!freOnly) {
822 sprintf(s, "%sCdf", columnName[column]);
823 if (((*cdfIndex)[column] = SDDS_DefineColumn(SDDSout, s, NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0)) < 0)
824 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
825 }
826 if (!cdfOnly) {
827 switch (normMode) {
828 case NORMALIZE_PEAK:
829 sprintf(s, "%sRelativeFrequency", columnName[column]);
830 break;
831 case NORMALIZE_SUM:
832 sprintf(s, "%sFractionalFrequency", columnName[column]);
833 break;
834 default:
835 sprintf(s, "%sFrequency", columnName[column]);
836 break;
837 }
838 if (((*histogramIndex)[column] = SDDS_DefineColumn(SDDSout, s, NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0)) < 0)
839 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
840 }
841 }
842 if (!SDDS_TransferAllParameterDefinitions(SDDSout, SDDSin, SDDS_TRANSFER_KEEPOLD) ||
843 !SDDS_WriteLayout(SDDSout))
844 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
845}
846
847double *ReadBoundaryData(char *file, char *column, int64_t *n, char **units) {
848 SDDS_DATASET SDDSin;
849 double *data;
850 int64_t j;
851
852 if (!SDDS_InitializeInput(&SDDSin, file)) {
853 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
854 }
855
856 if (SDDS_GetColumnInformation(&SDDSin, "units", units, SDDS_GET_BY_NAME, column) != SDDS_STRING)
857 return NULL;
858
859 if (SDDS_ReadPage(&SDDSin) <= 0) {
860 SDDS_SetError("No pages in boundary data file");
861 return NULL;
862 }
863
864 *n = SDDS_RowCount(&SDDSin);
865 if (*n <= 0)
866 return NULL;
867 if (!(data = SDDS_GetColumnInDoubles(&SDDSin, column)))
868 return NULL;
869 for (j = 1; j < (*n); j++) {
870 if (data[j] <= data[j - 1]) {
871 memmove(data + j, data + j + 1, sizeof(*data) * ((*n) - 1 - j));
872 *n -= 1;
873 j -= 1;
874 }
875 }
876 return data;
877}
878
879void MakeBoundaryHistogram(double *histogram, double *cdf, double *boundaryValue, int64_t nBoundaryValues,
880 double *data, double *weight, int64_t nData) {
881 int64_t i, j;
882 for (i = 0; i < nBoundaryValues; i++)
883 histogram[i] = cdf[i] = 0;
884 for (i = 0; i < nData; i++) {
885 j = binaryArraySearch(boundaryValue, sizeof(double), nBoundaryValues, &data[i], double_cmpasc, 1) + 1;
886 if (j < nBoundaryValues && j >= 0)
887 histogram[j] += weight ? fabs(weight[i]) : 1;
888 }
889 cdf[0] = histogram[0];
890 for (j = 1; j < nBoundaryValues; j++) {
891 cdf[j] = cdf[j - 1] + histogram[j];
892 }
893 if (cdf[nBoundaryValues - 1] > 0)
894 for (j = 0; j < nBoundaryValues; j++)
895 cdf[j] /= cdf[nBoundaryValues - 1];
896}
897
898void NormalizeHistogram(double *hist, int64_t bins, short mode) {
899 int64_t i;
900 double value = 0;
901 switch (mode) {
902 case NORMALIZE_SUM:
903 for (i = 0; i < bins; i++)
904 value += hist[i];
905 break;
906 case NORMALIZE_PEAK:
907 for (i = 0; i < bins; i++)
908 if (hist[i] > value)
909 value = hist[i];
910 break;
911 default:
912 return;
913 break;
914 }
915 if (value)
916 for (i = 0; i < bins; i++)
917 hist[i] /= value;
918}
SDDS (Self Describing Data Set) Data Types Definitions and Function Prototypes.
int32_t SDDS_CopyParameters(SDDS_DATASET *SDDS_target, SDDS_DATASET *SDDS_source)
Definition SDDS_copy.c:286
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.
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
double * SDDS_GetColumnInDoubles(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves the data of a specified numerical column as an array of doubles, considering only rows mark...
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.
Definition SDDS_info.c:364
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.
Definition SDDS_info.c:41
int32_t SDDS_InitializeInput(SDDS_DATASET *SDDS_dataset, char *filename)
Definition SDDS_input.c:49
int32_t SDDS_Terminate(SDDS_DATASET *SDDS_dataset)
int32_t SDDS_ReadPage(SDDS_DATASET *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.
Definition SDDS_utils.c:379
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.
Definition SDDS_utils.c:432
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
Definition SDDS_utils.c:677
#define SDDS_STRING
Identifier for the string data type.
Definition SDDStypes.h:85
#define SDDS_LONG
Identifier for the signed 32-bit integer data type.
Definition SDDStypes.h:61
#define SDDS_DOUBLE
Identifier for the double data type.
Definition SDDStypes.h:37
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.
Definition binsert.c:156
int find_min_max(double *min, double *max, double *list, int64_t n)
Finds the minimum and maximum values in a list of doubles.
Definition findMinMax.c:33
double max_in_array(double *array, long n)
Finds the maximum value in an array of doubles.
Definition findMinMax.c:318
double min_in_array(double *array, long n)
Finds the minimum value in an array of doubles.
Definition findMinMax.c:336
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)
Definition scanargs.c:36
long processPipeOption(char **item, long items, unsigned long *flags)
Definition scanargs.c:356
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
Definition scanargs.c:390
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.