Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2025-04-30 22:24:44

0001 #include <numeric>
0002 #include <iomanip>
0003 #include <sstream>
0004 
0005 #include "Validation/HGCalValidation/interface/TICLCandidateValidator.h"
0006 #include "DataFormats/HGCalReco/interface/Common.h"
0007 
0008 TICLCandidateValidator::TICLCandidateValidator(edm::EDGetTokenT<std::vector<TICLCandidate>> ticlCandidates,
0009                                                edm::EDGetTokenT<std::vector<TICLCandidate>> simTICLCandidatesToken,
0010                                                edm::EDGetTokenT<std::vector<reco::Track>> recoTracksToken,
0011                                                edm::EDGetTokenT<std::vector<ticl::Trackster>> trackstersToken,
0012                                                edm::EDGetTokenT<ticl::TracksterToTracksterMap> associatorMapRtSToken,
0013                                                edm::EDGetTokenT<ticl::TracksterToTracksterMap> associatorMapStRToken,
0014                                                bool isTICLv5)
0015     : TICLCandidatesToken_(ticlCandidates),
0016       simTICLCandidatesToken_(simTICLCandidatesToken),
0017       recoTracksToken_(recoTracksToken),
0018       trackstersToken_(trackstersToken),
0019       associatorMapRtSToken_(associatorMapRtSToken),
0020       associatorMapStRToken_(associatorMapStRToken),
0021       isTICLv5_(isTICLv5) {}
0022 
0023 TICLCandidateValidator::~TICLCandidateValidator() {}
0024 
0025 void TICLCandidateValidator::bookCandidatesHistos(DQMStore::IBooker& ibook,
0026                                                   Histograms& histograms,
0027                                                   std::string baseDir) const {
0028   // book CAND histos
0029   histograms.h_tracksters_in_candidate =
0030       ibook.book1D("N of tracksters in candidate", "N of tracksters in candidate", 100, 0, 99);
0031   histograms.h_candidate_raw_energy =
0032       ibook.book1D("Candidates raw energy", "Candidates raw energy;E (GeV)", 250, 0, 250);
0033   histograms.h_candidate_regressed_energy =
0034       ibook.book1D("Candidates regressed energy", "Candidates regressed energy;E (GeV)", 250, 0, 250);
0035   histograms.h_candidate_pT = ibook.book1D("Candidates pT", "Candidates pT;p_{T}", 250, 0, 250);
0036   histograms.h_candidate_charge = ibook.book1D("Candidates charge", "Candidates charge;Charge", 3, -1.5, 1.5);
0037   histograms.h_candidate_pdgId = ibook.book1D("Candidates PDG Id", "Candidates PDG ID", 100, -220, 220);
0038   histograms.h_candidate_partType = ibook.book1D("Candidates type", "Candidates type", 9, -0.5, 8.5);
0039 
0040   // neutral: photon, pion, hadron
0041   const std::vector<std::string> neutrals{"photons", "neutral_pions", "neutral_hadrons"};
0042   for (long unsigned int i = 0; i < neutrals.size(); i++) {
0043     ibook.setCurrentFolder(baseDir + "/" + neutrals[i]);
0044 
0045     histograms.h_neut_tracksters_in_candidate.push_back(ibook.book1D("N of tracksters in candidate for " + neutrals[i],
0046                                                                      "N of tracksters in candidate for " + neutrals[i],
0047                                                                      100,
0048                                                                      0,
0049                                                                      99));
0050     histograms.h_neut_candidate_regressed_energy.push_back(ibook.book1D(
0051         neutrals[i] + "candidates regressed energy", neutrals[i] + " candidates regressed energy;E (GeV)", 250, 0, 250));
0052     histograms.h_neut_candidate_charge.push_back(
0053         ibook.book1D(neutrals[i] + " candidates charge", neutrals[i] + " candidates charge;Charge", 3, -1.5, 1.5));
0054     histograms.h_neut_candidate_pdgId.push_back(
0055         ibook.book1D(neutrals[i] + " candidates PDG Id", neutrals[i] + " candidates PDG ID", 100, -220, 220));
0056     histograms.h_neut_candidate_partType.push_back(
0057         ibook.book1D(neutrals[i] + " candidates type", neutrals[i] + " candidates type", 9, -0.5, 8.5));
0058 
0059     histograms.h_den_fake_neut_energy_candidate.push_back(
0060         ibook.book1D("den_fake_cand_vs_energy_" + neutrals[i], neutrals[i] + " candidates energy;E (GeV)", 50, 0, 250));
0061     histograms.h_num_fake_neut_energy_candidate_pdgId.push_back(ibook.book1D(
0062         "num_fake_pid_cand_vs_energy_" + neutrals[i], neutrals[i] + " PID fake vs energy;E (GeV)", 50, 0, 250));
0063     histograms.h_num_fake_neut_energy_candidate_energy.push_back(
0064         ibook.book1D("num_fake_energy_cand_vs_energy_" + neutrals[i],
0065                      neutrals[i] + " PID and energy fake vs energy;E (GeV)",
0066                      50,
0067                      0,
0068                      250));
0069     histograms.h_den_fake_neut_pt_candidate.push_back(
0070         ibook.book1D("den_fake_cand_vs_pt_" + neutrals[i], neutrals[i] + " candidates pT;p_{T} (GeV)", 50, 0, 250));
0071     histograms.h_num_fake_neut_pt_candidate_pdgId.push_back(ibook.book1D(
0072         "num_fake_pid_cand_vs_pt_" + neutrals[i], neutrals[i] + " PID fake vs pT;p_{T} (GeV)", 50, 0, 250));
0073     histograms.h_num_fake_neut_pt_candidate_energy.push_back(
0074         ibook.book1D("num_fake_energy_cand_vs_pt_" + neutrals[i],
0075                      neutrals[i] + " PID and energy fake vs pT;p_{T} (GeV)",
0076                      50,
0077                      0,
0078                      250));
0079     histograms.h_den_fake_neut_eta_candidate.push_back(
0080         ibook.book1D("den_fake_cand_vs_eta_" + neutrals[i], neutrals[i] + " candidates eta;#eta (GeV)", 50, -3, 3));
0081     histograms.h_num_fake_neut_eta_candidate_pdgId.push_back(ibook.book1D(
0082         "num_fake_pid_cand_vs_eta_" + neutrals[i], neutrals[i] + " PID fake vs eta;#eta (GeV)", 50, -3, 3));
0083     histograms.h_num_fake_neut_eta_candidate_energy.push_back(
0084         ibook.book1D("num_fake_energy_cand_vs_eta_" + neutrals[i],
0085                      neutrals[i] + " PID and energy fake vs eta;#eta (GeV)",
0086                      50,
0087                      -3,
0088                      3));
0089     histograms.h_den_fake_neut_phi_candidate.push_back(ibook.book1D(
0090         "den_fake_cand_vs_phi_" + neutrals[i], neutrals[i] + " candidates phi;#phi (GeV)", 50, -3.14159, 3.14159));
0091     histograms.h_num_fake_neut_phi_candidate_pdgId.push_back(ibook.book1D(
0092         "num_fake_pid_cand_vs_phi_" + neutrals[i], neutrals[i] + " PID fake vs phi;#phi (GeV)", 50, -3.14159, 3.14159));
0093     histograms.h_num_fake_neut_phi_candidate_energy.push_back(
0094         ibook.book1D("num_fake_energy_cand_vs_phi_" + neutrals[i],
0095                      neutrals[i] + " PID and energy fake vs phi;#phi (GeV)",
0096                      50,
0097                      -3.14159,
0098                      3.14159));
0099 
0100     histograms.h_den_neut_energy_candidate.push_back(
0101         ibook.book1D("den_cand_vs_energy_" + neutrals[i], neutrals[i] + " simCandidates energy;E (GeV)", 50, 0, 250));
0102     histograms.h_num_neut_energy_candidate_pdgId.push_back(
0103         ibook.book1D("num_pid_cand_vs_energy_" + neutrals[i],
0104                      neutrals[i] + " track and PID efficiency vs energy;E (GeV)",
0105                      50,
0106                      0,
0107                      250));
0108     histograms.h_num_neut_energy_candidate_energy.push_back(
0109         ibook.book1D("num_energy_cand_vs_energy_" + neutrals[i],
0110                      neutrals[i] + " track, PID and energy efficiency vs energy;E (GeV)",
0111                      50,
0112                      0,
0113                      250));
0114     histograms.h_den_neut_pt_candidate.push_back(
0115         ibook.book1D("den_cand_vs_pt_" + neutrals[i], neutrals[i] + " simCandidates pT;p_{T} (GeV)", 50, 0, 250));
0116     histograms.h_num_neut_pt_candidate_pdgId.push_back(ibook.book1D(
0117         "num_pid_cand_vs_pt_" + neutrals[i], neutrals[i] + " track and PID efficiency vs pT;p_{T} (GeV)", 50, 0, 250));
0118     histograms.h_num_neut_pt_candidate_energy.push_back(
0119         ibook.book1D("num_energy_cand_vs_pt_" + neutrals[i],
0120                      neutrals[i] + " track, PID and energy efficiency vs pT;p_{T} (GeV)",
0121                      50,
0122                      0,
0123                      250));
0124     histograms.h_den_neut_eta_candidate.push_back(
0125         ibook.book1D("den_cand_vs_eta_" + neutrals[i], neutrals[i] + " simCandidates eta;#eta (GeV)", 50, -3, 3));
0126     histograms.h_num_neut_eta_candidate_pdgId.push_back(ibook.book1D(
0127         "num_pid_cand_vs_eta_" + neutrals[i], neutrals[i] + " track and PID efficiency vs eta;#eta (GeV)", 50, -3, 3));
0128     histograms.h_num_neut_eta_candidate_energy.push_back(
0129         ibook.book1D("num_energy_cand_vs_eta_" + neutrals[i],
0130                      neutrals[i] + " track, PID and energy efficiency vs eta;#eta (GeV)",
0131                      50,
0132                      -3,
0133                      3));
0134     histograms.h_den_neut_phi_candidate.push_back(ibook.book1D(
0135         "den_cand_vs_phi_" + neutrals[i], neutrals[i] + " simCandidates phi;#phi (GeV)", 50, -3.14159, 3.14159));
0136     histograms.h_num_neut_phi_candidate_pdgId.push_back(
0137         ibook.book1D("num_pid_cand_vs_phi_" + neutrals[i],
0138                      neutrals[i] + " track and PID efficiency vs phi;#phi (GeV)",
0139                      50,
0140                      -3.14159,
0141                      3.14159));
0142     histograms.h_num_neut_phi_candidate_energy.push_back(
0143         ibook.book1D("num_energy_cand_vs_phi_" + neutrals[i],
0144                      neutrals[i] + " track, PID and energy efficiency vs phi;#phi (GeV)",
0145                      50,
0146                      -3.14159,
0147                      3.14159));
0148   }
0149   // charged: electron, muon, hadron
0150   const std::vector<std::string> charged{"electrons", "muons", "charged_hadrons"};
0151   for (long unsigned int i = 0; i < charged.size(); i++) {
0152     ibook.setCurrentFolder(baseDir + "/" + charged[i]);
0153 
0154     histograms.h_chg_tracksters_in_candidate.push_back(ibook.book1D(
0155         "N of tracksters in candidate for " + charged[i], "N of tracksters in candidate for " + charged[i], 100, 0, 99));
0156     histograms.h_chg_candidate_regressed_energy.push_back(ibook.book1D(
0157         charged[i] + "candidates regressed energy", charged[i] + " candidates regressed energy;E (GeV)", 250, 0, 250));
0158     histograms.h_chg_candidate_charge.push_back(
0159         ibook.book1D(charged[i] + " candidates charge", charged[i] + " candidates charge;Charge", 3, -1.5, 1.5));
0160     histograms.h_chg_candidate_pdgId.push_back(
0161         ibook.book1D(charged[i] + " candidates PDG Id", charged[i] + " candidates PDG ID", 100, -220, 220));
0162     histograms.h_chg_candidate_partType.push_back(
0163         ibook.book1D(charged[i] + " candidates type", charged[i] + " candidates type", 9, -0.5, 8.5));
0164 
0165     histograms.h_den_fake_chg_energy_candidate.push_back(
0166         ibook.book1D("den_fake_cand_vs_energy_" + charged[i], charged[i] + " candidates energy;E (GeV)", 50, 0, 250));
0167     histograms.h_num_fake_chg_energy_candidate_track.push_back(ibook.book1D(
0168         "num_fake_track_cand_vs_energy_" + charged[i], charged[i] + " track fake vs energy;E (GeV)", 50, 0, 250));
0169     histograms.h_num_fake_chg_energy_candidate_pdgId.push_back(ibook.book1D(
0170         "num_fake_pid_cand_vs_energy_" + charged[i], charged[i] + " track and PID fake vs energy;E (GeV)", 50, 0, 250));
0171     histograms.h_num_fake_chg_energy_candidate_energy.push_back(
0172         ibook.book1D("num_fake_energy_cand_vs_energy_" + charged[i],
0173                      charged[i] + " track, PID and energy fake vs energy;E (GeV)",
0174                      50,
0175                      0,
0176                      250));
0177     histograms.h_den_fake_chg_pt_candidate.push_back(
0178         ibook.book1D("den_fake_cand_vs_pt_" + charged[i], charged[i] + " candidates pT;p_{T} (GeV)", 50, 0, 250));
0179     histograms.h_num_fake_chg_pt_candidate_track.push_back(ibook.book1D(
0180         "num_fake_track_cand_vs_pt_" + charged[i], charged[i] + " track fake vs pT;p_{T} (GeV)", 50, 0, 250));
0181     histograms.h_num_fake_chg_pt_candidate_pdgId.push_back(ibook.book1D(
0182         "num_fake_pid_cand_vs_pt_" + charged[i], charged[i] + " track and PID fake vs pT;p_{T} (GeV)", 50, 0, 250));
0183     histograms.h_num_fake_chg_pt_candidate_energy.push_back(
0184         ibook.book1D("num_fake_energy_cand_vs_pt_" + charged[i],
0185                      charged[i] + " track, PID and energy fake vs pT;p_{T} (GeV)",
0186                      50,
0187                      0,
0188                      250));
0189     histograms.h_den_fake_chg_eta_candidate.push_back(
0190         ibook.book1D("den_fake_cand_vs_eta_" + charged[i], charged[i] + " candidates eta;#eta (GeV)", 50, -3, 3));
0191     histograms.h_num_fake_chg_eta_candidate_track.push_back(ibook.book1D(
0192         "num_fake_track_cand_vs_eta_" + charged[i], charged[i] + " track fake vs eta;#eta (GeV)", 50, -3, 3));
0193     histograms.h_num_fake_chg_eta_candidate_pdgId.push_back(ibook.book1D(
0194         "num_fake_pid_cand_vs_eta_" + charged[i], charged[i] + " track and PID fake vs eta;#eta (GeV)", 50, -3, 3));
0195     histograms.h_num_fake_chg_eta_candidate_energy.push_back(
0196         ibook.book1D("num_fake_energy_cand_vs_eta_" + charged[i],
0197                      charged[i] + " track, PID and energy fake vs eta;#eta (GeV)",
0198                      50,
0199                      -3,
0200                      3));
0201     histograms.h_den_fake_chg_phi_candidate.push_back(ibook.book1D(
0202         "den_fake_cand_vs_phi_" + charged[i], charged[i] + " candidates phi;#phi (GeV)", 50, -3.14159, 3.14159));
0203     histograms.h_num_fake_chg_phi_candidate_track.push_back(ibook.book1D("num_fake_track_cand_vs_phi_" + charged[i],
0204                                                                          charged[i] + " track fake vs phi;#phi (GeV)",
0205                                                                          50,
0206                                                                          -3.14159,
0207                                                                          3.14159));
0208     histograms.h_num_fake_chg_phi_candidate_pdgId.push_back(
0209         ibook.book1D("num_fake_pid_cand_vs_phi_" + charged[i],
0210                      charged[i] + " track and PID fake vs phi;#phi (GeV)",
0211                      50,
0212                      -3.14159,
0213                      3.14159));
0214     histograms.h_num_fake_chg_phi_candidate_energy.push_back(
0215         ibook.book1D("num_fake_energy_cand_vs_phi_" + charged[i],
0216                      charged[i] + " track, PID and energy fake vs phi;#phi (GeV)",
0217                      50,
0218                      -3.14159,
0219                      3.14159));
0220 
0221     histograms.h_den_chg_energy_candidate.push_back(
0222         ibook.book1D("den_cand_vs_energy_" + charged[i], charged[i] + " simCandidates energy;E (GeV)", 50, 0, 250));
0223     histograms.h_num_chg_energy_candidate_track.push_back(ibook.book1D(
0224         "num_track_cand_vs_energy_" + charged[i], charged[i] + " track efficiency vs energy;E (GeV)", 50, 0, 250));
0225     histograms.h_num_chg_energy_candidate_pdgId.push_back(ibook.book1D(
0226         "num_pid_cand_vs_energy_" + charged[i], charged[i] + " track and PID efficiency vs energy;E (GeV)", 50, 0, 250));
0227     histograms.h_num_chg_energy_candidate_energy.push_back(
0228         ibook.book1D("num_energy_cand_vs_energy_" + charged[i],
0229                      charged[i] + " track, PID and energy efficiency vs energy;E (GeV)",
0230                      50,
0231                      0,
0232                      250));
0233     histograms.h_den_chg_pt_candidate.push_back(
0234         ibook.book1D("den_cand_vs_pt_" + charged[i], charged[i] + " simCandidates pT;p_{T} (GeV)", 50, 0, 250));
0235     histograms.h_num_chg_pt_candidate_track.push_back(ibook.book1D(
0236         "num_track_cand_vs_pt_" + charged[i], charged[i] + " track efficiency vs pT;p_{T} (GeV)", 50, 0, 250));
0237     histograms.h_num_chg_pt_candidate_pdgId.push_back(ibook.book1D(
0238         "num_pid_cand_vs_pt_" + charged[i], charged[i] + " track and PID efficiency vs pT;p_{T} (GeV)", 50, 0, 250));
0239     histograms.h_num_chg_pt_candidate_energy.push_back(
0240         ibook.book1D("num_energy_cand_vs_pt_" + charged[i],
0241                      charged[i] + " track, PID and energy efficiency vs pT;p_{T} (GeV)",
0242                      50,
0243                      0,
0244                      250));
0245     histograms.h_den_chg_eta_candidate.push_back(
0246         ibook.book1D("den_cand_vs_eta_" + charged[i], charged[i] + " simCandidates eta;#eta (GeV)", 50, -3, 3));
0247     histograms.h_num_chg_eta_candidate_track.push_back(ibook.book1D(
0248         "num_track_cand_vs_eta_" + charged[i], charged[i] + " track efficiency vs eta;#eta (GeV)", 50, -3, 3));
0249     histograms.h_num_chg_eta_candidate_pdgId.push_back(ibook.book1D(
0250         "num_pid_cand_vs_eta_" + charged[i], charged[i] + " track and PID efficiency vs eta;#eta (GeV)", 50, -3, 3));
0251     histograms.h_num_chg_eta_candidate_energy.push_back(
0252         ibook.book1D("num_energy_cand_vs_eta_" + charged[i],
0253                      charged[i] + " track, PID and energy efficiency vs eta;#eta (GeV)",
0254                      50,
0255                      -3,
0256                      3));
0257     histograms.h_den_chg_phi_candidate.push_back(ibook.book1D(
0258         "den_cand_vs_phi_" + charged[i], charged[i] + " simCandidates phi;#phi (GeV)", 50, -3.14159, 3.14159));
0259     histograms.h_num_chg_phi_candidate_track.push_back(ibook.book1D("num_track_cand_vs_phi_" + charged[i],
0260                                                                     charged[i] + " track efficiency vs phi;#phi (GeV)",
0261                                                                     50,
0262                                                                     -3.14159,
0263                                                                     3.14159));
0264     histograms.h_num_chg_phi_candidate_pdgId.push_back(
0265         ibook.book1D("num_pid_cand_vs_phi_" + charged[i],
0266                      charged[i] + " track and PID efficiency vs phi;#phi (GeV)",
0267                      50,
0268                      -3.14159,
0269                      3.14159));
0270     histograms.h_num_chg_phi_candidate_energy.push_back(
0271         ibook.book1D("num_energy_cand_vs_phi_" + charged[i],
0272                      charged[i] + " track, PID and energy efficiency vs phi;#phi (GeV)",
0273                      50,
0274                      -3.14159,
0275                      3.14159));
0276   }
0277 }
0278 
0279 void TICLCandidateValidator::fillCandidateHistos(const edm::Event& event,
0280                                                  const Histograms& histograms,
0281                                                  edm::Handle<ticl::TracksterCollection> simTrackstersCP_h) const {
0282   auto TICLCandidatesHandle = event.getHandle(TICLCandidatesToken_);
0283   if (!TICLCandidatesHandle.isValid()) {
0284     edm::LogError("TICLCandidatesError") << "Failed to retrieve TICL candidates.";
0285     return;  // Handle error appropriately
0286   }
0287 
0288   auto TICLCandidates = *TICLCandidatesHandle;
0289 
0290   edm::Handle<std::vector<TICLCandidate>> simTICLCandidates_h;
0291   event.getByToken(simTICLCandidatesToken_, simTICLCandidates_h);
0292   auto simTICLCandidates = *simTICLCandidates_h;
0293 
0294   edm::Handle<std::vector<reco::Track>> recoTracks_h;
0295   event.getByToken(recoTracksToken_, recoTracks_h);
0296   auto recoTracks = *recoTracks_h;
0297 
0298   edm::Handle<std::vector<ticl::Trackster>> Tracksters_h;
0299   event.getByToken(trackstersToken_, Tracksters_h);
0300   auto trackstersMerged = *Tracksters_h;
0301 
0302   edm::Handle<ticl::TracksterToTracksterMap> mergeTsRecoToSim_h;
0303   event.getByToken(associatorMapRtSToken_, mergeTsRecoToSim_h);
0304   auto const& mergeTsRecoToSimMap = *mergeTsRecoToSim_h;
0305 
0306   edm::Handle<ticl::TracksterToTracksterMap> mergeTsSimToReco_h;
0307   event.getByToken(associatorMapStRToken_, mergeTsSimToReco_h);
0308   auto const& mergeTsSimToRecoMap = *mergeTsSimToReco_h;
0309 
0310   // candidates plots
0311   for (const auto& cand : TICLCandidates) {
0312     histograms.h_tracksters_in_candidate->Fill(cand.tracksters().size());
0313     histograms.h_candidate_raw_energy->Fill(cand.rawEnergy());
0314     histograms.h_candidate_regressed_energy->Fill(cand.energy());
0315     histograms.h_candidate_pT->Fill(cand.pt());
0316     histograms.h_candidate_charge->Fill(cand.charge());
0317     histograms.h_candidate_pdgId->Fill(cand.pdgId());
0318     const auto& arr = cand.idProbabilities();
0319     histograms.h_candidate_partType->Fill(std::max_element(arr.begin(), arr.end()) - arr.begin());
0320   }
0321 
0322   std::vector<int> chargedCandidates;
0323   std::vector<int> neutralCandidates;
0324   chargedCandidates.reserve(simTICLCandidates.size());
0325   neutralCandidates.reserve(simTICLCandidates.size());
0326 
0327   for (size_t i = 0; i < simTICLCandidates.size(); ++i) {
0328     const auto& simCand = simTICLCandidates[i];
0329     const auto particleType = ticl::tracksterParticleTypeFromPdgId(simCand.pdgId(), simCand.charge());
0330     if (particleType == ticl::Trackster::ParticleType::electron or
0331         particleType == ticl::Trackster::ParticleType::muon or
0332         particleType == ticl::Trackster::ParticleType::charged_hadron)
0333       chargedCandidates.emplace_back(i);
0334     else if (particleType == ticl::Trackster::ParticleType::photon or
0335              particleType == ticl::Trackster::ParticleType::neutral_pion or
0336              particleType == ticl::Trackster::ParticleType::neutral_hadron)
0337       neutralCandidates.emplace_back(i);
0338     // should consider also unknown ?
0339   }
0340 
0341   chargedCandidates.shrink_to_fit();
0342   neutralCandidates.shrink_to_fit();
0343 
0344   for (const auto i : chargedCandidates) {
0345     const auto& simCand = simTICLCandidates[i];
0346     auto index = std::log2(int(ticl::tracksterParticleTypeFromPdgId(simCand.pdgId(), 1)));
0347     /* 11 (type 1) becomes 0
0348      * 13 (type 2) becomes 1
0349      * 211 (type 4) becomes 2
0350      */
0351     int32_t simCandTrackIdx = -1;
0352     if (simCand.trackPtr().get() != nullptr)
0353       simCandTrackIdx = simCand.trackPtr().get() - edm::Ptr<reco::Track>(recoTracks_h, 0).get();
0354     else {
0355       // no reco track, but simCand is charged
0356       continue;
0357     }
0358     if (simCand.trackPtr().get()->pt() < 1 or simCand.trackPtr().get()->missingOuterHits() > 5 or
0359         not simCand.trackPtr().get()->quality(reco::TrackBase::highPurity))
0360       continue;
0361 
0362     // +1 to all denominators
0363     histograms.h_den_chg_energy_candidate[index]->Fill(simCand.rawEnergy());
0364     histograms.h_den_chg_pt_candidate[index]->Fill(simCand.pt());
0365     histograms.h_den_chg_eta_candidate[index]->Fill(simCand.eta());
0366     histograms.h_den_chg_phi_candidate[index]->Fill(simCand.phi());
0367 
0368     int32_t cand_idx = -1;
0369     float shared_energy = 0.;
0370     const auto& ts_vec = mergeTsSimToRecoMap[i];
0371     if (!ts_vec.empty()) {
0372       auto min_elem =
0373           std::min_element(ts_vec.begin(), ts_vec.end(), [](auto const& ts1_id_pair, auto const& ts2_id_pair) {
0374             return ts1_id_pair.score() < ts2_id_pair.score();
0375           });
0376       shared_energy = min_elem->sharedEnergy();
0377       cand_idx = min_elem->index();
0378     }
0379     // no reco associated to sim
0380     if (cand_idx == -1)
0381       continue;
0382 
0383     auto& recoCand = TICLCandidates[cand_idx];
0384     if (isTICLv5_) {
0385       // cand_idx is the tsMerge index, find the ts in the candidates collection
0386       auto const tsPtr = edm::Ptr<ticl::Trackster>(Tracksters_h, cand_idx);
0387       auto cand_it = std::find_if(TICLCandidates.begin(), TICLCandidates.end(), [tsPtr](TICLCandidate const& cand) {
0388         if (!cand.tracksters().empty())
0389           return cand.tracksters()[0] == tsPtr;
0390         else
0391           return false;
0392       });
0393       if (cand_it != TICLCandidates.end())
0394         recoCand = *cand_it;
0395       else
0396         continue;
0397     }
0398 
0399     if (recoCand.trackPtr().get() != nullptr) {
0400       const auto candTrackIdx = recoCand.trackPtr().get() - edm::Ptr<reco::Track>(recoTracks_h, 0).get();
0401       if (simCandTrackIdx == candTrackIdx) {
0402         // +1 to track num
0403         histograms.h_num_chg_energy_candidate_track[index]->Fill(simCand.rawEnergy());
0404         histograms.h_num_chg_pt_candidate_track[index]->Fill(simCand.pt());
0405         histograms.h_num_chg_eta_candidate_track[index]->Fill(simCand.eta());
0406         histograms.h_num_chg_phi_candidate_track[index]->Fill(simCand.phi());
0407       } else {
0408         continue;
0409       }
0410     } else {
0411       continue;
0412     }
0413 
0414     //step 2: PID
0415     if (simCand.pdgId() == recoCand.pdgId()) {
0416       // +1 to num pdg id
0417       histograms.h_num_chg_energy_candidate_pdgId[index]->Fill(simCand.rawEnergy());
0418       histograms.h_num_chg_pt_candidate_pdgId[index]->Fill(simCand.pt());
0419       histograms.h_num_chg_eta_candidate_pdgId[index]->Fill(simCand.eta());
0420       histograms.h_num_chg_phi_candidate_pdgId[index]->Fill(simCand.phi());
0421 
0422       //step 3: energy
0423       if (shared_energy / simCand.rawEnergy() > 0.5) {
0424         // +1 to ene num
0425         histograms.h_num_chg_energy_candidate_energy[index]->Fill(simCand.rawEnergy());
0426         histograms.h_num_chg_pt_candidate_energy[index]->Fill(simCand.pt());
0427         histograms.h_num_chg_eta_candidate_energy[index]->Fill(simCand.eta());
0428         histograms.h_num_chg_phi_candidate_energy[index]->Fill(simCand.phi());
0429       }
0430     }
0431   }
0432 
0433   for (const auto i : neutralCandidates) {
0434     const auto& simCand = simTICLCandidates[i];
0435     auto index = int(ticl::tracksterParticleTypeFromPdgId(simCand.pdgId(), 0)) / 2;
0436     /* 22 (type 0) becomes 0
0437      * 111 (type 3) becomes 1
0438      * 130 (type 5) becomes 2
0439      */
0440     histograms.h_den_neut_energy_candidate[index]->Fill(simCand.rawEnergy());
0441     histograms.h_den_neut_pt_candidate[index]->Fill(simCand.pt());
0442     histograms.h_den_neut_eta_candidate[index]->Fill(simCand.eta());
0443     histograms.h_den_neut_phi_candidate[index]->Fill(simCand.phi());
0444 
0445     int32_t cand_idx = -1;
0446     float shared_energy = 0.;
0447     const auto& ts_vec = mergeTsSimToRecoMap[i];
0448     if (!ts_vec.empty()) {
0449       auto min_elem =
0450           std::min_element(ts_vec.begin(), ts_vec.end(), [](auto const& ts1_id_pair, auto const& ts2_id_pair) {
0451             return ts1_id_pair.score() < ts2_id_pair.score();
0452           });
0453       shared_energy = min_elem->sharedEnergy();
0454       cand_idx = min_elem->index();
0455     }
0456 
0457     // no reco associated to sim
0458     if (cand_idx == -1)
0459       continue;
0460 
0461     auto& recoCand = TICLCandidates[cand_idx];
0462     if (isTICLv5_) {
0463       // cand_idx is the tsMerge index, find the ts in the candidates collection
0464       auto const tsPtr = edm::Ptr<ticl::Trackster>(Tracksters_h, cand_idx);
0465       auto cand_it = std::find_if(TICLCandidates.begin(), TICLCandidates.end(), [tsPtr](TICLCandidate const& cand) {
0466         if (!cand.tracksters().empty())
0467           return cand.tracksters()[0] == tsPtr;
0468         else
0469           return false;
0470       });
0471       if (cand_it != TICLCandidates.end())
0472         recoCand = *cand_it;
0473       else
0474         continue;
0475     }
0476 
0477     if (recoCand.trackPtr().get() != nullptr)
0478       continue;
0479 
0480     //step 2: PID
0481     if (simCand.pdgId() == recoCand.pdgId()) {
0482       // +1 to num pdg id
0483       histograms.h_num_neut_energy_candidate_pdgId[index]->Fill(simCand.rawEnergy());
0484       histograms.h_num_neut_pt_candidate_pdgId[index]->Fill(simCand.pt());
0485       histograms.h_num_neut_eta_candidate_pdgId[index]->Fill(simCand.eta());
0486       histograms.h_num_neut_phi_candidate_pdgId[index]->Fill(simCand.phi());
0487 
0488       //step 3: energy
0489       if (shared_energy / simCand.rawEnergy() > 0.5) {
0490         // +1 to ene num
0491         histograms.h_num_neut_energy_candidate_energy[index]->Fill(simCand.rawEnergy());
0492         histograms.h_num_neut_pt_candidate_energy[index]->Fill(simCand.pt());
0493         histograms.h_num_neut_eta_candidate_energy[index]->Fill(simCand.eta());
0494         histograms.h_num_neut_phi_candidate_energy[index]->Fill(simCand.phi());
0495       }
0496     }
0497   }
0498 
0499   // FAKE rate
0500   chargedCandidates.clear();
0501   neutralCandidates.clear();
0502   chargedCandidates.reserve(TICLCandidates.size());
0503   neutralCandidates.reserve(TICLCandidates.size());
0504 
0505   auto isCharged = [](int pdgId) {
0506     pdgId = std::abs(pdgId);
0507     return (pdgId == 11 or pdgId == 211 or pdgId == 13);
0508   };
0509 
0510   for (size_t i = 0; i < TICLCandidates.size(); ++i) {
0511     const auto& cand = TICLCandidates[i];
0512     const auto& charged = isCharged(cand.pdgId());
0513     if (charged)
0514       chargedCandidates.emplace_back(i);
0515     else
0516       neutralCandidates.emplace_back(i);
0517 
0518     // should consider also unknown ?
0519   }
0520 
0521   chargedCandidates.shrink_to_fit();
0522   neutralCandidates.shrink_to_fit();
0523 
0524   // loop on charged
0525   for (const auto i : chargedCandidates) {
0526     const auto& cand = TICLCandidates[i];
0527     auto index = std::log2(int(ticl::tracksterParticleTypeFromPdgId(cand.pdgId(), 1)));
0528     /* 11 (type 1) becomes 0
0529      * 13 (type 2) becomes 1
0530      * 211 (type 4) becomes 2
0531      */
0532     int32_t candTrackIdx = -1;
0533     candTrackIdx = cand.trackPtr().get() - edm::Ptr<reco::Track>(recoTracks_h, 0).get();
0534 
0535     if (cand.tracksters().empty())
0536       continue;
0537 
0538     // i is the candidate idx == ts idx only in v4, find ts_idx in v5
0539     auto mergeTs_id = i;
0540     if (isTICLv5_) {
0541       mergeTs_id = cand.tracksters()[0].get() - edm::Ptr<ticl::Trackster>(Tracksters_h, 0).get();
0542     }
0543 
0544     // +1 to all denominators
0545     histograms.h_den_fake_chg_energy_candidate[index]->Fill(cand.rawEnergy());
0546     histograms.h_den_fake_chg_pt_candidate[index]->Fill(cand.pt());
0547     histograms.h_den_fake_chg_eta_candidate[index]->Fill(cand.eta());
0548     histograms.h_den_fake_chg_phi_candidate[index]->Fill(cand.phi());
0549 
0550     histograms.h_chg_tracksters_in_candidate[index]->Fill(cand.tracksters().size());
0551     histograms.h_chg_candidate_regressed_energy[index]->Fill(cand.energy());
0552     histograms.h_chg_candidate_charge[index]->Fill(cand.charge());
0553     histograms.h_chg_candidate_pdgId[index]->Fill(cand.pdgId());
0554     const auto& arr = cand.idProbabilities();
0555     histograms.h_chg_candidate_partType[index]->Fill(std::max_element(arr.begin(), arr.end()) - arr.begin());
0556 
0557     int32_t simCand_idx = -1;
0558     const auto& sts_vec = mergeTsRecoToSimMap[mergeTs_id];
0559     float shared_energy = 0.;
0560     // search for reco cand associated
0561     if (!sts_vec.empty()) {
0562       auto min_elem =
0563           std::min_element(sts_vec.begin(), sts_vec.end(), [](auto const& sts1_id_pair, auto const& sts2_id_pair) {
0564             return sts1_id_pair.score() < sts2_id_pair.score();
0565           });
0566       shared_energy = min_elem->sharedEnergy();
0567       simCand_idx = min_elem->index();
0568     }
0569 
0570     if (simCand_idx == -1)
0571       continue;
0572 
0573     const auto& simCand = simTICLCandidates[simCand_idx];
0574     if (simCand.trackPtr().get() != nullptr) {
0575       const auto simCandTrackIdx = simCand.trackPtr().get() - edm::Ptr<reco::Track>(recoTracks_h, 0).get();
0576       if (simCandTrackIdx != candTrackIdx) {
0577         // fake += 1
0578         histograms.h_num_fake_chg_energy_candidate_track[index]->Fill(cand.rawEnergy());
0579         histograms.h_num_fake_chg_pt_candidate_track[index]->Fill(cand.pt());
0580         histograms.h_num_fake_chg_eta_candidate_track[index]->Fill(cand.eta());
0581         histograms.h_num_fake_chg_phi_candidate_track[index]->Fill(cand.phi());
0582         continue;
0583       }
0584     } else {
0585       // fake += 1
0586       histograms.h_num_fake_chg_energy_candidate_track[index]->Fill(cand.rawEnergy());
0587       histograms.h_num_fake_chg_pt_candidate_track[index]->Fill(cand.pt());
0588       histograms.h_num_fake_chg_eta_candidate_track[index]->Fill(cand.eta());
0589       histograms.h_num_fake_chg_phi_candidate_track[index]->Fill(cand.phi());
0590       continue;
0591     }
0592 
0593     //step 2: PID
0594     if (simCand.pdgId() != cand.pdgId()) {
0595       // +1 to num fake pdg id
0596       histograms.h_num_fake_chg_energy_candidate_pdgId[index]->Fill(cand.rawEnergy());
0597       histograms.h_num_fake_chg_pt_candidate_pdgId[index]->Fill(cand.pt());
0598       histograms.h_num_fake_chg_eta_candidate_pdgId[index]->Fill(cand.eta());
0599       histograms.h_num_fake_chg_phi_candidate_pdgId[index]->Fill(cand.phi());
0600       continue;
0601     }
0602 
0603     //step 3: energy
0604     if (shared_energy / simCand.rawEnergy() < 0.5) {
0605       // +1 to ene num
0606       histograms.h_num_fake_chg_energy_candidate_energy[index]->Fill(cand.rawEnergy());
0607       histograms.h_num_fake_chg_pt_candidate_energy[index]->Fill(cand.pt());
0608       histograms.h_num_fake_chg_eta_candidate_energy[index]->Fill(cand.eta());
0609       histograms.h_num_fake_chg_phi_candidate_energy[index]->Fill(cand.phi());
0610     }
0611   }
0612   // loop on neutrals
0613   for (const auto i : neutralCandidates) {
0614     const auto& cand = TICLCandidates[i];
0615     auto index = int(ticl::tracksterParticleTypeFromPdgId(cand.pdgId(), 0)) / 2;
0616     /* 22 (type 0) becomes 0
0617      * 111 (type 3) becomes 1
0618      * 130 (type 5) becomes 2
0619      */
0620 
0621     if (cand.tracksters().empty())
0622       continue;
0623 
0624     // i is the candidate idx == ts idx only in v4, find ts_idx in v5
0625     auto mergeTs_id = i;
0626     if (isTICLv5_) {
0627       mergeTs_id = cand.tracksters()[0].get() - edm::Ptr<ticl::Trackster>(Tracksters_h, 0).get();
0628     }
0629 
0630     // +1 to all denominators
0631     histograms.h_den_fake_neut_energy_candidate[index]->Fill(cand.rawEnergy());
0632     histograms.h_den_fake_neut_pt_candidate[index]->Fill(cand.pt());
0633     histograms.h_den_fake_neut_eta_candidate[index]->Fill(cand.eta());
0634     histograms.h_den_fake_neut_phi_candidate[index]->Fill(cand.phi());
0635 
0636     histograms.h_neut_tracksters_in_candidate[index]->Fill(cand.tracksters().size());
0637     histograms.h_neut_candidate_regressed_energy[index]->Fill(cand.energy());
0638     histograms.h_neut_candidate_charge[index]->Fill(cand.charge());
0639     histograms.h_neut_candidate_pdgId[index]->Fill(cand.pdgId());
0640     const auto& arr = cand.idProbabilities();
0641     histograms.h_neut_candidate_partType[index]->Fill(std::max_element(arr.begin(), arr.end()) - arr.begin());
0642 
0643     int32_t simCand_idx = -1;
0644     const auto& sts_vec = mergeTsRecoToSimMap[mergeTs_id];
0645     float shared_energy = 0.;
0646     // search for reco cand associated
0647     if (!sts_vec.empty()) {
0648       auto min_elem =
0649           std::min_element(sts_vec.begin(), sts_vec.end(), [](auto const& sts1_id_pair, auto const& sts2_id_pair) {
0650             return sts1_id_pair.score() < sts2_id_pair.score();
0651           });
0652       shared_energy = min_elem->sharedEnergy();
0653       simCand_idx = min_elem->index();
0654     }
0655 
0656     if (simCand_idx == -1)
0657       continue;
0658 
0659     const auto& simCand = simTICLCandidates[simCand_idx];
0660 
0661     //step 2: PID
0662     if (simCand.pdgId() != cand.pdgId()) {
0663       // +1 to num fake pdg id
0664       histograms.h_num_fake_neut_energy_candidate_pdgId[index]->Fill(cand.rawEnergy());
0665       histograms.h_num_fake_neut_pt_candidate_pdgId[index]->Fill(cand.pt());
0666       histograms.h_num_fake_neut_eta_candidate_pdgId[index]->Fill(cand.eta());
0667       histograms.h_num_fake_neut_phi_candidate_pdgId[index]->Fill(cand.phi());
0668       continue;
0669     }
0670 
0671     //step 3: energy
0672     if (shared_energy / simCand.rawEnergy() < 0.5) {
0673       // +1 to ene num
0674       histograms.h_num_fake_neut_energy_candidate_energy[index]->Fill(cand.rawEnergy());
0675       histograms.h_num_fake_neut_pt_candidate_energy[index]->Fill(cand.pt());
0676       histograms.h_num_fake_neut_eta_candidate_energy[index]->Fill(cand.eta());
0677       histograms.h_num_fake_neut_phi_candidate_energy[index]->Fill(cand.phi());
0678     }
0679   }
0680 }