/* ======================================================================== *\
!
! *
! * 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 López, 12/2003 <mailto:jlopez@ifae.es>
!              Markus Gaug , 04/2004 <mailto:markus@ifae.es>
!
!   Copyright: MAGIC Software Development, 2000-2004
!
!
\* ======================================================================== */
/////////////////////////////////////////////////////////////////////////////
//
//  bootcampstandardanalysis.C
//
//  Updated version of the macro designed at the Wuerzburg bootcamp and 
//  compatible with the latest changes in Mars for general usage at the
//  Udine bootcamp. 
//
//  Needs as arguments the run number of a pedestal file ("*_P_*.root"), 
//  one of a calibration file ("*_C_*.root") and one of a data file 
//  ("*_D_*.root"). Performs the pedestal calculation, the calibration 
/// constants calculation and the calibration of the data. 
//
//  The TString inpath has to be set correctly.
//
//  The macro searches for the pulser colour which corresponds to the calibration
//  run number. If the run number is smaller than 20000, pulser colour "CT1" 
//  is assumed, otherwise, it searches for the strings "green", "blue", "uv" or 
//  "ct1" in the filenames. If no colour or multiple colours are found, the 
//  execution is aborted.  
//
//////////////////////////////////////////////////////////////////////////////////
const TString inpath = "/mnt/Data/rootdata/CrabNebula/2004_02_10/";
const TString outpath = "./";
const Int_t dpedrun  = 14607;
const Int_t dcalrun1 = 14608;
const Int_t dcalrun2 = 0;
const Int_t ddatrun1 = 14609;
const Int_t ddatrun2 = 14614;
const Bool_t usedisplay = kTRUE;
//
// A switch to use the Blind Pixel
//
const Bool_t blindpix = kTRUE;
//
// A switch to use the PIN Diode 
//
const Bool_t pindiode = kFALSE;
//
void bootcampstandardanalysis(const Int_t prun=dpedrun, // pedestal file
                              const Int_t crun1=dcalrun1, const Int_t crun2=dcalrun2, // calibration file(s)
                              const Int_t drun1=ddatrun1, const Int_t drun2=ddatrun2 // data files(s)
                              )
                              
