Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-16 08:25:21

0001 ////////////////////////////////////////
0002 // Read reconstruction ROOT output file
0003 // Plot variables
0004 ////////////////////////////////////////
0005 
0006 #include "ROOT/RDataFrame.hxx"
0007 #include <iostream>
0008 #include <algorithm>
0009 #include <string>
0010 
0011 #include "edm4hep/MCParticleCollection.h"
0012 #include "edm4hep/SimCalorimeterHitCollection.h"
0013 
0014 #include <boost/range/combine.hpp>
0015 
0016 #include "DD4hep/IDDescriptor.h"
0017 #include "DD4hep/Readout.h"
0018 #include "DD4hep/Segmentations.h"
0019 
0020 #include "TCanvas.h"
0021 #include "TStyle.h"
0022 #include "TMath.h"
0023 #include "TH1.h"
0024 #include "TF1.h"
0025 #include "TH1D.h"
0026 #include "TFitResult.h"
0027 #include "TLegend.h"
0028 #include "TString.h"
0029 #include "TGraph.h"
0030 #include "TGraph2D.h"
0031 #include "TGraphErrors.h"
0032 #include "TLine.h"
0033 #include "TError.h"
0034 
0035 R__LOAD_LIBRARY(libfmt.so)
0036 #include "fmt/core.h"
0037 #include "DD4hep/Detector.h"
0038 #include "DDG4/Geant4Data.h"
0039 #include "DDRec/CellIDPositionConverter.h"
0040 #include "emcal_barrel_common_functions.h"
0041 
0042 using ROOT::RDataFrame;
0043 using namespace ROOT::VecOps;
0044 
0045 void emcal_barrel_pion_rejection_analysis(
0046                                           const char* input_fname1 = "sim_output/sim_emcal_barrel_piRej_electron.edm4hep.root",
0047                                           const char* input_fname2 = "sim_output/sim_emcal_barrel_piRej_piminus.edm4hep.root"
0048                                           )
0049 {
0050   // Error Ignore Level Set
0051   gErrorIgnoreLevel = kFatal;
0052 
0053   // Setting for graphs
0054   gROOT->SetStyle("Plain");
0055   gStyle->SetOptFit(1);
0056   gStyle->SetLineWidth(2);
0057   gStyle->SetPadTickX(1);
0058   gStyle->SetPadTickY(1);
0059   gStyle->SetPadGridX(1);
0060   gStyle->SetPadGridY(1);
0061   gStyle->SetPadLeftMargin(0.14);
0062   gStyle->SetPadRightMargin(0.14);
0063 
0064   ROOT::EnableImplicitMT();
0065   ROOT::RDataFrame d0("events", {input_fname1, input_fname2});
0066 
0067   // Script requires EcalBarrelScFiHits
0068   if (! d0.HasColumn("EcalBarrelScFiHits")) {
0069     std::cout << "EcalBarrelScFiHits is required" << std::endl;
0070     return;
0071   }
0072 
0073   // Environment Variables
0074   std::string detector_path = "";
0075   std::string detector_name = "athena";//athena
0076   if(std::getenv("DETECTOR_PATH")) {
0077     detector_path = std::getenv("DETECTOR_PATH");
0078   }
0079   if(std::getenv("DETECTOR_CONFIG")) {
0080     detector_name = std::getenv("DETECTOR_CONFIG");
0081   }
0082 
0083   /*
0084   // Sampling Fraction grabbed from json file
0085   json j;
0086   std::ifstream prev_steps_ifstream("results/emcal_barrel_electron_calibration.json");
0087   prev_steps_ifstream >> j;
0088 
0089   // Sampling Fraction
0090   double samp_frac = j["electron"]["sampling_fraction"];
0091   */
0092 
0093   // Detector Layer Variables
0094   int layerNum; 
0095   int dep_min = 1;
0096   int dep_max = 6;
0097 
0098   // DD4HEP interface 
0099   dd4hep::Detector& detector = dd4hep::Detector::getInstance();
0100   detector.fromCompact(fmt::format("{}/{}.xml", detector_path, detector_name));
0101 
0102   auto decoder         = detector.readout("EcalBarrelImagingHits").idSpec().decoder();
0103   auto decoderScFi     = detector.readout("EcalBarrelScFiHits").idSpec().decoder();
0104   auto layer_index     = decoder->index("layer");
0105   auto layer_indexScFi = decoderScFi->index("layer");
0106 
0107   // Thrown Energy [GeV]
0108   auto Ethr = [](std::vector<edm4hep::MCParticleData> const& input) {
0109     return TMath::Sqrt(input[2].momentum.x*input[2].momentum.x + input[2].momentum.y*input[2].momentum.y + input[2].momentum.z*input[2].momentum.z + input[2].mass*input[2].mass);
0110   };
0111 
0112   // Thrown Momentum [GeV]
0113   auto Pthr = [](std::vector<edm4hep::MCParticleData> const& input) {
0114     return TMath::Sqrt(input[2].momentum.x*input[2].momentum.x + input[2].momentum.y*input[2].momentum.y + input[2].momentum.z*input[2].momentum.z);
0115   };
0116 
0117   // Thrown Eta 
0118   auto Eta = [](std::vector<edm4hep::MCParticleData> const& input) {
0119     double E  = TMath::Sqrt(input[2].momentum.x*input[2].momentum.x + input[2].momentum.y*input[2].momentum.y + input[2].momentum.z*input[2].momentum.z + input[2].mass*input[2].mass);
0120     return 0.5*TMath::Log((E + input[2].momentum.z) / (E - input[2].momentum.z));
0121   };
0122 
0123   // Thrown pT [GeV]
0124   auto pT = [](std::vector<edm4hep::MCParticleData> const& input) {
0125     return TMath::Sqrt(input[2].momentum.x*input[2].momentum.x + input[2].momentum.y*input[2].momentum.y);
0126   };
0127 
0128   // Number of hits
0129   auto nhits = [] (const std::vector<edm4hep::SimCalorimeterHitData>& evt) {return (int) evt.size(); };
0130 
0131   // Energy deposition [GeV]
0132   auto Esim = [](const std::vector<edm4hep::SimCalorimeterHitData>& evt) {
0133     double total_edep = 0.0;
0134     for (const auto& i: evt){
0135       total_edep += i.energy;
0136     }
0137     return total_edep;
0138   };
0139 
0140   // Energy deposititon [GeV] in the first 2 layers
0141   auto Esim_dep2 = [=](const std::vector<edm4hep::SimCalorimeterHitData>& evt) {
0142     auto total_edep = 0.0;
0143     for (const auto& i: evt) {
0144       if( decoder->get(i.cellID, layer_index) < 3 ){
0145         total_edep += i.energy;
0146       }
0147     }
0148     return total_edep;
0149   };
0150 
0151   // Energy deposititon [GeV] in the first 3 layers
0152   // Same as Esim_front from previous codes
0153   auto Esim_dep3 = [=](const std::vector<edm4hep::SimCalorimeterHitData>& evt) {
0154     auto total_edep = 0.0;
0155     for (const auto& i: evt) {
0156       if( decoder->get(i.cellID, layer_index) < 4 ){
0157         total_edep += i.energy;
0158       }
0159     }
0160     return total_edep;
0161   };
0162 
0163   // Energy deposititon [GeV] in the first 4 layers
0164   auto Esim_dep4 = [=](const std::vector<edm4hep::SimCalorimeterHitData>& evt) {
0165     auto total_edep = 0.0;
0166     for (const auto& i: evt) {
0167       if( decoder->get(i.cellID, layer_index) < 5 ){
0168         total_edep += i.energy;
0169       }
0170     }
0171     return total_edep;
0172   };
0173 
0174   // Energy deposititon [GeV] in the first 5 layers
0175   auto Esim_dep5 = [=](const std::vector<edm4hep::SimCalorimeterHitData>& evt) {
0176     auto total_edep = 0.0;
0177     for (const auto& i: evt) {
0178       if( decoder->get(i.cellID, layer_index) < 6 ){
0179         total_edep += i.energy;
0180       }
0181     }
0182     return total_edep;
0183   };
0184 
0185   // Energy deposititon [GeV] in the first 6 layers
0186   auto Esim_dep6 = [=](const std::vector<edm4hep::SimCalorimeterHitData>& evt) {
0187     auto total_edep = 0.0;
0188     for (const auto& i: evt) {
0189       if( decoder->get(i.cellID, layer_index) < 7 ){
0190         total_edep += i.energy;
0191       }
0192     }
0193     return total_edep;
0194   };
0195 
0196   // Energy deposititon [GeV] in the first 6 layers
0197   auto Esim_dep6_ScFi = [=](const std::vector<edm4hep::SimCalorimeterHitData>& evt) {
0198     auto total_edep = 0.0;
0199     for (const auto& i: evt) {
0200       if( decoderScFi->get(i.cellID, layer_indexScFi) < 7 ){
0201         total_edep += i.energy;
0202       } 
0203     }
0204     return total_edep;
0205   };
0206 
0207   // Energy deposititon [GeV] in the first 7 layers
0208   auto Esim_dep7 = [=](const std::vector<edm4hep::SimCalorimeterHitData>& evt) {
0209     auto total_edep = 0.0;
0210     for (const auto& i: evt) {
0211       if( decoder->get(i.cellID, layer_index) < 8 ){
0212         total_edep += i.energy;
0213       }
0214     }
0215     return total_edep;
0216   };
0217     // Energy deposititon [GeV] in the first 8 layers
0218   auto Esim_dep8 = [=](const std::vector<edm4hep::SimCalorimeterHitData>& evt) {
0219     auto total_edep = 0.0;
0220     for (const auto& i: evt) {
0221       if( decoder->get(i.cellID, layer_index) < 9 ){
0222         total_edep += i.energy;
0223       }
0224     }
0225     return total_edep;
0226   };
0227 
0228   // Energy deposititon [GeV] in the first 9 layers
0229   auto Esim_dep9 = [=](const std::vector<edm4hep::SimCalorimeterHitData>& evt) {
0230     auto total_edep = 0.0;
0231     for (const auto& i: evt) {
0232       if( decoder->get(i.cellID, layer_index) < 10 ){
0233         total_edep += i.energy;
0234       }
0235     }
0236     return total_edep;
0237   };
0238 
0239   // Energy deposititon [GeV], returns array
0240   // Note Layer_index = 0 does not exist at the wrting of this code
0241   auto Esim_dep = [=](const std::vector<edm4hep::SimCalorimeterHitData>& evt) {
0242     std::vector<double>res(20);
0243     for (const auto& i: evt) {
0244       res[decoder->get(i.cellID, layer_index)] += i.energy;
0245     }
0246     return res;
0247   };
0248 
0249   // Sum of Energy deposititon [GeV]
0250   auto Esim_dep_sum = [&dep_min, &dep_max](const std::vector<double>& dep) {
0251     double res = 0;
0252     for (int i = dep_min; i < dep_max + 1; i++) {
0253       if (i >= dep.size()) continue;
0254       res += dep[i];
0255     }
0256     return res;
0257   };
0258 
0259   // Energy deposititon in a layer [GeV]
0260   auto Esim_depN = [&layerNum](const std::vector<double>& dep) {
0261     return (layerNum < dep.size() ? dep[layerNum] : 0.0);
0262   };
0263 
0264   // Sampling fraction = Esampling / Ethrown
0265   auto fsam = [](const double& sampled, const double& thrown) {
0266     return sampled / thrown;
0267   };
0268 
0269   // E_front / p
0270   auto fEp = [](const double& E_front, const double& mom) {
0271     return E_front / mom;
0272   };
0273 
0274   // Returns the PDG of the particle
0275   auto getpid = [](std::vector<edm4hep::MCParticleData> const& input) {
0276     return input[2].PDG;
0277   };
0278 
0279   // Returns number of particle daughters
0280   auto getdau = [](std::vector<edm4hep::MCParticleData> const& input){
0281     return input[2].daughters_begin;
0282   };
0283 
0284   // Filter function to get electrons
0285   auto is_electron = [](std::vector<edm4hep::MCParticleData> const& input){
0286     return (input[2].PDG == 11 ? true : false);
0287   };
0288 
0289   // Filter function to get just negative pions
0290   auto is_piMinus = [](std::vector<edm4hep::MCParticleData> const& input){
0291     return (input[2].PDG == -211 ? true : false);
0292   };
0293 
0294   // Filter function Edeposit
0295   auto EDep_bool = [](std::vector<double> const& input){
0296     return (input[0] > input[1]);
0297   };
0298 
0299   auto Diff = [](const double &esim, const double &edep){
0300     return esim-edep;
0301   };
0302 
0303 
0304   // Define variables
0305   auto d1 = d0.Define("Ethr",            Ethr,                  {"MCParticles"})
0306               .Define("Pthr",            Pthr,                  {"MCParticles"})
0307               .Define("nhits",           nhits,                 {"EcalBarrelImagingHits"})
0308               .Define("Esim",            Esim,                  {"EcalBarrelImagingHits"})
0309               .Define("EsimScFi",        Esim,                  {"EcalBarrelScFiHits"})
0310               .Define("EsimOverP",       fEp,                   {"Esim", "Pthr"})
0311               .Define("EsimScFiOverP",   fEp,                   {"EsimScFi", "Pthr"})
0312               .Define("EsimTot",                                "EsimScFi+Esim")
0313               .Define("EsimTotOverP",    fEp,                   {"EsimTot", "Pthr"})
0314               .Define("fsam",            fsam,                  {"Esim","Ethr"})
0315               .Define("pid",             getpid,                {"MCParticles"})
0316               .Define("EDep",            Esim_dep,              {"EcalBarrelImagingHits"})
0317               .Define("EDepSum",         Esim_dep_sum,          {"EDep"})
0318               .Define("EDepN",           Esim_depN,             {"EDep"})
0319               .Define("EDep2",           Esim_dep2,             {"EcalBarrelImagingHits"})
0320               .Define("EDep3",           Esim_dep3,             {"EcalBarrelImagingHits"})
0321               .Define("EDep4",           Esim_dep4,             {"EcalBarrelImagingHits"})
0322               .Define("EDep5",           Esim_dep5,             {"EcalBarrelImagingHits"})
0323               .Define("EDep6",           Esim_dep6,             {"EcalBarrelImagingHits"})
0324               .Define("EDep6OverP",      fEp,                   {"EDep6", "Pthr"})
0325               .Define("EOverP",          fEp,                   {"EDep3", "Pthr"})
0326               .Define("Eta",             Eta,                   {"MCParticles"})
0327               .Define("pT",              pT,                    {"MCParticles"})
0328               .Define("EDepOverP",       fEp,                   {"EDepN", "Pthr"})
0329               .Define("EDepOverPT",      fEp,                   {"EDepN", "pT"})
0330               .Define("EDepSumOverP",    fEp,                   {"EDepSum", "Pthr"})
0331               .Define("EDepSumOverPT",   fEp,                   {"EDepSum", "pT"})
0332               .Define("EDepFrac",        fEp,                   {"EDepSum", "Esim"})
0333               ;
0334   
0335   // Particle Filters
0336   dep_min = 1;
0337   dep_max = 6;
0338   auto d_ele = d1.Filter(is_electron, {"MCParticles"});
0339   auto d_pim = d1.Filter(is_piMinus,  {"MCParticles"});
0340 
0341   // Cut Filter
0342   std::string currentCut = "(EDep6OverP>2.5e-3)&&(EDep6>5e-3)";// Good athena cut, that is changed by cutEE later
0343 
0344   // Generic 1D Histogram Plots Comparing Electons and Pions w/o cuts
0345   // Edep first 6 layers(EDep6), EDep/p, pT, eta
0346   std::vector<std::string> var              = {"Esim [GeV];", "EsimTot [GeV];", "EDep6 [GeV];", "EDep6/p;",     "pT [GeV];", "#eta;",  "EsimScFi [GeV]",  "EsimScFi/p"};
0347   std::vector<std::string> var_save         = {"Esim",        "EsimTot",        "EDep6",        "EDep6OverP",   "pT",        "eta",    "EsimScFi",        "EsimScFiOverP"};  
0348   std::vector<std::string> col              = {"Esim",        "EsimTot",        "EDep6",        "EDep6OverP",   "pT",        "Eta",    "EsimScFi",        "EsimScFiOverP"};
0349   std::vector<std::vector<double>> h1Ranges = {{0,0.2},       {0, 0.2},         {0,0.25},       {0, 0.02},      {0, 18},     {-1, 1},  {0,0.2},            {0,0.2}};
0350   for (int i = 0; i < var.size(); i++){
0351     std::string title = "#pi^{-}, e^{-};" + var[i] + " Events";
0352     auto he = d_ele.Histo1D({"he", title.c_str(), 100, h1Ranges[i][0], h1Ranges[i][1]}, col[i]);
0353     auto hp = d_pim.Histo1D({"hp", title.c_str(), 100, h1Ranges[i][0], h1Ranges[i][1]}, col[i]);
0354 
0355     hp->GetYaxis()->SetTitleOffset(1.4);
0356     he->SetLineWidth(2);
0357     he->SetLineColor(kRed);
0358     hp->SetLineWidth(2);
0359     hp->SetLineColor(kBlue);
0360     auto c = new TCanvas("c", "c", 700, 500);
0361     auto leng = new TLegend(0.7, 0.7, 0.9, 0.9);
0362     if (var[i] != "EsimScFi/p"){ 
0363       hp->DrawClone();
0364       he->DrawClone("same");
0365     }
0366     else {
0367       he->DrawClone();
0368       hp->DrawClone("same");
0369     }
0370     c->Update();
0371 
0372     leng->AddEntry(he.GetPtr(),"e^{-}","l");
0373     leng->AddEntry(hp.GetPtr(),"#pi^{-}","l");
0374     leng->Draw();
0375     c->SaveAs(("results/emcal_barrel_pion_rej_uncut_comb_" + var_save[i] + ".png").c_str());
0376   }
0377 
0378   // Cut Generation
0379   // The cut breaks the Energy range in to three energy bins (EBins) and the two barrel eta bins (-1 to 0, and 0 to 1)
0380   // Then fits a gaussian within the range
0381   // The cut is then based upon Mean -2*StdDev < Mean < 3*StdDev
0382   std::string cutEEta;
0383   std::vector<std::vector<double>> EBins = {{0,2}, {2, 4}, {4, 6}, {6, 9}, {9, 12}, {12, 19}};
0384   for (int i = 0; i < EBins.size(); i++){
0385     std::string minCut = "Pthr>="+std::to_string(EBins[i][0]);
0386     std::string maxCut = "Pthr<"+std::to_string(EBins[i][1]);
0387     cutEEta += "(" + minCut + "&&" + maxCut + "&&";
0388     
0389     for (int j = -1; j < 1; j++){
0390       std::string title = "#pi^{-}, e^{-}";
0391       title += fmt::format(" : {} < E < {}", EBins[i][0], EBins[i][1]);
0392       title += fmt::format(" & {} < #eta < {};EDep6/p; Events", j, j+1);
0393       std::string etaCutMin = fmt::format("Eta>={}", j);
0394       std::string etaCutMax = fmt::format("Eta<{}",j+1);
0395       cutEEta += "(" + etaCutMin + "&&" + etaCutMax;
0396       auto he = d_ele.Filter(minCut).Filter(maxCut).Filter(etaCutMin).Filter(etaCutMax).Histo1D({"he", title.c_str(), 50, 0, 0.02}, "EDep6OverP");
0397       auto hp = d_pim.Filter(minCut).Filter(maxCut).Filter(etaCutMin).Filter(etaCutMax).Histo1D({"hp", title.c_str(), 50, 0, 0.02}, "EDep6OverP");
0398       auto hecopy = he->DrawCopy();
0399       hecopy->Fit("gaus", "", "", 0, hecopy->GetMaximum());
0400       TF1* gaus = hecopy->GetFunction("gaus");
0401       if (gaus != nullptr) {
0402         double* res = gaus->GetParameters();
0403         cutEEta += fmt::format("&&EDep6OverP>={}", res[1] - 2.0*res[2]);
0404         cutEEta += fmt::format("&&EDep6OverP<{})||",res[1] + 3.0*res[2]);
0405       } else {
0406         cutEEta += ")||"; // Close the eta condition without EDep6OverP
0407         std::cerr << "Warning: Gaussian fit failed for E bin " << i << ", eta bin " << j << std::endl;
0408       }
0409 
0410       hp->GetYaxis()->SetTitleOffset(1.4);
0411       he->SetLineWidth(2);
0412       he->SetLineColor(kRed);
0413       hp->SetLineWidth(2);
0414       hp->SetLineColor(kBlue);
0415       auto c = new TCanvas("c", "c", 700, 500);
0416       auto leng = new TLegend(0.7, 0.7, 0.9, 0.9);
0417       hp->DrawClone();
0418       he->DrawClone("same");
0419       c->Update();
0420 
0421       leng->AddEntry(he.GetPtr(),"e^{-}","l");
0422       leng->AddEntry(hp.GetPtr(),"#pi^{-}","l");
0423       leng->Draw();
0424       c->SaveAs((fmt::format("results/emcal_barrel_pion_rej_uncut_comb_E{}Eta{}.png", i, j+1)).c_str());
0425     }
0426     cutEEta.pop_back();
0427     cutEEta.pop_back();
0428     cutEEta += ")||";
0429   }
0430   cutEEta.pop_back();
0431   cutEEta.pop_back();
0432   currentCut = cutEEta;
0433 
0434   // Filtered dataframes
0435   auto d_pim_cut = d_pim.Filter(currentCut.c_str());
0436   auto d_ele_cut = d_ele.Filter(currentCut.c_str());
0437 
0438   // Gathering benchmarks and plotting distrubutions
0439   std::vector<double> E                 = {5, 10, 18};
0440   std::vector<double> ledges5           = {2.8, 0.4, 0.3, 0.5};
0441   std::vector<double> ledges10          = {1.4, 0.5, 0.6, 1.0};
0442   std::vector<double> ledges18          = {0.9, 0.9, 1.0, 1.8};
0443   std::vector<double> maxRate5          = {0.1, 100, 500, 1000};
0444   std::vector<double> maxRate10         = {10, 400, 800, 1000};
0445   std::vector<double> maxRate18         = {200, 800, 1000, 100};
0446   std::vector<vector<double>> maxRate   = {maxRate5, maxRate10, maxRate18};
0447   std::vector<vector<double>> lowEdges  = {ledges5, ledges10, ledges18};
0448   double suppression                    = 1e-4;
0449   std::vector<vector<double>> rejRatios = lowEdges;
0450   std::vector<vector<double>> effEle    = lowEdges;
0451   std::vector<vector<double>> effPim    = lowEdges;
0452   std::vector<std::string> etaBin       = {"Eta >= -3.5 && Eta < -2.0", "Eta >= -2.0 && Eta < -1.0", "Eta >= -1.0 && Eta < 0", "Eta >= 0 && Eta < 1.0"};
0453   std::vector<std::string> etaTitle     = {"-3.5 < #eta < -2.0", "-2.0 < #eta < -1.0", "-1.0 < #eta < 0", "0 < #eta < 1.0"};
0454 
0455   // Pion Rejection Plot that mimics that of the one in the image
0456   std::vector<double> pBins  = {0.1,0.2,0.3,0.4,0.5,1,2,3,4,5,10,12,14,16,18};
0457   EBins = {{0,2}, {2, 4}, {4, 6}, {6, 9}, {9, 12}, {12, 19}};
0458   auto tg = new TGraphErrors();
0459 
0460   for (int i = 0; i < EBins.size(); i++){
0461     std::string filter = currentCut;
0462     filter += "&&(Pthr>=" + std::to_string(EBins[i][0]) + "&&Pthr<" + std::to_string(EBins[i][1]) + ")";
0463     double numer = (double)*d_ele_cut.Filter(filter.c_str()).Count();
0464     double denom = (double)*d_pim_cut.Filter(filter.c_str()).Count();
0465     double error = std::sqrt(std::pow(numer / denom, 2.0)*(1.0/numer + 1.0/denom));
0466     double ratio = numer / denom;
0467     if (denom == 0){ratio = 1; error = 1;}
0468     tg->SetPoint(i, 0.5*(EBins[i][0] + EBins[i][1]), ratio);
0469     tg->SetPointError(i, 0.5*(EBins[i][1] - EBins[i][0]), error);
0470   }
0471   double e_eff = (double)*d_ele_cut.Count() / (double)*d_ele.Count();
0472   tg->SetTitle(("#pi Rejection with #varepsilon_{e} = "+ std::to_string(e_eff)).c_str());
0473   tg->GetXaxis()->SetTitle("p [GeV]");
0474   tg->GetYaxis()->SetTitle("R_{e/#pi}");
0475   tg->SetMarkerColor(kBlue);
0476   tg->SetMarkerStyle(20);
0477 
0478   auto cp = new TCanvas("cp", "cp");
0479   cp->SetLogy();
0480   cp->SetLogx();
0481   tg->DrawClone("ap");
0482   cp->SaveAs("results/emcal_barrel_pion_rej_RatioRej.png");
0483 
0484   // Barrel eta cuts
0485   // The eta range for the barrel is -1 < eta < 1
0486   // Threfore the first bins are empty and will not be iterated over
0487   dep_min = 1;
0488   dep_max = 6;
0489   for (int i = 0; i < 3; i++){   // E loop
0490     for (int j = 2; j < 4; j++){ // Eta Looop
0491       
0492       // Apply eta cuts/binning and Momentum Cut
0493       std::string pCut = "Pthr>=" + std::to_string(lowEdges[i][j]) + "&&Pthr<" + std::to_string(E[i]);
0494       auto e_eta = d_ele.Filter(etaBin[j]).Filter(pCut);
0495       auto p_eta = d_pim.Filter(etaBin[j]).Filter(pCut);
0496       
0497       // Print out the momentum distributions for the electron and pi-
0498       std::string title = "e^{-} (E = " + std::to_string((int)E[i]) + " GeV) : " + etaTitle[j] + "; p [GeV]; Events";
0499       auto he = e_eta.Histo1D({"he", title.c_str(), 100, lowEdges[i][j], E[i]}, "Pthr");
0500       he->SetLineColor(kBlue);
0501       auto he_cut = e_eta.Filter(currentCut).Histo1D({"he_cut", title.c_str(), 100, lowEdges[i][j], E[i]}, "Pthr");
0502       he_cut->GetYaxis()->SetTitleOffset(1.4);
0503       he_cut->SetLineWidth(2);
0504       he_cut->SetLineColor(kRed);
0505 
0506       title = "#pi^{-} (E = " + std::to_string((int)E[i]) + " GeV) : " + etaTitle[j] + "; p [GeV]; Events";
0507       auto hp = p_eta.Histo1D({"hp", title.c_str(), 100, lowEdges[i][j], E[i]}, "Pthr");
0508       hp->SetLineColor(kBlue);
0509       auto hp_cut = p_eta.Filter(currentCut).Histo1D({"hp", title.c_str(), 100, lowEdges[i][j], E[i]}, "Pthr");
0510       hp_cut->GetYaxis()->SetTitleOffset(1.4);
0511       hp_cut->SetLineWidth(2);
0512       hp_cut->SetLineColor(kRed);
0513 
0514       auto c = new TCanvas("c", "c", 700, 500);
0515       c->SetLogy(1);
0516       he->DrawClone();
0517       he_cut->DrawClone("same");
0518       c->SaveAs((fmt::format("results/emcal_barrel_pion_rej_cut_mom_ele_E{}_eta{}.png", (int)E[i], j)).c_str());
0519       c->SaveAs((fmt::format("results/emcal_barrel_pion_rej_cut_mom_ele_E{}_eta{}.pdf", (int)E[i], j)).c_str());
0520       c->Clear();
0521 
0522       hp->DrawClone();
0523       hp_cut->DrawClone("same");
0524       c->SaveAs((fmt::format("results/emcal_barrel_pion_rej_cut_mom_pim_E{}_eta{}.png", (int)E[i], j)).c_str());
0525       c->SaveAs((fmt::format("results/emcal_barrel_pion_rej_cut_mom_pim_E{}_eta{}.pdf", (int)E[i], j)).c_str());
0526       c->Clear();
0527 
0528       // Gather ratio of pi/e and efficiencies for each Energy and eta bin
0529       // Then plot the distributions
0530       rejRatios[i][j] = (double)hp_cut->Integral() / (double)he_cut->Integral();
0531       effPim[i][j]    = (double)hp_cut->Integral() / (double)hp->Integral();
0532       effEle[i][j]    = (double)he_cut->Integral() / (double)he->Integral();
0533 
0534       hp_cut->Divide(he.GetPtr());
0535       title = "#pi^{-}/e^{-} (E = " + std::to_string((int)E[i]) + " GeV) : " + etaTitle[j];
0536       hp_cut->SetTitle(title.c_str());
0537       hp_cut->SetLineColor(kBlack);
0538       hp_cut->DrawClone();
0539       c->SaveAs((fmt::format("results/emcal_barrel_pion_rej_cut_ratio_pim_E{}_eta{}.png", (int)E[i], j)).c_str());
0540       c->SaveAs((fmt::format("results/emcal_barrel_pion_rej_cut_ratio_pim_E{}_eta{}.pdf", (int)E[i], j)).c_str());
0541       c->Clear();
0542       
0543       // Print out the 1D distributions for the electron and pi- within the current Eta bin
0544       std::vector<std::string> endStr           = {";pT [GeV]; Events", ";EDep6/p; Events"};
0545       std::vector<std::string> var_save_loc     = {"pT",                "EDep6OverP"};  
0546       std::vector<std::string> col_loc          = {"pT",                "EDep6OverP"};
0547       std::vector<std::vector<double>> h1Ranges = {{0, E[i]},           {0, 0.02}};
0548       for (int k = 0; k < 2; k++){
0549         auto cl = new TCanvas("cl", "cl", 700, 500);
0550         title = "e^{-} (E = " + std::to_string((int)E[i]) + " GeV) : " + etaTitle[j] + endStr[k];
0551         auto he1 = e_eta.Histo1D({"he", title.c_str(), 100, h1Ranges[k][0], h1Ranges[k][1]}, col_loc[k]);
0552         he1->SetLineColor(kBlue);
0553         auto he1_cut = e_eta.Filter(currentCut).Histo1D({"he_cut", title.c_str(), 100, h1Ranges[k][0], h1Ranges[k][1]}, col_loc[k]);
0554         he1_cut->GetYaxis()->SetTitleOffset(1.4);
0555         he1_cut->SetLineWidth(2);
0556         he1_cut->SetLineColor(kRed);
0557 
0558         title = "#pi^{-} (E = " + std::to_string((int)E[i]) + " GeV) : " + etaTitle[j] + endStr[k];
0559         auto hp1 = p_eta.Histo1D({"hp", title.c_str(), 100, h1Ranges[k][0], h1Ranges[k][1]}, col_loc[k]);
0560         hp1->SetLineColor(kBlue);
0561         auto hp1_cut = p_eta.Filter(currentCut).Histo1D({"hp_cut", title.c_str(), 100, h1Ranges[k][0], h1Ranges[k][1]}, col_loc[k]);
0562         hp1_cut->GetYaxis()->SetTitleOffset(1.4);
0563         hp1_cut->SetLineWidth(2);
0564         hp1_cut->SetLineColor(kRed);
0565 
0566         cl->SetLogy(1);
0567         he1->DrawClone();
0568         he1_cut->DrawClone("same");
0569         cl->SaveAs((fmt::format("results/emcal_barrel_pion_rej_cut_{}_ele_E{}_eta{}.png", col_loc[k], (int)E[i], j)).c_str());
0570         cl->SaveAs((fmt::format("results/emcal_barrel_pion_rej_cut_{}_ele_E{}_eta{}.pdf", col_loc[k], (int)E[i], j)).c_str());
0571         cl->Clear();
0572 
0573         hp1->DrawClone();
0574         hp1_cut->DrawClone("same");
0575         cl->SaveAs((fmt::format("results/emcal_barrel_pion_rej_cut_{}_pim_E{}_eta{}.png", col_loc[k], (int)E[i], j)).c_str());
0576         cl->SaveAs((fmt::format("results/emcal_barrel_pion_rej_cut_{}_pim_E{}_eta{}.pdf", col_loc[k], (int)E[i], j)).c_str());
0577         cl->Clear();
0578 
0579         // Combined plots
0580         title = "#pi^{-}, e^{-} (E = " + std::to_string((int)E[i]) + " GeV) : " + etaTitle[j] + endStr[k];
0581         hp1_cut->SetLineColor(kBlue);
0582         he1_cut->SetLineColor(kRed);
0583         he1_cut->SetTitle(title.c_str());
0584 
0585         auto leng = new TLegend(0.7, 0.7, 0.9, 0.9);
0586         he1_cut->DrawClone();
0587         hp1_cut->DrawClone("same");
0588         cl->Update();
0589 
0590         leng->AddEntry(he1_cut.GetPtr(),"e^{-}","l");
0591         leng->AddEntry(hp1_cut.GetPtr(),"#pi^{-}","l");
0592         leng->Draw();
0593         cl->SaveAs((fmt::format("results/emcal_barrel_pion_rej_cut_{}_comb_E{}_eta{}.png", col_loc[k], (int)E[i], j)).c_str());
0594         cl->SaveAs((fmt::format("results/emcal_barrel_pion_rej_cut_{}_comb_E{}_eta{}.pdf", col_loc[k], (int)E[i], j)).c_str());
0595 
0596       }// Generic 1d loop
0597     }// Eta Loop
0598   }// E loop
0599 
0600   // Writing out benchmarks
0601   //Tests
0602   std::string test_tag = "Barrel_emcal_pion_rejection";
0603   //TODO: Change test_tag to something else
0604   std:string detectorEle = "Barrel_emcal";
0605   
0606   for (int i = 0; i < etaTitle.size(); i++){
0607     etaTitle[i].erase(std::remove(etaTitle[i].begin(), etaTitle[i].end(), '#'), etaTitle[i].end());
0608     std::replace(etaTitle[i].begin(), etaTitle[i].end(), 'e', 'E');    
0609   }
0610   
0611   // E, Eta = 18, 2
0612   // Pion rejection analysis complete - results stored in rejection ratios and efficiencies
0613   std::cout << fmt::format("Pion rejection E={}, Eta=2: rejection ratio = {}\n", (int)E[0], rejRatios[0][2]);
0614   std::cout << fmt::format("Pion rejection E={}, Eta=3: rejection ratio = {}\n", (int)E[0], rejRatios[0][3]);
0615   std::cout << fmt::format("Pion rejection E={}, Eta=2: rejection ratio = {}\n", (int)E[1], rejRatios[1][2]);
0616   std::cout << fmt::format("Pion rejection E={}, Eta=3: rejection ratio = {}\n", (int)E[1], rejRatios[1][3]);
0617   std::cout << fmt::format("Pion rejection E={}, Eta=2: rejection ratio = {}\n", (int)E[2], rejRatios[2][2]);
0618   std::cout << fmt::format("Pion rejection E={}, Eta=3: rejection ratio = {}\n", (int)E[2], rejRatios[2][3]);
0619 }