Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-01 07:45:43

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/BoundTrackParameters.hpp"
0012 #include "Acts/EventData/detail/MultiComponentTrackParametersConcept.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 <ranges>
0019 #include <utility>
0020 
0021 namespace Acts {
0022 
0023 enum class ComponentMergeMethod;
0024 
0025 /// This class is only a light wrapper around a surface and a vector of
0026 /// parameters. Its main purpose is to provide many constructors for the
0027 /// underlying vector. Most accessors are generated from the
0028 /// BoundTrackParameters equivalent and thus may be expensive
0029 /// @note This class holds shared ownership on its reference surface.
0030 /// @note The accessors for parameters, covariance, position, etc.
0031 /// are the weighted means of the components.
0032 /// @note If all covariances are zero, the accessor for the total
0033 /// covariance does return std::nullopt;
0034 /// TODO Add constructor from range and projector maybe?
0035 class MultiComponentBoundTrackParameters {
0036  public:
0037   /// Type alias for bound track parameters
0038   using Parameters = BoundTrackParameters;
0039   /// Type alias for bound parameters vector
0040   using ParametersVector = typename Parameters::ParametersVector;
0041   /// Type alias for covariance matrix
0042   using CovarianceMatrix = typename Parameters::CovarianceMatrix;
0043   /// Type alias for the component tuple
0044   using Component =
0045       std::tuple<double, ParametersVector, std::optional<CovarianceMatrix>>;
0046 
0047  private:
0048   std::vector<double> m_weights;
0049   std::vector<ParametersVector> m_parameters;
0050   std::vector<CovarianceMatrix> m_covariances;
0051   std::shared_ptr<const Surface> m_surface;
0052   ParticleHypothesis m_particleHypothesis;
0053   bool m_hasCovariance{false};
0054 
0055  public:
0056   /// Type alias for construction tuple containing weight, position, direction,
0057   /// q/p, and covariance
0058   using ConstructionTuple =
0059       std::tuple<double, Vector4, Vector3, double, BoundMatrix>;
0060 
0061   /// We need this helper function in order to construct the base class properly
0062   /// @param geoCtx Geometry context for construction
0063   /// @param curvi Vector of construction tuples containing component data
0064   /// @param particleHypothesis Particle hypothesis for the parameters
0065   /// @return Multi-component bound track parameters in curvilinear representation
0066   static MultiComponentBoundTrackParameters createCurvilinear(
0067       const GeometryContext& geoCtx,
0068       const std::vector<ConstructionTuple>& curvi,
0069       ParticleHypothesis particleHypothesis) {
0070     // Construct and average surface
0071     Vector3 avgPos = Vector3::Zero();
0072     Vector3 avgDir = Vector3::Zero();
0073     for (const auto& [w, pos4, dir, qop, cov] : curvi) {
0074       avgPos += w * pos4.template segment<3>(0);
0075       avgDir += w * dir;
0076     }
0077 
0078     std::shared_ptr<PlaneSurface> s =
0079         CurvilinearSurface(avgPos, avgDir).planeSurface();
0080 
0081     std::vector<Component> bound;
0082     bound.reserve(curvi.size());
0083 
0084     // Project the position onto the surface, keep everything else as is
0085     for (const auto& [w, pos4, dir, qop, cov] : curvi) {
0086       const Intersection3D closestIntersection =
0087           s->intersect(geoCtx, pos4.template segment<3>(eFreePos0), dir,
0088                        BoundaryTolerance::Infinite())
0089               .closest();
0090       const Vector3& newPos = closestIntersection.position();
0091 
0092       BoundVector bv =
0093           transformFreeToCurvilinearParameters(pos4[eTime], dir, qop);
0094 
0095       // Because of the projection this should never fail
0096       bv.template segment<2>(eBoundLoc0) =
0097           *(s->globalToLocal(geoCtx, newPos, dir));
0098 
0099       bound.emplace_back(w, bv, cov);
0100     }
0101 
0102     return MultiComponentBoundTrackParameters(
0103         s, bound,
0104         [](const Component& cmp) {
0105           return std::tie(std::get<0>(cmp), std::get<1>(cmp),
0106                           *std::get<2>(cmp));
0107         },
0108         particleHypothesis);
0109   }
0110 
0111   /// Construct from a surface and particle hypothesis, without components
0112   /// @param surface Reference surface the parameters are defined on
0113   /// @param hasCovariance Flag indicating if covariance matrices will be provided for the
0114   /// @param particleHypothesis Particle hypothesis for the parameters
0115   MultiComponentBoundTrackParameters(std::shared_ptr<const Surface> surface,
0116                                      bool hasCovariance,
0117                                      ParticleHypothesis particleHypothesis)
0118       : m_surface(std::move(surface)),
0119         m_particleHypothesis(particleHypothesis),
0120         m_hasCovariance(hasCovariance) {}
0121 
0122   /// Construct from a single component
0123   /// @param surface Reference surface the parameters are defined on
0124   /// @param params Bound parameters vector
0125   /// @param cov Bound parameters covariance matrix
0126   /// @param particleHypothesis Particle hypothesis for these parameters
0127   MultiComponentBoundTrackParameters(std::shared_ptr<const Surface> surface,
0128                                      const BoundVector& params,
0129                                      std::optional<BoundMatrix> cov,
0130                                      ParticleHypothesis particleHypothesis)
0131       : m_surface(std::move(surface)),
0132         m_particleHypothesis(particleHypothesis) {
0133     m_weights.push_back(1.);
0134     m_parameters.push_back(params);
0135     if (cov) {
0136       m_covariances.push_back(*cov);
0137     }
0138     m_hasCovariance = cov.has_value();
0139   }
0140 
0141   /// Construct from multiple components without covariance
0142   /// @param surface Surface on which the parameters are bound
0143   /// @param cmps Vector of weight, parameters vector, and covariance components
0144   /// @param proj Projector to use for the parameters
0145   /// @param particleHypothesis Particle hypothesis for the parameters
0146   template <std::ranges::range component_range_t, typename projector_t>
0147   MultiComponentBoundTrackParameters(std::shared_ptr<const Surface> surface,
0148                                      const component_range_t& cmps,
0149                                      const projector_t& proj,
0150                                      ParticleHypothesis particleHypothesis)
0151     requires detail::ComponentRangeAndProjectorWithoutCovarianceConcept<
0152                  component_range_t, projector_t>
0153       : m_surface(std::move(surface)),
0154         m_particleHypothesis(particleHypothesis) {
0155     if (cmps.begin() == cmps.end()) {
0156       throw std::invalid_argument(
0157           "Cannot construct MultiComponentBoundTrackParameters without "
0158           "components");
0159     }
0160 
0161     for (const auto& cmp : cmps) {
0162       const auto& [weight, parameters] = proj(cmp);
0163       m_weights.push_back(weight);
0164       m_parameters.push_back(parameters);
0165     }
0166   }
0167 
0168   /// Construct from multiple components with covariance
0169   /// @param surface Surface on which the parameters are bound
0170   /// @param cmps Vector of weight, parameters vector, and covariance components
0171   /// @param proj Projector to use for the parameters
0172   /// @param particleHypothesis Particle hypothesis for the parameters
0173   template <std::ranges::range component_range_t, typename projector_t>
0174   MultiComponentBoundTrackParameters(std::shared_ptr<const Surface> surface,
0175                                      const component_range_t& cmps,
0176                                      const projector_t& proj,
0177                                      ParticleHypothesis particleHypothesis)
0178     requires detail::ComponentRangeAndProjectorWithCovarianceConcept<
0179                  component_range_t, projector_t>
0180       : m_surface(std::move(surface)),
0181         m_particleHypothesis(particleHypothesis),
0182         m_hasCovariance(true) {
0183     if (cmps.begin() == cmps.end()) {
0184       throw std::invalid_argument(
0185           "Cannot construct MultiComponentBoundTrackParameters without "
0186           "components");
0187     }
0188 
0189     for (const auto& cmp : cmps) {
0190       const auto& [weight, parameters, covariance] = proj(cmp);
0191       m_weights.push_back(weight);
0192       m_parameters.push_back(parameters);
0193       m_covariances.push_back(covariance);
0194     }
0195   }
0196 
0197   /// No default constructor, because we always need at least a surface and
0198   /// particle hypothesis
0199   MultiComponentBoundTrackParameters() = delete;
0200   /// Copy constructor
0201   MultiComponentBoundTrackParameters(
0202       const MultiComponentBoundTrackParameters&) = default;
0203   /// Move constructor
0204   MultiComponentBoundTrackParameters(MultiComponentBoundTrackParameters&&) =
0205       default;
0206   ~MultiComponentBoundTrackParameters() = default;
0207   /// Copy assignment operator
0208   /// @return Reference to this object after copying
0209   MultiComponentBoundTrackParameters& operator=(
0210       const MultiComponentBoundTrackParameters&) = default;
0211   /// Move assignment operator
0212   /// @return Reference to this object after moving
0213   MultiComponentBoundTrackParameters& operator=(
0214       MultiComponentBoundTrackParameters&&) = default;
0215 
0216   /// Comply with bound convertible, in this case return a copy
0217   /// @return Copy of this multi-component track parameters
0218   [[deprecated(
0219       "You already have a universal bound track parameter at hand. You can "
0220       "drop `toBound()`.")]]
0221   MultiComponentBoundTrackParameters toBound() const {
0222     return *this;
0223   }
0224 
0225   /// Size of the multi-component parameters
0226   /// @return Number of components in the multi-component parameters
0227   std::size_t size() const { return m_weights.size(); }
0228 
0229   /// Check if the multi-component parameters are empty
0230   /// @return True if there are no components, false otherwise
0231   bool empty() const { return m_weights.empty(); }
0232 
0233   /// Access to the weights of the components
0234   /// @return The weights for all components
0235   const std::vector<double>& weights() const { return m_weights; }
0236 
0237   /// Access to the parameters of the components
0238   /// @return The parameters vectors for all components
0239   const std::vector<ParametersVector>& parameters() const {
0240     return m_parameters;
0241   }
0242 
0243   /// Access to the covariances of the components
0244   /// @return The covariance matrices for all components
0245   /// @throws std::runtime_error if covariance matrices are not available for this multi-component parameters
0246   const std::vector<CovarianceMatrix>& covariances() const {
0247     if (!hasCovariance()) {
0248       throw std::runtime_error(
0249           "Covariance matrices are not available for this "
0250           "MultiComponentBoundTrackParameters");
0251     }
0252     return m_covariances;
0253   }
0254 
0255   /// Reference surface onto which the parameters are bound.
0256   /// @return Reference to the bound reference surface
0257   const Surface& referenceSurface() const { return *m_surface; }
0258 
0259   /// Particle hypothesis.
0260   /// @return Reference to the particle hypothesis
0261   const ParticleHypothesis& particleHypothesis() const {
0262     return m_particleHypothesis;
0263   }
0264 
0265   /// Check if covariance matrices are available for the components
0266   /// @return True if covariance matrices are available, false otherwise
0267   bool hasCovariance() const { return m_hasCovariance; }
0268 
0269   /// Convert the multi-component parameters to a vector of components
0270   /// @return Vector of components, where each component is a tuple of weight, parameters vector, and optional covariance matrix
0271   std::vector<Component> toComponents() const {
0272     std::vector<Component> cmps;
0273     cmps.reserve(size());
0274     for (std::size_t i = 0; i < size(); ++i) {
0275       cmps.emplace_back(
0276           m_weights[i], m_parameters[i],
0277           hasCovariance() ? std::optional(m_covariances[i]) : std::nullopt);
0278     }
0279     return cmps;
0280   }
0281 
0282   /// Get the weight and a GenericBoundTrackParameters object for one component
0283   /// @param i Index of the component to access
0284   /// @return Pair of weight and bound track parameters for the component
0285   std::pair<double, Parameters> operator[](std::size_t i) const {
0286     return {m_weights[i],
0287             Parameters(m_surface, m_parameters[i],
0288                        hasCovariance() ? std::optional(m_covariances[i])
0289                                        : std::nullopt,
0290                        m_particleHypothesis)};
0291   }
0292 
0293   /// Merge component mixture into a single set of parameters using the
0294   /// specified method.
0295   /// @param method Method to use for merging the components into a single set of parameters
0296   /// @return Single component bound track parameters representing the mixture
0297   BoundTrackParameters merge(ComponentMergeMethod method) const;
0298 
0299   /// Clear all components from the multi-component parameters
0300   void clear();
0301 
0302   /// Reserve space for a number of components in the multi-component parameters
0303   /// @param n Number of components to reserve space for
0304   void reserve(std::size_t n);
0305 
0306   /// Add a component to the multi-component parameters
0307   /// @param weight Weight of the new component
0308   /// @param params Parameters vector of the new component
0309   void pushComponent(double weight, const ParametersVector& params);
0310 
0311   /// Add a component with covariance to the multi-component parameters
0312   /// @param weight Weight of the new component
0313   /// @param params Parameters vector of the new component
0314   /// @param cov Covariance matrix of the new component
0315   void pushComponent(double weight, const ParametersVector& params,
0316                      const CovarianceMatrix& cov);
0317 
0318   /// Add a component with optional covariance to the multi-component parameters
0319   /// @param weight Weight of the new component
0320   /// @param params Parameters vector of the new component
0321   /// @param cov Optional covariance matrix of the new component
0322   void pushComponent(double weight, const ParametersVector& params,
0323                      const std::optional<CovarianceMatrix>& cov);
0324 
0325   /// Normalize the weights of the components so that they sum up to 1
0326   void normalizeWeights();
0327 };
0328 
0329 }  // namespace Acts