#ifndef MARS_MFindSupercutsONOFFThetaLoop
#define MARS_MFindSupercutsONOFFThetaLoop

#ifndef MARS_MParContainer
#include "MParContainer.h"
#endif

#ifndef ROOT_TArrayD
#include <TArrayD.h>
#endif
#ifndef ROOT_TArrayI
#include <TArrayI.h>
#endif

#ifndef ROOT_TH1F
#include <TH1F.h>
#endif

#ifndef ROOT_TPostScript
#include <TPostScript.h>
#endif


class MFilter;
class MEvtLoop;
class MH3;
class MSupercutsCalcONOFF;
class MFindSupercutsONOFF;
class MGeomCam;
class MHMatrix;


class MFindSupercutsONOFFThetaLoop : public MParContainer
{
private:

  TString fDataONRootFilename;
  TString fDataOFFRootFilename;


  TString fPathForFiles; // Path to directory where files (PsFiles, rootfiles) will be stored

  
  TString*  fOptSCParamFilenameVector; // Pointer to vector of TStrings containing name of the root files where optimized supercuts will be stored. To be created and filled once Vector of Costheta ranges is defined

  


  // Vectors containing the names of the root files where matrices 
  // will be stored for Train/Test ON/OFF samples.
  // To be defined and filled once vector fCosThetaRangeVector is 
  // defined

  TString* fTrainMatrixONFilenameVector;
  TString* fTestMatrixONFilenameVector;
  TString* fTrainMatrixOFFFilenameVector;
  TString* fTestMatrixOFFFilenameVector;
  

  Double_t fAlphaSig; // Max alpha value were signal is expected


  // Background range (in alpha) is defined by the member variables 
  // fAlphaBkgMin and fAlphaBkgMax
  Double_t fAlphaBkgMin; 
  Double_t fAlphaBkgMax; 


  // Size range of events used to fill the data matrices  
  // is defined by the following variables

  Double_t fSizeCutLow;
  Double_t fSizeCutUp;

  
 // Variables for binning of alpha plots
  
  Int_t fNAlphaBins;
  Double_t fAlphaBinLow;
  Double_t fAlphaBinUp;



  // Boolean variable used to disable the usage ("serious" usage) of the 
  // quantities computed from fits. This will be useful in those cases 
  // where there is too few events to perform a decent fit to the 
  // alpha histograms. In general this variable will be always kTRUE
  
  Bool_t fUseFittedQuantities;


  Double_t fPolyGaussFitAlphaSigma;


  Double_t fWhichFractionTrain;  // number <= 1; specifying fraction of ON Train events
  Double_t fWhichFractionTest;  // number <= 1; specifying fraction of ON Test events

   Double_t fWhichFractionTrainOFF;  // number <= 1; specifying fraction of OFF  Train events
  Double_t fWhichFractionTestOFF;  // number <= 1; specifying fraction of OFF Test events

  Double_t fThetaMin; // Cuts in ThetaOrig.fVal (in rad!!!)
  Double_t fThetaMax; // Cuts in ThetaOrig.fVal (in rad !!!)
  TArrayD fCosThetaRangeVector; // vector containing the 
  // theta ranges that will be used in the 
  // optimization

  TString* fThetaRangeStringVector; // Pointer to vector of TStrings that contain Cos theta ranges specified in fCosThetaRangeVector. It will be used to identify alpha distributions stored in fAlphaDistributionsRootFilename

  TArrayD fCosThetaBinCenterVector; // vector containing the 
  // theta bin centers of the theta ranges/bins contained in 
  // fCosThetaRangeVector

  Double_t fActualCosThetaBinCenter; // Theta value used to fill 
  // the histograms fNormFactorTrainHist, fNormFactorTestHist, 
  // fSigmaLiMaTrainHist ...

  

  Double_t fOverallNexTrain;
  Double_t fOverallNexTest;

  Double_t fOverallSigmaLiMaTrain;
  Double_t fOverallSigmaLiMaTest;
  

  TH1F* fSuccessfulThetaBinsHist; // Hist containing theta bins were optimization was successful

