#ifndef MARS_MCalibrationPix
#define MARS_MCalibrationPix

#ifndef MARS_MParContainer
#include "MParContainer.h"
#endif

#include "MHCalibrationPixel.h"

class MCalibrationPix : public MParContainer
{
private:

  static const Float_t gkAverageQE;              // The average quantum efficieny agreed on for the first analysis
  static const Float_t gkAverageQEErr;           // The error of average quantum efficieny 
  
  static const Float_t gkConversionHiLo;         // The default conversion factor HI gain - Lo Gain
  static const Float_t gkConversionHiLoErr;      // The error of the default conversion factor
  
  static const Float_t gkElectronicPedRms;       // The pure electronic component of the RMS
  static const Float_t gkElectronicPedRmsErr;    // The error of the pure electronic component of the RMS
  static const Float_t gkFFactor;                // The laboratory F-factor of the PMTs
  static const Float_t gkFFactorErr;             // The laboratory F-factor Error of the PMTs
  static const Float_t gkChargeLimit;            // The limit (in units of PedRMS) for acceptance of the fitted mean charge
  static const Float_t gkChargeErrLimit;         // The limit (in units of PedRMS) for acceptance of the fitted charge sigma
  static const Float_t gkChargeRelErrLimit;      // The limit (in units of Error of fitted charge) for acceptance of the fitted mean  
  static const Float_t gkTimeLimit;              // The limit (in units of FADC slices) for acceptance of the fitted time
  static const Float_t gkTimeErrLimit;           // The limit (in units of FADC slices) for acceptance of the fitted time sigma
  static const Float_t gkConvFFactorRelErrLimit; // The limit for acceptance of the rel. error of the conversion factor with the FFactor method

  Int_t   fPixId;                                // the pixel Id

  UInt_t  fFlags;                                // Flag for the set bits
 
  Float_t fAverageQE;                            // The average quantum efficieny (see Class description)
  Float_t fAverageQEErr;                         // The error of the average quantum efficieny (see Class description)
  
  Float_t fCharge;                               // The mean reduced charge after the fit
  Float_t fChargeErr;                            // The error of reduced mean charge after the fit
  Float_t fSigmaCharge;                          // The sigma of the mean charge after the fit
  Float_t fSigmaChargeErr;                       // The error of the sigma of the mean charge after the fit
  Float_t fRSigmaCharge;                         // The reduced squares of sigmas after the fit
  Float_t fRSigmaChargeErr;                      // The reduced squares of sigmas after the fit  
  Float_t fChargeProb;                           // The probability of the fit function 

  Float_t fPed;                                  // The mean pedestal (from MPedestalPix)
  Float_t fPedRms;                               // The pedestal  RMS (from MPedestalPix)
  Float_t fPedRmsErr;                            // The error of the pedestal  RMS (from MPedestalPix)  

  Float_t fAbsTimeMean;                          // The mean absolute arrival time
  Float_t fAbsTimeMeanErr;                       // The error of the absolute mean arrival time
  Float_t fAbsTimeRms;                           // The rms of the mean absolute arrival time
  
  Byte_t  fTimeFirstHiGain;                      // The first used FADC slice
  Byte_t  fTimeLastHiGain;                       // The last used FADC slice
  
  Byte_t  fTimeFirstLoGain;                      // The first used FADC slice
  Byte_t  fTimeLastLoGain;                       // The last used FADC slice
  
  Float_t fPheFFactorMethod;                     // The number of Phe's calculated (F-factor method)
  Float_t fPheFFactorMethodErr;                  // The error on the number of Phe's calculated (F-factor method)

  Float_t fMeanConversionFFactorMethod;          // The conversion factor to Phe's (F-factor method)
  Float_t fMeanConversionBlindPixelMethod;       // The conversion factor to Ph's (Blind Pixel method)
  Float_t fMeanConversionPINDiodeMethod;         // The conversion factor to Ph's (PIN Diode method)
  Float_t fMeanConversionCombinedMethod;         // The conversion factor to Ph's (all methods combined)

  Float_t fConversionFFactorMethodErr;           // The error of the conversion factor to Phe's (F-factor method)
  Float_t fConversionBlindPixelMethodErr;        // The error of the conversion factor to Ph's (Blind Pixel method)
  Float_t fConversionPINDiodeMethodErr;          // The error of the conversion factor to Ph's (PIN Diode method)
  Float_t fConversionCombinedMethodErr;          // The error of the conversion factor to Ph's (all methods combined)

  Float_t fSigmaConversionFFactorMethod;         // The sigma of conversion factor to Phe's (F-factor method)
  Float_t fSigmaConversionBlindPixelMethod;      // The conversion factor to Ph's (Blind Pixel method)
  Float_t fSigmaConversionPINDiodeMethod;        // The conversion factor to Ph's (PIN Diode method)
  Float_t fSigmaConversionCombinedMethod;        // The conversion factor to Ph's (all methods combined)
 
