/* ======================================================================== *\
!
! *
! * This file is part of MARS, the MAGIC Analysis and Reconstruction
! * Software. It is distributed to you in the hope that it can be a useful
! * and timesaving tool in analysing Data of imaging Cerenkov telescopes.
! * It is distributed WITHOUT ANY WARRANTY.
! *
! * Permission to use, copy, modify and distribute this software and its
! * documentation for any purpose is hereby granted without fee,
! * provided that the above copyright notice appear in all copies and
! * that both that copyright notice and this permission notice appear
! * in supporting documentation. It is provided "as is" without express
! * or implied warranty.
! *
!
!
!   Author(s): Thomas Bretz  12/2000 <mailto:tbretz@atsro.uni-wuerzburh.de>
!   Author(s): Markus Gaug   02/2004 <mailto:markus@ifae.es>
!
!   Copyright: MAGIC Software Development, 2000-2004
!
!
\* ======================================================================== */

/////////////////////////////////////////////////////////////////////////////
//
// MHPedestalCam
//
// Fills the extracted pedestals of MExtractedSignalCam into
// the MHCalibrationPix-classes MHPedestalPix for every:
//
// - Pixel, stored in the TObjArray's MHCalibrationCam::fHiGainArray
//   or MHCalibrationCam::fHiGainArray, respectively
//
// - Average pixel per AREA index (e.g. inner and outer for the MAGIC camera),
//   stored in the TObjArray's MHCalibrationCam::fAverageHiGainAreas and
//   MHCalibrationCam::fAverageHiGainAreas
//
// - Average pixel per camera SECTOR (e.g. sectors 1-6 for the MAGIC camera),
//   stored in the TObjArray's MHCalibrationCam::fAverageHiGainSectors
//   and MHCalibrationCam::fAverageHiGainSectors
//
// Every pedestal is directly taken from MExtractedSignalCam, filled by the
// appropriate extractor.
//
// The pedestals are filled into a histogram and an array, in order to perform
// a Fourier analysis (see MHGausEvents). The signals are moreover averaged on an
// event-by-event basis and written into the corresponding average pixels.
//
// The histograms are fitted to a Gaussian, mean and sigma with its errors
// and the fit probability are extracted. If none of these values are NaN's and
// if the probability is bigger than MHGausEvents::fProbLimit (default: 0.5%),
// the fit is declared valid.
// Otherwise, the fit is repeated within ranges of the previous mean
// +- MHCalibrationPix::fPickupLimit (default: 5) sigma (see MHCalibrationPix::RepeatFit())
// In case this does not make the fit valid, the histogram means and RMS's are
// taken directly (see MHCalibrationPix::BypassFit()).
//
// Outliers of more than MHCalibrationPix::fPickupLimit (default: 5) sigmas
// from the mean are counted as Pickup events (stored in MHCalibrationPix::fPickup)
//
// The number of summed FADC slices is taken to re-normalize
// the result to a pedestal per pixel with the formulas (see MHPedestalPix::Renorm()):
// - Mean Pedestal        / slice = Mean Pedestal        / Number slices
// - Mean Pedestal Error  / slice = Mean Pedestal Error  / Number slices
// - Sigma Pedestal       / slice = Sigma Pedestal       / Sqrt (Number slices)
// - Sigma Pedestal Error / slice = Sigma Pedestal Error / Sqrt (Number slices)
//
// The class also fills arrays with the signal vs. event number, creates a fourier
// spectrum (see MHGausEvents::CreateFourierSpectrum()) and investigates if the
// projected fourier components follow an exponential distribution.
//
// This same procedure is performed for the average pixels.
//
// The following results are written into MPedestalCam:
//
// - MCalibrationPix::SetMean()
// - MCalibrationPix::SetMeanErr()
// - MCalibrationPix::SetSigma()
// - MCalibrationPix::SetSigmaErr()
// - MCalibrationPix::SetProb()
// - MCalibrationPix::SetNumPickup()
//
// For all averaged areas, the fitted sigma is multiplied with the square root of
// the number involved pixels in order to be able to compare it to the average of
// sigmas in the camera.
//
/////////////////////////////////////////////////////////////////////////////
#include "MHPedestalCam.h"
#include "MHPedestalPix.h"