  TH1F* fNormFactorTrainHist; // Hist containing norm factors train for all Cos theta ranges
  TH1F* fNormFactorTestHist; // Hist containing norm factors test for all Cos theta ranges
  TH1F* fSigmaLiMaTrainHist; // Hist containing SigmaLiMa for Train samples for all Cos theta ranges
  TH1F* fSigmaLiMaTestHist; // Hist containing SigmaLiMa for Test samples for all Cos theta ranges
  TH1F* fNexTrainHist; // Hist containing Number os excess events for Train sample for all Cos thetas
  TH1F* fNexTestHist; // Hist containing Number os excess events for Test sample for all Cos theta

  TH1F* fNEvtsInTrainMatrixONHist; // Hist containing total number of events in Train Matrices of ON data for all Cos theta ranges
  TH1F* fNEvtsInTestMatrixONHist; // Hist containing total number of events in Test Matrices of ON data for all Cos theta ranges
  TH1F* fNEvtsInTrainMatrixOFFHist; // Hist containing total number of events in Train Matrices of OFF data for all Cos theta ranges
  TH1F* fNEvtsInTestMatrixOFFHist; // Hist containing total number of events in Test Matrices of OFF data for all Cos theta ranges
  


 
  // Boolean variable that controls wether the optimization of the 
  // parameters (MMinuitInterface::CallMinuit(..) in function FindParams(..))
  // takes place or not. kTRUE will skip such optimization.
  // This variable is useful to test the optmized parameters (previously found 
  // and stored in root file) on the TRAIN sample.

  Bool_t fSkipOptimization;




  // Boolean variable that allows the user to write the initial parameters 
  // into the root file that will be used to store the optimum cuts.
  // If fUseInitialSCParams = kTRUE , parameters are written.
  // In this way, the initial SC parameters can be applied on the data (train/test) 
  
  // The initial parameters are ONLY written to the root file if 
  // there is NO SC params optimization, i.e., if variable 
  // fSkipOptimization = kTRUE;
  
  // The default value is obviously kFALSE.

  Bool_t fUseInitialSCParams;


  Double_t fGammaEfficiency; // Fraction of gammas that remain after cuts
  // Quantity that will have to be determined with MC

  Bool_t fTuneNormFactor; // If true, normalization factors are corrected 
  // using the estimated number of gammas and the gamma efficiency
  // fNormFactor = fNormFactor - Ngammas/EventsInMatrixOFF


  // Boolean variable used to determine wether the normalization factor is 
  // computed from method 1) or 2)
  // 1) Using total number of ON and OFF events before cuts, and tuning the factor 
  //    correcting for "contamination" of gamma events in ON sample
  // 2) Using number of ON and OFF events after cuts in the background 
  //    region determined by variables fAlphaBkgMin-fAlphaBkgMax
 
  Bool_t fNormFactorFromAlphaBkg; // if kTRUE, method 2) is used


  // Boolean variable used to control decide wether to use theta information 
  // in the computation of teh dynamical cuts.
  Bool_t fNotUseTheta;
  
  // Boolean variable used to decide wether to use dynamical cuts or static cuts
  // kTRUE means that static cuts are used. 
  Bool_t fUseStaticCuts;


  // Names for the Hadronness containers for ON and OFF data

  TString  fHadronnessName;
  TString  fHadronnessNameOFF;

  // Vectors where initial SC parameters and steps are stored. 
  // If these vectors are empty, initial SC parameters and steps 
  // are taken from Supercuts container. 
  // They will be intialized to empty vectors in constructor

  TArrayD fInitSCPar;
  TArrayD fInitSCParSteps;

  

  // Name of Postscript file where, for each theta bin,  alpha ON and OFF distributions 
  //  after cuts (and hence, Nex and SigmaLiMa computations) will be stored
  // If fAlphaDistributionsPostScriptFilename is not defined, postscript file is not 
  // produced. It is an optional variable...

  // Still not working...
 
  TPostScript* fPsFilename; 


  // ********************************************************
  // Due to the failure of the use of object TPostScript
  // to make a Ps document with all plots, I decided to use the 
  // standard way (SaveAs(filename.ps)) to store plots related 
  // to alpha distributions 
  // for ON and OFF and BEFORE and AFTER cuts (VERY IMPORTANT
  // TO COMPUTE EFFICIENCIES IN CUTS) 
  
