/* ======================================================================== *\
   !
   ! *
   ! * 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): Abelardo Moralejo 1/2004 <mailto:moralejo@pd.infn.it>
   !              Thomas Bretz  5/2002 <mailto:tbretz@astro.uni-wuerzburg.de>
   !
   !   Copyright: MAGIC Software Development, 2000-2004
   !
   !
   \* ======================================================================== */

/////////////////////////////////////////////////////////////////////////////
//
//  MMCALIBRATE - Calibration of MC data
//
//  This macro is a version of the standard procedure to convert raw MC data 
//  into calibrated data (photons per pixel) 
//
/////////////////////////////////////////////////////////////////////////////

#include "MImgCleanStd.h"

void mccalibrate()
{
  //
  // This is a demonstration program which reads in MC camera files
  // and produces and output with calibrated events (signal in photons
  // for all pixels, in MCerPhotEvt containers).
  //


  // ------------- user change -----------------
  TString* CalibrationFilename;
  CalibrationFilename = new TString("../../gammas_nonoise/Gamma_zbin0_0*.root");
  // File to be used for the calibration (must be a camera file without added noise)

  Char_t* AnalysisFilename = "Gamma_zbin0*.root";  // File to be analyzed

  Char_t* OutFilename      = "calibrated_data.root";       // Output file name


  Int_t BinsHigh[2] = {5, 10}; // First and last FADC bin of the range to be integrated,
  Int_t BinsLow[2]  = {5, 10}; // for high and low gain respectively.

  // -------------------------------------------

  //
  // Create a empty Parameter List and an empty Task List
  // The tasklist is identified in the eventloop by its name
  //
  MParList  plist;

  MTaskList tlist;

  plist.AddToList(&tlist);

  MSrcPosCam src;
  src.SetReadyToSave();
  plist.AddToList(&src);

  MBadPixelsCam badpix;
  plist.AddToList(&badpix);
  

  //
  // Now setup the tasks and tasklist:
  // ---------------------------------
  //
  MReadMarsFile read("Events");

  if (CalibrationFilename)
    read.AddFile(CalibrationFilename->Data());

  read.DisableAutoScheme();

  MGeomApply geom; // Reads in geometry from MC file and sets the right sizes for
  // several parameter containers.

  MMcPedestalCopy   pcopy; 
  // Copies pedestal data from the MC file run fadc header to the MPedestalCam container.

  MExtractSignal    sigextract;
  sigextract.SetSaturationLimit(240);

  // Define ADC slices to be integrated in high and low gain:
  sigextract.SetRange(BinsHigh[0], BinsHigh[1], BinsLow[0], BinsLow[1]);

  MMcCalibrationUpdate  mccalibupdate;

  MCalibrate calib; // Transforms signals from ADC counts into photons.
  calib.SetCalibrationMode(MCalibrate::kFfactor);

  //    MBlindPixelCalc   blind;
  //    blind.SetUseInterpolation();

  //
  // Applies tail cuts to image. Since the calibration is performed on 
  // noiseless camera files, the precise values of the cleaning levels 
  // are unimportant (in any case, only pixels without any C-photon will
  // be rejected).
  //
  MImgCleanStd      clean;


  MHillasCalc       hcalc; // Calculates Hillas parameters not dependent on source position.

  MMcCalibrationCalc mccalibcalc;

  tlist.AddToList(&read);
  tlist.AddToList(&geom);
  tlist.AddToList(&pcopy);

  tlist.AddToList(&sigextract);
  tlist.AddToList(&mccalibupdate);
  tlist.AddToList(&calib);
  tlist.AddToList(&clean);
  //    tlist.AddToList(&blind);
  tlist.AddToList(&hcalc);

  tlist.AddToList(&mccalibcalc);

  //
  // Open output file:
  //
  MWriteRootFile write(OutFilename); // Writes output
  write.AddContainer("MGeomCam",            "RunHeaders");
  write.AddContainer("MMcConfigRunHeader",  "RunHeaders");
  write.AddContainer("MMcCorsikaRunHeader", "RunHeaders");
  write.AddContainer("MMcFadcHeader",       "RunHeaders");
  write.AddContainer("MMcRunHeader",        "RunHeaders");
  write.AddContainer("MMcTrigHeader",       "RunHeaders");
  write.AddContainer("MRawRunHeader",       "RunHeaders");
  write.AddContainer("MSrcPosCam",          "RunHeaders");


  write.AddContainer("MMcEvt",        "Events");
  write.AddContainer("MMcTrig",       "Events");
  write.AddContainer("MRawEvtHeader", "Events");
  write.AddContainer("MCerPhotEvt",   "Events");
  write.AddContainer("MPedPhotCam",   "Events");

  //
  // First loop: Calibration loop
  //

  MProgressBar bar;
  bar.SetWindowName("Calibrating...");

  MEvtLoop evtloop;
  evtloop.SetProgressBar(&bar);
  evtloop.SetParList(&plist);

  if (CalibrationFilename)
    {
      if (!evtloop.Eventloop())
	return;
      mccalibcalc->GetHist()->Write();
    }

  //
  // Second loop: analysis loop
  //

  //
  // Change the read task by another one which reads the file we want to analyze:
  //

  MReadMarsFile read2("Events");
  read2.AddFile(AnalysisFilename);
  read2.DisableAutoScheme();
  tlist.AddToListBefore(&read2, &read, "All");
  tlist.RemoveFromList(&read);

  bar.SetWindowName("Writing...");

  tlist.RemoveFromList(&clean);
  tlist.RemoveFromList(&hcalc);
  tlist.RemoveFromList(&mccalibcalc);

  tlist.AddToList(&write);            // Add task to write output.

  if (!evtloop.Eventloop())
    return;


  tlist.PrintStatistics();
}
