SDDSlib
Loading...
Searching...
No Matches
topbase.c
Go to the documentation of this file.
1/**
2 * @file topbase.c
3 * @brief Provides routines to determine the top-level and base-level of data.
4 *
5 * This file contains functions to find the top-level and base-level of a dataset, as well as to identify
6 * crossing points within the data. The routines utilize histogram binning and statistical analysis
7 * to compute these levels.
8 *
9 * @copyright
10 * - (c) 2002 The University of Chicago, as Operator of Argonne National Laboratory.
11 * - (c) 2002 The Regents of the University of California, as Operator of Los Alamos National Laboratory.
12 *
13 * @license
14 * This file is distributed under the terms of the Software License Agreement
15 * found in the file LICENSE included with this distribution.
16 *
17 * @author M. Borland, C. Saunders, R. Soliday
18 */
19
20#include "mdb.h"
21
22#define DEFAULT_BINFACTOR 0.05
23#define DEFAULT_SIGMAS 2
24
25/**
26 * @brief Finds the top-level and base-level of a dataset.
27 *
28 * @param top Pointer to store the computed top-level value.
29 * @param base Pointer to store the computed base-level value.
30 * @param data Pointer to the array of data points.
31 * @param points Number of data points in the array.
32 * @param bins Number of bins to use for histogram computation. If <= 0, a default bin factor is applied.
33 * @param sigmasRequired Number of standard deviations required for determining significant histogram peaks.
34 * @return Returns 1 on success, 0 on failure.
35 */
36long findTopBaseLevels(double *top, double *base, double *data, int64_t points,
37 long bins, double sigmasRequired) {
38 long binned, iMaximum, i;
39 static long maxBins = 0;
40 static double *histogram = NULL;
41 double min, max, midpoint, maxHistogram, meanBinned;
42 double lower, upper, delta;
43
44 if (bins <= 0)
45 bins = DEFAULT_BINFACTOR * points;
46 if (sigmasRequired <= 0)
47 sigmasRequired = DEFAULT_SIGMAS;
48 if (points < 2)
49 return 0;
50
51 if (bins > maxBins)
52 histogram = tmalloc(sizeof(*histogram) * (maxBins = bins));
53
54 if (!find_min_max(&min, &max, data, points))
55 return 0;
56
57 *base = min;
58 *top = max;
59 midpoint = (min + max) / 2;
60 if (points < 10)
61 return 1;
62
63 delta = (midpoint - min) / (bins - 1);
64 lower = min - delta / 2;
65 upper = midpoint + delta / 2;
66 if ((binned = make_histogram(histogram, bins, lower, upper, data, points, 1))) {
67 maxHistogram = 0;
68 iMaximum = -1;
69 for (i = 0; i < bins; i++) {
70 if (maxHistogram < histogram[i]) {
71 iMaximum = i;
72 maxHistogram = histogram[i];
73 }
74 }
75 meanBinned = ((double)binned) / bins;
76 if ((maxHistogram > 1) && (maxHistogram > (meanBinned + sigmasRequired * sqrt(meanBinned))))
77 *base = lower + (iMaximum + 0.5) * ((upper - lower) / bins);
78 }
79
80 delta = (max - midpoint) / (bins - 1);
81 lower = midpoint - delta / 2;
82 upper = max + delta / 2;
83 if ((binned = make_histogram(histogram, bins, lower, upper, data, points, 1))) {
84 maxHistogram = 0;
85 iMaximum = -1;
86 for (i = 0; i < bins; i++) {
87 if (maxHistogram < histogram[i]) {
88 iMaximum = i;
89 maxHistogram = histogram[i];
90 }
91 }
92 meanBinned = ((double)binned) / bins;
93 if ((maxHistogram > 1) && (maxHistogram > (meanBinned + sigmasRequired * sqrt(meanBinned))))
94 *top = lower + (iMaximum + 0.5) * ((upper - lower) / bins);
95 }
96
97 if (*top == *base) {
98 *base = min;
99 *top = max;
100 }
101 return 1;
102}
103
104/**
105 * @brief Finds the crossing point in the data where the data crosses a specified level.
106 *
107 * @param start The starting index to search for the crossing point.
108 * @param data Pointer to the array of data points.
109 * @param points Number of data points in the array.
110 * @param level The level at which to find the crossing point.
111 * @param direction The direction of crossing (positive for upward, negative for downward).
112 * @param indepData Pointer to the independent data array corresponding to the data points. Can be NULL.
113 * @param location Pointer to store the interpolated location of the crossing point. Can be NULL.
114 * @return
115 * @return The index of the crossing point on success,
116 * @return -1 if no crossing is found or if input parameters are invalid.
117 */
118int64_t findCrossingPoint(int64_t start, double *data, int64_t points, double level, long direction,
119 double *indepData, double *location) {
120 double diff;
121 int64_t i;
122 long transitionPossible;
123
124 if (start < 0 || start > (points - 1))
125 return -1;
126 transitionPossible = 0;
127 for (i = start; i < points; i++) {
128 diff = direction * (data[i] - level);
129 if (diff <= 0)
130 transitionPossible = 1;
131 if (diff > 0 && transitionPossible)
132 break;
133 }
134 if (i == points)
135 return -1;
136 if (!indepData || !location)
137 return i;
138 if (i == 0 || data[i] == data[i - 1]) {
139 *location = indepData[i];
140 return i;
141 }
142 *location = indepData[i - 1] + (indepData[i] - indepData[i - 1]) / (data[i] - data[i - 1]) * (level - data[i - 1]);
143 return i;
144}
void * tmalloc(uint64_t size_of_block)
Allocates a memory block of the specified size with zero initialization.
Definition array.c:59
int find_min_max(double *min, double *max, double *list, int64_t n)
Finds the minimum and maximum values in a list of doubles.
Definition findMinMax.c:33
long make_histogram(double *hist, long n_bins, double lo, double hi, double *data, int64_t n_pts, long new_start)
Compiles a histogram from data points.
long findTopBaseLevels(double *top, double *base, double *data, int64_t points, long bins, double sigmasRequired)
Finds the top-level and base-level of a dataset.
Definition topbase.c:36
int64_t findCrossingPoint(int64_t start, double *data, int64_t points, double level, long direction, double *indepData, double *location)
Finds the crossing point in the data where the data crosses a specified level.
Definition topbase.c:118