Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:10:45

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