File indexing completed on 2025-09-18 08:17:48
0001
0002
0003
0004 #include <edm4eic/EDM4eicVersion.h> // Needs edm4eic::TrackClusterMatch
0005 #include <edm4eic/Track.h>
0006 #include <fmt/core.h>
0007 #include <podio/RelationRange.h>
0008 #include <cstdint>
0009 #include <gsl/pointers>
0010 #include <optional>
0011 #include <set>
0012 #include <stdexcept>
0013 #include <vector>
0014 #if EDM4EIC_VERSION_MAJOR >= 8
0015
0016 #include <DD4hep/Detector.h>
0017 #include <edm4eic/ClusterCollection.h>
0018 #include <edm4eic/TrackPoint.h>
0019 #include <edm4hep/Vector3f.h>
0020 #include <edm4hep/utils/vector_utils.h>
0021
0022 #include "algorithms/reco/TrackClusterMatch.h"
0023 #include "algorithms/reco/TrackClusterMatchConfig.h"
0024
0025 namespace eicrecon {
0026 void TrackClusterMatch::process(const TrackClusterMatch::Input& input,
0027 const TrackClusterMatch::Output& output) const {
0028 auto [tracks, clusters] = input;
0029 auto [matched_particles] = output;
0030 trace("We have {} tracks and {} clusters", tracks->size(), clusters->size());
0031
0032
0033 if (m_cfg.matching_distance <= 0) {
0034 throw std::runtime_error(fmt::format("Invalid matching distance: {}", m_cfg.matching_distance));
0035 }
0036 if (m_cfg.calo_id.empty()) {
0037 throw std::runtime_error("Calorimeter ID must be set in the configuration");
0038 }
0039
0040 std::set<int> used_tracks;
0041
0042 for (auto cluster : *clusters) {
0043 const double cluster_eta = edm4hep::utils::eta(cluster.getPosition());
0044 const double cluster_phi = edm4hep::utils::angleAzimuthal(cluster.getPosition());
0045 trace("Cluster at eta={}, phi={}", cluster_eta, cluster_phi);
0046
0047
0048 std::optional<edm4eic::TrackSegment> closest_segment;
0049 int closest_segment_id = -1;
0050 double closest_distance = m_cfg.matching_distance;
0051
0052 for (int closest_id = 0; auto track : *tracks) {
0053 if (used_tracks.contains(closest_id)) {
0054 trace("Skipping track segment already used");
0055 continue;
0056 }
0057 for (auto point : track.getPoints()) {
0058
0059
0060 uint32_t calo_id = m_geo.detector()->constant<int>(m_cfg.calo_id);
0061 bool is_calo = point.system == calo_id;
0062 bool is_surface = point.surface == 1;
0063
0064 if (!is_calo || !is_surface) {
0065 trace("Skipping track point not at the calorimeter");
0066 continue;
0067 }
0068 const double track_eta = edm4hep::utils::eta(point.position);
0069 const double track_phi = edm4hep::utils::angleAzimuthal(point.position);
0070 trace("Track point at eta={}, phi={}", track_eta, track_phi);
0071
0072 double delta = distance(cluster.getPosition(), point.position);
0073 trace("Distance between cluster and track point: {}", delta);
0074 if (delta < closest_distance) {
0075 closest_distance = delta;
0076 closest_segment = track;
0077 closest_segment_id = closest_id;
0078 }
0079 }
0080 closest_id++;
0081 }
0082
0083 if (closest_segment) {
0084 trace("Found a closest point at distance {}", closest_distance);
0085 auto particle = matched_particles->create();
0086 particle.setCluster(cluster);
0087 particle.setTrack(closest_segment.value().getTrack());
0088 used_tracks.insert(closest_segment_id);
0089 }
0090 }
0091 trace("Matched {} particles", matched_particles->size());
0092 }
0093
0094 double TrackClusterMatch::distance(const edm4hep::Vector3f& v1, const edm4hep::Vector3f& v2) {
0095 double cluster_eta = edm4hep::utils::eta(v1);
0096 double cluster_phi = edm4hep::utils::angleAzimuthal(v1);
0097 double track_eta = edm4hep::utils::eta(v2);
0098 double track_phi = edm4hep::utils::angleAzimuthal(v2);
0099 double deta = cluster_eta - track_eta;
0100 double dphi = Phi_mpi_pi(cluster_phi - track_phi);
0101 return std::hypot(deta, dphi);
0102 }
0103 }
0104
0105 #endif