#ifndef MARS_MCalibrationChargePix
#define MARS_MCalibrationChargePix

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

class MBadPixelsPix;
class MCalibrationChargePix : public MCalibrationPix
{
private:

  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 fgPheFFactorMethodLimit;  // The default minimum number of Photo-electrons for a pixel to be accepted.
  
  Float_t fElectronicPedRms;        // The pure electronic component of the RMS
  Float_t fElectronicPedRmsVar;     // The error of the pure electronic component of the RMS

  Float_t fPheFFactorMethodLimit;   // The minimum number of Photo-electrons for a pixel to be accepted.
  
  Float_t fRSigma;                  // The reduced squares of sigmas after the fit
  Float_t fRSigmaVar;               // The reduced squares of sigmas after the fit  

  Float_t fPed;                     // The mean pedestal (from MPedestalPix) times number of FADC slices
  Float_t fPedVar;                  // The error of the pedestal 
  Float_t fPedRms;                  // The pedestal  RMS (from MPedestalPix) times sqrt of number of FADC slices

  Float_t fLoGainPedRms;            // The pedestal  RMS of the low gain
  Float_t fLoGainPedRmsVar;         // The pedestal  RMS Variance of the low gain

  Float_t fAbsTimeMean;             // The mean absolute arrival time
  Float_t fAbsTimeRms;              // The rms of the mean absolute arrival time
  
  Float_t fPheFFactorMethod;        // The number of Phe's calculated (F-factor method)
  Float_t fPheFFactorMethodVar;     // 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 fConversionFFactorMethodVar;      // The error of the conversion factor to Phe's (F-factor method)
  Float_t fConversionBlindPixelMethodVar;   // The error of the conversion factor to Ph's (Blind Pixel method)
  Float_t fConversionPINDiodeMethodVar;     // The error of the conversion factor to Ph's (PIN Diode method)
  Float_t fConversionCombinedMethodVar;     // 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 fTotalFFactorFFactorMethodVar;    // The variance of the total F-Factor to Ph's (F-factor method)
  Float_t fTotalFFactorBlindPixelMethodVar; // The variance of the total F-Factor to Ph's (Blind Pixel method)
  Float_t fTotalFFactorPINDiodeMethodVar;   // The variance of the total F-Factor to Ph's (PIN Diode method)
  Float_t fTotalFFactorCombinedMethodVar;   // The variance 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 fTotalFFactorVar;                 // The variance on the F-Factor of the total readout system
  
  Float_t fConversionHiLo;                  // The conversion factor between Hi Gain and Lo Gain  
  Float_t fConversionHiLoVar;               // The error of the conversion factor between Hi Gain and Lo Gain  

  Byte_t fCalibFlags;                       // The bit-field for the class-own bits

  enum  { kBlindPixelMethodValid, kFFactorMethodValid,
          kPINDiodeMethodValid, kCombinedMethodValid }; // The possible bits to be set

public:

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

  // Setter
  void SetPedestal(const Float_t ped, const Float_t pedrms, const Float_t pederr);

  void SetConversionHiLo(     const Float_t c = gkConversionHiLo)       { fConversionHiLo      = c;    }
  void SetConversionHiLoErr(  const Float_t e = gkConversionHiLoErr)    { fConversionHiLoVar   = e*e;    }

  void SetPheFFactorMethodLimit ( const Float_t f=fgPheFFactorMethodLimit  ) { fPheFFactorMethodLimit  = f;   }
  
  // Times
  void SetAbsTimeMean           ( const Float_t f ) { fAbsTimeMean           = f; }
  void SetAbsTimeRms            ( const Float_t f ) { fAbsTimeRms            = f; }

  // Conversion Factors
  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 );

  void SetTotalFFactorFFactorMethod   ( const Float_t f)  { fTotalFFactorFFactorMethod = f; }
  void SetTotalFFactorBlindPixelMethod ( const Float_t f)  { fTotalFFactorBlindPixelMethod = f; }
  void SetTotalFFactorPINDiodeMethod   ( const Float_t f)  { fTotalFFactorPINDiodeMethod = f; }
  
  void SetTotalFFactorFFactorMethodErr   ( const Float_t f)  { fTotalFFactorFFactorMethodVar = f*f; }
  void SetTotalFFactorBlindPixelMethodErr ( const Float_t f)  { fTotalFFactorBlindPixelMethodVar = f*f; }
  void SetTotalFFactorPINDiodeMethodErr   ( const Float_t f)  { fTotalFFactorPINDiodeMethodVar = f*f; }
  
  // Bit Setters
  void SetBlindPixelMethodValid( const Bool_t b = kTRUE );
  void SetFFactorMethodValid  (  const Bool_t b = kTRUE );
  void SetPINDiodeMethodValid (  const Bool_t b = kTRUE );
  void SetCombinedMethodValid (  const Bool_t b = kTRUE );

  Float_t GetLoGainMean     ()           const;
  Float_t GetLoGainMeanErr  ()           const;
  Float_t GetLoGainSigma    ()           const;
  Float_t GetLoGainSigmaErr ()           const;

  Float_t GetRSigma()                    const;
  Float_t GetRSigmaErr()                 const;

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

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

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

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

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

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

  Float_t GetPed()                             const { return fPed;                              }
  Float_t GetPedErr()                          const;
  Float_t GetPedRms()                          const;
  Float_t GetPedRmsErr()                       const;

  Float_t GetTotalFFactorFFactorMethod()       const { return fTotalFFactorFFactorMethod;        }
  Float_t GetTotalFFactorFFactorMethodErr()    const;
  
  Float_t GetTotalFFactorBlindPixelMethod()    const { return fTotalFFactorBlindPixelMethod;     }
  Float_t GetTotalFFactorBlindPixelMethodErr() const;
  
  Float_t GetTotalFFactorPINDiodeMethod()      const { return fTotalFFactorPINDiodeMethod;       }
  Float_t GetTotalFFactorPINDiodeMethodErr()   const;

  Float_t GetTotalFFactorCombinedMethod()      const { return fTotalFFactorCombinedMethod;       }
  Float_t GetTotalFFactorCombinedMethodErr()   const;
  
  Bool_t IsBlindPixelMethodValid()             const;
  Bool_t IsPINDiodeMethodValid()               const;
  Bool_t IsFFactorMethodValid()                const;
  Bool_t IsCombinedMethodValid()               const;

  // Miscellaneous
  void  CalcLoGainPedestal(const Float_t logainsamples);
  Bool_t CalcReducedSigma();
  Bool_t CalcFFactorMethod();

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

#endif

