/* ======================================================================== *\
!
! *
! * 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/2004 <mailto:markus@ifae.es>
!
!   Copyright: MAGIC Software Development, 2000-2004
!
!
\* ======================================================================== */
/////////////////////////////////////////////////////////////////////////////
//
//  getExtractor.C
//
// This macro has to be included in another macro or code in order to be 
// used in the following way:
//
// #include "getExtractor.C"
//
// Later, inside the macro, you can initialize one of the signal extractors, 
// as specified in the TDAS-Extractor with the following meaning:
//
//      Nr.    Extractor   Parameters
//
//         MExtractFixedWindow:
//             with the following parameters, if 'maxbin' defines the mean position 
//             of the High-Gain FADC slice carrying the pulse maximum:  
//       1:           SetRange('maxbin'-1,'maxbin'+2,'maxbin'+0.5,'maxbin'+3.5)  
//       2:           SetRange('maxbin'-1,'maxbin'+2,'maxbin'-0.5,'maxbin'+4.5) 
//       3:           SetRange('maxbin'-2,'maxbin'+3,'maxbin'-0.5,'maxbin'+4.5) 
//       4:           SetRange('maxbin'-3,'maxbin'+4,'maxbin'-1.5,'maxbin'+5.5) 
//       5:           SetRange('maxbin'-5,'maxbin'+8,'maxbin'-1.5,'maxbin'+7.5) 
//         MExtractFixedWindowSpline:  
//       6:           SetRange('maxbin'-1.5,'maxbin'+2.5,'maxbin','maxbin'+4) 
//       7:           SetRange('maxbin'-1.5,'maxbin'+2.5,'maxbin'-1,'maxbin'+5) 
//       8:           SetRange('maxbin'-2.5,'maxbin'+3.5,'maxbin'-1,'maxbin'+5) 
//       9:           SetRange('maxbin'-3.5,'maxbin'+4.5,'maxbin'-2,'maxbin'+6) 
//       10:          SetRange('maxbin'-5.5,'maxbin'+8.5,'maxbin'-2,'maxbin'+8) 
//         MExtractFixedWindowPeakSearch:  
//                    SetRange(0,18,2,14) and the following parameters: 
//       11:          SetWindows(2,2,2) 
//       12:          SetWindows(4,4,2) 
//       13:          SetWindows(4,6,4) 
//       14:          SetWindows(6,6,4) 
//       15:          SetWindows(8,8,4) 
//       16:          SetWindows(14,10,4) 
//        MExtractTimeAndChargeSlidingWindow: 
//                    SetRange(0,18,2,14) and the following parameters: 
//       17:          SetWindowSize(2,2) 
//       18:          SetWindowSize(4,4) 
//       19:          SetWindowSize(4,6) 
//       20:          SetWindowSize(6,6) 
//       21:          SetWindowSize(8,8) 
//       22:          SetWindowSize(14,10) 
//        MExtractTimeAndChargeSpline:   
//       23:          SetChargeType(MExtractTimeAndChargeSpline::kAmplitude 
//                    SetRange(0,13,2,13)  
//       24:          SetChargeType(MExtractTimeAndChargeSpline::kIntegral) and: 
//                    SetRange(0,18,2,14) and the following parameters:  
//                    SetRiseTime(0.5); SetFallTime(0.5) 
//       25:          SetRiseTime(0.5); SetFallTime(1.5) 
//       26:          SetRiseTime(1.0); SetFallTime(3.0) 
//       27:          SetRiseTime(1.5); SetFallTime(4.5) 
//        MExtractTimeAndChargeDigitalFilter 
//                    SetRange(0,18,2,14) and the following parameters:  
//       28:          SetNameWeightsFile('msignal/cosmics_weights.dat') 
//       29:          SetNameWeightsFile('msignal/cosmics_weights4.dat') 
//       30:          SetNameWeightsFile('msignal/cosmics_weights_logain.dat') 
//       31:          SetNameWeightsFile('msignal/cosmics_weights4_logain.dat') 
//       32:          SetNameWeightsFile('msignal/calibration_weights_UV.dat') 
//       33:          SetNameWeightsFile('msignal/calibration_weights_UV_logain.dat') 
//       34:          SetNameWeightsFile('msignal/MC_weights.dat') 
//        MExtractTimeAndChargeDigitalFilterPeakSearch 
//       35:          SetNameWeightsFile('msignal/calibration_weights_UV.dat') 
// 
// The extractor will also carry a meaningful name, storing all information about its 
// initialization there.
//
//////////////////////////////////////////////////////////////////////////////////////////
#include "MExtractor.h"
#include "MExtractFixedWindowPeakSearch.h"
#include "MExtractFixedWindow.h"
#include "MExtractFixedWindowSpline.h"
#include "MExtractTimeAndChargeDigitalFilter.h"
#include "MExtractTimeAndChargeDigitalFilterPeakSearch.h"
#include "MExtractTimeAndChargeSlidingWindow.h"
#include "MExtractTimeAndChargeSpline.h"
#include "MLog.h"

