Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MultiComponentTrackParameters.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file MultiComponentTrackParameters.hpp
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 
9 #pragma once
10 
15 
16 #include <cmath>
17 #include <memory>
18 #include <type_traits>
19 #include <utility>
20 
21 namespace Acts {
22 
34  public:
37  using Scalar = typename Parameters::Scalar;
40 
41  private:
42  std::vector<std::tuple<double, BoundVector, std::optional<BoundSquareMatrix>>>
44  std::shared_ptr<const Surface> m_surface;
45 
46  // TODO use [[no_unique_address]] once we switch to C++20
48 
50  template <typename projector_t>
51  auto reduce(projector_t&& proj) const {
52  using Ret = std::decay_t<decltype(proj(std::declval<Parameters>()))>;
53 
54  Ret ret;
55 
56  if constexpr (std::is_floating_point_v<Ret>) {
57  ret = 0.0;
58  } else {
59  ret = Ret::Zero();
60  }
61 
62  for (auto i = 0ul; i < m_components.size(); ++i) {
63  const auto [weight, single_pars] = (*this)[i];
64  ret += weight * proj(single_pars);
65  }
66 
67  return ret;
68  }
69 
70  public:
72  template <typename covariance_t>
74  std::shared_ptr<const Surface> surface,
75  const std::vector<std::tuple<double, BoundVector, covariance_t>>& cmps,
77  : m_surface(std::move(surface)),
78  m_particleHypothesis(particleHypothesis) {
79  static_assert(
80  std::is_same_v<BoundSquareMatrix, covariance_t> ||
81  std::is_same_v<std::optional<BoundSquareMatrix>, covariance_t>);
82  if constexpr (std::is_same_v<BoundSquareMatrix, covariance_t>) {
83  for (const auto& [weight, params, cov] : cmps) {
84  m_components.push_back({weight, params, cov});
85  }
86  } else {
87  m_components = cmps;
88  }
89  }
90 
104  MultiComponentBoundTrackParameters(std::shared_ptr<const Surface> surface,
105  const BoundVector& params,
106  std::optional<BoundSquareMatrix> cov,
108  : m_surface(std::move(surface)),
109  m_particleHypothesis(particleHypothesis) {
110  m_components.push_back({1., params, std::move(cov)});
111  }
112 
116  const MultiComponentBoundTrackParameters&) = default;
118  default;
121  const MultiComponentBoundTrackParameters&) = default;
124 
126  const auto& components() const { return m_components; }
127 
129  const Surface& referenceSurface() const { return *m_surface; }
130 
132  std::pair<double, Parameters> operator[](std::size_t i) const {
133  return std::make_pair(
134  std::get<double>(m_components[i]),
135  Parameters(m_surface, std::get<BoundVector>(m_components[i]),
136  std::get<std::optional<BoundSquareMatrix>>(m_components[i]),
138  }
139 
142  return reduce([](const Parameters& p) { return p.parameters(); });
143  }
144 
146  std::optional<CovarianceMatrix> covariance() const {
147  const auto ret = reduce([](const Parameters& p) {
148  return p.covariance() ? *p.covariance() : CovarianceMatrix::Zero();
149  });
150 
151  if (ret == CovarianceMatrix::Zero()) {
152  return std::nullopt;
153  } else {
154  return ret;
155  }
156  }
157 
161  template <BoundIndices kIndex>
162  Scalar get() const {
163  return reduce([&](const Parameters& p) { return p.get<kIndex>(); });
164  }
165 
171  return reduce([&](const Parameters& p) { return p.fourPosition(geoCtx); });
172  }
173 
179  return reduce([&](const Parameters& p) { return p.position(geoCtx); });
180  }
181 
183  Scalar time() const {
184  return reduce([](const Parameters& p) { return p.time(); });
185  }
186 
189  Vector3 direction() const {
190  return reduce([](const Parameters& p) { return p.direction(); })
191  .normalized();
192  }
193 
195  Scalar phi() const { return VectorHelpers::phi(direction()); }
196 
199 
201  Scalar qOverP() const { return get<eBoundQOverP>(); }
202 
205  return reduce([](const Parameters& p) { return p.absoluteMomentum(); });
206  }
207 
210  return reduce([](const Parameters& p) { return p.transverseMomentum(); });
211  }
212 
214  Vector3 momentum() const {
215  return reduce([](const Parameters& p) { return p.momentum(); });
216  }
217 
219  Scalar charge() const {
220  return reduce([](const Parameters& p) { return p.charge(); });
221  }
222 
225  return m_particleHypothesis;
226  }
227 };
228 
239 
240  public:
243 
244  private:
246 
247  using BaseConstructionTuple =
248  std::tuple<std::shared_ptr<Acts::Surface>,
249  std::vector<std::tuple<double, BoundVector, covariance_t>>>;
250 
253  const std::vector<ConstructionTuple>& curvi) {
254  // TODO where to get a geometry context here
256 
257  // Construct and average surface
258  Acts::Vector3 avgPos = Acts::Vector3::Zero();
259  Acts::Vector3 avgDir = Acts::Vector3::Zero();
260  for (const auto& [w, pos4, dir, qop, cov] : curvi) {
261  avgPos += w * pos4.template segment<3>(0);
262  avgDir += w * dir;
263  }
264 
265  auto s = Surface::makeShared<PlaneSurface>(avgPos, avgDir);
266 
267  std::vector<std::tuple<double, BoundVector, covariance_t>> bound;
268  bound.reserve(curvi.size());
269 
270  // Project the position onto the surface, keep everything else as is
271  for (const auto& [w, pos4, dir, qop, cov] : curvi) {
272  Vector3 newPos =
273  s->intersect(gctx, pos4.template segment<3>(eFreePos0), dir, false)
274  .closest()
275  .position();
276 
277  BoundVector bv =
279 
280  // Because of the projection this should never fail
281  bv.template segment<2>(eBoundLoc0) =
282  *(s->globalToLocal(gctx, newPos, dir));
283 
284  bound.emplace_back(w, bv, cov);
285  }
286 
287  return {s, bound};
288  }
289 
293  : Base(std::get<0>(t), std::get<1>(t), particleHypothesis) {}
294 
295  public:
297  const std::vector<ConstructionTuple>& cmps,
300  particleHypothesis) {}
301 };
302 
303 } // namespace Acts