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; 
 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] = {
  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");
 
 double LUMI = gConfigParser -> readDoubleOption("Input::Lumi");
 
 double LumiSyst = gConfigParser -> readDoubleOption("Input::LumiSyst");
 
 double Discovery = gConfigParser -> readDoubleOption("Input::Discovery");
 
 std::vector<std::string> SignalName;
 SignalName = gConfigParser -> readStringListOption("Input::SignalName");
 
 ///==== PU reweight (begin) ====
 std::vector<double> PUMC   = gConfigParser -> readDoubleListOption("PU::PUMC");
 std::vector<double> PUDATA = gConfigParser -> readDoubleListOption("PU::PUDATA");
 PUclass PU;
 
 std::cout << " PUMC.size()   = " << PUMC.size()   << std::endl;
 std::cout << " PUDATA.size() = " << PUDATA.size() << std::endl;
 
 if (PUMC.size() != PUDATA.size()) {
  std::cerr << " ERROR " << std::endl;
  return 1;
 }
 
 double sumPUMC = 0;
 for (int itVPU = 0; itVPU < PUMC.size(); itVPU++ ){
  sumPUMC += PUMC.at(itVPU);  
 }
 double sumPUDATA = 0;
 for (int itVPU = 0; itVPU < PUDATA.size(); itVPU++ ){
  sumPUDATA += PUDATA.at(itVPU);  
 } 
 
 for (int itVPU = 0; itVPU < PUMC.size(); itVPU++ ){
  PU.PUWeight.push_back(PUDATA.at(itVPU) / PUMC.at(itVPU) * sumPUMC / sumPUDATA);
 }

 PU.Write("autoWeight.cxx");
 gROOT->ProcessLine(".L autoWeight.cxx");
 ///==== PU reweight (end) ====
 
 ///==== save PU distribution in TH1F ====
 TH1F* hPUMC   = new TH1F("hPUMC","hPUMC",PUMC.size(),0,PUMC.size());
 TH1F* hPUDATA = new TH1F("hPUDATA","hPUDATA",PUDATA.size(),0,PUDATA.size());
 TH1F* hPUWeight = new TH1F("hPUWeight","hPUWeight",PUDATA.size(),0,PUDATA.size());
 
 for (int itVPU = 0; itVPU < PUMC.size(); itVPU++ ){
  hPUMC     -> SetBinContent(itVPU+1,PUMC.at(itVPU) / sumPUMC);
  hPUDATA   -> SetBinContent(itVPU+1,PUDATA.at(itVPU) / sumPUDATA);
  hPUWeight -> SetBinContent(itVPU+1,PUDATA.at(itVPU) / PUMC.at(itVPU) * sumPUMC / sumPUDATA);
 }
 
 
 
 TTree *treeEffVect[100];
 TTree *treeJetLepVect[100];
 

 
  //  [iCut] 
 TString* infoString[20];
 TLatex *infoLatex[20]; 
 TCanvas* ccCanvas[20];
 TCanvas* ccCanvasPull[20];
 TH1F* histoSumMC[20];
 //  [iName][iCut]
 TH1F* histo[100][20];
 TH1F* histo_temp[100][20];

 //  [iName][iCut]
 double numEvents[100][20];
 
 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);

 
 double XSection  = gConfigParser -> readDoubleOption("Plot::XSection");
 
 ///==== list of selections to perform (NOT sequential additive selections) ====
 std::string CutFile = gConfigParser -> readStringOption("Selections::CutFile");
 std::vector<std::string> vCut;
 std::cout << " nCuts = " << ReadFileCut(CutFile, vCut) << std::endl;
 
 
 ///==== list of systematic variables to change ====
//  std::string CutSystematicFile = gConfigParser -> readfStringOption("Selections::CutSystematicFile");
// 
//  std::vector< std::pair< int, std::pair<std::string, double> > > listSystematics;
//  ReadFileSystematics(CutSystematicFile, listSystematics);
//  ModifyCut(vCut,listSystematics);

 
  std::string CutSystematicFile = gConfigParser -> readStringOption("Selections::CutSystematicFile");
 
  std::vector< std::pair< std::string, std::string> > listSystematics;
  ReadFileSystematicsWithRegion(CutSystematicFile, listSystematics);
  ModifyCutWithRegion(vCut,listSystematics);
  
  
  
  ///==== something to load/exec ====
  try {
   std::string toLoad = gConfigParser -> readStringOption("Exec::ToLoad");
   std::string toExec = ".L ";
   toExec += toLoad;
   toExec += ".cxx";
   gROOT->ProcessLine(toExec.c_str());
   std::cout << std::endl;
   std::cout << " load: " << toLoad.c_str() << std::endl;
   std::cout << " do:   " << toExec.c_str() << std::endl;
   std::cout << std::endl;
  }
  catch (char const* exceptionString){
   std::cerr << " exception = " << exceptionString << std::endl;
  }
  
 
 ///==== output file ====
 std::string OutFileName    = gConfigParser -> readStringOption("Output::outFileName");
 std::cout << ">>>>> Output::outFileName  " << OutFileName  << std::endl;  
 
 TFile outFile(OutFileName.c_str(),"RECREATE");
 outFile.cd();
 
 
 ///==== 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/out_NtupleProducer_%s.root",inputDirectory.c_str(),nameSample[iSample]);  
  TFile* f = new TFile(nameFile, "READ");
  
  treeEffVect[iSample] = (TTree*) f->Get(treeNameSelections.c_str());
  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;
  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];
  
  if (numEntriesBefore != 0) {
   Normalization[iSample] = LUMI * XSection * preselection_efficiency / numEntriesBefore;
  }
  else {
   Normalization[iSample] = 0; 
  }    
 }
 
 
 
 TLegend* leg = new TLegend(0.8,0.25,0.98,0.78);
 bool LegendBuilt = false;

 TString lumiName = Form("#splitline{L = %.1f pb^{-1}}{#splitline{#sqrt{s} = 7}{CMS preliminary}}", LUMI);