#include "MBadPixelsCam.h"
#include "MBadPixelsPix.h"

#include "MLog.h"
#include "MLogManip.h"

#include "MParList.h"

#include "MExtractedSignalCam.h"
#include "MExtractedSignalPix.h"

#include "MPedestalCam.h"
#include "MPedestalPix.h"
#include "MCalibrationPix.h"

#include "MGeomCam.h"
#include "MGeomPix.h"

#include "MCalibrationPedCam.h"

#include "TH1.h"
#include "TH1F.h"

#include <TOrdCollection.h>

ClassImp(MHPedestalCam);

using namespace std;

const Int_t      MHPedestalCam::fgNbins    = 100;
const Axis_t     MHPedestalCam::fgFirst    = -50.;
const Axis_t     MHPedestalCam::fgLast     =  50.;
const TObjString MHPedestalCam::gsHistName   = "Pedestal";
const TObjString MHPedestalCam::gsHistTitle  = "Pedestal";
const TObjString MHPedestalCam::gsHistXTitle = "Charge [FADC slices]";
const TObjString MHPedestalCam::gsHistYTitle = "Nr. events";
// --------------------------------------------------------------------------
//
// Default constructor. 
//
// Initializes:
// - fExtractHiGainSlices to 0.
// - the event frequency to 1200 Hz.
// - the fRenorm flag to kFALSE
//
// - fNbins to fgNbins
// - fFirst to fgFirst
// - fLast  to fgLast 
//
// - fHistName   to gsHistName  
// - fHistTitle  to gsHistTitle 
// - fHistXTitle to gsHistXTitle
// - fHistYTitle to gsHistYTitle
//
MHPedestalCam::MHPedestalCam(const char *name, const char *title) 
    : fNumEvents(0), fExtractHiGainSlices(0.)
{

  fName  = name  ? name  : "MHPedestalCam";
  fTitle = title ? title : "Class to fill the pedestal histograms";
  
  SetPulserFrequency(1200);
  SetRenorm(kTRUE);
  SetLoGain(kFALSE);

  SetNbins(fgNbins);
  SetFirst(fgFirst);
  SetLast (fgLast );

  SetHistName  (gsHistName  .GetName());
  SetHistTitle (gsHistTitle .GetName());
  SetHistXTitle(gsHistXTitle.GetName());
  SetHistYTitle(gsHistYTitle.GetName());
}

// --------------------------------------------------------------------------
//
// Calls MHCalibrationCam::ResetHists()
//
// Resets:
// - fSum
// - fSum2
// - fAreaSum
// - fAreaSum2
// - fAreaVal
// - fSectorSum
// - fSectorSum2
// - fSectorVal
//
void MHPedestalCam::ResetHists()
{
  
  MHCalibrationCam::ResetHists();
  
  fNumEvents = 0;
  
  // If the size is yet set, set the size
  if (fSum.GetSize()>0)
    {
      // Reset contents of arrays.
      fSum.Reset();
      fSum2.Reset();
      
      fAreaSum. Reset();
      fAreaSum2.Reset();
      fAreaVal.Reset();
      
      fSectorSum. Reset();
      fSectorSum2.Reset();
      fSectorVal.Reset();
    }
}

// --------------------------------------------------------------------------
//
// Creates new MHCalibrationChargeCam only with the averaged areas:
// the rest has to be retrieved directly, e.g. via: 
//     MHPedestalCam *cam = MParList::FindObject("MHPedestalCam");
//  -  cam->GetAverageSector(5).DrawClone();
//  -  (*cam)[100].DrawClone()
//
TObject *MHPedestalCam::Clone(const char *) const
{

  MHPedestalCam *cam = new MHPedestalCam();

  //
  // Copy the data members
  //
  cam->fRunNumbers             = fRunNumbers;
  cam->fPulserFrequency        = fPulserFrequency;
  cam->fFlags                  = fFlags;
  cam->fNbins                  = fNbins;
  cam->fFirst                  = fFirst;
  cam->fLast                   = fLast;

  if (!IsAverageing())
    return cam;

  const Int_t navhi   =  fAverageHiGainAreas->GetSize();

  for (int i=0; i<navhi; i++)
    cam->fAverageHiGainAreas->AddAt(GetAverageHiGainArea(i).Clone(),i);

  return cam;
}

