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) {

    if(argc != 2)
    {
        std::cerr << ">>>>> analysis.cpp::usage: " << argv[0] << " configFileName      MVAconfigFileName" << std::endl ;
        return 1;
    }

    // Parse the config file
    parseConfigFile (argv[1]) ;

    std::string treeName  = gConfigParser -> readStringOption("Input::treeName");
    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("Options::Lumi");

    std::vector<std::string> SignalName;
    SignalName = gConfigParser -> readStringListOption("Options::SignalName");

    for (int iSignalSample=0; iSignalSample<SignalName.size(); iSignalSample++) {
        std::cout << " Signal[" << iSignalSample << "] = " << SignalName.at(iSignalSample) << std::endl;
    }

    std::string nameWeight = "1";
    try {
        nameWeight = gConfigParser -> readStringOption("Options::nameWeight");
    }
    catch (char const* exceptionString) {
        std::cerr << " exception = " << exceptionString << std::endl;
    }
    std::cout << ">>>>> Input::nameWeight  " << nameWeight  << std::endl;



    TTree *treeJetLepVect[200];

    char *nameSample[1000];
    char *nameHumanReadable[1000];
    char* xsectionName[1000];

    char nameFileIn[1000];
    sprintf(nameFileIn,"%s",fileSamples.c_str());

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

    double Normalization[1000];
    double xsection[1000];

    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");

        treeJetLepVect[iSample] = (TTree*) f->Get(treeName.c_str());
        char nameTreeJetLep[100];
        sprintf(nameTreeJetLep,"treeJetLep_%d",iSample);
        treeJetLepVect[iSample]->SetName(nameTreeJetLep);

        double XSection;
        XSection = xsection[iSample];
        Normalization[iSample] = XSection * LUMI / 1000.;
    }

    //==== cut
    std::string CutFile = gConfigParser -> readStringOption("Selections::CutFile");
    std::vector<std::string> vCut;
    std::cout << " nCuts   = " << ReadFileCut(CutFile, vCut) << std::endl;

    std::string Cut;
    if (vCut.size() != 0) {
        Cut = vCut.at(0);
    }
    else {
        Cut = "1";
    }

    //==== HiggsMass
    std::string HiggsMass = gConfigParser -> readStringOption("Options::HiggsMass");

    //==== list of methods
    std::vector<std::string> vectorMyMethodList = gConfigParser -> readStringListOption("Options::MVAmethods");
    TString myMethodList;
    for (int iMVA = 0; iMVA < vectorMyMethodList.size(); iMVA++) {
        if (iMVA == 0) myMethodList = Form ("%s",vectorMyMethodList.at(iMVA).c_str());
        else           myMethodList = Form ("%s,%s",myMethodList.Data(),vectorMyMethodList.at(iMVA).c_str());
    }

    //==== output
    TString outfileName = gConfigParser -> readStringOption("Output::outFileName");


    // This loads the library
    TMVA::Tools::Instance();

    // Default MVA methods to be trained + tested
    std::map<std::string,int> Use;

    Use["MLP"]             = 1;
    Use["BDTG"]            = 1;
    Use["FDA_GA"]          = 0;
    Use["PDEFoam"]         = 0;


    std::cout << std::endl;
    std::cout << "==> Start TMVAClassification" << std::endl;

    // Select methods (don't look at this code - not of interest)
    if (myMethodList != "") {
        for (std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++) it->second = 0;

        std::vector<TString> mlist = TMVA::gTools().SplitString( myMethodList, ',' );
        for (UInt_t i=0; i<mlist.size(); i++) {
            std::string regMethod(mlist[i]);

            if (Use.find(regMethod) == Use.end()) {
                std::cout << "Method \"" << regMethod << "\" not known in TMVA under this name. Choose among the following:" << std::endl;
                for (std::map<std::string,int>::iterator it = Use.begin(); it != Use.end(); it++) std::cout << it->first << " ";
                std::cout << std::endl;
                return 0;
            }
            Use[regMethod] = 1;
        }
    }

    // --------------------------------------------------------------------------------------------------
    // --- Here the preparation phase begins

    // Create a new root output file
    TFile* outputFile = TFile::Open( outfileName, "RECREATE" );

