Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:09:59

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2021 CERN for the benefit of the Acts project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 #include "Acts/EventData/GenericBoundTrackParameters.hpp"
0012 #include "Acts/EventData/TrackParameters.hpp"
0013 #include "Acts/Surfaces/PlaneSurface.hpp"
0014 #include "Acts/Surfaces/Surface.hpp"
0015 
0016 #include <cmath>
0017 #include <memory>
0018 #include <type_traits>
0019 #include <utility>
0020 
0021 namespace Acts {
0022 
0023 /// This class is only a light wrapper around a surface and a vector of
0024 /// parameters. Its main purpose is to provide many constructors for the
0025 /// underlying vector. Most accessors are generated from the
0026 /// BoundTrackParameters equivalent and thus may be expensive
0027 /// @note This class holds shared ownership on its reference surface.
0028 /// @note The accessors for parameters, covariance, position, etc.
0029 /// are the weighted means of the components.
0030 /// @note If all covariances are zero, the accessor for the total
0031 /// covariance does return std::nullopt;
0032 /// TODO Add constructor from range and projector maybe?
0033 class MultiComponentBoundTrackParameters {
0034  public:
0035   using Parameters = BoundTrackParameters;
0036   using ParticleHypothesis = Parameters::ParticleHypothesis;
0037   using Scalar = typename Parameters::Scalar;
0038   using ParametersVector = typename Parameters::ParametersVector;
0039   using CovarianceMatrix = typename Parameters::CovarianceMatrix;
0040 
0041  private:
0042   std::vector<std::tuple<double, BoundVector, std::optional<BoundSquareMatrix>>>
0043       m_components;
0044   std::shared_ptr<const Surface> m_surface;
0045 
0046   // TODO use [[no_unique_address]] once we switch to C++20
0047   ParticleHypothesis m_particleHypothesis;
0048 
0049   /// Helper function to reduce the component vector to a single representation
0050   template <typename projector_t>
0051   auto reduce(projector_t&& proj) const {
0052     using Ret = std::decay_t<decltype(proj(std::declval<Parameters>()))>;
0053 
0054     Ret ret;
0055 
0056     if constexpr (std::is_floating_point_v<Ret>) {
0057       ret = 0.0;
0058     } else {
0059       ret = Ret::Zero();
0060     }
0061 
0062     for (auto i = 0ul; i < m_components.size(); ++i) {
0063       const auto [weight, single_pars] = (*this)[i];
0064       ret += weight * proj(single_pars);
0065     }
0066 
0067     return ret;
0068   }
0069 
0070  public:
0071   /// Construct from multiple components
0072   template <typename covariance_t>
0073   MultiComponentBoundTrackParameters(
0074       std::shared_ptr<const Surface> surface,
0075       const std::vector<std::tuple<double, BoundVector, covariance_t>>& cmps,
0076       ParticleHypothesis particleHypothesis)
0077       : m_surface(std::move(surface)),
0078         m_particleHypothesis(particleHypothesis) {
0079     static_assert(
0080         std::is_same_v<BoundSquareMatrix, covariance_t> ||
0081         std::is_same_v<std::optional<BoundSquareMatrix>, covariance_t>);
0082     if constexpr (std::is_same_v<BoundSquareMatrix, covariance_t>) {
0083       for (const auto& [weight, params, cov] : cmps) {
0084         m_components.push_back({weight, params, cov});
0085       }
0086     } else {
0087       m_components = cmps;
0088     }
0089   }
0090 
0091   /// Construct from a parameters vector on the surface and particle charge.
0092   ///
0093   /// @param surface Reference surface the parameters are defined on
0094   /// @param params Bound parameters vector
0095   /// @param particleHypothesis Particle hypothesis for these parameters
0096   /// @param cov Bound parameters covariance matrix
0097   ///
0098   /// In principle, only the charge magnitude is needed her to allow
0099   /// unambiguous extraction of the absolute momentum. The particle charge is
0100   /// required as an input here to be consistent with the other constructors
0101   /// below that that also take the charge as an input. The charge sign is
0102   /// only used in debug builds to check for consistency with the q/p
0103   /// parameter.
0104   MultiComponentBoundTrackParameters(std::shared_ptr<const Surface> surface,
0105                                      const BoundVector& params,
0106                                      std::optional<BoundSquareMatrix> cov,
0107                                      ParticleHypothesis particleHypothesis)
0108       : m_surface(std::move(surface)),
0109         m_particleHypothesis(particleHypothesis) {
0110     m_components.push_back({1., params, std::move(cov)});
0111   }
0112 
0113   /// Parameters are not default constructible due to the charge type.
0114   MultiComponentBoundTrackParameters() = delete;
0115   MultiComponentBoundTrackParameters(
0116       const MultiComponentBoundTrackParameters&) = default;
0117   MultiComponentBoundTrackParameters(MultiComponentBoundTrackParameters&&) =
0118       default;
0119   ~MultiComponentBoundTrackParameters() = default;
0120   MultiComponentBoundTrackParameters& operator=(
0121       const MultiComponentBoundTrackParameters&) = default;
0122   MultiComponentBoundTrackParameters& operator=(
0123       MultiComponentBoundTrackParameters&&) = default;
0124 
0125   /// Access the parameters
0126   const auto& components() const { return m_components; }
0127 
0128   /// Reference surface onto which the parameters are bound.
0129   const Surface& referenceSurface() const { return *m_surface; }
0130 
0131   /// Get the weight and a GenericBoundTrackParameters object for one component
0132   std::pair<double, Parameters> operator[](std::size_t i) const {
0133     return std::make_pair(
0134         std::get<double>(m_components[i]),
0135         Parameters(m_surface, std::get<BoundVector>(m_components[i]),
0136                    std::get<std::optional<BoundSquareMatrix>>(m_components[i]),
0137                    m_particleHypothesis));
0138   }
0139 
0140   /// Parameters vector.
0141   ParametersVector parameters() const {
0142     return reduce([](const Parameters& p) { return p.parameters(); });
0143   }
0144 
0145   /// Optional covariance matrix.
0146   std::optional<CovarianceMatrix> covariance() const {
0147     const auto ret = reduce([](const Parameters& p) {
0148       return p.covariance() ? *p.covariance() : CovarianceMatrix::Zero();
0149     });
0150 
0151     if (ret == CovarianceMatrix::Zero()) {
0152       return std::nullopt;
0153     } else {
0154       return ret;
0155     }
0156   }
0157 
0158   /// Access a single parameter value identified by its index.
0159   ///
0160   /// @tparam kIndex Track parameter index
0161   template <BoundIndices kIndex>
0162   Scalar get() const {
0163     return reduce([&](const Parameters& p) { return p.get<kIndex>(); });
0164   }
0165 
0166   /// Space-time position four-vector.
0167   ///
0168   /// @param[in] geoCtx Geometry context for the local-to-global
0169   /// transformation
0170   Vector4 fourPosition(const GeometryContext& geoCtx) const {
0171     return reduce([&](const Parameters& p) { return p.fourPosition(geoCtx); });
0172   }
0173 
0174   /// Spatial position three-vector.
0175   ///
0176   /// @param[in] geoCtx Geometry context for the local-to-global
0177   /// transformation
0178   Vector3 position(const GeometryContext& geoCtx) const {
0179     return reduce([&](const Parameters& p) { return p.position(geoCtx); });
0180   }
0181 
0182   /// Time coordinate.
0183   Scalar time() const {
0184     return reduce([](const Parameters& p) { return p.time(); });
0185   }
0186 
0187   /// Unit direction three-vector, i.e. the normalized momentum
0188   /// three-vector.
0189   Vector3 direction() const {
0190     return reduce([](const Parameters& p) { return p.direction(); })
0191         .normalized();
0192   }
0193 
0194   /// Phi direction.
0195   Scalar phi() const { return VectorHelpers::phi(direction()); }
0196 
0197   /// Theta direction.
0198   Scalar theta() const { return VectorHelpers::theta(direction()); }
0199 
0200   /// Charge over momentum.
0201   Scalar qOverP() const { return get<eBoundQOverP>(); }
0202 
0203   /// Absolute momentum.
0204   Scalar absoluteMomentum() const {
0205     return reduce([](const Parameters& p) { return p.absoluteMomentum(); });
0206   }
0207 
0208   /// Transverse momentum.
0209   Scalar transverseMomentum() const {
0210     return reduce([](const Parameters& p) { return p.transverseMomentum(); });
0211   }
0212 
0213   /// Momentum three-vector.
0214   Vector3 momentum() const {
0215     return reduce([](const Parameters& p) { return p.momentum(); });
0216   }
0217 
0218   /// Particle electric charge.
0219   Scalar charge() const {
0220     return reduce([](const Parameters& p) { return p.charge(); });
0221   }
0222 
0223   /// Particle hypothesis.
0224   const ParticleHypothesis& particleHypothesis() const {
0225     return m_particleHypothesis;
0226   }
0227 };
0228 
0229 /// This class mimics the behaviour of the curvilinear parameters for ordinary
0230 /// track parameters. To adopt this concept, a "common surface" is constructed,
0231 /// and all parameters are projected onto this surface. The use of this is
0232 /// questionable, and if the result is reasonable depends largely on the initial
0233 /// multi component state. However, the propagator infrastructure forces the
0234 /// existence of this type
0235 /// @tparam charge_t Helper type to interpret the particle charge/momentum
0236 class MultiComponentCurvilinearTrackParameters
0237     : public MultiComponentBoundTrackParameters {
0238   using covariance_t = BoundSquareMatrix;
0239 
0240  public:
0241   using ConstructionTuple = std::tuple<double, Acts::Vector4, Acts::Vector3,
0242                                        ActsScalar, covariance_t>;
0243 
0244  private:
0245   using Base = MultiComponentBoundTrackParameters;
0246 
0247   using BaseConstructionTuple =
0248       std::tuple<std::shared_ptr<Acts::Surface>,
0249                  std::vector<std::tuple<double, BoundVector, covariance_t>>>;
0250 
0251   /// We need this helper function in order to construct the base class properly
0252   static BaseConstructionTuple construct(
0253       const std::vector<ConstructionTuple>& curvi) {
0254     // TODO where to get a geometry context here
0255     Acts::GeometryContext gctx{};
0256 
0257     // Construct and average surface
0258     Acts::Vector3 avgPos = Acts::Vector3::Zero();
0259     Acts::Vector3 avgDir = Acts::Vector3::Zero();
0260     for (const auto& [w, pos4, dir, qop, cov] : curvi) {
0261       avgPos += w * pos4.template segment<3>(0);
0262       avgDir += w * dir;
0263     }
0264 
0265     auto s = Surface::makeShared<PlaneSurface>(avgPos, avgDir);
0266 
0267     std::vector<std::tuple<double, BoundVector, covariance_t>> bound;
0268     bound.reserve(curvi.size());
0269 
0270     // Project the position onto the surface, keep everything else as is
0271     for (const auto& [w, pos4, dir, qop, cov] : curvi) {
0272       Vector3 newPos = s->intersect(gctx, pos4.template segment<3>(eFreePos0),
0273                                     dir, BoundaryCheck(false))
0274                            .closest()
0275                            .position();
0276 
0277       BoundVector bv =
0278           transformFreeToCurvilinearParameters(pos4[eTime], dir, qop);
0279 
0280       // Because of the projection this should never fail
0281       bv.template segment<2>(eBoundLoc0) =
0282           *(s->globalToLocal(gctx, newPos, dir));
0283 
0284       bound.emplace_back(w, bv, cov);
0285     }
0286 
0287     return {s, bound};
0288   }
0289 
0290   /// Private constructor from a tuple
0291   MultiComponentCurvilinearTrackParameters(
0292       const BaseConstructionTuple& t, ParticleHypothesis particleHypothesis)
0293       : Base(std::get<0>(t), std::get<1>(t), particleHypothesis) {}
0294 
0295  public:
0296   MultiComponentCurvilinearTrackParameters(
0297       const std::vector<ConstructionTuple>& cmps,
0298       ParticleHypothesis particleHypothesis)
0299       : MultiComponentCurvilinearTrackParameters(construct(cmps),
0300                                                  particleHypothesis) {}
0301 };
0302 
0303 }  // namespace Acts