//  TString lumiName = Form("#sqrt{s}=7 TeV   L=%.1f pb^{-1}", LUMI);
 TLatex *latex = new TLatex(0.80, 0.90, lumiName); 
 latex->SetTextAlign(12);
 latex->SetNDC();
 latex->SetTextFont(42);
 latex->SetTextSize(0.03);
  
 ///==== 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 (2) ;
 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;
   TString name_histo_temp = Form("%s_%d_temp",nameSample[iSample], iCut);
   histo_temp[iSample][iCut] = new TH1F(name_histo_temp,name_histo_temp,100,-10,10000000000);
   char toDraw[1000];
   sprintf(toDraw,"eventId >> %s",name_histo_temp.Data());      
   histo_temp[iSample][iCut] -> Sumw2(); //---- così mette l'errore giusto!
   
   TString CutExtended;
   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;
     }
    }
   }  
   if (!isData) {
    CutExtended = Form ("(%s) * autoWeight(numPUMC)",Cut.Data());    
   }
   else {
    CutExtended = Form ("(%s)",Cut.Data());    
   }
   if (debug) std::cerr << " drawing ..." << std::endl;
   treeJetLepVect[iSample]->Draw(toDraw,CutExtended,"");
   if (debug) std::cerr << " drawn ..." << std::endl;
   
   if (Normalization[iSample]>0) { 
    histo_temp[iSample][iCut] -> Scale(Normalization[iSample]); 
   }
   for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
    if (name_samples.at(iSample) == reduced_name_samples.at(iName)){
     if (reduced_name_samples_flag.at(iName) == -1){
      TString name_histoTot_temp = Form("%s_%d_Tot_temp",reduced_name_samples.at(iName).c_str(),iCut);
      TString name_HR_histoTot_temp = Form("cut %d",iCut);
      histo[iName][iCut] = new TH1F(name_histoTot_temp,name_HR_histoTot_temp,100,-10,10000000000);
      histo[iName][iCut] -> Sumw2(); //---- così mette l'errore giusto!
      reduced_name_samples_flag.at(iName) = 1;
     }
     histo[iName][iCut] -> Add(histo_temp[iSample][iCut]);
    }
   }
   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 ====
 
 //  [iName]
 TH1F* hTrend[100];
 THStack* hsTrend;
 //  [iCut]
 TPie* hTrendPie[100];
 
 //  [iCut]
 THStack* hs[100];
 
 std::cout << std::endl;
 
 ///==== cicle on selections ====
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
  TString nameStack = Form("%d_stack",iCut);
  hs[iCut] = new THStack(nameStack,nameStack);
  
  for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
   histo[iName][iCut]->GetXaxis()->SetTitle("eventId");
   histo[iName][iCut]->SetMarkerColor(vColor[iName]);
   histo[iName][iCut]->SetLineColor(vColor[iName]);
   histo[iName][iCut]->SetFillColor(vColor[iName]);
   histo[iName][iCut]->SetLineWidth(2);
   histo[iName][iCut]->SetFillStyle(3001);
   
   bool isSig = false;
   for (std::vector<std::string>::const_iterator itSig = SignalName.begin(); itSig != SignalName.end(); itSig++){
    if (reduced_name_samples.at(iName) == *itSig) isSig = true;
   }
   
   if (!isSig && reduced_name_samples.at(iName) != "DATA") {
    hs[iCut]->Add(histo[iName][iCut]);
   }
   else {
    if (!isSig) {
     histo[iName][iCut]->SetMarkerStyle(20);
     histo[iName][iCut]->SetMarkerSize(1);
     histo[iName][iCut]->SetMarkerColor(kBlack);
     histo[iName][iCut]->SetLineColor(kBlack);
     histo[iName][iCut]->SetFillColor(kBlack);
     histo[iName][iCut]->SetLineWidth(2);
     histo[iName][iCut]->SetFillStyle(3001);  
    }
    else {
     histo[iName][iCut]->SetMarkerStyle(21);
     histo[iName][iCut]->SetMarkerSize(1);
     histo[iName][iCut]->SetLineWidth(2);
     histo[iName][iCut]->SetFillStyle(3001);  
    }
   }
  }
  ///==== histo sum MC ====    
  ///==== Add systrematic error ====
  AddError(hs[iCut],LumiSyst);
  histoSumMC[iCut] = ((TH1F*)(hs[iCut]->GetStack()->Last()));

  std::cout << " MC / DATA[" << iCut << "] = "<< histoSumMC[iCut]->Integral() << " / " << histo[numDATA][iCut]->Integral() << " = " << (histo[numDATA][iCut]->Integral() ? histoSumMC[iCut]->Integral()/ histo[numDATA][iCut]->Integral() : 0) << std::endl;
  
  ///==== legend ====
  if (!LegendBuilt){
   for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
    leg->AddEntry(histo[iName][iCut],reduced_name_samples.at(iName).c_str(),"pf");    
    LegendBuilt = true;
   }
  }
 }
 std::cout << std::endl << std::endl;
 
 ///==== calculate number of events after each step of the analysis ====
 //  [iName][iCut]
 hsTrend = new THStack("Trend","Trend");
 
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
  TString nameTHTrendPie = Form("%d_Trend_Pie",iCut);
  hTrendPie[iCut] = new TPie (nameTHTrendPie,nameTHTrendPie,reduced_name_samples.size());
 }
 
 for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
  TString nameTHTrend = Form("%s_Trend",reduced_name_samples.at(iName).c_str());
  hTrend[iName] = new TH1F (nameTHTrend,nameTHTrend,vCut.size()+1,0,vCut.size()+1);
  hTrend[iName]->GetXaxis()->SetTitle("Selections");

  if (iName == numDATA) {
   hTrend[iName]->SetMarkerStyle(20);
   hTrend[iName]->SetMarkerSize(1);
   hTrend[iName]->SetMarkerColor(kBlack);
   hTrend[iName]->SetLineColor(kBlack);
   hTrend[iName]->SetFillColor(kBlack);
   hTrend[iName]->SetLineWidth(2);
   hTrend[iName]->SetFillStyle(3001);  
  }
  else {
   hTrend[iName]->SetMarkerColor(vColor[iName]);
   hTrend[iName]->SetLineColor(vColor[iName]);
   hTrend[iName]->SetFillColor(vColor[iName]);
   hTrend[iName]->SetLineWidth(2);
   hTrend[iName]->SetFillStyle(3001);
  }
  for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
   double error = 0;
   numEvents[iName][iCut] = histo[iName][iCut]->IntegralAndError(0,histo[iName][iCut]->GetNbinsX()+1,error);
   hTrend[iName]->SetBinContent(iCut+1,numEvents[iName][iCut]);
   hTrend[iName]->SetBinError(iCut+1,error);

   TString nameBin = Form("%d",iCut);
   hTrend[iName]->GetXaxis()->SetBinLabel(iCut+1,nameBin);
//     IntegralAndError
//     Double_t IntegralAndError(Int_t binx1, Int_t binx2, Double_t& err, Option_t* option = "") const
   std::cout << ">>>  numEvents[" << iName << "," << reduced_name_samples.at(iName) << "][" << iCut << "] = " << numEvents[iName][iCut] << " , " << histo[iName][iCut]->GetEntries() << " , " << histo[iName][iCut]->GetEffectiveEntries() << std::endl;
   
   if (iName != numDATA) {
    hTrendPie[iCut]->SetTextSize(0.04);
    hTrendPie[iCut]->SetTextFont(12);
    hTrendPie[iCut]->SetEntryFillColor(iName,vColor[iName]);
    hTrendPie[iCut]->SetEntryFillStyle(iName,3001);
    hTrendPie[iCut]->SetEntryLabel(iName, reduced_name_samples.at(iName).c_str());
    hTrendPie[iCut]->SetEntryLineColor(iName, vColor[iName]);
    hTrendPie[iCut]->SetEntryLineStyle(iName, 2);
    hTrendPie[iCut]->SetEntryLineWidth(iName, 2);
    hTrendPie[iCut]->SetEntryRadiusOffset(iName, 0.01);
    hTrendPie[iCut]->SetEntryVal(iName,numEvents[iName][iCut]);
   }
   else {
    hTrendPie[iCut]->SetEntryLabel(iName, "");
   }
  }
  if (iName != numDATA) {
   hsTrend->Add(hTrend[iName]);
  }
 }
 AddError(hsTrend,LumiSyst);
 
 TH1F* hTrendSumMC = ((TH1F*)(hsTrend->GetStack()->Last()));
 ///==== hTrend with pull plot ====
 TH1F* hPullTrendSumMC = PullPlot(hTrend[numDATA], hTrendSumMC);
  
 LumiSyst = 0; ///---- bug fix
 
 
 
 
 TCanvas* cTrendPie[100];
 TCanvas* cTrendPieAll = new TCanvas("cTrendPieAll","cTrendPieAll",400 * vCut.size(),400);
 cTrendPieAll -> Divide (vCut.size());
 TCanvas* cTrend = new TCanvas("cTrend","cTrend",400,400);
 TCanvas* cTrendSample[100];
 
 
 for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
  TString nameCanvas = Form("%d_Canvas_Sample",iName);
  cTrendSample[iName] = new TCanvas(nameCanvas,nameCanvas,400,400);
  hTrend[iName] -> Draw();
  gPad->SetLogy();
  gPad->SetGrid();
 }
 
 
 
 
 
 
 ///~~~~ for efficiency calculation ~~~~
 
 std::vector<double> numEntriesFirstStep_reduced_samples;
 for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
  numEntriesFirstStep_reduced_samples.push_back(0);
  for (int iSample = (numberOfSamples-1); iSample>= 0; iSample--){
   if (name_samples.at(iSample) == reduced_name_samples.at(iName)){
//     numEntriesFirstStep_reduced_samples.at(iName) += (Normalization[iSample] ? (1. / Normalization[iSample] * LUMI * xsection[iSample] * LUMI * xsection[iSample]) : -1);
    numEntriesFirstStep_reduced_samples.at(iName) += (xsection[iSample] * LUMI);
   }
  }
 }