  // Psfilename is set inside function LoopOverThetaRanges()
  // and given to the object MFindSupercutsONOFF created 
  // within this loop.

  // This will have to be removed as soon as the TPostScript
  // solutions works...
  // ********************************************************
  

  TString fAlphaDistributionsRootFilename;
  // Root file where histograms containing the ON alpha distribution and the 
  // OFF alpha distribution (non normalized) , AFTER CUTS, are stored.
  // Histograms containing the normalization factors, Nex and SigmaLiMa for 
  // each theta bin will be also stored there.
  // This name MUST be defined, since the histograms 
  // stored there will be used by 
  // function XXX to compute an overall Nex and sigmaLiMa 
  // combining all those histograms

  // Boolean variables seting flags for loop over theta ranges

  Bool_t fReadMatricesFromFile;
  Bool_t fOptimizeParameters;
  Bool_t fTestParameters;
  
   //--------------------------------------------


public:
  MFindSupercutsONOFFThetaLoop(const char *name=NULL, 
				  const char *title=NULL);
  ~MFindSupercutsONOFFThetaLoop();

  void SetHadronnessName(const TString &name)   
      {fHadronnessName = name;}
  void SetHadronnessNameOFF(const TString &name)   
      {fHadronnessNameOFF = name;}

  void SetPathForFiles(const TString &path)
      {fPathForFiles = path;}

  void SetDataONOFFRootFilenames(const TString &name1, const TString &name2 ) 
      {fDataONRootFilename = name1;  fDataOFFRootFilename = name2; }



  // Names of root files containing matrices and  optimizedparameters 
   Bool_t SetALLNames(); 

  // Function to set names manually... in case matrices are 
  // already defined...

  Bool_t SetNamesManually(TString* OptSCParamFilenameVector, 
			  TString* ThetaRangeStringVector,
			  TString* TrainMatrixONFilenameVector,
			  TString* TestMatrixONFilenameVector,
			  TString* TrainMatrixOFFFilenameVector,
			  TString* TestMatrixOFFFilenameVector) 

      {   
	  fOptSCParamFilenameVector = OptSCParamFilenameVector;
	  fThetaRangeStringVector = ThetaRangeStringVector;
	  fTrainMatrixONFilenameVector = TrainMatrixONFilenameVector;
	  fTestMatrixONFilenameVector = TestMatrixONFilenameVector;
	  fTrainMatrixOFFFilenameVector = TrainMatrixOFFFilenameVector;
	  fTestMatrixOFFFilenameVector = TestMatrixOFFFilenameVector; 

	  return kTRUE;
      }
  
  Bool_t SetAlphaDistributionsRootFilename(const TString &name); 


  Bool_t SetAlphaSig (Double_t alphasig);

  Bool_t SetAlphaBkgMin (Double_t alphabkgmin);
  Bool_t SetAlphaBkgMax (Double_t alphabkgmax);

  Bool_t CheckAlphaSigBkg();

  void SetPostScriptFile(TPostScript* PsFile);


  Bool_t SetCosThetaRangeVector (const TArrayD &d);
  
  Bool_t SetThetaRange (Int_t thetabin);


  void SetAlphaPlotBinining(Int_t nbins, Double_t binlow, Double_t binup)
    { fNAlphaBins = nbins; fAlphaBinLow = binlow; fAlphaBinUp = binup;}

  Bool_t SetNormFactorTrainHist();
  Bool_t SetNormFactorTestHist();
  Bool_t SetSigmaLiMaTrainHist();
  Bool_t SetSigmaLiMaTestHist();
  Bool_t SetNexTrainHist();
  Bool_t SetNexTestHist();
  Bool_t SetNexSigmaLiMaNormFactorNEvtsTrainTestHist();
  Bool_t SetSuccessfulThetaBinsHist();
  void WriteNexSigmaLiMaNormFactorNEvtsTrainTestHistToFile();

  void WriteSuccessfulThetaBinsHistToFile();
  
  
  Bool_t SetInitSCPar (TArrayD &d);
  Bool_t SetInitSCParSteps (TArrayD &d);

  

