/* * Histogram.hpp * * Created on: Jul 26, 2012 * Author: heber */ #ifndef HISTOGRAM_HPP_ #define HISTOGRAM_HPP_ // include config.h #ifdef HAVE_CONFIG_H #include #endif #include #include #include class HistogramTest; /** This class generates a histogram from a given vector of sampled values. * * Most importantly, it also contains operator+=() and operator-=() to perform * sum on the \b histograms. * * This is to be used with the OrthogonalSummation which requires these specific * operator implementations. * */ class Histogram { //!> grant unit test access to private parts friend class HistogramTest; //!> grant output operator access friend std::ostream & operator<<(std::ostream &ost, const Histogram &histogram); public: //!> named type for a vector of sample values typedef std::vector samples_t; //!> named type for the start of a bin typedef double BinLowerEnd; //!> named type for the count of a bin, may be fractional typedef double BinWeight; //!> named type for the pair identifying a bin by its lower end and count typedef std::pair< BinLowerEnd, BinWeight> Bin_t; private: //!> named type for a vector of bins typedef std::map< BinLowerEnd, BinWeight > Bins_t; public: /** Cpnstructor from a given set of sampled data. * * \param samples sampled data to construct histogram from */ Histogram(const samples_t &samples); /** Default constructor. * */ Histogram() : binwidth(0.5), offset(0.) {} /** Constructor for class Histogram. * * @param offset where the bins should start * @param binwidth width of the bins */ Histogram(const BinLowerEnd _offset, const double _binwidth) : binwidth(_binwidth), offset(_offset) {} /** Constructor for class Histogram. * * @param samples samples to put in the histogram. * @param offset where the bins should start * @param binwidth width of the bins */ Histogram(const samples_t &samples, const BinLowerEnd _offset, const double _binwidth); /** Adding another histogram onto this one. * * \note The operation is area-conserving, i.e. the new area is the sum of * both areas. * * @param other other histogram * @return ref to this instance */ Histogram& operator+=(const Histogram &other); /** Assignment operator. * * @param other other histogram to make ourselves equal to * @return ref to this instance */ Histogram& operator=(const Histogram &other); /** Subtracting another histogram from this one. * * \note The operation is area-conserving, i.e. the new area is the * difference of both areas. * * @param other other histogram * @return ref to this instance */ Histogram& operator-=(const Histogram &other); /** States whether each bin of this histogram has count of zero. * * @return true - all bins are zero, false - else */ bool isEmpty() const; /** Sums all found weights times the Histogram::binwidth. * * @return sum over all weights times width. */ double area() const; /** Adds given vector of samples to the histogram. * * @param samples vector of samples to add */ void addSamples(const samples_t &samples); private: /** Returns the iterator to the bin representing the lower end into which the \a value fits. * * @param _value value to fit. * @return iterator to bin or to bins.end() if not matching */ Bins_t::iterator getLowerEndBin(const double _value); /** Returns the iterator to the bin representing the upper end into which the \a value fits. * * @param _value value to fit. * @return iterator to bin or to bins.end() if not matching */ Bins_t::iterator getHigherEndBin(const double _value); /** Returns the lower end regardless of whether such a bin exists. * * @param _value value to place into a bin * @return start of would-be bin to contain this \a _value */ BinLowerEnd getLowerEnd(const double _value) const; /** Helper function that contains all the logic of how to superpose two * histograms. * * Is called by Histogram::operator+=() and Histogram::operator-=() * * @param other other histogram * @param prefactor +1. is then addition, -1. is subtraction. */ void superposeOtherHistogram(const Histogram &other, const double prefactor); /** Helper function to add missing bins in superposition operation. * * We add here enough bins, initialized to weight zero such that the bin * of [LowerEnd, NextLowerEnd) fully fits. Does nothing if the bins are * already present. * * @param LowerEnd lowerend of the other bin (to superpose) * @param NextLowerEnd lower end of bin (to superpose) next adjacent to other */ void extendMissingBins(const BinLowerEnd LowerEnd, const BinLowerEnd NextLowerEnd); /** Helper function to print BinLowerEnd and BinWeight to a string for every bin. * * @return string containing information on each consecutive bin */ std::string printBins() const; //!> pair for min and max of given samples typedef std::pair MinMax_t; /** Helper function that returns minimum and maximum in given \a samples * * @param samples sampled values * @return pair of min and max value */ MinMax_t getMinMaxFromSamples(const samples_t &samples) const; private: //!> vector of bins containing the histogram Bins_t bins; //!> width of bin const double binwidth; //!> offset for the start of the bins const BinLowerEnd offset; }; /** Function to print an arbitrary pair to ostream. * * @param ost output stream * @param elem element to print * @return ref to given ostream for concatenation */ std::ostream & operator<<(std::ostream &ost, const Histogram::Bin_t &elem); /** Function to print histogram to ostream. * * @param ost output stream * @param histogram histogram to print * @return ref to given ostream for concatenation */ std::ostream & operator<<(std::ostream &ost, const Histogram &histogram); #endif /* HISTOGRAM_HPP_ */