File indexing completed on 2024-09-27 07:02:31
0001
0002
0003
0004 #include <algorithms/truth/ParticlesWithTruthPID.h>
0005
0006 #include <algorithm>
0007 #include <cmath>
0008 #include <fmt/format.h>
0009
0010 #include <edm4hep/utils/vector_utils.h>
0011
0012 namespace algorithms::truth {
0013
0014 void ParticlesWithTruthPID::init() {
0015 ;
0016 }
0017 void ParticlesWithTruthPID::process(const ParticlesWithTruthPID::Input& input,
0018 const ParticlesWithTruthPID::Output& output) const {
0019 const auto [mc_ptr, tracks_ptr] = input;
0020 auto [part_ptr, assoc_ptr] = output;
0021
0022 const auto& mc = *mc_ptr;
0023 const auto& tracks = *tracks_ptr;
0024 auto& part = *part_ptr;
0025 auto& assoc = *assoc_ptr;
0026
0027 const double sinPhiOver2Tolerance = sin(0.5 * m_phiTolerance);
0028 std::vector<bool> consumed(mc.size(), false);
0029 for (const auto& trk : tracks) {
0030 const auto mom =
0031 edm4hep::utils::sphericalToVector(1.0 / std::abs(trk.getQOverP()), trk.getTheta(), trk.getPhi());
0032 const auto charge_rec = std::copysign(1., trk.getQOverP());
0033
0034 int best_match = -1;
0035 double best_delta = std::numeric_limits<double>::max();
0036 for (size_t ip = 0; ip < mc.size(); ++ip) {
0037 const auto& mcpart = mc[ip];
0038 if (consumed[ip] || mcpart.getGeneratorStatus() > 1 || mcpart.getCharge() == 0 ||
0039 mcpart.getCharge() * charge_rec < 0) {
0040 if (aboveDebugThreshold()) {
0041 debug() << "ignoring non-primary/neutral/opposite charge particle" << endmsg;
0042 }
0043 continue;
0044 }
0045 const auto& p = mcpart.getMomentum();
0046 const auto p_mag = std::hypot(p.x, p.y, p.z);
0047 const auto p_phi = std::atan2(p.y, p.x);
0048 const auto p_eta = std::atanh(p.z / p_mag);
0049 const double dp_rel = std::abs((edm4hep::utils::magnitude(mom) - p_mag) / p_mag);
0050
0051
0052 const double dsphi = std::abs(sin(0.5 * (edm4hep::utils::angleAzimuthal(mom) - p_phi)));
0053 const double deta = std::abs((edm4hep::utils::eta(mom) - p_eta));
0054
0055 if (dp_rel < m_pRelativeTolerance && deta < m_etaTolerance && dsphi < sinPhiOver2Tolerance) {
0056 const double delta = std::hypot(dp_rel / m_pRelativeTolerance, deta / m_etaTolerance,
0057 dsphi / sinPhiOver2Tolerance);
0058 if (delta < best_delta) {
0059 best_match = ip;
0060 best_delta = delta;
0061 }
0062 }
0063 }
0064 auto rec_part = part.create();
0065 int32_t best_pid = 0;
0066 auto referencePoint = rec_part.referencePoint();
0067
0068 float mass = 0;
0069 if (best_match >= 0) {
0070 consumed[best_match] = true;
0071 const auto& mcpart = mc[best_match];
0072 best_pid = mcpart.getPDG();
0073 referencePoint = {
0074 static_cast<float>(mcpart.getVertex().x), static_cast<float>(mcpart.getVertex().y),
0075 static_cast<float>(
0076 mcpart.getVertex().z)};
0077
0078 mass = mcpart.getMass();
0079 }
0080 rec_part.setType(static_cast<int16_t>(best_match >= 0 ? 0 : -1));
0081 rec_part.setEnergy(std::hypot(edm4hep::utils::magnitude(mom), mass));
0082 rec_part.setMomentum(mom);
0083 rec_part.setReferencePoint(referencePoint);
0084 rec_part.setCharge(charge_rec);
0085 rec_part.setMass(mass);
0086 rec_part.setGoodnessOfPID(1);
0087 rec_part.setPDG(best_pid);
0088
0089
0090 if (best_match >= 0) {
0091 auto rec_assoc = assoc.create();
0092 rec_assoc.setRecID(rec_part.getObjectID().index);
0093 rec_assoc.setSimID(mc[best_match].getObjectID().index);
0094 rec_assoc.setWeight(1);
0095 rec_assoc.setRec(rec_part);
0096
0097 }
0098 if (aboveDebugThreshold()) {
0099 if (best_match > 0) {
0100 const auto& mcpart = mc[best_match];
0101 debug() << fmt::format("Matched track with MC particle {}\n", best_match) << endmsg;
0102 debug() << fmt::format(" - Track: (mom: {}, theta: {}, phi: {}, charge: {})",
0103 edm4hep::utils::magnitude(mom), edm4hep::utils::anglePolar(mom),
0104 edm4hep::utils::angleAzimuthal(mom), charge_rec)
0105 << endmsg;
0106 const auto& p = mcpart.getMomentum();
0107 const auto p_mag = edm4hep::utils::magnitude(p);
0108 const auto p_phi = edm4hep::utils::angleAzimuthal(p);
0109 const auto p_theta = edm4hep::utils::anglePolar(p);
0110 debug() << fmt::format(
0111 " - MC particle: (mom: {}, theta: {}, phi: {}, charge: {}, type: {}", p_mag,
0112 p_theta, p_phi, mcpart.getCharge(), mcpart.getPDG())
0113 << endmsg;
0114 } else {
0115 debug() << fmt::format("Did not find a good match for track \n") << endmsg;
0116 debug() << fmt::format(" - Track: (mom: {}, theta: {}, phi: {}, charge: {})",
0117 edm4hep::utils::magnitude(mom), edm4hep::utils::anglePolar(mom),
0118 edm4hep::utils::angleAzimuthal(mom), charge_rec)
0119 << endmsg;
0120 }
0121 }
0122 }
0123 }
0124
0125 }
0126