// --------------------------------------------------------------------------
//
// Searches pointer to:
// - MPedestalCam
// - MExtractedSignalCam
//
// Searches or creates:
// - MCalibrationPedCam
//
// Retrieves from MExtractedSignalCam:
// - number of used High Gain FADC slices (MExtractedSignalCam::GetNumUsedHiGainFADCSlices())
//
// Initializes, if empty to MGeomCam::GetNumPixels():
// - MHCalibrationCam::fHiGainArray
//
// Initializes, if empty to MGeomCam::GetNumAreas() for:
// - MHCalibrationCam::fAverageHiGainAreas
//
// Initializes, if empty to MGeomCam::GetNumSectors() for:
// - MHCalibrationCam::fAverageHiGainSectors
// 
// Calls MHCalibrationCam::InitPedHists() for every entry in:
// - MHCalibrationCam::fHiGainArray
// - MHCalibrationCam::fAverageHiGainAreas
// - MHCalibrationCam::fAverageHiGainSectors
//
// Sets Titles and Names for the Histograms 
// - MHCalibrationCam::fAverageHiGainAreas
// 
Bool_t MHPedestalCam::ReInitHists(MParList *pList)
{

  MExtractedSignalCam *signal = (MExtractedSignalCam*)pList->FindObject("MExtractedSignalCam");
  if (!signal)
    {
      *fLog << err << "Cannot find MExtractedSignalCam... abort." << endl;
      return kFALSE;
    }
  

  fPedestals = (MPedestalCam*)pList->FindObject("MPedestalCam");

  if (!fPedestals)
    *fLog << warn << "Cannot find MPedestalCam ..." << endl;

  const Int_t npixels  = fGeom->GetNumPixels();
  const Int_t nsectors = fGeom->GetNumSectors();
  const Int_t nareas   = fGeom->GetNumAreas();

  fCam = (MCalibrationCam*)pList->FindObject("MCalibrationPedCam");
  if (!fCam)
  {
      fCam = (MCalibrationCam*)pList->FindCreateObj(AddSerialNumber("MCalibrationPedCam"));
      if (!fCam)
          return kFALSE;

      fCam->Init(*fGeom);
  }
  
  Float_t sliceshi = signal->GetNumUsedHiGainFADCSlices();

  if (sliceshi == 0.)
    {
      *fLog << err << "Number of used signal slices in MExtractedSignalCam is zero  ... abort." 
           << endl;
      return kFALSE;
    }

  if (fExtractHiGainSlices != 0. && sliceshi != fExtractHiGainSlices )
    {
      *fLog << err << "Number of used High Gain signal slices changed in MExtractedSignalCam  ... abort." 
           << endl;
      return kFALSE;
    }

  fExtractHiGainSlices = sliceshi;

  *fLog << endl;
  *fLog << inf << GetDescriptor() 
       << ": Number of found High Gain signal slices: " << fExtractHiGainSlices << endl;

  InitHiGainArrays(npixels,nareas,nsectors);

  if (fSum.GetSize()==0)
    {
      fSum.       Set(npixels);
      fSum2.      Set(npixels);
      fAreaSum.   Set(nareas);
      fAreaSum2.  Set(nareas);
      fAreaVal.  Set(nareas);
      fSectorSum. Set(nsectors);
      fSectorSum2.Set(nsectors);
      fSectorVal.Set(nsectors);
    }

  fNumEvents = 0;

  return kTRUE;
}


