| 1 | /*
 | 
|---|
| 2 |  * Histogram.hpp
 | 
|---|
| 3 |  *
 | 
|---|
| 4 |  *  Created on: Jul 26, 2012
 | 
|---|
| 5 |  *      Author: heber
 | 
|---|
| 6 |  */
 | 
|---|
| 7 | 
 | 
|---|
| 8 | #ifndef HISTOGRAM_HPP_
 | 
|---|
| 9 | #define HISTOGRAM_HPP_
 | 
|---|
| 10 | 
 | 
|---|
| 11 | 
 | 
|---|
| 12 | // include config.h
 | 
|---|
| 13 | #ifdef HAVE_CONFIG_H
 | 
|---|
| 14 | #include <config.h>
 | 
|---|
| 15 | #endif
 | 
|---|
| 16 | 
 | 
|---|
| 17 | #include <iosfwd>
 | 
|---|
| 18 | #include <map>
 | 
|---|
| 19 | #include <vector>
 | 
|---|
| 20 | 
 | 
|---|
| 21 | class HistogramTest;
 | 
|---|
| 22 | 
 | 
|---|
| 23 | /** This class generates a histogram from a given vector of sampled values.
 | 
|---|
| 24 |  *
 | 
|---|
| 25 |  * Most importantly, it also contains operator+=() and operator-=() to perform
 | 
|---|
| 26 |  * sum on the \b histograms.
 | 
|---|
| 27 |  *
 | 
|---|
| 28 |  * This is to be used with the OrthogonalSummation which requires these specific
 | 
|---|
| 29 |  * operator implementations.
 | 
|---|
| 30 |  *
 | 
|---|
| 31 |  */
 | 
|---|
| 32 | class Histogram
 | 
