#ifndef HEPHIST2D_H
#define HEPHIST2D_H


// ----------------------------------------------------------------------
//
// HepHist2D.h - class declaration for generic two-dimensional histogram
//
// HepHist2D is a generic two-dimensional histogram. It is derived from
// HepHist, and its final implementation is defined by a manager class/
// histogram subclass. HepHist2D provides methods for filling a
// histogram and retreiving information from and about it.
//
// HepHist2D 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];
//    :
//    :
//   HepHist2D* h(m->hist2D("Title", 100, 0.0, 2.0, 100, 0.0, 2.0));
//   float x, y, weight;
//    :
//   [gather data]
//    :
//   h->accumulate(x, y, weight);
//
//
// Note that the constructor can take an ID number which is used by
// some implementations of HepHist2D. 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   Corrected comments at head 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 Hist2D HepHist2D
#endif


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


ZM_BEGIN_NAMESPACE( zmht )	/*  namespace zmht  {  */


class HepFileManager;
class HepRawHist;


class HepHist2D : public HepHist  {

protected:

  // create a 2D histogram with the given title and binning
  HepHist2D(
    HepFileManager * manager
  , const std::string& title
  , const int nBinsX, const float lowX, const float highX
  , const int nBinsY, const float lowY, const float highY
  , const int id_req = 0
  );

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

public:

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

  virtual ~HepHist2D();

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

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

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

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

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

  virtual void reset();

  virtual float bin(
    const int binNumX
  , const int binNumY
  ) const;

  virtual int nBinsX() const; // retrieve # of in-range X bins
  virtual int nBinsY() const; // retrieve # of in-range Y bins

  virtual float minX() const; // retrieve low end of binned X range
  virtual float minY() const; // retrieve high end of binned X range

  virtual float maxX() const; // retrieve low end of binned X range
  virtual float maxY() const; // retrieve high end of binned X range

  virtual int   entries() const; // Number of entries in all bins

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

  virtual float sumX() const;		// Retrieve weighted sum of X
  virtual float sumY() const;		// Retrieve weighted sum of Y 
  virtual float sumX2() const;		// Retrieve weighted sum of X^2
  virtual float sumXY() const;		// Retrieve weighted sum of X*Y
  virtual float sumY2() const;		// Retrieve weighted sum of Y^2

  // The Sample Average of X can be obtained by: sumX() / weight() 
  // A biased estimator (Sample covariance) of the X,Y covariance can be
  // obtained by:
  //        sumXY()/weight() - sumX()/weight()*sumY()/weight() 
  // A biased estimator (Sample variance) of X can be obtained by:
  //        sumX2()/weight() - sumX()/weight()*sumX()/weight()

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

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

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

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

  virtual float binError(	 // retrieve error on specified bin
    int binNumX
 ,  int binNumY
  ) const;

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

  virtual void getOverflows( float * numXOverYOver,   float * numXOverYUnder,
                             float * numXUnderYUnder, float * numXUnderYOver,
                             float * numTop,          float * numRight,
                             float * numBottom,       float * numLeft ) const;

  bool compatibleHist2D( const HepHist2D & h );

  virtual HepRawHist importHist2D( const HepHist2D & 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      addHist2D( const HepRawHist & h );
  virtual void multiplyHist2D( const HepRawHist & h );
  virtual void subtractHist2D( const HepRawHist & h );
  virtual void   divideHist2D( const HepRawHist & h );

  virtual void removeImportedHist2D( const HepRawHist & h );


  // Arithmetic operation += on histograms
  HepHist2D & operator += ( const HepHist2D & );

  // Arithmetic operation -= on histograms
  HepHist2D & operator -= ( const HepHist2D & );

  // Arithmetic operation *= on histograms
  HepHist2D & operator *= ( const HepHist2D & );

  // Arithmetic operation /= on histograms
  HepHist2D & operator /= ( const HepHist2D & );

protected:

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


private:

  const int   _nBinsX;                    // # of in-range bins
  const float _minX;                      // lowest in-range value
  const float _maxX;                      // highest in-range value

  const int   _nBinsY;                    // # of in-range bins
  const float _minY;                      // lowest in-range value
  const float _maxY;                      // highest in-range value

  // forbidden operations, hence private (protected for sake of descendents):
  HepHist2D( const HepHist2D & );         // copy constructor
  HepHist2D & operator=( const HepHist2D & );  // assignment

};  // HepHist2D


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


#endif  // HEPHIST2D_H
