File indexing completed on 2024-09-27 07:02:59
0001
0002
0003
0004 #include "MergeParticleID.h"
0005
0006 #include <edm4eic/CherenkovParticleIDHypothesis.h>
0007 #include <edm4eic/TrackSegmentCollection.h>
0008 #include <edm4hep/Vector2f.h>
0009 #include <fmt/core.h>
0010 #include <podio/ObjectID.h>
0011 #include <podio/RelationRange.h>
0012 #include <spdlog/common.h>
0013 #include <stddef.h>
0014 #include <stdexcept>
0015 #include <unordered_map>
0016 #include <utility>
0017
0018 #include "algorithms/pid/MergeParticleIDConfig.h"
0019 #include "algorithms/pid/Tools.h"
0020
0021 namespace eicrecon {
0022
0023 void MergeParticleID::init(std::shared_ptr<spdlog::logger>& logger)
0024 {
0025 m_log = logger;
0026 m_cfg.Print(m_log, spdlog::level::debug);
0027 }
0028
0029 void MergeParticleID::process(
0030 const MergeParticleID::Input& input,
0031 const MergeParticleID::Output& output) const {
0032
0033 const auto [in_pid_collections_list] = input;
0034 auto [out_pids] = output;
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069 std::unordered_map< decltype(podio::ObjectID::index), std::vector<std::pair<size_t,size_t>> > particle_pids;
0070 m_log->trace("{:-<70}","Build `particle_pids` indexing data structure ");
0071
0072
0073 for(size_t idx_coll = 0; idx_coll < in_pid_collections_list.size(); idx_coll++) {
0074 const auto& in_pid_collection = in_pid_collections_list.at(idx_coll);
0075 m_log->trace("idx_col={}", idx_coll);
0076
0077
0078 for(size_t idx_pid = 0; idx_pid < in_pid_collection->size(); idx_pid++) {
0079
0080 const auto& in_pid = in_pid_collection->at(idx_pid);
0081 auto& charged_particle_track_segment = in_pid.getChargedParticle();
0082 if(!charged_particle_track_segment.isAvailable()) {
0083 m_log->error("PID object found with no charged particle");
0084 continue;
0085 }
0086 auto id_particle = charged_particle_track_segment.getObjectID().index;
0087 auto idx_paired = std::make_pair(idx_coll, idx_pid);
0088 m_log->trace(" idx_pid={} id_particle={}", idx_pid, id_particle);
0089
0090
0091 auto it = particle_pids.find(id_particle);
0092 if(it == particle_pids.end())
0093 particle_pids.insert({id_particle, {idx_paired}});
0094 else
0095 it->second.push_back(idx_paired);
0096 }
0097 }
0098
0099
0100 if(m_log->level() <= spdlog::level::trace) {
0101 m_log->trace("{:-<70}","Resulting `particle_pids` ");
0102 for(auto& [id_particle, idx_paired_list] : particle_pids) {
0103 m_log->trace("id_particle={}", id_particle);
0104 for(auto& [idx_coll, idx_pid] : idx_paired_list)
0105 m_log->trace(" (idx_coll, idx_pid) = ({}, {})", idx_coll, idx_pid);
0106 }
0107 }
0108
0109
0110
0111
0112
0113
0114 m_log->trace("{:-<70}","Begin Merging PID Objects ");
0115 for(auto& [id_particle, idx_paired_list] : particle_pids) {
0116
0117
0118 m_log->trace("Charged Particle:");
0119 m_log->trace(" id = {}", id_particle);
0120 m_log->trace(" PID Hypotheses:");
0121
0122
0123 auto out_pid = out_pids->create();
0124 decltype(edm4eic::CherenkovParticleIDData::npe) out_npe = 0.0;
0125 decltype(edm4eic::CherenkovParticleIDData::refractiveIndex) out_refractiveIndex = 0.0;
0126 decltype(edm4eic::CherenkovParticleIDData::photonEnergy) out_photonEnergy = 0.0;
0127
0128
0129 std::unordered_map< decltype(edm4eic::CherenkovParticleIDHypothesis::PDG), edm4eic::CherenkovParticleIDHypothesis > pdg_2_out_hyp;
0130
0131
0132 for(auto& [idx_coll, idx_pid] : idx_paired_list) {
0133 const auto& in_pid = in_pid_collections_list.at(idx_coll)->at(idx_pid);
0134
0135
0136 m_log->trace(" Hypotheses for PID result (idx_coll, idx_pid) = ({}, {}):", idx_coll, idx_pid);
0137 Tools::PrintHypothesisTableHead(m_log,6);
0138
0139
0140 out_npe += in_pid.getNpe();
0141 out_refractiveIndex += in_pid.getNpe() * in_pid.getRefractiveIndex();
0142 out_photonEnergy += in_pid.getNpe() * in_pid.getPhotonEnergy();
0143
0144
0145 for(auto in_photon_vec : in_pid.getThetaPhiPhotons())
0146 out_pid.addToThetaPhiPhotons(in_photon_vec);
0147
0148
0149 if(!out_pid.getChargedParticle().isAvailable())
0150 out_pid.setChargedParticle(in_pid.getChargedParticle());
0151
0152
0153 for(auto in_hyp : in_pid.getHypotheses()) {
0154 Tools::PrintHypothesisTableLine(m_log,in_hyp,6);
0155 auto out_hyp_it = pdg_2_out_hyp.find(in_hyp.PDG);
0156 if(out_hyp_it == pdg_2_out_hyp.end()) {
0157 edm4eic::CherenkovParticleIDHypothesis out_hyp;
0158 out_hyp.PDG = in_hyp.PDG;
0159 out_hyp.npe = in_hyp.npe;
0160 out_hyp.weight = in_hyp.weight;
0161 pdg_2_out_hyp.insert({out_hyp.PDG,out_hyp});
0162 }
0163 else {
0164 auto& out_hyp = out_hyp_it->second;
0165 out_hyp.npe += in_hyp.npe;
0166
0167 switch(m_cfg.mergeMode) {
0168 case MergeParticleIDConfig::kAddWeights:
0169 out_hyp.weight += in_hyp.weight;
0170 break;
0171 case MergeParticleIDConfig::kMultiplyWeights:
0172 out_hyp.weight *= in_hyp.weight;
0173 break;
0174 default:
0175 throw std::runtime_error("unknown MergeParticleIDConfig::mergeMode setting; weights not combined");
0176 }
0177 }
0178 }
0179
0180 }
0181
0182
0183 out_pid.setNpe(out_npe);
0184 if(out_npe > 0) {
0185 out_pid.setRefractiveIndex( out_refractiveIndex / out_npe );
0186 out_pid.setPhotonEnergy( out_photonEnergy / out_npe );
0187 }
0188
0189
0190 for(auto [pdg,out_hyp] : pdg_2_out_hyp)
0191 out_pid.addToHypotheses(out_hyp);
0192
0193
0194 m_log->trace(" => merged hypothesis weights:");
0195 Tools::PrintHypothesisTableHead(m_log,6);
0196 for(auto out_hyp : out_pid.getHypotheses())
0197 Tools::PrintHypothesisTableLine(m_log,out_hyp,6);
0198
0199 }
0200 }
0201
0202 }