File indexing completed on 2026-09-07 08:28:00
0001
0002
0003
0004 #include <edm4eic/ClusterCollection.h>
0005 #include <edm4eic/ReconstructedParticleCollection.h>
0006 #include <edm4hep/Vector3f.h>
0007 #include <edm4hep/utils/vector_utils.h>
0008 #include <cmath>
0009 #include <set>
0010 #include <tuple>
0011
0012 #include "CaloRemnantCombiner.h"
0013 #include "algorithms/particle_flow/CaloRemnantCombinerConfig.h"
0014
0015 namespace eicrecon {
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036 void CaloRemnantCombiner::process(const CaloRemnantCombiner::Input& input,
0037 const CaloRemnantCombiner::Output& output) const {
0038
0039 const auto [ecal_clusters, hcal_clusters] = input;
0040 auto [out_neutral_candidates] = output;
0041
0042
0043 if ((ecal_clusters->size() == 0) && (hcal_clusters->size() == 0)) {
0044 debug("Both ECAL and HCAL inputs are empty; skipping event.");
0045 return;
0046 }
0047
0048 auto ecal_cmp = [ecal_clusters](std::size_t a, std::size_t b) {
0049 float ea = (*ecal_clusters)[a].getEnergy();
0050 float eb = (*ecal_clusters)[b].getEnergy();
0051 if (ea != eb) {
0052 return ea > eb;
0053 }
0054 return a < b;
0055 };
0056
0057 auto hcal_cmp = [hcal_clusters](std::size_t a, std::size_t b) {
0058 float ea = (*hcal_clusters)[a].getEnergy();
0059 float eb = (*hcal_clusters)[b].getEnergy();
0060 if (ea != eb) {
0061 return ea > eb;
0062 }
0063 return a < b;
0064 };
0065
0066 std::set<std::size_t, decltype(ecal_cmp)> remaining_ecal(ecal_cmp);
0067 std::set<std::size_t, decltype(hcal_cmp)> remaining_hcal(hcal_cmp);
0068
0069 for (std::size_t i = 0; i < ecal_clusters->size(); ++i) {
0070 remaining_ecal.insert(i);
0071 }
0072 for (std::size_t i = 0; i < hcal_clusters->size(); ++i) {
0073 remaining_hcal.insert(i);
0074 }
0075
0076
0077 while (!remaining_ecal.empty()) {
0078
0079 auto neutral_candidate_eh = out_neutral_candidates->create();
0080
0081
0082 std::size_t seed_ecal_index = *remaining_ecal.begin();
0083
0084
0085 std::vector<std::size_t> ecal_to_merge = move_cluster_indices_for_merging(
0086 *ecal_clusters, remaining_ecal, seed_ecal_index, m_cfg.ecalDeltaR, *ecal_clusters);
0087
0088 for (const auto& idx : ecal_to_merge) {
0089 neutral_candidate_eh.addToClusters((*ecal_clusters)[idx]);
0090 }
0091
0092
0093 std::vector<std::size_t> hcal_to_merge = move_cluster_indices_for_merging(
0094 *hcal_clusters, remaining_hcal, seed_ecal_index, m_cfg.hcalDeltaR, *ecal_clusters);
0095
0096 for (const auto& idx : hcal_to_merge) {
0097 neutral_candidate_eh.addToClusters((*hcal_clusters)[idx]);
0098 }
0099
0100 }
0101
0102
0103 while (!remaining_hcal.empty()) {
0104
0105 auto neutral_candidate_h = out_neutral_candidates->create();
0106
0107
0108 std::size_t seed_hcal_index = *remaining_hcal.begin();
0109
0110 std::vector<std::size_t> hcal_to_merge = move_cluster_indices_for_merging(
0111 *hcal_clusters, remaining_hcal, seed_hcal_index, m_cfg.hcalDeltaR, *hcal_clusters);
0112
0113 for (const auto& idx : hcal_to_merge) {
0114 neutral_candidate_h.addToClusters((*hcal_clusters)[idx]);
0115 }
0116
0117 }
0118 }
0119
0120
0121
0122
0123 std::vector<std::size_t> CaloRemnantCombiner::move_cluster_indices_for_merging(
0124 const edm4eic::ClusterCollection& clusters, auto& remaining, std::size_t seed_cluster_index,
0125 double delta_r_add, const edm4eic::ClusterCollection& seed) const {
0126
0127 std::vector<std::size_t> merged_indices;
0128
0129
0130 edm4hep::Vector3f seed_pos = seed[seed_cluster_index].getPosition();
0131 float eta_seed = edm4hep::utils::eta(seed_pos);
0132 float phi_seed = edm4hep::utils::angleAzimuthal(seed_pos);
0133
0134 if (delta_r_add < 0.0)
0135 delta_r_add = 0.0;
0136
0137
0138 auto it = remaining.begin();
0139 while (it != remaining.end()) {
0140 std::size_t i = *it;
0141
0142 edm4hep::Vector3f cluster_pos = clusters[i].getPosition();
0143 float eta_cluster = edm4hep::utils::eta(cluster_pos);
0144 float phi_cluster = edm4hep::utils::angleAzimuthal(cluster_pos);
0145
0146 float dphi = std::remainder(phi_cluster - phi_seed, 2 * M_PI);
0147 float deta = eta_cluster - eta_seed;
0148 float distance = std::sqrt(deta * deta + dphi * dphi);
0149
0150 if (distance <= delta_r_add) {
0151 merged_indices.push_back(i);
0152 it = remaining.erase(it);
0153 } else {
0154 ++it;
0155 }
0156 }
0157 return merged_indices;
0158 }
0159 }