File indexing completed on 2026-04-01 07:45:43
0001
0002
0003
0004
0005
0006
0007
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
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 class MultiComponentBoundTrackParameters {
0036 public:
0037
0038 using Parameters = BoundTrackParameters;
0039
0040 using ParametersVector = typename Parameters::ParametersVector;
0041
0042 using CovarianceMatrix = typename Parameters::CovarianceMatrix;
0043
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
0057
0058 using ConstructionTuple =
0059 std::tuple<double, Vector4, Vector3, double, BoundMatrix>;
0060
0061
0062
0063
0064
0065
0066 static MultiComponentBoundTrackParameters createCurvilinear(
0067 const GeometryContext& geoCtx,
0068 const std::vector<ConstructionTuple>& curvi,
0069 ParticleHypothesis particleHypothesis) {
0070
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
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
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
0112
0113
0114
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
0123
0124
0125
0126
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
0142
0143
0144
0145
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
0169
0170
0171
0172
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
0198
0199 MultiComponentBoundTrackParameters() = delete;
0200
0201 MultiComponentBoundTrackParameters(
0202 const MultiComponentBoundTrackParameters&) = default;
0203
0204 MultiComponentBoundTrackParameters(MultiComponentBoundTrackParameters&&) =
0205 default;
0206 ~MultiComponentBoundTrackParameters() = default;
0207
0208
0209 MultiComponentBoundTrackParameters& operator=(
0210 const MultiComponentBoundTrackParameters&) = default;
0211
0212
0213 MultiComponentBoundTrackParameters& operator=(
0214 MultiComponentBoundTrackParameters&&) = default;
0215
0216
0217
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
0226
0227 std::size_t size() const { return m_weights.size(); }
0228
0229
0230
0231 bool empty() const { return m_weights.empty(); }
0232
0233
0234
0235 const std::vector<double>& weights() const { return m_weights; }
0236
0237
0238
0239 const std::vector<ParametersVector>& parameters() const {
0240 return m_parameters;
0241 }
0242
0243
0244
0245
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
0256
0257 const Surface& referenceSurface() const { return *m_surface; }
0258
0259
0260
0261 const ParticleHypothesis& particleHypothesis() const {
0262 return m_particleHypothesis;
0263 }
0264
0265
0266
0267 bool hasCovariance() const { return m_hasCovariance; }
0268
0269
0270
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
0283
0284
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
0294
0295
0296
0297 BoundTrackParameters merge(ComponentMergeMethod method) const;
0298
0299
0300 void clear();
0301
0302
0303
0304 void reserve(std::size_t n);
0305
0306
0307
0308
0309 void pushComponent(double weight, const ParametersVector& params);
0310
0311
0312
0313
0314
0315 void pushComponent(double weight, const ParametersVector& params,
0316 const CovarianceMatrix& cov);
0317
0318
0319
0320
0321
0322 void pushComponent(double weight, const ParametersVector& params,
0323 const std::optional<CovarianceMatrix>& cov);
0324
0325
0326 void normalizeWeights();
0327 };
0328
0329 }