|---|
| 33 | {
 | 
|---|
| 34 |   //!> grant unit test access to private parts
 | 
|---|
| 35 |   friend class HistogramTest;
 | 
|---|
| 36 |   //!> grant output operator access
 | 
|---|
| 37 |   friend std::ostream & operator<<(std::ostream &ost, const Histogram &histogram);
 | 
|---|
| 38 | public:
 | 
|---|
| 39 |   //!> named type for a vector of sample values
 | 
|---|
| 40 |   typedef std::vector<double> samples_t;
 | 
|---|
| 41 |   //!> named type for the start of a bin
 | 
|---|
| 42 |   typedef double BinLowerEnd;
 | 
|---|
| 43 |   //!> named type for the count of a bin, may be fractional
 | 
|---|
| 44 |   typedef double BinWeight;
 | 
|---|
| 45 |   //!> named type for the pair identifying a bin by its lower end and count
 | 
|---|
| 46 |   typedef std::pair< BinLowerEnd, BinWeight> Bin_t;
 | 
|---|
| 47 | private:
 | 
|---|
| 48 |   //!> named type for a vector of bins
 | 
|---|
| 49 |   typedef std::map< BinLowerEnd, BinWeight > Bins_t;
 | 
|---|
| 50 | public:
 | 
|---|
| 51 |   /** Constructor from a given set of sampled data.
 | 
|---|
| 52 |    *
 | 
|---|
| 53 |    * \param samples sampled data to construct histogram from
 | 
|---|
| 54 |    */
 | 
|---|
| 55 |   Histogram(const samples_t &samples);
 | 
|---|
| 56 | 
 | 
|---|
| 57 |   /** Default constructor.
 | 
|---|
| 58 |    *
 | 
|---|
| 59 |    */
 | 
|---|
| 60 |   Histogram() :
 | 
|---|
| 61 |     binwidth(0.5),
 | 
|---|
| 62 |     offset(0.)
 | 
|---|
| 63 |   {}
 | 
|---|
| 64 | 
 | 
|---|
| 65 |   /** Constructor for class Histogram.
 | 
|---|
| 66 |    *
 | 
|---|
| 67 |    * @param offset where the bins should start
 | 
|---|
| 68 |    * @param binwidth width of the bins
 | 
|---|
| 69 |    */
 | 
|---|
| 70 |   Histogram(const BinLowerEnd _offset, const double _binwidth) :
 | 
|---|
| 71 |     binwidth(_binwidth),
 | 
|---|
| 72 |     offset(_offset)
 | 
|---|
| 73 |   {}
 | 
|---|
| 74 | 
 | 
|---|
| 75 |   /** Constructor for class Histogram.
 | 
|---|
| 76 |    *
 | 
|---|
| 77 |    * @param samples samples to put in the histogram.
 | 
|---|
| 78 |    * @param offset where the bins should start
 | 
|---|
| 79 |    * @param binwidth width of the bins
 | 
|---|
| 80 |    */
 | 
|---|
| 81 |   Histogram(const samples_t &samples, const BinLowerEnd _offset, const double _binwidth);
 | 
|---|
| 82 | 
 | 
|---|
| 83 |   /** Adding another histogram onto this one.
 | 
|---|
| 84 |    *
 | 
|---|
| 85 |    * \note The operation is area-conserving, i.e. the new area is the sum of
 | 
|---|
| 86 |    * both areas.
 | 
|---|
| 87 |    *
 | 
|---|
| 88 |    * @param other other histogram
 | 
|---|
| 89 |    * @return ref to this instance
 | 
|---|
| 90 |    */
 | 
|---|
| 91 |   Histogram& operator+=(const Histogram &other);
 | 
|---|
| 92 | 
 | 
|---|
| 93 |   /** Assignment operator.
 | 
|---|
| 94 |    *
 | 
|---|
| 95 |    * @param other other histogram to make ourselves equal to
 | 
|---|
| 96 |    * @return ref to this instance
 | 
|---|
| 97 |    */
 | 
|---|
| 98 |   Histogram& operator=(const Histogram &other);
 | 
|---|
| 99 | 
 | 
|---|
| 100 |   /** Subtracting another histogram from this one.
 | 
|---|
| 101 |    *
 | 
|---|
| 102 |    * \note The operation is area-conserving, i.e. the new area is the
 | 
|---|
| 103 |    * difference of both areas.
 | 
|---|
| 104 |    *
 | 
|---|
| 105 |    * @param other other histogram
 | 
|---|
| 106 |    * @return ref to this instance
 | 
|---|
| 107 |    */
 | 
|---|
| 108 |   Histogram& operator-=(const Histogram &other);
 | 
|---|
| 109 | 
 | 
|---|
| 110 |   /** States whether each bin of this histogram has count of zero.
 | 
|---|
| 111 |    *
 | 
|---|
| 112 |    * @return true - all bins are zero, false - else
 | 
|---|
| 113 |    */
 | 
|---|
| 114 |   bool isEmpty() const;
 | 
|---|
| 115 | 
 | 
|---|
| 116 |   /** Sums all found weights times the Histogram::binwidth.
 | 
|---|
| 117 |    *
 | 
|---|
| 118 |    * @return sum over all weights times width.
 | 
|---|
| 119 |    */
 | 
|---|
| 120 |   double area() const;
 | 
|---|
| 121 | 
 | 
|---|
| 122 |   /** Adds given vector of samples to the histogram.
 | 
|---|
| 123 |    *
 | 
|---|
| 124 |    * @param samples vector of samples to add
 | 
|---|
| 125 |    */
 | 
|---|
| 126 |   void addSamples(const samples_t &samples);
 | 
|---|
| 127 | 
 | 
|---|
| 128 |   /** Equality operator.
 | 
|---|
| 129 |    *
 | 
|---|
| 130 |    * @param other other instance to check against
 | 
|---|
| 131 |    * @return true - both are equal, false - some bins differ
 | 
|---|
| 132 |    */
 | 
|---|
| 133 |   bool operator==(const Histogram& other) const;
 | 
|---|
| 134 | 
 | 
|---|
| 135 |   bool operator!=(const Histogram& other) const
 | 
|---|
| 136 |   {
 | 
|---|
| 137 |     return (!(*this == other));
 | 
|---|
| 138 |   }
 | 
|---|
| 139 | 
 | 
|---|
| 140 | private:
 | 
|---|
| 141 |   /** Returns the iterator to the bin representing the lower end into which the \a value fits.
 | 
|---|
| 142 |    *
 | 
|---|
| 143 |    * @param _value value to fit.
 | 
|---|
| 144 |    * @return iterator to bin or to bins.end() if not matching
 | 
|---|
| 145 |    */
 | 
|---|
| 146 |   Bins_t::iterator getLowerEndBin(const double _value);
 | 
|---|
| 147 | 
 | 
|---|
| 148 |   /** Returns the iterator to the bin representing the upper end into which the \a value fits.
 | 
|---|
| 149 |    *
 | 
|---|
| 150 |    * @param _value value to fit.
 | 
|---|
| 151 |    * @return iterator to bin or to bins.end() if not matching
 | 
|---|
| 152 |    */
 | 
|---|
| 153 |   Bins_t::iterator getHigherEndBin(const double _value);
 | 
|---|
| 154 | 
 | 
|---|
| 155 |   /** Returns the lower end regardless of whether such a bin exists.
 | 
|---|
| 156 |    *
 | 
|---|
| 157 |    * @param _value value to place into a bin
 | 
|---|
| 158 |    * @return start of would-be bin to contain this \a _value
 | 
|---|
| 159 |    */
 | 
|---|
| 160 |   BinLowerEnd getLowerEnd(const double _value) const;
 | 
|---|
| 161 | 
 | 
|---|
| 162 |   /** Helper function that contains all the logic of how to superpose two
 | 
|---|
| 163 |    * histograms.
 | 
|---|
| 164 |    *
 | 
|---|
| 165 |    * Is called by Histogram::operator+=() and Histogram::operator-=()
 | 
|---|
| 166 |    *
 | 
|---|
| 167 |    * @param other other histogram
 | 
|---|
| 168 |    * @param prefactor +1. is then addition, -1. is subtraction.
 | 
|---|
| 169 |    */
 | 
|---|
| 170 |   void superposeOtherHistogram(const Histogram &other, const double prefactor);
 | 
|---|
| 171 | 
 | 
|---|
| 172 |   /** Helper function to add missing bins in superposition operation.
 | 
|---|
| 173 |    *
 | 
|---|
| 174 |    *  We add here enough bins, initialized to weight zero such that the bin
 | 
|---|
| 175 |    *  of [LowerEnd, NextLowerEnd) fully fits. Does nothing if the bins are
 | 
|---|
| 176 |    *  already present.
 | 
|---|
| 177 |    *
 | 
|---|
| 178 |    * @param LowerEnd lowerend of the other bin (to superpose)
 | 
|---|
| 179 |    * @param NextLowerEnd lower end of bin (to superpose) next adjacent to other
 | 
|---|
| 180 |    */
 | 
|---|
| 181 |   void extendMissingBins(const BinLowerEnd LowerEnd, const BinLowerEnd NextLowerEnd);
 | 
|---|
| 182 | 
 | 
|---|
| 183 |   /** Helper function to print BinLowerEnd and BinWeight to a string for every bin.
 | 
|---|
| 184 |    *
 | 
|---|
| 185 |    * @return string containing information on each consecutive bin
 | 
|---|
| 186 |    */
 | 
|---|
| 187 |   std::string printBins() const;
 | 
|---|
| 188 | 
 | 
|---|
| 189 |   //!> pair for min and max of given samples
 | 
|---|
| 190 |   typedef std::pair<samples_t::const_iterator, samples_t::const_iterator> MinMax_t;
 | 
|---|
| 191 | 
 | 
|---|
| 192 |   /** Helper function that returns minimum and maximum in given \a samples
 | 
|---|
| 193 |    *
 | 
|---|
| 194 |    * @param samples sampled values
 | 
|---|
| 195 |    * @return pair of min and max value
 | 
|---|
| 196 |    */
 | 
|---|
| 197 |   MinMax_t getMinMaxFromSamples(const samples_t &samples) const;
 | 
|---|
| 198 | 
 | 
|---|
| 199 | private:
 | 
|---|
| 200 |   //!> vector of bins containing the histogram
 | 
|---|
| 201 |   Bins_t bins;
 | 
|---|
| 202 |   //!> width of bin
 | 
|---|
| 203 |   const double binwidth;
 | 
|---|
| 204 |   //!> offset for the start of the bins
 | 
|---|
| 205 |   const BinLowerEnd offset;
 | 
|---|
| 206 | };
 | 
