File indexing completed on 2025-07-01 07:56:24
0001
0002
0003
0004 #include <DD4hep/Handle.h>
0005 #include <DD4hep/IDDescriptor.h>
0006 #include <DD4hep/Objects.h>
0007 #include <DD4hep/Readout.h>
0008 #include <DD4hep/detail/SegmentationsInterna.h>
0009 #include <DDSegmentation/BitFieldCoder.h>
0010 #include <JANA/JException.h>
0011 #include <Math/GenVector/Cartesian3D.h>
0012 #include <Math/GenVector/DisplacementVector3D.h>
0013 #include <ROOT/RVec.hxx>
0014 #include <algorithms/geo.h>
0015 #include <edm4eic/Cov3f.h>
0016 #include <edm4hep/Vector2f.h>
0017 #include <fmt/core.h>
0018 #include <cstddef>
0019 #include <gsl/pointers>
0020
0021 #include "algorithms/fardetectors/FarDetectorTrackerCluster.h"
0022 #include "algorithms/fardetectors/FarDetectorTrackerClusterConfig.h"
0023
0024 namespace eicrecon {
0025
0026 void FarDetectorTrackerCluster::init() {
0027
0028 m_detector = algorithms::GeoSvc::instance().detector();
0029
0030 if (m_cfg.readout.empty()) {
0031 throw JException("Readout is empty");
0032 }
0033 try {
0034 m_seg = m_detector->readout(m_cfg.readout).segmentation();
0035 m_id_dec = m_detector->readout(m_cfg.readout).idSpec().decoder();
0036 if (!m_cfg.x_field.empty()) {
0037 m_x_idx = m_id_dec->index(m_cfg.x_field);
0038 debug("Find layer field {}, index = {}", m_cfg.x_field, m_x_idx);
0039 }
0040 if (!m_cfg.y_field.empty()) {
0041 m_y_idx = m_id_dec->index(m_cfg.y_field);
0042 debug("Find layer field {}, index = {}", m_cfg.y_field, m_y_idx);
0043 }
0044 } catch (...) {
0045 error("Failed to load ID decoder for {}", m_cfg.readout);
0046 throw JException("Failed to load ID decoder");
0047 }
0048 }
0049
0050 void FarDetectorTrackerCluster::process(const FarDetectorTrackerCluster::Input& input,
0051 const FarDetectorTrackerCluster::Output& output) const {
0052
0053 const auto [inputHitsCollections] = input;
0054 auto [outputClustersCollection] = output;
0055
0056
0057
0058 for (std::size_t i = 0; i < inputHitsCollections.size(); i++) {
0059 auto inputHits = inputHitsCollections[i];
0060 if (inputHits->empty()) {
0061 continue;
0062 }
0063 auto outputClusters = outputClustersCollection[i];
0064
0065
0066 ClusterHits(*inputHits, *outputClusters);
0067 }
0068 }
0069
0070
0071 void FarDetectorTrackerCluster::ClusterHits(
0072 const edm4eic::TrackerHitCollection& inputHits,
0073 edm4eic::Measurement2DCollection& outputClusters) const {
0074
0075 ROOT::VecOps::RVec<unsigned long> id;
0076 ROOT::VecOps::RVec<int> x;
0077 ROOT::VecOps::RVec<int> y;
0078 ROOT::VecOps::RVec<float> e;
0079 ROOT::VecOps::RVec<float> t;
0080
0081
0082 for (const auto& hit : inputHits) {
0083 auto cellID = hit.getCellID();
0084 id.push_back(cellID);
0085 x.push_back(m_id_dec->get(cellID, m_x_idx));
0086 y.push_back(m_id_dec->get(cellID, m_y_idx));
0087 e.push_back(hit.getEdep());
0088 t.push_back(hit.getTime());
0089 }
0090
0091
0092 ROOT::VecOps::RVec<bool> available(id.size(), 1);
0093 auto indices = Enumerate(id);
0094
0095
0096 while (ROOT::VecOps::Any(available)) {
0097
0098 dd4hep::Position localPos = {0, 0, 0};
0099 float weightSum = 0;
0100
0101 float t0 = 0;
0102 auto maxIndex = ROOT::VecOps::ArgMax(e * available);
0103
0104 available[maxIndex] = 0;
0105
0106 ROOT::VecOps::RVec<unsigned long> clusterList = {maxIndex};
0107 ROOT::VecOps::RVec<float> clusterT;
0108 ROOT::VecOps::RVec<float> clusterW;
0109
0110
0111 auto cluster = outputClusters->create();
0112
0113
0114 while (!clusterList.empty()) {
0115
0116
0117 auto index = clusterList[0];
0118
0119
0120 auto filter = available * (abs(x - x[index]) <= 1) * (abs(y - y[index]) <= 1) *
0121 (abs(t - t[index]) < m_cfg.hit_time_limit);
0122
0123
0124 clusterList = Concatenate(clusterList, indices[filter]);
0125
0126
0127 available = available * (!filter);
0128
0129
0130 clusterList.erase(clusterList.begin());
0131
0132
0133 auto pos = m_seg->position(id[index]);
0134
0135
0136 float weight =
0137 e[index];
0138 weightSum += weight;
0139 localPos += pos * weight;
0140
0141
0142 clusterT.push_back(t[index]);
0143
0144
0145 cluster.addToHits(inputHits[index]);
0146 clusterW.push_back(e[index]);
0147 }
0148
0149
0150 localPos /= weightSum;
0151
0152 edm4hep::Vector2f xyPos = {static_cast<float>(localPos.x()), static_cast<float>(localPos.y())};
0153
0154
0155 t0 = Mean(clusterT);
0156
0157
0158 clusterW /= weightSum;
0159
0160 for (auto& w : clusterW) {
0161 cluster.addToWeights(w);
0162 }
0163
0164 edm4eic::Cov3f covariance;
0165
0166 cluster.setSurface(id[maxIndex]);
0167 cluster.setLoc(xyPos);
0168 cluster.setTime(t0);
0169 cluster.setCovariance(covariance);
0170 }
0171 }
0172
0173 }