Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SpacePointGrid.ipp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file SpacePointGrid.ipp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2021 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 #include <iostream>
11 #include <memory>
12 
13 template <typename SpacePoint>
14 std::unique_ptr<Acts::SpacePointGrid<SpacePoint>>
18  if (not config.isInInternalUnits) {
19  throw std::runtime_error(
20  "SpacePointGridConfig not in ACTS internal units in "
21  "SpacePointGridCreator::createGrid");
22  }
23  if (not options.isInInternalUnits) {
24  throw std::runtime_error(
25  "SpacePointGridOptions not in ACTS internal units in "
26  "SpacePointGridCreator::createGrid");
27  }
29  using namespace Acts::UnitLiterals;
30 
31  int phiBins = 0;
32  // for no magnetic field, create 100 phi-bins
33  if (options.bFieldInZ == 0) {
34  phiBins = 100;
35  } else {
36  // calculate circle intersections of helix and max detector radius
37  float minHelixRadius =
38  config.minPt /
39  (1_T * 1e6 *
40  options.bFieldInZ); // in mm -> R[mm] =pT[GeV] / (3·10−4×B[T])
41  // = pT[MeV] / (300 *Bz[kT])
42 
43  // sanity check: if yOuter takes the square root of a negative number
44  if (minHelixRadius < config.rMax / 2) {
45  throw std::domain_error(
46  "The value of minHelixRadius cannot be smaller than rMax / 2. Please "
47  "check the configuration of bFieldInZ and minPt");
48  }
49 
50  float maxR2 = config.rMax * config.rMax;
51  float xOuter = maxR2 / (2 * minHelixRadius);
52  float yOuter = std::sqrt(maxR2 - xOuter * xOuter);
53  float outerAngle = std::atan(xOuter / yOuter);
54  // intersection of helix and max detector radius minus maximum R distance
55  // from middle SP to top SP
56  float innerAngle = 0;
57  float rMin = config.rMax;
58  if (config.rMax > config.deltaRMax) {
59  rMin = config.rMax - config.deltaRMax;
60  float innerCircleR2 =
61  (config.rMax - config.deltaRMax) * (config.rMax - config.deltaRMax);
62  float xInner = innerCircleR2 / (2 * minHelixRadius);
63  float yInner = std::sqrt(innerCircleR2 - xInner * xInner);
64  innerAngle = std::atan(xInner / yInner);
65  }
66 
67  // evaluating the azimutal deflection including the maximum impact parameter
68  float deltaAngleWithMaxD0 =
69  std::abs(std::asin(config.impactMax / (rMin)) -
70  std::asin(config.impactMax / config.rMax));
71 
72  // evaluating delta Phi based on the inner and outer angle, and the azimutal
73  // deflection including the maximum impact parameter
74  // Divide by config.phiBinDeflectionCoverage since we combine
75  // config.phiBinDeflectionCoverage number of consecutive phi bins in the
76  // seed making step. So each individual bin should cover
77  // 1/config.phiBinDeflectionCoverage of the maximum expected azimutal
78  // deflection
79  float deltaPhi = (outerAngle - innerAngle + deltaAngleWithMaxD0) /
81 
82  // sanity check: if the delta phi is equal to or less than zero, we'll be
83  // creating an infinite or a negative number of bins, which would be bad!
84  if (deltaPhi <= 0.f) {
85  throw std::domain_error(
86  "Delta phi value is equal to or less than zero, leading to an "
87  "impossible number of bins (negative or infinite)");
88  }
89 
90  // divide 2pi by angle delta to get number of phi-bins
91  // size is always 2pi even for regions of interest
92  phiBins = static_cast<int>(std::ceil(2 * M_PI / deltaPhi));
93  // need to scale the number of phi bins accordingly to the number of
94  // consecutive phi bins in the seed making step.
95  // Each individual bin should be approximately a fraction (depending on this
96  // number) of the maximum expected azimutal deflection.
97 
98  // set protection for large number of bins, by default it is large
99  if (phiBins > config.maxPhiBins) {
100  phiBins = config.maxPhiBins;
101  }
102  }
103 
104  Acts::detail::Axis<detail::AxisType::Equidistant,
105  detail::AxisBoundaryType::Closed>
106  phiAxis(config.phiMin, config.phiMax, phiBins);
107 
108  // vector that will store the edges of the bins of z
109  std::vector<AxisScalar> zValues;
110 
111  // If zBinEdges is not defined, calculate the edges as zMin + bin * zBinSize
112  if (config.zBinEdges.empty()) {
113  // TODO: can probably be optimized using smaller z bins
114  // and returning (multiple) neighbors only in one z-direction for forward
115  // seeds
116  // FIXME: zBinSize must include scattering
117  float zBinSize = config.cotThetaMax * config.deltaRMax;
118  int zBins =
119  std::max(1, (int)std::floor((config.zMax - config.zMin) / zBinSize));
120 
121  for (int bin = 0; bin <= zBins; bin++) {
122  AxisScalar edge =
123  config.zMin + bin * ((config.zMax - config.zMin) / (float)zBins);
124  zValues.push_back(edge);
125  }
126 
127  } else {
128  // Use the zBinEdges defined in the config
129  for (auto& bin : config.zBinEdges) {
130  zValues.push_back(bin);
131  }
132  }
133 
134  detail::Axis<detail::AxisType::Variable, detail::AxisBoundaryType::Bound>
135  zAxis(zValues);
136  return std::make_unique<Acts::SpacePointGrid<SpacePoint>>(
137  std::make_tuple(phiAxis, zAxis));
138 }