Back to home page

EIC code displayed by LXR

 
 

    


Warning, file /include/Acts/Detector/detail/IndexedGridFiller.hpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2023-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/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Common.hpp"
0013 #include "Acts/Detector/detail/ReferenceGenerators.hpp"
0014 #include "Acts/Geometry/GeometryContext.hpp"
0015 #include "Acts/Geometry/Polyhedron.hpp"
0016 #include "Acts/Navigation/InternalNavigation.hpp"
0017 #include "Acts/Utilities/Delegate.hpp"
0018 #include "Acts/Utilities/Enumerate.hpp"
0019 #include "Acts/Utilities/GridAccessHelpers.hpp"
0020 #include "Acts/Utilities/IAxis.hpp"
0021 #include "Acts/Utilities/Logger.hpp"
0022 
0023 #include <algorithm>
0024 #include <array>
0025 #include <set>
0026 #include <string>
0027 #include <vector>
0028 
0029 namespace Acts::Experimental::detail {
0030 
0031 /// @brief Helper method to generate completely populated bin sequences
0032 /// that respect the boundary type of the axis
0033 ///
0034 /// @param minMaxBins estimated bin range (aka binning boundary box)
0035 /// @param expand the parameter to expand the view (extra window)
0036 /// @param nBins the maximum number of bins on this axis
0037 /// @param type the boundary type of the axis (for correct bin closure)
0038 ///
0039 /// @note for closed binning a span over half the bins flips direction
0040 ///
0041 /// @return a vector of bins to be filled
0042 std::vector<std::size_t> binSequence(std::array<std::size_t, 2u> minMaxBins,
0043                                      std::size_t expand, std::size_t nBins,
0044                                      Acts::detail::AxisBoundaryType type);
0045 
0046 /// @brief Helper method to fill local bins given a set of query points
0047 /// bin in between the extra points are filled, and a possible expansion
0048 /// of the bin window can be chosen
0049 ///
0050 /// @tparam grid_type the type of the grid that determines locall binning
0051 ///
0052 /// @param grid the grid used for this
0053 /// @param queries the grid positions for the bin queries
0054 /// @param expansion are the additional (configured) number of bins to expand
0055 /// the view
0056 ///
0057 /// @return a set of unique indices
0058 template <typename grid_type>
0059 std::set<typename grid_type::index_t> localIndices(
0060     const grid_type& grid,
0061     const std::vector<typename grid_type::point_t>& queries,
0062     const std::vector<std::size_t>& expansion = {}) {
0063   // Return indices
0064   std::set<typename grid_type::index_t> lIndices;
0065 
0066   if (queries.empty()) {
0067     throw std::runtime_error("IndexedSurfaceGridFiller: no query point given.");
0068   }
0069 
0070   if (!expansion.empty() && expansion.size() != grid_type::DIM) {
0071     throw std::runtime_error(
0072         "IndexedSurfaceGridFiller: wrong dimension of bin expansion given.");
0073   }
0074 
0075   /// These are the axis bounds type parameters - for correct bin sequences
0076   std::array<Acts::detail::AxisBoundaryType, grid_type::DIM> axisTypes{};
0077   std::array<std::size_t, grid_type::DIM> axisBins{};
0078   // Fill the axis types
0079   for (auto [ia, a] : enumerate(grid.axes())) {
0080     axisTypes[ia] = a->getBoundaryType();
0081     axisBins[ia] = a->getNBins();
0082   }
0083 
0084   // Initialize the bin ranges
0085   std::array<std::array<std::size_t, 2u>, grid_type::DIM> binRanges = {};
0086   for (auto& br : binRanges) {
0087     br[0u] = std::numeric_limits<std::size_t>::max();
0088     br[1u] = 0u;
0089   }
0090   // Bin range bounding box - estimated from the query points
0091   for (const auto& q : queries) {
0092     auto qbin = grid.localBinsFromPosition(q);
0093     for (std::size_t ib = 0; ib < grid_type::DIM; ++ib) {
0094       auto iqb = qbin[ib];
0095       binRanges[ib][0u] = std::min(iqb, binRanges[ib][0u]);
0096       binRanges[ib][1u] = std::max(iqb, binRanges[ib][1u]);
0097     }
0098   }
0099   // Fill the bins - 1D case
0100   if constexpr (grid_type::DIM == 1u) {
0101     // Take the expansion if available & generate the local bin sequence
0102     std::size_t expand = expansion.empty() ? 0u : expansion[0u];
0103     auto localBins0 =
0104         binSequence(binRanges[0u], expand, axisBins[0u], axisTypes[0u]);
0105     for (auto l0 : localBins0) {
0106       typename grid_type::index_t b;
0107       b[0u] = l0;
0108       lIndices.insert(b);
0109     }
0110   }
0111   // Fill the bins - 2D case
0112   if constexpr (grid_type::DIM == 2u) {
0113     // Take the expansion if available & generate the local bin sequence
0114     std::size_t expand = expansion.empty() ? 0u : expansion[0u];
0115     auto localBins0 =
0116         binSequence(binRanges[0u], expand, axisBins[0u], axisTypes[0u]);
0117     expand = expansion.empty() ? 0u : expansion[1u];
0118     auto localBins1 =
0119         binSequence(binRanges[1u], expand, axisBins[1u], axisTypes[1u]);
0120     for (auto l0 : localBins0) {
0121       for (auto l1 : localBins1) {
0122         typename grid_type::index_t b;
0123         b[0u] = l0;
0124         b[1u] = l1;
0125         lIndices.insert(b);
0126       }
0127     }
0128   }
0129   return lIndices;
0130 }
0131 
0132 /// @brief Helper method to screen output the local bins
0133 ///
0134 /// @tparam local_bin the type of the local bins
0135 ///
0136 /// @param lbins the local bins
0137 ///
0138 /// @return a string containing the local bins ordered in a set
0139 template <typename local_bin>
0140 std::string outputIndices(const std::set<local_bin>& lbins) {
0141   std::string rString;
0142   for (auto [ilb, lb] : Acts::enumerate(lbins)) {
0143     if (ilb == 0) {
0144       rString = "bins: [";
0145     } else {
0146       rString += ", [";
0147     }
0148     for (auto [ib, b] : Acts::enumerate(lb)) {
0149       if (ib != 0u) {
0150         rString += ", ";
0151       }
0152       rString += std::to_string(b);
0153     }
0154     rString += "]";
0155   }
0156   return rString;
0157 }
0158 
0159 /// A helper class that fills surfaces into predefined grids
0160 struct IndexedGridFiller {
0161   /// Bin expansion where needed
0162   std::vector<std::size_t> binExpansion = {};
0163 
0164   /// Screen output logger
0165   std::unique_ptr<const Logger> oLogger =
0166       getDefaultLogger("IndexedGridFiller", Logging::INFO);
0167 
0168   /// @brief This method takes a collection of objects and fills them
0169   /// into an index grid - it uses a reference generator for grid query points
0170   /// and then completes the bins in between.
0171   ///
0172   /// It also allows for expanding the fill view.
0173   ///
0174   /// @tparam index_grid the type of the index grid
0175   /// @tparam indexed_objects the type of the object container
0176   /// @tparam reference_generator the generator for reference points to be filled
0177   ///
0178   /// @param gctx the geometry context of the operation
0179   /// @param iGrid [in,out] the index grid object to be filled
0180   /// @param iObjects the object container to be indexed
0181   /// @param rGenerator the reference point generator for position queries
0182   /// @param aToAll the indices that are assigned to all bins
0183   ///
0184   /// @note as this is a Detector module, the objects within the indexed_objects container
0185   /// are assumed to have pointer semantics
0186   ///
0187   template <typename index_grid, typename indexed_objects,
0188             typename reference_generator>
0189   void fill(
0190       const GeometryContext& gctx, index_grid& iGrid,
0191       const indexed_objects& iObjects, const reference_generator& rGenerator,
0192       const typename index_grid::grid_type::value_type& aToAll = {}) const {
0193     // Loop over the surfaces to be filled
0194     for (auto [io, o] : enumerate(iObjects)) {
0195       // Exclude indices that should be handled differently
0196       if (std::find(aToAll.begin(), aToAll.end(), io) != aToAll.end()) {
0197         continue;
0198       }
0199       // Get the reference positions
0200       auto refs = rGenerator.references(gctx, *o);
0201       std::vector<typename index_grid::grid_type::point_t> gridQueries;
0202       gridQueries.reserve(refs.size());
0203       for (const auto& ref : refs) {
0204         // Cast the transform according to the grid binning
0205         gridQueries.push_back(
0206             GridAccessHelpers::castPosition<decltype(iGrid.grid)>(
0207                 iGrid.transform * ref, iGrid.casts));
0208       }
0209       ACTS_DEBUG(gridQueries.size() << " reference points generated.");
0210       auto lIndices = localIndices<decltype(iGrid.grid)>(
0211           iGrid.grid, gridQueries, binExpansion);
0212       ACTS_DEBUG(lIndices.size() << " indices assigned.");
0213       if (oLogger->level() <= Logging::VERBOSE) {
0214         ACTS_VERBOSE("- list of indices: " << outputIndices(lIndices));
0215       }
0216       // Now fill the surface indices
0217       for (const auto& li : lIndices) {
0218         auto& bContent = iGrid.grid.atLocalBins(li);
0219         if (std::find(bContent.begin(), bContent.end(), io) == bContent.end()) {
0220           bContent.push_back(io);
0221         }
0222       }
0223     }
0224 
0225     // Assign the indices into all
0226     if (!aToAll.empty()) {
0227       assignToAll(iGrid, aToAll);
0228     }
0229   }
0230 
0231   /// Helper method to fill a dedicated list of indices into the entire grid
0232   ///
0233   /// This is useful if e.g. certain objects are to be attempted in any case,
0234   /// regardless of their binning.
0235   ///
0236   template <typename index_grid, typename indices>
0237   void assignToAll(index_grid& iGrid, const indices& idcs) const {
0238     for (std::size_t gi = 0; gi < iGrid.grid.size(true); ++gi) {
0239       auto& bContent = iGrid.grid.at(gi);
0240       for (const auto& io : idcs) {
0241         if (std::find(bContent.begin(), bContent.end(), io) == bContent.end()) {
0242           bContent.push_back(io);
0243         }
0244       }
0245     }
0246   }
0247 
0248   /// Access to the logger
0249   ///
0250   /// @return a const reference to the logger
0251   const Logger& logger() const { return (*oLogger); }
0252 };
0253 
0254 }  // namespace Acts::Experimental::detail