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