// -------------------------------------------------------------------------------
//
// Retrieves pointer to MExtractedSignalCam:
//
// Retrieves from MGeomCam:
// - number of pixels
// - number of pixel areas
// - number of sectors
//
// Fills HiGain histograms (MHGausEvents::FillHistAndArray()), respectively
// with the signals MExtractedSignalCam::GetExtractedSignalHiGain().
//
Bool_t MHPedestalCam::FillHists(const MParContainer *par, const Stat_t w)
{

  MExtractedSignalCam *signal = (MExtractedSignalCam*)par;
  if (!signal)
    {
      *fLog << err << "No argument in MExtractedSignalCam::Fill... abort." << endl;
      return kFALSE;
    }
  
  const UInt_t npixels  = fGeom->GetNumPixels();
  const UInt_t nareas   = fGeom->GetNumAreas();
  const UInt_t nsectors = fGeom->GetNumSectors();

  MArrayF sumareahi(nareas);
  MArrayF sumsectorhi(nsectors);
  MArrayI numareahi(nareas);
  MArrayI numsectorhi(nsectors);

  for (UInt_t i=0; i<npixels; i++)
  {

      MHCalibrationPix &histhi = (*this)[i];

      if (histhi.IsExcluded())
          continue;

      const MExtractedSignalPix &pix = (*signal)[i];

      const Float_t pedhi = pix.GetExtractedSignalHiGain();

      const Int_t aidx   = (*fGeom)[i].GetAidx();
      const Int_t sector = (*fGeom)[i].GetSector();

      histhi.FillHistAndArray(pedhi) ;

      fSum[i]            += pedhi;
      fAreaSum[aidx]     += pedhi;
      fSectorSum[sector] += pedhi;      

      const Float_t sqrsum  = pedhi*pedhi;
      fSum2[i]            += sqrsum;
      fAreaSum2[aidx]     += sqrsum;
      fSectorSum2[sector] += sqrsum;      

      sumareahi  [aidx]   += pedhi;
      numareahi  [aidx]   ++;
      sumsectorhi[sector] += pedhi;
      numsectorhi[sector] ++;

    }
  
  for (UInt_t j=0; j<nareas; j++)
    {
      MHCalibrationPix &histhi = GetAverageHiGainArea(j);
      histhi.FillHistAndArray(numareahi[j] == 0 ? 0. : sumareahi[j]/numareahi[j]);
    }
  
  for (UInt_t j=0; j<nsectors; j++)
    {
      MHCalibrationPix &histhi = GetAverageHiGainSector(j);
      histhi.FillHistAndArray(numsectorhi[j] == 0 ? 0. : sumsectorhi[j]/numsectorhi[j]);

    }
  
  fNumEvents++;

  return kTRUE;
}

// --------------------------------------------------------------------------
//
// Calls:
// - MHCalibrationCam::FitHiGainArrays() with Bad Pixels flags 0
// 
Bool_t MHPedestalCam::FinalizeHists()
{
  
  if (fNumEvents <= 1)
    {
      *fLog << err << GetDescriptor()
            << ": Number of processed events smaller or equal to 1" << endl;
      return kFALSE;
    }
  
  FitHists();

  if (fRenorm)
    RenormResults();

  return kTRUE;
  
}

