SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sddseventhist.c
Go to the documentation of this file.
1/**
2 * @file sddseventhist.c
3 * @brief Generates histograms for events from SDDS input files.
4 *
5 * @details
6 * This program processes SDDS files to generate histograms for events identified by a specific column.
7 * It allows for binning, normalization, and overlap analysis between event histograms.
8 * The program supports multiple options for customizing histogram generation, including bin size, limits,
9 * and normalization strategies. Input can be specified as files or through pipes.
10 *
11 * @section Usage
12 * ```
13 * sddseventhist [<inputfile>] [<outputfile>]
14 * [-pipe=<input>,<output>]
15 * -dataColumn=<columnName>
16 * -eventIdentifier=<columnName>
17 * [-overlapEvent=<eventValue>]
18 * [-bins=<number> | -sizeOfBins=<value>]
19 * [-lowerLimit=<value>]
20 * [-upperLimit=<value>]
21 * [-sides]
22 * [-normalize[={sum|area|peak}]]
23 * [-majorOrder=row|column]
24 * ```
25 *
26 * @section Options
27 * | Required | Description |
28 * |--------------------|----------------------------------------------------------------------------|
29 * | `-dataColumn` | Specifies the column to generate histograms for. |
30 * | `-eventIdentifier` | Specifies the column identifying unique events for separate histograms. |
31 *
32 * | Option | Description |
33 * |--------------------|----------------------------------------------------------------------------|
34 * | `-pipe` | Use pipe for input and/or output. |
35 * | `-overlapEvent` | Multiplies histograms with the specified event's histogram. |
36 * | `-bins` | Number of bins for the histogram. |
37 * | `-sizeOfBins` | Size of each bin. |
38 * | `-lowerLimit` | Lower limit for the histogram range. |
39 * | `-upperLimit` | Upper limit for the histogram range. |
40 * | `-sides` | Adds sides to the histogram extending to the zero level. |
41 * | `-normalize` | Normalizes the histogram by sum, area, or peak value. |
42 * | `-majorOrder` | Specifies the major order of data output: `row` or `column`. |
43 *
44 * @subsection Incompatibilities
45 * - `-bins` and `-sizeOfBins` cannot be used together.
46 * - The `-normalize` option defaults to `sum` if no specific value is provided.
47 *
48 * @subsection Requirements
49 * - `-eventIdentifier` must reference a string or integer column.
50 *
51 * @copyright
52 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
53 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
54 *
55 * @license
56 * This file is distributed under the terms of the Software License Agreement
57 * found in the file LICENSE included with this distribution.
58 *
59 * @authors
60 * M. Borland, R. Soliday, Xuesong Jiao, H. Shang
61 */
62
63#include "mdb.h"
64#include "scan.h"
65#include "SDDS.h"
66
67/* Enumeration for option types */
68enum option_type {
69 SET_BINS,
70 SET_LOWERLIMIT,
71 SET_UPPERLIMIT,
72 SET_DATACOLUMN,
73 SET_BINSIZE,
74 SET_NORMALIZE,
75 SET_SIDES,
76 SET_PIPE,
77 SET_EVENTIDENTIFIER,
78 SET_OVERLAPEVENT,
79 SET_MAJOR_ORDER,
80 N_OPTIONS
81};
82
83char *option[N_OPTIONS] = {
84 "bins",
85 "lowerlimit",
86 "upperlimit",
87 "datacolumn",
88 "sizeofbins",
89 "normalize",
90 "sides",
91 "pipe",
92 "eventidentifier",
93 "overlapevent",
94 "majorOrder",
95};
96
97/* Improved usage message for better readability */
98char *USAGE =
99 "sddseventhist [<inputfile>] [<outputfile>]\n"
100 " [-pipe=<input>,<output>]\n"
101 " -dataColumn=<columnName>\n"
102 " -eventIdentifier=<columnName>\n"
103 " [-overlapEvent=<eventValue>]\n"
104 " [-bins=<number> | -sizeOfBins=<value>]\n"
105 " [-lowerLimit=<value>]\n"
106 " [-upperLimit=<value>]\n"
107 " [-sides]\n"
108 " [-normalize[={sum|area|peak}]]\n"
109 " [-majorOrder=row|column]\n";
110
111static char *additional_help = "\n\
112dataColumn : Name of the column to histogram.\n\
113eventIdentifier : Name of the column used to identify events.\n\
114 A separate histogram is created for each unique value in this column.\n\
115 The column must contain string or integer data;\n\
116 if string data, the values must be valid SDDS column names.\n\
117overlapEvent : If specified, histograms are multiplied bin-by-bin with this event's histogram.\n\
118bins : Number of bins for the histogram.\n\
119sizeOfBins : Size of each bin for the histogram.\n\
120lowerLimit : Lower limit of the histogram range.\n\
121upperLimit : Upper limit of the histogram range.\n\
122normalize : Normalize the histogram by sum, area, or peak.\n\
123sides : Adds sides to the histogram down to the zero level.\n\
124majorOrder : Specifies the major order for the output file (row or column).\n\n\
125Program by Michael Borland. (" __DATE__ " " __TIME__ ", SVN revision: " SVN_VERSION ")\n";
126
127#define NORMALIZE_PEAK 0
128#define NORMALIZE_AREA 1
129#define NORMALIZE_SUM 2
130#define NORMALIZE_NO 3
131#define N_NORMALIZE_OPTIONS 4
132
133char *normalize_option[N_NORMALIZE_OPTIONS] = {
134 "peak", "area", "sum", "no"};
135
136typedef struct
137{
138 char *string;
139 int64_t events;
140 double *data;
141 /* Indices in output file of histogram and overlap */
142 long histogramIndex, overlapIndex;
143} EVENT_DATA;
144
145typedef struct
146{
147 char *string;
148 double data;
149} EVENT_PAIR;
150
151static long setupOutputFile(SDDS_DATASET *outTable, char *outputfile, SDDS_DATASET *inTable,
152 char *inputfile, char *dataColumn, char *eventIDColumn, char *overlapEventID,
153 EVENT_DATA **eventDataRet, int64_t *eventIDsRet, double **dataRet, long bins,
154 double binSize, long normalizeMode, short columnMajorOrder);
155long makeEventHistogram(double *hist, long bins, double lowerLimit, double dx, EVENT_DATA *eventRefData);
156void makeEventOverlap(double *overlap, double *hist, double *overlapHist, long bins);
157int event_cmpasc(const void *ep1, const void *ep2);
158
159int main(int argc, char **argv) {
160 /* Flags to keep track of what is set in command line */
161 long binsGiven, lowerLimitGiven, upperLimitGiven;
162 SDDS_DATASET inTable, outTable;
163 double *data; /* Pointer to the array to histogram */
164 double *hist; /* To store the histogram */
165 double *indep; /* To store values of bin centers */
166 double *overlap, *overlapHist;
167 double lowerLimit, upperLimit; /* Lower and upper limits in histogram */
168 double givenLowerLimit, givenUpperLimit; /* Given lower and upper limits */
169 double range, binSize;
170 long bins; /* Number of bins in the histogram */
171 char *dataColumn, *eventIDColumn, *overlapEventID;
172 SCANNED_ARG *scanned; /* Scanned argument structure */
173 char *inputfile, *outputfile; /* Input and output file names */
174 double dx; /* Spacing of bins in histogram */
175 long pointsBinned; /* Number of points that are in histogram */
176 long normalizeMode, doSides, verbose = 0, readCode;
177 unsigned long pipeFlags, majorOrderFlag;
178 long eventIDIndex, eventIDType;
179 int64_t eventRefIDs = 0;
180 EVENT_DATA *eventRefData = NULL;
181 /*char **eventID; */
182 int64_t i, points, iEvent;
183 short columnMajorOrder = -1;
184
186
187 argc = scanargs(&scanned, argc, argv);
188 if (argc < 3) {
189 fprintf(stderr, "Usage: %s\n", USAGE);
190 fputs(additional_help, stderr);
191 exit(EXIT_FAILURE);
192 }
193
194 hist = overlap = overlapHist = NULL;
195 binsGiven = lowerLimitGiven = upperLimitGiven = 0;
196 binSize = doSides = 0;
197 inputfile = outputfile = NULL;
198 dataColumn = eventIDColumn = overlapEventID = NULL;
199 normalizeMode = NORMALIZE_NO;
200 pipeFlags = 0;
201
202 for (i = 1; i < argc; i++) {
203 if (scanned[i].arg_type == OPTION) {
204 switch (match_string(scanned[i].list[0], option, N_OPTIONS, 0)) {
205 case SET_MAJOR_ORDER:
206 majorOrderFlag = 0;
207 scanned[i].n_items--;
208 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)))
209 SDDS_Bomb("invalid -majorOrder syntax/values");
210 if (majorOrderFlag & SDDS_COLUMN_MAJOR_ORDER)
211 columnMajorOrder = 1;
212 else if (majorOrderFlag & SDDS_ROW_MAJOR_ORDER)
213 columnMajorOrder = 0;
214 break;
215 case SET_BINS: /* set number of bins */
216 if (binsGiven)
217 SDDS_Bomb("-bins specified more than once");
218 binsGiven = 1;
219 if (sscanf(scanned[i].list[1], "%ld", &bins) != 1 || bins <= 0)
220 SDDS_Bomb("invalid value for bins");
221 break;
222 case SET_LOWERLIMIT:
223 if (lowerLimitGiven)
224 SDDS_Bomb("-lowerLimit specified more than once");
225 lowerLimitGiven = 1;
226 if (sscanf(scanned[i].list[1], "%lf", &givenLowerLimit) != 1)
227 SDDS_Bomb("invalid value for lowerLimit");
228 break;
229 case SET_UPPERLIMIT:
230 if (upperLimitGiven)
231 SDDS_Bomb("-upperLimit specified more than once");
232 upperLimitGiven = 1;
233 if (sscanf(scanned[i].list[1], "%lf", &givenUpperLimit) != 1)
234 SDDS_Bomb("invalid value for upperLimit");
235 break;
236 case SET_DATACOLUMN:
237 if (dataColumn)
238 SDDS_Bomb("-dataColumn specified more than once");
239 if (scanned[i].n_items != 2)
240 SDDS_Bomb("invalid -dataColumn syntax---supply name");
241 dataColumn = scanned[i].list[1];
242 break;
243 case SET_EVENTIDENTIFIER:
244 if (eventIDColumn)
245 SDDS_Bomb("-eventIdentifier specified more than once");
246 if (scanned[i].n_items != 2)
247 SDDS_Bomb("invalid -eventIdentifier syntax---supply name");
248 eventIDColumn = scanned[i].list[1];
249 break;
250 case SET_OVERLAPEVENT:
251 if (overlapEventID)
252 SDDS_Bomb("-overlapEvent specified more than once");
253 if (scanned[i].n_items != 2)
254 SDDS_Bomb("invalid -overlapEvent syntax---supply value");
255 overlapEventID = scanned[i].list[1];
256 if (!strlen(overlapEventID))
257 SDDS_Bomb("invalid -overlapEvent syntax---supply value");
258 break;
259 case SET_NORMALIZE:
260 if (scanned[i].n_items == 1)
261 normalizeMode = NORMALIZE_SUM;
262 else if (scanned[i].n_items != 2 || (normalizeMode = match_string(scanned[i].list[1], normalize_option, N_NORMALIZE_OPTIONS, 0)) < 0)
263 SDDS_Bomb("invalid -normalize syntax");
264 break;
265 case SET_SIDES:
266 doSides = 1;
267 break;
268 case SET_BINSIZE:
269 if (sscanf(scanned[i].list[1], "%le", &binSize) != 1 || binSize <= 0)
270 SDDS_Bomb("invalid value for bin size");
271 break;
272 case SET_PIPE:
273 if (!processPipeOption(scanned[i].list + 1, scanned[i].n_items - 1, &pipeFlags))
274 SDDS_Bomb("invalid -pipe syntax");
275 break;
276 default:
277 fprintf(stderr, "Error: option %s not recognized\n", scanned[i].list[0]);
278 exit(EXIT_FAILURE);
279 break;
280 }
281 } else {
282 /* Argument is filename */
283 if (!inputfile)
284 inputfile = scanned[i].list[0];
285 else if (!outputfile)
286 outputfile = scanned[i].list[0];
287 else
288 SDDS_Bomb("Too many filenames provided.");
289 }
290 }
291
292 processFilenames("sddseventhist", &inputfile, &outputfile, pipeFlags, 0, NULL);
293
294 if (binSize && binsGiven)
295 SDDS_Bomb("Specify either -binSize or -bins, not both.");
296 if (!binsGiven)
297 bins = 20;
298 if (!dataColumn)
299 SDDS_Bomb("-dataColumn must be specified.");
300 if (!eventIDColumn)
301 SDDS_Bomb("-eventIdentifier must be specified.");
302
303 if (!(indep = SDDS_Malloc(sizeof(*indep) * (bins + 2))) ||
304 !(hist = SDDS_Malloc(sizeof(*hist) * (bins + 2))) ||
305 !(overlap = SDDS_Malloc(sizeof(*overlap) * (bins + 2))) ||
306 !(overlapHist = SDDS_Malloc(sizeof(*overlapHist) * (bins + 2))))
307 SDDS_Bomb("Memory allocation failure.");
308
309 if (!SDDS_InitializeInput(&inTable, inputfile))
310 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
311 if (SDDS_GetColumnIndex(&inTable, dataColumn) < 0)
312 SDDS_Bomb("Data column not found.");
313 if ((eventIDIndex = SDDS_GetColumnIndex(&inTable, eventIDColumn)) < 0)
314 SDDS_Bomb("Event ID column not found.");
315 if ((eventIDType = SDDS_GetColumnType(&inTable, eventIDIndex)) != SDDS_STRING)
316 SDDS_Bomb("Event ID column must be of string type.");
317 if (!SDDS_NUMERIC_TYPE(SDDS_GetNamedColumnType(&inTable, dataColumn)))
318 SDDS_Bomb("Data column must be of a numeric data type.");
319
320 data = NULL;
321 while ((readCode = SDDS_ReadPage(&inTable)) > 0) {
322 if (readCode > 1)
323 SDDS_Bomb("This program cannot process multi-page files.");
324 pointsBinned = 0;
325 if ((points = SDDS_CountRowsOfInterest(&inTable)) < 0)
326 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
327 if (!points)
328 SDDS_Bomb("No data found in the file.");
329
330 if (!setupOutputFile(&outTable, outputfile, &inTable, inputfile, dataColumn, eventIDColumn, overlapEventID, &eventRefData, &eventRefIDs, &data, bins, binSize, normalizeMode, columnMajorOrder))
331 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
332
333 if (!lowerLimitGiven) {
334 lowerLimit = 0;
335 if (points)
336 lowerLimit = data[0];
337 for (i = 0; i < points; i++)
338 if (lowerLimit > data[i])
339 lowerLimit = data[i];
340 } else {
341 lowerLimit = givenLowerLimit;
342 }
343
344 if (!upperLimitGiven) {
345 upperLimit = 0;
346 if (points)
347 upperLimit = data[0];
348 for (i = 0; i < points; i++)
349 if (upperLimit < data[i])
350 upperLimit = data[i];
351 } else {
352 upperLimit = givenUpperLimit;
353 }
354
355 free(data);
356 data = NULL;
357 range = upperLimit - lowerLimit;
358 if (!lowerLimitGiven)
359 lowerLimit -= range * 1e-7;
360 if (!upperLimitGiven)
361 upperLimit += range * 1e-7;
362 if (upperLimit == lowerLimit) {
363 if (binSize) {
364 upperLimit += binSize / 2;
365 lowerLimit -= binSize / 2;
366 } else if (fabs(upperLimit) < sqrt(DBL_MIN)) {
367 upperLimit = sqrt(DBL_MIN);
368 lowerLimit = -sqrt(DBL_MIN);
369 } else {
370 upperLimit += upperLimit * (1 + 2 * DBL_EPSILON);
371 lowerLimit -= upperLimit * (1 - 2 * DBL_EPSILON);
372 }
373 }
374 dx = (upperLimit - lowerLimit) / bins;
375
376 if (binSize) {
377 double middle;
378 range = ((range / binSize) + 1) * binSize;
379 middle = (lowerLimit + upperLimit) / 2;
380 lowerLimit = middle - range / 2;
381 upperLimit = middle + range / 2;
382 dx = binSize;
383 bins = range / binSize + 0.5;
384 if (bins < 1 && !doSides)
385 bins = 2;
386 if (!(indep = SDDS_Realloc(indep, sizeof(*indep) * (bins + 2))) ||
387 !(hist = SDDS_Realloc(hist, sizeof(*hist) * (bins + 2))) ||
388 !(overlap = SDDS_Realloc(overlap, sizeof(*overlap) * (bins + 2))) ||
389 !(overlapHist = SDDS_Realloc(overlapHist, sizeof(*overlapHist) * (bins + 2))))
390 SDDS_Bomb("Memory allocation failure.");
391 }
392
393 for (i = -1; i < bins + 1; i++) {
394 indep[i + 1] = (i + 0.5) * dx + lowerLimit;
395 }
396 if (!SDDS_StartPage(&outTable, points ? (doSides ? bins + 2 : bins) : 0) ||
397 !SDDS_CopyParameters(&outTable, &inTable) ||
398 (points && (!SDDS_SetColumnFromDoubles(&outTable, SDDS_SET_BY_NAME, indep + (doSides ? 0 : 1), doSides ? bins + 2 : bins, dataColumn))))
399 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
400
401 if (overlapEventID) {
402 for (iEvent = 0; iEvent < eventRefIDs; iEvent++) {
403 if (strcmp(eventRefData[iEvent].string, overlapEventID) == 0)
404 break;
405 }
406 if (iEvent == eventRefIDs)
407 SDDS_Bomb("Cannot create overlap as the specified overlap event is not present.");
408 makeEventHistogram(overlapHist, bins, lowerLimit, dx, eventRefData + iEvent);
409 }
410
411 for (iEvent = pointsBinned = 0; iEvent < eventRefIDs; iEvent++) {
412 pointsBinned += makeEventHistogram(hist, bins, lowerLimit, dx, eventRefData + iEvent);
413 if (normalizeMode != NORMALIZE_NO) {
414 double norm = 0;
415 switch (normalizeMode) {
416 case NORMALIZE_PEAK:
417 norm = max_in_array(hist, bins);
418 break;
419 case NORMALIZE_AREA:
420 case NORMALIZE_SUM:
421 for (i = 0; i < bins; i++)
422 norm += hist[i];
423 if (normalizeMode == NORMALIZE_AREA)
424 norm *= dx;
425 break;
426 default:
427 SDDS_Bomb("Invalid normalization mode.");
428 break;
429 }
430 if (norm)
431 for (i = 0; i < bins; i++)
432 hist[i] /= norm;
433 }
434
435 if (!SDDS_SetColumnFromDoubles(&outTable, SDDS_SET_BY_INDEX, hist + (doSides ? 0 : 1), doSides ? bins + 2 : bins, eventRefData[iEvent].histogramIndex))
436 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
437 if (overlapEventID) {
438 makeEventOverlap(overlap, hist, overlapHist, bins + 2);
439 if (!SDDS_SetColumnFromDoubles(&outTable, SDDS_SET_BY_INDEX, overlap + (doSides ? 0 : 1), doSides ? bins + 2 : bins, eventRefData[iEvent].overlapIndex))
440 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
441 }
442 free(eventRefData[iEvent].data);
443 }
444
445 if (!SDDS_SetParameters(&outTable, SDDS_SET_BY_NAME | SDDS_PASS_BY_VALUE,
446 "sddseventhistBins", bins,
447 "sddseventhistBinSize", dx,
448 "sddseventhistPointsBinned", pointsBinned,
449 NULL))
450 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
451
452 if (verbose)
453 fprintf(stderr, "%ld points of %" PRId64 " from page %ld histogrammed in %ld bins\n", pointsBinned, points, readCode, bins);
454
455 if (!SDDS_WritePage(&outTable))
456 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors | SDDS_EXIT_PrintErrors);
457 free(eventRefData);
458 }
459
460 if (!SDDS_Terminate(&inTable)) {
461 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
462 return EXIT_FAILURE;
463 }
464 if (!SDDS_Terminate(&outTable)) {
465 SDDS_PrintErrors(stderr, SDDS_VERBOSE_PrintErrors);
466 return EXIT_FAILURE;
467 }
468
469 free(hist);
470 free(overlapHist);
471 free(overlap);
472 free(indep);
473 return EXIT_SUCCESS;
474}
475
476long setupOutputFile(SDDS_DATASET *outTable, char *outputfile, SDDS_DATASET *inTable,
477 char *inputfile, char *dataColumn, char *eventIDColumn, char *overlapEventID,
478 EVENT_DATA **eventDataRet, int64_t *eventIDsRet, double **dataRet, long bins,
479 double binSize, long normalizeMode, short columnMajorOrder) {
480 char **eventValue, buffer[SDDS_MAXLINE];
481 int64_t eventRows, uniqueRows, row;
482 EVENT_DATA *eventData;
483 EVENT_PAIR *eventPair;
484 double *eventDataValue;
485 int64_t row0, iEvent, drow;
486
487 if (!SDDS_InitializeOutput(outTable, SDDS_BINARY, 0, NULL, "sddseventhist output", outputfile) ||
488 !SDDS_TransferColumnDefinition(outTable, inTable, dataColumn, NULL) ||
489 (eventRows = SDDS_RowCount(inTable)) == 0 ||
490 !(eventValue = SDDS_GetColumn(inTable, eventIDColumn)) ||
491 !(*dataRet = eventDataValue = SDDS_GetColumnInDoubles(inTable, dataColumn)))
492 return 0;
493 if (columnMajorOrder != -1)
494 outTable->layout.data_mode.column_major = columnMajorOrder;
495 else
496 outTable->layout.data_mode.column_major = inTable->layout.data_mode.column_major;
497
498 if (!(eventPair = SDDS_Malloc(sizeof(*eventPair) * eventRows)))
499 SDDS_Bomb("Memory allocation failure.");
500
501 /* Populate eventPair with event strings and data */
502 for (row = 0; row < eventRows; row++) {
503 eventPair[row].string = eventValue[row];
504 eventPair[row].data = eventDataValue[row];
505 }
506 qsort(eventPair, eventRows, sizeof(*eventPair), event_cmpasc);
507
508 /* Count unique events */
509 uniqueRows = 1;
510 for (row = 1; row < eventRows; row++) {
511 if (strcmp(eventPair[row - 1].string, eventPair[row].string) != 0)
512 uniqueRows++;
513 }
514 *eventIDsRet = uniqueRows;
515
516 /* Allocate and populate EVENT_DATA structures */
517 if (!(eventData = *eventDataRet = SDDS_Malloc(sizeof(**eventDataRet) * uniqueRows)))
518 SDDS_Bomb("Memory allocation failure.");
519 row0 = 0;
520 iEvent = 0;
521 for (row = 1; row < eventRows; row++) {
522 if (row == (eventRows - 1) || strcmp(eventPair[row].string, eventPair[row0].string) != 0) {
523 /* [row0, row-1] have the same event name */
524 eventData[iEvent].events = row - row0;
525 if (!SDDS_CopyString(&eventData[iEvent].string, eventPair[row0].string) ||
526 !(eventData[iEvent].data = SDDS_Malloc(sizeof(*eventData[iEvent].data) * eventData[iEvent].events)))
527 SDDS_Bomb("Memory allocation failure");
528 for (drow = 0; drow < eventData[iEvent].events; drow++) {
529 eventData[iEvent].data[drow] = eventPair[row0 + drow].data;
530 /* free(eventPair[row0+drow].string); */
531 }
532 if (row == (eventRows - 1) && strcmp(eventPair[row].string, eventPair[row0].string) != 0) {
533 /* this is necessary to pick up the last event if it is a loner */
534 row0 = row;
535 row--;
536 } else {
537 row0 = row;
538 }
539 iEvent++;
540 }
541 }
542
543 free(eventPair);
544 for (row = 0; row < eventRows; row++)
545 free(eventValue[row]);
546 free(eventValue);
547 if (iEvent != uniqueRows)
548 SDDS_Bomb("Unique row count mismatch.");
549
550 if (overlapEventID && strlen(overlapEventID)) {
551 for (iEvent = 0; iEvent < uniqueRows; iEvent++) {
552 if (strcmp(overlapEventID, eventData[iEvent].string) == 0)
553 break;
554 }
555 if (iEvent == uniqueRows)
556 SDDS_Bomb("Overlap event not found.");
557 }
558
559 for (row = 0; row < uniqueRows; row++) {
560 snprintf(buffer, sizeof(buffer), "%sFrequency", eventData[row].string);
561 if ((eventData[row].histogramIndex = SDDS_DefineColumn(outTable, buffer, NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0)) < 0)
562 return 0;
563 eventData[row].overlapIndex = -1;
564 if (overlapEventID) {
565 snprintf(buffer, sizeof(buffer), "%s.%sOverlap", eventData[row].string, overlapEventID);
566 if ((eventData[row].overlapIndex = SDDS_DefineColumn(outTable, buffer, NULL, NULL, NULL, NULL, SDDS_DOUBLE, 0)) < 0)
567 return 0;
568 }
569 }
570
571 if (SDDS_DefineParameter(outTable, "sddseventhistInput", NULL, NULL, NULL, NULL, SDDS_STRING,
572 inputfile) < 0 ||
573 SDDS_DefineParameter(outTable, "sddseventhistBins", NULL, NULL, NULL, NULL, SDDS_LONG,
574 NULL) < 0 ||
575 SDDS_DefineParameter(outTable, "sddseventhistBinSize", NULL, NULL, NULL, NULL,
576 SDDS_DOUBLE, NULL) < 0 ||
577 SDDS_DefineParameter(outTable, "sddseventhistPointsBinned", NULL, NULL, NULL, NULL, SDDS_LONG,
578 NULL) < 0 ||
579 SDDS_DefineParameter(outTable, "sddseventhistEventIDColumn", NULL, NULL, NULL, NULL,
580 SDDS_STRING, eventIDColumn) < 0 ||
581 SDDS_DefineParameter(outTable, "sddshistNormMode", NULL, NULL, NULL, NULL, SDDS_STRING, normalize_option[normalizeMode]) < 0 ||
582 !SDDS_TransferAllParameterDefinitions(outTable, inTable, SDDS_TRANSFER_KEEPOLD) || !SDDS_WriteLayout(outTable))
583 return 0;
584 return 1;
585}
586
587long makeEventHistogram(double *hist, long bins, double lowerLimit, double dx, EVENT_DATA *eventRefData) {
588 long iBin, pointsBinned;
589 int64_t iRow;
590 double *hist1;
591 hist1 = hist + 1;
592 for (iBin = 0; iBin <= bins + 1; iBin++)
593 hist[iBin] = 0;
594 for (iRow = 0; iRow < eventRefData->events; iRow++) {
595 iBin = (eventRefData->data[iRow] - lowerLimit) / dx;
596 if (iBin >= 0 && iBin < bins)
597 hist1[iBin] += 1;
598 }
599 for (iBin = pointsBinned = 0; iBin < bins; iBin++)
600 pointsBinned += hist1[iBin];
601 return pointsBinned;
602}
603
604void makeEventOverlap(double *overlap, double *hist, double *overlapHist, long bins) {
605 long i;
606 for (i = 0; i < bins; i++) {
607 overlap[i] = fmin(hist[i], overlapHist[i]);
608 }
609}
610
611int event_cmpasc(const void *ep1, const void *ep2) {
612 EVENT_PAIR *ev1, *ev2;
613 int comp;
614 ev1 = (EVENT_PAIR *)ep1;
615 ev2 = (EVENT_PAIR *)ep2;
616 if ((comp = strcmp(ev1->string, ev2->string)) != 0)
617 return comp;
618 if (ev1->data < ev2->data)
619 return -1;
620 else if (ev1->data > ev2->data)
621 return 1;
622 else
623 return 0;
624}
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_SetParameters(SDDS_DATASET *SDDS_dataset, int32_t mode,...)
int32_t SDDS_SetColumnFromDoubles(SDDS_DATASET *SDDS_dataset, int32_t mode, double *data, int64_t rows,...)
Sets the values for a single data column using double-precision floating-point numbers.
void * SDDS_GetColumn(SDDS_DATASET *SDDS_dataset, char *column_name)
Retrieves a copy of the data for a specified column, including only rows marked as "of interest".
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_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_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_DefineParameter(SDDS_DATASET *SDDS_dataset, const char *name, const char *symbol, const char *units, const char *description, const char *format_string, int32_t type, char *fixed_value)
Defines a data parameter with a fixed string value.
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.
int32_t SDDS_GetNamedColumnType(SDDS_DATASET *SDDS_dataset, char *name)
Retrieves the data type of a column in the SDDS dataset by its name.
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_Malloc(size_t size)
Allocates memory of a specified size.
Definition SDDS_utils.c:639
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
Definition SDDS_utils.c:288
int32_t SDDS_GetColumnType(SDDS_DATASET *SDDS_dataset, int32_t index)
Retrieves the data type of a column in the SDDS dataset by its index.
void SDDS_Bomb(char *message)
Terminates the program after printing an error message and recorded errors.
Definition SDDS_utils.c:342
int32_t SDDS_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
Definition SDDS_utils.c:856
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
#define SDDS_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
Definition SDDStypes.h:138
double max_in_array(double *array, long n)
Finds the maximum value in an array of doubles.
Definition findMinMax.c:318
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.