Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
KdtSurfacesProvider.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file KdtSurfacesProvider.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 
17 
18 #include <array>
19 #include <stdexcept>
20 #include <tuple>
21 #include <vector>
22 
23 namespace Acts {
24 
25 namespace Experimental {
26 
32 template <size_t kDIM = 2u, size_t bSize = 100u,
33  typename reference_generator =
34  detail::PolyhedronReferenceGenerator<1u, false>>
35 class KdtSurfaces {
36  public:
38  using KDTS =
40 
42  using Query = std::array<ActsScalar, kDIM>;
43 
45  using Entry = std::pair<Query, std::shared_ptr<Surface>>;
46 
54  const std::vector<std::shared_ptr<Surface>>& surfaces,
55  const std::array<BinningValue, kDIM>& casts,
56  const reference_generator& rgen =
58  : m_kdt(nullptr), m_casts(casts), m_rGenerator(rgen) {
59  // Simple check if the dimension is correct
60  if (kDIM == 0u) {
61  throw std::invalid_argument(
62  "KdtSurfaces: dimension and/or cast rules are incorrect.");
63  }
64  // Fill the tree from surfaces
65  std::vector<Entry> kdtEntries;
66  kdtEntries.reserve(surfaces.size());
67  for (auto& s : surfaces) {
68  // Generate the references and the center of gravity from it
69  const auto references = m_rGenerator.references(gctx, *s);
70  std::vector<Query> castedReferences;
71  castedReferences.reserve(references.size());
72  for (const auto& r : references) {
73  // Now cast into the correct fill position
74  Query rc = {};
75  fillCasts(r, rc, std::make_integer_sequence<std::size_t, kDIM>{});
76  castedReferences.push_back(rc);
77  }
78  // Calculate the center of gravity in casted frame
79  kdtEntries.push_back({cog(castedReferences), s});
80  }
81  // Create the KDTree
82  m_kdt = std::make_unique<KDTS>(std::move(kdtEntries));
83  }
84 
90  std::vector<std::shared_ptr<Surface>> surfaces(
91  const RangeXD<kDIM, ActsScalar>& range) const {
92  // Strip the surfaces
93  std::vector<std::shared_ptr<Surface>> surfacePtrs;
94  auto surfaceQuery = m_kdt->rangeSearchWithKey(range);
95  std::for_each(surfaceQuery.begin(), surfaceQuery.end(),
96  [&](auto& s) { surfacePtrs.push_back(s.second); });
97  return surfacePtrs;
98  }
99 
105  std::vector<std::shared_ptr<Surface>> surfaces(const Extent& extent) const {
107  for (auto [ibv, v] : enumerate(m_casts)) {
108  qRange[ibv] = extent.range(v);
109  }
110  return surfaces(qRange);
111  }
112 
113  private:
115  std::unique_ptr<KDTS> m_kdt = nullptr;
116 
118  std::array<BinningValue, kDIM> m_casts = {};
119 
121  reference_generator m_rGenerator;
122 
126  template <typename Array, std::size_t... idx>
127  void fillCasts(const Vector3& position, Array& a,
128  std::index_sequence<idx...> /*indices*/) const {
129  ((a[idx] = VectorHelpers::cast(position, m_casts[idx])), ...);
130  }
131 
143  Query cog(const std::vector<Query>& cQueries) const {
144  // If there is only one position, return it
145  if (cQueries.size() == 1) {
146  return cQueries.front();
147  }
148  // Build the center of gravity of the n positions
149  Query c{};
150  float weight = 1. / cQueries.size();
151  for (auto& q : cQueries) {
152  std::transform(c.begin(), c.end(), q.begin(), c.begin(),
153  std::plus<ActsScalar>());
154  }
155  std::for_each(c.begin(), c.end(), [&](auto& v) { v *= weight; });
156  return c;
157  }
158 };
159 
164 template <size_t kDIM = 2u, size_t bSize = 100u,
165  typename reference_generator =
166  detail::PolyhedronReferenceGenerator<1u, false>>
168  public:
175  std::shared_ptr<KdtSurfaces<kDIM, bSize, reference_generator>> kdts,
176  const Extent& kregion)
177  : m_kdt(std::move(kdts)), m_region(kregion) {
179  if (m_kdt == nullptr) {
180  throw std::invalid_argument(
181  "KdtSurfacesProvider: no KDTree structure provided.");
182  }
183  }
184 
186  std::vector<std::shared_ptr<Surface>> surfaces(
187  [[maybe_unused]] const GeometryContext& gctx) const final {
188  return m_kdt->surfaces(m_region);
189  }
190 
191  private:
192  std::shared_ptr<KdtSurfaces<kDIM, bSize, reference_generator>> m_kdt =
193  nullptr;
196 };
197 
198 } // namespace Experimental
199 
200 } // namespace Acts