File indexing completed on 2025-12-15 09:23:46
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 }