File indexing completed on 2025-06-08 07:53:21
0001
0002
0003
0004 #include "algorithms/calorimetry/EnergyPositionClusterMerger.h"
0005
0006 #include <edm4hep/Vector3f.h>
0007 #include <edm4hep/utils/vector_utils.h>
0008 #include <fmt/core.h>
0009 #include <podio/ObjectID.h>
0010 #include <cmath>
0011 #include <cstddef>
0012 #include <gsl/pointers>
0013 #include <limits>
0014 #include <vector>
0015
0016 #include "algorithms/calorimetry/EnergyPositionClusterMergerConfig.h"
0017
0018 namespace eicrecon {
0019
0020 void EnergyPositionClusterMerger::process(const Input& input, const Output& output) const {
0021
0022 const auto [energy_clus, energy_assoc, pos_clus, pos_assoc] = input;
0023 auto [merged_clus, merged_assoc] = output;
0024
0025 debug("Merging energy and position clusters for new event");
0026
0027 if (energy_clus->size() == 0 && pos_clus->size() == 0) {
0028 debug("Nothing to do for this event, returning...");
0029 return;
0030 }
0031
0032 std::vector<bool> consumed(energy_clus->size(), false);
0033
0034
0035 for (const auto& pc : *pos_clus) {
0036
0037 trace(" --> Processing position cluster {}, energy: {}", pc.getObjectID().index,
0038 pc.getEnergy());
0039
0040
0041 int best_match = -1;
0042 double best_delta = std::numeric_limits<double>::max();
0043 for (std::size_t ie = 0; ie < energy_clus->size(); ++ie) {
0044 if (consumed[ie]) {
0045 continue;
0046 }
0047
0048 const auto& ec = (*energy_clus)[ie];
0049
0050 trace(" --> Evaluating energy cluster {}, energy: {}", ec.getObjectID().index,
0051 ec.getEnergy());
0052
0053
0054
0055 const double de_rel = std::abs((pc.getEnergy() - ec.getEnergy()) / ec.getEnergy());
0056 const double deta =
0057 std::abs(edm4hep::utils::eta(pc.getPosition()) - edm4hep::utils::eta(ec.getPosition()));
0058
0059
0060 const double dphi = edm4hep::utils::angleAzimuthal(pc.getPosition()) -
0061 edm4hep::utils::angleAzimuthal(ec.getPosition());
0062 const double dsphi = std::abs(sin(0.5 * dphi));
0063 if ((m_cfg.energyRelTolerance > 0 && de_rel > m_cfg.energyRelTolerance) ||
0064 (m_cfg.etaTolerance > 0 && deta > m_cfg.etaTolerance) ||
0065 (m_cfg.phiTolerance > 0 && dsphi > sin(0.5 * m_cfg.phiTolerance))) {
0066 continue;
0067 }
0068
0069
0070
0071
0072 const double delta = std::abs(pc.getEnergy() - ec.getEnergy());
0073 if (delta < best_delta) {
0074 best_delta = delta;
0075 best_match = ie;
0076 }
0077 }
0078
0079
0080 if (best_match >= 0) {
0081
0082 const auto& ec = (*energy_clus)[best_match];
0083
0084 auto new_clus = merged_clus->create();
0085 new_clus.setEnergy(ec.getEnergy());
0086 new_clus.setEnergyError(ec.getEnergyError());
0087 new_clus.setTime(pc.getTime());
0088 new_clus.setNhits(pc.getNhits() + ec.getNhits());
0089 new_clus.setPosition(pc.getPosition());
0090 new_clus.setPositionError(pc.getPositionError());
0091 new_clus.addToClusters(pc);
0092 new_clus.addToClusters(ec);
0093
0094 trace(" --> Found matching energy cluster {}, energy: {}", ec.getObjectID().index,
0095 ec.getEnergy());
0096 trace(" --> Created a new combined cluster {}, energy: {}", new_clus.getObjectID().index,
0097 new_clus.getEnergy());
0098
0099
0100 auto ea = energy_assoc->begin();
0101 for (; ea != energy_assoc->end(); ++ea) {
0102 if (ea->getRec() == ec) {
0103 break;
0104 }
0105 }
0106
0107 auto pa = pos_assoc->begin();
0108 for (; pa != pos_assoc->end(); ++pa) {
0109 if (pa->getRec() == pc) {
0110 break;
0111 }
0112 }
0113 if (ea != energy_assoc->end() || pa != pos_assoc->end()) {
0114
0115 if (ea != energy_assoc->end() && pa != pos_assoc->end()) {
0116
0117 if (pa->getSimID() == ea->getSimID()) {
0118
0119 auto clusterassoc = merged_assoc->create();
0120 clusterassoc.setRecID(new_clus.getObjectID().index);
0121 clusterassoc.setSimID(ea->getSimID());
0122 clusterassoc.setWeight(1.0);
0123 clusterassoc.setRec(new_clus);
0124 clusterassoc.setSim(ea->getSim());
0125 } else {
0126
0127 debug(" --> Two associations added to {} and {}", ea->getSimID(), pa->getSimID());
0128 auto clusterassoc1 = merged_assoc->create();
0129 clusterassoc1.setRecID(new_clus.getObjectID().index);
0130 clusterassoc1.setSimID(ea->getSimID());
0131 clusterassoc1.setWeight(0.5);
0132 clusterassoc1.setRec(new_clus);
0133 clusterassoc1.setSim(ea->getSim());
0134 auto clusterassoc2 = merged_assoc->create();
0135 clusterassoc2.setRecID(new_clus.getObjectID().index);
0136 clusterassoc2.setSimID(pa->getSimID());
0137 clusterassoc2.setWeight(0.5);
0138 clusterassoc2.setRec(new_clus);
0139 clusterassoc2.setSim(pa->getSim());
0140 }
0141 } else if (ea != energy_assoc->end()) {
0142
0143 debug(" --> Only added energy cluster association to {}", ea->getSimID());
0144 auto clusterassoc = merged_assoc->create();
0145 clusterassoc.setRecID(new_clus.getObjectID().index);
0146 clusterassoc.setSimID(ea->getSimID());
0147 clusterassoc.setWeight(1.0);
0148 clusterassoc.setRec(new_clus);
0149 clusterassoc.setSim(ea->getSim());
0150 } else if (pa != pos_assoc->end()) {
0151
0152 debug(" --> Only added position cluster association to {}", pa->getSimID());
0153 auto clusterassoc = merged_assoc->create();
0154 clusterassoc.setRecID(new_clus.getObjectID().index);
0155 clusterassoc.setSimID(pa->getSimID());
0156 clusterassoc.setWeight(1.0);
0157 clusterassoc.setRec(new_clus);
0158 clusterassoc.setSim(pa->getSim());
0159 }
0160 }
0161
0162
0163 consumed[best_match] = true;
0164
0165 debug(" Matched position cluster {} with energy cluster {}", pc.getObjectID().index,
0166 ec.getObjectID().index);
0167 debug(" - Position cluster: (E: {}, phi: {}, z: {})", pc.getEnergy(),
0168 edm4hep::utils::angleAzimuthal(pc.getPosition()), pc.getPosition().z);
0169 debug(" - Energy cluster: (E: {}, phi: {}, z: {})", ec.getEnergy(),
0170 edm4hep::utils::angleAzimuthal(ec.getPosition()), ec.getPosition().z);
0171 debug(" ---> Merged cluster: (E: {}, phi: {}, z: {})", new_clus.getEnergy(),
0172 edm4hep::utils::angleAzimuthal(new_clus.getPosition()), new_clus.getPosition().z);
0173
0174 } else {
0175
0176 debug(" Unmatched position cluster {}", pc.getObjectID().index);
0177 }
0178 }
0179 }
0180
0181 }