/* ======================================================================== *\
!
! *
! * 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): Markus Gaug   11/2003 <mailto:markus@ifae.es>
!
!   Copyright: MAGIC Software Development, 2000-2004
!
!
\* ======================================================================== */
/////////////////////////////////////////////////////////////////////////////
//                                                               
// MCalibrationTestCam                                               
//                                                               
// Storage container for calibrated photons, with calibration applied on the 
// same calibration run (see MHCalibrationTestCam and MHCalibrationTestPix).
//
// Contains TClonesArrays for the following objects:
// - fPixels:         Array of classes derived from MCalibrationTestPix, one entry 
//                    per pixel.
// - fAverageAreas:   Array of classes derived from MCalibrationTestPix, one entry
//                    per pixel AREA. 
// - fAverageSectors: Array of classes derived from MCalibrationTestPix, one entry
//                    per camera SECTOR. 
//
// Averaged values over one whole area index (e.g. inner or outer pixels for 
// the MAGIC camera), can be retrieved via: 
// MCalibrationTestPix &avpix = fTestCam->GetAverageArea(i)
//
// Averaged values over one whole camera sector can be retrieved via: 
// MCalibrationTestPix &avpix = fTestCam->GetAverageSector(i)
//
// See also: MCalibrationTestPix, MCalibrationTestCalc, MCalibrationQECam
//           MHCalibrationTestPix, MHCalibrationTestCam              
//
/////////////////////////////////////////////////////////////////////////////
#include "MCalibrationTestCam.h"
#include "MCalibrationTestPix.h"

#include <TClonesArray.h>

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

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

ClassImp(MCalibrationTestCam);

using namespace std;
// --------------------------------------------------------------------------
//
// Default constructor. 
//
// Sets all pointers to 0
// 
// Creates a TClonesArray of MCalibrationTestPix containers, initialized to 1 entry, destinated 
// to hold one container per pixel. Later, a call to MCalibrationTestCam::InitSize() 
// has to be performed (in MGeomApply). 
//
// Creates a TClonesArray of MCalibrationTestPix containers, initialized to 1 entry, destinated 
// to hold one container per pixel AREA. Later, a call to MCalibrationTestCam::InitAreas() 
// has to be performed (in MGeomApply). 
//
// Creates a TClonesArray of MCalibrationTestPix containers, initialized to 1 entry, destinated
// to hold one container per camera SECTOR. Later, a call to MCalibrationTestCam::InitSectors() 
// has to be performed (in MGeomApply). 
//
// Calls:
// - Clear()
//
MCalibrationTestCam::MCalibrationTestCam(const char *name, const char *title)
{

  fName  = name  ? name  : "MCalibrationTestCam";
  fTitle = title ? title : "Storage container for the Calibration Test Information in the camera";
  
  fPixels           = new TClonesArray("MCalibrationTestPix",1);
  fAverageAreas     = new TClonesArray("MCalibrationTestPix",1);
  fAverageSectors   = new TClonesArray("MCalibrationTestPix",1);

  Clear();
}

// --------------------------------------------------------------------------
//
// Deletes the following TClonesArray's of MCalibrationPix containers (if exist):
// - fPixels
// - fAverageAreas
// - fAverageSectors
//  
MCalibrationTestCam::~MCalibrationTestCam()
{

  delete fPixels;
  delete fAverageAreas;
  delete fAverageSectors;
  
}

// --------------------------------------
//
// Sets all variable to 0.
// Sets all flags to kFALSE
// Calls MCalibrationCam::Clear()
//
void MCalibrationTestCam::Clear(Option_t *o)
{

  fNumUninterpolatedInMaxCluster = 0; 

  {  fPixels        ->ForEach(TObject, Clear)();  }
  {  fAverageAreas  ->ForEach(TObject, Clear)();  }
  {  fAverageSectors->ForEach(TObject, Clear)();  }
  
  return;
}

// -------------------------------------------------------------------
//
// Calls TClonesArray::ExpandCreate() for fPixels
//
void MCalibrationTestCam::InitSize(const UInt_t i)
{
  fPixels->ExpandCreate(i);
}

