#ifndef MARS_MHCalibrationCam
#define MARS_MHCalibrationCam

#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

#ifndef MARS_MBadPixelsPix
#include "MBadPixelsPix.h"
#endif

class TText;
class TArrayI;
class TArrayF;
class MHGausEvents;
class MGeomCam;
class MRawRunHeader;
class MCalibrationCam;
class MCalibrationPix;
class MBadPixelsCam;
class MBadPixelsPix;
class MHCalibrationCam : public MH, public MCamEvent
{
  
private:

  static const Int_t fgAverageNbins;     //! The default for fAverageNbins    (now set to: 2000)
  static const Int_t fgPulserFrequency;  //! The default for fPulserFrequency (now set to: 500)

protected:

  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

  TArrayI    fAverageAreaNum;           // Number of pixels in average pixels per area
  TArrayF    fAverageAreaRelSigma;      // Re-normalized relative sigmas in average pixels per area
  TArrayF    fAverageAreaRelSigmaVar;   // Variance Re-normalized relative sigmas 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    fAverageAreaSigmaVar;      // Variance Re-normalized sigmas in average pixels per area
  Int_t      fAverageNbins;             // Number of bins for the average histograms
  TObjArray *fAverageHiGainAreas;       //-> Array of calibration pixels, one per pixel area
  TObjArray *fAverageHiGainSectors;     //-> Array of calibration pixels, one per camera sector
  TObjArray *fAverageLoGainAreas;       //-> Array of calibration pixels, one per pixel area
  TObjArray *fAverageLoGainSectors;     //-> Array of calibration pixels, one per camera sector
  TArrayI    fAverageSectorNum;         // Number of pixels in average pixels per sector 
  TArrayI    fRunNumbers;               // Numbers of runs used
  UInt_t     fHiGainOverFlow;           // Number of times overflow occurred in whole run
  UInt_t     fLoGainOverFlow;           // Number of times overflow occurred in whole run
  
  MBadPixelsCam    *fBadPixels;         //!  Bad Pixels storage container
  MCalibrationCam  *fCam;               //!  Calibration Cam with the results
  MGeomCam         *fGeom;              //!  Camera geometry
  MRawRunHeader    *fRunHeader;         //!  Run Header
  
  TObjArray *fHiGainArray;              //-> Array of calibration pixels, one per pixel
  TObjArray *fLoGainArray;              //-> Array of calibration pixels, one per pixel

  Int_t      fPulserFrequency;          // Light pulser frequency
  Bool_t     fDebug;                    // Debug option is used?
  
  virtual Bool_t SetupHists(const MParList *pList);
  virtual Bool_t ReInitHists(MParList *pList);  
  virtual Bool_t FillHists(const MParContainer *par, const Stat_t w=1);
  virtual Bool_t FinalizeHists();
  virtual void   FinalizeBadPixels();
  
  virtual void CalcAverageSigma();
  
  void DrawAverageSigma(Bool_t sat, Bool_t inner,
                        Float_t sigma, Float_t sigmaerr,
                        Float_t relsigma, Float_t relsigmaerr) const; 
  
  void FitHiGainArrays(MCalibrationCam &calcam, MBadPixelsCam &badcam,
                       MBadPixelsPix::UncalibratedType_t fittyp,
                       MBadPixelsPix::UncalibratedType_t osctyp);
  
  void FitHiGainHists(MHGausEvents &hist, 
                      MCalibrationPix &pix, 
                      MBadPixelsPix &bad, 
                      MBadPixelsPix::UncalibratedType_t fittyp,
                      MBadPixelsPix::UncalibratedType_t osctyp);
  
  void FitLoGainArrays(MCalibrationCam &calcam, MBadPixelsCam &badcam,
                       MBadPixelsPix::UncalibratedType_t fittyp,
                       MBadPixelsPix::UncalibratedType_t osctyp);
  
  void FitLoGainHists(MHGausEvents &hist, 
                      MCalibrationPix &pix, 
                      MBadPixelsPix &bad, 
                      MBadPixelsPix::UncalibratedType_t fittyp,
                      MBadPixelsPix::UncalibratedType_t osctyp);

  void InitHists(MHGausEvents &hist, MBadPixelsPix &bad, const Int_t i);

  Int_t ReadEnv(const TEnv &env, TString prefix, Bool_t print);

public:

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

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

  // Clone
  virtual TObject *Clone(const char *name="") const;

  // Draw
  virtual void   Draw(const Option_t *opt);

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

  const Int_t          GetAverageAreas       ()          const;	 
        MHGausEvents  &GetAverageHiGainArea  (UInt_t i);
  const MHGausEvents  &GetAverageHiGainArea  (UInt_t i)  const;
        MHGausEvents  &GetAverageLoGainArea  (UInt_t i);
  const MHGausEvents  &GetAverageLoGainArea  (UInt_t i)  const;
        MHGausEvents  &GetAverageHiGainSector(UInt_t i);
  const MHGausEvents  &GetAverageHiGainSector(UInt_t i)  const;
        MHGausEvents  &GetAverageLoGainSector(UInt_t i);
  const MHGausEvents  &GetAverageLoGainSector(UInt_t i)  const;
  const Int_t          GetAverageSectors     ()          const;
  const Float_t        GetNumHiGainSaturationLimit()     const  { return fNumHiGainSaturationLimit; }
  const Float_t        GetNumLoGainSaturationLimit()     const  { return fNumLoGainSaturationLimit; }
  const TArrayI       &GetRunNumbers         ()          const;
  const Int_t          GetSize               ()          const  { return fHiGainArray->GetSize();   }

  const Bool_t         IsDebug                ()          const  { return fDebug; }
  
        MHGausEvents  &operator[]            (UInt_t i);
  const MHGausEvents  &operator[]            (UInt_t i)  const;
        MHGausEvents  &operator()            (UInt_t i);
  const MHGausEvents  &operator()            (UInt_t i)  const;
 
  void SetDebug                (const Bool_t b=kTRUE) { fDebug           = b; }
  void SetAverageNbins        ( const Int_t bins=fgAverageNbins ) { fAverageNbins = bins; }
  void SetNumLoGainSaturationLimit( const Float_t lim) { fNumLoGainSaturationLimit = lim; }
  void SetNumHiGainSaturationLimit( const Float_t lim) { fNumHiGainSaturationLimit = lim; }
  void SetPulserFrequency      ( const Int_t f=fgPulserFrequency)  { fPulserFrequency = f; }
  
  ClassDef(MHCalibrationCam, 1)	// Base Histogram class for Calibration Camera
};

#endif