//   Normalization[iSample] = LUMI * XSection * preselection_efficiency / numEntriesBefore;
//   1. / Normalization[iSample] = numEntriesBefore / preselection_efficiency / LUMI / XSection;
//   1. / Normalization[iSample] * LUMI * xsection[iSample] = numEntriesBefore / preselection_efficiency;
//   1. / Normalization[iSample] * LUMI * xsection[iSample] * LUMI * xsection[iSample] = numEntriesBefore / preselection_efficiency * LUMI * xsection[iSample];

 for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
  std::cout << "[" << reduced_name_samples.at(iName) << "] = " << numEntriesFirstStep_reduced_samples.at(iName) << std::endl;
 }
 
 std::cout.precision (2) ;
 std::cout.unsetf(std::ios::scientific);


 
 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::setw (12) << "sample";
 std::cout << " | " << std::setw (8) <<  -1;
 std::cout << " [" << std::setw (8) <<  "XXX";
 std::cout << " ]";
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
  std::cout << " | " << std::setw (8) <<  iCut;
  std::cout << " [" << std::setw (8) <<  "XXX";
  std::cout << " ]";
 }
 std::cout << std::endl;
 for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
  std::cout << std::setw (12) << reduced_name_samples.at(iName) ;
  std::cout << " | " << cyan << std::setw (8) <<  numEntriesFirstStep_reduced_samples.at(iName);
  std::cout << normal << " [" << std::setw (8) <<  "XXX";
  std::cout << " ]";
  for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
   std::cout << " | " << blue << std::setw (8) <<  hTrend[iName]->GetBinContent(iCut+1);
   std::cout << normal << " [" << std::setw (8) <<  hTrend[iName]->GetBinError(iCut+1);
   std::cout << " ]";
  }
  std::cout << std::endl;
 }
 
 std::cout << std::endl;
 std::cout << " *********************************** " << std::endl;
 for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
  std::cout << " | " << std::setw (8) << reduced_name_samples.at(iName) ;
  std::cout << " [" << std::setw (8) <<  "err";
  std::cout << " ]";
 }
 std::cout << std::endl;
 for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
  std::cout << " | " << cyan << std::setw (8) <<  numEntriesFirstStep_reduced_samples.at(iName);
  std::cout << normal << " [" << std::setw (8) <<  "XXX";
  std::cout << " ]";
 }
 std::cout << std::endl;
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
  for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
   std::cout << " | " << blue << std::setw (8) <<  hTrend[iName]->GetBinContent(iCut+1);
   std::cout << normal << " [" << std::setw (8) <<  hTrend[iName]->GetBinError(iCut+1);
   std::cout << " ]";
  }
  std::cout << std::endl;
 }
 
 
 
 std::cout << std::endl;
 std::cout << std::endl;
 std::cout << std::endl;
 std::cout << " *********************************** " << std::endl;
 std::cout << " ************* 1 fb-1 ************* " << std::endl;
 std::cout << std::setw (12) << "sample";
 std::cout << " | " << std::setw (8) <<  -1;
 std::cout << " [" << std::setw (8) <<  "XXX";
 std::cout << " ]";
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
  std::cout << " | " << std::setw (8) <<  iCut;
  std::cout << " [" << std::setw (8) <<  "XXX";
  std::cout << " ]";
 }
 std::cout << std::endl;
 for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
  std::cout << std::setw (12) << reduced_name_samples.at(iName) ;
  std::cout << " | " << purple << std::setw (9) <<  1000 / LUMI * numEntriesFirstStep_reduced_samples.at(iName);
  std::cout << normal << " [" << std::setw (9) <<  "XXX";
  std::cout << " ]";
  for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
   std::cout << " | " << red << std::setw (9) <<  hTrend[iName]->GetBinContent(iCut+1) / LUMI * 1000.;
   std::cout << normal << " [" << std::setw (9) <<  hTrend[iName]->GetBinError(iCut+1) / LUMI * 1000.;
   std::cout << " ]";
  }
  std::cout << std::endl;
 }
 
 std::cout << std::endl;
 std::cout << " *********************************** " << std::endl;
 for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
  std::cout << " | " << red << std::setw (8) << reduced_name_samples.at(iName) ;
  std::cout << normal << " [" << std::setw (8) <<  "err";
  std::cout << " ]";
 }
 std::cout << std::endl;
 for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
  std::cout << " | " << purple << std::setw (8) <<  1000 / LUMI * numEntriesFirstStep_reduced_samples.at(iName);
  std::cout << normal << " [" << std::setw (8) <<  "XXX";
  std::cout << " ]";
 }
 std::cout << std::endl;
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
  for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
   std::cout << " | " << red << std::setw (8) <<  hTrend[iName]->GetBinContent(iCut+1) / LUMI * 1000.;
   std::cout << normal << " [" << std::setw (8) <<  hTrend[iName]->GetBinError(iCut+1) / LUMI * 1000.;
   std::cout << " ]";
  }
  std::cout << std::endl;
 }
 
  
 std::cout << std::endl;
 std::cout << std::endl;
 std::cout << std::endl;
 std::cout << " **************************************** " << std::endl;
 std::cout << " ************* efficiency *************** " << std::endl;
 std::cout << std::setw (12) << "sample";
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
  std::cout << " | " << std::setw (8) <<  iCut;
  std::cout << " [" << std::setw (8) <<  "XXX";
  std::cout << " ]";
 }
 std::cout << std::endl;
 for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
  std::cout << std::setw (12) << reduced_name_samples.at(iName) ;
  for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
   std::cout << " | " << yellow << std::setw (8) <<  hTrend[iName]->GetBinContent(iCut+1) / numEntriesFirstStep_reduced_samples.at(iName);
   std::cout << normal << " [" << std::setw (8) <<  hTrend[iName]->GetBinError(iCut+1) / numEntriesFirstStep_reduced_samples.at(iName);
//    std::cout << " | " << yellow << std::setw (8) <<  hTrend[iName]->GetBinContent(iCut+1) << " / " << numEntriesFirstStep_reduced_samples.at(iName);
//    std::cout << normal << " [" << std::setw (8) <<  hTrend[iName]->GetBinError(iCut+1) << " / " << numEntriesFirstStep_reduced_samples.at(iName);
   std::cout << " ]";
  }
  std::cout << std::endl;
 }
 
 std::cout << std::endl;
 std::cout << " *********************************** " << std::endl;
 for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
  std::cout << " | " << std::setw (8) << reduced_name_samples.at(iName) ;
  std::cout << " [" << std::setw (8) <<  "err";
  std::cout << " ]";
 }
 std::cout << std::endl;
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
  for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
   std::cout << " | " << yellow << std::setw (8) <<  hTrend[iName]->GetBinContent(iCut+1) / numEntriesFirstStep_reduced_samples.at(iName);
   std::cout << normal << " [" << std::setw (8) <<  hTrend[iName]->GetBinError(iCut+1) / numEntriesFirstStep_reduced_samples.at(iName);
   std::cout << " ]";
  }
  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 << " *********************** for Lands datacard *********************** " << std::endl;
 std::cout << std::endl;
 std::cout << std::endl;
 std::cout << std::endl;
 std::cout << std::endl;
 
 
 
 std::string mass = "160";
 try {
  mass = gConfigParser -> readStringOption("Input::mass");
 }
 catch (char const* exceptionString){
  std::cerr << " exception = " << exceptionString << std::endl;
 }
 std::cout << ">>>>> input::mass  " << mass << std::endl;  
 
 std::ofstream myfile;
 std::string nameOutDataCard = "dataCard_H" + mass + ".txt";
 
 ///==== output - txt file name ====
 try {
  nameOutDataCard = gConfigParser -> readStringOption("Output::DataCard");
 }
 catch (char const* exceptionString){
  std::cerr << " exception = " << exceptionString << std::endl;
 }
 
 myfile.open (nameOutDataCard.c_str());
 std::cout << "Writing to: " << nameOutDataCard << std::endl;
 std::cout << std::endl;
 
 
 myfile << "Limit" << std::endl;
 myfile << "imax 1 number of channels" << std::endl;
 myfile << "jmax "<< (reduced_name_samples.size() - SignalName.size() - 1) << " number of background" << std::endl;
 //---- -1 to take into account "DATA"
 myfile << "kmax "<< 0 << " number of nuisance parameters" << std::endl;
 
 double totalSig = 0;
 double totalBkg = 0;
 for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
  if (iName != numDATA) {
   bool isSig = false;
   for (std::vector<std::string>::const_iterator itSig = SignalName.begin(); itSig != SignalName.end(); itSig++){
    if (reduced_name_samples.at(iName) == *itSig) isSig = true;
   }
   if (isSig) {
    totalSig += hTrend[iName]->GetBinContent(vCut.size());   ///---- last cut!
   }
   else {
    totalBkg += hTrend[iName]->GetBinContent(vCut.size());   ///---- last cut!
   }
  }
 }
 myfile << "-------------------------------------------------" << std::endl;
