Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SurfaceArrayCreator.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file SurfaceArrayCreator.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2016-2020 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 
20 
21 #include <algorithm>
22 #include <cmath>
23 #include <cstddef>
24 #include <functional>
25 #include <iterator>
26 #include <memory>
27 #include <optional>
28 #include <ostream>
29 #include <tuple>
30 #include <utility>
31 #include <vector>
32 
33 namespace Acts {
34 namespace Test {
35 struct SurfaceArrayCreatorFixture;
36 }
37 
38 using SurfaceMatcher = std::function<bool(
39  const GeometryContext& gctx, BinningValue, const Surface*, const Surface*)>;
40 
41 using SurfaceVector = std::vector<const Surface*>;
42 using SurfaceMatrix = std::vector<SurfaceVector>;
43 
44 using V3Vector = std::vector<Vector3>;
45 using V3Matrix = std::vector<V3Vector>;
46 
48 
55  public:
57  friend class Acts::SurfaceArray;
58 
59  struct ProtoAxis {
62  size_t nBins = 0;
65  std::vector<AxisScalar> binEdges;
66 
67  size_t getBin(AxisScalar x) const {
68  if (binEdges.empty()) {
69  // equidistant
70  AxisScalar w = (max - min) / nBins;
71  return static_cast<size_t>(std::floor((x - min) / w));
72  } else {
73  // variable
74  const auto it =
75  std::upper_bound(std::begin(binEdges), std::end(binEdges), x);
76  return std::distance(std::begin(binEdges), it) - 1;
77  }
78  }
79  };
80 
81  // Configuration struct
82  struct Config {
86 
91  };
92 
96  SurfaceArrayCreator(std::unique_ptr<const Logger> logger = getDefaultLogger(
97  "SurfaceArrayCreator", Logging::INFO))
98  : m_cfg(Config()), m_logger(std::move(logger)) {}
104  std::unique_ptr<const Logger> logger = getDefaultLogger(
105  "SurfaceArrayCreator", Logging::INFO))
106  : m_cfg(cfg), m_logger(std::move(logger)) {}
107 
109  virtual ~SurfaceArrayCreator() = default;
110 
127  std::unique_ptr<SurfaceArray> surfaceArrayOnCylinder(
128  const GeometryContext& gctx,
129  std::vector<std::shared_ptr<const Surface>> surfaces, size_t binsPhi,
130  size_t binsZ, std::optional<ProtoLayer> protoLayerOpt = std::nullopt,
131  const Transform3& transform = Transform3::Identity()) const;
132 
150  std::unique_ptr<Acts::SurfaceArray> surfaceArrayOnCylinder(
151  const GeometryContext& gctx,
152  std::vector<std::shared_ptr<const Surface>> surfaces,
153  BinningType bTypePhi = equidistant, BinningType bTypeZ = equidistant,
154  std::optional<ProtoLayer> protoLayerOpt = std::nullopt,
155  const Transform3& transform = Transform3::Identity()) const;
156 
173  std::unique_ptr<SurfaceArray> surfaceArrayOnDisc(
174  const GeometryContext& gctx,
175  std::vector<std::shared_ptr<const Surface>> surfaces, size_t binsR,
176  size_t binsPhi, std::optional<ProtoLayer> protoLayerOpt = std::nullopt,
177  const Transform3& transform = Transform3::Identity()) const;
178 
199  std::unique_ptr<Acts::SurfaceArray> surfaceArrayOnDisc(
200  const GeometryContext& gctx,
201  std::vector<std::shared_ptr<const Surface>> surfaces, BinningType bTypeR,
202  BinningType bTypePhi,
203  std::optional<ProtoLayer> protoLayerOpt = std::nullopt,
204  const Transform3& transform = Transform3::Identity()) const;
205 
225  std::unique_ptr<SurfaceArray> surfaceArrayOnPlane(
226  const GeometryContext& gctx,
227  std::vector<std::shared_ptr<const Surface>> surfaces, size_t bins1,
228  size_t bins2, BinningValue bValue,
229  std::optional<ProtoLayer> protoLayerOpt = std::nullopt,
230  const Transform3& transform = Transform3::Identity()) const;
231 
238  static bool isSurfaceEquivalent(const GeometryContext& gctx,
239  BinningValue bValue, const Surface* a,
240  const Surface* b) {
241  using namespace UnitLiterals;
242  using VectorHelpers::perp;
243 
244  if (bValue == Acts::binPhi) {
245  // Take the two binning positions
246  auto pos1 = a->binningPosition(gctx, binR),
247  pos2 = b->binningPosition(gctx, binR);
248 
249  // Project them on the (x, y) plane, where Phi angles are calculated
250  auto proj1 = pos1.head<2>(), proj2 = pos2.head<2>();
251 
252  // Basic dot and cross products identities give us the cosine and sine
253  // of these angles, time the squared vector norm
254  auto cos_dPhi_n2 = proj1.dot(proj2);
255  auto sin_dPhi_n2 = proj1.x() * proj2.y() - proj2.x() * proj1.y();
256 
257  // ...so by injecting them into atan2, we get the angle between them
258  auto dPhi = std::atan2(sin_dPhi_n2, cos_dPhi_n2);
259  return std::abs(dPhi) < M_PI / 180.;
260  }
261 
262  if (bValue == Acts::binZ) {
263  return (std::abs(a->binningPosition(gctx, binR).z() -
264  b->binningPosition(gctx, binR).z()) < 1_um);
265  }
266 
267  if (bValue == Acts::binR) {
268  return (std::abs(perp(a->binningPosition(gctx, binR)) -
269  perp(b->binningPosition(gctx, binR))) < 1_um);
270  }
271 
272  return false;
273  }
274 
277  void setLogger(std::unique_ptr<const Logger> logger) {
278  m_logger = std::move(logger);
279  }
280 
281  private:
284 
286  const Logger& logger() const { return *m_logger; }
287 
288  std::vector<const Surface*> findKeySurfaces(
289  const std::vector<const Surface*>& surfaces,
290  const std::function<bool(const Surface*, const Surface*)>& equal) const;
291 
292  size_t determineBinCount(const GeometryContext& gctx,
293  const std::vector<const Surface*>& surfaces,
294  BinningValue bValue) const;
295 
317  ProtoAxis createVariableAxis(const GeometryContext& gctx,
318  const std::vector<const Surface*>& surfaces,
319  BinningValue bValue,
320  const ProtoLayer& protoLayer,
321  Transform3& transform) const;
322 
345  ProtoAxis createEquidistantAxis(const GeometryContext& gctx,
346  const std::vector<const Surface*>& surfaces,
347  BinningValue bValue,
348  const ProtoLayer& protoLayer,
350  size_t nBins = 0) const;
351 
365  typename F1, typename F2>
366  static std::unique_ptr<SurfaceArray::ISurfaceGridLookup>
367  makeSurfaceGridLookup2D(F1 globalToLocal, F2 localToGlobal, ProtoAxis pAxisA,
368  ProtoAxis pAxisB) {
370  std::unique_ptr<ISGL> ptr;
371 
372  // this becomes completely unreadable otherwise
373  // clang-format off
374  if (pAxisA.bType == equidistant && pAxisB.bType == equidistant) {
375 
376  detail::Axis<detail::AxisType::Equidistant, bdtA> axisA(pAxisA.min, pAxisA.max, pAxisA.nBins);
377  detail::Axis<detail::AxisType::Equidistant, bdtB> axisB(pAxisB.min, pAxisB.max, pAxisB.nBins);
378 
380  ptr = std::unique_ptr<ISGL>(static_cast<ISGL*>(
381  new SGL(globalToLocal, localToGlobal, std::make_tuple(axisA, axisB), {pAxisA.bValue, pAxisB.bValue})));
382 
383  } else if (pAxisA.bType == equidistant && pAxisB.bType == arbitrary) {
384 
385  detail::Axis<detail::AxisType::Equidistant, bdtA> axisA(pAxisA.min, pAxisA.max, pAxisA.nBins);
386  detail::Axis<detail::AxisType::Variable, bdtB> axisB(pAxisB.binEdges);
387 
389  ptr = std::unique_ptr<ISGL>(static_cast<ISGL*>(
390  new SGL(globalToLocal, localToGlobal, std::make_tuple(axisA, axisB), {pAxisA.bValue, pAxisB.bValue})));
391 
392  } else if (pAxisA.bType == arbitrary && pAxisB.bType == equidistant) {
393 
394  detail::Axis<detail::AxisType::Variable, bdtA> axisA(pAxisA.binEdges);
395  detail::Axis<detail::AxisType::Equidistant, bdtB> axisB(pAxisB.min, pAxisB.max, pAxisB.nBins);
396 
398  ptr = std::unique_ptr<ISGL>(static_cast<ISGL*>(
399  new SGL(globalToLocal, localToGlobal, std::make_tuple(axisA, axisB), {pAxisA.bValue, pAxisB.bValue})));
400 
401  } else /*if (pAxisA.bType == arbitrary && pAxisB.bType == arbitrary)*/ {
402 
403  detail::Axis<detail::AxisType::Variable, bdtA> axisA(pAxisA.binEdges);
404  detail::Axis<detail::AxisType::Variable, bdtB> axisB(pAxisB.binEdges);
405 
407  ptr = std::unique_ptr<ISGL>(static_cast<ISGL*>(
408  new SGL(globalToLocal, localToGlobal, std::make_tuple(axisA, axisB), {pAxisA.bValue, pAxisB.bValue})));
409  }
410  // clang-format on
411 
412  return ptr;
413  }
414 
416  std::unique_ptr<const Logger> m_logger;
417 
437  const std::vector<const Surface*>& surfaces) const {
438  ACTS_VERBOSE(
439  "Complete binning by filling closest neighbour surfaces into "
440  "empty bins.");
441 
442  size_t binCompleted = sl.completeBinning(gctx, surfaces);
443 
444  ACTS_VERBOSE(" filled : " << binCompleted
445  << " (includes under/overflow)");
446  }
447 
454  std::vector<Acts::Vector3> makeGlobalVertices(
455  const GeometryContext& gctx, const Acts::Surface& surface,
456  const std::vector<Acts::Vector2>& locVertices) const;
457 };
458 
459 } // namespace Acts