{

  //
  // Choose the signal Extractor:
  //
  MExtractSlidingWindow extractor;
  //  MExtractFixedWindowPeakSearch extractor;
  //  MExtractFixedWindow    extractor;   

  //
  // Set Ranges or Windows
  //
  extractor.SetRange(2,14,5,14);
  //  extractor.SetWindows(8,8);

  //
  // Choose the arrival time Extractor:
  //
  MExtractTimeFastSpline       timeext;
  //  MExtractTimeHighestIntegral timeext;
  //  MExtractTimeSpline          timeext;
  //
  // Set Ranges or Windows
  //
  timeext.SetRange(3,12,6,14);


  MRunIter pruns;
  MRunIter cruns;
  MRunIter druns;

  pruns.AddRun(prun,inpath);

  if (crun2==0)
    cruns.AddRun(crun1,inpath);
  else
    cruns.AddRuns(crun1,crun2,inpath);

  if (drun2==0)
    druns.AddRun(drun1,inpath);
  else
    druns.AddRuns(drun1,drun2,inpath);
  
  //
  // Now setup the tasks and tasklist for the pedestals:
  // ---------------------------------------------------
  //
  MBadPixelsCam     badcam;
  MGeomCamMagic     geomcam;
  MGeomApply        geomapl;
  //
  // If you want to exclude pixels from the beginning, read 
  // an ascii-file with the corr. pixel numbers (see MBadPixelsCam)
  //
  //  badcam.AsciiRead("badpixels.dat");
  
  /************************************/
  /* FIRST LOOP: PEDESTAL COMPUTATION */
  /************************************/

  MJPedestal pedloop;
  pedloop.SetInput(&pruns);
  pedloop.SetOutputPath(outpath.Data());
  if (usedisplay)
    {
      MStatusDisplay *display = new MStatusDisplay;
      display->SetUpdateTime(3000);
      display->Resize(850,700);
      pedloop.SetDisplay(display);
    }
  pedloop.SetBadPixels(badcam);
  pedloop.SetExtractor(&extractor);

  if (!pedloop.Process())
    return;

  /****************************************/
  /* SECOND LOOP: CALIBRATION COMPUTATION */
  /****************************************/

  //
  // Now setup the new tasks for the calibration:
  // ---------------------------------------------------
  //
  MCalibrationQECam qecam;
  MJCalibration     calloop;
  calloop.SetInput(&cruns);
  calloop.SetOutputPath(outpath.Data());
  calloop.SetExtractor(&extractor);
  //
  // Apply rel. time calibration:
  //
  calloop.SetRelTimeCalibration();
  calloop.SetTimeExtractor(&timeext);
  //
  // Set the corr. cams:
  //
  calloop.SetQECam(qecam);
  calloop.SetBadPixels(pedloop.GetBadPixels());
  //
  // Choose if you want to use the blind pixel and/or the pin diode
  //
  calloop.SetUseBlindPixel(blindpix);
  calloop.SetUsePINDiode(pindiode);
  //
  // The next two commands are for the display:
  //
  if (usedisplay)
      calloop.SetDisplay(display);
  
  //
  // Do the event-loop:
  //
  if (!calloop.Process(pedloop.GetPedestalCam()))
    return;
  

  /*************************************/
  /* THIRD LOOP: PEDESTAL CALIBRATION  */
  /*************************************/

  MJExtractSignal pedphotloop;

  pedphotloop.SetExtractor(&extractor);
  pedphotloop.SetTimeExtractor(&timeext);
  pedphotloop.SetInput(&pruns);
  pedphotloop.SetOutputPath(outpath);
  pedphotloop.SetDisplay(display);
  pedphotloop.SetBadPixels(calloop.GetBadPixels());
  
  if (!pedphotloop.ProcessP(pedloop.GetPedestalCam(),calloop.GetCalibrationCam(),calloop.GetQECam()))
    return;

  /*************************************/
  /* FOURTH LOOP: DATA CALIBRATION     */
  /*************************************/

  //
  // Create a empty Parameter List and an empty Task List
  //
  MParList  plist4;
  MTaskList tlist4;
  plist4.AddToList(&tlist4);
  
  //
  // Now setup the tasks and tasklist to analize the data
  // -----------------------------------------------------
  //
  plist4.AddToList(&geomcam);
  //
  // Retrieve the cameras from the previous runs:
  //
  plist4.AddToList(&pedloop.GetPedestalCam());
  plist4.AddToList(&calloop.GetCalibrationCam());
  plist4.AddToList(&calloop.GetQECam());
  plist4.AddToList(&calloop.GetRelTimeCam());
  plist4.AddToList(&calloop.GetBadPixels());
  plist4.AddToList(&pedphotloop.GetPedPhotCam());

  MCerPhotEvt nphot;
  plist4.AddToList(&nphot);

  MArrivalTime times;
  plist4.AddToList(&times);
  
  //tasks
  MReadMarsFile read4("Events");
  read4.DisableAutoScheme();
  static_cast<MRead&>(read4).AddFiles(druns);  
  
  MCalibrate       photcalc;
  photcalc.SetCalibrationMode(MCalibrate::kFfactor);
  MCalibrateRelTimes  timecal;

  tlist4.AddToList(&read4);
  tlist4.AddToList(&geomapl);
  tlist4.AddToList(&extractor);
  tlist4.AddToList(&timeext);
  tlist4.AddToList(&photcalc);
  tlist4.AddToList(&timecal);
  
  //
  // Create and setup the eventloop
  //
  MEvtLoop evtloop4;
  evtloop4.SetParList(&plist4);

  if (!evtloop4.PreProcess())
    return;
  
  TCanvas *c1 = new TCanvas;
  MHCamera disp1(geomcam);
  disp1.SetPrettyPalette();
  //disp1.SetInvDeepBlueSeaPalette()
  disp1.Draw();
  gPad->SetLogy();
  gPad->cd(1);
  
  /*
  TCanvas *c2 = new TCanvas;
  MHCamera disp2(geomcam);
  disp2.SetPrettyPalette();
  //disp2.SetInvDeepBlueSeaPalette()
  disp2.Draw();
  gPad->SetLogy();
  gPad->cd(1);
  */
  while (tlist4.Process())
    {
      disp1.SetCamContent(nphot);
      
      gPad->Modified();
      gPad->Update();

      /*    
      disp2.SetCamContent(times);
      
      gPad->Modified();
      gPad->Update();
      */

      // Remove the comments if you want to go through the file
      // event-by-event:
      if (!HandleInput())
	break;
    }

  evtloop4.PostProcess();
  
}

Bool_t HandleInput()
{
    TTimer timer("gSystem->ProcessEvents();", 50, kFALSE);

    while (1)
    {
        //
        // While reading the input process gui events asynchronously
        //
        timer.TurnOn();
        TString input = Getline("Type 'q' to exit, <return> to go on: ");
        timer.TurnOff();

        if (input=="q\n")
            return kFALSE;

        if (input=="\n")
            return kTRUE;
    };

    return kFALSE;
}