//  myfile << "Observation   " << ((Discovery==1) ? (int) (totalBkg+totalSig) : (int) (totalBkg)) << std::endl;
 myfile << "Observation   " << hTrend[numDATA]->GetBinContent(vCut.size()) << std::endl;
 //# 1 = discovery, 0 = exclusion
 myfile << "-------------------------------------------------" << std::endl;
 
 
 myfile << std::setw (12) << " bin  " << std::setw (8) << 1 << "  ";
 for (int i=0; i < (reduced_name_samples.size() - SignalName.size() - 1); i++){
  myfile << std::setw (8) << 1 << "  ";
 }
 myfile << std::endl;
 
 myfile << std::setw (12) << " process  " << std::setw (8) << "sig" << "  ";
 for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
  if (iName != numDATA) {
   bool isSig = false;
   for (std::vector<std::string>::const_iterator itSig = SignalName.begin(); itSig != SignalName.end(); itSig++){
    if (reduced_name_samples.at(iName) == *itSig) isSig = true;
   }
   if (!isSig) {
    myfile << std::setw (8) << reduced_name_samples.at(iName) << "  ";
   }
  }
 }
 myfile << std::endl;
 
 myfile << std::setw (12) << " process  " << std::setw (8) << 0 << "  ";
 for (int i=0; i < (reduced_name_samples.size() - SignalName.size() - 1); i++){
  myfile << std::setw (8) << i+1 << "  ";
 }
 myfile << std::endl;
 
 myfile << std::setw (12) << " rate  " << std::setw (8) << totalSig << "  ";
 for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
  if (iName != numDATA) {
   bool isSig = false;
   for (std::vector<std::string>::const_iterator itSig = SignalName.begin(); itSig != SignalName.end(); itSig++){
    if (reduced_name_samples.at(iName) == *itSig) isSig = true;
   }
   if (!isSig) {
    myfile << std::setw (8) << hTrend[iName]->GetBinContent(vCut.size()) << "  ";
   }
  }
 }
 myfile << std::endl;
 
 
 myfile << "-------------------------------------------------" << std::endl;
 
 myfile.close(); 
 
 
 
 
 ///==== plot on the screen ====
 
 std::cout << "Limit" << std::endl;
 std::cout << "imax 1 number of channels" << std::endl;
 std::cout << "jmax "<< (reduced_name_samples.size() - SignalName.size() - 1) << " number of background" << std::endl;
 //---- -1 to take into account "DATA"
 std::cout << "kmax "<< 0 << " number of nuisance parameters" << std::endl;
 
 totalSig = 0;
 totalBkg = 0;
 for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
  if (iName != numDATA) {
   bool isSig = false;
   for (std::vector<std::string>::const_iterator itSig = SignalName.begin(); itSig != SignalName.end(); itSig++){
    if (reduced_name_samples.at(iName) == *itSig) isSig = true;
   }
   if (isSig) {
    totalSig += hTrend[iName]->GetBinContent(vCut.size());   ///---- last cut!
   }
   else {
    totalBkg += hTrend[iName]->GetBinContent(vCut.size());   ///---- last cut!
   }
  }
 }
 std::cout << "-------------------------------------------------" << std::endl;
