File indexing completed on 2024-09-27 07:02:58
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/VolumeManager.h>
0009 #include <DD4hep/detail/SegmentationsInterna.h>
0010 #include <DDSegmentation/BitFieldCoder.h>
0011 #include <Evaluator/DD4hepUnits.h>
0012 #include <JANA/JException.h>
0013 #include <Math/GenVector/Cartesian3D.h>
0014 #include <Math/GenVector/DisplacementVector3D.h>
0015 #include <ROOT/RVec.hxx>
0016 #include <algorithms/geo.h>
0017 #include <edm4hep/Vector3d.h>
0018 #include <fmt/core.h>
0019 #include <gsl/pointers>
0020 #include <sys/types.h>
0021
0022 #include "algorithms/fardetectors/FarDetectorTrackerCluster.h"
0023 #include "algorithms/fardetectors/FarDetectorTrackerClusterConfig.h"
0024
0025 namespace eicrecon {
0026
0027 void FarDetectorTrackerCluster::init() {
0028
0029 m_detector = algorithms::GeoSvc::instance().detector();
0030 m_cellid_converter = algorithms::GeoSvc::instance().cellIDPositionConverter();
0031
0032 if (m_cfg.readout.empty()) {
0033 throw JException("Readout is empty");
0034 }
0035 try {
0036 m_seg = m_detector->readout(m_cfg.readout).segmentation();
0037 m_id_dec = m_detector->readout(m_cfg.readout).idSpec().decoder();
0038 if (!m_cfg.x_field.empty()) {
0039 m_x_idx = m_id_dec->index(m_cfg.x_field);
0040 debug("Find layer field {}, index = {}", m_cfg.x_field, m_x_idx);
0041 }
0042 if (!m_cfg.y_field.empty()) {
0043 m_y_idx = m_id_dec->index(m_cfg.y_field);
0044 debug("Find layer field {}, index = {}", m_cfg.y_field, m_y_idx);
0045 }
0046 } catch (...) {
0047 error("Failed to load ID decoder for {}", m_cfg.readout);
0048 throw JException("Failed to load ID decoder");
0049 }
0050 }
0051
0052 void FarDetectorTrackerCluster::process(const FarDetectorTrackerCluster::Input& input,
0053 const FarDetectorTrackerCluster::Output& output) const {
0054
0055 const auto [inputHitsCollections] = input;
0056 auto [outputClustersCollection] = output;
0057
0058
0059
0060 for (size_t i = 0; i < inputHitsCollections.size(); i++) {
0061 auto inputHits = inputHitsCollections[i];
0062 if (inputHits->size() == 0)
0063 continue;
0064 auto outputClusters = outputClustersCollection[i];
0065
0066
0067 auto clusters = ClusterHits(*inputHits);
0068
0069
0070 ConvertClusters(clusters, *outputClusters);
0071 }
0072 }
0073
0074
0075 std::vector<FDTrackerCluster>
0076 FarDetectorTrackerCluster::ClusterHits(const edm4eic::RawTrackerHitCollection& inputHits) const {
0077
0078 std::vector<FDTrackerCluster> clusters;
0079
0080 ROOT::VecOps::RVec<unsigned long> id;
0081 ROOT::VecOps::RVec<int> x;
0082 ROOT::VecOps::RVec<int> y;
0083 ROOT::VecOps::RVec<float> e;
0084 ROOT::VecOps::RVec<float> t;
0085
0086
0087 for (const auto& hit : inputHits) {
0088 auto cellID = hit.getCellID();
0089 id.push_back(cellID);
0090 x.push_back(m_id_dec->get(cellID, m_x_idx));
0091 y.push_back(m_id_dec->get(cellID, m_y_idx));
0092 e.push_back(hit.getCharge());
0093 t.push_back(hit.getTimeStamp());
0094 }
0095
0096
0097 ROOT::VecOps::RVec<bool> available(id.size(), 1);
0098 auto indices = Enumerate(id);
0099
0100
0101 while (ROOT::VecOps::Any(available)) {
0102
0103 dd4hep::Position localPos = {0, 0, 0};
0104 float weightSum = 0;
0105
0106 float esum = 0;
0107 float t0 = 0;
0108 float tError = 0;
0109 auto maxIndex = ROOT::VecOps::ArgMax(e * available);
0110
0111 available[maxIndex] = 0;
0112
0113 ROOT::VecOps::RVec<unsigned long> clusterList = {maxIndex};
0114 ROOT::VecOps::RVec<float> clusterT;
0115 std::vector<podio::ObjectID> clusterHits;
0116
0117
0118 while (clusterList.size()) {
0119
0120
0121 auto index = clusterList[0];
0122
0123
0124 auto filter = available * (abs(x - x[index]) <= 1) * (abs(y - y[index]) <= 1) *
0125 (abs(t - t[index]) < m_cfg.hit_time_limit);
0126
0127
0128 clusterList = Concatenate(clusterList, indices[filter]);
0129
0130
0131 available = available * (!filter);
0132
0133
0134 clusterList.erase(clusterList.begin());
0135
0136
0137 clusterHits.push_back((inputHits)[index].getObjectID());
0138
0139
0140 auto hitE = e[index];
0141 esum += hitE;
0142
0143 auto pos = m_seg->position(id[index]);
0144
0145
0146 float weight = hitE;
0147 weightSum += weight;
0148 localPos += pos * weight;
0149
0150
0151 clusterT.push_back(t[index]);
0152 }
0153
0154
0155 localPos /= weightSum;
0156
0157
0158 t0 = Mean(clusterT);
0159 tError = StdDev(clusterT);
0160
0161
0162 clusters.push_back(FDTrackerCluster{.cellID = id[maxIndex],
0163 .x = localPos.x(),
0164 .y = localPos.y(),
0165 .energy = esum,
0166 .time = t0,
0167 .timeError = tError,
0168 .rawHits = clusterHits});
0169 }
0170
0171 return clusters;
0172 }
0173
0174
0175 void FarDetectorTrackerCluster::ConvertClusters(
0176 const std::vector<FDTrackerCluster>& clusters,
0177 edm4hep::TrackerHitCollection& outputClusters) const {
0178
0179
0180 const dd4hep::VolumeManagerContext* context = m_cellid_converter->findContext(clusters[0].cellID);
0181
0182 for (auto cluster : clusters) {
0183 auto hitPos = outputClusters.create();
0184
0185 auto globalPos = context->localToWorld({cluster.x, cluster.y, 0});
0186
0187
0188 hitPos.setCellID(cluster.cellID);
0189 hitPos.setPosition(edm4hep::Vector3d(globalPos.x() / dd4hep::mm, globalPos.y() / dd4hep::mm,
0190 globalPos.z() / dd4hep::mm));
0191 hitPos.setEDep(cluster.energy);
0192 hitPos.setTime(cluster.time);
0193
0194
0195 for (auto hit : cluster.rawHits) {
0196 hitPos.addToRawHits(hit);
0197 }
0198 }
0199 }
0200
0201 }