File indexing completed on 2024-06-01 07:06:45
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 <JANA/JException.h>
0012 #include <Math/GenVector/Cartesian3D.h>
0013 #include <Math/GenVector/DisplacementVector3D.h>
0014 #include <ROOT/RVec.hxx>
0015 #include <algorithms/geo.h>
0016 #include <edm4hep/Vector3d.h>
0017 #include <fmt/core.h>
0018 #include <sys/types.h>
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(std::shared_ptr<spdlog::logger>& log) {
0027
0028 m_log = log;
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 m_log->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 m_log->debug("Find layer field {}, index = {}", m_cfg.y_field, m_y_idx);
0045 }
0046 } catch (...) {
0047 m_log->error("Failed to load ID decoder for {}", m_cfg.readout);
0048 throw JException("Failed to load ID decoder");
0049 }
0050
0051 }
0052
0053 void FarDetectorTrackerCluster::process(
0054 const FarDetectorTrackerCluster::Input& input,
0055 const FarDetectorTrackerCluster::Output& output) const {
0056
0057 const auto [inputHitsCollections] = input;
0058 auto [outputClustersCollection] = output;
0059
0060
0061 for(size_t i=0; i<inputHitsCollections.size(); i++){
0062 auto inputHits = inputHitsCollections[i];
0063 if(inputHits->size() == 0) continue;
0064 auto outputClusters = outputClustersCollection[i];
0065
0066
0067 auto clusters = ClusterHits(*inputHits);
0068
0069
0070 ConvertClusters(clusters, *outputClusters);
0071
0072 }
0073 }
0074
0075
0076 std::vector<FDTrackerCluster> 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)*(abs(t-t[index])<m_cfg.hit_time_limit);
0125
0126
0127 clusterList = Concatenate(clusterList,indices[filter]);
0128
0129
0130 available = available*(!filter);
0131
0132
0133 clusterList.erase(clusterList.begin());
0134
0135
0136 clusterHits.push_back((inputHits)[index].getObjectID());
0137
0138
0139 auto hitE = e[index];
0140 esum += hitE;
0141
0142 auto pos = m_seg->position(id[index]);
0143
0144
0145 float weight = hitE;
0146 weightSum += weight;
0147 localPos += pos*weight;
0148
0149
0150 clusterT.push_back(t[index]);
0151
0152 }
0153
0154
0155 localPos/=weightSum;
0156
0157
0158 t0 = Mean(clusterT);
0159 tError = StdDev(clusterT);
0160
0161
0162 clusters.push_back(FDTrackerCluster{
0163 .cellID = id[maxIndex],
0164 .x = localPos.x(),
0165 .y = localPos.y(),
0166 .energy = esum,
0167 .time = t0,
0168 .timeError = tError,
0169 .rawHits = clusterHits
0170 });
0171
0172
0173 }
0174
0175 return clusters;
0176
0177 }
0178
0179
0180 void FarDetectorTrackerCluster::ConvertClusters(const std::vector<FDTrackerCluster>& clusters, edm4hep::TrackerHitCollection& outputClusters) const {
0181
0182
0183 const dd4hep::VolumeManagerContext* context = m_cellid_converter->findContext(clusters[0].cellID);
0184
0185 for(auto cluster: clusters){
0186 auto hitPos = outputClusters.create();
0187
0188 auto globalPos = context->localToWorld({cluster.x,cluster.y,0});
0189
0190
0191 hitPos.setCellID (cluster.cellID);
0192 hitPos.setPosition(edm4hep::Vector3d(globalPos.x()/dd4hep::mm,globalPos.y()/dd4hep::mm,globalPos.z()/dd4hep::mm));
0193 hitPos.setEDep (cluster.energy);
0194 hitPos.setTime (cluster.time);
0195
0196
0197 for(auto hit: cluster.rawHits){
0198 hitPos.addToRawHits(hit);
0199 }
0200
0201 }
0202
0203 }
0204
0205
0206 }