#ifndef MARS_MHCalibrationPixel
#define MARS_MHCalibrationPixel

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

class TArrayF;
class TH1F;
class TH1I;
class TF1;
class TProfile;
class TPaveText;

class MHCalibrationPixel : public MH
{

private:

  Int_t fPixId;                  // Pixel Nr

  TArrayF *fHiGains;             //->
  TArrayF *fLoGains;             //->

  const Int_t   fChargeNbinsHiGain;
  const Int_t   fChargeNbinsLoGain;
  const Int_t   fTimeNbins;
  const Int_t   fChargevsNbins;

  const Axis_t  fTimeFirst;
  const Axis_t  fTimeLast;
  
  TProfile* fHivsLoGain;

  Double_t fOffset;
  Double_t fSlope;
  
protected:

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

  TH1F* fHPSD;                   // Power spectrum density of fHBlindPixelChargevsN
  
  TF1* fChargeGausFit;
  TF1* fTimeGausFit;
  
  TPaveText *fFitLegend;  
  
  Int_t fTotalEntries;           // Number of entries

  Axis_t  fChargeFirstHiGain;
  Axis_t  fChargeLastHiGain;
  Axis_t  fChargeFirstLoGain;
  Axis_t  fChargeLastLoGain;

  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;

  Byte_t   fFlags;

  enum   { kUseLoGain, kFitOK };
  
  virtual void DrawLegend();
  
public:

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

  void Clear(Option_t *o="");
  void Reset();  

  void ChangeHistId(Int_t i);
  
  // Setters
  void   SetUseLoGain(Bool_t b = kTRUE)
    { b ? SETBIT(fFlags, kUseLoGain) : SETBIT(fFlags, kUseLoGain); }

  void SetTimeFitRangesHiGain(Byte_t low, Byte_t up) { fTimeLowerFitRangeHiGain = low,
                                               fTimeUpperFitRangeHiGain = up ;  }
  void SetTimeFitRangesLoGain(Byte_t low, Byte_t up) { fTimeLowerFitRangeLoGain = low,
                                               fTimeUpperFitRangeLoGain = up ;  }

  // Getters
  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 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 TH1F *GetHCharge()                  { return fHChargeHiGain;    }
  const TH1F *GetHCharge()            const { return fHChargeHiGain;    }

  const TH1F *GetHTime()                    { return fHTimeHiGain; }
  const TH1F *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 UseLoGain();

  Bool_t IsFitOK()     const;    
  Bool_t IsUseLoGain() const;
  Bool_t IsEmpty()     const;
  
  // Fill histos
  Bool_t FillChargeLoGain(Float_t q);
  Bool_t FillTimeLoGain(Float_t t);
  Bool_t FillChargevsNLoGain(Float_t q, Int_t n);

  Bool_t FillChargeHiGain(Float_t q);
  Bool_t FillTimeHiGain(Float_t t);
  Bool_t FillChargevsNHiGain(Float_t q, Int_t n);

  Bool_t FillPointInGraph(Float_t qhi, Float_t qlo);

  Bool_t SetupFill(const MParList *pList);
  Bool_t Fill(const MParContainer *, const Stat_t w=1) { return kTRUE; }
  
  // Fits
  Bool_t FitCharge(Option_t *option="RQ0");  

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

  void   FitHiGainvsLoGain();

  // Draws
  virtual void Draw(Option_t *option="");
  TObject *DrawClone(Option_t *option="") const;
  
  // Prints
  void PrintChargeFitResult();
  void PrintTimeFitResult();  

  // Others
  virtual void CutAllEdges();

  ClassDef(MHCalibrationPixel, 1)     // Histograms for each calibrated pixel
};

#endif