//  std::cout << "Observation   " << ((Discovery==1) ? (int) (totalBkg+totalSig) : (int) (totalBkg)) << std::endl;
 std::cout << "Observation   " << hTrend[numDATA]->GetBinContent(vCut.size()) << std::endl;
 //# 1 = discovery, 0 = exclusion
 std::cout << "-------------------------------------------------" << std::endl;
 
 
 std::cout << std::setw (12) << " bin  " << std::setw (8) << 1 << "  ";
 for (int i=0; i < (reduced_name_samples.size() - SignalName.size() - 1); i++){
  std::cout << std::setw (8) << 1 << "  ";
 }
 std::cout << std::endl;
 
 std::cout << std::setw (12) << " process  " << std::setw (8) << "sig" << "  ";
 for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
  if (iName != numDATA) {
   bool isSig = false;
   for (std::vector<std::string>::const_iterator itSig = SignalName.begin(); itSig != SignalName.end(); itSig++){
    if (reduced_name_samples.at(iName) == *itSig) isSig = true;
   }
   if (!isSig) {
    std::cout << std::setw (8) << reduced_name_samples.at(iName) << "  ";
   }
  }
 }
 std::cout << std::endl;
 
 std::cout << std::setw (12) << " process  " << std::setw (8) << 0 << "  ";
 for (int i=0; i < (reduced_name_samples.size() - SignalName.size() - 1); i++){
  std::cout << std::setw (8) << i+1 << "  ";
 }
 std::cout << std::endl;
 
 std::cout << std::setw (12) << " rate  " << std::setw (8) << totalSig << "  ";
 for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
  if (iName != numDATA) {
   bool isSig = false;
   for (std::vector<std::string>::const_iterator itSig = SignalName.begin(); itSig != SignalName.end(); itSig++){
    if (reduced_name_samples.at(iName) == *itSig) isSig = true;
   }
   if (!isSig) {
    std::cout << std::setw (8) << hTrend[iName]->GetBinContent(vCut.size()) << "  ";
   }
  }
 }
 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;
 
 
 
 
 
 
 ///==== draw trend vs cut (begin)
 cTrend->cd();
 DrawStack(hsTrend,1,LumiSyst);
 hTrend[numDATA] -> Draw("EsameP");
 gPad->SetLogy();
 gPad->SetGrid();
 leg->Draw();
 latex->Draw();
  
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
  TString nameCanvas = Form("%d_Canvas_Trend",iCut);
  cTrendPie[iCut] = new TCanvas(nameCanvas,nameCanvas,400,400);
  cTrendPie[iCut]->cd();
  hTrendPie[iCut] -> Draw("3d t nol");
  hTrendPie[iCut]->SetX(.45);
  hTrendPie[iCut]->SetRadius(.22);
  leg->Draw();
  latex->Draw();
  
  cTrendPieAll->cd(iCut+1);
  hTrendPie[iCut] -> Draw("3d t nol");
  hTrendPie[iCut]->SetX(.45);
  hTrendPie[iCut]->SetRadius(.22);
  leg->Draw();
  latex->Draw();
 }
 ///==== draw trend vs cut (end)
 
 
 
 std::cerr << " ******************************************* end *******************************************" << std::endl;
 end = clock();
 std::cout <<"Time = " <<  ((double) (end - start)) << " (a.u.)" << std::endl;  
 
 
 
 ///==== save output ====
 outFile.cd();
 cTrend -> Write();
 
 outFile.mkdir("Trend");
 outFile.cd("Trend");
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
  cTrendPie[iCut] -> Write();
 }
 cTrendPieAll -> Write();
 
 
 outFile.cd();
 outFile.mkdir("PU");
 outFile.cd("PU");
 
 hPUMC     -> Write();
 hPUDATA   -> Write();
 hPUWeight -> Write();
 
 
 outFile.cd();
 outFile.mkdir("Sample");
 outFile.cd("Sample");
 
 for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
  cTrendSample[iName] ->Write();
 }  
 
 leg->Write();
 
}
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 testTL1Resolution()
{
    std::shared_ptr<TStyle> myStyle(new TStyle(TDRStyle()));
    SetMyStyle(55, 0.07, myStyle.get());

    // Basic
    std::string sample = "Data";
    std::string triggerName = "SingleMu";
    std::string triggerTitle = "Single Muon";

    std::string run = "2016B_v1";
    std::string outDirBase = "/afs/cern.ch/work/s/sbreeze/L1TriggerStudiesOutput";
    std::vector<std::string> puType = {"0PU12","13PU19","20PU"};
    std::vector<int> puBins = {0,13,20,999};

    // std::string inDir = "/afs/cern.ch/work/s/sbreeze/public/jets_and_sums/160511_l1t-integration-v48p2/SingleMu/Ntuples";
    // std::string inDir = "/afs/cern.ch/work/s/sbreeze/public/jets_and_sums/160519_l1t-integration-v53p1/SingleMu_273301/Ntuples";
    // std::string inDir = "/afs/cern.ch/work/s/sbreeze/public/jets_and_sums/160602_r273450_SingleMu_l1t-int-v53p1";
    // std::string inDir = "/afs/cern.ch/work/s/sbreeze/public/jets_and_sums/160607_combinedRuns_SingleMu";
    std::string inDir = "/afs/cern.ch/work/s/sbreeze/public/jets_and_sums/160704_SingleMu2016Bv1_l1t-int-v67p0";
    std::shared_ptr<TL1EventClass> event(new TL1EventClass(inDir));

    std::vector<std::shared_ptr<TL1Resolution>> resolution;

    // caloMetBE
    resolution.emplace_back(new TL1Resolution());
    std::string outDir = outDirBase+"/"+resolution.front()->GetDate()+"_"+sample+"_"+"run-"+run+"_"+triggerName+"/Resolutions/";
    resolution[0]->SetBins(bins());
    resolution[0]->SetX("caloMetBE","Offline E_{T}^{miss}");
    resolution[0]->SetY("l1Met","L1 E_{T}^{miss}");
    resolution[0]->SetOutName(triggerName+"_caloMetBE_over_l1Met");
    resolution[0]->AddRelTitle("recoCaloMetBE","Offline E_{T}^{miss} (GeV)");
    resolution[0]->AddRelBins({20.,40.,60.,80.,100.,120.,140.});
    resolution[0]->SetAddMark("no HF, Offline E_{T}^{miss} > 40 GeV");

    // caloMet
    resolution.emplace_back(new TL1Resolution());
    resolution[1]->SetBins(bins());
    resolution[1]->SetX("caloMet","Offline E_{T}^{miss}");
    resolution[1]->SetY("l1MetHF","L1 E_{T}^{miss}");
    resolution[1]->SetOutName(triggerName+"_caloMet_over_l1MetHF");
    resolution[1]->AddRelTitle("recoCaloMetBE","Offline E_{T}^{miss} (GeV)");
    resolution[1]->AddRelBins({20.,40.,60.,80.,100.,120.,140.});
    resolution[1]->SetAddMark("HF, Offline E_{T}^{miss} > 40 GeV");

    // mht
    //resolution.emplace_back(new TL1Resolution());
    //resolution[1]->SetBins(bins());
    //resolution[1]->SetX("mht","Offline H_{T}^{miss}");
    //resolution[1]->SetY("l1mht","L1 H_{T}^{miss}");
    //resolution[1]->SetOutName(triggerName+"_recalcMht_over_l1Mht");
    //resolution[1]->AddRelTitle("recoMht","Offline H_{T}^{miss} (GeV)");
    //resolution[1]->AddRelBins({0.,10.,20.,30.,40.,50.,60.,70.,80.,100.});
    ////resolution[1]->SetAddMark("L1 ETM > 40 GeV");

    //// caloEttBE
    //resolution.emplace_back(new TL1Resolution());
    //resolution[2]->SetBins(bins());
    //resolution[2]->SetX("caloEttBE","Offline Total E_{T}");
    //resolution[2]->SetY("l1ett","L1 Total E_{T}");
    //resolution[2]->SetOutName(triggerName+"_caloEttBE_over_l1Ett");
    //resolution[2]->AddRelTitle("recoEtt","Offline Total E_{T} (GeV)");
    //resolution[2]->AddRelBins({0.,10.,20.,30.,40.,50.,60.,70.,80.,100.});
    ////resolution[2]->SetAddMark("L1 ETM > 40 GeV");

    //// htt
    //resolution.emplace_back(new TL1Resolution());
    //resolution[3]->SetBins(bins());
    //resolution[3]->SetX("htt","Offline Total H_{T}");
    //resolution[3]->SetY("l1htt","L1 Total H_{T}");
    //resolution[3]->SetOutName(triggerName+"_htt_over_l1Htt");
    //resolution[3]->AddRelTitle("recoHtt","Offline Total H_{T} (GeV)");
    //resolution[3]->AddRelBins({0.,10.,20.,30.,40.,50.,60.,70.,80.,100.});
    //resolution[3]->SetAddMark("Offline HTT > 100 GeV");

    // caloMetBE Phi
    //double p = TMath::Pi();
    //resolution.emplace_back(new TL1Resolution());
    //resolution[4]->SetBins(bins());
    //resolution[4]->SetX("caloMetBEPhi","Offline E_{T}^{miss} Phi");
    //resolution[4]->SetY("l1metphi","L1 E_{T}^{miss} Phi");
    //resolution[4]->SetOutName(triggerName+"_caloMetBEPhi_over_l1MetPhi");
    //resolution[4]->AddRelTitle("recoCaloMetPhiBE","Offline E_{T}^{miss} Phi");
    //resolution[4]->AddRelBins({-p,-0.75*p,-0.5*p,-0.25*p,0.,0.25*p,0.5*p,0.75*p,p});
    //resolution[0]->SetAddMark("L1 ETM > 40 GeV");

    // mht Phi
    //resolution.emplace_back(new TL1Resolution());
    //resolution[5]->SetBins(bins());
    //resolution[5]->SetX("mhtPhi","Offline H_{T}^{miss} Phi");
    //resolution[5]->SetY("l1httphi","L1 Total H_{T} Phi");
    //resolution[5]->SetOutName(triggerName+"_recalcMhtPhi_over_l1MhtPhi");
    //resolution[5]->AddRelTitle("recoMhtPhi","Offline H_{T}^{miss} Phi");
    //resolution[5]->AddRelBins({-p,-0.75*p,-0.5*p,-0.25*p,0.,0.25*p,0.5*p,0.75*p,p});
    //resolution[0]->SetAddMark("L1 ETM > 40 GeV");

    for(auto it=resolution.begin(); it!=resolution.end(); ++it)
    {
        (*it)->SetSample(sample,"");
        (*it)->SetTrigger(triggerName,triggerTitle);
        (*it)->SetRun(run);
        (*it)->SetOutDir(outDir);
        (*it)->SetPuType(puType);
        (*it)->SetPuBins(puBins);
        (*it)->InitPlots();
    }
    
    unsigned NEntries = event->GetPEvent()->GetNEntries();
    while( event->Next() )
    {
        unsigned position = event->GetPEvent()->GetPosition()+1;
        TL1Progress::PrintProgressBar(position, NEntries);

        int pu = event->GetPEvent()->fVertex->nVtx;
        auto sums = event->GetPEvent()->fSums;

        if( !event->fMuonFilterPassFlag ) continue;

        // MET
        double recoMet = sums->caloMetBE;
        double l1Met = event->fL1Met;

        double recoMetHF = sums->caloMet;
        double l1MetHF = event->fL1MetHF;
        if( event->fMetFilterPassFlag )
        {
            if( recoMet > 40.0 && l1Met != 0.0 )
                resolution[0]->Fill(recoMet, l1Met, pu);
            //resolution[0]->RelFill(recoMet, l1Met, pu, {recoMet});
            if( recoMetHF > 40.0 && l1MetHF != 0.0 )
                resolution[1]->Fill(recoMetHF, l1MetHF, pu);
        }

        // MET Phi
        //double recoMetPhi = event->GetPEvent()->fSums->caloMetPhiBE;
        //double l1MetPhi = event->fL1MetPhi;
        //if( recoMet != 0.0 && l1Met != 0.0 )
        //    resolution[4]->Fill(FoldPhi(recoMetPhi), FoldPhi(l1MetPhi), pu);
        //resolution[4]->RelFill(FoldPhi(recoMetPhi), FoldPhi(l1MetPhi), pu, {FoldPhi(recoMetPhi)});

    }

//    resolution[0]->DrawPlots();
//    resolution[3]->DrawPlots();
    for(auto it=resolution.begin(); it!=resolution.end(); ++it)
        (*it)->DrawPlots();
        
}
Example #4
0
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 () ;
 }
 
}
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;
 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;  
 
 double LUMI = gConfigParser -> readDoubleOption("Input::Lumi");
 
 double LumiSyst = gConfigParser -> readDoubleOption("Input::LumiSyst");
 
 double Discovery = gConfigParser -> readDoubleOption("Input::Discovery");
 
 int Normalize = gConfigParser -> readIntOption("Input::Normalize");
 
 std::vector<std::string> SignalName;
 if (Discovery == 1) SignalName = gConfigParser -> readStringListOption("Input::SignalName");
 
 
 ///==== PU reweight (begin) ====
 bool doWeightFromFile = false; 
 try {
  doWeightFromFile = gConfigParser -> readStringOption("PU::doWeightFromFile");
 }
 catch (char const* exceptionString){
  std::cerr << " exception = " << exceptionString << std::endl;
 }
 std::cout << ">>>>> PU::doWeightFromFile  " << doWeightFromFile  << std::endl;  
 
 std::vector<double> PUMC;
 std::vector<double> PUDATA;
 PUclass PU;
 double sumPUMC = 0;
 double sumPUDATA = 0;
 TH1F* hPUMC;
 TH1F* hPUDATA;
 TH1F* hPUWeight;
 
 
 
 std::string nameWeight = "weight"; 
 if (doWeightFromFile) {
  try {
   nameWeight = gConfigParser -> readStringOption("PU::nameWeight");
  }
  catch (char const* exceptionString){
   std::cerr << " exception = " << exceptionString << std::endl;
  }
  std::cout << ">>>>> PU::nameWeight  " << nameWeight  << std::endl;  
 }
 
 if (!doWeightFromFile) {
  
  PUMC   = gConfigParser -> readDoubleListOption("PU::PUMC");
  PUDATA = gConfigParser -> readDoubleListOption("PU::PUDATA");
  
  std::cout << " PUMC.size()   = " << PUMC.size()   << std::endl;
  std::cout << " PUDATA.size() = " << PUDATA.size() << std::endl;
  
  if (PUMC.size() != PUDATA.size()) {
   std::cerr << " ERROR " << std::endl;
   return 1;
  }
  
  for (int itVPU = 0; itVPU < PUMC.size(); itVPU++ ){
   sumPUMC += PUMC.at(itVPU);  
  }
  for (int itVPU = 0; itVPU < PUDATA.size(); itVPU++ ){
   sumPUDATA += PUDATA.at(itVPU);  
  } 
  
  for (int itVPU = 0; itVPU < PUMC.size(); itVPU++ ){
   PU.PUWeight.push_back(PUDATA.at(itVPU) / PUMC.at(itVPU) * sumPUMC / sumPUDATA);
  }
  
  PU.Write("autoWeight.cxx");
  gROOT->ProcessLine(".L autoWeight.cxx");
  
  ///==== save PU distribution in TH1F ====
  hPUMC   = new TH1F("hPUMC","hPUMC",PUMC.size(),0,PUMC.size());
  hPUDATA = new TH1F("hPUDATA","hPUDATA",PUDATA.size(),0,PUDATA.size());
  hPUWeight = new TH1F("hPUWeight","hPUWeight",PUDATA.size(),0,PUDATA.size());
  
  for (int itVPU = 0; itVPU < PUMC.size(); itVPU++ ){
   hPUMC     -> SetBinContent(itVPU+1,PUMC.at(itVPU) / sumPUMC);
   hPUDATA   -> SetBinContent(itVPU+1,PUDATA.at(itVPU) / sumPUDATA);
   hPUWeight -> SetBinContent(itVPU+1,PUDATA.at(itVPU) / PUMC.at(itVPU) * sumPUMC / sumPUDATA);
  }
  
 }
 
 ///==== PU reweight (end) ====
 
 ///==== pT Higgs reweight (begin) ====
 std::string nameptHWeight; 
 try {
  nameptHWeight = gConfigParser -> readStringOption("Input::nameptHWeight");
 }
 catch (char const* exceptionString){
  std::cerr << " exception = " << exceptionString << std::endl;
 }
 std::cout << ">>>>> input::nameptHWeight  " << nameptHWeight  << std::endl;  
 if (nameptHWeight != ""){
  TString toLoad;
  //   toLoad = Form("cp %s ./",nameptHWeight.c_str());
  //   gROOT->ProcessLine(toLoad.Data());
  toLoad = Form(".L %s",nameptHWeight.c_str());
  gROOT->ProcessLine(toLoad.Data());
 }
 
 std::string nameptHWeightSample; 
 try {
  nameptHWeight = gConfigParser -> readStringOption("Input::nameptHWeightSample");
 }
 catch (char const* exceptionString){
  std::cerr << " exception = " << exceptionString << std::endl;
 }
 std::cout << ">>>>> input::nameptHWeightSample  " << nameptHWeightSample  << std::endl;  
 
 
 ///==== pT Higgs reweight (end) ====
 
 TTree *treeEffVect[100];
 TTree *treeJetLepVect[100];
 

 
  //  [iCut][iVar] 
 TString* infoString[20][30];
 TLatex *infoLatex[20][30]; 
 TCanvas* ccCanvas[20][30];
 TCanvas* ccCanvasPull[20][30];
 TCanvas* ccCanvasPullTrace[20][30];
 TH2F* histoSumMC[20][30];
 //  [iName][iCut][iVar]
 TH2F* histo[100][30][30];
 TH2F* histo_temp[100][20][30];

 //  [iName][iCut]
 double numEvents[100][30];
 
 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 variables to plot ====
 std::vector<std::pair<double, double> > vMin;
 std::vector<std::pair<double, double> > vMax;
 std::vector<std::pair<int, int> > vNBin;
 std::vector<std::pair<std::string, std::string> > vVarName;
 std::vector<std::pair<std::string, std::string> > vVarNameHR;
 std::string VarFile = gConfigParser -> readStringOption("Plot::VarFile");
 
 int numVar = ReadFileVar2D(VarFile,vMin,vMax,vNBin,vVarName,vVarNameHR);
  
 
