Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-05 08:10:58

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