Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-06-05 08:29:38

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2024 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 http://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include "Acts/EventData/SourceLink.hpp"
0012 #include "Acts/Surfaces/Surface.hpp"
0013 #include "Acts/Utilities/Delegate.hpp"
0014 
0015 namespace Acts::Experimental {
0016 
0017 /// @brief Seeding algorigthm that extracts
0018 /// the IP parameters and sorts the source links
0019 /// into possible track candidates
0020 ///
0021 /// The algorithm to convert the given source links
0022 /// into seeds -- pairs of IP parameters and the corresponding
0023 /// source links -- as follows: First the source links
0024 /// are sorted into a user-defined grid. Then, iteration over the source links
0025 /// is performed. If a source link is attached to a surface that is
0026 /// in the first tracking layer, as defined by the user, the IP parameters
0027 /// are estimated and the tracking layers are intersected to construct the
0028 /// core of the "Path". The source links in the subsequent layers are then
0029 /// added to the seed if they lie within the path width of the core.
0030 /// Both the list of source links and the IP parameters are stored in the seed
0031 /// struct.
0032 ///
0033 /// @tparam axis_t Type of the axis to bin
0034 /// the source links
0035 ///
0036 /// @note The algorithm is designed to be used in the
0037 /// context of a telescope-style geometry. The surfaces
0038 /// are assumed to be planar.
0039 ///
0040 /// @note Handling of the rotated surfaces has to happen
0041 /// in the user-defined delegate functions.
0042 
0043 template <typename grid_t>
0044 class PathSeeder {
0045  public:
0046   using GridType = grid_t;
0047 
0048   /// @brief The seed struct
0049   ///
0050   /// The seed struct contains the IP parameters
0051   /// and the source links that are associated with
0052   /// the seed.
0053   struct Seed {
0054     /// The IP momentum magnitude
0055     ActsScalar ipP;
0056 
0057     /// The IP momentum direction
0058     Vector3 ipDir;
0059 
0060     /// The IP vertex position
0061     Vector3 ipVertex;
0062 
0063     /// The source links associated with the seed
0064     std::vector<SourceLink> sourceLinks;
0065 
0066     Seed() = delete;
0067     Seed(ActsScalar ipPmag, Vector3 ipPdir, Vector3 ipPos,
0068          std::vector<SourceLink> sls)
0069         : ipP(ipPmag),
0070           ipDir(std::move(ipPdir)),
0071           ipVertex(std::move(ipPos)),
0072           sourceLinks(std::move(sls)) {};
0073   };
0074 
0075   /// @brief Delegate to provide the relevant grid
0076   /// filled with source links for the given geometry
0077   /// member
0078   ///
0079   /// @arg The geometry identifier to use
0080   ///
0081   /// @return The grid filled with source links
0082   using SourceLinkGridLookup = Delegate<GridType(const GeometryIdentifier&)>;
0083 
0084   /// @brief Delegate to estimate the IP parameters
0085   /// and the momentum direction at the first tracking layer
0086   ///
0087   /// @arg The geometry context to use
0088   /// @arg The global position of the pivot source link
0089   ///
0090   /// @return Particle charge, the IP momentum magnitude, the IP vertex position,
0091   /// the IP momentum direction, the momentum direction at the
0092   /// first tracking layer
0093   using TrackEstimator =
0094       Delegate<std::tuple<ActsScalar, ActsScalar, Vector3, Vector3, Vector3>(
0095           const GeometryContext&, const Vector3&)>;
0096 
0097   /// @brief Delegate to transform the source link to the
0098   /// appropriate global frame.
0099   ///
0100   /// @arg The geometry context to use
0101   /// @arg The source link to calibrate
0102   ///
0103   /// @return The global position of the source link measurement
0104   using SourceLinkCalibrator =
0105       Delegate<Vector3(const GeometryContext&, const SourceLink&)>;
0106 
0107   /// @brief Delegate to find the intersections for the given pivot
0108   /// source link
0109   ///
0110   /// @arg The geometry context to use
0111   /// @arg The global position of the pivot source link
0112   /// @arg The momentum direction of the pivot source link
0113   /// at the first tracking layer
0114   /// @arg The IP momentum magnitude
0115   /// @arg The particle charge
0116   using IntersectionLookup =
0117       Delegate<std::vector<std::pair<GeometryIdentifier, Vector3>>(
0118           const GeometryContext&, const Vector3&, const Vector3&,
0119           const ActsScalar&, const ActsScalar&)>;
0120 
0121   /// @brief Delegate to provide the path width around
0122   /// the intersection point to pull the source links
0123   /// from the grid
0124   ///
0125   /// @arg The geometry context to use
0126   /// @arg The geometry identifier to use if the
0127   /// path width is varied across different tracking layers
0128   ///
0129   /// @return The path width in the bin0 and bin1 direction
0130   /// defined with respect to the surface normal
0131   using PathWidthLookup = Delegate<std::pair<ActsScalar, ActsScalar>(
0132       const GeometryContext&, const GeometryIdentifier&)>;
0133 
0134   /// @brief The nested configuration struct
0135   struct Config {
0136     /// Binned SourceLink provider
0137     SourceLinkGridLookup sourceLinkGridLookup;
0138     /// Parameters estimator
0139     TrackEstimator trackEstimator;
0140     /// SourceLink calibrator
0141     SourceLinkCalibrator sourceLinkCalibrator;
0142     /// Intersection finder
0143     IntersectionLookup intersectionFinder;
0144     /// Path width provider
0145     PathWidthLookup pathWidthProvider;
0146     /// First layer extent
0147     Extent firstLayerExtent;
0148     /// Direction of the telescope extent
0149     BinningValue orientation = BinningValue::binX;
0150   };
0151 
0152   /// @brief Constructor
0153   PathSeeder(const Config& config) : m_cfg(std::move(config)) {};
0154 
0155   /// @brief Destructor
0156   ~PathSeeder() = default;
0157 
0158   /// @brief Extract the IP parameters and
0159   /// sort the source links into the seeds
0160   ///
0161   /// @param gctx The geometry context
0162   /// @param sourceLinks The source links to seed
0163   ///
0164   /// @return The vector of seeds
0165   std::vector<Seed> getSeeds(const GeometryContext& gctx,
0166                              const std::vector<SourceLink>& sourceLinks) const {
0167     // Get plane of the telescope
0168     // sensitive surfaces
0169     int bin0 = static_cast<int>(BinningValue::binX);
0170     int bin1 = static_cast<int>(BinningValue::binY);
0171     if (m_cfg.orientation == BinningValue::binX) {
0172       bin0 = static_cast<int>(BinningValue::binY);
0173       bin1 = static_cast<int>(BinningValue::binZ);
0174     } else if (m_cfg.orientation == BinningValue::binY) {
0175       bin0 = static_cast<int>(BinningValue::binX);
0176       bin1 = static_cast<int>(BinningValue::binZ);
0177     }
0178 
0179     // Create the seeds
0180     std::vector<Seed> seeds;
0181     for (const auto& sl : sourceLinks) {
0182       Vector3 globalPos = m_cfg.sourceLinkCalibrator(gctx, sl);
0183 
0184       // Check if the hit is in the
0185       // first tracking layer
0186       if (!m_cfg.firstLayerExtent.contains(globalPos)) {
0187         continue;
0188       }
0189 
0190       // Get the IP parameters
0191       auto [q, ipP, ipVertex, ipDir, flDir] =
0192           m_cfg.trackEstimator(gctx, globalPos);
0193 
0194       // Intersect with the surfaces
0195       std::vector<std::pair<GeometryIdentifier, Vector3>> intersections =
0196           m_cfg.intersectionFinder(gctx, globalPos, flDir, ipP, q);
0197 
0198       // Continue if no intersections
0199       if (intersections.empty()) {
0200         continue;
0201       }
0202       // Vector to store the source links
0203       std::vector<SourceLink> seedSourceLinks;
0204 
0205       // Store the pivot source link
0206       seedSourceLinks.push_back(sl);
0207 
0208       // Iterate over the intersections
0209       // and get the source links
0210       // in the subsequent layers
0211       for (auto& [geoId, refPoint] : intersections) {
0212         // Get the path width
0213         auto [pathWidth0, pathWidth1] = m_cfg.pathWidthProvider(gctx, geoId);
0214 
0215         // Get the bounds of the path
0216         ActsScalar top0 = refPoint[bin0] + pathWidth0;
0217         ActsScalar bot0 = refPoint[bin0] - pathWidth0;
0218         ActsScalar top1 = refPoint[bin1] + pathWidth1;
0219         ActsScalar bot1 = refPoint[bin1] - pathWidth1;
0220 
0221         // Get the lookup table for the source links
0222         auto grid = m_cfg.sourceLinkGridLookup(geoId);
0223 
0224         // Get the range of bins to search for source links
0225         auto botLeftBin = grid.localBinsFromPosition(Vector2(bot0, bot1));
0226         auto topRightBin = grid.localBinsFromPosition(Vector2(top0, top1));
0227 
0228         // Get the source links from the lookup table
0229         // by iterating over the bin ranges
0230         auto currentBin = botLeftBin;
0231         while (currentBin.at(1) <= topRightBin.at(1)) {
0232           while (currentBin.at(0) <= topRightBin.at(0)) {
0233             auto sourceLinksToAdd = grid.atLocalBins(currentBin);
0234 
0235             seedSourceLinks.insert(seedSourceLinks.end(),
0236                                    sourceLinksToAdd.begin(),
0237                                    sourceLinksToAdd.end());
0238             currentBin.at(0)++;
0239           }
0240           currentBin.at(1)++;
0241           currentBin.at(0) = botLeftBin.at(0);
0242         }
0243       }
0244 
0245       // Store the IP parameters and
0246       // add the source links to the seed
0247       Seed seed{ipP, ipDir, ipVertex, seedSourceLinks};
0248 
0249       // Add the seed to the list
0250       seeds.push_back(seed);
0251     }
0252     return seeds;
0253   };
0254 
0255  private:
0256   Config m_cfg;
0257 };
0258 
0259 }  // namespace Acts::Experimental