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