#ifndef MARS_MHCalibrationChargeCam
#define MARS_MHCalibrationChargeCam

#ifndef ROOT_TObjArray
#include <TObjArray.h>
#endif

#ifndef ROOT_TArrayI
#include <TArrayI.h>
#endif

#ifndef ROOT_TArrayF
#include <TArrayF.h>
#endif

#ifndef MARS_MH
#include "MH.h"
#endif
#ifndef MARS_MCamEvent
#include "MCamEvent.h"
#endif

class TText;
class TArrayI;
class TArrayF;
class MRawEvtData;
class MGeomCam;
class MBadPixelsCam;
class MBadPixelsPix;
class MCalibrationChargeCam;
class MCalibrationChargePix;
class MHCalibrationChargeHiGainPix;
class MHCalibrationChargeLoGainPix;
class MHCalibrationChargeCam : public MH, public MCamEvent
{
private:

  static const Int_t   fgAverageNbins;               // The default for fAverageNbins
  static const Float_t fgNumHiGainSaturationLimit;   // The default for fNumHiGainSaturationLimit
  static const Float_t fgNumLoGainSaturationLimit;   // The default for fNumLoGainSaturationLimit
  static const Int_t   fgPulserFrequency;            // The default for fPulserFrequency
  
  Int_t   fAverageNbins;              // Number of bins for the average histograms
  Float_t fNumHiGainSaturationLimit;  // Rel. amount sat. higain FADC slices until pixel is called saturated
  Float_t fNumLoGainSaturationLimit;  // Rel. amount sat. logain FADC slices until pixel is called saturated
  Int_t   fPulserFrequency;           // Light pulser frequency
  
  TObjArray *fHiGainArray;            //-> Array of MHCalibrationChargeHiGainPix, one per pixel
  TObjArray *fLoGainArray;            //-> Array of MHCalibrationChargeLoGainPix, one per pixel
  TObjArray *fAverageHiGainAreas;     //-> Array of MHCalibrationChargeHiGainPix, one per pixel area
  TObjArray *fAverageLoGainAreas;     //-> Array of MHCalibrationChargeLoGainPix, one per pixel area
  TObjArray *fAverageHiGainSectors;   //-> Array of MHCalibrationChargeHiGainPix, one per camera sector
  TObjArray *fAverageLoGainSectors;   //-> Array of MHCalibrationChargeLoGainPix, one per camera sector

  MCalibrationChargeCam  *fCam;       //!  Calibration Cam with the results
  MRawEvtData            *fRawEvt;    //!  Raw event data 
  MGeomCam               *fGeom;      //!  Camera geometry
  MBadPixelsCam          *fBadPixels; //!  Bad Pixels storage container

  TArrayI fAverageAreaNum;            // Number of pixels in average pixels per area
  TArrayI fAverageAreaSat;            // Number of saturated slices in average pixels per area
  TArrayF fAverageAreaSigma;          // Re-normalized sigmas in average pixels per area
  TArrayF fAverageAreaSigmaErr;       // Errors of Re-normalized sigmas in average pixels per area
  TArrayF fAverageAreaRelSigma;       // Re-normalized relative sigmas in average pixels per area
  TArrayF fAverageAreaRelSigmaErr;    // Errors of Re-normalized relative sigmas in average pixels per area

  TArrayI fAverageSectorNum;          // Number of pixels in average pixels per sector 

  void InitializeHiGainHists(MHCalibrationChargeHiGainPix &hist, MBadPixelsPix &bad, const Int_t i);
  void InitializeLoGainHists(MHCalibrationChargeLoGainPix &hist, MBadPixelsPix &bad, const Int_t i);  
  
  void FinalizeHiGainHists(MHCalibrationChargeHiGainPix &hist, MCalibrationChargePix &pix, MBadPixelsPix &bad);
  void FinalizeLoGainHists(MHCalibrationChargeLoGainPix &hist, MCalibrationChargePix &pix, MBadPixelsPix &bad);
  void DrawAverageSigma(Bool_t sat, Bool_t inner,
                        Float_t sigma, Float_t sigmaerr,
                        Float_t relsigma, Float_t relsigmaerr) const; 
  
public:

  MHCalibrationChargeCam(const char *name=NULL, const char *title=NULL);
  ~MHCalibrationChargeCam();

  void SetAverageNbins(    const Int_t bins=fgAverageNbins  )          { fAverageNbins = bins; }
  void SetNumLoGainSaturationLimit( const Float_t lim=fgNumLoGainSaturationLimit) { fNumLoGainSaturationLimit = lim; }
  void SetNumHiGainSaturationLimit( const Float_t lim=fgNumHiGainSaturationLimit) { fNumHiGainSaturationLimit = lim; }
  void SetPulserFrequency        ( const Int_t   f=fgPulserFrequency)          { fPulserFrequency = f;            }
  
  Float_t GetNumHiGainSaturationLimit()                       const  { return fNumHiGainSaturationLimit; }
  Float_t GetNumLoGainSaturationLimit()                       const  { return fNumLoGainSaturationLimit; }

        MHCalibrationChargeHiGainPix &operator[](UInt_t i);
  const MHCalibrationChargeHiGainPix &operator[](UInt_t i)    const;

        MHCalibrationChargeLoGainPix &operator()(UInt_t i);
  const MHCalibrationChargeLoGainPix &operator()(UInt_t i)    const;

        MHCalibrationChargeHiGainPix  &GetAverageHiGainArea(UInt_t i);
  const MHCalibrationChargeHiGainPix  &GetAverageHiGainArea(UInt_t i)  const;

        MHCalibrationChargeLoGainPix  &GetAverageLoGainArea(UInt_t i);
  const MHCalibrationChargeLoGainPix  &GetAverageLoGainArea(UInt_t i)  const;

        MHCalibrationChargeHiGainPix  &GetAverageHiGainSector(UInt_t i);
  const MHCalibrationChargeHiGainPix  &GetAverageHiGainSector(UInt_t i)  const;

        MHCalibrationChargeLoGainPix  &GetAverageLoGainSector(UInt_t i);
  const MHCalibrationChargeLoGainPix  &GetAverageLoGainSector(UInt_t i)  const;

  Bool_t SetupFill(const MParList *pList);
  Bool_t ReInit   (      MParList *pList);
  Bool_t Fill     (const MParContainer *par, const Stat_t w=1);
  Bool_t Finalize ( );

  // Clone
  TObject *Clone(const char *) const;
  
  // Draw
  void Draw(const Option_t *opt);

  Bool_t GetPixelContent ( Double_t &val, Int_t idx, const MGeomCam &cam, Int_t type=0) const;
  void   DrawPixelContent( Int_t num )  const;    

  ClassDef(MHCalibrationChargeCam, 1)	// Histogram class for camera calibration 
};

#endif









