#ifndef MARS_MHCalibrationCam
#define MARS_MHCalibrationCam

#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

#ifndef MARS_MCalibrationCam
#include "MCalibrationCam.h"
#endif

class TText;
class TObjArray;

class MHCalibrationPix;
class MGeomCam;
class MRawRunHeader;
class MCalibrationIntensityCam;
class MCalibrationCam;
class MCalibrationPix;
class MBadPixelsCam;
class MBadPixelsPix;

class MHCalibrationCam : public MH, public MCamEvent
{
  
private:

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

  static const TString gsHistName;       //! Default Histogram names
  static const TString gsHistTitle;      //! Default Histogram titles
  static const TString gsHistXTitle;     //! Default Histogram x-axis titles
  static const TString gsHistYTitle;     //! Default Histogram y-axis titles
  
protected:

  Int_t   fNbins;                        // Number of bins        
  Axis_t  fFirst;                        // Lower histogram limit 
  Axis_t  fLast;                         // Upper histogram limit 

  TString fHistName;                     // Histogram names
  TString fHistTitle;                    // Histogram titles
  TString fHistXTitle;                   // Histogram x-axis titles
  TString fHistYTitle;                   // Histogram y-axis titles
  
  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

  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

  MCalibrationCam::PulserColor_t fColor; // Colour of the pulsed LEDs
  
  MBadPixelsCam    *fBadPixels;          //! Bad Pixels storage container
  MCalibrationIntensityCam *fIntensCam;  //! Intensity Calibration Cam with the results
  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

  enum { kDebug, kLoGain, kAverageing,
         kOscillations, kSizeCheck };     // Possible flags
  
  Byte_t     fFlags;                     // Bit-field to hold the flags
  
  virtual Bool_t SetupHists ( const MParList *pList ) { return kTRUE; }
  virtual Bool_t ReInitHists(       MParList *pList ) { return kTRUE; }
  virtual Bool_t FillHists  ( const MParContainer *par, const Stat_t w=1) { return kTRUE; }
  virtual Bool_t FinalizeHists()                      { return kTRUE;  }
  
  virtual void   FinalizeBadPixels() { }
  
  virtual void   CalcAverageSigma();
  
  virtual void   InitHiGainArrays( const Int_t npix, const Int_t nareas, const Int_t nsectors );
  virtual void   InitLoGainArrays( const Int_t npix, const Int_t nareas, const Int_t nsectors );

  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  ( MHCalibrationPix &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  ( MHCalibrationPix &hist, 
                         MCalibrationPix &pix, 
                         MBadPixelsPix &bad, 
                         MBadPixelsPix::UncalibratedType_t fittyp,
                         MBadPixelsPix::UncalibratedType_t osctyp);

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

  Bool_t IsAverageing  () const  { return TESTBIT(fFlags,kAverageing);   }
  Bool_t IsDebug       () const  { return TESTBIT(fFlags,kDebug);        }  
  Bool_t IsLoGain      () const  { return TESTBIT(fFlags,kLoGain);       }
  Bool_t IsOscillations() const  { return TESTBIT(fFlags,kOscillations); }
  Bool_t IsSizeCheck   () const  { return TESTBIT(fFlags,kSizeCheck);    }
  
  Int_t ReadEnv        ( const TEnv &env, TString prefix, Bool_t print);

public:

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

  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 ( );

  virtual void ResetHists();
  
  // Clone
  TObject *Clone(const char *name="") 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 { return kTRUE; }
  void   DrawPixelContent( Int_t num )  const  {}

  const Int_t              GetAverageAreas       ()          const;	 
        MHCalibrationPix  &GetAverageHiGainArea  (UInt_t i);
  const MHCalibrationPix  &GetAverageHiGainArea  (UInt_t i)  const;
        MHCalibrationPix  &GetAverageLoGainArea  (UInt_t i);
  const MHCalibrationPix  &GetAverageLoGainArea  (UInt_t i)  const;
        MHCalibrationPix  &GetAverageHiGainSector(UInt_t i);
  const MHCalibrationPix  &GetAverageHiGainSector(UInt_t i)  const;
        MHCalibrationPix  &GetAverageLoGainSector(UInt_t i);
  const MHCalibrationPix  &GetAverageLoGainSector(UInt_t i)  const;
  const Int_t              GetAverageSectors     ()          const;
  const MCalibrationCam::PulserColor_t GetColor   ()     const  { return fColor;                    }
  const Float_t        GetNumHiGainSaturationLimit()     const  { return fNumHiGainSaturationLimit; }
  const Float_t        GetNumLoGainSaturationLimit()     const  { return fNumLoGainSaturationLimit; }
  const TArrayI       &GetRunNumbers         ()          const { return fRunNumbers;            }
  const Int_t          GetSize               ()          const;

        MHCalibrationPix  &operator[]            (UInt_t i);
  const MHCalibrationPix  &operator[]            (UInt_t i)  const;
        MHCalibrationPix  &operator()            (UInt_t i);
  const MHCalibrationPix  &operator()            (UInt_t i)  const;
 
  void SetColor                   ( const MCalibrationCam::PulserColor_t color) { fColor = color; }
  void SetAverageing              ( const Bool_t b=kTRUE ) { b 
								? SETBIT(fFlags,kAverageing) 
								: CLRBIT(fFlags,kAverageing); }
  void SetDebug                   ( const Bool_t b=kTRUE ) { b 
								? SETBIT(fFlags,kDebug) 
								: CLRBIT(fFlags,kDebug); }
  void SetLoGain                  ( const Bool_t b=kTRUE ) { b 
								? SETBIT(fFlags,kLoGain) 
								: CLRBIT(fFlags,kLoGain); }
  void SetOscillations            ( const Bool_t b=kTRUE ) { b 
								? SETBIT(fFlags,kOscillations) 
								: CLRBIT(fFlags,kOscillations); }
  void SetSizeCheck               ( const Bool_t b=kTRUE ) { b 
								? SETBIT(fFlags,kSizeCheck) 
								: CLRBIT(fFlags,kSizeCheck); }
  void SetHistName  ( const char *name )  { fHistName  = name;  }
  void SetHistTitle ( const char *name )  { fHistTitle = name;  }
  void SetHistXTitle( const char *name )  { fHistXTitle = name; }
  void SetHistYTitle( const char *name )  { fHistYTitle = name; }
   
  void SetNbins                   ( const Int_t  i )       { fNbins   = i; }
  void SetFirst                   ( const Axis_t f )       { fFirst   = f; }
  void SetLast                    ( const Axis_t f )       { fLast    = f; }  

  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









