SDDS ToolKit Programs and Libraries for C and Python
All Classes Files Functions Variables Macros Pages
sddseventhist.c File Reference

Detailed Description

Generates histograms for events from SDDS input files.

This program processes SDDS files to generate histograms for events identified by a specific column. It allows for binning, normalization, and overlap analysis between event histograms. The program supports multiple options for customizing histogram generation, including bin size, limits, and normalization strategies. Input can be specified as files or through pipes.

Usage

sddseventhist [<inputfile>] [<outputfile>]
[-pipe=<input>,<output>]
-dataColumn=<columnName>
-eventIdentifier=<columnName>
[-overlapEvent=<eventValue>]
[-bins=<number> | -sizeOfBins=<value>]
[-lowerLimit=<value>]
[-upperLimit=<value>]
[-sides]
[-normalize[={sum|area|peak}]]
[-majorOrder=row|column]

Options

Required Description
-dataColumn Specifies the column to generate histograms for.
-eventIdentifier Specifies the column identifying unique events for separate histograms.
Option Description
-pipe Use pipe for input and/or output.
-overlapEvent Multiplies histograms with the specified event's histogram.
-bins Number of bins for the histogram.
-sizeOfBins Size of each bin.
-lowerLimit Lower limit for the histogram range.
-upperLimit Upper limit for the histogram range.
-sides Adds sides to the histogram extending to the zero level.
-normalize Normalizes the histogram by sum, area, or peak value.
-majorOrder Specifies the major order of data output: row or column.

Incompatibilities

  • -bins and -sizeOfBins cannot be used together.
  • The -normalize option defaults to sum if no specific value is provided.

Requirements

  • -eventIdentifier must reference a string or integer column.
License
This file is distributed under the terms of the Software License Agreement found in the file LICENSE included with this distribution.
Authors
M. Borland, R. Soliday, Xuesong Jiao, H. Shang

Definition in file sddseventhist.c.

#include "mdb.h"
#include "scan.h"
#include "SDDS.h"

Go to the source code of this file.

Functions

static long setupOutputFile (SDDS_DATASET *outTable, char *outputfile, SDDS_DATASET *inTable, char *inputfile, char *dataColumn, char *eventIDColumn, char *overlapEventID, EVENT_DATA **eventDataRet, int64_t *eventIDsRet, double **dataRet, long bins, double binSize, long normalizeMode, short columnMajorOrder)
 
long makeEventHistogram (double *hist, long bins, double lowerLimit, double dx, EVENT_DATA *eventRefData)
 
void makeEventOverlap (double *overlap, double *hist, double *overlapHist, long bins)
 
int event_cmpasc (const void *ep1, const void *ep2)
 
int main (int argc, char **argv)
 

Function Documentation

◆ event_cmpasc()

int event_cmpasc ( const void * ep1,
const void * ep2 )

Definition at line 611 of file sddseventhist.c.

611 {
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}

◆ main()

int main ( int argc,
char ** argv )

Definition at line 159 of file sddseventhist.c.

159 {
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}
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.
int64_t SDDS_CountRowsOfInterest(SDDS_DATASET *SDDS_dataset)
Counts the number of rows marked as "of interest" in the current data table.
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_WritePage(SDDS_DATASET *SDDS_dataset)
Writes the current data table to the output file.
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
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_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.

◆ makeEventHistogram()

long makeEventHistogram ( double * hist,
long bins,
double lowerLimit,
double dx,
EVENT_DATA * eventRefData )

Definition at line 587 of file sddseventhist.c.

587 {
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}

◆ makeEventOverlap()

void makeEventOverlap ( double * overlap,
double * hist,
double * overlapHist,
long bins )

Definition at line 604 of file sddseventhist.c.

604 {
605 long i;
606 for (i = 0; i < bins; i++) {
607 overlap[i] = fmin(hist[i], overlapHist[i]);
608 }
609}

◆ setupOutputFile()

long setupOutputFile ( SDDS_DATASET * outTable,
char * outputfile,
SDDS_DATASET * inTable,
char * inputfile,
char * dataColumn,
char * eventIDColumn,
char * overlapEventID,
EVENT_DATA ** eventDataRet,
int64_t * eventIDsRet,
double ** dataRet,
long bins,
double binSize,
long normalizeMode,
short columnMajorOrder )
static

Definition at line 476 of file sddseventhist.c.

479 {
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}
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".
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_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_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_CopyString(char **target, const char *source)
Copies a source string to a target string with memory allocation.
Definition SDDS_utils.c:856
#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