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