  Float_t fTotalFFactorFFactorMethod;            // The total F-Factor to Ph's (F-factor method)
  Float_t fTotalFFactorBlindPixelMethod;         // The total F-Factor to Ph's (Blind Pixel method)
  Float_t fTotalFFactorPINDiodeMethod;           // The total F-Factor to Ph's (PIN Diode method)
  Float_t fTotalFFactorCombinedMethod;           // The total F-Factor to Ph's (all methods combined)
 
  Float_t fTotalFFactorErrFFactorMethod;         // The error of the total F-Factor to Ph's (F-factor method)
  Float_t fTotalFFactorErrBlindPixelMethod;      // The error of the total F-Factor to Ph's (Blind Pixel method)
  Float_t fTotalFFactorErrPINDiodeMethod;        // The error of the total F-Factor to Ph's (PIN Diode method)
  Float_t fTotalFFactorErrCombinedMethod;        // The error of the total F-Factor to Ph's (all methods combined)
 
  Float_t fTotalFFactor;                         // The F-Factor of the total readout system (Sigma(out)/mean(out)*Mean(in)/sigma(in)
  Float_t fTotalFFactorErr;                      // The error on the F-Factor of the total readout system
  
  Float_t fConversionHiLo;                       // The conversion factor between Hi Gain and Lo Gain  
  Float_t fConversionHiLoErr;                    // The error of the conversion factor between Hi Gain and Lo Gain  

  Float_t fNumHiGainSamples;                     // The number of hi-gain samples used for the signal extraction
  Float_t fNumLoGainSamples;                     // The number of hi-gain samples used for the signal extraction
  
  enum  { kHiGainSaturation,
          kExcluded, kExcludeQualityCheck,
          kChargeValid, kTimeFitValid,
          kFitted, kOscillating, 
          kBlindPixelMethodValid, kFFactorMethodValid, 
	  kPINDiodeMethodValid, kCombinedMethodValid };
  
  MHCalibrationPixel *fHist;                     // Pointer to the histograms performing the fits, etc.  

  Bool_t CheckChargeValidity();
  Bool_t CheckTimeFitValidity();
  
public:

  MCalibrationPix(const char *name=NULL, const char *title=NULL);
  ~MCalibrationPix();
  
  void Clear(Option_t *o="");

  // Getter
  MHCalibrationPixel *GetHist() const   { return fHist;     }

  // Setter
  void SetPedestal(const Float_t ped, const Float_t pedrms,
                   const Float_t higainsamp, const Float_t logainsamp);
  void SetConversionHiLo(     const Float_t c = gkConversionHiLo)       { fConversionHiLo      = c;    }
  void SetConversionHiLoErr(  const Float_t e = gkConversionHiLoErr)    { fConversionHiLoErr   = e;    }
  void SetAverageQE(          const Float_t qe= gkAverageQE, 
			      const Float_t err=gkAverageQEErr)         { fAverageQE    = qe;           
			                                                  fAverageQEErr = err;         }

  // Setters for MC
  void SetConversionFFactorMethod(    Float_t c, Float_t err, Float_t sig );
  void SetConversionBlindPixelMethod( Float_t c, Float_t err, Float_t sig );
  void SetConversionPINDiodeMethod(   Float_t c, Float_t err, Float_t sig );
  void SetConversionCombinedMethod(   Float_t c, Float_t err, Float_t sig );

  // Bit Setters
  void SetHiGainSaturation(      Bool_t b = kTRUE );
  void SetExcluded(              Bool_t b = kTRUE );
  void SetExcludeQualityCheck(   Bool_t b = kTRUE );
  void SetChargeValid(           Bool_t b = kTRUE );
  void SetFitted(                Bool_t b = kTRUE );
  void SetOscillating(           Bool_t b = kTRUE );
  void SetBlindPixelMethodValid( Bool_t b = kTRUE );
  void SetFFactorMethodValid(    Bool_t b = kTRUE );
  void SetPINDiodeMethodValid(   Bool_t b = kTRUE );

  void SetAbsTimeBordersHiGain( Byte_t f, Byte_t l );
  void SetAbsTimeBordersLoGain( Byte_t f, Byte_t l );
  
  // Charges
  Float_t GetCharge()              const { return fCharge;          }
  Float_t GetChargeErr()           const { return fChargeErr;       }
  Float_t GetChargeProb()          const { return fChargeProb;      }    
  Float_t GetSigmaCharge()         const { return fSigmaCharge;     }
  Float_t GetSigmaChargeErr()      const { return fSigmaChargeErr;  }
  Float_t GetRSigmaCharge()        const { return fRSigmaCharge;    }
  Float_t GetRSigmaChargeErr()     const { return fRSigmaChargeErr; }  