  Bool_t ReadSCParamsFromAsciiFile(const char* filename, Int_t Nparams);


  void SetFractionTrainTestOnOffEvents(Double_t fontrain, 
				       Double_t fontest, 
				       Double_t fofftrain,
				       Double_t fofftest);

   void SetTuneNormFactor(Bool_t b) {fTuneNormFactor = b;}
   Bool_t SetGammaEfficiency (Double_t gammaeff);
   


   void SetNormFactorFromAlphaBkg (Bool_t b) {fNormFactorFromAlphaBkg = b;}

   void SetUseFittedQuantities (Bool_t b)
      {fUseFittedQuantities = b;}

   void SetReadMatricesFromFile(Bool_t b);
   void SetTrainParameters(Bool_t b) {fOptimizeParameters = b;}
   void SetTestParameters(Bool_t b) {fTestParameters = b;}


   void SetSkipOptimization(Bool_t b) {fSkipOptimization = b;}

   void SetUseInitialSCParams(Bool_t b) {fUseInitialSCParams = b;}


   void SetVariableNotUseTheta(Bool_t b) {fNotUseTheta = b;}
   Bool_t GetVariableNotUseTheta() { return fNotUseTheta;}


   void SetVariableUseStaticCuts(Bool_t b) {fUseStaticCuts = b;}
   Bool_t GetVariableUseStaticCuts() { return fUseStaticCuts;}


   void SetSizeRange(Double_t SizeMin, Double_t SizeMax)
	{fSizeCutLow = SizeMin; fSizeCutUp = SizeMax; }

   // Function that loops over the theta ranges defined by 
   // fCosThetaRangeVector optimizing parameter and/or testing
   // parameters

   Bool_t LoopOverThetaRanges();


   // Function that loops over the alpha distributions (ON-OFF)
   // stored in root file defined by fAlphaDistributionsRootFilename
   // and computes the significance and Nex (using MHFindSignificanceONOFF::FindSigma)
   // for several cuts in alpha (0-fAlphaSig; in bins defined for alpha distributions 
   // by user).

   // It creates the histograms, fills them and store them 
   // in root file defined by fAlphaDistributionsRootFilename. A single histogram 
   // for each theta bin.

   // The function returns kFALSE if it could not accomplish its duty

   Bool_t ComputeNexSignificanceVSAlphaSig();

   


   // Function that gets the histograms with the alpha distributions
   // (for all the theta bins specified by fCosThetaRangeVector)
   // stored in fAlphaDistributionsRootFilename, and combine them
   // (correcting OFF histograms with the normalization factors stored 
   // in NormFactorTrain or NormFactorTest) to get one single 
   // Alpha distribution for ON and another one for OFF. 
   // Then these histograms are given as arguments to 
   // the function MHFindSignificanceONOFF::FindSigmaONOFF, 
   // (Object of this class is created) to compute the 
   // Overall Excess events and  significance, that will be 
   // stored in variables fOverallNexTrain and fOverallSigmaLiMaTrain
   // and Test.

 

   Bool_t ComputeOverallSignificance(Bool_t CombineTrainData,
				     Bool_t CombineTestData);


   Double_t GetOverallNexTrain() {return fOverallNexTrain;}
   Double_t GetOverallNexTest() {return fOverallNexTest;}
   
   Double_t GetOverallSigmaLiMaTrain() {return fOverallSigmaLiMaTrain;}
   Double_t GetOverallSigmaLiMaTest() {return fOverallSigmaLiMaTest;}

   Double_t GetGammaEfficiency() {return fGammaEfficiency;}

   Double_t GetAlphaSig() {return fAlphaSig;}
  Double_t GetAlphaBkgMin () {return fAlphaBkgMin;}
  Double_t GetAlphaBkgMax () {return fAlphaBkgMax;}
   
  Bool_t GetSkipOptimization() {return fSkipOptimization;}

  Bool_t GetUseFittedQuantities() {return fUseFittedQuantities;}
 
   ClassDef(MFindSupercutsONOFFThetaLoop, 1) 
  // Class for optimization of the Supercuts
};

#endif




