#ifndef HEPHIST1D_H
#define HEPHIST1D_H

// ----------------------------------------------------------------------
//
// HepHist1D.h - class declaration for generic one-dimensional histogram
//
// HepHist1D is a generic one-dimensional histogram. It is derived from
// HepHist, and its final implementation is defined by a manager class/
// histogram subclass. HepHist1D provides methods for filling a
// histogram and retreiving information from and about it.
//
// HepHist1D objects are not directly instantiated. Instead, the manager
// creates the object using its own implementation of the histogram.
//
// Typical usage:
//
//   HepFileManager* m = new [define the manager];
//    :
//    :
//   HepHist1D* h(m->hist1D("Histogram Title", 100, 0.0, 23.0));
//   float x, weight;
//    :
//   [gather data]
//    :
//   h->accumulate(x, weight);
//
//
// Note that the constructor can take an ID number which is used by
// some implementations of HepHist1D. If omitted, the ID number is
// generated automatically (which is recommended). The ID number is
// available through the id() method.
//
//
// History:
//   ??-???-19??  Bob Jacobsen   Initial draft, based on ideas in HepTuple
//     and the SLT histogram classes of Joe Boudreau
//   05-May-1997  Walter Brown   Initial design & draft of Hist class
//   22-May-1997  Walter Brown   Merged Hist into HepHistogram
//   30-May-1997  Walter Brown   Added cloning functions
//   29-May-1997  Jason Luther   Added comments
//   04-Jun-1997  Jason Luther   Changed comments at beginning of file
//   30-Jul-1998  Philippe Canal Added typeId
//   04-Aug-1998  Philippe Canal Added weight, entries, sum, etc..
//
// ----------------------------------------------------------------------


#ifdef HEP_SHORT_NAMES      // done early to override HepPlot
  #define Hist1D HepHist1D
#endif


#ifndef HEPHIST_H
  #include "HepTuple/HepHist.h"
#endif


ZM_BEGIN_NAMESPACE( zmht )	/*  namespace zmht  {  */


class HepFileManager;
class HepRawHist;


class HepHist1D : public HepHist  {

protected:

  // create a 1D histogram with the given title and binning
  HepHist1D(
    HepFileManager * manager
  , const std::string& title
  , const int nBins, const float low, const float high
  , const int id_req = 0
  );

  // Used for dummy construction ...
  // the object is then not valid ...
  HepHist1D( );                           // default constructor

public:
  
  // type identifier ( is equal to type() for this object )
  static const char typeId;

  virtual ~HepHist1D();

  virtual ZM_COVARIANT_TYPE(HepObj,HepHist1D) & makeClone(
    const std::string& title
  , const int  id = 0
  ) const;

  virtual ZM_COVARIANT_TYPE(HepObj,HepHist1D) & makeEmpty(
    const std::string& title
  , const int  id = 0
  ) const;

  virtual ZM_COVARIANT_TYPE(HepObj,HepHist1D) & makeClone(
    HepFileManager *manager
  , const std::string& title
  , const int  id = 0
  ) const;

  virtual ZM_COVARIANT_TYPE(HepObj,HepHist1D) & makeEmpty(
    HepFileManager *manager
  , const std::string& title
  , const int  id = 0
  ) const;

  virtual void accumulate(
    const float x
  , const float weight = 1.0
  );

  virtual void reset();

  virtual float bin(		 // retrieve contents of specified bin
    const int binNum
  ) const;

  virtual void getContents(	 // get contents of all in-range bins
    float * values
  ) const;

  virtual void putContents(	 // put contents of all in-range bins
    float * values
  ) const;

  virtual void getErrors(	 // get errors of all in-range bins
    float * errors
  ) const;

  virtual void putErrors(	 // put errors of all in-range bins
    float * errors
  ) const;

  virtual float binError(	 // retrieve error on specified bin
    const int binNum
  ) const;

  virtual int nBins() const;     // retrieve # of in-range bins

  virtual float min() const;     // retrieve low end of binned range
  virtual float max() const;     // retrieve high end of binned range

  virtual int   entries() const; // number of entries

  virtual float weight() const;  // sum of all weight
  virtual float weight2() const; // sum of all weight^2

  virtual float sum() const;     // retrieve weighted sum of X
  virtual float sum2() const;    // retrieve weighted sum of square (X^2)

  virtual void getStatistics( int & numEntries, float & sumW, float & sumW2,
                              double & sumWX, double & sumWX2 ) const;

  virtual void getOverflows( float * numOver, float * numUnder ) const;

  bool compatibleHist1D( const HepHist1D & h );

  virtual HepRawHist importHist1D( const HepHist1D & h );

  virtual void setXTitle( const std::string& label );
  virtual void setYTitle( const std::string& label );
  virtual void setZTitle( const std::string& label );
  virtual void setTitle ( const std::string& label );

  virtual void      addHist1D( const HepRawHist & h );
  virtual void multiplyHist1D( const HepRawHist & h );
  virtual void subtractHist1D( const HepRawHist & h );
  virtual void   divideHist1D( const HepRawHist & h );

  virtual void removeImportedHist1D( const HepRawHist & h );

  // The Sample Average of X can be obtained by: sum() / weight() 
  // A biased estimator (Sample variance) of the X's variance can be
  // obtained by:
  //        (sum2() - sumX()^2) / weight()

  float mean() const {      // retrieve the sample average
    float w = weight();
    return ( w!=0 ? ( sum()/w ) : 0 );
  };

  float variance() const {  // retrieve the sample variance
    float w = weight(); 
    if (w==0) return 0;
    float m = sum()/w;
    return (sum2()/w-m*m);
  };

  // Arithmetic operations on histograms
  HepHist1D & operator += ( const HepHist1D & );
  HepHist1D & operator -= ( const HepHist1D & );
  HepHist1D & operator *= ( const HepHist1D & );
  HepHist1D & operator /= ( const HepHist1D & );


protected:

  virtual void _accumulate(
    const float x
  , const float weight = 1.0
  );


private:

  const int   _nBins;                     // # of in-range bins
  const float _min;                       // lowest in-range value
  const float _max;                       // highest in-range value

  // forbidden operations, hence private
  HepHist1D( const HepHist1D & );         // copy constructor
  HepHist1D & operator=( const HepHist1D & );  // assignment

};  // HepHist1D


ZM_END_NAMESPACE( zmht )	/*  }  // namespace zmht  */

#endif  // HEPHIST1D_H