  Float_t GetAbsTimeMean()         const { return fAbsTimeMean;     }
  Float_t GetAbsTimeMeanErr()      const { return fAbsTimeMeanErr;  }
  Float_t GetAbsTimeRms()          const { return fAbsTimeRms;      }
  
  // Conversion Factors
  Float_t GetConversionHiLo()      const  { return fConversionHiLo;    }
  Float_t GetConversionHiLoErr()   const  { return fConversionHiLoErr; }

  Float_t GetMeanConversionBlindPixelMethod()  const { return fMeanConversionBlindPixelMethod  ; }
  Float_t GetConversionBlindPixelMethodErr()   const { return fConversionBlindPixelMethodErr ;   }
  Float_t GetSigmaConversionBlindPixelMethod() const { return fSigmaConversionBlindPixelMethod ; }

  Float_t GetMeanConversionFFactorMethod()     const { return fMeanConversionFFactorMethod;      }
  Float_t GetConversionFFactorMethodErr()      const { return fConversionFFactorMethodErr;       } 
  Float_t GetSigmaConversionFFactorMethod()    const { return fSigmaConversionFFactorMethod;     }

  Float_t GetMeanConversionPINDiodeMethod()    const { return fMeanConversionPINDiodeMethod ;    }
  Float_t GetConversionPINDiodeMethodErr()     const { return fConversionPINDiodeMethodErr ;     }
  Float_t GetSigmaConversionPINDiodeMethod()   const { return fSigmaConversionPINDiodeMethod ;   }

  Float_t GetMeanConversionCombinedMethod()    const { return fMeanConversionCombinedMethod ;    }
  Float_t GetConversionCombinedMethodErr()     const { return fConversionCombinedMethodErr ;     }
  Float_t GetSigmaConversionCombinedMethod()   const { return fSigmaConversionCombinedMethod ;   }

  Float_t GetPheFFactorMethod()                const { return fPheFFactorMethod;                 }    
  Float_t GetPheFFactorMethodErr()             const { return fPheFFactorMethodErr;              }

  Int_t   GetPixId()                           const { return fPixId;                            }

  Float_t GetPed()                             const { return fPed;                              }
  Float_t GetPedRms()                          const { return fPedRms;                           }

  Float_t GetTotalFFactorFFactorMethod()       const { return fTotalFFactorFFactorMethod;        }
  Float_t GetTotalFFactorErrFFactorMethod()    const { return fTotalFFactorErrFFactorMethod;     }
  
  Float_t GetTotalFFactorBlindPixelMethod()    const { return fTotalFFactorBlindPixelMethod;     }
  Float_t GetTotalFFactorErrBlindPixelMethod() const { return fTotalFFactorErrBlindPixelMethod;  }
  
  Float_t GetTotalFFactorPINDiodeMethod()      const { return fTotalFFactorPINDiodeMethod;       }
  Float_t GetTotalFFactorErrPINDiodeMethod()   const { return fTotalFFactorErrPINDiodeMethod;    } 

  Float_t GetTotalFFactorCombinedMethod()      const { return fTotalFFactorCombinedMethod;       }
  Float_t GetTotalFFactorErrCombinedMethod()   const { return fTotalFFactorErrCombinedMethod;    }
  
  Bool_t IsExcluded()                          const;
  Bool_t IsExcludeQualityCheck()               const;
  Bool_t IsHiGainSaturation()                  const;
  Bool_t IsChargeValid()                       const;
  Bool_t IsFitted()                            const;
  Bool_t IsOscillating()                       const;
  Bool_t IsBlindPixelMethodValid()             const;
  Bool_t IsPINDiodeMethodValid()               const;
  Bool_t IsFFactorMethodValid()                const;
  Bool_t IsCombinedMethodValid()               const;

  // Fill histos
  Bool_t FillChargeHiGain(Float_t q)         const { return fHist->FillChargeHiGain(q); }
  Bool_t FillAbsTimeHiGain(Float_t t)        const { return fHist->FillAbsTimeHiGain(t); }

  Bool_t FillChargeLoGain(Float_t q)         const { return fHist->FillChargeLoGain(q); }
  Bool_t FillAbsTimeLoGain(Float_t t)        const { return fHist->FillAbsTimeLoGain(t); }

  Bool_t FillGraphs(Float_t qhi,Float_t qlo) const { return fHist->FillGraphs(qhi,qlo); }

  void   DefinePixId(Int_t i);

  // Fits
  Bool_t FitCharge();
  
  // Draws
  void Draw(Option_t *opt="")                    { fHist->Draw(opt); }
  TObject *DrawClone(Option_t *opt="") const    { return fHist->DrawClone(opt); }  
  
  // Miscellaneous
  void  ApplyLoGainConversion();
  void  CheckOscillations();  
  Bool_t CalcFFactorMethod();

  ClassDef(MCalibrationPix, 1)	// Container for Calibration of one pixel
};

#endif

