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