Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-03-28 07:45:42

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include "Acts/Seeding2/GbtsDataStorage.hpp"
0010 
0011 #include "Acts/Seeding2/GbtsGeometry.hpp"
0012 
0013 #include <algorithm>
0014 #include <cmath>
0015 #include <cstring>
0016 #include <numbers>
0017 #include <utility>
0018 
0019 namespace Acts::Experimental {
0020 
0021 GbtsEtaBin::GbtsEtaBin() {
0022   // TODO config
0023   vn.reserve(1000);
0024   vFirstEdge.reserve(1000);
0025   vNumEdges.reserve(1000);
0026 }
0027 
0028 void GbtsEtaBin::sortByPhi() {
0029   // TODO config
0030   std::array<std::vector<std::pair<float, const GbtsNode*>>, 32> phiBuckets;
0031 
0032   // TODO config
0033   const std::uint32_t nBuckets = 31;
0034 
0035   for (const GbtsNode* n : vn) {
0036     const auto bIdx = static_cast<std::uint32_t>(
0037         0.5 * nBuckets * (n->phi / std::numbers::pi_v<float> + 1.0f));
0038     phiBuckets[bIdx].emplace_back(n->phi, n);
0039   }
0040 
0041   for (auto& b : phiBuckets) {
0042     std::ranges::sort(b);
0043   }
0044 
0045   std::uint32_t idx = 0;
0046   for (const auto& b : phiBuckets) {
0047     for (const auto& p : b) {
0048       vn[idx] = p.second;
0049       ++idx;
0050     }
0051   }
0052 }
0053 
0054 void GbtsEtaBin::initializeNodes() {
0055   if (vn.empty()) {
0056     return;
0057   }
0058 
0059   params.resize(vn.size());
0060 
0061   vFirstEdge.resize(vn.size(), 0);
0062   vNumEdges.resize(vn.size(), 0);
0063   vIsConnected.resize(vn.size(), 0);
0064 
0065   std::ranges::transform(
0066       vn.begin(), vn.end(), params.begin(), [](const GbtsNode* pN) {
0067         return std::array<float, 5>{-100.0, 100.0, pN->phi, pN->r, pN->z};
0068       });
0069 
0070   const auto [minIter, maxIter] = std::ranges::minmax_element(
0071       vn, {}, [](const GbtsNode* s) { return s->r; });
0072   minRadius = (*minIter)->r;
0073   maxRadius = (*maxIter)->r;
0074 }
0075 
0076 void GbtsEtaBin::generatePhiIndexing(float dphi) {
0077   for (std::uint32_t nIdx = 0; nIdx < vn.size(); nIdx++) {
0078     const float phi = params[nIdx][2];
0079     if (phi <= std::numbers::pi_v<float> - dphi) {
0080       continue;
0081     }
0082     vPhiNodes.emplace_back(phi - 2 * std::numbers::pi_v<float>, nIdx);
0083   }
0084 
0085   for (std::uint32_t nIdx = 0; nIdx < vn.size(); nIdx++) {
0086     const float phi = params[nIdx][2];
0087     vPhiNodes.emplace_back(phi, nIdx);
0088   }
0089 
0090   for (std::uint32_t nIdx = 0; nIdx < vn.size(); nIdx++) {
0091     const float phi = params[nIdx][2];
0092     if (phi >= -std::numbers::pi_v<float> + dphi) {
0093       break;
0094     }
0095     vPhiNodes.emplace_back(phi + 2 * std::numbers::pi_v<float>, nIdx);
0096   }
0097 }
0098 
0099 GbtsNodeStorage::GbtsNodeStorage(std::shared_ptr<const GbtsGeometry> geometry,
0100                                  GbtsMlLookupTable mlLut)
0101     : m_geometry(std::move(geometry)), m_mlLut(std::move(mlLut)) {
0102   m_etaBins.resize(m_geometry->numBins());
0103 }
0104 
0105 std::uint32_t GbtsNodeStorage::loadPixelGraphNodes(
0106     const std::uint16_t layerIndex, const std::span<const GbtsNode> coll,
0107     const bool useMl, const float maxEndcapClusterWidth) {
0108   std::uint32_t nLoaded = 0;
0109 
0110   const GbtsLayer& pL = m_geometry->layerByIndex(layerIndex);
0111 
0112   const bool isBarrel = pL.layerDescription().type == GbtsLayerType::Barrel;
0113 
0114   for (const GbtsNode& node : coll) {
0115     const std::int32_t binIndex = pL.getEtaBin(node.z, node.r);
0116 
0117     if (binIndex == -1) {
0118       continue;
0119     }
0120 
0121     if (isBarrel) {
0122       m_etaBins.at(binIndex).vn.push_back(&node);
0123     } else {
0124       if (useMl) {
0125         const float clusterWidth = node.pcw;
0126         if (clusterWidth > maxEndcapClusterWidth) {
0127           continue;
0128         }
0129       }
0130       m_etaBins.at(binIndex).vn.push_back(&node);
0131     }
0132 
0133     nLoaded++;
0134   }
0135 
0136   return nLoaded;
0137 }
0138 
0139 std::uint32_t GbtsNodeStorage::loadStripGraphNodes(
0140     const std::uint16_t layerIndex, const std::span<const GbtsNode> coll) {
0141   std::uint32_t nLoaded = 0;
0142 
0143   const GbtsLayer& pL = m_geometry->layerByIndex(layerIndex);
0144 
0145   for (const GbtsNode& node : coll) {
0146     const std::int32_t binIndex = pL.getEtaBin(node.z, node.r);
0147 
0148     if (binIndex == -1) {
0149       continue;
0150     }
0151 
0152     m_etaBins.at(binIndex).vn.push_back(&node);
0153     nLoaded++;
0154   }
0155 
0156   return nLoaded;
0157 }
0158 
0159 std::uint32_t GbtsNodeStorage::numberOfNodes() const {
0160   std::uint32_t n = 0;
0161 
0162   for (const auto& b : m_etaBins) {
0163     n += b.vn.size();
0164   }
0165   return n;
0166 }
0167 
0168 void GbtsNodeStorage::sortByPhi() {
0169   for (GbtsEtaBin& b : m_etaBins) {
0170     b.sortByPhi();
0171   }
0172 }
0173 
0174 void GbtsNodeStorage::initializeNodes(const bool useMl) {
0175   for (GbtsEtaBin& b : m_etaBins) {
0176     b.initializeNodes();
0177     if (!b.vn.empty()) {
0178       b.layerId = m_geometry->layerIdByIndex((b.vn.front())->layer);
0179     }
0180   }
0181 
0182   if (!useMl) {
0183     return;
0184   }
0185 
0186   const std::uint32_t nL = m_geometry->numLayers();
0187 
0188   for (std::uint32_t layerIdx = 0; layerIdx < nL; ++layerIdx) {
0189     const GbtsLayer& layer = m_geometry->layerByIndex(layerIdx);
0190 
0191     // skip strips volumes: layers in range [1200X-1400X]
0192     if (layer.layerDescription().id < 20000) {
0193       continue;
0194     }
0195 
0196     const bool isBarrel =
0197         layer.layerDescription().type == GbtsLayerType::Barrel;
0198     if (!isBarrel) {
0199       continue;
0200     }
0201 
0202     // adjusting cuts on |cot(theta)| using pre-trained LUT loaded from file
0203 
0204     const auto lutSize = static_cast<std::uint32_t>(m_mlLut.size());
0205 
0206     const std::uint32_t nBins = layer.numOfBins();
0207 
0208     // loop over eta-bins in Layer
0209     for (std::uint32_t b = 0; b < nBins; ++b) {
0210       GbtsEtaBin& B = m_etaBins.at(layer.bins().at(b));
0211 
0212       if (B.empty()) {
0213         continue;
0214       }
0215 
0216       for (std::uint32_t nIdx = 0; nIdx < B.vn.size(); ++nIdx) {
0217         const float clusterWidth = B.vn[nIdx]->pcw;
0218         const float locPosY = B.vn[nIdx]->locPosY;
0219 
0220         // lut bin width is 0.05 mm, check if this is actually what we want with
0221         // float conversion
0222         const std::int32_t lutBinIdx =
0223             static_cast<std::uint32_t>(std::floor(20 * clusterWidth)) - 1;
0224 
0225         if (lutBinIdx >= static_cast<std::int32_t>(lutSize)) {
0226           continue;
0227         }
0228         if (lutBinIdx < 0) {
0229           // protect against negative index
0230           continue;
0231         }
0232 
0233         const std::array<float, 5> lutBin = m_mlLut[lutBinIdx];
0234 
0235         const float dist2border = 10.0f - std::abs(locPosY);
0236 
0237         float minTau = -100.0f;
0238         float maxTau = 100.0f;
0239 
0240         if (dist2border > 0.3f) {
0241           // far enough from the edge
0242           minTau = lutBin[1];
0243           maxTau = lutBin[2];
0244         } else {
0245           // possible cluster shortening at a module edge
0246           minTau = lutBin[3];
0247           maxTau = lutBin[4];
0248         }
0249 
0250         if (maxTau < 0) {
0251           // insufficient training data
0252           // use "no-cut" default
0253           maxTau = 100.0f;
0254         }
0255 
0256         B.params[nIdx][0] = minTau;
0257         B.params[nIdx][1] = maxTau;
0258       }
0259     }
0260   }
0261 }
0262 
0263 void GbtsNodeStorage::generatePhiIndexing(const float dphi) {
0264   for (GbtsEtaBin& b : m_etaBins) {
0265     b.generatePhiIndexing(dphi);
0266   }
0267 }
0268 
0269 }  // namespace Acts::Experimental