void MHPedestalCam::FitHists()
{

  for (Int_t i=0; i<fHiGainArray->GetSize(); i++)
    {
      
      MHCalibrationPix &hist = (*this)[i];
      MCalibrationPix &pix   = (*fCam)[i];
      
      if (hist.IsEmpty() || hist.IsOnlyOverflow() || hist.IsOnlyUnderflow())
        continue;
      
      //
      // 2) Fit the Hi Gain histograms with a Gaussian
      //
      hist.FitGaus();
      //
      // 3) Take histogram means and RMS
      //
      hist.BypassFit();
      //
      // 4) Check for oscillations
      // 
      if (IsOscillations())
        hist.CreateFourierSpectrum();
      //
      // 5) Retrieve the results and store them in this class
      //
      pix.SetHiGainMean       ( hist.GetMean()      );
      pix.SetHiGainMeanVar    ( hist.GetMeanErr() * hist.GetMeanErr()   );
      pix.SetHiGainRms        ( hist.GetHistRms()   );
      pix.SetHiGainSigma      ( hist.GetSigma()     );
      pix.SetHiGainSigmaVar   ( hist.GetSigmaErr()* hist.GetSigmaErr()  );
      pix.SetHiGainProb       ( hist.GetProb()      );
      pix.SetHiGainNumBlackout( hist.GetBlackout()  );
      pix.SetHiGainNumPickup  ( hist.GetPickup()    );
      //
      // 6) Store calculated means and variances in the low-gain slices
      //
      pix.SetLoGainMean    ( fSum[i] / fNumEvents  );
      pix.SetLoGainSigma   ( TMath::Sqrt( (fSum2[i] - fSum[i]*fSum[i]/fNumEvents) / (fNumEvents-1) ));
      pix.SetLoGainMeanVar ( pix.GetLoGainSigma() * pix.GetLoGainSigma() / fNumEvents  );
      pix.SetLoGainSigmaVar( pix.GetLoGainMeanVar() / 4. );
    }

  if (!IsAverageing())
    return;
  
  for (Int_t j=0; j<fAverageHiGainAreas->GetSize(); j++)
    {
      
      MHCalibrationPix &hist = GetAverageHiGainArea(j);      
      MCalibrationPix  &pix  = fCam->GetAverageArea(j);

      if (hist.IsEmpty() || hist.IsOnlyOverflow() || hist.IsOnlyUnderflow())
        continue;
      
      //
      // 2) Fit the Hi Gain histograms with a Gaussian
      //
      hist.FitGaus();
      //
      // 3) Take histogram means and RMS
      //
      hist.BypassFit();
      //
      // 4) Check for oscillations
      // 
      if (IsOscillations())
        hist.CreateFourierSpectrum();
      //
      // 5) Retrieve the results and store them in this class
      //
      pix.SetHiGainMean       ( hist.GetMean()      );
      pix.SetHiGainMeanVar    ( hist.GetMeanErr() * hist.GetMeanErr()   );
      pix.SetHiGainRms        ( hist.GetHistRms()   );
      pix.SetHiGainSigma      ( hist.GetSigma()     );
      pix.SetHiGainSigmaVar   ( hist.GetSigmaErr()* hist.GetSigmaErr()  );
      pix.SetHiGainProb       ( hist.GetProb()      );
      pix.SetHiGainNumBlackout( hist.GetBlackout()  );
      pix.SetHiGainNumPickup  ( hist.GetPickup()    );
      //
      // 6) Store calculated means and variances in the low-gain slices
      //
      const ULong_t aevts = fNumEvents * fAreaVal[j];
      if (aevts <= 1)
        continue;
      pix.SetLoGainMean ( fAreaSum[j] / aevts  );
      pix.SetLoGainSigma( TMath::Sqrt( (fAreaSum2[j] - fAreaSum[j]*fAreaSum[j]/aevts) / (aevts-1) ));
    }
  
  for (Int_t j=0; j<fAverageHiGainSectors->GetSize(); j++)
    {
      MHCalibrationPix &hist = GetAverageHiGainSector(j);      
      MCalibrationPix  &pix  = fCam->GetAverageSector(j);

      if (hist.IsEmpty() || hist.IsOnlyOverflow() || hist.IsOnlyUnderflow())
        continue;
      
      //
      // 2) Fit the Hi Gain histograms with a Gaussian
      //
      hist.FitGaus();
      //
      // 3) Take histogram means and RMS
      //
      hist.BypassFit();
      //
      // 4) Check for oscillations
      // 
      if (IsOscillations())
        hist.CreateFourierSpectrum();
      //
      // 5) Retrieve the results and store them in this class
      //
      pix.SetHiGainMean       ( hist.GetMean()      );
      pix.SetHiGainMeanVar    ( hist.GetMeanErr() * hist.GetMeanErr()   );
      pix.SetHiGainRms        ( hist.GetHistRms()   );
      pix.SetHiGainSigma      ( hist.GetSigma()     );
      pix.SetHiGainSigmaVar   ( hist.GetSigmaErr()* hist.GetSigmaErr()  );
      pix.SetHiGainProb       ( hist.GetProb()      );
      pix.SetHiGainNumBlackout( hist.GetBlackout()  );
      pix.SetHiGainNumPickup  ( hist.GetPickup()    );
      //
      // 6) Store calculated means and variances in the low-gain slices
      //
      const ULong_t sevts = fNumEvents * fSectorVal[j];
      if (sevts <= 1)
        continue;
      pix.SetLoGainMean ( fAreaSum[j] / sevts  );
      pix.SetLoGainSigma( TMath::Sqrt( (fAreaSum2[j] - fAreaSum[j]*fAreaSum[j]/sevts) / (sevts-1) ));
    }
}

