void TreeReader::FillNewTree(TTree* tree, TCut cuts, double frac, void (*addFunc)(TreeReader *, TTree *, bool))
{
	fChain->Draw(">>skim", cuts, "entrylist");
	TEntryList *skim = (TEntryList*)gDirectory->Get("skim");
	if(skim == NULL) return;
	int nEntries = skim->GetN();
	SetEntryList(skim);

	BranchNewTree(tree);
	if(addFunc) addFunc(this,tree,true);

	if(pmode=="v") cout << "N candidates = " << nEntries << endl;
	if(frac > 0 && frac < 1) { nEntries *= frac; if(pmode=="v") cout << "Using only " << 100*frac << "% of the entries" << endl; }
	else if (frac > 1) { nEntries = frac; if(pmode=="v") cout << "Using only " << frac << " entries" << endl; }

	for(Long64_t i = 0 ; i < nEntries ; i++)
	{
		GetEntry(i,skim);
		if(addFunc) addFunc(this,tree,false);
		tree->Fill();
	}

	SetEntryList(0);
	delete skim;
}
///////////////////////
// Get the number of entries in the entry list
SEXP nEntriesEntryList(SEXP entryList)
{
  TEntryList* el = checkForEntryListWrapper(entryList);
  
  SEXP n = NEW_INTEGER(1);
  INTEGER(n)[0] = el->GetN();
  
  return n;
}
int main(int argc, char** argv)
{ 
 TDRStyle();
 
 gStyle->SetPadTopMargin(0.11);
 gStyle->SetPadLeftMargin(0.07);
 gStyle->SetPadRightMargin(0.23);
 gStyle->cd(); 
 
 
 std::cout << " " << std::endl;
 std::cout << " " << std::endl;
 std::cout << "          __ \\                                |                       _)       _ \\                     ____|        |    " << std::endl;
 std::cout << "          |   |  |   |  __ `__ \\   __ \\       |      |   |  __ `__ \\   |      |   |  |   |  __ \\       __| \\ \\   /  __|  " << std::endl; 
 std::cout << "          |   |  |   |  |   |   |  |   |      |      |   |  |   |   |  |      __ <   |   |  |   |      |    \\ \\ /   |    " << std::endl;   
 std::cout << "         ____/  \\__,_| _|  _|  _|  .__/      _____| \\__,_| _|  _|  _| _|     _| \\_\\ \\__,_| _|  _|     _____| \\_/   \\__|  " << std::endl; 
 std::cout << "                                  _|                                        " << std::endl;                                             
 std::cout << " " << std::endl;
 std::cout << " " << std::endl; 

 char normal[] = { 0x1b, '[', '0', ';', '3', '9', 'm', 0 };
 char black[] = { 0x1b, '[', '0', ';', '3', '0', 'm', 0 };
 char red[] = { 0x1b, '[', '0', ';', '3', '1', 'm', 0 };
 char green[] = { 0x1b, '[', '0', ';', '3', '2', 'm', 0 };
 char yellow[] = { 0x1b, '[', '0', ';', '3', '3', 'm', 0 };
 char blue[] = { 0x1b, '[', '0', ';', '3', '4', 'm', 0 };
 char purple[] = { 0x1b, '[', '0', ';', '3', '5', 'm', 0 };
 char cyan[] = { 0x1b, '[', '0', ';', '3', '6', 'm', 0 };
 char Lgray[] = { 0x1b, '[', '0', ';', '3', '7', 'm', 0 };
 char Dgray[] = { 0x1b, '[', '0', ';', '3', '8', 'm', 0 };
 char Bred[] = { 0x1b, '[', '1', ';', '3', '1', 'm', 0 };
 //for bold colors, just change the 0 after the [ to a 1
 
 EColor vColor[1000] = {
  (EColor) (kRed+1),
  (EColor) (kRed+3),
  (EColor) (kGray+1),
  (EColor) (kAzure-2),
  (EColor) (kAzure-9),
  (EColor) (kYellow),
  (EColor) (kGreen+2),
//   
  kGreen,
  //kMagenta,(EColor) (kMagenta+1),(EColor) (kMagenta+2),
  kTeal,//(EColor) (kTeal+1),
  kRed,
  kGray,
  kOrange,(EColor) (kOrange+1),
  kBlue,//(EColor)(kBlue+1),(EColor) (kBlue+2),
  (EColor) (kPink+2),//(EColor) (kPink+1),(EColor) (kPink+2),
  kViolet,
  kYellow,
  kGray,(EColor) (kGray+1),(EColor) (kViolet),(EColor) (kYellow),(EColor) (kGray)
 };
 
 
 
 
 //Check if all nedeed arguments to parse are there                                                                                                                               
 if(argc != 2)
 {
  std::cerr << ">>>>> analysis.cpp::usage: " << argv[0] << " configFileName" << std::endl ;
  return 1;
 }


 // Parse the config file                                                                                                                                                          
 parseConfigFile (argv[1]) ;
 
 std::string treeName  = gConfigParser -> readStringOption("Input::treeName");
 std::string treeNameSelections = gConfigParser -> readStringOption("Input::treeNameSelections");
 std::string fileSamples = gConfigParser -> readStringOption("Input::fileSamples");
 std::string inputDirectory = gConfigParser -> readStringOption("Input::inputDirectory");
 
 std::string inputBeginningFile = "out_NtupleProducer_"; 
 try {
  inputBeginningFile = gConfigParser -> readStringOption("Input::inputBeginningFile");
 }
 catch (char const* exceptionString){
  std::cerr << " exception = " << exceptionString << std::endl;
 }
 std::cout << ">>>>> Input::inputBeginningFile  " << inputBeginningFile  << std::endl;  
 
 TTree *treeEffVect[100];
 TTree *treeJetLepVect[100];
 
 //  <iEvent>[iCut]
 std::vector<int> Run [100];
 std::vector<int> Lumi[100];
 std::vector<int> Evt [100];
 
 char *nameSample[1000];
 char *nameHumanReadable[1000];
 char* xsectionName[1000];
 
 double Normalization[1000];
 double xsection[1000];
 char nameFileIn[1000];
 sprintf(nameFileIn,"%s",fileSamples.c_str());

 int numberOfSamples = ReadFile(nameFileIn, nameSample, nameHumanReadable, xsectionName);

 ///==== list of selections to perform (NOT sequential additive selections) ====
 std::string CutFile = gConfigParser -> readStringOption("Selections::CutFile");
 std::string CutHRFile = "";
 try {
  CutHRFile = gConfigParser -> readStringOption("Selections::CutHRFile");
 }
 catch (char const* exceptionString){
  std::cerr << " exception = " << exceptionString << std::endl;
 }
 
 std::vector<std::string> vCut;
 std::vector<std::string> vCutHR;
 
 std::cout << " nCuts   = " << ReadFileCut(CutFile, vCut) << std::endl;
 if (CutHRFile != "") {
  std::cout << " nCutsHR = " << ReadFileCutHR(CutHRFile, vCutHR) << std::endl;
 }
 
 if (vCutHR.size() < vCut.size()) {
  int size1 = vCut.size();
  int size2 = vCutHR.size();
  for (int i=0; i<(size1-size2+2); i++) {
   vCutHR.push_back("test");
  }
 }

 for (unsigned int iCut = 0; iCut<vCutHR.size(); iCut++){ 
  std::cout << " vCutHR[" << iCut << "] = " << vCutHR.at(iCut).c_str() << std::endl;
 }
 
 ///==== Latinos flag ==== 
 bool  Latinos = false; 
 try {
  Latinos = gConfigParser -> readBoolOption("Input::Latinos");
 }
 catch (char const* exceptionString){
  std::cerr << " exception = " << exceptionString << std::endl;
 }
 std::cout << ">>>>> input::Latinos  " << Latinos  << std::endl;  
 
 
 ///==== debug flag ====
 
 bool  debug = false; 
 try {
  debug = gConfigParser -> readBoolOption("Input::debug");
 }
 catch (char const* exceptionString){
  std::cerr << " exception = " << exceptionString << std::endl;
 }
 std::cout << ">>>>> input::debug  " << debug  << std::endl;  
 
 ///==== program ====
 
 
 double start, end;
 start = clock();
  
 for (int iSample=0; iSample<numberOfSamples; iSample++){
  xsection[iSample] = atof(xsectionName[iSample]);
 }

for (int iSample=0; iSample<numberOfSamples; iSample++){
  
  char nameFile[20000];
  sprintf(nameFile,"%s/%s%s.root",inputDirectory.c_str(),inputBeginningFile.c_str(),nameSample[iSample]);  
  if (debug) std::cout << " nameFile = " << nameFile << std::endl;
  
  TFile* f = new TFile(nameFile, "READ");
  
  treeEffVect[iSample] = (TTree*) f->Get(treeNameSelections.c_str());
  if (treeEffVect[iSample] != 0) {
   char nameTreeEff[100];
   sprintf(nameTreeEff,"treeEff_%d",iSample); 
   treeEffVect[iSample]->SetName(nameTreeEff);      
  }
  
  treeJetLepVect[iSample] = (TTree*) f->Get(treeName.c_str());
  char nameTreeJetLep[100];
  sprintf(nameTreeJetLep,"treeJetLep_%d",iSample); 
  treeJetLepVect[iSample]->SetName(nameTreeJetLep);
 }
 
 ///===== create map for joint sample ====
 
 std::vector<int> join_samples;
 std::vector<std::string> name_samples;
 for (int iSample=0; iSample<numberOfSamples; iSample++){
  name_samples.push_back(nameHumanReadable[iSample]);
  join_samples.push_back(-1);
 }
 
 
 std::vector<std::string> reduced_name_samples;
 std::vector<int>         reduced_name_samples_flag;
 for (int iSample = (numberOfSamples-1); iSample>= 0; iSample--){
  bool flag_name = false;
  for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
   if (reduced_name_samples.at(iName) == name_samples.at(iSample)) flag_name = true;
  }
  if (flag_name == false) {
   reduced_name_samples.push_back(name_samples.at(iSample));
   reduced_name_samples_flag.push_back(-1);
  }

 }

 
 std::cout << " numberOfSamples = " << numberOfSamples << std::endl;
 for (int iSample = (numberOfSamples-1); iSample>= 0; iSample--){
  double XSection;
  int numEntriesBefore;
  double preselection_efficiency;
  if (treeEffVect[iSample] != 0) {   
   treeEffVect[iSample]->SetBranchAddress("XSection",&XSection);
   treeEffVect[iSample]->SetBranchAddress("numEntriesBefore",&numEntriesBefore);
   treeEffVect[iSample]->SetBranchAddress("preselection_efficiency",&preselection_efficiency);  
   treeEffVect[iSample]->GetEntry(0);
  }
  std::cout << " Xsection = " << XSection << " ~~~> " << xsection[iSample] << std::endl;
  XSection = xsection[iSample];
 }

 
 ///==== get number in sample list that correspond to DATA ====
 int numDATA = -1;
 for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
  if (reduced_name_samples.at(iName) == "DATA") {
   numDATA = iName;
  }
 }

 if (debug) std::cout << " Cut size = " << vCut.size() << " ~~ " << std::endl;
 std::cout.precision (5) ;
 std::cout.unsetf(std::ios::scientific);

 
 ///==== cicle on selections ====
 for (unsigned int iCut =0; iCut<vCut.size(); iCut++){
  TString Cut = Form ("%s",vCut.at(iCut).c_str());
  if (debug) std::cout << " Cut[" << iCut << ":" << vCut.size() << "] = " << Cut.Data() << " ~~ " << std::endl;
  ///==== initialize ====
  for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
   reduced_name_samples_flag.at(iName) = -1;
  }
  
  ///==== cicle on samples ====
  for (int iSample = (numberOfSamples-1); iSample>= 0; iSample--){
   if (debug) std::cout << " Sample[" << iSample << ":" << numberOfSamples << "] = " << nameSample[iSample] << " ~~ " << std::endl;
  
   bool isData = false;
   for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
    if (name_samples.at(iSample) == reduced_name_samples.at(iName)){
     if (iName == numDATA) {
      isData = true;
     }
    }
   }  
   
   //---- only if DATA it make sense! ----
   if (isData) {
    TString CutExtended  = Cut;
    treeJetLepVect[iSample]->SetEntryList(0); 
    treeJetLepVect[iSample]->Draw(">> myList",CutExtended,"entrylist");
    TEntryList *myList = (TEntryList*)gDirectory->Get("myList");
    treeJetLepVect[iSample]->SetEntryList(myList); 
    
    std::cout << " Dumping ... " << std::endl;
    
    treeJetLepVect[iSample]->SetEstimate(myList->GetN());
    treeJetLepVect[iSample]->Draw("run:lumi:event","","para goff");
    int nEntries = myList->GetN();
    
    std::cout << " nEntries = " << nEntries << std::endl;
    
    Double_t *vTempRun  = treeJetLepVect[iSample]->GetV1();
    Double_t *vTempLumi = treeJetLepVect[iSample]->GetV2();
    Double_t *vTempEvt  = treeJetLepVect[iSample]->GetV3();
    
    std::cout << " got! " << std::endl;
    
    for (int iEntry = 0; iEntry<nEntries; iEntry++){
     if (!(iEntry%(nEntries/10))) std::cout << "iEntry = " << iEntry << " :: " << nEntries << std::endl;
     Run[iCut] .push_back(vTempRun[iEntry]);
     Lumi[iCut].push_back(vTempLumi[iEntry]);
     Evt[iCut] .push_back(vTempEvt[iEntry]);
    }
   }
   
   std::cout <<"Processing: " << blue << (((double) iCut)/vCut.size())*100. << "% "  << normal <<  " -- " <<  red << (((double) numberOfSamples - iSample)/(numberOfSamples))*100. << "% \r"  << normal << std::flush;   
  } ///==== end cicle on samples ====
   //std::cout << "Processing: " << blue << (((double) iCut)/vCut.size())*100. << "% \r"  << normal << std::flush;   
  } ///==== end cicle on selections ====
 
 if (debug) std::cout << " >>> Reprocessing ... " << std::endl;
 
 std::cout << std::endl;
 
 
 
 
 
 
 
 ///==== output - txt file name ====
 
 std::cout.precision (5) ;
 std::cout.unsetf(std::ios::scientific);
 
 std::ofstream myfile;
 std::string ListRunLumiEvt;
 
 try {
  ListRunLumiEvt = gConfigParser -> readStringOption("Output::ListRunLumiEvt");
 }
 catch (char const* exceptionString){
  std::cerr << " exception = " << exceptionString << std::endl;
  std::cerr << " *** ERROR *** " << std::endl;  
  return 0;
 }
 
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){ 
  std::string nameFile_ListRunLumiEvt = ListRunLumiEvt;
  nameFile_ListRunLumiEvt += "_";
  std::stringstream numberString;
  numberString << iCut;
  nameFile_ListRunLumiEvt += numberString.str();
  nameFile_ListRunLumiEvt += ".txt";
  myfile.open (nameFile_ListRunLumiEvt.c_str());
  std::cout << " preparing :: nameFile_ListRunLumiEvt " << nameFile_ListRunLumiEvt << std::endl;
  
  for (int iEvent=0; iEvent< Run[iCut].size(); iEvent++) {
   myfile << std::setw (15) << Run[iCut] .at(iEvent) << " ";
   myfile << std::setw (15) << Lumi[iCut].at(iEvent) << " ";
   myfile << std::setw (15) << Evt[iCut] .at(iEvent) << " ";
   myfile << std::endl;   
  }
  
  std::cout << " iCut = " << iCut << " :: numSelectedEvents = " << Run[iCut].size() << std::endl;
  
  myfile.close();
 }
