Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SeedingAlgorithm.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file SeedingAlgorithm.cpp
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 
10 
13 #include "Acts/Geometry/Extent.hpp"
24 
25 #include <cmath>
26 #include <csignal>
27 #include <cstddef>
28 #include <iterator>
29 #include <limits>
30 #include <ostream>
31 #include <stdexcept>
32 
33 namespace ActsExamples {
34 struct AlgorithmContext;
35 } // namespace ActsExamples
36 
39  : ActsExamples::IAlgorithm("SeedingAlgorithm", lvl), m_cfg(std::move(cfg)) {
40  // Seed Finder config requires Seed Filter object before conversion to
41  // internal units
44  std::make_unique<Acts::SeedFilter<SimSpacePoint>>(m_cfg.seedFilterConfig);
45 
53  if (m_cfg.inputSpacePoints.empty()) {
54  throw std::invalid_argument("Missing space point input collections");
55  }
56 
57  for (const auto& spName : m_cfg.inputSpacePoints) {
58  if (spName.empty()) {
59  throw std::invalid_argument("Invalid space point input collection");
60  }
61 
62  auto& handle = m_inputSpacePoints.emplace_back(
64  this,
65  "InputSpacePoints#" + std::to_string(m_inputSpacePoints.size())));
66  handle->initialize(spName);
67  }
68  if (m_cfg.outputSeeds.empty()) {
69  throw std::invalid_argument("Missing seeds output collection");
70  }
71 
73 
75  m_cfg.allowSeparateRMax == false) {
76  throw std::invalid_argument(
77  "Inconsistent config rMax: using different values in gridConfig and "
78  "seedFinderConfig. If values are intentional set allowSeparateRMax to "
79  "true");
80  }
81 
83  throw std::invalid_argument("Inconsistent config deltaRMin");
84  }
85 
87  throw std::invalid_argument("Inconsistent config deltaRMax");
88  }
89 
90  static_assert(
91  std::numeric_limits<
92  decltype(m_cfg.seedFinderConfig.deltaRMaxTopSP)>::has_quiet_NaN,
93  "Value of deltaRMaxTopSP must support NaN values");
94 
95  static_assert(
96  std::numeric_limits<
97  decltype(m_cfg.seedFinderConfig.deltaRMinTopSP)>::has_quiet_NaN,
98  "Value of deltaRMinTopSP must support NaN values");
99 
100  static_assert(
101  std::numeric_limits<
102  decltype(m_cfg.seedFinderConfig.deltaRMaxBottomSP)>::has_quiet_NaN,
103  "Value of deltaRMaxBottomSP must support NaN values");
104 
105  static_assert(
106  std::numeric_limits<
107  decltype(m_cfg.seedFinderConfig.deltaRMinBottomSP)>::has_quiet_NaN,
108  "Value of deltaRMinBottomSP must support NaN values");
109 
110  if (std::isnan(m_cfg.seedFinderConfig.deltaRMaxTopSP)) {
112  }
113 
114  if (std::isnan(m_cfg.seedFinderConfig.deltaRMinTopSP)) {
116  }
117 
118  if (std::isnan(m_cfg.seedFinderConfig.deltaRMaxBottomSP)) {
120  }
121 
122  if (std::isnan(m_cfg.seedFinderConfig.deltaRMinBottomSP)) {
124  }
125 
127  throw std::invalid_argument("Inconsistent config zMin");
128  }
129 
131  throw std::invalid_argument("Inconsistent config zMax");
132  }
133 
136  throw std::invalid_argument("Inconsistent config maxSeedsPerSpM");
137  }
138 
140  throw std::invalid_argument("Inconsistent config cotThetaMax");
141  }
142 
144  throw std::invalid_argument("Inconsistent config minPt");
145  }
146 
148  throw std::invalid_argument("Inconsistent config bFieldInZ");
149  }
150 
151  if (m_cfg.gridConfig.zBinEdges.size() - 1 != m_cfg.zBinNeighborsTop.size() &&
152  m_cfg.zBinNeighborsTop.empty() == false) {
153  throw std::invalid_argument("Inconsistent config zBinNeighborsTop");
154  }
155 
156  if (m_cfg.gridConfig.zBinEdges.size() - 1 !=
157  m_cfg.zBinNeighborsBottom.size() &&
158  m_cfg.zBinNeighborsBottom.empty() == false) {
159  throw std::invalid_argument("Inconsistent config zBinNeighborsBottom");
160  }
161 
163  // check if zBinsCustomLooping contains numbers from 1 to the total number
164  // of bin in zBinEdges
165  for (size_t i = 1; i != m_cfg.gridConfig.zBinEdges.size(); i++) {
166  if (std::find(m_cfg.seedFinderConfig.zBinsCustomLooping.begin(),
169  throw std::invalid_argument(
170  "Inconsistent config zBinsCustomLooping does not contain the same "
171  "bins as zBinEdges");
172  }
173  }
174  }
175 
178  [](const void*, const SimSpacePoint& sp) -> float {
179  return sp.topHalfStripLength();
180  });
181 
183  [](const void*, const SimSpacePoint& sp) -> float {
184  return sp.bottomHalfStripLength();
185  });
186 
188  [](const void*, const SimSpacePoint& sp) -> Acts::Vector3 {
189  return sp.topStripDirection();
190  });
191 
193  [](const void*, const SimSpacePoint& sp) -> Acts::Vector3 {
194  return sp.bottomStripDirection();
195  });
196 
198  [](const void*, const SimSpacePoint& sp) -> Acts::Vector3 {
199  return sp.stripCenterDistance();
200  });
201 
203  [](const void*, const SimSpacePoint& sp) -> Acts::Vector3 {
204  return sp.topStripCenterPosition();
205  });
206  }
207 
208  m_bottomBinFinder = std::make_shared<const Acts::BinFinder<SimSpacePoint>>(
210  m_topBinFinder = std::make_shared<const Acts::BinFinder<SimSpacePoint>>(
212 
214  std::make_unique<Acts::SeedFilter<SimSpacePoint>>(m_cfg.seedFilterConfig);
216 }
217 
219  const AlgorithmContext& ctx) const {
220  // construct the combined input container of space point pointers from all
221  // configured input sources.
222  // pre-compute the total size required so we only need to allocate once
223  size_t nSpacePoints = 0;
224  for (const auto& isp : m_inputSpacePoints) {
225  nSpacePoints += (*isp)(ctx).size();
226  }
227 
228  std::vector<const SimSpacePoint*> spacePointPtrs;
229  spacePointPtrs.reserve(nSpacePoints);
230  for (const auto& isp : m_inputSpacePoints) {
231  for (const auto& spacePoint : (*isp)(ctx)) {
232  // since the event store owns the space
233  // points, their pointers should be stable and
234  // we do not need to create local copies.
235  spacePointPtrs.push_back(&spacePoint);
236  }
237  }
238 
239  // construct the seeding tools
240  // covariance tool, extracts covariances per spacepoint as required
241  auto extractGlobalQuantities =
242  [=](const SimSpacePoint& sp, float, float,
243  float) -> std::pair<Acts::Vector3, Acts::Vector2> {
244  Acts::Vector3 position{sp.x(), sp.y(), sp.z()};
246  return std::make_pair(position, covariance);
247  };
248 
249  // extent used to store r range for middle spacepoint
250  Acts::Extent rRangeSPExtent;
251 
252  auto grid = Acts::SpacePointGridCreator::createGrid<SimSpacePoint>(
253  m_cfg.gridConfig, m_cfg.gridOptions);
254 
255  auto spacePointsGrouping = Acts::BinnedSPGroup<SimSpacePoint>(
256  spacePointPtrs.begin(), spacePointPtrs.end(), extractGlobalQuantities,
257  m_bottomBinFinder, m_topBinFinder, std::move(grid), rRangeSPExtent,
258  m_cfg.seedFinderConfig, m_cfg.seedFinderOptions);
259 
260  // safely clamp double to float
261  float up = Acts::clampValue<float>(
262  std::floor(rRangeSPExtent.max(Acts::binR) / 2) * 2);
263 
265  const Acts::Range1D<float> rMiddleSPRange(
266  std::floor(rRangeSPExtent.min(Acts::binR) / 2) * 2 +
267  m_cfg.seedFinderConfig.deltaRMiddleMinSPRange,
268  up - m_cfg.seedFinderConfig.deltaRMiddleMaxSPRange);
269 
270  // run the seeding
271  static thread_local SimSeedContainer seeds;
272  seeds.clear();
273  static thread_local decltype(m_seedFinder)::SeedingState state;
274  state.spacePointData.resize(
275  spacePointPtrs.size(),
276  m_cfg.seedFinderConfig.useDetailedDoubleMeasurementInfo);
277 
278  if (m_cfg.seedFinderConfig.useDetailedDoubleMeasurementInfo) {
279  for (std::size_t grid_glob_bin(0);
280  grid_glob_bin < spacePointsGrouping.grid().size(); ++grid_glob_bin) {
281  const auto& collection = spacePointsGrouping.grid().at(grid_glob_bin);
282  for (const auto& sp : collection) {
283  std::size_t index = sp->index();
284 
285  const float topHalfStripLength =
286  m_cfg.seedFinderConfig.getTopHalfStripLength(sp->sp());
287  const float bottomHalfStripLength =
288  m_cfg.seedFinderConfig.getBottomHalfStripLength(sp->sp());
289  const Acts::Vector3 topStripDirection =
290  m_cfg.seedFinderConfig.getTopStripDirection(sp->sp());
291  const Acts::Vector3 bottomStripDirection =
292  m_cfg.seedFinderConfig.getBottomStripDirection(sp->sp());
293 
294  state.spacePointData.setTopStripVector(
295  index, topHalfStripLength * topStripDirection);
296  state.spacePointData.setBottomStripVector(
297  index, bottomHalfStripLength * bottomStripDirection);
298  state.spacePointData.setStripCenterDistance(
299  index, m_cfg.seedFinderConfig.getStripCenterDistance(sp->sp()));
300  state.spacePointData.setTopStripCenterPosition(
301  index, m_cfg.seedFinderConfig.getTopStripCenterPosition(sp->sp()));
302  }
303  }
304  }
305 
306  for (const auto [bottom, middle, top] : spacePointsGrouping) {
307  m_seedFinder.createSeedsForGroup(
308  m_cfg.seedFinderOptions, state, spacePointsGrouping.grid(),
309  std::back_inserter(seeds), bottom, middle, top, rMiddleSPRange);
310  }
311 
312  ACTS_DEBUG("Created " << seeds.size() << " track seeds from "
313  << spacePointPtrs.size() << " space points");
314 
315  m_outputSeeds(ctx, SimSeedContainer{seeds});
317 }