#ifndef MARS_MCalibrationChargePix
#define MARS_MCalibrationChargePix

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

class MBadPixelsPix;
class MCalibrationChargePix : public MParContainer
{
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 fgChargeLimit;            // The default limit (in units of PedRMS) for acceptance of the fitted mean charge
  static const Float_t fgChargeErrLimit;         // The default limit (in units of PedRMS) for acceptance of the fitted charge sigma
  static const Float_t fgChargeRelErrLimit;      // The default limit (in units of Error of fitted charge) for acceptance of the fitted mean  

  static const Float_t fgTimeLimit;              // The limit (in units of FADC slices) for acceptance of the fitted time
  static const Float_t fgTimeErrLimit;           // The limit (in units of FADC slices) for acceptance of the fitted time sigma

  Float_t fChargeLimit;                     // The limit (in units of PedRMS) for acceptance of the fitted mean charge
  Float_t fChargeErrLimit;                  // The limit (in units of PedRMS) for acceptance of the fitted charge sigma
  Float_t fChargeRelErrLimit;               // The limit (in units of Error of fitted charge) for acceptance of the fitted mean  
  
  Float_t fTimeLimit;                       // The limit (in units of FADC slices) for acceptance of the fitted time
  Float_t fTimeErrLimit;                    // The limit (in units of FADC slices) for acceptance of the fitted time sigma

  Float_t fElectronicPedRms;                // The pure electronic component of the RMS
  Float_t fElectronicPedRmsErr;             // The error of the pure electronic component of the RMS

  Int_t   fPixId;                           // the pixel Id

  UInt_t  fFlags;                           // Flag for the set bits
 
  Float_t fHiGainMeanCharge;                // The mean reduced charge after the fit
  Float_t fHiGainMeanChargeErr;             // The error of reduced mean charge after the fit
  Float_t fHiGainSigmaCharge;               // The sigma of the mean charge after the fit
  Float_t fHiGainSigmaChargeErr;            // The error of the sigma of the mean charge after the fit
  Float_t fHiGainChargeProb;                // The probability of the fit function 

  Float_t fLoGainMeanCharge;                // The mean reduced charge after the fit
  Float_t fLoGainMeanChargeErr;             // The error of reduced mean charge after the fit
  Float_t fLoGainSigmaCharge;               // The sigma of the mean charge after the fit
  Float_t fLoGainSigmaChargeErr;            // The error of the sigma of the mean charge after the fit
  Float_t fLoGainChargeProb;                // The probability of the fit function 

  Float_t fRSigmaCharge;                    // The reduced squares of sigmas after the fit
  Float_t fRSigmaChargeErr;                 // The reduced squares of sigmas after the fit  

  Float_t fPed;                             // The mean pedestal (from MPedestalPix) times number of FADC slices
  Float_t fPedErr;                          // 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 fLoGainPedRmsErr;                 // The pedestal  RMS Error of the low gain

  Float_t fAbsTimeMean;                     // The mean absolute 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 fNumLoGainSamples;

  Float_t   fHiGainNumPickup;
  Float_t   fLoGainNumPickup;

  enum  { kHiGainSaturation, kLoGainSaturation,
          kExcluded, 
          kChargeValid, kTimeFitValid,
          kHiGainFitted, kLoGainFitted, 
          kBlindPixelMethodValid, kFFactorMethodValid, 
	  kPINDiodeMethodValid, kCombinedMethodValid };