// -------------------------------------------------------------------
//
// Calls TClonesArray::ExpandCreate() for:
// - fAverageAreas
//
void MCalibrationTestCam::InitAverageAreas(const UInt_t i)
{

  fAverageAreas->ExpandCreate(i);

  for (UInt_t j=0; j<i; j++)
    GetAverageArea(j).SetPixId(j);
  
  fNumUninterpolated.Set(i);
}

// -------------------------------------------------------------------
//
// Calls TClonesArray::ExpandCreate() for:
// - fAverageSectors
//
void MCalibrationTestCam::InitAverageSectors(const UInt_t i)
{

  fAverageSectors->ExpandCreate(i);

  for (UInt_t j=0; j<i; j++)
    GetAverageSector(j).SetPixId(j);

}

// -------------------------------------------------------------------
//
// Calls:
// - InitSize()
// - InitAverageAreas()
// - InitAverageSectors()
//
void MCalibrationTestCam::Init(const MGeomCam &geom)
{

  InitSize          (geom.GetNumPixels() );
  InitAverageAreas  (geom.GetNumAreas()  );
  InitAverageSectors(geom.GetNumSectors());
}

// --------------------------------------------------------------------------
//
// Returns the current size of the TClonesArray fAverageAreas
// independently if the MCalibrationPix is filled with values or not.
//
const Int_t MCalibrationTestCam::GetAverageAreas() const
{
  return fAverageAreas->GetEntriesFast();
}

// --------------------------------------------------------------------------
//
// Returns the current size of the TClonesArray fAverageSectors
// independently if the MCalibrationPix is filled with values or not.
//
const Int_t MCalibrationTestCam::GetAverageSectors() const
{
  return fAverageSectors->GetEntriesFast();
}


// --------------------------------------------------------------------------
//
// Get i-th pixel (pixel number)
//
MCalibrationTestPix &MCalibrationTestCam::operator[](UInt_t i)
{
  return *static_cast<MCalibrationTestPix*>(fPixels->UncheckedAt(i));
}

// --------------------------------------------------------------------------
//
// Get i-th pixel (pixel number)
//
const MCalibrationTestPix &MCalibrationTestCam::operator[](UInt_t i) const
{
  return *static_cast<MCalibrationTestPix*>(fPixels->UncheckedAt(i));
}

// --------------------------------------------------------------------------
//
// Returns the current size of the TClonesArray fPixels 
// independently if the MCalibrationTestPix is filled with values or not.
//
const Int_t MCalibrationTestCam::GetSize() const
{
  return fPixels->GetEntriesFast();
}

// --------------------------------------------------------------------------
//
// Get i-th average pixel (area number)
//
MCalibrationTestPix &MCalibrationTestCam::GetAverageArea(UInt_t i)
{
  return *static_cast<MCalibrationTestPix*>(fAverageAreas->UncheckedAt(i));
}

// --------------------------------------------------------------------------
//
// Get i-th average pixel (area number)
//
const MCalibrationTestPix &MCalibrationTestCam::GetAverageArea(UInt_t i) const 
{
  return *static_cast<MCalibrationTestPix*>(fAverageAreas->UncheckedAt(i));
}

// --------------------------------------------------------------------------
//
// Get i-th average pixel (sector number)
//
MCalibrationTestPix &MCalibrationTestCam::GetAverageSector(UInt_t i)
{
  return *static_cast<MCalibrationTestPix*>(fAverageSectors->UncheckedAt(i));
}

// --------------------------------------------------------------------------
//
// Get i-th average pixel (sector number)
//
const MCalibrationTestPix &MCalibrationTestCam::GetAverageSector(UInt_t i) const 
{
  return *static_cast<MCalibrationTestPix*>(fAverageSectors->UncheckedAt(i));
}

