#ifndef MARS_MHCalibrationPixel
#define MARS_MHCalibrationPixel

#ifndef ROOT_TH1
#include "TH1.h"
#endif

#ifndef ROOT_TH1
#include "TH1F.h"
#endif

#ifndef MARS_MH
#include "MH.h"
#endif

#ifndef ROOT_TF1
#include "TF1.h"
#endif

#ifndef ROOT_TProfile
#include "TProfile.h"
#endif

#ifndef ROOT_TArrayF
#include "TArrayF.h"
#endif

class TPaveText;
class TMath;
class MParList;

class MHCalibrationPixel : public MH
{

private:

  Int_t fPixId;                  // Pixel Nr
  Int_t fTotalEntries;           // Number of entries

  TArrayF *fHiGains;
  TArrayF *fLoGains;

protected:

  TH1F* fHChargeHiGain;          // Summed FADC slices High Gain
  TH1I* fHTimeHiGain;            // Mean arrival time in number of FADC sice
  TH1I* fHChargevsNHiGain;       // Summed Charge vs. Event Nr. 
  
  TH1F* fHChargeLoGain;          // Summed FADC slices Low Gain
  TH1I* fHTimeLoGain;            // Mean arrival time in number of FADC sice
  TH1I* fHChargevsNLoGain;       // Summed Charge vs. Event Nr. 

  TF1* fChargeGausFit;
  TF1* fTimeGausFit;
  
  TProfile* fHivsLoGain;

  TPaveText *fFitLegend;  
  
  Axis_t  fLowerFitRange;
  Axis_t  fChargeFirstHiGain;
  Axis_t  fChargeLastHiGain;
  Int_t   fChargeNbinsHiGain;

  Axis_t  fChargeFirstLoGain;
  Axis_t  fChargeLastLoGain;
  Int_t   fChargeNbinsLoGain;

  Double_t fChargeChisquare;
  Double_t fChargeProb;
  Int_t    fChargeNdf;

  Double_t fChargeMean;
  Double_t fChargeMeanErr;
  Double_t fChargeSigma;
  Double_t fChargeSigmaErr;
  
  Double_t fTimeChisquare;
  Double_t fTimeProb;
  Int_t    fTimeNdf;

  Double_t fTimeMean;
  Double_t fTimeSigma;

  Byte_t   fTimeLowerFitRangeHiGain;
  Byte_t   fTimeUpperFitRangeHiGain;
  Byte_t   fTimeLowerFitRangeLoGain;
  Byte_t   fTimeUpperFitRangeLoGain;
  
  Bool_t fUseLoGain;
  Bool_t fFitOK;

  Double_t fOffset;
  Double_t fSlope;
  
  virtual void DrawLegend();
  
public:

  MHCalibrationPixel(const char *name=NULL, const char *title=NULL);
  ~MHCalibrationPixel();

  void ChangeHistId(Int_t i);
  
  Bool_t SetupFill(const MParList *pList);
  Bool_t Fill(const MParContainer *, const Stat_t w=1) { return kTRUE; }

  void   SetPointInGraph(Float_t qhi, Float_t qlo);

  Bool_t FillChargeLoGain(Float_t q)             { return (fHChargeLoGain->Fill(q) > -1); }
  Bool_t FillTimeLoGain(Int_t t)                 { return (fHTimeLoGain->Fill(t)   > -1); }
  Bool_t FillChargevsNLoGain(Float_t q, Int_t n) { return (fHChargevsNLoGain->Fill(n,q) > -1); }

  Bool_t FillChargeHiGain(Float_t q)             { return (fHChargeHiGain->Fill(q)      > -1); }
  Bool_t FillTimeHiGain(Int_t t)                 { return (fHTimeHiGain->Fill(t)        > -1); }
  Bool_t FillChargevsNHiGain(Float_t q, Int_t n) { return (fHChargevsNHiGain->Fill(n,q) > -1); }

  void   SetUseLoGain()                               { fUseLoGain = kTRUE; }
  Bool_t UseLoGain();

  void SetTimeFitRangesHiGain(Byte_t low, Byte_t up) { fTimeLowerFitRangeHiGain = low,
                                               fTimeUpperFitRangeHiGain = up ;  }
  void SetTimeFitRangesLoGain(Byte_t low, Byte_t up) { fTimeLowerFitRangeLoGain = low,
                                               fTimeUpperFitRangeLoGain = up ;  }
  
  const TH1F *GetHCharge()                 { return fHChargeHiGain;    }
  const TH1F *GetHCharge() const           { return fHChargeHiGain;    }

  const Double_t GetChargeMean()     const { return fChargeMean;    }
  const Double_t GetChargeMeanErr()  const { return fChargeMeanErr; }
  const Double_t GetChargeSigma()    const { return fChargeSigma;   }
  const Double_t GetChargeSigmaErr() const { return fChargeSigmaErr; }
  const Double_t GetArea()           const { return fChargeGausFit->GetParameter(0); }
  const Double_t GetAreaErr()        const { return fChargeGausFit->GetParError(0);  }

  const Double_t GetChargeChiSquare() const { return fChargeChisquare; }
  const Double_t GetChargeProb()      const { return fChargeProb;      }  
  const Int_t    GetChargeNdf()       const { return fChargeNdf;       }   

  const Double_t GetTimeMean()        const { return fTimeMean;  }
  const Double_t GetTimeSigma()       const { return fTimeSigma; }

  const Byte_t   GetTimeLowerFitRangeHiGain()  const { return fTimeLowerFitRangeHiGain;  }
  const Byte_t   GetTimeUpperFitRangeHiGain()  const { return fTimeUpperFitRangeHiGain;  }
  const Byte_t   GetTimeLowerFitRangeLoGain()  const { return fTimeLowerFitRangeLoGain;  }
  const Byte_t   GetTimeUpperFitRangeLoGain()  const { return fTimeUpperFitRangeLoGain;  }
  
  const Double_t GetTimeChiSquare()     const { return fTimeChisquare; }
  const Double_t GetTimeProb()        const { return fTimeProb;      }
  const Int_t    GetTimeNdf()         const { return fTimeNdf;       }   
  
  const TH1I *GetHTime()                    { return fHTimeHiGain; }
  const TH1I *GetHTime()              const { return fHTimeHiGain; }
  
  const TH1I *GetHChargevsN()               { return fHChargevsNHiGain; }
  const TH1I *GetHChargevsN()         const { return fHChargevsNHiGain; }

  Double_t GetOffset()  { return fOffset; }
  Double_t GetSlope()   { return fSlope;  }
  
  Bool_t FitChargeHiGain(Option_t *option="RQ0");  
  Bool_t FitTimeHiGain(Axis_t rmin=0, Axis_t rmax=0, Option_t *option="RQ0");    

  Bool_t FitChargeLoGain(Option_t *option="RQ0");  
  Bool_t FitTimeLoGain(Axis_t rmin=0, Axis_t rmax=0, Option_t *option="RQ0");    

  void   FitHiGainvsLoGain();

  virtual void Draw(Option_t *option="");
  virtual void CutAllEdges();
  virtual void Reset();

  void SetLowerFitRange(Axis_t min)                {  fLowerFitRange = min; }

  void PrintChargeFitResult();
  void PrintTimeFitResult();  

  Bool_t IsFitOK()                           {  return fFitOK;          }
  Bool_t IsEmpty()                           {  return !( (fHChargeHiGain->GetEntries())
                                                     || (fHChargeLoGain->GetEntries()) ); }  
  
  ClassDef(MHCalibrationPixel, 1) 
};

#endif