#include <TSystem.h>
#include <fstream>

using namespace std;

MExtractor *getExtractor(const UInt_t flag)
{

  MExtractor *extractor   = NULL;
  
  //
  // Choose the signal Extractor:
  //
  // PURE CHARGE EXTRACTORS:
  // MExtractFixedWindowPeakSearchs
  // MExtractSlidingWindow           
  // MExtractFixedWindow          
  // MExtractFixedWindowSpline    
  // MExtractAmplitudeSpline      
  //
  switch (flag)
    {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
      extractor = new MExtractFixedWindow();
      break;
    case 6:
    case 7:
    case 8:
    case 9:
    case 10:
      extractor = new MExtractFixedWindowSpline();
      break;
    case 11:
    case 12:
    case 13:
    case 14:
    case 15:
    case 16:
      extractor = new MExtractFixedWindowPeakSearch();
      extractor->SetRange(0,18,2,14);
      break;
      //
      // PURE TIME EXTRACTORS:
      // ATTENTION: If an extractor deriving from MExtractTimeAndCharge is
      //            used, you may want to use the timing calculated directly
      //            from there. 
      //
      // MExtractTimeHighestIntegral 
      // MExtractTimeFastSpline      
      // MExtractTimeSpline          
      //
      // COMBINED TIME AND CHARGE EXTRACTORS:
      // MExtractTimeAndChargeDigitalFilter 
      // MExtractTimeAndChargeSpline        
      // MExtractTimeAndChargeSlidingWindow 
      //
    case 17:
    case 18:
    case 19:
    case 20:
    case 21:
    case 22:
      extractor = new MExtractTimeAndChargeSlidingWindow();
      extractor->SetRange(0,18,2,14);
      break;
    case 23:
    case 24:
    case 25:
    case 26:
    case 27:
      extractor = new MExtractTimeAndChargeSpline();
      ((MExtractTimeAndChargeSpline*)extractor)->SetChargeType(MExtractTimeAndChargeSpline::kIntegral);      
      extractor->SetRange(0,18,2,14);
      break;
    case 28:
    case 29:
    case 30:
    case 31:
    case 32:
    case 33:
    case 34:
    case 35:
      extractor = new MExtractTimeAndChargeDigitalFilter();
      extractor->SetRange(0,16,3,14);
      break;
    case 36:
      extractor = new MExtractTimeAndChargeDigitalFilterPeakSearch();
      extractor->SetRange(0,20,3,14);
      break;
    default:
      gLog << "No valid extractor flag chosen, cannot run..." << flag << endl;
      return NULL;
      break;
    }

  //
  //  Set Ranges or Windows
  //
  switch (flag)
    {
      // MExtractFixedWindow:
    case 1:
      extractor->SetRange(4,7,6,9);
      break;
    case 2:
      extractor->SetRange(4,7,6,11);
      break;
    case 3:
      extractor->SetRange(4,9,6,11);
      break;
    case 4:
      extractor->SetRange(4,11,6,13);
      break;
    case 5:
      extractor->SetRange(3,16,5,14);
      break;
      // MExtractFixedWindowSpline:
    case 6:
      extractor->SetRange(4,8,6,10);
      break;
    case 7:
      extractor->SetRange(4,8,5,11);
      break;
    case 8:
      extractor->SetRange(4,10,5,11);
      break;
    case 9:
      extractor->SetRange(3,11,5,13);
      break;
    case 10:
      extractor->SetRange(3,17,4,14);
      break;
      // MExtractFixedWindowPeakSearch:
    case 11:
      ((MExtractFixedWindowPeakSearch*)extractor)->SetWindows(2,2,2);
      ((MExtractFixedWindowPeakSearch*)extractor)->SetOffsetFromWindow(0);
      break;
    case 12:
      ((MExtractFixedWindowPeakSearch*)extractor)->SetWindows(4,4,2);
      break;
    case 13:
      ((MExtractFixedWindowPeakSearch*)extractor)->SetWindows(4,6,4);
      ((MExtractFixedWindowPeakSearch*)extractor)->SetOffsetFromWindow(0);
      break;
    case 14:
      ((MExtractFixedWindowPeakSearch*)extractor)->SetWindows(6,6,4);
      break;
    case 15:
      ((MExtractFixedWindowPeakSearch*)extractor)->SetWindows(8,8,4);
      break;
    case 16:
      ((MExtractFixedWindowPeakSearch*)extractor)->SetWindows(14,10,4);
      ((MExtractFixedWindowPeakSearch*)extractor)->SetOffsetFromWindow(2);
      break;
      // MExtractTimeAndChargeSlidingWindow
    case 17:
      ((MExtractTimeAndChargeSlidingWindow*)extractor)->SetWindowSize(2,2);
      break;
    case 18:
      ((MExtractTimeAndChargeSlidingWindow*)extractor)->SetWindowSize(4,4);
      break;
    case 19:
      ((MExtractTimeAndChargeSlidingWindow*)extractor)->SetWindowSize(4,6);
      break;
    case 20:
      ((MExtractTimeAndChargeSlidingWindow*)extractor)->SetWindowSize(6,6);
      break;
    case 21:
      ((MExtractTimeAndChargeSlidingWindow*)extractor)->SetWindowSize(8,8);
      break;
    case 22:
      ((MExtractTimeAndChargeSlidingWindow*)extractor)->SetWindowSize(14,10);
      break;
      // MExtractTimeAndChargeSpline
    case 23:
      ((MExtractTimeAndChargeSpline*)extractor)->SetChargeType(MExtractTimeAndChargeSpline::kAmplitude);
      extractor->SetRange(0,13,2,13);
      extractor->SetName(Form("%s_Amplitude",extractor->GetName()));
      break;
    case 24:
      ((MExtractTimeAndChargeSpline*)extractor)->SetRiseTimeHiGain(0.5); 
      ((MExtractTimeAndChargeSpline*)extractor)->SetFallTimeHiGain(0.5);
      extractor->SetName(Form("%s_Rise-and-Fall-Time_%2.1f_%2.1f",extractor->GetName(),0.5,0.5));
      break;
    case 25:
      ((MExtractTimeAndChargeSpline*)extractor)->SetRiseTimeHiGain(0.5); 
      ((MExtractTimeAndChargeSpline*)extractor)->SetFallTimeHiGain(1.5);
      extractor->SetName(Form("%s_Rise-and-Fall-Time_%2.1f_%2.1f",extractor->GetName(),0.5,1.5));
      break;
    case 26:
      ((MExtractTimeAndChargeSpline*)extractor)->SetRiseTimeHiGain(1.0); 
      ((MExtractTimeAndChargeSpline*)extractor)->SetFallTimeHiGain(3.0);
      extractor->SetName(Form("%s_Rise-and-Fall-Time_%2.1f_%2.1f",extractor->GetName(),1.0,3.0));
      break;
    case 27:
      ((MExtractTimeAndChargeSpline*)extractor)->SetRiseTimeHiGain(1.5); 
      ((MExtractTimeAndChargeSpline*)extractor)->SetFallTimeHiGain(4.5);
      extractor->SetName(Form("%s_Rise-and-Fall-Time_%2.1f_%2.1f",extractor->GetName(),1.5,4.5));
      break;
      // MExtractTimeAndChargeDigitalFilter
    case 28:
      ((MExtractTimeAndChargeDigitalFilter*)extractor)->SetNameWeightsFile("msignal/cosmics_weights.dat");
      break;
    case 29:
      ((MExtractTimeAndChargeDigitalFilter*)extractor)->SetNameWeightsFile("msignal/cosmics_weights4.dat");
      break;
    case 30:
      ((MExtractTimeAndChargeDigitalFilter*)extractor)->SetNameWeightsFile("msignal/cosmics_weights_logaintest.dat");
      break;
    case 31:
      ((MExtractTimeAndChargeDigitalFilter*)extractor)->SetNameWeightsFile("msignal/cosmics_weights4_logaintest.dat");
      break;
    case 32:
      ((MExtractTimeAndChargeDigitalFilter*)extractor)->SetNameWeightsFile("msignal/calibration_weights_UV.dat");
      break;
    case 33:
      ((MExtractTimeAndChargeDigitalFilter*)extractor)->SetNameWeightsFile("msignal/calibration_weights_UV_logaintest.dat");
      break;
    case 34:
      ((MExtractTimeAndChargeDigitalFilter*)extractor)->SetNameWeightsFile("msignal/MC_weights.dat");
      break;
    case 35:
      ((MExtractTimeAndChargeDigitalFilter*)extractor)->SetNameWeightsFile("msignal/calibration_weights_UV.dat");
      break;
    case 36:
      ((MExtractTimeAndChargeDigitalFilter*)extractor)->SetNameWeightsFile("msignal/calibration_weights_UV.dat");
      break;
    default:
      gLog << "No valid extractor flag chosen, cannot run..." << endl;
      return NULL;
      break;
    }
  
  //
  // Set the names of the extractors:
  //
  switch (flag)
    {
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:
    case 8:
    case 9:
    case 10:
      break;
    case 11:
    case 12:
    case 13:
    case 14:
    case 15:
    case 16:
      extractor->SetName(Form("%s_Windows_%02d_%02d",extractor->GetName(),
                              (Int_t)((MExtractFixedWindowPeakSearch*)extractor)->GetHiGainWindowSize(),
                              (Int_t)((MExtractFixedWindowPeakSearch*)extractor)->GetLoGainWindowSize()));
      break;
    case 17:
    case 18:
    case 19:
    case 20:
    case 21:
    case 22:
      extractor->SetName(Form("%s_Windows_%02d_%02d",extractor->GetName(),
                              (Int_t)((MExtractTimeAndChargeSlidingWindow*)extractor)->GetWindowSizeHiGain(),
                              (Int_t)((MExtractTimeAndChargeSlidingWindow*)extractor)->GetWindowSizeLoGain()));
      break;
    case 23:
    case 24:
    case 25:
    case 26:
    case 27:
      break;
    case 28:
    case 29:
    case 30:
    case 31:
    case 32:
    case 33:
    case 34:
    case 35:
    case 36:
      extractor->SetName(Form("%s_Weights_%s",extractor->GetName(),
                              gSystem->BaseName(((MExtractTimeAndChargeDigitalFilter*)extractor)->GetNameWeightsFile())));
      break;
    default:
      gLog << "No valid extractor flag chosen, cannot run..." << endl;
      return NULL;
      break;
    }

  extractor->SetName(Form("%s_Range_%02d_%02d_%02d_%02d",extractor->GetName(),
                          (Int_t)extractor->GetHiGainFirst(),
                          (Int_t)extractor->GetHiGainLast(),
                          (Int_t)extractor->GetLoGainFirst(),
                          (Int_t)extractor->GetLoGainLast()));

  gLog << "Extractor: " << flag << " with name: " << extractor->GetName() << endl;

  return extractor;
  
}