// --------------------------------------------------------------------------
//
// Print first the well fitted pixels 
// and then the ones which are not FitValid
//
void MCalibrationTestCam::Print(Option_t *o) const
{

  *fLog << all << GetDescriptor() << ":" << endl;
  int id = 0;
  
  *fLog << all << "Calibrated (or interpolated) pixels:" << endl;
  *fLog << all << endl;

  TIter Next(fPixels);
  MCalibrationTestPix *pix;
  while ((pix=(MCalibrationTestPix*)Next()))
    {
      
      if (!pix->IsExcluded()) 
	{                            

          *fLog << all 
                << Form("%s%3i","Pixel: ",pix->GetPixId())
		<< Form("%s%4.2f%s%4.2f","  Num.Photons: ",pix->GetNumPhotons(),"+-",pix->GetNumPhotonsErr()) 
		<< Form("%s%4.2f%s%4.2f","  Num.Photons/mm^2: ",pix->GetNumPhotonsPerArea()
                        ,"+-",pix->GetNumPhotonsPerAreaErr()) 
		<< endl;
          id++;
	}
    }
  
  *fLog << all << id << " pixels" << endl;
  id = 0;
  
   
  *fLog << all << endl;
  *fLog << all << "Not interpolated pixels:" << endl;
  *fLog << all << endl;
  
  id = 0;

  TIter Next4(fPixels);
  while ((pix=(MCalibrationTestPix*)Next4()))
  {
      if (pix->IsExcluded())
      {
        *fLog << all << pix->GetPixId() << " ";
        id++;

        if (!(id % 25))
          *fLog << endl;
      }
  }
  
  *fLog << endl;
  *fLog << all << id << " Excluded pixels " << endl;
  *fLog << endl;

  *fLog << all << endl;
  *fLog << all << "Averaged Areas:" << endl;
  *fLog << all << endl;

  TIter Next5(fAverageAreas);
  while ((pix=(MCalibrationTestPix*)Next5()))
  {
    *fLog << all << Form("%s%3i","Area Idx: ",pix->GetPixId())
          << Form("%s%4.2f%s%4.2f","  Num.Photons: ",pix->GetNumPhotons(),"+-",pix->GetNumPhotonsErr()) 
          << Form("%s%4.2f%s%4.2f","  Num.Photons/mm^2: ",pix->GetNumPhotonsPerArea()
                  ,"+-",pix->GetNumPhotonsPerAreaErr()) 
          << endl;
  }

  *fLog << all << endl;
  *fLog << all << "Averaged Sectors:" << endl;
  *fLog << all << endl;

  TIter Next6(fAverageSectors);
  while ((pix=(MCalibrationTestPix*)Next6()))
  {
    *fLog << all << Form("%s%3i","Sector: ",pix->GetPixId())
          << Form("%s%4.2f%s%4.2f","  Num.Photons: ",pix->GetNumPhotons(),"+-",pix->GetNumPhotonsErr()) 
          << Form("%s%4.2f%s%4.2f","  Num.Photons/mm^2: ",pix->GetNumPhotonsPerArea()
                  ,"+-",pix->GetNumPhotonsPerAreaErr()) 
          << endl;
  }
  *fLog << all << endl;
}


// --------------------------------------------------------------------------
//
// The types are as follows:
// 
// 0: Number Photons
// 1: Error Number Photons
// 2: Number photons per area
// 3: Error Number Photons per area
// 4: Pixels which are not interpolateable
//
Bool_t MCalibrationTestCam::GetPixelContent(Double_t &val, Int_t idx, const MGeomCam &cam, Int_t type) const
{

  if (idx > GetSize())
    return kFALSE;

  Float_t area = cam[idx].GetA();

 if (area == 0)
    return kFALSE;

 MCalibrationTestPix &pix = (MCalibrationTestPix&)(*this)[idx];

  switch (type)
    {
    case 0:
      if (pix.IsExcluded())
        return kFALSE;
      val = pix.GetNumPhotons();
      break;
    case 1:
      if (pix.IsExcluded())
        return kFALSE;
      val = pix.GetNumPhotonsErr();
      break;
    case 2:
      if (pix.IsExcluded())
        return kFALSE;
      val = pix.GetNumPhotonsPerArea();
      break;
    case 3:
      if (pix.IsExcluded())
        return kFALSE;
      val = pix.GetNumPhotonsPerAreaErr();
      break;
    case 4:
      if (!pix.IsExcluded())
        return kFALSE;
      val = 1;
      break;
    default:
      return kFALSE;
    }

  return val!=-1.;
}

void  MCalibrationTestCam::SetNumUninterpolated( const UInt_t i, const Int_t aidx ) 
{

  if (aidx < 0)
    return;

  if (aidx < fNumUninterpolated.GetSize())
    fNumUninterpolated[aidx] = i;  
}