//  double XSection  = gConfigParser -> readDoubleOption("Plot::XSection");
 
 ///==== 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");
  }
 }
 
 ///==== output file ====
 std::string OutFileName    = gConfigParser -> readStringOption("Output::outFileName");
 std::cout << ">>>>> Output::outFileName  " << OutFileName  << std::endl;  
 
 TFile outFile(OutFileName.c_str(),"RECREATE");
 outFile.cd();
 
 ///==== 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]);  
  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];
  
  if (numEntriesBefore != 0) {
   Normalization[iSample] = LUMI * XSection * preselection_efficiency / numEntriesBefore;
  }
  else {
   Normalization[iSample] = 0; 
  }    
  
  if (Latinos) Normalization[iSample] = XSection * LUMI / 1000.;
 }
 
 
 
 TLegend* leg = new TLegend(0.8,0.25,0.98,0.78);
 bool LegendBuilt = false;

 TString lumiName = Form("#splitline{L = %.1f pb^{-1}}{#splitline{#sqrt{s} = 7}{CMS preliminary}}", LUMI);
//  TString lumiName = Form("#sqrt{s}=7 TeV   L=%.1f pb^{-1}", LUMI);
 TLatex *latex = new TLatex(0.80, 0.90, lumiName); 
 latex->SetTextAlign(12);
 latex->SetNDC();
 latex->SetTextFont(42);
 latex->SetTextSize(0.03);
  
 ///==== 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 (2) ;
 
 ///==== 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;
  ///==== cicle on variables to plot ====
  for (unsigned int iVar = 0; iVar<vVarName.size(); iVar++){  
   if (debug) std::cout << " Var[" << iVar << ":" << vVarName.size() << "] = " << vVarName.at(iVar).first << " && " << vVarName.at(iVar).second << " ~~ " << 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;
    TString name_histo_temp = Form("%s_%d_%d_temp",nameSample[iSample], iCut, iVar);
    histo_temp[iSample][iCut][iVar] = new TH2F(name_histo_temp,name_histo_temp,vNBin.at(iVar).first,vMin.at(iVar).first, vMax.at(iVar).first,vNBin.at(iVar).second,vMin.at(iVar).second, vMax.at(iVar).second);
    char toDraw[1000];
    sprintf(toDraw,"%s:%s >> %s",vVarName.at(iVar).second.c_str(),vVarName.at(iVar).first.c_str(),name_histo_temp.Data());      

    histo_temp[iSample][iCut][iVar] -> Sumw2(); //---- così mette l'errore giusto!
    
    TString CutExtended;
    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;
      }
     }
    }  
    if (!isData) {
     if (nameptHWeight != "" && name_samples.at(iSample) == nameptHWeightSample){
      if (!doWeightFromFile) {
       CutExtended = Form ("(%s) * autoWeight(numPUMC) * ptHWeight(ptH)",Cut.Data());    
      }
      else {
       CutExtended = Form ("(%s) * ptHWeight(ptH) * (%s)",Cut.Data(),nameWeight.c_str());    
      }
     }
     else {
      if (!doWeightFromFile) {
       CutExtended = Form ("(%s) * autoWeight(numPUMC)",Cut.Data());    
      }
      else {
       CutExtended = Form ("(%s) * (%s)",Cut.Data(),nameWeight.c_str());    
      }
     }
     //      CutExtended = Form ("(%s) * autoWeight(numPUMC) * ptHWeight(ptH)",Cut.Data());    
    }
    else {
     CutExtended = Form ("(%s)",Cut.Data());    
    }
    treeJetLepVect[iSample]->Draw(toDraw,CutExtended,"");
    
    if (Normalization[iSample]>0) { 
//      histo_temp[iSample][iCut][iVar] -> Sumw2();
     histo_temp[iSample][iCut][iVar] -> Scale(Normalization[iSample]); 
    }
    
//     std::cout << "Processing: " << blue << (((double) numberOfSamples - iSample)/numberOfSamples) << "% \r"  << normal << std::flush;
   } ///==== end cicle on samples ====