|---|
| 207 | 
 | 
|---|
| 208 | /** Function to print an arbitrary pair to ostream.
 | 
|---|
| 209 |  *
 | 
|---|
| 210 |  * @param ost output stream
 | 
|---|
| 211 |  * @param elem element to print
 | 
|---|
| 212 |  * @return ref to given ostream for concatenation
 | 
|---|
| 213 |  */
 | 
|---|
| 214 | std::ostream & operator<<(std::ostream &ost, const Histogram::Bin_t &elem);
 | 
|---|
| 215 | 
 | 
|---|
| 216 | /** Function to print histogram to ostream.
 | 
|---|
| 217 |  *
 | 
|---|
| 218 |  * @param ost output stream
 | 
|---|
| 219 |  * @param histogram histogram to print
 | 
|---|
| 220 |  * @return ref to given ostream for concatenation
 | 
|---|
| 221 |  */
 | 
|---|
| 222 | std::ostream & operator<<(std::ostream &ost, const Histogram &histogram);
 | 
|---|
| 223 | 
 | 
|---|
| 224 | template<typename T> T ZeroInstance();
 | 
|---|
| 225 | template<> Histogram ZeroInstance<Histogram>();
 | 
|---|
| 226 | 
 | 
|---|
| 227 | 
 | 
|---|
| 228 | #endif /* HISTOGRAM_HPP_ */
 | 
|---|