/* ======================================================================== *\
!
! *
! * 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): Javier Lopez    04/2004 <mailto:jlopez@ifae.es>
!   Author(s): Javier Rico     04/2004 <mailto:jrico@ifae.es>
!
!   Copyright: MAGIC Software Development, 2000-2004
!
!
\* ======================================================================== */

//////////////////////////////////////////////////////////////////////////////
//
// MSrcPlace
//
// Abstract task to set the source position in any place in the camera
// It keeps a 2D histogram with the assigned positions, so that the same
// distribution can be applied later to any data set (tipically the OFF data)
//
//  Input Containers:
//    MSrcPosCam
//
//  Output Containers:
//    MSrcPosCam
//    MDCA
//
//////////////////////////////////////////////////////////////////////////////

#include <fstream>
#include <math.h>

#include "TH2F.h"

#include "MParList.h"
#include "MSrcPlace.h"
#include "MSrcPosCam.h"
#include "MDCA.h"

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

ClassImp(MSrcPlace);

using namespace std;

static const TString gsDefName  = "MSrcPlace";
static const TString gsDefTitle = "Set the position of the source";

// -------------------------------------------------------------------------
//
// Default constructor. The first (second) argument is the name of a container
// containing the source position in the camera plain, MScrPosCam (MDCA).
// The default is "MSrcPosCam" ("MDCA"). 
//
MSrcPlace::MSrcPlace(const char* srcPos, const char* dca, const char *name, const char *title)
  : fSrcPos(NULL), fDCA(NULL)
{
    fName  = name  ? name  : gsDefName.Data();
    fTitle = title ? title : gsDefTitle.Data();

    fSrcPosName  = srcPos;
    fDCAName     = dca;

    const Float_t cameraSize   = 600; //[mm]
    const Float_t binPrecision =   1; //[mm] ~ 0.0033 deg

    const UInt_t nbins =  (UInt_t)(cameraSize*2/binPrecision);
    fHistSrcPos = new TH2F("HistSrcPos","",nbins,-cameraSize,cameraSize,nbins,-cameraSize,cameraSize);

    fMode=kOn;
}
// -------------------------------------------------------------------------
//
// Destructor
//
MSrcPlace::~MSrcPlace()
{
  delete fHistSrcPos;
}
// -------------------------------------------------------------------------
//
// Look for/create the needed containers
// Check whether RA and DEC have been initialized
//
Int_t MSrcPlace::SearchForSrcPos(MParList *pList)
{
    // look for/create MSrcPosCam
  fSrcPos = (MSrcPosCam*)pList->FindObject(AddSerialNumber(fSrcPosName), "MSrcPosCam");
  if (!fSrcPos)
    {
      *fLog << warn << AddSerialNumber(fSrcPosName) << " [MSrcPosCam] not found... creating default container." << endl;
      fSrcPos = (MSrcPosCam*)pList->FindCreateObj("MSrcPosCam", AddSerialNumber(fSrcPosName));
      if(!fSrcPos)
	return kFALSE;
    }

  // look for/create MDCA
  fDCA = (MDCA*)pList->FindObject(AddSerialNumber(fDCAName), "MDCA");
  if (!fDCA)
    {
      *fLog << warn << AddSerialNumber(fDCAName) << " [MDCA] not found... creating default container." << endl;
      fDCA = (MDCA*)pList->FindCreateObj("MDCA", AddSerialNumber(fDCAName));
      if(!fDCA)
	return kFALSE;
    }

  return kTRUE;
}

// -------------------------------------------------------------------------
//
// Save the position of the source in the histogram
//
void MSrcPlace::SavePosIntoHisto()
{  
  fHistSrcPos->Fill(fSrcPos->GetX(),fSrcPos->GetY());
}
// -------------------------------------------------------------------------
//
// Read the position of the source from the histogram
//
void MSrcPlace::ReadPosFromHisto()
{  
  Axis_t x;
  Axis_t y;
  
  fHistSrcPos->GetRandom2(x,y);
  fSrcPos->SetXY(x,y);
  fDCA->SetRefPoint(x,y);
}
// -------------------------------------------------------------------------
//
// Look for needed containers
//
Int_t MSrcPlace::PreProcess(MParList* plist)
{  
  return SearchForSrcPos(plist);
}

// -------------------------------------------------------------------------
//
// Call to compute a new position and then save it in the histogram (fMode==kOn) 
// of to read the new position from the histogram (fMode==kOff)
//
Int_t MSrcPlace::Process()
{  
  switch(fMode)
    {
    case kOn:
      if(!ComputeNewSrcPosition())
	return kFALSE;
      SavePosIntoHisto();
      break;
    case kOff:
      ReadPosFromHisto();
      break;
    default:
      *fLog << err << "MSrcPlace::Process Warning: Wrong mode " << fMode << endl;
      return kFALSE;
    }
  return kTRUE;
}

// -------------------------------------------------------------------------
//
// Dump 2D histo statistics
//
Int_t MSrcPlace::PostProcess()
{
  *fLog << inf << endl;
  *fLog << inf << "MSrcPlace::PostProcess Message: Created internal histogram with: ";
  *fLog << inf << "Entries: " << fHistSrcPos->GetEntries() << endl;
  *fLog << inf << "X projection mean: " << fHistSrcPos->ProjectionX()->GetMean() << endl;
  *fLog << inf << "X projection rms:  " << fHistSrcPos->ProjectionX()->GetRMS() << endl;
  *fLog << inf << "Y projection mean: " << fHistSrcPos->ProjectionY()->GetMean() << endl;
  *fLog << inf << "Y projection rms:  " << fHistSrcPos->ProjectionY()->GetRMS() << endl;
  
  return kTRUE;
}