// --------------------------------------------------------------------------
//
// Renormalizes the pedestal fit results by the following formulae:
//
// - Mean Pedestal        / slice -> Mean Pedestal        / Number slices
// - Mean Pedestal Error  / slice -> Mean Pedestal Error  / Number slices
// - Sigma Pedestal       / slice -> Sigma Pedestal       / Sqrt (Number slices)
// - Sigma Pedestal Error / slice -> Sigma Pedestal Error / Sqrt (Number slices)
// 
void MHPedestalCam::RenormResults()
{

  //
  // One never knows...
  //
  if (fExtractHiGainSlices <= 0)
    return;

  const Float_t sqslices = TMath::Sqrt(fExtractHiGainSlices);

  for (Int_t i=0; i<fHiGainArray->GetSize(); i++)
    {
      
      MCalibrationPix &pix = (*fCam)[i];
      pix.SetHiGainMean     ( pix.GetHiGainMean()     / fExtractHiGainSlices  );
      pix.SetLoGainMean     ( pix.GetLoGainMean()     / fExtractHiGainSlices  );
      //
      // Mean error goes with PedestalRMS/Sqrt(entries) -> scale with sqrt(slices)
      // 
      pix.SetHiGainMeanVar  ( pix.GetHiGainMeanVar()  / fExtractHiGainSlices );
      pix.SetLoGainMeanVar  ( pix.GetHiGainMeanVar()  / fExtractHiGainSlices );
      //
      // Sigma goes like PedestalRMS -> scale with sqrt(slices)    
      //
      pix.SetHiGainSigma    ( pix.GetHiGainSigma()    / sqslices  );
      pix.SetLoGainSigma    ( pix.GetLoGainSigma()    / sqslices  );
      //
      // Sigma error goes like PedestalRMS/2.(entries) -> scale with sqrt(slices)
      //
      pix.SetHiGainSigmaVar ( pix.GetHiGainSigmaVar() / fExtractHiGainSlices );
      pix.SetLoGainSigmaVar ( pix.GetLoGainSigmaVar() / fExtractLoGainSlices );
    }

  if (!IsAverageing())
    return;
  
  for (Int_t j=0; j<fAverageHiGainAreas->GetSize(); j++)
    {
      
      MCalibrationPix  &pix  = fCam->GetAverageArea(j);
      pix.SetHiGainMean     ( pix.GetHiGainMean()     / fExtractHiGainSlices  );
      pix.SetLoGainMean     ( pix.GetLoGainMean()     / fExtractHiGainSlices  );
      pix.SetHiGainMeanVar  ( pix.GetHiGainMeanVar()  / fExtractHiGainSlices  );
      pix.SetHiGainSigma    ( pix.GetHiGainSigma()    / sqslices  );
      pix.SetLoGainSigma    ( pix.GetLoGainSigma()    / sqslices  );
      pix.SetHiGainSigmaVar ( pix.GetHiGainSigmaVar() / fExtractHiGainSlices  );
  }
  
  for (Int_t j=0; j<fAverageHiGainSectors->GetSize(); j++)
    {
      MCalibrationPix  &pix  = fCam->GetAverageSector(j);
      pix.SetHiGainMean     ( pix.GetHiGainMean()     / fExtractHiGainSlices  );
      pix.SetLoGainMean     ( pix.GetLoGainMean()     / fExtractHiGainSlices  );
      pix.SetHiGainMeanVar  ( pix.GetHiGainMeanVar()  / fExtractHiGainSlices  );
      pix.SetHiGainSigma    ( pix.GetHiGainSigma()    / sqslices  );
      pix.SetLoGainSigma    ( pix.GetLoGainSigma()    / sqslices  );
      pix.SetHiGainSigmaVar ( pix.GetHiGainSigmaVar() / fExtractHiGainSlices  );
    }

}