//    std::cout << "###";
  std::cout << "Processing: " << blue << (((double) iCut)/vCut.size())*100. << "% "  << normal <<  " -- " <<  blue << (((double) iVar)/vVarName.size())*100. << "% \r"  << normal << std::flush;   
  } ///==== end cicle on variables to plot ====
  //   std::cout << "***";
 } ///==== end cicle on selections ====
 std::cout << std::endl; 
 
 

 
 ///---- create "big" histos ----
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
  for (unsigned int iVar = 0; iVar<vVarName.size(); iVar++){
   ///---- initialize (begin) ----
   for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
    reduced_name_samples_flag.at(iName) = -1;
   }
   ///---- initialize (end) ----
   for (int iSample = (numberOfSamples-1); iSample>= 0; iSample--){    
    for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
     if (name_samples.at(iSample) == reduced_name_samples.at(iName) && iName == numDATA){
      if (reduced_name_samples_flag.at(iName) == -1){
       TString name_histoTot_temp = Form("%s_%d_%d_Tot_temp",reduced_name_samples.at(iName).c_str(),iCut, iVar);
       TString name_HR_histoTot_temp = Form("%s vs %s @ %s",vVarNameHR.at(iVar).second.c_str(),vVarNameHR.at(iVar).first.c_str(), vCutHR.at(iCut).c_str());
       //        TString name_HR_histoTot_temp = Form("%s %d %s",vVarNameHR.at(iVar).c_str(), iCut, reduced_name_samples.at(iName).c_str());
       histo[iName][iCut][iVar] = new TH2F(name_histoTot_temp,name_HR_histoTot_temp,vNBin.at(iVar).first,vMin.at(iVar).first, vMax.at(iVar).first,vNBin.at(iVar).second,vMin.at(iVar).second, vMax.at(iVar).second);
       histo[iName][iCut][iVar] -> Sumw2(); //---- così mette l'errore giusto!
       reduced_name_samples_flag.at(iName) = 1;
      }
      histo[iName][iCut][iVar] -> Add(histo_temp[iSample][iCut][iVar]);
     }
    }
   }
  }
 }
 
 
 if (Normalize == 1) { //---- normalize to Data ----
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
  for (unsigned int iVar = 0; iVar<vVarName.size(); iVar++){
   ///---- initialize (begin) ----
   for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
    reduced_name_samples_flag.at(iName) = -1;
   }
   ///---- initialize (end) ----
   double data_int = histo[numDATA][iCut][iVar] -> Integral();
   double mc_int = 0;
   
   for (int iSample = (numberOfSamples-1); iSample>= 0; iSample--){
    for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
     if (name_samples.at(iSample) == reduced_name_samples.at(iName) && iName != numDATA){
      mc_int += histo_temp[iSample][iCut][iVar] -> Integral();
     }
    }
   }
   
   std::cout << " data_int / mc_int = " << data_int / mc_int << std::endl;
   for (int iSample = (numberOfSamples-1); iSample>= 0; iSample--){ 
    histo_temp[iSample][iCut][iVar] -> Scale (data_int / mc_int);
    
    for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
     if (name_samples.at(iSample) == reduced_name_samples.at(iName)  && iName != numDATA){
      if (reduced_name_samples_flag.at(iName) == -1){
       TString name_histoTot_temp = Form("%s_%d_%d_Tot_temp",reduced_name_samples.at(iName).c_str(),iCut, iVar);
       TString name_HR_histoTot_temp = Form("%s vs %s @ %s",vVarNameHR.at(iVar).second.c_str(),vVarNameHR.at(iVar).first.c_str(), vCutHR.at(iCut).c_str());
       //        TString name_HR_histoTot_temp = Form("%s %d %s",vVarNameHR.at(iVar).c_str(), iCut, reduced_name_samples.at(iName).c_str());
       histo[iName][iCut][iVar] = new TH2F(name_histoTot_temp,name_HR_histoTot_temp,vNBin.at(iVar).first,vMin.at(iVar).first, vMax.at(iVar).first,vNBin.at(iVar).second,vMin.at(iVar).second, vMax.at(iVar).second);
       histo[iName][iCut][iVar] -> Sumw2(); //---- così mette l'errore giusto!
       reduced_name_samples_flag.at(iName) = 1;
      }
      histo[iName][iCut][iVar] -> Add(histo_temp[iSample][iCut][iVar]);
     }
    }
   }
  }
 }
 
 }
 else { //---- normalize to Lumi
  
  for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
   for (unsigned int iVar = 0; iVar<vVarName.size(); iVar++){
    ///---- initialize (begin) ----
    for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
     reduced_name_samples_flag.at(iName) = -1;
    }
    ///---- initialize (end) ----
    for (int iSample = (numberOfSamples-1); iSample>= 0; iSample--){
     
     for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
      if (name_samples.at(iSample) == reduced_name_samples.at(iName) && iName != numDATA ){
       if (reduced_name_samples_flag.at(iName) == -1){
	TString name_histoTot_temp = Form("%s_%d_%d_Tot_temp",reduced_name_samples.at(iName).c_str(),iCut, iVar);
	TString name_HR_histoTot_temp = Form("%s vs %s @ %s",vVarNameHR.at(iVar).second.c_str(),vVarNameHR.at(iVar).first.c_str(), vCutHR.at(iCut).c_str());
	//        TString name_HR_histoTot_temp = Form("%s %d %s",vVarNameHR.at(iVar).c_str(), iCut, reduced_name_samples.at(iName).c_str());
	histo[iName][iCut][iVar] = new TH2F(name_histoTot_temp,name_HR_histoTot_temp,vNBin.at(iVar).first,vMin.at(iVar).first, vMax.at(iVar).first,vNBin.at(iVar).second,vMin.at(iVar).second, vMax.at(iVar).second);
	histo[iName][iCut][iVar] -> Sumw2(); //---- così mette l'errore giusto!
	reduced_name_samples_flag.at(iName) = 1;
       }
       histo[iName][iCut][iVar] -> Add(histo_temp[iSample][iCut][iVar]);
      }
     }
    }
   }
  }
 }
 
 
 //  [iCut][iVar]
 THStack* hs[100][100];
 
 std::cout << std::endl;
 
 ///==== cicle on selections ====
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
  ///==== cicle on variables to plot ====
  for (unsigned int iVar = 0; iVar<vVarName.size(); iVar++){
   TString nameStack = Form("%d_%d_stack",iCut,iVar);
   hs[iCut][iVar] = new THStack(nameStack,nameStack);
   
   for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
    histo[iName][iCut][iVar]->GetXaxis()->SetTitle(vVarNameHR.at(iVar).first.c_str());
    histo[iName][iCut][iVar]->GetYaxis()->SetTitle(vVarNameHR.at(iVar).second.c_str());
    histo[iName][iCut][iVar]->SetMarkerColor(vColor[iName]);
    histo[iName][iCut][iVar]->SetLineColor(vColor[iName]);
    histo[iName][iCut][iVar]->SetFillColor(vColor[iName]);
    histo[iName][iCut][iVar]->SetLineWidth(2);
    histo[iName][iCut][iVar]->SetFillStyle(3001);
    
    bool isSig = false;
    for (std::vector<std::string>::const_iterator itSig = SignalName.begin(); itSig != SignalName.end(); itSig++){
     if (reduced_name_samples.at(iName) == *itSig) isSig = true;
    }
    
    if (!isSig && reduced_name_samples.at(iName) != "DATA") {
     hs[iCut][iVar]->Add(histo[iName][iCut][iVar]);
    }
    else {
     if (!isSig) {
      histo[iName][iCut][iVar]->SetMarkerStyle(20);
      histo[iName][iCut][iVar]->SetMarkerSize(1);
      histo[iName][iCut][iVar]->SetMarkerColor(kBlack);
      histo[iName][iCut][iVar]->SetLineColor(kBlack);
      histo[iName][iCut][iVar]->SetFillColor(kBlack);
      histo[iName][iCut][iVar]->SetLineWidth(2);
      histo[iName][iCut][iVar]->SetFillStyle(3001);  
     }
     else {
      histo[iName][iCut][iVar]->SetMarkerStyle(21);
      histo[iName][iCut][iVar]->SetMarkerSize(1);
      histo[iName][iCut][iVar]->SetLineWidth(2);
      histo[iName][iCut][iVar]->SetFillStyle(3001);  
     }
    }
   }
   ///==== histo sum MC ====    
   ///==== Add systrematic error ====
//    AddError(hs[iCut][iVar],LumiSyst);
   histoSumMC[iCut][iVar] = ((TH2F*)(hs[iCut][iVar]->GetStack()->Last()));
    
   ///==== legend ====
   if (!LegendBuilt){
    for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
     leg->AddEntry(histo[iName][iCut][iVar],reduced_name_samples.at(iName).c_str(),"pf");    
     LegendBuilt = true;
    }
   }
  }
 }
 std::cout << std::endl << std::endl;
 
 
 
 LumiSyst = 0; ///---- bug fix
 

