#ifndef MARS_MCalibrationChargePix
#define MARS_MCalibrationChargePix

#ifndef MARS_MCalibrationPix
#include "MCalibrationPix.h"
#endif

class MCalibrationChargePix : public MCalibrationPix
{
private:

  static const Float_t gkElectronicPedRms;     //! Electronic component of ped. RMS from opt. receiver on (now set to: 1.)
  static const Float_t gkElectronicPedRmsErr;  //! Error Electr. component ped. RMS (now set to: 0.35)
  static const Float_t gkFFactor;              //! Laboratory F-factor PMTs         (now set to: 1.15)
  static const Float_t gkFFactorErr;           //! Laboratory F-factor Error PMTs   (now set to: 0.02)

  static const Float_t fgConversionHiLo;         //! Default fConversionHiLo          (now set to: 10.)
  static const Float_t fgConversionHiLoErr;      //! Default fConversionHiLoVar       (now set to: 2.5)
  static const Float_t fgPheFFactorMethodLimit;  //! Default fPheFFactorMethodLimit   (now set to: 5.)
  static const Float_t fgConvFFactorRelErrLimit; //! Default fConvFFactorRelErrLimit  (now set to: 0.35)  
  
  Float_t fAbsTimeMean;                     // Mean Absolute Arrival Time
  Float_t fAbsTimeRms;                      // RMS Mean Absolute Arrival Time
  Byte_t  fCalibFlags;                      // Bit-field for the class-own bits
  Float_t fConversionHiLo;                  // Conversion factor betw. Hi Gain and Lo Gain  
  Float_t fConversionHiLoVar;               // Variance Conversion factor betw. Hi and Lo Gain
  Float_t fConvFFactorRelVarLimit;          // Limit for acceptance rel. variance Conversion FADC2Phe
  Float_t fLoGainPedRmsSquare;              // Pedestal RMS square of Low Gain
  Float_t fLoGainPedRmsSquareVar;           // Pedestal RMS square Variance of Low Gain
  Float_t fMeanConvFADC2Phe;                // Conversion factor (F-factor method)
  Float_t fMeanConvFADC2PheVar;             // Variance conversion factor (F-factor method)
  Float_t fMeanFFactorFADC2Phot;            // Total mean F-Factor to photons (F-factor method)
  Float_t fMeanFFactorFADC2PhotVar;         // Variance mean F-Factor photons (F-factor method)  
  Float_t fPed;                             // Pedestal (from MPedestalPix) times number FADC slices
  Float_t fPedVar;                          // Variance of pedestal 
  Float_t fPedRms;                          // Pedestal RMS (from MPedestalPix) times sqrt nr. FADC slices
  Float_t fPedRmsVar;                       // Pedestal RMS (from MPedestalPix) times sqrt nr. FADC slices
  Float_t fPheFFactorMethod;                // Number Phe's calculated (F-factor method)
  Float_t fPheFFactorMethodVar;             // Variance number of Phe's (F-factor method)
  Float_t fPheFFactorMethodLimit;           // Min. number Photo-electrons for pix to be accepted.
  Float_t fRSigmaSquare;                    // Square of Reduced sigma
  Float_t fRSigmaSquareVar;                 // Variance Reduced sigma
  
  enum  { kFFactorMethodValid   };          // Possible bits to be set

  const Float_t GetElectronicPedRmsRelVar() const;
  const Float_t GetConversionHiLoRelVar()  const;
  const Float_t GetFFactorRelVar()     const;
  
public:

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