// ------------------------------------------------------------------
//
// The types are as follows:
// 
// Fitted values:
// ============== 
//
// 0: Fitted Charge
// 1: Error of fitted Charge
// 2: Sigma of fitted Charge
// 3: Error of Sigma of fitted Charge
//
//
// Useful variables derived from the fit results:
// =============================================
//
// 4: Returned probability of Gauss fit to Charge distribution
// 5: Relative differenc of calculated pedestal (per slice) and fitted (per slice)
// 6: Error of the Relative differenc of calculated pedestal (per slice) and fitted (per slice)
// 7: Relative difference of the error of the mean pedestal (per slice) - calculated and fitted
// 8: Relative differenc of calculated pedestal RMS (per slice) and fitted sigma (per slice)
// 9: Error of Relative differenc of calculated pedestal RMS (per slice) and fitted sigma (per slice)
// 10: Relative difference of the error of the pedestal RMS (per slice) - calculated and fitted
//
// Localized defects:
// ==================
//
// 11: Gaus fit not OK
// 12: Fourier spectrum not OK
//
Bool_t MHPedestalCam::GetPixelContent(Double_t &val, Int_t idx, const MGeomCam &cam, Int_t type) const
{

  if (fHiGainArray->GetSize() <= idx)
    return kFALSE;

  if ((*this)[idx].IsExcluded())
    return kFALSE;

  const Float_t ped      = (*fPedestals)[idx].GetPedestal();
  const Float_t rms      = (*fPedestals)[idx].GetPedestalRms();

  const Float_t entsqr    =  TMath::Sqrt((Float_t)fPedestals->GetTotalEntries());

  const Float_t pederr   = rms/entsqr;
  const Float_t rmserr   = rms/entsqr/2.;

  const Float_t mean     = (*this)[idx].GetMean();
  const Float_t meanerr  = (*this)[idx].GetMeanErr();
  const Float_t sigma    = (*this)[idx].GetSigma() ;
  const Float_t sigmaerr = (*this)[idx].GetSigmaErr();

  switch (type)
    {
    case 0:
      val = mean;
      break;
    case 1:
      val = meanerr;
      break;
    case 2:
      val = sigma;
      break;
    case 3:
      val = sigmaerr;
      break;
    case 4:
      val = (*this)[idx].GetProb();
      break;
    case 5:
      val = 2.*(mean-ped)/(ped+mean);
      break;
    case 6:
      val = TMath::Sqrt((pederr*pederr + meanerr*meanerr) * (ped*ped + mean*mean))
            *2./(ped+mean)/(ped+mean);
      break;
    case 7:
      val = 2.*(meanerr-pederr)/(pederr + meanerr);
      break;
    case 8:
      val = 2.*(sigma-rms)/(sigma+rms);
      break;
    case 9:
      val = TMath::Sqrt((rmserr*rmserr + sigmaerr*sigmaerr) * (rms*rms + sigma*sigma))
            *2./(rms+sigma)/(rms+sigma);
      break;
    case 10:
      val = 2.*(sigmaerr - rmserr)/(sigmaerr + rmserr);
      break;
    case 11:
      if (!(*this)[idx].IsGausFitOK())
        val = 1.;
      break;
    case 12:
      if (!(*this)[idx].IsFourierSpectrumOK())
        val = 1.;
      break;
    default:
      return kFALSE;
    }
  return kTRUE;
}

// --------------------------------------------------------------------------
//
// Calls MHGausEvents::DrawClone() for pixel idx
//
void MHPedestalCam::DrawPixelContent(Int_t idx) const
{
  (*this)[idx].DrawClone();
}
