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