//  [iName][iCut][iVar]
 TCanvas* cCanvasAll[100][30][30];

 TCanvas* cCompareCut[100];
 TCanvas* cCompareVar[100];
 
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
  TString nameCanvas = Form("%d_Cut_Canvas",iCut);
  cCompareCut[iCut] = new TCanvas(nameCanvas,nameCanvas,400 * vVarName.size(),400);
  cCompareCut[iCut] -> Divide (vVarName.size(),1);
 }
 
 for (unsigned int iVar = 0; iVar<vVarName.size(); iVar++){ ///==== cicle on variables to plot ====
   TString nameCanvas = Form("%d_Var_Canvas",iVar);
   cCompareVar[iVar] = new TCanvas(nameCanvas,nameCanvas,400,400 * vCut.size());
   cCompareVar[iVar] -> Divide (1,vCut.size());
 }
 
 
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
  for (unsigned int iVar = 0; iVar<vVarName.size(); iVar++){
   TString nameCanvas = Form("%d_%d_Canvas",iCut,iVar);
   ccCanvas[iCut][iVar] = new TCanvas(nameCanvas,nameCanvas,400,400);
   for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
    TString nameCanvasName = Form("%d_%d_%d_Canvas",iCut,iVar,iName);
    cCanvasAll[iName][iCut][iVar] = new TCanvas(nameCanvasName,nameCanvasName,400,400);
   }
  }
 } 
 
 ///==== cicle on selections ====
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
  ///==== cicle on variables to plot ====
  for (unsigned int iVar = 0; iVar<vVarName.size(); iVar++){
   ///==== draw in canvas ====
   
   for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
    cCanvasAll[iName][iCut][iVar]->cd();
    gPad->SetLeftMargin(0.14);
    gPad->SetRightMargin(0.23);
    histo[iName][iCut][iVar]->Draw();
    histo[iName][iCut][iVar]->GetXaxis()->SetTitle(vVarNameHR.at(iVar).first.c_str());
    histo[iName][iCut][iVar]->GetYaxis()->SetTitle(vVarNameHR.at(iVar).second.c_str());
    gPad->SetLogz();
    gPad->SetGrid();
    leg->Draw();
    latex->Draw();
   }
   
   cCompareCut[iCut] -> cd(iVar+1);
   hs[iCut][iVar] ->Draw();
   hs[iCut][iVar]->GetXaxis()->SetTitle(vVarNameHR.at(iVar).first.c_str());
   hs[iCut][iVar]->GetYaxis()->SetTitle(vVarNameHR.at(iVar).second.c_str());
   gPad->SetLogz();
   gPad->SetGrid();
   leg->Draw();
   latex->Draw();
   
   cCompareVar[iVar] -> cd(iCut+1);
   hs[iCut][iVar] ->Draw("LEGO");
   hs[iCut][iVar]->GetXaxis()->SetTitle(vVarNameHR.at(iVar).first.c_str());
   hs[iCut][iVar]->GetYaxis()->SetTitle(vVarNameHR.at(iVar).second.c_str());
   gPad->SetLogz();
   gPad->SetGrid();
   leg->Draw();
   latex->Draw();

   ccCanvas[iCut][iVar]-> cd();
   hs[iCut][iVar]->Draw("LEGO");
   hs[iCut][iVar]->GetXaxis()->SetTitle(vVarNameHR.at(iVar).first.c_str());
   hs[iCut][iVar]->GetYaxis()->SetTitle(vVarNameHR.at(iVar).second.c_str());
   gPad->SetLogz();
   gPad->SetGrid();
   leg->Draw();
   latex->Draw();

   for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
    
    bool isSig = false;
    for (std::vector<std::string>::const_iterator itSig = SignalName.begin(); itSig != SignalName.end(); itSig++){
     if (reduced_name_samples.at(iName) == *itSig) isSig = true;
    }
    
    if (isSig || reduced_name_samples.at(iName) == "DATA") {
     cCompareCut[iCut] -> cd(iVar+1);
//      histo[iName][iCut][iVar]->Draw("EsameB");
//      histo[iName][iCut][iVar]->Draw("same");
     
     cCompareVar[iVar] -> cd(iCut+1);
//      histo[iName][iCut][iVar]->Draw("EsameB");
//      histo[iName][iCut][iVar]->Draw("same");
     
     ccCanvas[iCut][iVar]-> cd();
//      histo[iName][iCut][iVar]->Draw("EsameB");
//      histo[iName][iCut][iVar]->Draw("same");
    }
   }
   
   cCompareCut[iCut] -> cd(iVar+1);
   leg->Draw();
   cCompareVar[iVar] -> cd(iCut+1);
   leg->Draw();
   ccCanvas[iCut][iVar]-> cd();
   leg->Draw();
   
  } ///==== end cicle on variables to plot ====
 } ///==== end cicle on selections ====
 
 std::cerr << " ******************************************* end *******************************************" << std::endl;
 end = clock();
 std::cout <<"Time = " <<  ((double) (end - start)) << " (a.u.)" << std::endl;  
 
 
 
 ///==== save output ====
 outFile.cd();
 
 outFile.cd();
 outFile.mkdir("PU");
 outFile.cd("PU");
 
 if (!doWeightFromFile) { 
  hPUMC     -> Write();
  hPUDATA   -> Write();
  hPUWeight -> Write();
 }
 
 outFile.cd();
 outFile.mkdir("Cut");
 outFile.cd("Cut");
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
  cCompareCut[iCut] -> Write();
  TString nameCut = Form ("Cut_%d",iCut);
  TString Cut = Form ("%s",vCut.at(iCut).c_str());
  TNamed nameCutNamed (nameCut,Cut);
  nameCutNamed.Write();
 }
 
 outFile.cd();
 outFile.mkdir("Var");
 outFile.cd("Var");
 for (unsigned int iVar = 0; iVar<vVarName.size(); iVar++){
  cCompareVar[iVar] -> Write();
 }
 
 outFile.cd();
 TDirectory* cdAll = (TDirectory*) outFile.mkdir("All");
 cdAll->mkdir("Var");
 outFile.cd("All/Var");
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
  for (unsigned int iVar = 0; iVar<vVarName.size(); iVar++){
   ccCanvas[iCut][iVar]-> Write();
  }
 }
 
 
 outFile.cd();
 outFile.mkdir("Data");
 outFile.cd("Data");
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
  for (unsigned int iVar = 0; iVar<vVarName.size(); iVar++){
   hs[iCut][iVar] -> Write() ;
   for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
    histo[iName][iCut][iVar] -> Write();
    //     bool isSig = false;
    //     for (std::vector<std::string>::const_iterator itSig = SignalName.begin(); itSig != SignalName.end(); itSig++){
     //      if (reduced_name_samples.at(iName) == *itSig) isSig = true;
    //     }
    //     if (isSig || reduced_name_samples.at(iName) == "DATA") {
     //      histo[iName][iCut][iVar] -> Write();
    //     }
   }
   //    ((TH1F*)(hs[iCut][iVar] ->GetStack()->Last()))->Write() ;
   TH1F* tempH =  ((TH1F*)(hs[iCut][iVar] ->GetStack()->Last())) ;
   TString name = Form("All_%d_%d",iCut,iVar);
   tempH -> SetName(name);
   tempH -> Write();
  }
 }
 
 
 outFile.cd();
 cdAll->mkdir("CutVar");
 outFile.cd("All/CutVar");
 ///==== cicle on selections ====
 for (unsigned int iCut = 0; iCut<vCut.size(); iCut++){
  ///==== cicle on variables to plot ====
  for (unsigned int iVar = 0; iVar<vVarName.size(); iVar++){
   for (unsigned int iName=0; iName<reduced_name_samples.size(); iName++){
    cCanvasAll[iName][iCut][iVar]->Write();
   }
  }
 }
 outFile.cd();
   
 
 
 
 
 
 
 
 leg->Write();
 
}
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;
 
 
 //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;  
 
 float weight;
 std::string nameWeight = "weight"; 
 nameWeight = gConfigParser -> readStringOption("Input::nameWeight");
 
 TTree *treeJetLepVect[1000];
 

 char *nameSample[1000];
 char *nameHumanReadable[1000];
 char* xsectionName[1000];
 
 double Normalization[1000];
 float xsection[1000];
 char nameFileIn[1000];
 sprintf(nameFileIn,"%s",fileSamples.c_str());

 int numberOfSamples = ReadFile(nameFileIn, nameSample, nameHumanReadable, xsectionName);
 
 
 ///==== 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 ====
 
 int Entries[100];
 
 for (int iSample=0; iSample<numberOfSamples; iSample++){
  xsection[iSample] = atof(xsectionName[iSample]);
 }

 for (int iSample=0; iSample<numberOfSamples; iSample++){
  if (debug) std::cout << " iSample = " << iSample << std::endl;
  
  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");
  
  treeJetLepVect[iSample] = (TTree*) f->Get(treeName.c_str());
  char nameTreeJetLep[100];
  sprintf(nameTreeJetLep,"treeJetLep_%d",iSample); 
  treeJetLepVect[iSample]->SetName(nameTreeJetLep);
  treeJetLepVect[iSample]->SetBranchAddress(nameWeight.c_str(),&weight);
  
  if (treeJetLepVect[iSample]->GetEntries() != 0) {
   treeJetLepVect[iSample]->GetEntry(0);
   if (weight == xsection[iSample]){
    std::cout << " OK ";
   }
   else {
    std::cout << " NO ";
   }
   std::cout << " weight[" << nameWeight.c_str() <<  "][" << iSample << "] = " << weight << " = " << xsection[iSample];
   if (weight != xsection[iSample]){
    std::cout << " ---> " << nameSample[iSample];
   }
   std::cout << std::endl;
  }
  else {
   std::cout << " problem ... 0 entries ! " << std::endl;
   exit(1);
  }
 }
 
 std::cout << std::endl;
 
}