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