// This may look like C code, but it is really -*- C++ -*-
//
// $Id: histos.h,v 1.1.1.1 1999-11-26 16:37:10 ansari Exp $
//

#ifndef HISTOS_SEEN
#define HISTOS_SEEN

#include "objfio.h"
#include <iostream.h>
#include <stdio.h>
#include "peida.h"
#include "tvector.h"
#include "ppersist.h"
#include "anydataobj.h"

namespace SOPHYA {

class GeneralFit;

class Histo : public AnyDataObj {
  friend class ObjFileIO<Histo>;
public:

  // CREATOR / DESTRUCTOR
  Histo();
  Histo(float xMin, float xMax, int nBin=100);
  Histo(const Histo& H);
  virtual        ~Histo();

  // OPTIONS
  void   Errors();

  // UPDATING or SETTING
  void   Zero();
  void   Add(float x, float w = 1.);
  void   AddBin(int numBin, float w = 1.);
  void   SetBin(float x, float w = 1.);
  void   SetBin(int numBin, float w = 1.);
  void   SetErr2(float x, double e2);
  void   SetErr2(int numBin, double e2);
  void   SetErr(float x, float e);
  void   SetErr(int numBin, float e);

  // Operators
  Histo& operator = (const Histo& h);
  Histo& operator *= (double b);
  Histo& operator /= (double b);
  Histo& operator += (double b);
  Histo& operator -= (double b);
  friend Histo operator * (const Histo& a, double b);
  friend Histo operator * (double b, const Histo& a);
  friend Histo operator / (const Histo& a, double b);
  friend Histo operator + (const Histo& a, double b);
  friend Histo operator + (double b, const Histo& a);
  friend Histo operator - (const Histo& a, double b);
  friend Histo operator - (double b, const Histo& a);
  Histo& operator += (const Histo& a);
  Histo& operator -= (const Histo& a);
  Histo& operator *= (const Histo& a);
  Histo& operator /= (const Histo& a);
  friend Histo operator + (const Histo& a, const Histo& b);
  friend Histo operator - (const Histo& a, const Histo& b);
  friend Histo operator * (const Histo& a, const Histo& b);
  friend Histo operator / (const Histo& a, const Histo& b);

  // get/put dans/depuis un vector
  void GetAbsc(Vector& v);
  void GetValue(Vector& v);
  void GetError2(Vector& v);
  void GetError(Vector& v);
  void PutValue(Vector& v, int ierr=0);
  void PutValueAdd(Vector &v, int ierr=0);
  void PutError2(Vector& v);
  void PutError2Add(Vector& v);
  void PutError(Vector& v);

  // INLINES
  inline float          XMin() const             {return min;}
  inline float          XMax() const             {return max;}
  inline int_4          NBins() const            {return bins;}
  inline float          BinWidth() const         {return binWidth;}
  inline float*         Bins() const             {return data;}
  inline float          operator()(int i) const  {return data[i];}
  inline float&         operator()(int i)        {return data[i];}
  inline bool           HasErrors() { if(err2) return true; else return false;}
  inline float          Error(int i) const
                          {if(err2) {if(err2[i]>0.) return sqrt(err2[i]); else return 0.;}
                           else return 0.;}
  inline double         Error2(int i) const
                          {if(err2) return err2[i]; else return 0.;}
  inline double&        Error2(int i) {return err2[i];}
  inline float          NData() const            {return (float) nHist;}
  inline float          NEntries() const         {return nEntries;}
  inline float          NOver() const            {return over;}
  inline float          NUnder() const           {return under;}

  inline float          BinLowEdge(int i)  const {return min + i*binWidth;}
  inline float          BinCenter(int i)   const {return min + (i+0.5)*binWidth;}
  inline float          BinHighEdge(int i) const {return min + (i+1)*binWidth;} 
  inline int_4          FindBin(float x) const   
                            {return (int_4) floorf((x - min) / binWidth);}

  // Info, statistique et calculs sur les histogrammes
  int            BinNonNul() const;
  int            ErrNonNul() const;
  int            IMax() const;
  int            IMin() const;
  float          VMax() const;
  float          VMin() const;
  float          Mean() const;
  float          Sigma() const;
  float          MeanLH(int il,int ih) const;
  float          SigmaLH(int il,int ih) const;
  float          Mean(float x0, float dx) const;
  float          Sigma(float x0, float dx) const;
  float          CleanedMean() const;
  float          CleanedMean(float& sigma) const;
  int            BinPercent(float per) const;
  int            BinPercent(float x,float per,int& imin,int& imax);
  int            BinPercent(float x,float per,float& xmin,float& xmax);
  void           HInteg(float norm = 0.);
  void           HDeriv();
  void           HRebin(int nbinew);

  int            MaxiLocal(float& maxi,int& imax,float& maxn,int& imaxn);
  float          FitMax(int degree=2, float frac=0.5f, int debug=0) const;
  float          FindWidth(float xmax,float frac=0.5f, int debug=0) const;
  float          FindWidth(float frac=0.5f, int debug=0) const;
  int            EstimeMax(float& xm,int SzPav = 3);
  int            EstimeMax(int& im,float& xm,int SzPav = 3);
  void           EstimeWidthS(float frac,float& widthG,float& widthD);

  // Fit
  int    Fit(GeneralFit& gfit,unsigned short typ_err=0);
  Histo  FitResidus(GeneralFit& gfit);
  Histo  FitFunction(GeneralFit& gfit);

  // Print et Display ASCII
  void           PrintF(FILE * fp, int dyn = 100, float hmin = 1., float hmax = -1.,
			int pflag = 0, int il = 1, int ih = -1);
  void           Print(int dyn = 100, float hmin = 1., float hmax = -1.,
			int pflag = 0, int il = 1, int ih = -1);

protected:
  void Delete();

  float*         data;		 
  double*        err2;		 
  float          under;
  float          over;
  double         nHist;
  int_4          nEntries;
  int_4          bins;
  float          min;
  float          max;
  float          binWidth;
};


inline POutPersist& operator << (POutPersist& os, Histo & obj)
{ ObjFileIO<Histo> fio(&obj);  fio.Write(os);  return(os); }
inline PInPersist& operator >> (PInPersist& is, Histo & obj)
{ ObjFileIO<Histo> fio(&obj);  fio.Read(is);  return(is); }

// Classe pour la gestion de persistance
// ObjFileIO<Histo>


} // Fin du namespace

#endif // HISTOS_SEEN
