Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
IndexedGridFiller.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file IndexedGridFiller.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2023 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #pragma once
10 
19 #include "Acts/Utilities/IAxis.hpp"
21 
22 #include <algorithm>
23 #include <array>
24 #include <set>
25 #include <string>
26 #include <vector>
27 
28 namespace Acts {
29 namespace Experimental {
30 namespace detail {
31 
43 std::vector<std::size_t> binSequence(std::array<std::size_t, 2u> minMaxBins,
44  std::size_t expand, std::size_t nBins,
46 
59 template <typename grid_type>
60 std::set<typename grid_type::index_t> localIndices(
61  const grid_type& grid,
62  const std::vector<typename grid_type::point_t>& queries,
63  const std::vector<std::size_t>& expansion = {}) {
64  // Return indices
65  std::set<typename grid_type::index_t> lIndices;
66 
67  if (queries.empty()) {
68  throw std::runtime_error("IndexedSurfaceGridFiller: no query point given.");
69  }
70 
71  if (not expansion.empty() and expansion.size() != grid_type::DIM) {
72  throw std::runtime_error(
73  "IndexedSurfaceGridFiller: wrong dimension of bin expansion given.");
74  }
75 
77  std::array<Acts::detail::AxisBoundaryType, grid_type::DIM> axisTypes{};
78  std::array<std::size_t, grid_type::DIM> axisBins{};
79  // Fill the axis types
80  for (auto [ia, a] : enumerate(grid.axes())) {
81  axisTypes[ia] = a->getBoundaryType();
82  axisBins[ia] = a->getNBins();
83  }
84 
85  // Initialize the bin ranges
86  std::array<std::array<std::size_t, 2u>, grid_type::DIM> binRanges = {};
87  for (auto& br : binRanges) {
88  br[0u] = std::numeric_limits<std::size_t>::max();
89  br[1u] = 0u;
90  }
91  // Bin range bounding box - estimated from the query points
92  for (const auto& q : queries) {
93  auto qbin = grid.localBinsFromPosition(q);
94  for (std::size_t ib = 0; ib < grid_type::DIM; ++ib) {
95  auto iqb = qbin[ib];
96  binRanges[ib][0u] = std::min(iqb, binRanges[ib][0u]);
97  binRanges[ib][1u] = std::max(iqb, binRanges[ib][1u]);
98  }
99  }
100  // Fill the bins - 1D case
101  if constexpr (grid_type::DIM == 1u) {
102  // Take the expansion if available & generate the local bin sequence
103  std::size_t expand = expansion.empty() ? 0u : expansion[0u];
104  auto localBins0 =
105  binSequence(binRanges[0u], expand, axisBins[0u], axisTypes[0u]);
106  for (auto l0 : localBins0) {
107  typename grid_type::index_t b;
108  b[0u] = l0;
109  lIndices.insert(b);
110  }
111  }
112  // Fill the bins - 2D case
113  if constexpr (grid_type::DIM == 2u) {
114  // Take the expansion if available & generate the local bin sequence
115  std::size_t expand = expansion.empty() ? 0u : expansion[0u];
116  auto localBins0 =
117  binSequence(binRanges[0u], expand, axisBins[0u], axisTypes[0u]);
118  expand = expansion.empty() ? 0u : expansion[1u];
119  auto localBins1 =
120  binSequence(binRanges[1u], expand, axisBins[1u], axisTypes[1u]);
121  for (auto l0 : localBins0) {
122  for (auto l1 : localBins1) {
123  typename grid_type::index_t b;
124  b[0u] = l0;
125  b[1u] = l1;
126  lIndices.insert(b);
127  }
128  }
129  }
130  return lIndices;
131 }
132 
140 template <typename local_bin>
141 std::string outputIndices(const std::set<local_bin>& lbins) {
142  std::string rString;
143  for (auto [ilb, lb] : Acts::enumerate(lbins)) {
144  if (ilb == 0) {
145  rString = "bins: [";
146  } else {
147  rString += ", [";
148  }
149  for (auto [ib, b] : Acts::enumerate(lb)) {
150  if (ib != 0u) {
151  rString += ", ";
152  }
153  rString += std::to_string(b);
154  }
155  rString += "]";
156  }
157  return rString;
158 }
159 
163  std::vector<std::size_t> binExpansion = {};
164 
166  std::unique_ptr<const Logger> oLogger =
167  getDefaultLogger("IndexedGridFiller", Logging::INFO);
168 
188  template <typename index_grid, typename indexed_objects,
189  typename reference_generator>
190  void fill(
191  const GeometryContext& gctx, index_grid& iGrid,
192  const indexed_objects& iObjects, const reference_generator& rGenerator,
193  const typename index_grid::grid_type::value_type& aToAll = {}) const {
194  // Loop over the surfaces to be filled
195  for (auto [io, o] : enumerate(iObjects)) {
196  // Exclude indices that should be handled differently
197  if (std::find(aToAll.begin(), aToAll.end(), io) != aToAll.end()) {
198  continue;
199  }
200  // Get the reference positions
201  auto refs = rGenerator.references(gctx, *o);
202  std::vector<typename index_grid::grid_type::point_t> gridQueries;
203  gridQueries.reserve(refs.size());
204  for (const auto& ref : refs) {
205  // Cast the transform according to the grid binning
206  gridQueries.push_back(iGrid.castPosition(ref));
207  }
208  ACTS_DEBUG(gridQueries.size() << " reference points generated.");
209  auto lIndices = localIndices<decltype(iGrid.grid)>(
210  iGrid.grid, gridQueries, binExpansion);
211  ACTS_DEBUG(lIndices.size() << " indices assigned.");
212  if (oLogger->level() <= Logging::VERBOSE) {
213  ACTS_VERBOSE("- list of indices: " << outputIndices(lIndices));
214  }
215  // Now fill the surface indices
216  for (const auto& li : lIndices) {
217  auto& bContent = iGrid.grid.atLocalBins(li);
218  if (std::find(bContent.begin(), bContent.end(), io) == bContent.end()) {
219  bContent.push_back(io);
220  }
221  }
222  }
223 
224  // Assign the indices into all
225  if (not aToAll.empty()) {
226  assignToAll(iGrid, aToAll);
227  }
228  }
229 
235  template <typename index_grid, typename indices>
236  void assignToAll(index_grid& iGrid, const indices& idcs) const {
237  for (std::size_t gi = 0; gi < iGrid.grid.size(true); ++gi) {
238  auto& bContent = iGrid.grid.at(gi);
239  for (const auto& io : idcs) {
240  if (std::find(bContent.begin(), bContent.end(), io) == bContent.end()) {
241  bContent.push_back(io);
242  }
243  }
244  }
245  }
246 
250  const Logger& logger() const { return (*oLogger); }
251 };
252 
253 } // namespace detail
254 } // namespace Experimental
255 } // namespace Acts