//   TMVA::Factory *factory = new TMVA::Factory( "TMVAMulticlass",     outputFile, "AnalysisType=multiclass:!V:!Silent:!V:Transformations=I;D" );
    TMVA::Factory *factory = new TMVA::Factory( "TMVAMulticlass",     outputFile, "!V:!Silent:Color:DrawProgressBar:Transformations=I;D;P;G,D:AnalysisType=multiclass" );

    factory->AddVariable( "jetpt1" , 'F');
    factory->AddVariable( "jetpt2" , 'F');
    factory->AddVariable( "mjj" , 'F');
    factory->AddVariable( "detajj" , 'F');
    factory->AddVariable( "dphilljetjet" , 'F');

    factory->AddVariable( "pt1" , 'F');
    factory->AddVariable( "pt2" , 'F');
    factory->AddVariable( "mll" , 'F');
    factory->AddVariable( "dphill" , 'F');
    factory->AddVariable( "mth" , 'F');

    factory->AddVariable( "dphillmet" , 'F');
    factory->AddVariable( "mpmet" , 'F');

    factory->AddSpectator( "channel" , 'F');

    for (int iSample=0; iSample<numberOfSamples; iSample++) {
        int numEnt = treeJetLepVect[iSample]->GetEntries(Cut.c_str());
        std::cout << " Sample = " << nameSample[iSample] << " ~ " << nameHumanReadable[iSample] << " --> " << numEnt << std::endl;
        if (numEnt != 0) {
            if (iSample == 0) factory->AddTree( treeJetLepVect[iSample], "Signal", Normalization[iSample] );
            else if (iSample == 1) factory->AddTree( treeJetLepVect[iSample], "Background", Normalization[iSample] );
            else factory->AddTree( treeJetLepVect[iSample], TString(nameHumanReadable[iSample]), Normalization[iSample] );

//     factory->AddTree( treeJetLepVect[iSample], TString(nameHumanReadable[iSample]), Normalization[iSample] );
//     factory->AddTree( treeJetLepVect[iSample], TString(nameHumanReadable[iSample]), Normalization[iSample] , nameWeight.c_str());
            //     factory->AddTree( treeJetLepVect[iSample], TString(nameHumanReadable[iSample]));
        }
    }

//   for (int iSample=0; iSample<numberOfSamples; iSample++){
//    int numEnt = treeJetLepVect[iSample]->GetEntries(Cut.c_str());
//    std::cout << " Sample = " << nameSample[iSample] << " ~ " << nameHumanReadable[iSample] << " --> " << numEnt << std::endl;
//    if (numEnt != 0) {
//     bool isSig = false;
//     for (std::vector<std::string>::const_iterator itSig = SignalName.begin(); itSig != SignalName.end(); itSig++){
//      if (nameHumanReadable[iSample] == *itSig) isSig = true;
//     }
//     if (isSig) {
//      factory->AddTree( treeJetLepVect[iSample], TString("Signal"), Normalization[iSample] ); //---> ci deve essere uno chiamato Signal!
//     }
//     else {
//      factory->AddTree( treeJetLepVect[iSample], TString(nameHumanReadable[iSample]), Normalization[iSample] );
//     }
//    }
//   }
//
//   for (int iSample=0; iSample<numberOfSamples; iSample++){
//    int numEnt = treeJetLepVect[iSample]->GetEntries(Cut.c_str());
//    std::cout << " Sample = " << nameSample[iSample] << " ~ " << nameHumanReadable[iSample] << " --> " << numEnt << std::endl;
//    if (numEnt != 0) {
//     bool isSig = false;
//     for (std::vector<std::string>::const_iterator itSig = SignalName.begin(); itSig != SignalName.end(); itSig++){
//      if (nameHumanReadable[iSample] == *itSig) isSig = true;
//     }
//     if (isSig) {
// //      factory->AddTree( treeJetLepVect[iSample], TString("Signal"), Normalization[iSample] ); //---> ci deve essere uno chiamato Signal!
//     }
//     else {
//      factory->AddTree( treeJetLepVect[iSample], TString(nameHumanReadable[iSample]), Normalization[iSample] );
//     }
//    }
//   }


    std::cerr << " AAAAAAAAAAAAAAAAAAAAAAAAAAAAA " << std::endl;

    TCut mycuts = Cut.c_str();

