Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-05 08:17:34

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 #pragma once
0010 
0011 #include "Acts/EventData/SpacePointColumnProxy.hpp"
0012 #include "Acts/EventData/SpacePointContainer.hpp"
0013 #include "Acts/EventData/StripSpacePointCalibrationDetails.hpp"
0014 #include "Acts/EventData/Types.hpp"
0015 #include "Acts/Seeding/GbtsLayerDescription.hpp"
0016 #include "Acts/Seeding/detail/GbtsGraphTypes.hpp"
0017 
0018 #include <cassert>
0019 #include <cstdint>
0020 #include <memory>
0021 #include <optional>
0022 #include <span>
0023 #include <vector>
0024 
0025 namespace Acts::Experimental {
0026 
0027 class GraphBasedTrackSeeder;
0028 class GbtsGeometry;
0029 
0030 /// Storage for the GBTS graph nodes.
0031 ///
0032 /// Nodes go in one at a time through `insert`, which takes plain scalars so
0033 /// that a caller can fill the storage from its own space point EDM. `finalize`
0034 /// then orders the nodes by (eta bin, phi) into a space point container, with
0035 /// the derived per-node data in dynamic columns on that container.
0036 class GbtsNodeStorage final {
0037  public:
0038   /// Maximum `Config::phiSortBuckets`; sizes the fixed bucket array.
0039   static constexpr std::uint32_t kMaxPhiSortBuckets = 31;
0040 
0041   /// Filled storage is not relocatable: the column proxies point into the
0042   /// space point container held by value.
0043   GbtsNodeStorage(const GbtsNodeStorage&) = delete;
0044   GbtsNodeStorage(GbtsNodeStorage&&) = delete;
0045   GbtsNodeStorage& operator=(const GbtsNodeStorage&) = delete;
0046   GbtsNodeStorage& operator=(GbtsNodeStorage&&) = delete;
0047   ~GbtsNodeStorage() = default;
0048 
0049   //! [gbts insert]
0050   /// Insert a space point, deriving r and phi from the global position.
0051   /// @param index Index of the space point in the caller's own collection
0052   /// @param x Global x coordinate
0053   /// @param y Global y coordinate
0054   /// @param z Global z coordinate
0055   /// @param layerIndex Dense GBTS layer index
0056   /// @param clusterWidth Pixel cluster width
0057   /// @param localPositionY Local y cluster position
0058   /// @return The eta bin the node was placed in, or nullopt if it was rejected
0059   std::optional<std::uint32_t> insert(SpacePointIndex index, float x, float y,
0060                                       float z, std::uint32_t layerIndex,
0061                                       float clusterWidth = 0.f,
0062                                       float localPositionY = 0.f);
0063   //! [gbts insert]
0064 
0065   /// Insert a space point for callers that already have r and phi.
0066   /// @param index Index of the space point in the caller's own collection
0067   /// @param x Global x coordinate
0068   /// @param y Global y coordinate
0069   /// @param z Global z coordinate
0070   /// @param r Transverse distance from the beamline
0071   /// @param phi Azimuthal angle in the xy plane
0072   /// @param layerIndex Dense GBTS layer index
0073   /// @param clusterWidth Pixel cluster width
0074   /// @param localPositionY Local y cluster position
0075   /// @param strip Stereo pair the point was formed from, null for a pixel one
0076   /// @return The eta bin the node was placed in, or nullopt if it was rejected
0077   std::optional<std::uint32_t> insert(
0078       SpacePointIndex index, float x, float y, float z, float r, float phi,
0079       std::uint32_t layerIndex, float clusterWidth = 0.f,
0080       float localPositionY = 0.f,
0081       const OuterStripSpacePointCalibrationDetails* strip = nullptr);
0082 
0083   /// Insert a space point from an ACTS space point container.
0084   /// @param sp The space point to insert
0085   /// @param layerColumn Column holding the dense GBTS layer index
0086   /// @param clusterWidthColumn Column holding the pixel cluster width
0087   /// @param localPositionYColumn Column holding the local y cluster position
0088   /// @param strips Whether the container carries the stereo pairs
0089   /// @return The eta bin the node was placed in, or nullopt if it was rejected
0090   std::optional<std::uint32_t> insert(
0091       const ConstSpacePointProxy& sp,
0092       const ConstSpacePointColumnProxy<std::uint32_t>& layerColumn,
0093       const ConstSpacePointColumnProxy<float>& clusterWidthColumn,
0094       const ConstSpacePointColumnProxy<float>& localPositionYColumn,
0095       bool strips = false) {
0096     return insert(sp.index(), sp.x(), sp.y(), sp.z(), sp.r(), sp.phi(),
0097                   sp.extra(layerColumn), sp.extra(clusterWidthColumn),
0098                   sp.extra(localPositionYColumn),
0099                   strips ? &sp.outerStripCalibrationDetails() : nullptr);
0100   }
0101 
0102   /// Insert every space point of a container. A container carrying
0103   /// `SpacePointColumns::StripCalibrationDetails` has its stereo pairs taken
0104   /// with it, for the layers the configuration marks as strip layers.
0105   ///
0106   /// @param spacePoints The space points to insert
0107   /// @param layerColumn Column holding the dense GBTS layer index
0108   /// @param clusterWidthColumn Column holding the pixel cluster width
0109   /// @param localPositionYColumn Column holding the local y cluster position
0110   void extend(const SpacePointContainer& spacePoints,
0111               const ConstSpacePointColumnProxy<std::uint32_t>& layerColumn,
0112               const ConstSpacePointColumnProxy<float>& clusterWidthColumn,
0113               const ConstSpacePointColumnProxy<float>& localPositionYColumn);
0114 
0115   /// Sort the nodes by (eta bin, phi) and build the derived per-node data.
0116   /// Must be called once after all inserts and before the storage is read.
0117   void finalize();
0118 
0119   /// Get the total number of nodes
0120   /// @return Total number of nodes
0121   std::uint32_t numberOfNodes() const { return m_nodes.size(); }
0122 
0123   /// Map a node index back to the index the caller used when inserting it.
0124   /// @param node Node index
0125   /// @return The caller's space point index
0126   SpacePointIndex spacePointIndex(SpacePointIndex node) const {
0127     return m_nodes.copiedFromIndexColumn()[node];
0128   }
0129 
0130   /// Whether any node carries a stereo pair, i.e. whether the graph has a
0131   /// strip path to take. A caller that fed strip space points in can check
0132   /// here that their pairs arrived.
0133   /// @return Whether there are any
0134   bool hasStrips() const { return !m_strips.empty(); }
0135 
0136  private:
0137   // Only the seeder builds one and walks the graph inside it.
0138   friend class GraphBasedTrackSeeder;
0139 
0140   /// Configuration for node loading.
0141   struct Config {
0142     /// Enable the cluster width cuts: wide endcap rejection and tau narrowing.
0143     bool useClusterWidthCuts = false;
0144     /// Maximum endcap cluster width, applied to pixel endcap nodes when
0145     /// the cluster width cuts are enabled.
0146     float maxEndcapClusterWidth = 0.35f;
0147     /// Half-length in local y of a pixel module, against which the distance of
0148     /// a cluster to the module edge is measured.
0149     float moduleHalfLengthY = 10.f;
0150     /// Distance to the module edge below which a cluster may be shortened,
0151     /// which switches to the tau lookup table's near-edge bounds.
0152     float moduleEdgeTolerance = 0.3f;
0153     /// Width of the phi slice used to build the phi indexing.
0154     float phiSliceWidth = 0.f;
0155     /// Multiples of `phiSliceWidth` duplicated either side of the wrap-around,
0156     /// so a sliding window never has to wrap.
0157     float phiIndexMargin = 1.5f;
0158     /// Buckets used to sort a bin by phi, at most `kMaxPhiSortBuckets`.
0159     std::uint32_t phiSortBuckets = 31;
0160     /// Cluster width covered by one bin of the tau lookup table.
0161     float tauLutBinWidth = 0.05f;
0162   };
0163 
0164   /// @param config Node loading configuration
0165   /// @param geometry Shared pointer to GBTS geometry
0166   /// @param tauLut Per-cluster-width tau bounds
0167   GbtsNodeStorage(const Config& config,
0168                   std::shared_ptr<const GbtsGeometry> geometry,
0169                   detail::GbtsTauLookupTable tauLut);
0170 
0171   /// Get eta bin info by index
0172   /// @param idx Eta bin index
0173   /// @return Reference to the eta bin info
0174   const detail::GbtsEtaBinInfo& etaBin(std::uint32_t idx) const {
0175     return m_etaBins.at(idx < m_etaBins.size() ? idx : idx - 1);
0176   }
0177 
0178   /// Read-only view of the node positions and layers
0179   /// @return Node view
0180   detail::GbtsNodeView nodeView() const {
0181     return detail::GbtsNodeView{m_nodes.xyzrColumn().data(), m_layers, m_strips,
0182                                 m_stripIndex};
0183   }
0184 
0185   /// Per-node graph parameters, indexed by node index
0186   /// @return Span over the node parameters
0187   std::span<const detail::GbtsNodeParams> nodeParams() const {
0188     return m_paramsColumn->data();
0189   }
0190 
0191   /// Per-node graph bookkeeping, indexed by node index
0192   /// @return Mutable span over the node edge info
0193   std::span<detail::GbtsNodeEdgeInfo> nodeEdgeInfo() {
0194     return m_edgeInfoColumn->data();
0195   }
0196 
0197   /// Per-node graph bookkeeping, indexed by node index
0198   /// @return Span over the node edge info
0199   std::span<const detail::GbtsNodeEdgeInfo> nodeEdgeInfo() const {
0200     return m_edgeInfoColumn->data();
0201   }
0202 
0203   /// The stereo pair of a strip node, in the form the calibration reads.
0204   ///
0205   /// @pre The node carries one, i.e. its eta bin is not a pixel bin.
0206   ///
0207   /// @param node Node index
0208   /// @return The pair
0209   const OuterStripSpacePointCalibrationDetailsDerived& strip(
0210       SpacePointIndex node) const {
0211     // A strip layer fed from a container without the pairs leaves the node
0212     // without one while its bin still says it is a strip bin.
0213     assert(node < m_stripIndex.size() &&
0214            m_stripIndex[node] != detail::kNoStrip &&
0215            "node carries no stereo pair");
0216     return m_strips[m_stripIndex[node]];
0217   }
0218 
0219   /// A node as recorded by `insert`, before sorting.
0220   struct StagedNode {
0221     SpacePointIndex spacePointIndex{};
0222     float x{};
0223     float y{};
0224     float z{};
0225     float r{};
0226     float phi{};
0227     float clusterWidth{};
0228     float localPositionY{};
0229     std::uint16_t layer{};
0230     /// Index into the staged stereo pairs, `detail::kNoStrip` for a pixel node
0231     std::uint32_t strip{detail::kNoStrip};
0232   };
0233 
0234   /// Sort a single bin's staged nodes by phi.
0235   /// @param staged Staged node indices of the bin
0236   /// @return The staged indices in phi order
0237   std::vector<std::uint32_t> sortBinByPhi(
0238       const std::vector<std::uint32_t>& staged) const;
0239 
0240   /// Narrow a node's tau window using the tau lookup table.
0241   /// @param staged The staged node
0242   /// @param params The node parameters to narrow
0243   void applyTauCuts(const StagedNode& staged,
0244                     detail::GbtsNodeParams& params) const;
0245 
0246   /// Build the wrap-around aware phi indexing for every bin.
0247   /// @param dphi Width of the phi margin duplicated at the wrap-around
0248   void generatePhiIndexing(float dphi);
0249 
0250   Config m_cfg;
0251 
0252   std::shared_ptr<const GbtsGeometry> m_geometry;
0253 
0254   detail::GbtsTauLookupTable m_tauLut;
0255 
0256   /// Nodes ordered by (eta bin, phi). Carries the caller's index and the packed
0257   /// (x, y, z, r) position, plus the derived data as dynamic columns.
0258   SpacePointContainer m_nodes;
0259 
0260   std::optional<MutableSpacePointColumnProxy<detail::GbtsNodeParams>>
0261       m_paramsColumn;
0262   std::optional<MutableSpacePointColumnProxy<detail::GbtsNodeEdgeInfo>>
0263       m_edgeInfoColumn;
0264 
0265   /// Dense layer index per node, in node order.
0266   std::vector<std::uint16_t> m_layers;
0267 
0268   /// Stereo pairs of the strip nodes, in node order and compacted: too large
0269   /// to carry for every node of a mostly pixel detector.
0270   std::vector<OuterStripSpacePointCalibrationDetailsDerived> m_strips;
0271   /// Index into `m_strips` per node, empty when nothing carries a pair.
0272   std::vector<std::uint32_t> m_stripIndex;
0273 
0274   std::vector<detail::GbtsEtaBinInfo> m_etaBins;
0275 
0276   /// Nodes as inserted, before sorting.
0277   std::vector<StagedNode> m_staged;
0278   /// Staged node indices per eta bin.
0279   std::vector<std::vector<std::uint32_t>> m_stagedPerBin;
0280 };
0281 
0282 }  // namespace Acts::Experimental