  void CalcLoGainPed();
  
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)    { fConversionHiLoErr   = e;    }
  void SetChargeLimit    (   const Float_t f=fgChargeLimit       ) { fChargeLimit       = f; }
  void SetChargeErrLimit (   const Float_t f=fgChargeErrLimit    ) { fChargeErrLimit    = f; }
  void SetChargeRelErrLimit( const Float_t f=fgChargeRelErrLimit ) { fChargeRelErrLimit = f; }

  void SetTimeLimit      (   const Float_t f=fgTimeLimit         ) { fTimeLimit       = f;   }
  void SetTimeErrLimit   (   const Float_t f=fgTimeErrLimit      ) { fTimeErrLimit    = f;   }

  // Charges
  void SetHiGainMeanCharge      ( const Float_t f ) { fHiGainMeanCharge      = f; }
  void SetHiGainMeanChargeErr   ( const Float_t f ) { fHiGainMeanChargeErr   = f; }
  void SetHiGainChargeProb      ( const Float_t f ) { fHiGainChargeProb      = f; }
  void SetHiGainSigmaCharge     ( const Float_t f ) { fHiGainSigmaCharge     = f; }
  void SetHiGainSigmaChargeErr  ( const Float_t f ) { fHiGainSigmaChargeErr  = f; }

  void SetLoGainMeanCharge      ( const Float_t f ) { fLoGainMeanCharge      = f; }
  void SetLoGainMeanChargeErr   ( const Float_t f ) { fLoGainMeanChargeErr   = f; }
  void SetLoGainChargeProb      ( const Float_t f ) { fLoGainChargeProb      = f; }
  void SetLoGainSigmaCharge     ( const Float_t f ) { fLoGainSigmaCharge     = f; }
  void SetLoGainSigmaChargeErr  ( const Float_t f ) { fLoGainSigmaChargeErr  = f; }

  void SetMeanCharge            ( const Float_t f );                
  void SetMeanChargeErr         ( const Float_t f );             
  void SetSigmaCharge           ( const Float_t f );               
  void SetSigmaChargeErr        ( const Float_t f );            

  void SetHiGainNumPickup       ( const Float_t   f ) { fHiGainNumPickup       = f; }
  void SetLoGainNumPickup       ( const Float_t   f ) { fLoGainNumPickup       = f; }

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

  void SetNumLoGainSamples      ( const Float_t f ) { fNumLoGainSamples      = 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 SetTotalFFactorErrFFactorMethod   ( const Float_t f)  { fTotalFFactorErrFFactorMethod = f; }
  void SetTotalFFactorErrBlindPixelMethod ( const Float_t f)  { fTotalFFactorErrBlindPixelMethod = f; }
  void SetTotalFFactorErrPINDiodeMethod   ( const Float_t f)  { fTotalFFactorErrPINDiodeMethod = f; }
  
  // Bit Setters
  void SetHiGainSaturation    (  const Bool_t b = kTRUE );
  void SetLoGainSaturation    (  const Bool_t b = kTRUE );
  void SetExcluded            (  const Bool_t b = kTRUE );
  void SetHiGainFitted        (  const Bool_t b = kTRUE );
  void SetLoGainFitted        (  const Bool_t b = kTRUE );
  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 );

  void SetAbsTimeBordersHiGain( Byte_t f, Byte_t l );
  void SetAbsTimeBordersLoGain( Byte_t f, Byte_t l );
  
  // Charges
  Float_t GetHiGainMeanCharge()          const { return fHiGainMeanCharge;      }
  Float_t GetHiGainMeanChargeErr()       const { return fHiGainMeanChargeErr;   }
  Float_t GetHiGainChargeProb()          const { return fHiGainChargeProb;      }    
  Float_t GetHiGainSigmaCharge()         const { return fHiGainSigmaCharge;     }
  Float_t GetHiGainSigmaChargeErr()      const { return fHiGainSigmaChargeErr;  }

  Float_t GetLoGainMeanCharge()          const { return fLoGainMeanCharge;      }
  Float_t GetLoGainMeanChargeErr()       const { return fLoGainMeanChargeErr;   }
  Float_t GetLoGainChargeProb()          const { return fLoGainChargeProb;      }    
  Float_t GetLoGainSigmaCharge()         const { return fLoGainSigmaCharge;     }
  Float_t GetLoGainSigmaChargeErr()      const { return fLoGainSigmaChargeErr;  }

  Float_t GetMeanCharge()                const;
  Float_t GetMeanChargeErr()             const;
  Float_t GetChargeProb()                const;
  Float_t GetSigmaCharge()               const;
  Float_t GetSigmaChargeErr()            const;

  Float_t GetRSigmaCharge()              const { return fRSigmaCharge;    }
  Float_t GetRSigmaChargeErr()           const { return fRSigmaChargeErr; }  

  Float_t GetHiGainNumPickup()           const { return fHiGainNumPickup; }
  Float_t GetLoGainNumPickup()           const { return fLoGainNumPickup; }

  Float_t GetAbsTimeMean()               const { return fAbsTimeMean;     }
  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 GetPedErr()                          const { return fPedErr;                           }
  Float_t GetPedRms()                          const { return fPedRms;                           }
  Float_t GetPedRmsErr()                       const { return fPedErr / 2.;                      }

  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 IsHiGainSaturation()                  const;
  Bool_t IsLoGainSaturation()                  const;
  Bool_t IsHiGainFitted()                      const;
  Bool_t IsLoGainFitted()                      const;
  Bool_t IsFitted()                            const;
  Bool_t IsBlindPixelMethodValid()             const;
  Bool_t IsPINDiodeMethodValid()               const;
  Bool_t IsFFactorMethodValid()                const;
  Bool_t IsCombinedMethodValid()               const;

  void   DefinePixId(Int_t i);

  // Miscellaneous
  void  ApplyLoGainConversion();

  void CheckChargeValidity ( MBadPixelsPix *bad );
  void CheckTimeValidity   ( MBadPixelsPix *bad );
  Bool_t CalcReducedSigma();
  Bool_t CalcFFactorMethod();

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

#endif