//   factory->SetWeightExpression( nameWeight.c_str() );
//   factory->SetBackgroundWeightExpression( nameWeight.c_str() );
//   factory->SetSignalWeightExpression    ( nameWeight.c_str() );

    std::cerr << " BBBBBBBBBBBBBBBBBBBBBBBBBBBBB " << std::endl;

    factory->PrepareTrainingAndTestTree( mycuts ,"SplitMode=Random:NormMode=None:!V");
//   factory->PrepareTrainingAndTestTree( "" ,"SplitMode=Random:NormMode=None:!V");

    std::cerr << " CCCCCCCCCCCCCCCCCCCCCCCCCCCCC " << std::endl;



    // gradient boosted decision trees
//   if (Use["BDTG"])    factory->BookMethod( TMVA::Types::kBDT, "BDTG", "!H:!V:NTrees=1000:BoostType=Grad:Shrinkage=0.10:UseBaggedGrad:GradBaggingFraction=0.50:nCuts=20:NNodesMax=8");
    if (Use["BDTG"])    factory->BookMethod( TMVA::Types::kBDT, "BDTG", "!H:!V:NTrees=600:BoostType=Grad:Shrinkage=0.10:UseBaggedGrad:GradBaggingFraction=0.50:nCuts=20:NNodesMax=8");
    // neural network
    if (Use["MLP"])     factory->BookMethod( TMVA::Types::kMLP, "MLP", "!H:!V:NeuronType=tanh:NCycles=1000:HiddenLayers=N+5,5:TestRate=5:EstimatorType=MSE");
    // functional discriminant with GA minimizer
    if (Use["FDA_GA"])  factory->BookMethod( TMVA::Types::kFDA, "FDA_GA", "H:!V:Formula=(0)+(1)*x0+(2)*x1+(3)*x2+(4)*x3:ParRanges=(-1,1);(-10,10);(-10,10);(-10,10);(-10,10):FitMethod=GA:PopSize=300:Cycles=3:Steps=20:Trim=True:SaveBestGen=1" );
    // PDE-Foam approach
    if (Use["PDEFoam"]) factory->BookMethod( TMVA::Types::kPDEFoam, "PDEFoam", "!H:!V:TailCut=0.001:VolFrac=0.0666:nActiveCells=500:nSampl=2000:nBin=5:Nmin=100:Kernel=None:Compress=T" );



    //==== Optimize parameters in MVA methods
//   factory->OptimizeAllMethods();
//   factory->OptimizeAllMethods("ROCIntegral","Scan");
    //==== Train MVAs using the set of training events ====
    factory->TrainAllMethods();

    //==== Evaluate all MVAs using the set of test events ====
    factory->TestAllMethods();

    //==== Evaluate and compare performance of all configured MVAs ====
    factory->EvaluateAllMethods();

    // --------------------------------------------------------------

    // Save the output
    outputFile->Close();

    std::cout << "==> Wrote root file: " << outputFile->GetName() << std::endl;
    std::cout << "==> TMVAnalysis is done!" << std::endl;

    delete factory;

    //==== change position of weights file
    std::string toDo;

    toDo = "rm -r Weights-MVA-MultiClass/weights_" + HiggsMass + "_testVariables";
    std::cerr << "toDo = " << toDo << std::endl;
    system (toDo.c_str());

    toDo = "mv weights Weights-MVA-MultiClass/weights_" + HiggsMass + "_testVariables";
    std::cerr << "toDo = " << toDo << std::endl;
    system (toDo.c_str());

    // Launch the GUI for the root macros
    //   if (!gROOT->IsBatch()) TMVAGui( outfileName );
}
示例#3
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; 

 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;  
 
 
 
}
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();
 
}