c@241: /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ c@241: c@241: // Histogram.h: interface for the THistogram class. c@241: // c@241: ////////////////////////////////////////////////////////////////////// c@241: c@241: c@241: #ifndef HISTOGRAM_H c@241: #define HISTOGRAM_H c@241: c@241: c@241: #include c@241: c@241: /*! \brief A histogram class c@241: c@241: This class computes the histogram of a vector. c@241: c@241: \par Template parameters c@241: c@241: - T type of input data (can be any: float, double, int, UINT, etc...) c@241: - TOut type of output data: float or double. (default is double) c@241: c@241: \par Moments: c@241: c@241: The moments (average, standard deviation, skewness, etc.) are computed using c@241: the algorithm of the Numerical recipies (see Numerical recipies in C, Chapter 14.1, pg 613). c@241: c@241: \par Example: c@241: c@241: This example shows the typical use of the class: c@241: \code c@241: // a vector containing the data c@241: vector data; c@241: // Creating histogram using float data and with 101 containers, c@241: THistogram histo(101); c@241: // computing the histogram c@241: histo.compute(data); c@241: \endcode c@241: c@241: Once this is done, you can get a vector with the histogram or the normalized histogram (such that it's area is 1): c@241: \code c@241: // getting normalized histogram c@241: vector v=histo.getNormalizedHistogram(); c@241: \endcode c@241: c@241: \par Reference c@241: c@241: Equally spaced acsissa function integration (used in #GetArea): Numerical Recipies in C, Chapter 4.1, pg 130. c@241: c@241: \author Jonathan de Halleux, dehalleux@auto.ucl.ac.be, 2002 c@241: */ c@241: c@241: template c@241: class THistogram c@241: { c@241: public: c@241: //! \name Constructors c@241: //@{ c@241: /*! Default constructor c@241: \param counters the number of histogram containers (default value is 10) c@241: */ c@241: THistogram(unsigned int counters = 10); c@241: virtual ~THistogram() { clear();}; c@241: //@} c@241: c@241: //! \name Histogram computation, update c@241: //@{ c@241: /*! Computes histogram of vector v c@241: \param v vector to compute histogram c@241: \param computeMinMax set to true if min/max of v have to be used to get the histogram limits c@241: c@241: This function computes the histogram of v and stores it internally. c@241: \sa Update, GeTHistogram c@241: */ c@241: void compute( const std::vector& v, bool computeMinMax = true); c@241: //! Update histogram with the vector v c@241: void update( const std::vector& v); c@241: //! Update histogram with t c@241: void update( const T& t); c@241: //@} c@241: c@241: //! \name Resetting functions c@241: //@{ c@241: //! Resize the histogram. Warning this function clear the histogram. c@241: void resize( unsigned int counters ); c@241: //! Clears the histogram c@241: void clear() { m_counters.clear();}; c@241: //@} c@241: c@241: //! \name Setters c@241: //@{ c@241: /*! This function sets the minimum of the histogram spectrum. c@241: The spectrum is not recomputed, use it with care c@241: */ c@241: void setMinSpectrum( const T& min ) { m_min = min; computeStep();}; c@241: /*! This function sets the minimum of the histogram spectrum. c@241: The spectrum is not recomputed, use it with care c@241: */ c@241: void setMaxSpectrum( const T& max ) { m_max = max; computeStep();}; c@241: //@} c@241: //! \name Getters c@241: //@{ c@241: //! return minimum of histogram spectrum c@241: const T& getMinSpectrum() const { return m_min;}; c@241: //! return maximum of histogram spectrum c@241: const T& getMaxSpectrum() const { return m_max;}; c@241: //! return step size of histogram containers c@241: TOut getStep() const { return m_step;}; c@241: //! return number of points in histogram c@241: unsigned int getSum() const; c@241: /*! \brief returns area under the histogram c@241: c@241: The Simpson rule is used to integrate the histogram. c@241: */ c@241: TOut getArea() const; c@241: c@241: /*! \brief Computes the moments of the histogram c@241: c@241: \param data dataset c@241: \param ave mean c@241: \f[ \bar x = \frac{1}{N} \sum_{j=1}^N x_j\f] c@241: \param adev mean absolute deviation c@241: \f[ adev(X) = \frac{1}{N} \sum_{j=1}^N | x_j - \bar x |\f] c@241: \param var average deviation: c@241: \f[ \mbox{Var}(X) = \frac{1}{N-1} \sum_{j=1}^N (x_j - \bar x)^2\f] c@241: \param sdev standard deviation: c@241: \f[ \sigma(X) = \sqrt{var(\bar x) }\f] c@241: \param skew skewness c@241: \f[ \mbox{Skew}(X) = \frac{1}{N}\sum_{j=1}^N \left[ \frac{x_j - \bar x}{\sigma}\right]^3\f] c@241: \param kurt kurtosis c@241: \f[ \mbox{Kurt}(X) = \left\{ \frac{1}{N}\sum_{j=1}^N \left[ \frac{x_j - \bar x}{\sigma}\right]^4 \right\} - 3\f] c@241: c@241: */ c@241: static void getMoments(const std::vector& data, TOut& ave, TOut& adev, TOut& sdev, TOut& var, TOut& skew, TOut& kurt); c@241: c@241: //! return number of containers c@241: unsigned int getSize() const { return m_counters.size();}; c@241: //! returns i-th counter c@241: unsigned int operator [] (unsigned int i) const { c@241: // ASSERT( i < m_counters.size() ); c@241: return m_counters[i]; c@241: }; c@241: //! return the computed histogram c@241: const std::vector& geTHistogram() const { return m_counters;}; c@241: //! return the computed histogram, in TOuts c@241: std::vector geTHistogramD() const; c@241: /*! return the normalized computed histogram c@241: c@241: \return the histogram such that the area is equal to 1 c@241: */ c@241: std::vector getNormalizedHistogram() const; c@241: //! returns left containers position c@241: std::vector getLeftContainers() const; c@241: //! returns center containers position c@241: std::vector getCenterContainers() const; c@241: //@} c@241: protected: c@241: //! Computes the step c@241: void computeStep() { m_step = (TOut)(((TOut)(m_max-m_min)) / (m_counters.size()-1));}; c@241: //! Data accumulators c@241: std::vector m_counters; c@241: //! minimum of dataset c@241: T m_min; c@241: //! maximum of dataset c@241: T m_max; c@241: //! width of container c@241: TOut m_step; c@241: }; c@241: c@241: template c@241: THistogram::THistogram(unsigned int counters) c@241: : m_counters(counters,0), m_min(0), m_max(0), m_step(0) c@241: { c@241: c@241: } c@241: c@241: template c@241: void THistogram::resize( unsigned int counters ) c@241: { c@241: clear(); c@241: c@241: m_counters.resize(counters,0); c@241: c@241: computeStep(); c@241: } c@241: c@241: template c@241: void THistogram::compute( const std::vector& v, bool computeMinMax) c@241: { c@241: using namespace std; c@241: unsigned int i; c@241: int index; c@241: c@241: if (m_counters.empty()) c@241: return; c@241: c@241: if (computeMinMax) c@241: { c@241: m_max = m_min = v[0]; c@241: for (i=1;i= m_counters.size() || index < 0) c@241: return; c@241: c@241: m_counters[index]++; c@241: } c@241: } c@241: c@241: template c@241: void THistogram::update( const std::vector& v) c@241: { c@241: if (m_counters.empty()) c@241: return; c@241: c@241: computeStep(); c@241: c@241: TOut size = m_counters.size(); c@241: c@241: int index; c@241: for (unsigned int i = 0;i < size ; i++) c@241: { c@241: index = (int)floor(((TOut)(v[i]-m_min))/m_step); c@241: c@241: if (index >= m_counters.size() || index < 0) c@241: return; c@241: c@241: m_counters[index]++; c@241: } c@241: } c@241: c@241: template c@241: void THistogram::update( const T& t) c@241: { c@241: int index=(int) floor( ((TOut)(t-m_min))/m_step ) ; c@241: c@241: if (index >= m_counters.size() || index < 0) c@241: return; c@241: c@241: m_counters[index]++; c@241: }; c@241: c@241: template c@241: std::vector THistogram::geTHistogramD() const c@241: { c@241: std::vector v(m_counters.size()); c@241: for (unsigned int i = 0;i c@241: std::vector THistogram::getLeftContainers() const c@241: { c@241: std::vector x( m_counters.size()); c@241: c@241: for (unsigned int i = 0;i c@241: std::vector THistogram::getCenterContainers() const c@241: { c@241: std::vector x( m_counters.size()); c@241: c@241: for (unsigned int i = 0;i c@241: unsigned int THistogram::getSum() const c@241: { c@241: unsigned int sum = 0; c@241: for (unsigned int i = 0;i c@241: TOut THistogram::getArea() const c@241: { c@241: const size_t n=m_counters.size(); c@241: TOut area=0; c@241: c@241: if (n>6) c@241: { c@241: area=3.0/8.0*(m_counters[0]+m_counters[n-1]) c@241: +7.0/6.0*(m_counters[1]+m_counters[n-2]) c@241: +23.0/24.0*(m_counters[2]+m_counters[n-3]); c@241: for (unsigned int i=3;i4) c@241: { c@241: area=5.0/12.0*(m_counters[0]+m_counters[n-1]) c@241: +13.0/12.0*(m_counters[1]+m_counters[n-2]); c@241: for (unsigned int i=2;i1) c@241: { c@241: area=1/2.0*(m_counters[0]+m_counters[n-1]); c@241: for (unsigned int i=1;i c@241: std::vector THistogram::getNormalizedHistogram() const c@241: { c@241: std::vector normCounters( m_counters.size()); c@241: TOut area = (TOut)getArea(); c@241: c@241: for (unsigned int i = 0;i c@241: void THistogram::getMoments(const std::vector& data, TOut& ave, TOut& adev, TOut& sdev, TOut& var, TOut& skew, TOut& kurt) c@241: { c@241: int j; c@241: double ep=0.0,s,p; c@241: const size_t n = data.size(); c@241: c@241: if (n <= 1) c@241: // nrerror("n must be at least 2 in moment"); c@241: return; c@241: c@241: s=0.0; // First pass to get the mean. c@241: for (j=0;j