Line data Source code
1 : /** \file histogramUniform.hpp
2 : * \author Jared R. Males
3 : * \brief Header for the std::vector utilities
4 : * \ingroup gen_math_files
5 : *
6 : */
7 :
8 : //***********************************************************************//
9 : // Copyright 2015, 2016, 2017 Jared R. Males (jaredmales@gmail.com)
10 : //
11 : // This file is part of mxlib.
12 : //
13 : // mxlib is free software: you can redistribute it and/or modify
14 : // it under the terms of the GNU General Public License as published by
15 : // the Free Software Foundation, either version 3 of the License, or
16 : // (at your option) any later version.
17 : //
18 : // mxlib is distributed in the hope that it will be useful,
19 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 : // GNU General Public License for more details.
22 : //
23 : // You should have received a copy of the GNU General Public License
24 : // along with mxlib. If not, see <http://www.gnu.org/licenses/>.
25 : //***********************************************************************//
26 :
27 : #ifndef math_histogramUniform_hpp
28 : #define math_histogramUniform_hpp
29 :
30 : #include <vector>
31 :
32 : namespace mx
33 : {
34 : namespace math
35 : {
36 :
37 : /// A histogram with uniform bin spacing
38 : /** Calculates the frequency in bins with uniform spacing.
39 : *
40 : * \tparam realT the real data type
41 : *
42 : * \ingroup gen_math
43 : */
44 : template <typename realT>
45 : class histogramUniform
46 : {
47 : protected:
48 : realT m_min{ 0 }; ///< The mininum bin location
49 : realT m_max{ 0 }; ///< The maximum bin location
50 : realT m_width{ 0 }; ///< The bin width
51 :
52 : std::vector<realT> m_freqs; ///< The frequencies, one for each bin.
53 :
54 : public:
55 :
56 : /// Default c'tor, does not allocate.
57 : /** Must call setup before use */
58 0 : histogramUniform()
59 0 : {
60 0 : }
61 :
62 : /// C'tor to setup the histogram, performing allocations.
63 0 : histogramUniform( realT mn, ///< [in] the minimum bin location
64 : realT mx, ///< [in] the maximum bin location
65 : realT w ///< [in] the bin width
66 : )
67 0 : : m_min( mn ), m_max( mx ), m_width( w )
68 : {
69 0 : reset();
70 0 : }
71 :
72 : /// C'tor to setup the histogram, performing allocations, and accumulate from a vector of values.
73 : /**
74 : * Optionally normalizes the histogram
75 : */
76 0 : histogramUniform( realT mn, ///< [in] the minimum bin location
77 : realT mx, ///< [in] the maximum bin location
78 : realT w, ///< [in] the bin width
79 : const std::vector<realT> &vals, ///< [in] The vector of values to accumulate
80 : bool normalize = false ///< [in] [opt] whether or not to normalize after accumulation
81 : )
82 0 : : m_min( mn ), m_max( mx ), m_width( w )
83 : {
84 0 : reset();
85 0 : accum( vals );
86 0 : if( normalize )
87 : {
88 0 : this->normalize();
89 : }
90 0 : }
91 :
92 : /// Setup the histogram, performing allocations.
93 0 : void setup( realT mn, ///< [in] the new minimum bin location
94 : realT mx, ///< [in] the new maximum bin location
95 : realT w ///< [in] the bin width
96 : )
97 : {
98 0 : m_min = mn;
99 0 : m_max = mx;
100 0 : m_width = w;
101 :
102 0 : reset();
103 0 : }
104 :
105 : /// Resize and 0 the frequency vector. Assumes m_min, m_max, and m_width are set.
106 0 : void reset()
107 : {
108 0 : m_freqs.resize( ( m_max - m_min ) / m_width + 1, 0 );
109 0 : }
110 :
111 : /// Accumulate a value in the appropriate bin.
112 0 : void accum( const realT &val /**< [in] The value to accumulate */ )
113 : {
114 0 : int i = ( val - m_min ) / m_width;
115 0 : if( i < 0 )
116 : {
117 0 : i = 0;
118 : }
119 0 : if( i >= m_freqs.size() )
120 : {
121 0 : i = m_freqs.size() - 1;
122 : }
123 :
124 0 : ++m_freqs[i];
125 0 : }
126 :
127 : /// Accumulate a vector of values.
128 0 : void accum( const std::vector<realT> &vals /**< [in] The vector of values to accumulate */ )
129 : {
130 0 : for( int i = 0; i < vals.size(); ++i )
131 : {
132 0 : accum( vals[i] );
133 : }
134 0 : }
135 :
136 : /// Get the frequency in the i-th bin.
137 0 : realT freq( int i /**< [in] the bin number */ )
138 : {
139 0 : return m_freqs[i]; ///\returns the current value of m_freqs[i].
140 : }
141 :
142 : /// Get the number of bins
143 0 : int bins()
144 : {
145 0 : return m_freqs.size(); ///\returns the size of the frequency vector.
146 : }
147 :
148 : /// Get the value of the left-edge of the i-th bin.
149 0 : realT binLeft( int i /**< [in] the bin number */ )
150 : {
151 0 : return m_min + i * m_width; ///\returns the value of the left-edge of the i-th bin.
152 : }
153 :
154 : /// Get the value of the middle of the i-th bin.
155 0 : realT binMid( int i /**< [in] the bin number */ )
156 : {
157 0 : return m_min + i * m_width + 0.5 * m_width; ///\returns the value of the middle of the i-th bin.
158 : }
159 :
160 : /// Get the value of the right edge of the i-th bin.
161 0 : realT binRight( int i /**< [in] the bin number */ )
162 : {
163 0 : return m_min + i * m_width + 1.0 * m_width; ///\returns the value of the right edge of the i-th bin.
164 : }
165 :
166 : /// Normalize the current frequencies so that the integral over all bins is 1.
167 : /** This normalizes the histogram so that it is a probability distribution, such that the sum
168 : * \f$ \sum_i P_i \Delta x = 1 \f$ where \f$ \Delta x \f$ is the bin width.
169 : */
170 0 : void normalize( int excludeTop = 0 /**< [in] [optional] specifies a number of bins at the
171 : top of the range to exclude from the sum */
172 : )
173 : {
174 0 : realT sum = 0;
175 :
176 0 : for( int i = 0; i < m_freqs.size() - excludeTop; ++i )
177 : {
178 0 : sum += m_freqs[i];
179 : }
180 :
181 0 : for( int i = 0; i < m_freqs.size(); ++i )
182 : {
183 0 : m_freqs[i] /= ( sum * m_width );
184 : }
185 0 : }
186 : };
187 :
188 : } // namespace math
189 : } // namespace mx
190 :
191 : #endif // math_histogramUniform_hpp
|