159 {
160
161 long binsGiven, lowerLimitGiven, upperLimitGiven;
163 double *data;
164 double *hist;
165 double *indep;
166 double *overlap, *overlapHist;
167 double lowerLimit, upperLimit;
168 double givenLowerLimit, givenUpperLimit;
169 double range, binSize;
170 long bins;
171 char *dataColumn, *eventIDColumn, *overlapEventID;
172 SCANNED_ARG *scanned;
173 char *inputfile, *outputfile;
174 double dx;
175 long pointsBinned;
176 long normalizeMode, doSides, verbose = 0, readCode;
177 unsigned long pipeFlags, majorOrderFlag;
178 long eventIDIndex, eventIDType;
179 int64_t eventRefIDs = 0;
181
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:
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)
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)
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)
271 break;
272 case SET_PIPE:
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
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))))
308
316 SDDS_Bomb(
"Event ID column must be of string type.");
318 SDDS_Bomb(
"Data column must be of a numeric data type.");
319
320 data = NULL;
322 if (readCode > 1)
323 SDDS_Bomb(
"This program cannot process multi-page files.");
324 pointsBinned = 0;
327 if (!points)
329
330 if (!setupOutputFile(&outTable, outputfile, &inTable, inputfile, dataColumn, eventIDColumn, overlapEventID, &eventRefData, &eventRefIDs, &data, bins, binSize, normalizeMode, columnMajorOrder))
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))))
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) ||
398 (points && (!
SDDS_SetColumnFromDoubles(&outTable, SDDS_SET_BY_NAME, indep + (doSides ? 0 : 1), doSides ? bins + 2 : bins, dataColumn))))
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:
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))
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))
441 }
442 free(eventRefData[iEvent].data);
443 }
444
446 "sddseventhistBins", bins,
447 "sddseventhistBinSize", dx,
448 "sddseventhistPointsBinned", pointsBinned,
449 NULL))
451
452 if (verbose)
453 fprintf(stderr, "%ld points of %" PRId64 " from page %ld histogrammed in %ld bins\n", pointsBinned, points, readCode, bins);
454
457 free(eventRefData);
458 }
459
462 return EXIT_FAILURE;
463 }
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)
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.
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.
void * SDDS_Malloc(size_t size)
Allocates memory of a specified size.
void SDDS_RegisterProgramName(const char *name)
Registers the executable program name for use in error messages.
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.
void * SDDS_Realloc(void *old_ptr, size_t new_size)
Reallocates memory to a new size.
#define SDDS_STRING
Identifier for the string data type.
#define SDDS_NUMERIC_TYPE(type)
Checks if the given type identifier corresponds to any numeric type.
double max_in_array(double *array, long n)
Finds the maximum value in an array of doubles.
long match_string(char *string, char **option, long n_options, long mode)
Matches a given string against an array of option strings based on specified modes.
int scanargs(SCANNED_ARG **scanned, int argc, char **argv)
long processPipeOption(char **item, long items, unsigned long *flags)
void processFilenames(char *programName, char **input, char **output, unsigned long pipeFlags, long noWarnings, long *tmpOutputUsed)
long scanItemList(unsigned long *flags, char **item, long *items, unsigned long mode,...)
Scans a list of items and assigns values based on provided keywords and types.