File indexing completed on 2025-07-01 07:56:15
0001
0002
0003
0004 #include "CherenkovPIDAnalysis.h"
0005
0006 namespace benchmarks {
0007
0008
0009
0010 void CherenkovPIDAnalysis::AlgorithmInit(
0011 std::string rad_name,
0012 std::shared_ptr<spdlog::logger>& logger
0013 )
0014 {
0015 m_rad_name = rad_name;
0016 m_log = logger;
0017
0018
0019 m_rad_title = TString(m_rad_name);
0020 if(m_rad_name=="Merged") m_rad_title += " Aerogel+Gas";
0021
0022
0023 m_rad_name_trun = TString(m_rad_name);
0024 m_rad_name_trun(TRegexp(" .*")) = "";
0025
0026
0027 m_npe_dist = new TH1D(
0028 "npe_dist_"+m_rad_name_trun,
0029 "Overall NPE for "+m_rad_title+";NPE",
0030 Tools::npe_max, 0, Tools::npe_max
0031 );
0032 m_theta_dist = new TH1D(
0033 "theta_dist_"+m_rad_name_trun,
0034 "Estimated Cherenkov Angle for "+m_rad_title+";#theta [mrad]",
0035 Tools::theta_bins, 0, Tools::theta_max
0036 );
0037 m_thetaResid_dist = new TH1D(
0038 "thetaResid_dist_"+m_rad_name_trun,
0039 "Estimated Cherenkov Angle Residual for "+m_rad_title+";#Delta#theta [mrad]",
0040 Tools::theta_bins, -Tools::thetaResid_max, Tools::thetaResid_max
0041 );
0042 m_photonTheta_vs_photonPhi = new TH2D(
0043 "photonTheta_vs_photonPhi_"+m_rad_name_trun,
0044 "Estimated Photon #theta vs #phi for "+m_rad_title+";#phi [rad];#theta [mrad]",
0045 Tools::phi_bins, -TMath::Pi(), TMath::Pi(),
0046 Tools::theta_bins, 0, Tools::theta_max
0047 );
0048
0049
0050 m_mcWavelength_dist = new TH1D(
0051 "mcWavelength_"+m_rad_name_trun,
0052 "MC Photon Wavelength for "+m_rad_title+";#lambda [nm]",
0053 Tools::n_bins, 0, 1000
0054 );
0055 m_mcRindex_dist = new TH1D(
0056 "mcRindex_"+m_rad_name_trun,
0057 "MC Refractive Index for "+m_rad_title+";n",
0058 10*Tools::n_bins, 0.99, 1.03
0059 );
0060
0061
0062 m_highestWeight_dist = new TH1D(
0063 "highestWeight_dist_"+m_rad_name_trun,
0064 "Highest PDG Weight for "+m_rad_title+";PDG",
0065 Tools::GetNumPDGs()+1, 0, Tools::GetNumPDGs()+1
0066 );
0067
0068
0069 m_npe_vs_p = new TH2D(
0070 "npe_vs_p_"+m_rad_name_trun,
0071 "Overall NPE vs. Particle Momentum for "+m_rad_title+";p [GeV];NPE",
0072 Tools::momentum_bins, 0, Tools::momentum_max,
0073 Tools::npe_max, 0, Tools::npe_max
0074 );
0075 m_theta_vs_p = new TH2D(
0076 "theta_vs_p_"+m_rad_name_trun,
0077 "Estimated Cherenkov Angle vs. Particle Momentum for "+m_rad_title+";p [GeV];#theta [mrad]",
0078 Tools::momentum_bins, 0, Tools::momentum_max,
0079 Tools::theta_bins, 0, Tools::theta_max
0080 );
0081 m_thetaResid_vs_p = new TH2D(
0082 "thetaResid_vs_p_"+m_rad_name_trun,
0083 "Estimated Cherenkov Angle Residual vs. Particle Momentum for "+m_rad_title+";p [GeV];#Delta#theta [mrad]",
0084 Tools::momentum_bins, 0, Tools::momentum_max,
0085 Tools::theta_bins, -Tools::thetaResid_max, Tools::thetaResid_max
0086 );
0087 m_highestWeight_vs_p = new TH2D(
0088 "highestWeight_vs_p_"+m_rad_name_trun,
0089 "Highest PDG Weight vs. Particle Momentum for "+m_rad_title+";p [GeV]",
0090 Tools::momentum_bins, 0, Tools::momentum_max,
0091 Tools::GetNumPDGs()+1, 0, Tools::GetNumPDGs()+1
0092 );
0093
0094
0095 m_npe_vs_eta = new TH2D(
0096 "npe_vs_eta_"+m_rad_name_trun,
0097 "Overall NPE vs. Pseudorapidity for "+m_rad_title+";#eta;NPE",
0098 Tools::eta_bins, Tools::eta_min, Tools::eta_max,
0099 Tools::npe_max, 0, Tools::npe_max
0100 );
0101 m_theta_vs_eta = new TH2D(
0102 "theta_vs_eta_"+m_rad_name_trun,
0103 "Estimated Cherenkov Angle vs. Pseudorapidity for "+m_rad_title+";#eta;#theta [mrad]",
0104 Tools::eta_bins, Tools::eta_min, Tools::eta_max,
0105 Tools::theta_bins, 0, Tools::theta_max
0106 );
0107 m_thetaResid_vs_eta = new TH2D(
0108 "thetaResid_vs_eta_"+m_rad_name_trun,
0109 "Estimated Cherenkov Angle Residual vs. Pseudorapidity for "+m_rad_title+";#eta;#Delta#theta [mrad]",
0110 Tools::eta_bins, Tools::eta_min, Tools::eta_max,
0111 Tools::theta_bins, -Tools::thetaResid_max, Tools::thetaResid_max
0112 );
0113 m_highestWeight_vs_eta = new TH2D(
0114 "highestWeight_vs_eta_"+m_rad_name_trun,
0115 "Highest PDG Weight vs. Pseudorapidity for "+m_rad_title+";#eta",
0116 Tools::eta_bins, Tools::eta_min, Tools::eta_max,
0117 Tools::GetNumPDGs()+1, 0, Tools::GetNumPDGs()+1
0118 );
0119
0120
0121 auto format1D = [] (auto h) {
0122 h->SetLineColor(kAzure);
0123 h->SetFillColor(kAzure);
0124 };
0125 format1D(m_npe_dist);
0126 format1D(m_theta_dist);
0127 format1D(m_thetaResid_dist);
0128 format1D(m_mcWavelength_dist);
0129 format1D(m_mcRindex_dist);
0130 format1D(m_highestWeight_dist);
0131 }
0132
0133
0134
0135
0136 void CherenkovPIDAnalysis::AlgorithmProcess(
0137 const edm4hep::MCParticleCollection& mc_parts,
0138 const edm4eic::CherenkovParticleIDCollection& cherenkov_pids
0139 )
0140 {
0141 m_log->trace("-> {} Radiator:", m_rad_name);
0142
0143
0144 auto part = std::make_unique<ChargedParticle>(m_log);
0145 part->SetSingleParticle(mc_parts);
0146 auto thrown_momentum = part->GetMomentum();
0147 auto thrown_eta = part->GetEta();
0148 auto thrown_pdg = part->GetPDG();
0149
0150
0151 for(const auto& cherenkov_pid : cherenkov_pids) {
0152
0153
0154 if(cherenkov_pid.getNpe() == 0) {
0155 m_log->warn("Event found with NPE=0");
0156 continue;
0157 }
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168
0169 auto charged_particle_momentum = thrown_momentum;
0170 auto charged_particle_eta = thrown_eta;
0171 auto charged_particle_pdg = thrown_pdg;
0172 auto charged_particle_mass = Tools::GetPDGMass(charged_particle_pdg);
0173 m_log->trace(" Charged Particle PDG={}, mass={} GeV, p={} GeV from truth",
0174 charged_particle_pdg, charged_particle_mass, charged_particle_momentum);
0175
0176
0177 double theta_rec = 0.0;
0178 for(const auto& [theta,phi] : cherenkov_pid.getThetaPhiPhotons())
0179 theta_rec += theta;
0180 theta_rec /= cherenkov_pid.getNpe();
0181 auto theta_rec_mrad = theta_rec * 1e3;
0182
0183
0184
0185 auto mc_rindex = cherenkov_pid.getRefractiveIndex();
0186 auto theta_exp = TMath::ACos(
0187 TMath::Hypot( charged_particle_momentum, charged_particle_mass ) /
0188 ( mc_rindex * charged_particle_momentum )
0189 );
0190 auto theta_resid = theta_rec - theta_exp;
0191 auto theta_resid_mrad = theta_resid * 1e3;
0192
0193
0194 m_npe_dist->Fill( cherenkov_pid.getNpe());
0195 m_npe_vs_p->Fill( charged_particle_momentum, cherenkov_pid.getNpe());
0196 m_npe_vs_eta->Fill( charged_particle_eta, cherenkov_pid.getNpe());
0197 m_theta_dist->Fill( theta_rec_mrad);
0198 m_theta_vs_p->Fill( charged_particle_momentum, theta_rec_mrad);
0199 m_theta_vs_eta->Fill( charged_particle_eta, theta_rec_mrad);
0200 m_thetaResid_dist->Fill( theta_resid_mrad);
0201 m_thetaResid_vs_p->Fill( charged_particle_momentum, theta_resid_mrad);
0202 m_thetaResid_vs_eta->Fill( charged_particle_eta, theta_resid_mrad);
0203 for(const auto& [theta,phi] : cherenkov_pid.getThetaPhiPhotons())
0204 m_photonTheta_vs_photonPhi->Fill( phi, theta*1e3);
0205 m_mcWavelength_dist->Fill( Tools::HC / cherenkov_pid.getPhotonEnergy() );
0206 m_mcRindex_dist->Fill( mc_rindex);
0207
0208
0209 float max_weight = -1000;
0210 int pdg_max_weight = 0;
0211 for(const auto& hyp : cherenkov_pid.getHypotheses()) {
0212 if(hyp.weight > max_weight) {
0213 max_weight = hyp.weight;
0214 pdg_max_weight = hyp.PDG;
0215 }
0216 }
0217 std::string pdg_max_weight_str = "UNKNOWN";
0218 if(pdg_max_weight!=0 && !std::isnan(pdg_max_weight))
0219 pdg_max_weight_str = std::to_string(pdg_max_weight);
0220 m_log->trace(" Highest weight is {} for PDG {} (string='{}')", max_weight, pdg_max_weight, pdg_max_weight_str);
0221 m_highestWeight_dist->Fill( pdg_max_weight_str.c_str(), 1);
0222 m_highestWeight_vs_p->Fill( charged_particle_momentum, pdg_max_weight_str.c_str(), 1);
0223 m_highestWeight_vs_eta->Fill( charged_particle_eta, pdg_max_weight_str.c_str(), 1);
0224
0225 }
0226 }
0227
0228
0229
0230
0231 void CherenkovPIDAnalysis::AlgorithmFinish() {
0232 }
0233
0234 }