File indexing completed on 2025-07-03 08:57:51
0001
0002
0003
0004 #include <algorithm>
0005
0006 #include "Gaudi/Property.h"
0007 #include "Gaudi/Algorithm.h"
0008 #include "GaudiKernel/PhysicalConstants.h"
0009 #include "GaudiKernel/RndmGenerators.h"
0010 #include "GaudiKernel/ToolHandle.h"
0011
0012 #include "DDRec/CellIDPositionConverter.h"
0013 #include "DDRec/Surface.h"
0014 #include "DDRec/SurfaceManager.h"
0015
0016 #include <k4FWCore/DataHandle.h>
0017 #include <k4Interface/IGeoSvc.h>
0018
0019
0020 #include "edm4hep/SimCalorimeterHitCollection.h"
0021 #include "edm4eic/CalorimeterHitCollection.h"
0022 #include "edm4eic/ClusterCollection.h"
0023 #include "edm4eic/ProtoClusterCollection.h"
0024 #include "edm4hep/utils/vector_utils.h"
0025
0026 using namespace Gaudi::Units;
0027
0028 namespace Jug::Reco {
0029
0030
0031
0032
0033
0034 class SimpleClustering : public Gaudi::Algorithm {
0035 private:
0036 using RecHits = edm4eic::CalorimeterHitCollection;
0037 using ProtoClusters = edm4eic::ProtoClusterCollection;
0038 using Clusters = edm4eic::ClusterCollection;
0039
0040 mutable DataHandle<RecHits> m_inputHitCollection{"inputHitCollection", Gaudi::DataHandle::Reader, this};
0041 mutable DataHandle<ProtoClusters> m_outputProtoClusters{"outputProtoCluster", Gaudi::DataHandle::Writer, this};
0042 mutable DataHandle<Clusters> m_outputClusters{"outputClusterCollection", Gaudi::DataHandle::Writer, this};
0043
0044 Gaudi::Property<std::string> m_mcHits{this, "mcHits", ""};
0045
0046 Gaudi::Property<double> m_minModuleEdep{this, "minModuleEdep", 5.0 * MeV};
0047 Gaudi::Property<double> m_maxDistance{this, "maxDistance", 20.0 * cm};
0048
0049
0050 SmartIF<IGeoSvc> m_geoSvc;
0051
0052
0053 std::unique_ptr<DataHandle<edm4hep::SimCalorimeterHitCollection>> m_inputMC;
0054
0055 public:
0056 SimpleClustering(const std::string& name, ISvcLocator* svcLoc)
0057 : Gaudi::Algorithm(name, svcLoc) {
0058 declareProperty("inputHitCollection", m_inputHitCollection, "");
0059 declareProperty("outputProtoClusterCollection", m_outputClusters, "Output proto clusters");
0060 declareProperty("outputClusterCollection", m_outputClusters, "Output clusters");
0061 }
0062
0063 StatusCode initialize() override
0064 {
0065 if (Gaudi::Algorithm::initialize().isFailure()) {
0066 return StatusCode::FAILURE;
0067 }
0068
0069 if (m_mcHits != "") {
0070 m_inputMC =
0071 std::make_unique<DataHandle<edm4hep::SimCalorimeterHitCollection>>(m_mcHits, Gaudi::DataHandle::Reader, this);
0072 }
0073 m_geoSvc = service("GeoSvc");
0074 if (!m_geoSvc) {
0075 error() << "Unable to locate Geometry Service. "
0076 << "Make sure you have GeoSvc and SimSvc in the right order in the configuration." << endmsg;
0077 return StatusCode::FAILURE;
0078 }
0079 return StatusCode::SUCCESS;
0080 }
0081
0082 StatusCode execute(const EventContext&) const override
0083 {
0084
0085 const auto& hits = *m_inputHitCollection.get();
0086
0087 auto& proto = *m_outputProtoClusters.createAndPut();
0088 auto& clusters = *m_outputClusters.createAndPut();
0089
0090
0091
0092
0093
0094
0095
0096
0097 std::vector<std::pair<uint32_t, edm4eic::CalorimeterHit>> the_hits;
0098 std::vector<std::pair<uint32_t, edm4eic::CalorimeterHit>> remaining_hits;
0099
0100 double max_dist = m_maxDistance.value() / mm;
0101 double min_energy = m_minModuleEdep.value() / GeV;
0102
0103 edm4eic::CalorimeterHit ref_hit;
0104 bool have_ref = false;
0105
0106 {
0107 uint32_t idx = 0;
0108 for (const auto& h : hits) {
0109 if (!have_ref || h.getEnergy() > ref_hit.getEnergy()) {
0110 ref_hit = h;
0111 have_ref = true;
0112 }
0113 the_hits.emplace_back(idx, h);
0114 idx += 1;
0115 }
0116 }
0117
0118 if (msgLevel(MSG::DEBUG)) {
0119 debug() << " max_dist = " << max_dist << endmsg;
0120 }
0121
0122 while (have_ref && ref_hit.getEnergy() > min_energy) {
0123
0124 std::vector<std::pair<uint32_t, edm4eic::CalorimeterHit>> cluster_hits;
0125
0126 for (const auto& [idx, h] : the_hits) {
0127 if (edm4hep::utils::magnitude(h.getPosition() - ref_hit.getPosition()) < max_dist) {
0128 cluster_hits.emplace_back(idx, h);
0129 } else {
0130 remaining_hits.emplace_back(idx, h);
0131 }
0132 }
0133
0134 double total_energy = std::accumulate(
0135 std::begin(cluster_hits), std::end(cluster_hits), 0.0,
0136 [](double t, const std::pair<uint32_t, edm4eic::CalorimeterHit>& h1) { return (t + h1.second.getEnergy()); });
0137
0138 if (msgLevel(MSG::DEBUG)) {
0139 debug() << " total_energy = " << total_energy << endmsg;
0140 debug() << " cluster size " << cluster_hits.size() << endmsg;
0141 }
0142 auto cl = clusters.create();
0143 cl.setNhits(cluster_hits.size());
0144 auto pcl = proto.create();
0145 for (const auto& [idx, h] : cluster_hits) {
0146 cl.setEnergy(cl.getEnergy() + h.getEnergy());
0147 cl.setPosition(cl.getPosition() + (h.getPosition() * h.getEnergy() / total_energy));
0148 pcl.addToHits(h);
0149 pcl.addToWeights(1);
0150 }
0151
0152
0153
0154
0155
0156
0157
0158 have_ref = false;
0159 if ((remaining_hits.size() > 5) && (clusters.size() < 10)) {
0160 for (const auto& [idx, h] : remaining_hits) {
0161 if (!have_ref || h.getEnergy() > ref_hit.getEnergy()) {
0162 ref_hit = h;
0163 have_ref = true;
0164 }
0165 }
0166
0167 std::swap(remaining_hits, the_hits);
0168 remaining_hits.clear();
0169 }
0170 }
0171 if (msgLevel(MSG::DEBUG)) {
0172 debug() << " clusters found: " << clusters.size() << endmsg;
0173 }
0174
0175 return StatusCode::SUCCESS;
0176 }
0177 };
0178
0179
0180 DECLARE_COMPONENT(SimpleClustering)
0181
0182 }