File indexing completed on 2025-10-31 08:16:03
0001 
0002 
0003 
0004 
0005 
0006 
0007 
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 #include "Acts/Utilities/Intersection.hpp"
0016 
0017 #include <memory>
0018 #include <type_traits>
0019 #include <utility>
0020 
0021 namespace Acts {
0022 
0023 
0024 
0025 
0026 
0027 
0028 
0029 
0030 
0031 
0032 
0033 class MultiComponentBoundTrackParameters {
0034  public:
0035   
0036   using Parameters = BoundTrackParameters;
0037   
0038   using ParticleHypothesis = Parameters::ParticleHypothesis;
0039   
0040   using ParametersVector = typename Parameters::ParametersVector;
0041   
0042   using CovarianceMatrix = typename Parameters::CovarianceMatrix;
0043 
0044  private:
0045   std::vector<std::tuple<double, BoundVector, std::optional<BoundSquareMatrix>>>
0046       m_components;
0047   std::shared_ptr<const Surface> m_surface;
0048 
0049   
0050   ParticleHypothesis m_particleHypothesis;
0051 
0052   
0053   template <typename projector_t>
0054   auto reduce(projector_t&& proj) const {
0055     using Ret = std::decay_t<decltype(proj(std::declval<Parameters>()))>;
0056 
0057     Ret ret;
0058 
0059     if constexpr (std::is_floating_point_v<Ret>) {
0060       ret = 0.0;
0061     } else {
0062       ret = Ret::Zero();
0063     }
0064 
0065     for (auto i = 0ul; i < m_components.size(); ++i) {
0066       const auto [weight, single_pars] = (*this)[i];
0067       ret += weight * proj(single_pars);
0068     }
0069 
0070     return ret;
0071   }
0072 
0073  public:
0074   
0075   
0076   using ConstructionTuple = std::tuple<double, Acts::Vector4, Acts::Vector3,
0077                                        double, CovarianceMatrix>;
0078 
0079   
0080   
0081   
0082   
0083   
0084   static MultiComponentBoundTrackParameters createCurvilinear(
0085       const GeometryContext& geoCtx,
0086       const std::vector<ConstructionTuple>& curvi,
0087       ParticleHypothesis particleHypothesis) {
0088     
0089     Acts::Vector3 avgPos = Acts::Vector3::Zero();
0090     Acts::Vector3 avgDir = Acts::Vector3::Zero();
0091     for (const auto& [w, pos4, dir, qop, cov] : curvi) {
0092       avgPos += w * pos4.template segment<3>(0);
0093       avgDir += w * dir;
0094     }
0095 
0096     std::shared_ptr<PlaneSurface> s =
0097         CurvilinearSurface(avgPos, avgDir).planeSurface();
0098 
0099     std::vector<std::tuple<double, ParametersVector, CovarianceMatrix>> bound;
0100     bound.reserve(curvi.size());
0101 
0102     
0103     for (const auto& [w, pos4, dir, qop, cov] : curvi) {
0104       Intersection3D closestIntersection =
0105           s->intersect(geoCtx, pos4.template segment<3>(eFreePos0), dir,
0106                        BoundaryTolerance::Infinite())
0107               .closest();
0108       const Vector3& newPos = closestIntersection.position();
0109 
0110       ParametersVector bv =
0111           transformFreeToCurvilinearParameters(pos4[eTime], dir, qop);
0112 
0113       
0114       bv.template segment<2>(eBoundLoc0) =
0115           *(s->globalToLocal(geoCtx, newPos, dir));
0116 
0117       bound.emplace_back(w, bv, cov);
0118     }
0119 
0120     return MultiComponentBoundTrackParameters(s, bound, particleHypothesis);
0121   }
0122 
0123   
0124   
0125   
0126   
0127   template <typename covariance_t>
0128   MultiComponentBoundTrackParameters(
0129       std::shared_ptr<const Surface> surface,
0130       const std::vector<std::tuple<double, ParametersVector, covariance_t>>&
0131           cmps,
0132       ParticleHypothesis particleHypothesis)
0133       : m_surface(std::move(surface)),
0134         m_particleHypothesis(particleHypothesis) {
0135     static_assert(
0136         std::is_same_v<BoundSquareMatrix, covariance_t> ||
0137         std::is_same_v<std::optional<BoundSquareMatrix>, covariance_t>);
0138     if constexpr (std::is_same_v<BoundSquareMatrix, covariance_t>) {
0139       for (const auto& [weight, params, cov] : cmps) {
0140         m_components.push_back({weight, params, cov});
0141       }
0142     } else {
0143       m_components = cmps;
0144     }
0145   }
0146 
0147   
0148   
0149   
0150   
0151   
0152   
0153   
0154   
0155   
0156   
0157   
0158   
0159   
0160   MultiComponentBoundTrackParameters(std::shared_ptr<const Surface> surface,
0161                                      const ParametersVector& params,
0162                                      std::optional<BoundSquareMatrix> cov,
0163                                      ParticleHypothesis particleHypothesis)
0164       : m_surface(std::move(surface)),
0165         m_particleHypothesis(particleHypothesis) {
0166     m_components.push_back({1., params, std::move(cov)});
0167   }
0168 
0169   
0170   MultiComponentBoundTrackParameters() = delete;
0171   
0172   MultiComponentBoundTrackParameters(
0173       const MultiComponentBoundTrackParameters&) = default;
0174   
0175   MultiComponentBoundTrackParameters(MultiComponentBoundTrackParameters&&) =
0176       default;
0177   ~MultiComponentBoundTrackParameters() = default;
0178   
0179   
0180   MultiComponentBoundTrackParameters& operator=(
0181       const MultiComponentBoundTrackParameters&) = default;
0182   
0183   
0184   MultiComponentBoundTrackParameters& operator=(
0185       MultiComponentBoundTrackParameters&&) = default;
0186 
0187   
0188   
0189   MultiComponentBoundTrackParameters toBound() const { return *this; }
0190 
0191   
0192   
0193   const auto& components() const { return m_components; }
0194 
0195   
0196   
0197   const Surface& referenceSurface() const { return *m_surface; }
0198 
0199   
0200   
0201   
0202   std::pair<double, Parameters> operator[](std::size_t i) const {
0203     return {
0204         std::get<double>(m_components[i]),
0205         Parameters(m_surface, std::get<ParametersVector>(m_components[i]),
0206                    std::get<std::optional<CovarianceMatrix>>(m_components[i]),
0207                    m_particleHypothesis)};
0208   }
0209 
0210   
0211   
0212   ParametersVector parameters() const {
0213     return reduce([](const Parameters& p) { return p.parameters(); });
0214   }
0215 
0216   
0217   
0218   std::optional<CovarianceMatrix> covariance() const {
0219     const auto ret = reduce([](const Parameters& p) {
0220       return p.covariance() ? *p.covariance() : CovarianceMatrix::Zero();
0221     });
0222 
0223     if (ret == CovarianceMatrix::Zero()) {
0224       return std::nullopt;
0225     } else {
0226       return ret;
0227     }
0228   }
0229 
0230   
0231   
0232   
0233   
0234   template <BoundIndices kIndex>
0235   double get() const {
0236     return reduce([&](const Parameters& p) { return p.get<kIndex>(); });
0237   }
0238 
0239   
0240   
0241   
0242   
0243   
0244   Vector4 fourPosition(const GeometryContext& geoCtx) const {
0245     return reduce([&](const Parameters& p) { return p.fourPosition(geoCtx); });
0246   }
0247 
0248   
0249   
0250   
0251   
0252   
0253   Vector3 position(const GeometryContext& geoCtx) const {
0254     return reduce([&](const Parameters& p) { return p.position(geoCtx); });
0255   }
0256 
0257   
0258   
0259   double time() const {
0260     return reduce([](const Parameters& p) { return p.time(); });
0261   }
0262 
0263   
0264   
0265   
0266   Vector3 direction() const {
0267     return reduce([](const Parameters& p) { return p.direction(); })
0268         .normalized();
0269   }
0270 
0271   
0272   
0273   double phi() const { return VectorHelpers::phi(direction()); }
0274 
0275   
0276   
0277   double theta() const { return VectorHelpers::theta(direction()); }
0278 
0279   
0280   
0281   double qOverP() const { return get<eBoundQOverP>(); }
0282 
0283   
0284   
0285   double absoluteMomentum() const {
0286     return reduce([](const Parameters& p) { return p.absoluteMomentum(); });
0287   }
0288 
0289   
0290   
0291   double transverseMomentum() const {
0292     return reduce([](const Parameters& p) { return p.transverseMomentum(); });
0293   }
0294 
0295   
0296   
0297   Vector3 momentum() const {
0298     return reduce([](const Parameters& p) { return p.momentum(); });
0299   }
0300 
0301   
0302   
0303   double charge() const {
0304     return reduce([](const Parameters& p) { return p.charge(); });
0305   }
0306 
0307   
0308   
0309   const ParticleHypothesis& particleHypothesis() const {
0310     return m_particleHypothesis;
0311   }
0312 };
0313 
0314 }