File indexing completed on 2025-10-24 08:18:31
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Tolerance.hpp"
0012 #include "Acts/EventData/ParticleHypothesis.hpp"
0013 #include "Acts/EventData/TrackParameterHelpers.hpp"
0014 #include "Acts/EventData/TransformationHelpers.hpp"
0015 #include "Acts/EventData/detail/PrintParameters.hpp"
0016 #include "Acts/Surfaces/CurvilinearSurface.hpp"
0017 #include "Acts/Surfaces/Surface.hpp"
0018 #include "Acts/Utilities/UnitVectors.hpp"
0019 #include "Acts/Utilities/detail/periodic.hpp"
0020
0021 #include <cassert>
0022 #include <cmath>
0023 #include <memory>
0024
0025 namespace Acts {
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 template <class particle_hypothesis_t>
0039 class GenericBoundTrackParameters {
0040 public:
0041
0042 using ParametersVector = BoundVector;
0043
0044 using CovarianceMatrix = BoundSquareMatrix;
0045
0046 using ParticleHypothesis = particle_hypothesis_t;
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063 static Result<GenericBoundTrackParameters> create(
0064 const GeometryContext& geoCtx, std::shared_ptr<const Surface> surface,
0065 const Vector4& pos4, const Vector3& dir, double qOverP,
0066 std::optional<CovarianceMatrix> cov,
0067 ParticleHypothesis particleHypothesis,
0068 double tolerance = s_onSurfaceTolerance) {
0069 Result<BoundVector> bound =
0070 transformFreeToBoundParameters(pos4.segment<3>(ePos0), pos4[eTime], dir,
0071 qOverP, *surface, geoCtx, tolerance);
0072
0073 if (!bound.ok()) {
0074 return bound.error();
0075 }
0076
0077 return GenericBoundTrackParameters{std::move(surface), std::move(*bound),
0078 std::move(cov),
0079 std::move(particleHypothesis)};
0080 }
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090 static GenericBoundTrackParameters createCurvilinear(
0091 const Vector4& pos4, const Vector3& dir, double qOverP,
0092 std::optional<CovarianceMatrix> cov,
0093 ParticleHypothesis particleHypothesis) {
0094 return GenericBoundTrackParameters(
0095 CurvilinearSurface(pos4.segment<3>(ePos0), dir).surface(),
0096 transformFreeToCurvilinearParameters(pos4[eTime], dir, qOverP),
0097 std::move(cov), std::move(particleHypothesis));
0098 }
0099
0100
0101
0102
0103
0104
0105
0106
0107
0108
0109 static GenericBoundTrackParameters createCurvilinear(
0110 const Vector4& pos4, double phi, double theta, double qOverP,
0111 std::optional<CovarianceMatrix> cov,
0112 ParticleHypothesis particleHypothesis) {
0113 return GenericBoundTrackParameters(
0114 CurvilinearSurface(pos4.segment<3>(ePos0),
0115 makeDirectionFromPhiTheta(phi, theta))
0116 .surface(),
0117 transformFreeToCurvilinearParameters(pos4[eTime], phi, theta, qOverP),
0118 std::move(cov), std::move(particleHypothesis));
0119 }
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133 GenericBoundTrackParameters(std::shared_ptr<const Surface> surface,
0134 const ParametersVector& params,
0135 std::optional<CovarianceMatrix> cov,
0136 ParticleHypothesis particleHypothesis)
0137 : m_params(params),
0138 m_cov(std::move(cov)),
0139 m_surface(std::move(surface)),
0140 m_particleHypothesis(std::move(particleHypothesis)) {
0141
0142 assert(isBoundVectorValid(m_params, false) &&
0143 "Invalid bound parameters vector");
0144 assert(m_surface != nullptr && "Reference surface must not be null");
0145 normalizePhiTheta();
0146 }
0147
0148
0149
0150 template <typename other_particle_hypothesis_t>
0151 explicit GenericBoundTrackParameters(
0152 const GenericBoundTrackParameters<other_particle_hypothesis_t>& other)
0153 : GenericBoundTrackParameters(
0154 other.referenceSurface().getSharedPtr(), other.parameters(),
0155 other.covariance(),
0156 ParticleHypothesis{other.particleHypothesis()}) {}
0157
0158
0159
0160 GenericBoundTrackParameters<Acts::ParticleHypothesis> toBound() const {
0161 return GenericBoundTrackParameters<Acts::ParticleHypothesis>{*this};
0162 }
0163
0164
0165
0166 ParametersVector& parameters() { return m_params; }
0167
0168
0169 const ParametersVector& parameters() const { return m_params; }
0170
0171
0172 Vector2 spatialImpactParameters() const { return m_params.head<2>(); }
0173
0174
0175 Vector3 impactParameters() const {
0176 Vector3 ip;
0177 ip.template head<2>() = m_params.template head<2>();
0178 ip(2) = m_params(eBoundTime);
0179 return ip;
0180 }
0181
0182
0183
0184 std::optional<CovarianceMatrix>& covariance() { return m_cov; }
0185
0186
0187 const std::optional<CovarianceMatrix>& covariance() const { return m_cov; }
0188
0189
0190 std::optional<ActsSquareMatrix<2>> spatialImpactParameterCovariance() const {
0191 if (!m_cov.has_value()) {
0192 return std::nullopt;
0193 }
0194
0195 return m_cov.value().template topLeftCorner<2, 2>();
0196 }
0197
0198
0199
0200
0201 std::optional<ActsSquareMatrix<3>> impactParameterCovariance() const {
0202 if (!m_cov.has_value()) {
0203 return std::nullopt;
0204 }
0205
0206 ActsSquareMatrix<3> ipCov;
0207 ipCov.template topLeftCorner<2, 2>() =
0208 m_cov.value().template topLeftCorner<2, 2>();
0209 ipCov.template block<2, 1>(0, 2) =
0210 m_cov.value().template block<2, 1>(0, eBoundTime);
0211 ipCov.template block<1, 2>(2, 0) =
0212 m_cov.value().template block<1, 2>(eBoundTime, 0);
0213 ipCov(2, 2) = m_cov.value()(eBoundTime, eBoundTime);
0214 return ipCov;
0215 }
0216
0217
0218
0219
0220
0221 template <BoundIndices kIndex>
0222 double get() const {
0223 return m_params[kIndex];
0224 }
0225
0226
0227
0228 Vector2 localPosition() const { return m_params.segment<2>(eBoundLoc0); }
0229
0230
0231
0232
0233
0234
0235
0236
0237
0238
0239
0240 Vector4 fourPosition(const GeometryContext& geoCtx) const {
0241 Vector4 pos4;
0242 pos4.segment<3>(ePos0) =
0243 m_surface->localToGlobal(geoCtx, localPosition(), direction());
0244 pos4[eTime] = m_params[eBoundTime];
0245 return pos4;
0246 }
0247
0248
0249
0250
0251
0252
0253
0254
0255
0256
0257
0258 Vector3 position(const GeometryContext& geoCtx) const {
0259 return m_surface->localToGlobal(geoCtx, localPosition(), direction());
0260 }
0261
0262
0263 double time() const { return m_params[eBoundTime]; }
0264
0265
0266
0267 double phi() const { return m_params[eBoundPhi]; }
0268
0269
0270 double theta() const { return m_params[eBoundTheta]; }
0271
0272
0273 double qOverP() const { return m_params[eBoundQOverP]; }
0274
0275
0276
0277
0278 Vector3 direction() const {
0279 return makeDirectionFromPhiTheta(m_params[eBoundPhi],
0280 m_params[eBoundTheta]);
0281 }
0282
0283
0284 double absoluteMomentum() const {
0285 return m_particleHypothesis.extractMomentum(m_params[eBoundQOverP]);
0286 }
0287
0288
0289 double transverseMomentum() const {
0290 return std::sin(m_params[eBoundTheta]) * absoluteMomentum();
0291 }
0292
0293
0294 Vector3 momentum() const { return absoluteMomentum() * direction(); }
0295
0296
0297
0298 double charge() const {
0299 return m_particleHypothesis.extractCharge(get<eBoundQOverP>());
0300 }
0301
0302
0303
0304 const ParticleHypothesis& particleHypothesis() const {
0305 return m_particleHypothesis;
0306 }
0307
0308
0309
0310 const Surface& referenceSurface() const { return *m_surface; }
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321 RotationMatrix3 referenceFrame(const GeometryContext& geoCtx) const {
0322 return m_surface->referenceFrame(geoCtx, position(geoCtx), momentum());
0323 }
0324
0325
0326 void reflectInPlace() { m_params = reflectBoundParameters(m_params); }
0327
0328
0329
0330 GenericBoundTrackParameters<ParticleHypothesis> reflect() const {
0331 GenericBoundTrackParameters<ParticleHypothesis> reflected = *this;
0332 reflected.reflectInPlace();
0333 return reflected;
0334 }
0335
0336 private:
0337 BoundVector m_params;
0338 std::optional<BoundSquareMatrix> m_cov;
0339
0340 std::shared_ptr<const Surface> m_surface;
0341
0342 ParticleHypothesis m_particleHypothesis;
0343
0344
0345 void normalizePhiTheta() {
0346 auto [phi, theta] =
0347 detail::normalizePhiTheta(m_params[eBoundPhi], m_params[eBoundTheta]);
0348 m_params[eBoundPhi] = phi;
0349 m_params[eBoundTheta] = theta;
0350 }
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362 friend bool operator==(const GenericBoundTrackParameters& lhs,
0363 const GenericBoundTrackParameters& rhs) {
0364 return (lhs.m_params == rhs.m_params) && (lhs.m_cov == rhs.m_cov) &&
0365 (lhs.m_surface == rhs.m_surface) &&
0366 (lhs.m_particleHypothesis == rhs.m_particleHypothesis);
0367 }
0368
0369
0370 friend std::ostream& operator<<(std::ostream& os,
0371 const GenericBoundTrackParameters& tp) {
0372 detail::printBoundParameters(
0373 os, tp.referenceSurface(), tp.parameters(),
0374 tp.covariance().has_value() ? &tp.covariance().value() : nullptr);
0375 return os;
0376 }
0377 };
0378
0379 }