#ifndef MARS_MCalibrationChargeCam
#define MARS_MCalibrationChargeCam

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

class TH1D;
class TH2D;
class TClonesArray;

class MCalibrationChargeBlindPix;
class MCalibrationChargePINDiode;
class MCalibrationChargePix;
class MBadPixelsPix;
class MBadPixelsCam;
class MCalibrationChargeCam : public MParContainer, public MCamEvent
{
private:
  
  static const Float_t fgAverageQE;              // The default for fAverageQE    (now set to: 0.18)
  static const Float_t fgAverageQEErr;           // The default for fAverageQEErr (now set to: 0.02)
  static const Float_t fgConvFFactorRelErrLimit; // The default for fConvFFactorRelErrLimit (now set to: 0.35)
  static const Float_t fgPheFFactorRelErrLimit;  // The default for fPheFFactorRelErrLimit  (now set to: 5.)
  
  Float_t fAverageQE;                // The average quantum efficieny (see Class description)
  Float_t fAverageQEVar;             // The error of the average quantum efficieny (see Class description)
  Float_t fConvFFactorRelVarLimit;   // Acceptance limit for rel. error of conversion factor (FFactor method)
  Float_t fPheFFactorRelVarLimit;    // Acceptance limit for number of phe's w.r.t mean number (in variances)
  
  TClonesArray *fPixels;             //-> Array of MCalibrationChargePix, one per pixel
  TClonesArray *fAverageAreas;       //-> Array of MCalibrationChargePix, one per pixel area
  TClonesArray *fAverageSectors;     //-> Array of MCalibrationChargePix, one per camera sector
  TClonesArray *fAverageBadAreas;    //-> Array of MBadPixelsPix, one per pixel area
  TClonesArray *fAverageBadSectors;  //-> Array of MBadPixelsPix, one per camera sector
  
  TH1D* fOffsets;                    //! 
  TH1D* fSlopes;                     //! 
  
  TH2D* fOffvsSlope;                 //! 

  Byte_t  fFlags;

  enum  { kFFactorMethodValid, kBlindPixelMethodValid, kPINDiodeMethodValid, kCombinedMethodValid };

  Float_t fMeanFluxPhesInnerPixel;        //  The mean number of photo-electrons in an INNER PIXEL
  Float_t fMeanFluxPhesInnerPixelVar;     //  The variance of the number of photo-electrons INNER PIXEL  
  Float_t fMeanFluxPhesOuterPixel;        //  The mean number of photo-electrons in an INNER PIXEL
  Float_t fMeanFluxPhesOuterPixelVar;     //  The variance of the number of photo-electrons INNER PIXEL  

  Float_t fMeanFluxPhotonsInnerPixel;        //  The mean number of photo-electrons in an INNER PIXEL
  Float_t fMeanFluxPhotonsInnerPixelVar;     //  The variance of the number of photo-electrons INNER PIXEL  
  Float_t fMeanFluxPhotonsOuterPixel;        //  The mean number of photo-electrons in an INNER PIXEL
  Float_t fMeanFluxPhotonsOuterPixelVar;     //  The variance of the number of photo-electrons INNER PIXEL  
  
public:

  MCalibrationChargeCam(const char *name=NULL, const char *title=NULL);
  ~MCalibrationChargeCam();
  
  void Clear(    Option_t *o="" );
  void InitSize( const UInt_t i );
  void InitAverageAreas(  const UInt_t i );
  void InitAverageSectors( const UInt_t i );

  // Setters   
  void SetAverageQE(          const Float_t qe= fgAverageQE, 
			      const Float_t err=fgAverageQEErr)         { fAverageQE    = qe;           
			                                                  fAverageQEVar = err*err; }
  void SetConvFFactorRelErrLimit( const Float_t f=fgConvFFactorRelErrLimit ) { fConvFFactorRelVarLimit = f*f; }
  void SetPheFFactorRelErrLimit (  const Float_t f=fgPheFFactorRelErrLimit )     { fPheFFactorRelVarLimit = f*f;    }  

  void SetFFactorMethodValid(    const Bool_t b = kTRUE );
  void SetBlindPixelMethodValid( const Bool_t b = kTRUE );
  void SetPINDiodeMethodValid(   const Bool_t b = kTRUE );  

  // Getters
  Int_t   GetSize()               const;
  Int_t   GetAverageAreas()       const;
  Int_t   GetAverageSectors()     const;  

  Bool_t  GetConversionFactorFFactor(    Int_t ipx, Float_t &mean, Float_t &err, Float_t &sigma );
  Bool_t  GetConversionFactorBlindPixel( Int_t ipx, Float_t &mean, Float_t &err, Float_t &sigma );
  Bool_t  GetConversionFactorPINDiode(   Int_t ipx, Float_t &mean, Float_t &err, Float_t &sigma );
  Bool_t  GetConversionFactorCombined(   Int_t ipx, Float_t &mean, Float_t &err, Float_t &sigma );

  Float_t GetMeanFluxPhesInnerPixel()     const { return fMeanFluxPhesInnerPixel;     }
  Float_t GetMeanFluxPhesInnerPixelErr()  const;
  Float_t GetMeanFluxPhesOuterPixel()     const { return fMeanFluxPhesOuterPixel;     }
  Float_t GetMeanFluxPhesOuterPixelErr()  const;

  Float_t GetMeanFluxPhotonsInnerPixel()     const { return fMeanFluxPhotonsInnerPixel;     }
  Float_t GetMeanFluxPhotonsInnerPixelErr()  const;
  Float_t GetMeanFluxPhotonsOuterPixel()     const { return fMeanFluxPhotonsOuterPixel;     }
  Float_t GetMeanFluxPhotonsOuterPixelErr()  const;

  Bool_t IsBlindPixelMethodValid()   const;
  Bool_t IsPINDiodeMethodValid()     const;  

  // Others
  MCalibrationChargePix &operator[](UInt_t i);
  const MCalibrationChargePix &operator[](UInt_t i) const;

  MCalibrationChargePix &GetAverageArea(UInt_t i);
  const MCalibrationChargePix &GetAverageArea(UInt_t i) const;

  MBadPixelsPix &GetAverageBadArea(UInt_t i);
  const MBadPixelsPix &GetAverageBadArea(UInt_t i) const;

  MCalibrationChargePix &GetAverageSector(UInt_t i);
  const MCalibrationChargePix &GetAverageSector(UInt_t i) const;

  MBadPixelsPix &GetAverageBadSector(UInt_t i);
  const MBadPixelsPix &GetAverageBadSector(UInt_t i) const;

  // Prints
  void Print(Option_t *o="") const;
  
  // Draws
  void DrawPixelContent(Int_t num) const;    
//  void DrawHiLoFits();
  
  // Others
  Bool_t GetPixelContent(Double_t &val, Int_t idx, const MGeomCam &cam, Int_t type=0) const;

  Bool_t CalcMeanFluxPhotonsFFactorMethod(const MGeomCam &geom, MBadPixelsCam &bad);  

  void   ApplyPINDiodeCalibration(const MGeomCam &geom,
                                  const MBadPixelsCam &bad,
                                  const MCalibrationChargePINDiode &pindiode);
  void   ApplyBlindPixelCalibration(const MGeomCam &geom,
                                    const MBadPixelsCam &bad,
                                    const MCalibrationChargeBlindPix &blindpix);
  void   ApplyFFactorCalibration(const MGeomCam &geom, const MBadPixelsCam &bad);

  ClassDef(MCalibrationChargeCam, 1)	// Container for calibration of the camera
};

#endif