  // Setter
  void SetAbsTimeMean ( const Float_t f ) { fAbsTimeMean = f; }
  void SetAbsTimeRms  ( const Float_t f ) { fAbsTimeRms  = f; }
  void SetConversionHiLo    ( const Float_t c=fgConversionHiLo    )        { fConversionHiLo    = c;       }
  void SetConversionHiLoErr ( const Float_t e=fgConversionHiLoErr )        { fConversionHiLoVar = e*e;     }
  void SetConvFFactorRelErrLimit   ( const Float_t f=fgConvFFactorRelErrLimit) { fConvFFactorRelVarLimit = f*f;}
  void SetFFactorMethodValid   ( const Bool_t b = kTRUE );
  void SetMeanConvFADC2Phe      ( const Float_t f)                          { fMeanConvFADC2Phe       = f; }
  void SetMeanConvFADC2PheVar   ( const Float_t f)                          { fMeanConvFADC2PheVar    = f; }
  void SetMeanFFactorFADC2Phot  ( const Float_t f)                          { fMeanFFactorFADC2Phot   = f; }
  void SetPedestal              ( const Float_t ped, const Float_t pedrms, const Float_t pederr);
  void SetPed                   ( const Float_t ped, const Float_t pederr);  
  void SetPedRMS              ( const Float_t pedrms, const Float_t pedrmserr);  
  void SetPheFFactorMethod      ( const Float_t f)                          { fPheFFactorMethod       = f; }
  void SetPheFFactorMethodVar   ( const Float_t f)                          { fPheFFactorMethodVar    = f; }  
  void SetPheFFactorMethodLimit ( const Float_t f=fgPheFFactorMethodLimit ) { fPheFFactorMethodLimit  = f; }
  
  // Getters
  Float_t GetAbsTimeMean             () const { return fAbsTimeMean;             }
  Float_t GetAbsTimeRms              () const { return fAbsTimeRms;              }
  Float_t GetConversionHiLo          () const { return fConversionHiLo;          }
  Float_t GetConversionHiLoErr       () const;
  Float_t GetConvertedMean           () const;
  Float_t GetConvertedMeanErr        () const;
  Float_t GetConvertedSigma          () const;
  Float_t GetConvertedSigmaErr       () const;
  Float_t GetConvertedRSigma         () const;
  Float_t GetConvertedRSigmaErr      () const;
  Float_t GetConvertedRSigmaSquare   () const;  
  Float_t GetMeanConvFADC2Phe        () const { return fMeanConvFADC2Phe;        } 
  Float_t GetMeanConvFADC2PheErr     () const;
  Float_t GetMeanConvFADC2PheVar     () const { return fMeanConvFADC2PheVar;     }
  Float_t GetMeanFFactorFADC2Phot    () const { return fMeanFFactorFADC2Phot;    }
  Float_t GetMeanFFactorFADC2PhotErr () const;
  Float_t GetMeanFFactorFADC2PhotVar () const { return fMeanFFactorFADC2PhotVar; }    
  Float_t GetPed                     () const { return fPed;                     }
  Float_t GetPedErr                  () const { return TMath::Sqrt(fPedVar);     }
  Float_t GetPedRms                  () const;
  Float_t GetPedRmsErr               () const;
  Float_t GetPheFFactorMethod        () const { return fPheFFactorMethod;        }    
  Float_t GetPheFFactorMethodErr     () const;
  Float_t GetPheFFactorMethodVar     () const { return fPheFFactorMethodVar;     }
  Float_t GetPheFFactorMethodRelVar  () const;
  Float_t GetRSigma                  () const;
  Float_t GetRSigmaErr               () const;
  Float_t GetRSigmaRelVar            () const;
  Float_t GetRSigmaPerCharge         () const;
  Float_t GetRSigmaPerChargeErr      () const;

  Bool_t IsFFactorMethodValid        () const;

  // Calculations
  void   CalcLoGainPedestal       ( const Float_t logainsamples);
  Bool_t CalcReducedSigma  (  );
  Bool_t CalcFFactor       (  );
  Bool_t CalcConvFFactor   (  );  
  Bool_t CalcMeanFFactor   ( const Float_t nphotons, const Float_t nphotonsrelvar );
  
  ClassDef(MCalibrationChargePix, 2)	// Container Charge Calibration Results Pixel
};

#endif