//  
//  std::cout << "Writing to: " << nameOutDataCard << std::endl;
//  std::cout << std::endl;
 
 
 std::cout << std::endl;
 std::cout << std::endl;
 std::cout << std::endl;
 std::cout << std::endl;
 std::cout << std::endl;
 
 
 
 
 
 std::cerr << " ******************************************* end *******************************************" << std::endl;
 end = clock();
 std::cout <<"Time = " <<  ((double) (end - start)) << " (a.u.)" << std::endl;  
 
 
 
}
void treeToHistogramConverter(const std::string& fileName, const std::string& newFileName, const std::string& cut)
{
  TFile* file = TFile::Open(fileName.c_str());
  if(file->IsZombie())
  {
    std::cout << "File with name " << fileName << " not found!  Exiting." << std::endl;
    return;
  }
  TTree* tree = (TTree*)file->Get("tree");

  tree->SetBranchAddress("jetData", &jetInfo_.flavour);
  tree->SetBranchAddress("leptonData", &leptonInfo_.pt);
  tree->SetBranchAddress("svData", &svInfo_.svNSelectedTrks);
  tree->SetBranchAddress("2dIPTagInfo", &ip2dInfo_.ip2dTrk1);
  tree->SetBranchAddress("3dIPTagInfo", &ip3dInfo_.ip3dTrk1);
  tree->SetBranchAddress("tagData", &discInfo_.tcheDisc);

  tree->Draw(">>theList", cut.c_str(), "entrylist");
  TEntryList* theList = (TEntryList*)gDirectory->Get("theList");


  TFile* newFile = new TFile(newFileName.c_str(), "RECREATE");
  TH1F* flavour = new TH1F("flavour", "MC Flavour of the Jets with Leptons", 22, -0.5, 21.5);
  flavour->GetXaxis()->SetTitle("Jet Flavour");
  TH1F* jetPt = new TH1F("jetPt", "p_{T} of the Jets with Leptons", 100, 0.0, 350.0);
  jetPt->GetXaxis()->SetTitle("Jet p_{T} (GeV)");
  TH1F* jetEta = new TH1F("jetEta", "#eta of the Jets with Leptons", 100, -2.5, 2.5);
  jetEta->GetXaxis()->SetTitle("Jet #eta");
  TH1F* jetPhi = new TH1F("jetPhi", "#phi of the Jets with Leptons", 100, -3.2, 3.2);
  jetPhi->GetXaxis()->SetTitle("Jet #phi");
  TH1F* jetEMFraction = new TH1F("jetEMFraction", "EM Fraction of the Jets with Leptons", 100, -0.1, 1.1);
  jetEMFraction->GetXaxis()->SetTitle("Jet EM Fraction");

  TH1F* lepPt = new TH1F("lepPt", "p_{T} of Lepton Associated to a Jet", 100, 0.0, 50.0);
  lepPt->GetXaxis()->SetTitle("lepton p_{T} (GeV)");
  TH1F* lepEta = new TH1F("lepEta", "#eta of Lepton Associated to a Jet", 100, -2.5, 2.5);
  lepEta->GetXaxis()->SetTitle("lepton #eta");
  TH1F* lepPhi = new TH1F("lepPhi", "#phi of Lepton Associated to a Jet", 100, -3.2, 3.2);
  lepPhi->GetXaxis()->SetTitle("lepton #phi");
  TH1F* lepNHits = new TH1F("lepNHits", "Number of Track Hits of Lepton Associated to a Jet", 25, -0.5, 24.5);
  lepNHits->GetXaxis()->SetTitle("Number of Track Hits");
  TH1F* lepNChi2 = new TH1F("lepNChi2", "Track Normalized #chi^{2} of Lepton Associated to a Jet", 100, 0.0, 10.0);
  lepNChi2->GetXaxis()->SetTitle("lepton track Normalized #chi^{2}");
  TH1F* ptRel = new TH1F("ptRel", "p_{T,Rel} of Lepton Associated to a Jet", 100, 0.0, 8.0);
  ptRel->GetXaxis()->SetTitle("p_{T,Rel} (GeV)");
  TH1F* sip2d = new TH1F("sip2d", "sip2d of Lepton Associated to a Jet", 100, -10.0, 30.0);
  sip2d->GetXaxis()->SetTitle("Transverse Signed Impact Parameter Significance");
  TH1F* sip3d = new TH1F("sip3d", "sip3d of Lepton Associated to a Jet", 100, -10.0, 30.0);
  sip3d->GetXaxis()->SetTitle("3D Signed Impact Parameter Significance");
  TH1F* p0par = new TH1F("p0par", "p_{0,par} of Lepton Associated to a Jet", 100, -10.0, 10.0);
  p0par->GetXaxis()->SetTitle("p_{0,par} (GeV)");
  TH1F* deltaR = new TH1F("deltaR", "#Delta R of Lepton Associated to a Jet", 100, 0.0, 0.4);
  deltaR->GetXaxis()->SetTitle("#Delta R");
  TH1F* etaRel = new TH1F("etaRel", "Relative #eta of Lepton Associated to a Jet", 100, 0.0, 10.0);
  etaRel->GetXaxis()->SetTitle("Relative #eta");
  TH1F* ratio = new TH1F("ratio", "Ratio of Lepton Momentum to Associated Jet Energy", 100, 0.0, 2.0);
  ratio->GetXaxis()->SetTitle("p_{lep} / E_{Jet}");
  TH1F* ratioRel = new TH1F("ratioRel", "Ratio of Lepton p0par to Associated Jet Energy", 100, 0.0, 2.0);
  ratioRel->GetXaxis()->SetTitle("p_{0, par} / E_{Jet}");

  TH1F* svNSelectedTrks = new TH1F("svNSelectedTrks", "Number of Selected Tracks for SV Reconstruction", 26, -0.5, 25.5);
  svNSelectedTrks->GetXaxis()->SetTitle("Number of Selected Tracks");
  TH1F* svNVtx = new TH1F("svNVtx", "Number of SVs Associated to a Jet", 6, -0.5, 5.5);
  svNVtx->GetXaxis()->SetTitle("Number of Vertices");
  TH1F* svNVtxTrks = new TH1F("svNVtxTrks", "Number of Tracks Associated to SV with Longest Decay Length", 21, -0.5, 20.5);
  svNVtxTrks->GetXaxis()->SetTitle("Number of Vertex Tracks");
  TH1F* svNChi2 = new TH1F("svNChi2", "Normalized #chi^{2} of SV with Longest Decay Length", 100, 0.0, 20.0);
  svNChi2->GetXaxis()->SetTitle("Normalized #chi^{2}");
  TH1F* svDist2d = new TH1F("svDist2d", "Transverse Decay Length of SV with Longest Decay Length", 100, 0.0, 3.0);
  svDist2d->GetXaxis()->SetTitle("Transverse Decay Length (cm)");
  TH1F* svDist2dErr = new TH1F("svDist2dErr", "Transverse Decay Length Error of SV with Longest Decay Length", 100, 0.0, 0.12);
  svDist2dErr->GetXaxis()->SetTitle("Transverse Decay Length Error (cm)");
  TH1F* svDist3d = new TH1F("svDist3d", "3D Decay Length of SV with Longest Decay Length", 100, 0.0, 5.0);
  svDist3d->GetXaxis()->SetTitle("3D Decay Length (cm)");
  TH1F* svDist3dErr = new TH1F("svDist3dErr", "3D Decay Length Error of SV with Longest Decay Length", 100, 0.0, 0.2);
  svDist3dErr->GetXaxis()->SetTitle("3D Decay Length Error (cm)");

  TH1F* ip2dTrk1 = new TH1F("ip2dTrk1", "Transverse IP of 1st Track Associated to Jet", 100, 0.0, 0.3);
  ip2dTrk1->GetXaxis()->SetTitle("1st Track Transverse IP (cm)");
  TH1F* ip2dErrTrk1 = new TH1F("ip2dErrTrk1", "Transverse IP Error of 1st Track Associated to Jet", 100, 0.0, 0.04);
  ip2dErrTrk1->GetXaxis()->SetTitle("1st Track Transverse IP Error (cm)");
  TH1F* ip2dProbTrk1 = new TH1F("ip2dProbTrk1", "Transverse IP Probability of 1st Track Associated to Jet", 100, 0.0, 1.0);
  ip2dProbTrk1->GetXaxis()->SetTitle("1st Track Transverse IP Probability");
  TH1F* ip2dTrk2 = new TH1F("ip2dTrk2", "Transverse IP of 2nd Track Associated to Jet", 100, 0.0, 0.3);
  ip2dTrk2->GetXaxis()->SetTitle("2nd Track Transverse IP (cm)");
  TH1F* ip2dErrTrk2 = new TH1F("ip2dErrTrk2", "Transverse IP Error of 2nd Track Associated to Jet", 100, 0.0, 0.04);
  ip2dErrTrk2->GetXaxis()->SetTitle("2nd Track Transverse IP Error (cm)");
  TH1F* ip2dProbTrk2 = new TH1F("ip2dProbTrk2", "Transverse IP Probability of 2nd Track Associated to Jet", 100, 0.0, 1.0);
  ip2dProbTrk2->GetXaxis()->SetTitle("2nd Track Transverse IP Probability");
  TH1F* ip2dTrk3 = new TH1F("ip2dTrk3", "Transverse IP of 3rd Track Associated to Jet", 100, 0.0, 0.3);
  ip2dTrk3->GetXaxis()->SetTitle("3rd Track Transverse IP (cm)");
  TH1F* ip2dErrTrk3 = new TH1F("ip2dErrTrk3", "Transverse IP Error of 3rd Track Associated to Jet", 100, 0.0, 0.04);
  ip2dErrTrk3->GetXaxis()->SetTitle("3rd Track Transverse IP Error (cm)");
  TH1F* ip2dProbTrk3 = new TH1F("ip2dProbTrk3", "Transverse IP Probability of 3rd Track Associated to Jet", 100, 0.0, 1.0);
  ip2dProbTrk3->GetXaxis()->SetTitle("3rd Track Transverse IP Probability");

  TH1F* ip3dTrk1 = new TH1F("ip3dTrk1", "3D IP of 1st Track Associated to Jet", 100, 0.0, 0.5);
  ip3dTrk1->GetXaxis()->SetTitle("1st Track 3D IP (cm)");
  TH1F* ip3dErrTrk1 = new TH1F("ip3dErrTrk1", "3D IP Error of 1st Track Associated to Jet", 100, 0.0, 0.04);
  ip3dErrTrk1->GetXaxis()->SetTitle("1st Track 3D IP Error (cm)");
  TH1F* ip3dProbTrk1 = new TH1F("ip3dProbTrk1", "3D IP Probability of 1st Track Associated to Jet", 100, 0.0, 1.0);
  ip3dProbTrk1->GetXaxis()->SetTitle("1st Track 3D IP Probability");
  TH1F* ip3dTrk2 = new TH1F("ip3dTrk2", "3D IP of 2nd Track Associated to Jet", 100, 0.0, 0.5);
  ip3dTrk2->GetXaxis()->SetTitle("2nd Track 3D IP (cm)");
  TH1F* ip3dErrTrk2 = new TH1F("ip3dErrTrk2", "3D IP Error of 2nd Track Associated to Jet", 100, 0.0, 0.04);
  ip3dErrTrk2->GetXaxis()->SetTitle("2nd Track 3D IP Error (cm)");
  TH1F* ip3dProbTrk2 = new TH1F("ip3dProbTrk2", "3D IP Probability of 2nd Track Associated to Jet", 100, 0.0, 1.0);
  ip3dProbTrk2->GetXaxis()->SetTitle("2nd Track 3D IP Probability");
  TH1F* ip3dTrk3 = new TH1F("ip3dTrk3", "3D IP of 3rd Track Associated to Jet", 100, 0.0, 0.5);
  ip3dTrk3->GetXaxis()->SetTitle("3rd Track 3D IP (cm)");
  TH1F* ip3dErrTrk3 = new TH1F("ip3dErrTrk3", "3D IP Error of 3rd Track Associated to Jet", 100, 0.0, 0.04);
  ip3dErrTrk3->GetXaxis()->SetTitle("3rd Track 3D IP Error (cm)");
  TH1F* ip3dProbTrk3 = new TH1F("ip3dProbTrk3", "3D IP Probability of 3rd Track Associated to Jet", 100, 0.0, 1.0);
  ip3dProbTrk3->GetXaxis()->SetTitle("3rd Track 3D IP Probability");

  TH1F* tcheDisc = new TH1F("tcheDisc", "TCHE Discriminator for Jets with Leptons", 100, -10.0, 30.0);
  tcheDisc->GetXaxis()->SetTitle("Track Counting High Efficiency Discriminator");
  TH1F* tchpDisc = new TH1F("tchpDisc", "TCHP Discriminator for Jets with Leptons", 100, -10.0, 30.0);
  tchpDisc->GetXaxis()->SetTitle("Track Counting High Purity Discriminator");
  TH1F* jpDisc = new TH1F("jpDisc", "JP Discriminator for Jets with Leptons", 100, 0.0, 2.5);
  jpDisc->GetXaxis()->SetTitle("Jet Probability Discriminator");
  TH1F* jbpDisc = new TH1F("jbpDisc", "JBP Discriminator for Jets with Leptons", 100, 0.0, 8.0);
  jbpDisc->GetXaxis()->SetTitle("Jet B Probability Discriminator");
  TH1F* ssvDisc = new TH1F("ssvDisc", "SSV Discriminator for Jets with Leptons", 100, 0.0, 8.0);
  ssvDisc->GetXaxis()->SetTitle("Simple Secondary Vertex Discriminator");
  TH1F* csvDisc = new TH1F("csvDisc", "CSV Discriminator for Jets with Leptons", 100, 0.0, 1.0);
  csvDisc->GetXaxis()->SetTitle("Combined Secondary Vertex Discriminator");
  TH1F* csvMVADisc = new TH1F("csvMVADisc", "CSV MVA Discriminator for Jets with Leptons", 100, 0.0, 1.0);
  csvMVADisc->GetXaxis()->SetTitle("Combined Secondary Vertex MVA Discriminator");
  TH1F* smDisc = new TH1F("smDisc", "SMT Discriminator for Jets with Leptons", 100, 0.0, 1.0);
  smDisc->GetXaxis()->SetTitle("Soft Muon Discriminator");
  TH1F* smIPDisc = new TH1F("smIPDisc", "SM IP Discriminator for Jets with Leptons", 100, -10.0, 30.0);
  smIPDisc->GetXaxis()->SetTitle("Soft Muon SIP-3D Discriminator");
  TH1F* smPtDisc = new TH1F("smPtDisc", "SM PtRel Discriminator for Jets with Leptons", 100, 0.0, 8.0);
  smPtDisc->GetXaxis()->SetTitle("Soft Muon p_{T, Rel} Discriminator");
  TH1F* seIPDisc = new TH1F("seIPDisc", "SE IP Discriminator for Jets with Leptons", 100, -10.0, 30.0);
  seIPDisc->GetXaxis()->SetTitle("Soft Electron SIP-3D Discriminator");
  TH1F* sePtDisc = new TH1F("sePtDisc", "SE PtRel Discriminator for Jets with Leptons", 100, 0.0, 8.0);
  sePtDisc->GetXaxis()->SetTitle("Soft Electron p_{T, Rel} Discriminator");

  int nEntries = theList->GetN();
  for(int i = 0; i != nEntries; ++i)
  {
    tree->GetEntry(theList->Next());
    flavour->Fill(jetInfo_.flavour);
    jetPt->Fill(jetInfo_.pt);
    jetEta->Fill(jetInfo_.eta);
    jetPhi->Fill(jetInfo_.phi);
    jetEMFraction->Fill(jetInfo_.emFraction);

    lepPt->Fill(leptonInfo_.pt);
    lepEta->Fill(leptonInfo_.eta);
    lepPhi->Fill(leptonInfo_.phi);
    lepNHits->Fill(leptonInfo_.nhits);
    lepNChi2->Fill(leptonInfo_.nchi2);
    ptRel->Fill(leptonInfo_.ptRel);
    sip2d->Fill(leptonInfo_.sip2d);
    sip3d->Fill(leptonInfo_.sip3d);
    p0par->Fill(leptonInfo_.p0par);
    deltaR->Fill(leptonInfo_.deltaR);
    etaRel->Fill(leptonInfo_.etaRel);
    ratio->Fill(leptonInfo_.ratio);
    ratioRel->Fill(leptonInfo_.ratioRel);

    svNSelectedTrks->Fill(svInfo_.svNSelectedTrks);
    svNVtx->Fill(svInfo_.svNVtx);
    svNVtxTrks->Fill(svInfo_.svNVtxTrks);
    svNChi2->Fill(svInfo_.svNChi2);
    svDist2d->Fill(svInfo_.svDist2d);
    svDist2dErr->Fill(svInfo_.svDist2dErr);
    svDist3d->Fill(svInfo_.svDist3d);
    svDist3dErr->Fill(svInfo_.svDist3dErr);

    ip2dTrk1->Fill(ip2dInfo_.ip2dTrk1);
    ip2dErrTrk1->Fill(ip2dInfo_.ip2dErrTrk1);
    ip2dProbTrk1->Fill(ip2dInfo_.ip2dProbTrk1);
    ip2dTrk2->Fill(ip2dInfo_.ip2dTrk2);
    ip2dErrTrk2->Fill(ip2dInfo_.ip2dErrTrk2);
    ip2dProbTrk2->Fill(ip2dInfo_.ip2dProbTrk2);
    ip2dTrk3->Fill(ip2dInfo_.ip2dTrk3);
    ip2dErrTrk3->Fill(ip2dInfo_.ip2dErrTrk3);
    ip2dProbTrk3->Fill(ip2dInfo_.ip2dProbTrk3);

    ip3dTrk1->Fill(ip3dInfo_.ip3dTrk1);
    ip3dErrTrk1->Fill(ip3dInfo_.ip3dErrTrk1);
    ip3dProbTrk1->Fill(ip3dInfo_.ip3dProbTrk1);
    ip3dTrk2->Fill(ip3dInfo_.ip3dTrk2);
    ip3dErrTrk2->Fill(ip3dInfo_.ip3dErrTrk2);
    ip3dProbTrk2->Fill(ip3dInfo_.ip3dProbTrk2);
    ip3dTrk3->Fill(ip3dInfo_.ip3dTrk3);
    ip3dErrTrk3->Fill(ip3dInfo_.ip3dErrTrk3);
    ip3dProbTrk3->Fill(ip3dInfo_.ip3dProbTrk3);

    tcheDisc->Fill(discInfo_.tcheDisc);
    tchpDisc->Fill(discInfo_.tchpDisc);
    jpDisc->Fill(discInfo_.jpDisc);
    jbpDisc->Fill(discInfo_.jbpDisc);
    ssvDisc->Fill(discInfo_.ssvDisc);
    csvDisc->Fill(discInfo_.csvDisc);
    csvMVADisc->Fill(discInfo_.csvMVADisc);
    smDisc->Fill(discInfo_.smDisc);
    smIPDisc->Fill(discInfo_.smIPDisc);
    smPtDisc->Fill(discInfo_.smPtDisc);
    seIPDisc->Fill(discInfo_.seIPDisc);
    sePtDisc->Fill(discInfo_.sePtDisc);
  }

  newFile->Write();
  newFile->Close();
  file->Close();
}
int main(int argc, char** argv)
{ 
 TDRStyle();
 
 gStyle->SetPadTopMargin(0.2);
 gStyle->SetPadBottomMargin(0.2);
 gStyle->SetPadLeftMargin(0.07);
 gStyle->SetPadRightMargin(0.23);
 gStyle->cd(); 
 
 
 std::cout << " " << std::endl;
 std::cout << " " << std::endl;
 std::cout << " " << std::endl; 
 std::cout << "     ___|          | _)  |         ___|                            |                   " << std::endl;
 std::cout << "   \\___ \\   __ \\   |  |  __|     \\___ \\    _` |  __ `__ \\   __ \\   |   _ \\     " << std::endl; 
 std::cout << "         |  |   |  |  |  |             |  (   |  |   |   |  |   |  |   __/             " << std::endl;
 std::cout << "   _____/   .__/  _| _| \\__|     _____/  \\__,_| _|  _|  _|  .__/  _| \\___|          " << std::endl;
 std::cout << "           _|                                              _|                          " << std::endl;
 std::cout << " " << std::endl;
 std::cout << " " << std::endl;
 std::cout << "    _ \\                      _ \\                                   " << std::endl;
 std::cout << "   |   |  |   |  __ \\       |   |   _` |  __ \\    _` |   _ \\      " << std::endl;
 std::cout << "   __ <   |   |  |   |      __ <   (   |  |   |  (   |   __/         " << std::endl;
 std::cout << "  _| \\_\\ \\__,_| _|  _|     _| \\_\\ \\__,_| _|  _| \\__, | \\___| " << std::endl;
 std::cout << "                                                |___/                " << std::endl;
 std::cout << " " << std::endl;
 std::cout << " " << std::endl;
 
 
 //Check if all nedeed arguments to parse are there                                                                                                                               
 if(argc != 2)
 {
  std::cerr << ">>>>> analysis.cpp::usage: " << argv[0] << " configFileName" << std::endl ;
  return 1;
 }


 // Parse the config file                                                                                                                                                          
 parseConfigFile (argv[1]) ;
 
 std::string treeName  = gConfigParser -> readStringOption("Input::treeName");
 std::string inputFileName = gConfigParser -> readStringOption("Input::inputFileName");

 std::vector<int> runRangesMin = gConfigParser -> readIntListOption("Options::runRangesMin");
 std::vector<int> runRangesMax = gConfigParser -> readIntListOption("Options::runRangesMax");
 
 TTree *treeJetLepVect; 
 
 std::string CutFile = gConfigParser -> readStringOption("Selections::CutFile"); 
 std::vector<std::string> vCut; ///====> only the first cut is used!
 std::cout << " nCuts   = " << ReadFileCut(CutFile, vCut) << std::endl;
 
 ///==== output file ====
 std::string outputDirectory = gConfigParser -> readStringOption("Output::outputDirectory");
 std::string OutFileName    = gConfigParser -> readStringOption("Output::outFileName");
 
 ///==== debug flag (begin) ==== 
 bool  debug = false; 
 try {
  debug = gConfigParser -> readBoolOption("Input::debug");
 }
 catch (char const* exceptionString){
  std::cerr << " exception = " << exceptionString << std::endl;
 }
 std::cout << ">>>>> input::debug  " << debug  << std::endl;  
 ///==== debug flag (end) ==== 
 
 
 
 
 ///==== program ====
 
 TFile* f = new TFile(inputFileName.c_str(), "READ");    
 treeJetLepVect = (TTree*) f->Get(treeName.c_str());
  
 int totNumEvents = treeJetLepVect->GetEntries(vCut.at(0).c_str());
 int numOutputFiles = runRangesMax.size();
 std::cout << " totNumEvents   = " << totNumEvents   << std::endl;
 std::cout << " numOutputFiles = " << numOutputFiles << std::endl;
 
 treeJetLepVect->SetEntryList(0); 
 treeJetLepVect->Draw(">> myList",vCut.at(0).c_str(),"entrylist");
 TEntryList *myList = (TEntryList*)gDirectory->Get("myList");
 treeJetLepVect->SetEntryList(myList); 
 
 std::cout << " tot = " << myList->GetN() << " = " << totNumEvents << " =? " << treeJetLepVect -> GetEntries () << std::endl;
 
 TH1F* MyHistoCounterMC = (TH1F*) f->Get("AllEvents/totalEvents");
 
 for (int iOutFile = 0; iOutFile < numOutputFiles; iOutFile++) {
  std::cout << " iOutFile = " << iOutFile << " : " << numOutputFiles << std::endl;
  TString outputRootFileName = Form("%s/%s_%d.root",outputDirectory.c_str(),OutFileName.c_str(), iOutFile); 
  TFile outputRootFile ( outputRootFileName.Data(), "RECREATE") ;
  outputRootFile.cd () ;
  outputRootFile.mkdir ("ntupleEcalAlignment") ;
  outputRootFile.cd ("ntupleEcalAlignment") ;  
  
  TTree* cloneTree = treeJetLepVect -> CloneTree (0) ;
  
  int countiEntry = 0;
    
  ///==== create list for this run range ====
  TString Cut = Form ("((%s) && (runId >= %d && runId < %d))", vCut.at(0).c_str(), runRangesMin.at(iOutFile), runRangesMax.at(iOutFile));
  treeJetLepVect->SetEntryList(0); 
  treeJetLepVect->Draw(">> myList",Cut.Data(),"entrylist");
  TEntryList *myList = (TEntryList*)gDirectory->Get("myList");
  treeJetLepVect->SetEntryList(myList); 
  for ( int iEntry = 0; iEntry < myList -> GetN () ; iEntry++) { 
   countiEntry++;
   treeJetLepVect -> GetEntry (myList->Next());
   cloneTree -> Fill () ;
  }
  cloneTree -> AutoSave () ;
  outputRootFile.cd () ;
  outputRootFile.mkdir ("AllEvents") ;
  outputRootFile.cd ("AllEvents") ;  
  MyHistoCounterMC -> Write();
  outputRootFile.Close () ;
 }
 
}
//Calls treeAnalyzer::applySelection(strInputTextFile) and then for each plot made here it analyzes the raw data that went into making each plot
//The output is stored inside the Plots directory for each Canvas created
void treeAnalyzerTDC::applySelectionTDC(string strOutputROOTFile){
    //Variable Declaration
    bool bExitSuccess = false;
    
    //Apply the Selection
    //------------------------------------------------------
    applySelection(strOutputROOTFile);
    
    //Load the ROOT file that was just created in the UPDATE mode
    //------------------------------------------------------
    //TFile *file_ROOT_Output = new TFile(strOutputROOTFile.c_str(), "UPDATE", "", 1);
    //TFile file_ROOT_Output = getFile(strOutputROOTFile, "UPDATE", bExitSuccess);
    TFile * file_ROOT_Output = getFile(strOutputROOTFile, "UPDATE", bExitSuccess);
    
    if (!bExitSuccess) { //Case: Output File Was Not Created Successfully
        if(bVerbose_IO) {
            cout<< ("treeAnalyzerTDC::applySelectionTDC() - Output ROOT File: " + strOutputROOTFile + " was not successfully created, stopping\n").c_str();
            cout<<"treeAnalyzerTDC::applySelectionTDC() - Please Cross-Check (Maybe you do not have write-permission in working directory or filepath does not exist???)"<<endl;
        }
        
        return;
    } //End Case: Output File Was Not Created Successfully
    
    //Loop Over Selection Input to create the indepth TDC Analysis
    //------------------------------------------------------
    for (auto iterSel = vecSelInfo.begin(); iterSel != vecSelInfo.end(); ++iterSel) { //Loop Over vecSelInfo
        //Get the TDirectory that was made for this SelInfo
        TDirectory *dir_thisSel = file_ROOT_Output->GetDirectory( (*iterSel).strDirectory.c_str(), false, "GetDirectory" );
        
        //Loop over all CanvasInfo's that were requested for this SelInfo
        //------------------------------------------------------
        for (auto iterCanvas = (*iterSel).mapCanvas.begin(); iterCanvas != (*iterSel).mapCanvas.end(); ++iterCanvas) { //Loop Over (*iterSel).mapCanvas
            //Get the TDirectory that was made for this CanvasInfo
            TDirectory *dir_thisCanvas = dir_thisSel->GetDirectory( ((*iterCanvas).second).strDirectory.c_str(), false, "GetDirectory" );
            
            //Loop over all PlotInfo's that were requested for this CanvasInfo
            //------------------------------------------------------
            for (auto iterPlot = ((*iterCanvas).second).mapPlot.begin(); iterPlot != ((*iterCanvas).second).mapPlot.end(); ++iterPlot) { //Loop Over ((*iterCanvas).second).mapPlot
                //Skip this plot if no friend branch was defined by the user
                if ( ((*iterPlot).second).strFriendBranch.length() == 0 ) continue;
                
                //Get the TDirectory that was made for this PlotInfo
                //------------------------------------------------------
                TDirectory *dir_thisPlot = dir_thisCanvas->GetDirectory( ((*iterPlot).second).strDirectory.c_str(), false, "GetDirectory" );
                TDirectory *dir_HistoWithFit = dir_thisPlot->mkdir( ("HistoWithFit_" + ((*iterPlot).second).strVarIndep).c_str() );
                TDirectory *dir_HistoOverFit = dir_thisPlot->mkdir( ("HistoOverFit_" + ((*iterPlot).second).strVarIndep).c_str() );
                
                //Open the Input Data File
                //------------------------------------------------------
                TFile * file_ROOT_Input = getFile( ((*iterPlot).second).strNameROOTFile, "READ", bExitSuccess );
                
                if (!bExitSuccess) { //Case: Input File Failed To Open Successfully
                    if (bVerbose_IO) {
                        std::cout << ("treeAnalyzerTDC::applySelectionTDC(): error while opening file: " + ((*iterPlot).second).strNameROOTFile).c_str() << endl;
                        std::cout << "Skipping Plot: " << ((*iterPlot).second).strName << endl;
                    }
                    
                    continue;
                } //End Case: Input File Failed To Open Successfully
                
                //Load the TTree from file_ROOT_Input
                //------------------------------------------------------
                TTree *treeInput = (TTree*) file_ROOT_Input->Get( ((*iterPlot).second).strNameTree.c_str() );
                
                //Note the Selection is already setup due to calling "applySelection()" of the parent class
                
                //Declaration of TTree's leaf types
                //------------------------------------------------------
                int iRun;                           //value of the run number
                
                float fVarIndep;                    //value of the independent variable for the i^th point
                
                TH1F *hTDC_Histo = new TH1F();      //Histogram from the i^th point
                
                TF1 *func_FriendBranch = new TF1(); //Fit Function from the i^th point
                
                //Set the branch addresses
                //------------------------------------------------------
                treeInput->SetBranchAddress("iRun",&iRun);
                treeInput->SetBranchAddress( ((*iterPlot).second).strVarIndep.c_str(), &fVarIndep);
                treeInput->SetBranchAddress("hTDC_Histo",&hTDC_Histo);
                treeInput->SetBranchAddress( ((*iterPlot).second).strFriendBranch.c_str(), &func_FriendBranch);
                
                //Loop Over the Entries in treeInput that pass the selection
                //------------------------------------------------------
                //Inform the user we have moved to a new SelInfo and then draw the tree
                //cout<< ("Selection = '" + (*iterSel).strSel + "'" ) << endl;
                //treeInput->Draw( ">>listSelEvts", (*iterSel).strSel.c_str(), "entrylist" );
                
                cout<< ("Selection = '" + ((*iterPlot).second).strSelLocal + "'" ) << endl;
                treeInput->Draw( ">>listSelEvts", ((*iterPlot).second).strSelLocal.c_str(), "entrylist" );
                
                //Get the Entry List
                TEntryList *listSelEvts = (TEntryList*) gDirectory->Get("listSelEvts");
                
                //Loop Over the events passing ((*iterPlot).second).strSelLocal stored in eventList
                //cout<<"i\tidx_EvtList\tSigma_Fit\n";
                for (int i=0; i < listSelEvts->GetN(); ++i) { //Loop over events stored in eventList
                    //int iEvtIdx = listSelEvts->Next();  //Should probably use listSelEvts->GetEntry(i) because duplicate calls of Next() per loop iteration cause undesired iteration through the list
                    
                    //treeInput->GetEntry( iEvtIdx );
                    treeInput->GetEntry( listSelEvts->GetEntry(i) );
                    
                    //Skip this Event if the Histogram pointer is a null pointer
                    if (hTDC_Histo == nullptr){
                        continue;
                    }
                    else{ //Otherwise Set the Histogram Style
                        hTDC_Histo = getHistogram( (*iterPlot).second, hTDC_Histo);
                    }
                    
                    //treeInput->Show();
                    //if(i==0) treeInput->Show();
                    
                    //Set the Style
                    
                    //Create the Canvas - Histogram w/Fit
                    //------------------------------------------------------
                    //set the style based on user input
                    //Make a copy of the CanvasInfo, reset the name, and then pass it to treeAnalyzer::getCanvas()
                    CanvasInfo tempCanvasInfo = (*iterCanvas).second;
                    tempCanvasInfo.strName = "canvas_DataHistoWithFit_R" + getString(iRun) + "_" + ((*iterPlot).second).strVarDepend + "_" + ((*iterPlot).second).strVarIndep + getString(fVarIndep);
                    
                    TCanvas *cHistoWithFit = getCanvas(tempCanvasInfo);
                    cHistoWithFit->cd();
                    
                    TLegend *leg = (TLegend *) ((*iterCanvas).second).leg->Clone( ("leg_HistoWithFit_" + getString(fVarIndep) ).c_str() );
                    leg->Clear();   //Wipe all previous entries
                    
                    leg->AddEntry(hTDC_Histo,"Data","LPE");
                    
                    //Plot Histogram on the Canvas
                    cHistoWithFit->cd();
                    hTDC_Histo->Draw("E1");
                    
                    //Check that the fit function exists
                    if ( func_FriendBranch != nullptr) {
                        //Set the style
                        func_FriendBranch->SetLineColor( ((*iterPlot).second).iColor );
                        func_FriendBranch->SetLineStyle( ((*iterPlot).second).iStyleLine );
                        func_FriendBranch->SetLineWidth( ((*iterPlot).second).fSizeLine );
                        
                        //Add to the Legend
                        leg->AddEntry(func_FriendBranch, "Fit", "L");
                        
                        //Draw
                        func_FriendBranch->Draw("same");
                    }
                    
                    //Draw the legend
                    leg->Draw("same");
                    
                    //Store
                    dir_HistoWithFit->cd();
                    cHistoWithFit->Write();
                    hTDC_Histo->Write();
                    func_FriendBranch->Write();
                    //if ( func_FriendBranch != nullptr) func_FriendBranch->Write();
                    
                    //Create the Canvas - Histogram DIVIDED by Fit
                    //------------------------------------------------------
                    //set the style based on user input
                    //Make a copy of the CanvasInfo, reset the name, and then pass it to treeAnalyzer::getCanvas()
                    tempCanvasInfo.strName = "canvas_DataHistoOverFit_R" + getString(iRun) + "_" + ((*iterPlot).second).strVarDepend + "_" + ((*iterPlot).second).strVarIndep + getString(fVarIndep);
                    
                    TCanvas *cHistoOverFit = getCanvas(tempCanvasInfo);
                    cHistoOverFit->cd();
                    
                    TH1F *hTDC_HistoOverFit = (TH1F *) hTDC_Histo->Clone( (hTDC_Histo->GetName() + getString("_OverFit") ).c_str() );
                    
                    hTDC_HistoOverFit->Divide(func_FriendBranch);
                    
                    hTDC_HistoOverFit->GetYaxis()->SetRangeUser(0.,2.);
                    
                    hTDC_HistoOverFit->Draw("E1");
                    
                    //store
                    dir_HistoOverFit->cd();
                    cHistoOverFit->Write();
                    hTDC_HistoOverFit->Write();
                    
                    //Delete pointers
                    delete cHistoWithFit;
                    delete cHistoOverFit;
                    //delete func_FriendBranch; //No this breaks the TTree::GetEntry() Call
                    //delete hTDC_Histo;        //No this breaks the TTree::GetEntry() Call
                    delete leg;
                } //End Loop over events stored in eventList
                
                //Close the Input ROOT File
                //------------------------------------------------------
                file_ROOT_Input->Close();
            } //End Loop Over ((*iterCanvas).second).mapPlot
        } //End Loop Over (*iterSel).mapCanvas
    } //End Loop Over vecSelInfo
    
    //Close the output ROOT file
    //------------------------------------------------------
    file_ROOT_Output->Close();
    
    return;
} //End treeAnalyzerTDC::applySelectionTDC()
double Chi2Func(const double *xx ){
 const Double_t DX = xx[0];
 const Double_t DY = xx[1];
 const Double_t DZ = xx[2];
 
 const Double_t DPHIEuler = xx[3]; ///==== Euler angles
 const Double_t DTHETAEuler = xx[4];
 const Double_t DPSIEuler = xx[5];
 
///  The transform rotates first, then translates.
///  The Euler angles are gotten from HepRotation::eulerAngles()
///  (a HepTransform3D is a HepRotation and a HepTranslation).
 
//  CLHEP::HepEulerAngles RotMat((CLHEP::HepRotationZ( DPHIEuler )).eulerAngles());
 CLHEP::HepEulerAngles RotMat(DPHIEuler,DTHETAEuler,DPSIEuler);
 
 HepGeom::Transform3D RotoTrasl( RotMat,
		                 CLHEP::Hep3Vector(DX,DY,DZ));

 myTree->SetEntryList(0); 
 myTree->Draw(">> myList",globalCut.Data(),"entrylist");
 TEntryList *myList = (TEntryList*)gDirectory->Get("myList");

 //==== bux fix in ROOT see https://savannah.cern.ch/bugs/?60569 ====
 /*
 TIter next( myList->GetLists() ); 
 if (myList->GetLists() != 0){
// if ((int) myList->GetLists() != 0){
  TEntryList *ilist;
  while( (ilist = (TEntryList*) *next ) ) {
   ilist->SetTreeName(myTree->GetName()); 
   next();
   } 
  TEntryList *duplist = (TEntryList*) myList->Clone(); 
  delete myList; myList = duplist; 
 }
 else {
  myList->SetTreeName(myTree->GetName());
 }
 */
  //==== end bux fix in ROOT see https://savannah.cern.ch/bugs/?60569 ==== 
 myTree->SetEntryList(myList); 
 
 myTree->Draw("DeltaEtaIn:DeltaPhiIn:etaSC:phiSC","","para goff");
 int nEntries = myList->GetN();
 Double_t *vTemp = myTree->GetV1();
 Double_t *vDEta = new Double_t[nEntries];
 for (int iEntry = 0; iEntry<nEntries; iEntry++){
  vDEta[iEntry] = vTemp[iEntry];
 }
 Double_t *vTemp2 = myTree->GetV2();
 Double_t *vDPhi = new Double_t[nEntries];
 for (int iEntry = 0; iEntry<nEntries; iEntry++){
  vDPhi[iEntry] = vTemp2[iEntry];
 }
 Double_t *vEta = myTree->GetV3();
 Double_t *vPhi = myTree->GetV4();
 myTree->Draw("E5x5:eleCharge","","para goff");
 Double_t *vEnergy = myTree->GetV1();
 Double_t *vCharge = myTree->GetV2();

  Double_t vErrDEta;
  Double_t vErrDPhi;
  Double_t vErrEta;
  Double_t vErrPhi;
  
  double Chi2 = 0;
  
  int counter = 0;
  for (int iEntry = 0; iEntry < nEntries; iEntry++){
   if ((even && !(iEntry%2)) || (odd && (iEntry%2))) {
//    if (!(iEntry%10)) {
    counter++;
    
//   for (int iEntry = 0; iEntry<nEntries; iEntry++){
//     if (!(iEntry/100)) std::cout << " iEntry = " << iEntry << " : " << nEntries << std::endl;
//     std::cerr << " " << vDEta[iEntry] << std::endl;
//     std::cerr << " " << vDPhi[iEntry] << std::endl;
//     std::cerr << " " << vEta[iEntry] << std::endl;
//     std::cerr << " " << vPhi[iEntry] << std::endl;
//     std::cerr << " " << vEnergy[iEntry] << " " << std::endl;
    
    vErrDEta = fabs((sqrt(3.6 / sqrt(vEnergy[iEntry]) * 3.6 / sqrt(vEnergy[iEntry]) + 12. / vEnergy[iEntry] * 12. / vEnergy[iEntry] + 0.54*0.54)) / 1000. / (Z * tan(2*atan(exp(-vEta[iEntry])))) * fabs(sin(2*atan(exp(-vEta[iEntry]))))); ///===> /1000 perchè è in "mm" -> "m"
  
    vErrDPhi = 1.3 * fabs((sqrt(3.6 / sqrt(vEnergy[iEntry]) * 3.6 / sqrt(vEnergy[iEntry]) + 12. / vEnergy[iEntry] * 12. / vEnergy[iEntry] + 0.54*0.54)) / 1000. / (Z * tan(2*atan(exp(-vEta[iEntry]))))); ///===> /1000 perchè è in "mm" -> "m"
    
    vErrEta = 0.0;
    vErrPhi = 0.0;


    ///==== (x,y,z) 
     HepGeom::Point3D<double> xyz( Z / cos(2*atan(exp(-vEta[iEntry]))) * sin(2*atan(exp(-vEta[iEntry]))) * cos (vPhi[iEntry]),
				  Z / cos(2*atan(exp(-vEta[iEntry]))) * sin(2*atan(exp(-vEta[iEntry]))) * sin (vPhi[iEntry]),
				  Z );

			   
    ///==== (x',y',z') = RotoTrasl(x,y,z) 
    HepGeom::Point3D<double> xyz_prime = RotoTrasl * xyz;
    ///==== deta / dphi [(x',y',z'),(x,y,z)]
    

    double deta = xyz.pseudoRapidity() - xyz_prime.pseudoRapidity(); ///==== deta_data = SC - Tracker
    double dphi = deltaPhi(xyz.phi() , xyz_prime.phi()); ///==== check sign convention!!!!!!!!!!!!!!!!!!!!!
    double ddeta = (vDEta[iEntry] - deta);
    double ddphi = (vDPhi[iEntry] - dphi);
    
    ddeta = ddeta - FunctionDeta->Eval(vEta[iEntry],vCharge[iEntry]);
    ddphi = ddphi - FunctionDphi->Eval(vEta[iEntry],vCharge[iEntry]);
         
    Chi2 += (ddeta / vErrDEta * ddeta / vErrDEta + ddphi / vErrDPhi * ddphi / vErrDPhi);
    
   }
  }
  
  std::cout << " Chi2 = " << Chi2 << " / " << counter << " = " << Chi2/counter << " - " << DX*1000 << " mm: " << DY*1000 << " mm: " << DZ*1000 << " mm: "  <<  DPHIEuler << " : "  <<  DTHETAEuler << " : "  <<  DPSIEuler << std::endl;
   return Chi2;
}
Exemple #8
0
int main(int argc, char** argv){
 
 ///=======================================================================================
 ///==== Calculate Scale from Data (minimization Chi2 and more)
 ///==== then perform toy MC to see the error on THAT scale with THAT statistics available
 ///======================================================================================= 

 if(argc != 2)
 {
  std::cerr << ">>>>> analysis.cpp::usage: " << argv[0] << " configFileName" << std::endl ;
  return 1;
 }
 
 // Parse the config file                                                                                                                                                          
 
 std::string fileName (argv[1]) ;
 boost::shared_ptr<edm::ProcessDesc> processDesc = edm::readConfigFile(fileName) ;
 boost::shared_ptr<edm::ParameterSet> parameterSet = processDesc->getProcessPSet () ;

 edm::ParameterSet subPSetInput = parameterSet->getParameter<edm::ParameterSet> ("inputTree") ;
 std::string treeNameDATA  = subPSetInput.getParameter<std::string> ("treeNameDATA") ;
 std::string inputFileDATA = subPSetInput.getParameter<std::string> ("inputFileDATA") ;
 treeNameMC = subPSetInput.getParameter<std::string> ("treeNameMC") ;
 std::string inputFileMC = subPSetInput.getParameter<std::string> ("inputFileMC") ;
  
 std::cout << ">>>>> InputDATA::treeName  " << treeNameDATA  << std::endl;  
 std::cout << ">>>>> InputDATA::inputFile  " << inputFileDATA  << std::endl;  
 std::cout << ">>>>> InputMC::treeName  " << treeNameMC  << std::endl;  
 std::cout << ">>>>> InputMC::inputFile  " << inputFileMC  << std::endl;  


 edm::ParameterSet subPSetOutput = parameterSet->getParameter<edm::ParameterSet> ("outputTree") ;
 std::string outputFile = subPSetOutput.getParameter<std::string> ("outputFile") ;

 std::cout << ">>>>> Output::outputFile  " << outputFile  << std::endl;  


 edm::ParameterSet subPSetOptions = parameterSet->getParameter<edm::ParameterSet> ("options") ;
 MinScan  = subPSetOptions.getParameter<double> ("MinScan") ;
 MaxScan  = subPSetOptions.getParameter<double> ("MaxScan") ;
 iNoSteps = subPSetOptions.getParameter<int>    ("iNoSteps") ;
  
 std::cout << ">>>>> Options::MinScan  " << MinScan  << std::endl;  
 std::cout << ">>>>> Options::MaxScan  " << MaxScan  << std::endl;  
 std::cout << ">>>>> Options::iNoSteps " << iNoSteps << std::endl;  

 MinScanRange  = subPSetOptions.getParameter<double> ("MinScanRange") ;
 MaxScanRange  = subPSetOptions.getParameter<double> ("MaxScanRange") ;
 
 std::cout << ">>>>> Options::MinScanRange  " << MinScanRange  << std::endl;  
 std::cout << ">>>>> Options::MaxScanRange  " << MaxScanRange  << std::endl;  

 minBINS = subPSetOptions.getParameter<double> ("minBINS") ;
 maxBINS = subPSetOptions.getParameter<double> ("maxBINS") ;
 numBINS = subPSetOptions.getParameter<int>    ("numBINS") ;

 std::cout << ">>>>> Options::numBINS   " << numBINS  << std::endl;  
 std::cout << ">>>>> Options::minBINS   " << minBINS  << std::endl;
 std::cout << ">>>>> Options::maxBINS   " << maxBINS  << std::endl;


 NBINTemplate = 10 * numBINS;
 MinTemplate = minBINS;
 MaxTemplate = maxBINS;
 Delta = (MaxTemplate - MinTemplate) / NBINTemplate;



 variableName = subPSetOptions.getParameter<std::string> ("variableName") ;
 std::cout << ">>>>> Options::variableName " << variableName.c_str() << std::endl;
 
 double minET = subPSetOptions.getParameter<double> ("minET") ;
 std::cout << ">>>>> Options::minET " << minET << std::endl;
 
 
 std::string temp_cut = subPSetOptions.getParameter<std::string> ("cut") ;
 std::cout << ">>>>> Options::cut " << temp_cut.c_str() << std::endl;
 AdditionalCut = Form("%s",temp_cut.c_str());
 std::cout << ">>>>> Options::AdditionalCut " << AdditionalCut.Data() << std::endl;
 
 
 EEEB = subPSetOptions.getParameter<int> ("EEorEB");
 std::cout << ">>>>> Options::EEEB " << EEEB << std::endl;
///==== 0 = EE+EB
///==== 1 = EE
///==== 2 = EB
///==== 3 = EE+
///==== 4 = EE-

 if (EEEB == 1) { ///==== EE
  AdditionalCut = Form("%s && (eta > 1.5 || eta < -1.5)",AdditionalCut.Data());
 }

 if (EEEB == 2) { ///==== EB
  AdditionalCut = Form("%s && (eta < 1.5 && eta > -1.5)",AdditionalCut.Data());
 }
 if (EEEB == 3) { ///==== EE+
  AdditionalCut = Form("%s && (eta > 1.5)",AdditionalCut.Data());
 }
 if (EEEB == 4) { ///==== EE-
  AdditionalCut = Form("%s && (eta < -1.5)",AdditionalCut.Data());
 }
 if (EEEB == 5) { ///==== EB mod 1
  AdditionalCut = Form("%s && (abs(eta) < 0.435)",AdditionalCut.Data());
 }
 if (EEEB == 6) { ///==== EB mod 2
  AdditionalCut = Form("%s && (abs(eta) < 0.783 && abs(eta) > 0.435)",AdditionalCut.Data());
 }
 if (EEEB == 7) { ///==== EB mod 3
  AdditionalCut = Form("%s && (abs(eta) < 1.131 && abs(eta) > 0.783)",AdditionalCut.Data());
 }
 if (EEEB == 8) { ///==== EB mod 4
  AdditionalCut = Form("%s && (abs(eta) < 1.479 && abs(eta) > 1.131)",AdditionalCut.Data());
 }
 if (EEEB == 9) { ///==== EE No ES
  AdditionalCut = Form("%s && (abs(eta) > 2.5)",AdditionalCut.Data());
 }
 if (EEEB == 10) { ///==== EE + ES
 AdditionalCut = Form("%s && (abs(eta) < 2.5 && abs(eta) > 1.5)",AdditionalCut.Data());
 }
 if (EEEB == 11) { ///==== EE- + ES
  AdditionalCut = Form("%s && (eta > -2.5 && eta < -1.5)",AdditionalCut.Data());
 }
 if (EEEB == 12) { ///==== EE+ + ES
  AdditionalCut = Form("%s && (eta < 2.5 && eta > 1.5)",AdditionalCut.Data());
 }
 
 std::cout << ">>>>>        :: " << AdditionalCut.Data() << std::endl;

 maxIter = subPSetOptions.getParameter<int> ("numToyMC") ;
 std::cout << ">>>>> Options::numToyMC  " << maxIter  << std::endl;  

 ///==== DATA ====
 fileInDATA = new TFile(inputFileDATA.c_str(),"READ");
 
 ///==== W ====
 fileInMC = new TFile(inputFileMC.c_str(),"READ");

 ///==== output ====
 outFile = new TFile(outputFile.c_str(),"RECREATE");
 outFile->cd();
 

 double ScaleTrue_Chi2;
 double ScaleTrue_Chi2_Fit;
 double ScaleTrue_LL;
 double ScaleTrue_LL_Fit;
 double ScaleTrue_NewChi2;
 double ScaleTrue_NewChi2_Fit;


 ///==== Prepare output trees ====

 myTreeChi2 = new TTree("myTreeChi2","myTreeChi2");
 myTreeChi2->Branch("Data_or_MC",&Data_or_MC,"Data_or_MC/I");
 myTreeChi2->Branch("Alpha",&Alpha,"Alpha/D");
 myTreeChi2->Branch("Chi2",&Chi2,"Chi2/D");
 myTreeChi2->Branch("NewChi2",&NewChi2,"NewChi2/D");
 myTreeChi2->Branch("LL",&LL,"LL/D");
 myTreeChi2->Branch("ScaleTrue",&ScaleTrue,"ScaleTrue/D");

 myTreeChi2_Result = new TTree("myTreeChi2_Result","myTreeChi2_Result");

 myTreeChi2_Result->Branch("Data_or_MC",&Data_or_MC,"Data_or_MC/I");
 myTreeChi2_Result->Branch("AlphaMean",&AlphaMean,"AlphaMean/D");
 myTreeChi2_Result->Branch("AlphaMinus",&AlphaMinus,"AlphaMinus/D");
 myTreeChi2_Result->Branch("AlphaPlus",&AlphaPlus,"AlphaPlus/D");
 myTreeChi2_Result->Branch("AlphaMean_Fit",&AlphaMean_Fit,"AlphaMean_Fit/D");
 myTreeChi2_Result->Branch("AlphaMinus_Fit",&AlphaMinus_Fit,"AlphaMinus_Fit/D");
 myTreeChi2_Result->Branch("AlphaPlus_Fit",&AlphaPlus_Fit,"AlphaPlus_Fit/D");
 myTreeChi2_Result->Branch("ScaleTrue",&ScaleTrue,"ScaleTrue/D");

 myTreeLL_Result = new TTree("myTreeLL_Result","myTreeLL_Result");
 myTreeLL_Result->Branch("Data_or_MC",&Data_or_MC,"Data_or_MC/I");
 myTreeLL_Result->Branch("AlphaMean",&AlphaMean,"AlphaMean/D");
 myTreeLL_Result->Branch("AlphaMinus",&AlphaMinus,"AlphaMinus/D");
 myTreeLL_Result->Branch("AlphaPlus",&AlphaPlus,"AlphaPlus/D");
 myTreeLL_Result->Branch("AlphaMean_Fit",&AlphaMean_Fit,"AlphaMean_Fit/D");
 myTreeLL_Result->Branch("AlphaMinus_Fit",&AlphaMinus_Fit,"AlphaMinus_Fit/D");
 myTreeLL_Result->Branch("AlphaPlus_Fit",&AlphaPlus_Fit,"AlphaPlus_Fit/D");
 myTreeLL_Result->Branch("ScaleTrue",&ScaleTrue,"ScaleTrue/D");

 myTreeNewChi2_Result = new TTree("myTreeNewChi2_Result","myTreeNewChi2_Result");
 myTreeNewChi2_Result->Branch("Data_or_MC",&Data_or_MC,"Data_or_MC/I");
 myTreeNewChi2_Result->Branch("AlphaMean",&AlphaMean,"AlphaMean/D");
 myTreeNewChi2_Result->Branch("AlphaMinus",&AlphaMinus,"AlphaMinus/D");
 myTreeNewChi2_Result->Branch("AlphaPlus",&AlphaPlus,"AlphaPlus/D");
 myTreeNewChi2_Result->Branch("AlphaMean_Fit",&AlphaMean_Fit,"AlphaMean_Fit/D");
 myTreeNewChi2_Result->Branch("AlphaMinus_Fit",&AlphaMinus_Fit,"AlphaMinus_Fit/D");
 myTreeNewChi2_Result->Branch("AlphaPlus_Fit",&AlphaPlus_Fit,"AlphaPlus_Fit/D");
 myTreeNewChi2_Result->Branch("ScaleTrue",&ScaleTrue,"ScaleTrue/D");


 ///==== Prepare input trees ====
 TTree* MyTreeDATA = (TTree*) fileInDATA->Get(treeNameDATA.c_str());

 MyTreeDATA->SetBranchAddress("pT",&pT);
 MyTreeDATA->SetBranchAddress("ET",&ET);
 MyTreeDATA->SetBranchAddress("MT",&MT);
 MyTreeDATA->SetBranchAddress("EoP",&EoP);
 MyTreeDATA->SetBranchAddress("eta",&eta);

 MyTreeDATA->SetBranchAddress("E5x5",&E5x5);
 MyTreeDATA->SetBranchAddress("p",&p);
 MyTreeDATA->SetBranchAddress("eleES",&eleES);
 MyTreeDATA->SetBranchAddress("eleFBrem",&eleFBrem);
 
 TTree* MyTreeMC = (TTree*) fileInMC->Get(treeNameMC.c_str());
 MyTreeMC->SetBranchAddress("pT",&pT);
 MyTreeMC->SetBranchAddress("ET",&ET);
 MyTreeMC->SetBranchAddress("MT",&MT);
 MyTreeMC->SetBranchAddress("EoP",&EoP);
 MyTreeMC->SetBranchAddress("eta",&eta);
 
 MyTreeMC->SetBranchAddress("E5x5",&E5x5);
 MyTreeMC->SetBranchAddress("p",&p);
 MyTreeMC->SetBranchAddress("eleES",&eleES);
 MyTreeMC->SetBranchAddress("eleFBrem",&eleFBrem);
 
 numEntriesMC = MyTreeMC->GetEntries();
 
 ///==== prepare minuit ====

 fitMin->SetRange(MinScanRange,MaxScanRange); 
 
 double step[1] = {0.001};
 double variable[1] = {0.0};
 minuit->SetLimitedVariable(0,"Scale" , variable[0]  , step[0] , MinScan  , MaxScan );
 

///===========================
///==== DATA Scale search ====
 ScaleTrue = -1000; ///==== default
 Data_or_MC = 1; ///=== 1 = Data;  0 = MC;
 numEvents = MyTreeDATA->GetEntries(); //==== number of events in Data sample
 outFile->cd();
 vET_data.clear();
 nIter = 1000000000; ///==== less than 1000000000 iterations at the end !!!
 TString nameDATA = Form("hDATA_%d_%d_%.5f",Data_or_MC,nIter,ScaleTrue);
 TH1F hDATA(nameDATA,nameDATA,numBINS,minBINS,maxBINS);
 
 MyTreeDATA->Draw(">> myList",(AdditionalCut + Form(" && ET > %f",minET)).Data(),"entrylist");
 TEntryList *mylist = (TEntryList*)gDirectory->Get("myList");
 MyTreeDATA->SetEntryList(mylist);
 
 MyTreeDATA->Draw(Form("%s >> %s",variableName.c_str(),nameDATA.Data()));
 ConvertStdVectDouble(vET_data,MyTreeDATA->GetV1(),mylist->GetN());
 
 hDATA.Write();
  
 std::cerr << "... I'm minimizing ... DATA analysis" << std::endl;
 std::cerr << ">>>>>>> numEvents = " << numEvents << " => " << vET_data.size() << " selected (=" << mylist->GetN() << ")" << std::endl;
 numSelectedData = vET_data.size();
 
 
 ///===== Chi2 ====
 std::cerr << " === Chi2 === " << std::endl;
 minuit->SetFunction(functorChi2);

 TGraph * grChi2 = new TGraph(iNoSteps);
 minuit->Scan(iPar_NoBG,iNoSteps,grChi2->GetX(),grChi2->GetY(),MinScan,MaxScan);

// TGraph * grChi2 = new TGraph();
// for (int iStep = 0; iStep < iNoSteps; iStep++){
//  double x = MinScan + (MaxScan - MinScan) / iNoSteps * (iStep+0.5);
//  double y = Chi2F(&x);
//  grChi2->SetPoint(iStep+1,x,y);
// }
 grChi2->Draw("AL");
 outFile->cd();
 minuit->PrintResults();
 outFile->cd();
 grChi2->SetTitle("grChi2");
 grChi2->Write();
 const double *outParametersTemp = minuit->X();
 const double *errParametersTemp = minuit->Errors();
  
 double *outParameters = new double;
 double *errParameters = new double;
 outParameters[0] = outParametersTemp[0];
 errParameters[0] = errParametersTemp[0];
   
 double minChi2 = grChi2->Eval(outParameters[0]);
 std::cerr << " numEvents = " << numEvents << " Scale = " << outParameters[0] << " +/- " << errParameters[0] << std::endl;
 ///===== end Chi2 ====
  
 ///==== likelihood ====
 std::cerr << " === LL === " << std::endl;
 minuit->SetFunction(functorLL);

 TGraph * grLL_temp = new TGraph(iNoSteps);
 minuit->Scan(iPar_NoBG,iNoSteps,grLL_temp->GetX(),grLL_temp->GetY(),MinScan,MaxScan);
 TGraph * grLL = new TGraph();
 grLL->SetName("grLL");
 int nPointLL = 0;
 for (unsigned int iStep = 0; iStep < iNoSteps; iStep++){
  double x = MinScan + (MaxScan - MinScan) / iNoSteps * (iStep+0.5);
  double y = LLFunc(&x);
//  std::cerr << " y = " << y << std::endl;
  if (y != numberDATA * numEvents) {
   std::cerr << " Ok y = " << y << std::endl;
   grLL->SetPoint(nPointLL,x,y);
   nPointLL++;
  }
 }
 
 
 std::cerr << " finito " << std::endl;
 
 grLL->Draw("AL");
 outFile->cd();
 minuit->PrintResults();
 outFile->cd();
 grLL->SetTitle("grLL");
 grLL->Write();
 
 std::cerr << " done " << std::endl;

 const double *outParametersTemp2 = minuit->X();
 const double *errParametersTemp2 = minuit->Errors();

 std::cerr << " done 2 " << std::endl;
  
 double *outParametersLL = new double;
 double *errParametersLL = new double;
 outParametersLL[0] = outParametersTemp2[0];
 errParametersLL[0] = errParametersTemp2[0];
 
 double minLL = grLL->Eval(outParametersLL[0]);
 std::cerr << " numEvents = " << numEvents << " Scale = " << outParametersLL[0] << " +/- " << errParametersLL[0] << std::endl;
 ///==== end likelihood ====
 
 
 ///==== newChi2 ====
 std::cerr << " === newChi2 === " << std::endl;
 minuit->SetFunction(functorNewChi2);
 TGraph * grNewChi2 = new TGraph(iNoSteps);
 minuit->Scan(iPar_NoBG,iNoSteps,grNewChi2->GetX(),grNewChi2->GetY(),MinScan,MaxScan);
 grNewChi2->Draw("AL");
 outFile->cd();
 minuit->PrintResults();
 outFile->cd();
 grNewChi2->SetTitle("grNewChi2");
 grNewChi2->Write();
 const double *outParametersNewChi2 = minuit->X();
 const double *errParametersNewChi2 = minuit->Errors();
 double minNewChi2 = grNewChi2->Eval(outParametersNewChi2[0]);
 std::cerr << " numEvents = " << numEvents << " Scale = " << outParametersNewChi2[0] << " +/- " << errParametersNewChi2[0] << std::endl;
 ///==== end newChi2 ====
  
 
 
 std::cerr << "... Minimized with all methods ..." << std::endl;

 ///==== Save the whole shape of LL/Chi2 ====
 for (unsigned int ii=0; ii < iNoSteps; ii++){
  double X_ii = (MaxScan - MinScan) / iNoSteps * ii + MinScan;
  
  Alpha   = X_ii;
  Chi2    = grChi2->Eval(X_ii);
  LL      = grLL->Eval(X_ii);
  NewChi2 = grNewChi2->Eval(X_ii);
  myTreeChi2->Fill();
 }
  
 ///===== Look for minima =====
  
 ///===== Chi2 ====
 std::cerr << " === Chi2 === " << std::endl;
 std::cerr << "==== min Scan = " << minChi2 << std::endl;
 double errX_low = -9999;
 double errX_up = 9999;
 int err_low = 0;
 int err_up = 0;
 for (unsigned int ii=0; ii < iNoSteps; ii++){
  double X_ii = (MaxScan - MinScan) / iNoSteps * ii + MinScan;
  double here = grChi2->Eval(X_ii);
  if (err_low == 0){
   if (here < (minChi2 + DELTA_CHI2)){
    errX_low = X_ii;
    err_low = 1;
   }
  }
  else if (err_up == 0 && here > (minChi2 + DELTA_CHI2) && X_ii > outParameters[0]){
   errX_up = X_ii; 
   err_up = 1;
  }
 }
 
 AlphaMean = outParameters[0];
 AlphaMinus = errX_low;
 AlphaPlus = errX_up;

 grChi2->Fit("fitMin","RMQ");
 c = fitMin->GetParameter(0);
 b = fitMin->GetParameter(1);
 a = fitMin->GetParameter(2);
 AlphaMean_Fit  = -b / (2*a);
 AlphaMinus_Fit = (-b + 2 * sqrt(a)) / (2*a);  ///==== delta Chi2 = 1 
 AlphaPlus_Fit  = (-b - 2 * sqrt(a)) / (2*a);  ///==== delta Chi2 = 1   
 myTreeChi2_Result->Fill();
  
 ScaleTrue_Chi2 = AlphaMean;
 ScaleTrue_Chi2_Fit = AlphaMean_Fit;

 ///===== LogLikelihood ====
 std::cerr << " === LL === " << std::endl;
 std::cerr << "==== min Scan = " << minLL << std::endl;
 errX_low = -9999;
 errX_up = 9999;
 err_low = 0;
 err_up = 0;
 for (unsigned int ii=0; ii < iNoSteps; ii++){
  double X_ii = (MaxScan - MinScan) / iNoSteps * ii + MinScan;
  double here = grLL->Eval(X_ii);
  if (err_low == 0){
   if (here < (minLL + DELTA_LL)){
    errX_low = X_ii;
    err_low = 1;
   }
  }
  else if (err_up == 0 && here > (minLL + DELTA_LL) && X_ii > outParametersLL[0]){
   errX_up = X_ii; 
   err_up = 1;
  }
 }
 
 AlphaMean = outParametersLL[0];
 AlphaMinus = errX_low;
 AlphaPlus = errX_up;

 grLL->Fit("fitMin","RMQ");
 c = fitMin->GetParameter(0);
 b = fitMin->GetParameter(1);
 a = fitMin->GetParameter(2);
 AlphaMean_Fit  = -b / (2*a);
 AlphaMinus_Fit = (-b + sqrt(2*a)) / (2*a);  ///==== delta LL = 0.5
 AlphaPlus_Fit  = (-b - sqrt(2*a)) / (2*a);  ///==== delta LL = 0.5   
 
 myTreeLL_Result->Fill();
 
 ScaleTrue_LL = AlphaMean;
 ScaleTrue_LL_Fit = AlphaMean_Fit;

 
 ///===== NewChi2 ====
 std::cerr << " === NewChi2 === " << std::endl;
 std::cerr << "==== min Scan = " << minNewChi2 << std::endl;
 errX_low = -9999;
 errX_up = 9999;
 err_low = 0;
 err_up = 0;
 for (unsigned int ii=0; ii < iNoSteps; ii++){
  double X_ii = (MaxScan - MinScan) / iNoSteps * ii + MinScan;
  double here = grNewChi2->Eval(X_ii);
  if (err_low == 0){
   if (here < (minNewChi2 + DELTA_CHI2)){
    errX_low = X_ii;
    err_low = 1;
   }
  }
  else if (err_up == 0 && here > (minNewChi2 + DELTA_CHI2) && X_ii > outParametersNewChi2[0]){
   errX_up = X_ii; 
   err_up = 1;
  }
 }
  
 AlphaMean = outParametersNewChi2[0];
 AlphaMinus = errX_low;
 AlphaPlus = errX_up;
 
 
 grNewChi2->Fit("fitMin","RMQ");
 c = fitMin->GetParameter(0);
 b = fitMin->GetParameter(1);
 a = fitMin->GetParameter(2);
 AlphaMean_Fit  = -b / (2*a);
 AlphaMinus_Fit = (-b + 2 * sqrt(a)) / (2*a);  ///==== delta Chi2 = 1 
 AlphaPlus_Fit  = (-b - 2 * sqrt(a)) / (2*a);  ///==== delta Chi2 = 1   
 
 myTreeNewChi2_Result->Fill();
  
 ScaleTrue_NewChi2 = AlphaMean;
 ScaleTrue_NewChi2_Fit = AlphaMean_Fit;

 std::cerr << " ================ End DATA Scale search ================ " << std::endl;


///==== MC analysis ==== Scale search ====
 Data_or_MC = 0; ///=== 1 = Data;  0 = MC; -1 = MC Fit
 std::cerr << " ==== MC Scale search ==== " << std::endl; 
 ///==== cycle on number of Toy MC experiments ====
 ///=== Chi2 ===
 std::cerr << "======================= Chi2 " << ScaleTrue_Chi2 << " =====================" << std::endl;
//  ScaleTrue = ScaleTrue_Chi2;
//  doMC_Chi2();

///=== LogLikelihood ===
 std::cerr << "======================= LL " << ScaleTrue_LL << " =====================" << std::endl;
//  ScaleTrue = ScaleTrue_LL;
//  doMC_LL();

///=== NewChi2 ===
 std::cerr << "======================= NewChi2 " << ScaleTrue_NewChi2 << " =====================" << std::endl;
//  ScaleTrue = ScaleTrue_NewChi2;
//  doMC_NewChi2();


 Data_or_MC = -1; ///=== 1 = Data;  0 = MC; -1 = MC Fit
 std::cerr << " ==== MC Scale search ==== " << std::endl; 
 ///==== cycle on number of Toy MC experiments ====
 ///=== Chi2 ===
 std::cerr << "======================= Chi2 FIT " << ScaleTrue_Chi2_Fit << " =====================" << std::endl;
//  ScaleTrue = ScaleTrue_Chi2_Fit;
//  doMC_Chi2();

///=== LogLikelihood ===
 std::cerr << "======================= LL FIT " << ScaleTrue_LL_Fit << " =====================" << std::endl;
 ScaleTrue = ScaleTrue_LL_Fit;
 doMC_LL();

///=== NewChi2 ===
 std::cerr << "======================= NewChi2 FIT " << ScaleTrue_NewChi2_Fit << " =====================" << std::endl;
//  ScaleTrue = ScaleTrue_NewChi2_Fit;
//  doMC_NewChi2();

 
  ///----------------------
  ///---- Plot results ----
  ///----------------------
  outFile->cd();
  myTreeChi2->Write();
  myTreeLL_Result->Write();
  myTreeChi2_Result->Write();
  myTreeNewChi2_Result->Write();
  delete fitMin;
  
}
Exemple #9
0
///**** NewChi2 ****
void doMC_NewChi2(){
 TTree* MyTreeMC = (TTree*) fileInMC->Get(treeNameMC.c_str());
 for (nIter = 0; nIter<maxIter; nIter++){
  if (!(nIter%1)) std::cerr << ">>> nIter = " << nIter << " : " << maxIter << std::endl;
  vET_data.clear();
  outFile->cd();
  TString nameDATA = Form("hDATA_%d_%d_%.5f",Data_or_MC,nIter,ScaleTrue);
  TH1F hDATA(nameDATA,nameDATA,numBINS,minBINS,maxBINS);
  
  MyTreeMC->Draw(">> myListMC",(AdditionalCut+Form("&& (ET * (1+(%f)))>%f",ScaleTrue,minET)).Data(),"entrylist");
  TEntryList *myListMC = (TEntryList*)gDirectory->Get("myListMC");

  MyTreeMC->SetEntryList(0); 
  TEntryList *listMCHere = new TEntryList("listMCHere","listMCHere");    
  for (int iEvt = 0; iEvt < numSelectedData; iEvt ++){
   listMCHere->Enter(myListMC->GetEntry(gRandom->Uniform(0,myListMC->GetN())));
  }
 
 MyTreeMC->SetEntryList(listMCHere);
 MyTreeMC->Draw(Form("(1+%f) * %s >> %s",ScaleTrue,variableName.c_str(),nameDATA.Data()));
  
 ConvertStdVectDouble(vET_data,MyTreeMC->GetV1(),numSelectedData);
   
  ///==== newChi2 ====
  minuit->SetFunction(functorNewChi2);
  TGraph * grNewChi2 = new TGraph(iNoSteps);
  minuit->Scan(iPar_NoBG,iNoSteps,grNewChi2->GetX(),grNewChi2->GetY(),MinScan,MaxScan);
  grNewChi2->Draw("AL");
  outFile->cd();
  minuit->PrintResults();
  const double *outParametersNewChi2 = minuit->X();
  const double *errParametersNewChi2 = minuit->Errors();
 
  double minNewChi2 = grNewChi2->Eval(outParametersNewChi2[0]);
  ///==== end newChi2 ====
 
  ///==== Save the whole shape of LL/Chi2 ====
  for (unsigned int ii=0; ii < iNoSteps; ii++){
   double X_ii = (MaxScan - MinScan) / iNoSteps * ii + MinScan;
   
   Alpha   = X_ii;
   Chi2    = 0;
   LL      = 0;
   NewChi2 = grNewChi2->Eval(X_ii);
   
   myTreeChi2->Fill();
  }
  

  ///===== Look for minima =====
  double a;
  double b;
  double c;
  
  double errX_low = -9999;
  double errX_up = 9999;
  int err_low = 0;
  int err_up = 0;
  for (unsigned int ii=0; ii < iNoSteps; ii++){
   double X_ii = (MaxScan - MinScan) / iNoSteps * ii + MinScan;
   double here = grNewChi2->Eval(X_ii);
   if (err_low == 0){
    if (here < (minNewChi2 + DELTA_CHI2)){
     errX_low = X_ii;
     err_low = 1;
    }
   }
   else if (err_up == 0 && here > (minNewChi2 + DELTA_CHI2) && X_ii > outParametersNewChi2[0]){
    errX_up = X_ii; 
    err_up = 1;
   }
  }
  
  AlphaMean = outParametersNewChi2[0];
  AlphaMinus = errX_low;
  AlphaPlus = errX_up;
  
  
  grNewChi2->Fit("fitMin","RMQ");
  c = fitMin->GetParameter(0);
  b = fitMin->GetParameter(1);
  a = fitMin->GetParameter(2);
  AlphaMean_Fit  = -b / (2*a);
  AlphaMinus_Fit = (-b + 2 * sqrt(a)) / (2*a);  ///==== delta Chi2 = 1 
  AlphaPlus_Fit  = (-b - 2 * sqrt(a)) / (2*a);  ///==== delta Chi2 = 1   
  
  myTreeNewChi2_Result->Fill();
  
 // delete listMCHere;
 }
 
}
Exemple #10
0
///**** LL ****
void doMC_LL(){
 TTree* MyTreeMC = (TTree*) fileInMC->Get(treeNameMC.c_str());

 for (nIter = 0; nIter<maxIter; nIter++){
  if (!(nIter%1)) std::cerr << ">>> nIter = " << nIter << " : " << maxIter << std::endl;
  vET_data.clear();
  outFile->cd();
  TString nameDATA = Form("hDATA_%d_%d_%.5f",Data_or_MC,nIter,ScaleTrue);
  TH1F hDATA(nameDATA,nameDATA,numBINS,minBINS,maxBINS);
  
  MyTreeMC->Draw(">> myListMC",(AdditionalCut+Form("&& (ET * (1+(%f)))>%f",ScaleTrue,minET)).Data(),"entrylist");
  TEntryList *myListMC = (TEntryList*)gDirectory->Get("myListMC");
  
  MyTreeMC->SetEntryList(0); 
  TEntryList *listMCHere = new TEntryList("listMCHere","listMCHere");    
  for (int iEvt = 0; iEvt < numSelectedData; iEvt ++){
   listMCHere->Enter(myListMC->GetEntry(gRandom->Uniform(0,myListMC->GetN())));
  }
  
  MyTreeMC->SetEntryList(listMCHere);
  MyTreeMC->Draw(Form("(1+%f) * %s >> %s",ScaleTrue,variableName.c_str(),nameDATA.Data()));
  
  ConvertStdVectDouble(vET_data,MyTreeMC->GetV1(),numSelectedData);
  
  ///==== likelihood ====
 std::cerr << " === LL === " << std::endl;
 std::cerr << " === pseudo vET_data.size() = " << vET_data.size() << std::endl;
 
 
  minuit->SetFunction(functorLL); 
  TGraph * grLL_temp = new TGraph(iNoSteps);
  minuit->Scan(iPar_NoBG,iNoSteps,grLL_temp->GetX(),grLL_temp->GetY(),MinScan,MaxScan);
  TGraph * grLL = new TGraph();
  int nPointLL = 0;
 for (unsigned int iStep = 0; iStep < iNoSteps; iStep++){
   double x = MinScan + (MaxScan - MinScan) / iNoSteps * (iStep+0.5);
   double y = LLFunc(&x);
   if (y != numberDATA * numEvents) {
    grLL->SetPoint(nPointLL,x,y);
    nPointLL++;
   }
  }
  grLL->Draw("AL");
  outFile->cd();
  minuit->PrintResults();
  const double *outParametersTemp2 = minuit->X();
  const double *errParametersTemp2 = minuit->Errors();
  
  double *outParametersLL = new double;
  double *errParametersLL = new double;
  outParametersLL[0] = outParametersTemp2[0];
  errParametersLL[0] = errParametersTemp2[0];
  
  std::cerr << " nPointLL = " << nPointLL << std::endl;
  
  double minLL = grLL->Eval(outParametersLL[0]);
  ///==== end likelihood ====
  
    ///==== Save the whole shape of LL/Chi2 ====
  for (unsigned int ii=0; ii < iNoSteps; ii++){
   double X_ii = (MaxScan - MinScan) / iNoSteps * ii + MinScan;
   
   Alpha   = X_ii;
   Chi2    = 0;
   LL      = grLL->Eval(X_ii);
   NewChi2 = 0;
   
   myTreeChi2->Fill();
  }

  ///===== Look for minima =====
  double a;
  double b;
  double c;
  
  
  double errX_low = -9999;
  double errX_up = 9999;
  int err_low = 0;
  int err_up = 0;
  for (unsigned int ii=0; ii < iNoSteps; ii++){
   double X_ii = (MaxScan - MinScan) / iNoSteps * ii + MinScan;
   double here = grLL->Eval(X_ii);
   if (err_low == 0){
    if (here < (minLL + DELTA_LL)){
     errX_low = X_ii;
     err_low = 1;
    }
   }
   else if (err_up == 0 && here > (minLL + DELTA_LL) && X_ii > outParametersLL[0]){
    errX_up = X_ii; 
    err_up = 1;
   }
  }
  
  AlphaMean = outParametersLL[0];
  AlphaMinus = errX_low;
  AlphaPlus = errX_up;
 
  grLL->Fit("fitMin","RMQ");
  c = fitMin->GetParameter(0);
  b = fitMin->GetParameter(1);
  a = fitMin->GetParameter(2);
  AlphaMean_Fit  = -b / (2*a);
  AlphaMinus_Fit = (-b + sqrt(2*a)) / (2*a);  ///==== delta LL = 0.5
  AlphaPlus_Fit  = (-b - sqrt(2*a)) / (2*a);  ///==== delta LL = 0.5   
  
  myTreeLL_Result->Fill();
 
  grLL->Write();
  
  //delete listMCHere;
  
 }
}
int main() {
	Int_t nbins = 800, count = 0;
    Double_t integral;
	TFile *input = new TFile("FilterRMSComparison.root");
    TFile *templatefile = new TFile("/home/marko/Desktop/H4Analysis/ntuples/Templates_APDs.old.root");
	TTree *MyTree = (TTree*) input->Get("RMS");
    TCanvas *can1 = new TCanvas("can1", "canvas", 1200,900);
    TCanvas *can2 = new TCanvas("can2", "canvas", 1200,1200);
    TCanvas *can3 = new TCanvas("can3", "canvas", 1200,1200);
    can1->Divide(1,3);
    can2->Divide(1,2);
    can3->Divide(1,2);
    MyTree->SetEntryList(0);
    TString listcut = "abs(unfilteredbslope)<6 && unfilteredampfit>700";
    MyTree->Draw(">>myList", listcut, "entrylist");
    TEntryList *myList = (TEntryList*) gDirectory->Get("myList");
    MyTree->SetEntryList(myList);
    Int_t nevents = myList->GetN();
	MyTree->Draw("unfilteredevent", "abs(unfilteredbslope)<6 && unfilteredampfit>700", "goff");
    Double_t *vTemp = MyTree->GetV1();
    Int_t *vEvent = new Int_t[nevents];
    for (int iEntry = 0; iEntry<nevents; iEntry++) {
        vEvent[iEntry] = vTemp[iEntry];
    }
	TString plot, plot2, cut;
	char name[50];
    TH1F *histoave = new TH1F("histoave","Wave Pulse Average", nbins, -40, 120);
    TH1F *histoavefft = new TH1F("histoavefft","Wave Pulse Average FFT", nbins, 0, 5);
    TH1F *histoaveph = new TH1F("histoaveph","Wave Pulse Average Phase", nbins, 0, 800);
    TH1F *originaltemplate = (TH1F*) templatefile->Get("APD2_E50_G50_prof");
    originaltemplate->Rebin(16);
    TH1F *templatehisto = new TH1F("templatehisto", "Template = Green, Average = Red", nbins, -40, 120); 
    TH1F *difference = new TH1F("difference","Template vs. Average Difference", nbins, -40, 120);
    TH1F *percentdifference = new TH1F("percentdifference","Template vs. Average Percent Difference", nbins, -40, 120);
    for (Int_t i=0;i<nbins;i++) {
        templatehisto->SetBinContent(i+1, originaltemplate->GetBinContent(i+1));
    }
    templatehisto->SetLineColor(kGreen+3);
    templatehisto->SetLineWidth(4);
    can2->cd(2);
    histoave->GetYaxis()->SetRangeUser(-.120,1.2);
    //templatehisto->Draw();
    histoave->SetStats(0);
    histoave->Draw();
	for (Int_t i=0;i<nevents;i++) {
    //for (Int_t i=0;i<10;i++) {
        if (vEvent[i]==513) continue; //event for which electronics die out for a bit halfway through
		TString histoname = "TempHisto_";
        histoname += i;
        TString histoname2 = "TempHisto2_";
        histoname2 += i;
        TH2F* TempHisto = new TH2F (histoname, "Temp Histo", nbins, -40, 120, 1000, -120, 800); //nanoseconds
        TH2F* TempHisto2 = new TH2F (histoname2, "Temp Histo", nbins, -40, 120, 1000, -120, 800); //nanoseconds
        TString h1name = "h1001_";
        h1name += i;
        TString h1name2 = "h1002_";
        h1name2 += i;
        TString h1name2fft = "h1002fft_";
        h1name2 += i;
        TString h1name2ph = "h1002ph_";
        h1name2 += i;
        TString h1name3 = "h1003_";
        h1name3 += i;
        TString h1name4 = "h1004_";
        h1name4 += i;
        TH1F *h1001 = new TH1F(h1name,"Red = Unfiltered, Blue = Filtered", nbins, -40, 120);
        TH1F *h1002 = new TH1F(h1name2,"h1002", nbins, -40, 120);
        TH1F *h1002fft = new TH1F(h1name2fft,"h1002fft", nbins, 0, 5);
        TH1F *h1002ph = new TH1F(h1name2ph,"h1002ph", nbins, 0, 800);
        TH1F *h1003 = new TH1F(h1name3,"Filtered WF - Unfiltered WF", nbins, -40, 120);
        TH1F *h1004 = new TH1F(h1name4,"Percent Change in Filtered WF - Unfiltered WF", nbins, -40, 120);
        plot = "unfilteredwfval:(unfilteredwftime-unfilteredtimeref)>>";
        plot += histoname;
        plot2 = "filteredwfval:(filteredwftime-filteredtimeref)>>";
        plot2 += histoname2;
        cut = "abs(unfilteredbslope)<6 && unfilteredampfit>700 && unfilteredevent==";
        cut += vEvent[i];
        MyTree->Draw(plot, cut, "goff");
        TempHisto = (TH2F*) gDirectory->Get(histoname);
        h1001 = transform2Dto1D(TempHisto);
        MyTree->Draw(plot2, cut, "goff");
        TempHisto2 = (TH2F*) gDirectory->Get(histoname2);
        h1002 = transform2Dto1D(TempHisto2);
        if (h1002->GetBinCenter(h1002->GetMaximumBin()) < 30) continue;
        sprintf(name, "Good Events/Event%d", vEvent[i]);
        strcat(name, ".png");
        h1001->SetLineColor(kRed);
        h1002->SetLineColor(kBlue);
        h1001->SetStats(0);
        h1002->SetStats(0);
        //can1->cd(1);
        can1->cd();
        h1001->GetXaxis()->SetTitle("Time (ns)");
        h1001->GetYaxis()->SetTitle("Amplitude");
        h1001->Draw();
        h1002->Draw("same");
        //for (Int_t i=0;i<nbins;i++) {
        //    h1003->SetBinContent(i+1, (h1002->GetBinContent(i+1))-(h1001->GetBinContent(i+1)));
        //    if (h1001->GetBinContent(i+1) != 0) h1004->SetBinContent(i+1, ((h1002->GetBinContent(i+1))-(h1001->GetBinContent(i+1)))/(h1001->GetBinContent(i+1)));
        //    else h1004->SetBinContent(i+1, 0);
        //}
        //can1->cd(2);
        //h1003->Draw();
        //can1->cd(3);
        //h1004->Draw();
        //h1004->GetYaxis()->SetRangeUser(-0.1,0.1);
        //gPad->SetGrid();
        can1->SaveAs(name);
        //h1002->FFT(h1002fft, "MAG");
        //h1002->FFT(h1002ph, "PH");
        //histoavefft->Add(histoavefft, h1002fft);
        //histoaveph->Add(histoaveph, h1002ph);
        histoave->Add(histoave, h1002);
        can2->cd(2);
        h1002->Scale(1./(h1002->GetMaximum()));
        h1002->Draw("same");
        count++;
        delete TempHisto, TempHisto2, h1001, h1002, h1003, h1004, histoname, histoname2, h1name, h1name2, h1name3, h1name4;
        gDirectory->Clear();
	}
    can2->cd(1);
    //histoavefft->Scale(1./count);
    //histoaveph->Scale(1./count);
    histoave->Scale(1./count);
    
    //Double_t *re_full = new Double_t[nbins];
    //Double_t *im_full = new Double_t[nbins];
    //TH1 *Throwaway = 0;
    //TH1F *invhistoave = new TH1F(invhistoave, "Average Pulse", nbins, -40, 120);
    //TVirtualFFT *invFFT = TVirtualFFT::FFT(1, &nbins, "C2R M K");
    //for (Int_t n=0; n<nbins; n++) {
    //    (re_full)[n]=(histoavefft->GetBinContent(n+1)*cos(histoaveph->GetBinContent(n+1)));
    //    (im_full)[n]=(histoavefft->GetBinContent(n+1)*sin(histoaveph->GetBinContent(n+1)));
    //}
    //invFFT->SetPointsComplex(re_full, im_full);
    //invFFT->Transform();
    //Throwaway = TH1::TransformHisto(invFFT, Throwaway, "Re");
    //for (Int_t p=0; p<nbins; p++) {
    //    histoave->SetBinContent(p+1, Throwaway->GetBinContent(p+1)/nbins);
    //}
    histoave->Scale(1./(histoave->GetMaximum()));
    histoave->SetLineColor(kRed);
    histoave->SetLineWidth(4);
    integral = templatehisto->Integral();
    templatehisto->Scale(1./integral);
    templatehisto->SetStats(0);
    templatehisto->Draw();
    integral = histoave->Integral();
    histoave->Scale(1./integral);
    histoave->DrawClone("same");
    histoave->Scale(integral);
    can2->cd(2);
    histoave->GetXaxis()->SetTitle("Time (ns)");
    histoave->GetYaxis()->SetTitle("Normalized Amplitude");
    histoave->DrawClone("same");
    can2->SaveAs("AmpSpread.png");
    can2->SaveAs("AmpSpreadRoot.root");
    TFile *output = new TFile("Alignment.root", "recreate");
    output->cd();
    originaltemplate->Write();
    histoave->Write();
    templatehisto->Write();
    output->Close();
    can3->cd(1);
    histoave->Scale(1./integral);
    for (int i=0;i<nbins;i++) {
        difference->SetBinContent(i+1, histoave->GetBinContent(i+1) - templatehisto->GetBinContent(i+1));
        if (templatehisto->GetBinContent(i+1) != 0) percentdifference->SetBinContent(i+1, (histoave->GetBinContent(i+1) - templatehisto->GetBinContent(i+1))/templatehisto->GetBinContent(i+1));
        else percentdifference->SetBinContent(i+1, 0);
    }
    difference->GetXaxis()->SetTitle("Time (ns)");
    difference->GetYaxis()->SetTitle("Average - Template");
    difference->SetStats(0);
    difference->Draw();
    can3->cd(2);
    percentdifference->GetXaxis()->SetTitle("Time (ns)");
    percentdifference->GetYaxis()->SetTitle("Percent Difference Average - Template");
    percentdifference->SetStats(0);
    percentdifference->Draw();
    percentdifference->GetYaxis()->SetRangeUser(-0.1,0.1);
    gPad->SetGrid();
    can3->SaveAs("Difference.png");
    can3->SaveAs("Difference.root");
}
int main() {
    Int_t nbins = 800, j;
    char name[20], title[100];
    TStopwatch t;
    TFile f1("/home/marko/Desktop/H4Analysis/ntuples/analysis_3898.root"); //Run 3898 ntuple
    TFile f2("/home/marko/Desktop/H4Analysis/ntuples/analysis_3902.root"); //Run 3902 ntuple
    TFile f3("/home/marko/Desktop/H4Analysis/ntuples/analysis_3905.root"); //Run 3905 ntuple
    TTree* h4_3898 = (TTree*) f1.Get("h4");
    TTree* h4_3902 = (TTree*) f2.Get("h4");
    TTree* h4_3905 = (TTree*) f3.Get("h4");
    TFile outputfile("AllPedestalEventFFTs.root", "recreate"); //individual event noise spectra
    Int_t nentries1 = h4_3898->GetEntries("WF_ch==APD1 && amp_max[APD3]<25 && b_rms[APD3]<5. && charge_tot[APD3]<20000 &&  amp_max[APD5]<25 && b_rms[APD5]<5. &&  amp_max[APD6]<25 && b_rms[APD6]<5. &&  amp_max[APD4]<25 && b_rms[APD4]<5. && amp_max[SiPM1]<20 && amp_max[SiPM2]<20 && amp_max[APD1]<40 && amp_max[APD2]<40 && b_rms[APD1]<5. && b_rms[APD2]<5. && WF_time<160");
    Int_t nentries2 = h4_3902->GetEntries("WF_ch==APD1 && amp_max[APD3]<25 && b_rms[APD3]<5. && charge_tot[APD3]<20000 &&  amp_max[APD5]<25 && b_rms[APD5]<5. &&  amp_max[APD6]<25 && b_rms[APD6]<5. &&  amp_max[APD4]<25 && b_rms[APD4]<5. && amp_max[SiPM1]<20 && amp_max[SiPM2]<20 && amp_max[APD1]<40 && amp_max[APD2]<40 && b_rms[APD1]<5. && b_rms[APD2]<5. && WF_time<160");
    Int_t nentries3 = h4_3905->GetEntries("WF_ch==APD1 && amp_max[APD3]<25 && b_rms[APD3]<5. && charge_tot[APD3]<20000 &&  amp_max[APD5]<25 && b_rms[APD5]<5. &&  amp_max[APD6]<25 && b_rms[APD6]<5. &&  amp_max[APD4]<25 && b_rms[APD4]<5. && amp_max[SiPM1]<20 && amp_max[SiPM2]<20 && amp_max[APD1]<40 && amp_max[APD2]<40 && b_rms[APD1]<5. && b_rms[APD2]<5. && WF_time<160");
    Int_t entriestotal = nentries1 + nentries2 + nentries3;
    Int_t nspill = 15; //how many spills will be analyzed (not all spills necessarily have data)
    TH1F *HistoEvent[entriestotal];
    for (Int_t z=0;z<entriestotal;z++) {
        sprintf(name,"HistoEvent%d",z);
        sprintf(title,"Event%d Histo", z);
        HistoEvent[z] = new TH1F(name,title,nbins, -0.1, 159.9);
    }
    TH1F *NewHistoEvent[entriestotal];
    for (Int_t z=0;z<entriestotal;z++) {
        sprintf(name,"NewHistoEvent%d",z);
        sprintf(title,"Event%d Histo", z);
        NewHistoEvent[z] = new TH1F(name,title,nbins, -0.1, 159.9);
    }
    TH1F *NewHistoEventFFT[entriestotal];
    for (Int_t z=0;z<entriestotal;z++) {
        sprintf(name,"NewHistoEventFFT%d",z);
        sprintf(title,"Event%d Histo", z);
        NewHistoEventFFT[z] = new TH1F(name,title,nbins, 0, 5);
    }
    TH1F* NormNoiseFFT = new TH1F ("NormNoiseFFT", "Normalized Noise FFT", nbins, 0, 5);
    Int_t count = 0;
    t.Start();
    for (Int_t spill=0;spill<nspill;spill++) {
        cout << "Run 3898 Spill " << spill << endl;
        h4_3898->SetEntryList(0);
        TString listcut = "WF_ch==APD1 && amp_max[APD3]<25 && b_rms[APD3]<5. && charge_tot[APD3]<20000 &&  amp_max[APD5]<25 && b_rms[APD5]<5. &&  amp_max[APD6]<25 && b_rms[APD6]<5. &&  amp_max[APD4]<25 && b_rms[APD4]<5. && amp_max[SiPM1]<20 && amp_max[SiPM2]<20 && amp_max[APD1]<40 && amp_max[APD2]<40 && b_rms[APD1]<5. && b_rms[APD2]<5. && WF_time<160 && spill==";
        listcut += spill;
        TString spillcut = "spill==";
        spillcut += spill;
        h4_3898->Draw(">>myList", listcut, "entrylist");
        TEntryList *myList = (TEntryList*) gDirectory->Get("myList");
        h4_3898->SetEntryList(myList);
        Int_t entriesperspill = myList->GetN();
        h4_3898->Draw("event", spillcut, "goff");
        Double_t *vTemp = h4_3898->GetV1();
        Double_t *vEvent = new Double_t[entriesperspill];
        for (int iEntry = 0; iEntry<entriesperspill; iEntry++){
            vEvent[iEntry] = vTemp[iEntry];
        }
        Double_t mean. rms;
        TString plot, cut;
        for (j=0;j<entriesperspill;j++) {
            TString histoname = "Run3898TempHisto_";
            histoname += spill;
            histoname += "_";
            histoname += j;
            TH2F* TempHisto = new TH2F (histoname, "Temp Histo", nbins, -0.1, 159.9, 1000, -15, 15);
            plot = "WF_val:WF_time>>";
            plot += histoname;
            cut = "WF_ch==APD1 && amp_max[APD3]<25 && b_rms[APD3]<5. && charge_tot[APD3]<20000 &&  amp_max[APD5]<25 && b_rms[APD5]<5. &&  amp_max[APD6]<25 && b_rms[APD6]<5. &&  amp_max[APD4]<25 && b_rms[APD4]<5. && amp_max[SiPM1]<20 && amp_max[SiPM2]<20 && amp_max[APD1]<40 && amp_max[APD2]<40 && b_rms[APD1]<5. && b_rms[APD2]<5. && WF_time<160 && spill==";
            cut += spill;
            cut += " && event==";
            cut += vEvent[j];
            h4_3898->Draw(plot, cut, "goff");
            TempHisto = (TH2F*) gDirectory->Get(histoname);
            if (TempHisto->GetMaximum() == 0) {
                continue;
            }
            HistoEvent[count] = transform2Dto1D(TempHisto);
            mean = TempHisto->GetMean(2);
            rms = TempHisto->GetRMS(2);
            for (Int_t q=0;q<nbins;q++) {
                NewHistoEvent[count]->SetBinContent(q+1, HistoEvent[count]->GetBinContent(q+1)-mean); //centering the pedestal at <y> = 0
            }
            NewHistoEvent[count]->Scale(1/rms); //dividing by RMS of pedestal event, later undone when the filter is applied to the wave pulses
            NewHistoEvent[count]->FFT(NewHistoEventFFT[count], "MAG"); //noise power spectrum (frequency domain)
            NormNoiseFFT->Add(NormNoiseFFT, NewHistoEventFFT[count]);
            NewHistoEventFFT[count]->Write();
            cout << "Event " << count+1 << " out of " << entriestotal << endl;
            count += 1;
            delete TempHisto;
        }
    }
    for (Int_t spill=0;spill<nspill;spill++) {
        cout << "Run 3902 Spill " << spill << endl;
        h4_3902->SetEntryList(0);
        TString listcut = "WF_ch==APD1 && amp_max[APD3]<25 && b_rms[APD3]<5. && charge_tot[APD3]<20000 &&  amp_max[APD5]<25 && b_rms[APD5]<5. &&  amp_max[APD6]<25 && b_rms[APD6]<5. &&  amp_max[APD4]<25 && b_rms[APD4]<5. && amp_max[SiPM1]<20 && amp_max[SiPM2]<20 && amp_max[APD1]<40 && amp_max[APD2]<40 && b_rms[APD1]<5. && b_rms[APD2]<5. && WF_time<160 && spill==";
        listcut += spill;
        TString spillcut = "spill==";
        spillcut += spill;
        h4_3902->Draw(">>myList", listcut, "entrylist");
        TEntryList *myList = (TEntryList*) gDirectory->Get("myList");
        h4_3902->SetEntryList(myList);
        Int_t entriesperspill = myList->GetN();
        h4_3902->Draw("event", spillcut, "goff");
        Double_t *vTemp = h4_3902->GetV1();
        Double_t *vEvent = new Double_t[entriesperspill];
        for (int iEntry = 0; iEntry<entriesperspill; iEntry++){
            vEvent[iEntry] = vTemp[iEntry];
        }
        Double_t mean, rms;
        TString plot, cut;
        for (j=0;j<entriesperspill;j++) {
            TString histoname = "Run3902TempHisto_";
            histoname += spill;
            histoname += "_";
            histoname += j;
            TH2F* TempHisto = new TH2F (histoname, "Temp Histo", nbins, -0.1, 159.9, 1000, -15, 15);
            plot = "WF_val:WF_time>>";
            plot += histoname;
            cut = "WF_ch==APD1 && amp_max[APD3]<25 && b_rms[APD3]<5. && charge_tot[APD3]<20000 &&  amp_max[APD5]<25 && b_rms[APD5]<5. &&  amp_max[APD6]<25 && b_rms[APD6]<5. &&  amp_max[APD4]<25 && b_rms[APD4]<5. && amp_max[SiPM1]<20 && amp_max[SiPM2]<20 && amp_max[APD1]<40 && amp_max[APD2]<40 && b_rms[APD1]<5. && b_rms[APD2]<5. && WF_time<160 && spill==";
            cut += spill;
            cut += " && event==";
            cut += vEvent[j];
            h4_3902->Draw(plot, cut, "goff");
            TempHisto = (TH2F*) gDirectory->Get(histoname);
            if (TempHisto->GetMaximum() == 0) {
                continue;
            }
            HistoEvent[count] = transform2Dto1D(TempHisto);
            mean = TempHisto->GetMean(2);
            rms = TempHisto->GetRMS(2);
            for (Int_t q=0;q<nbins;q++) {
                NewHistoEvent[count]->SetBinContent(q+1, HistoEvent[count]->GetBinContent(q+1)-mean);
            }
            NewHistoEvent[count]->Scale(1/rms);
            NewHistoEvent[count]->FFT(NewHistoEventFFT[count], "MAG");
            NormNoiseFFT->Add(NormNoiseFFT, NewHistoEventFFT[count]);
            NewHistoEventFFT[count]->Write();
            cout << "Event " << count+1 << " out of " << entriestotal << endl;
            count += 1;
            delete TempHisto;
        }
    }
    for (Int_t spill=1;spill<2;spill++) {
        cout << "Run 3905 Spill " << spill << endl;
        h4_3905->SetEntryList(0);
        TString listcut = "WF_ch==APD1 && amp_max[APD3]<25 && b_rms[APD3]<5. && charge_tot[APD3]<20000 &&  amp_max[APD5]<25 && b_rms[APD5]<5. &&  amp_max[APD6]<25 && b_rms[APD6]<5. &&  amp_max[APD4]<25 && b_rms[APD4]<5. && amp_max[SiPM1]<20 && amp_max[SiPM2]<20 && amp_max[APD1]<40 && amp_max[APD2]<40 && b_rms[APD1]<5. && b_rms[APD2]<5. && WF_time<160 && spill==";
        listcut += spill;
        TString spillcut = "spill==";
        spillcut += spill;
        h4_3905->Draw(">>myList", listcut, "entrylist");
        TEntryList *myList = (TEntryList*) gDirectory->Get("myList");
        h4_3905->SetEntryList(myList);
        Int_t entriesperspill = myList->GetN();
        h4_3905->Draw("event", spillcut, "goff");
        Double_t *vTemp = h4_3905->GetV1();
        Double_t *vEvent = new Double_t[entriesperspill];
        for (int iEntry = 0; iEntry<entriesperspill; iEntry++){
            vEvent[iEntry] = vTemp[iEntry];
        }
        Double_t mean, rms;
        TString plot, cut;
        for (j=0;j<entriesperspill;j++) {
            TString histoname = "Run3905TempHisto_";
            histoname += spill;
            histoname += "_";
            histoname += j;
            TH2F* TempHisto = new TH2F (histoname, "Temp Histo", nbins, -0.1, 159.9, 1000, -15, 15);
            plot = "WF_val:WF_time>>";
            plot += histoname;
            cut = "WF_ch==APD1 && amp_max[APD3]<25 && b_rms[APD3]<5. && charge_tot[APD3]<20000 &&  amp_max[APD5]<25 && b_rms[APD5]<5. &&  amp_max[APD6]<25 && b_rms[APD6]<5. &&  amp_max[APD4]<25 && b_rms[APD4]<5. && amp_max[SiPM1]<20 && amp_max[SiPM2]<20 && amp_max[APD1]<40 && amp_max[APD2]<40 && b_rms[APD1]<5. && b_rms[APD2]<5. && WF_time<160 && spill==";
            cut += spill;
            cut += " && event==";
            cut += vEvent[j];
            h4_3905->Draw(plot, cut, "goff");
            TempHisto = (TH2F*) gDirectory->Get(histoname);
            if (TempHisto->GetMaximum() == 0) {
                continue;
            }
            HistoEvent[count] = transform2Dto1D(TempHisto);
            mean = TempHisto->GetMean(2);
            rms = TempHisto->GetRMS(2);
            for (Int_t q=0;q<nbins;q++) {
                NewHistoEvent[count]->SetBinContent(q+1, HistoEvent[count]->GetBinContent(q+1)-mean);
            }
            NewHistoEvent[count]->Scale(1/rms);
            NewHistoEvent[count]->FFT(NewHistoEventFFT[count], "MAG");
            NormNoiseFFT->Add(NormNoiseFFT, NewHistoEventFFT[count]);
            HistoEvent[count]->Write();
            NewHistoEventFFT[count]->Write();
            cout << "Event " << count+1 << " out of " << entriestotal << endl;
            count += 1;
            delete TempHisto;
        }
    }
    TFile out("AllNormalizedNoiseFFT.root", "recreate");
    NormNoiseFFT->Scale(1./count);
    NormNoiseFFT->Write();
    t.Stop();
    t.Print();
}