File indexing completed on 2026-06-30 07:34:57
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 std::size_t size() const { return m_weights.size(); }
0219
0220
0221
0222 bool empty() const { return m_weights.empty(); }
0223
0224
0225
0226 const std::vector<double>& weights() const { return m_weights; }
0227
0228
0229
0230 const std::vector<ParametersVector>& parameters() const {
0231 return m_parameters;
0232 }
0233
0234
0235
0236
0237 const std::vector<CovarianceMatrix>& covariances() const {
0238 if (!hasCovariance()) {
0239 throw std::runtime_error(
0240 "Covariance matrices are not available for this "
0241 "MultiComponentBoundTrackParameters");
0242 }
0243 return m_covariances;
0244 }
0245
0246
0247
0248 const Surface& referenceSurface() const { return *m_surface; }
0249
0250
0251
0252 const ParticleHypothesis& particleHypothesis() const {
0253 return m_particleHypothesis;
0254 }
0255
0256
0257
0258 bool hasCovariance() const { return m_hasCovariance; }
0259
0260
0261
0262 std::vector<Component> toComponents() const {
0263 std::vector<Component> cmps;
0264 cmps.reserve(size());
0265 for (std::size_t i = 0; i < size(); ++i) {
0266 cmps.emplace_back(
0267 m_weights[i], m_parameters[i],
0268 hasCovariance() ? std::optional(m_covariances[i]) : std::nullopt);
0269 }
0270 return cmps;
0271 }
0272
0273
0274
0275
0276 std::pair<double, Parameters> operator[](std::size_t i) const {
0277 return {m_weights[i],
0278 Parameters(m_surface, m_parameters[i],
0279 hasCovariance() ? std::optional(m_covariances[i])
0280 : std::nullopt,
0281 m_particleHypothesis)};
0282 }
0283
0284
0285
0286
0287
0288 BoundTrackParameters merge(ComponentMergeMethod method) const;
0289
0290
0291 void clear();
0292
0293
0294
0295 void reserve(std::size_t n);
0296
0297
0298
0299
0300 void pushComponent(double weight, const ParametersVector& params);
0301
0302
0303
0304
0305
0306 void pushComponent(double weight, const ParametersVector& params,
0307 const CovarianceMatrix& cov);
0308
0309
0310
0311
0312
0313 void pushComponent(double weight, const ParametersVector& params,
0314 const std::optional<CovarianceMatrix>& cov);
0315
0316
0317 void normalizeWeights();
0318 };
0319
0320 }