File indexing completed on 2025-01-18 09:28:03
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Common.hpp"
0013 #include "Acts/Definitions/PdgParticle.hpp"
0014 #include "Acts/Definitions/TrackParametrization.hpp"
0015 #include "Acts/EventData/ParticleHypothesis.hpp"
0016 #include "Acts/EventData/TrackParameters.hpp"
0017 #include "Acts/Geometry/GeometryContext.hpp"
0018 #include "Acts/Surfaces/Surface.hpp"
0019 #include "Acts/Utilities/VectorHelpers.hpp"
0020 #include "ActsFatras/EventData/Barcode.hpp"
0021 #include "ActsFatras/EventData/ParticleOutcome.hpp"
0022 #include "ActsFatras/EventData/ProcessType.hpp"
0023
0024 #include <cmath>
0025 #include <iosfwd>
0026 #include <optional>
0027
0028 namespace ActsFatras {
0029
0030
0031
0032
0033 class Particle {
0034 public:
0035 using Scalar = Acts::ActsScalar;
0036 using Vector3 = Acts::ActsVector<3>;
0037 using Vector4 = Acts::ActsVector<4>;
0038
0039
0040 Particle() = default;
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050 Particle(Barcode particleId, Acts::PdgParticle pdg, Scalar charge,
0051 Scalar mass)
0052 : m_particleId(particleId), m_pdg(pdg), m_charge(charge), m_mass(mass) {}
0053
0054
0055
0056
0057
0058
0059 Particle(Barcode particleId, Acts::PdgParticle pdg);
0060 Particle(const Particle &) = default;
0061 Particle(Particle &&) = default;
0062 Particle &operator=(const Particle &) = default;
0063 Particle &operator=(Particle &&) = default;
0064
0065
0066
0067
0068
0069
0070 Particle withParticleId(Barcode particleId) const {
0071 Particle p = *this;
0072 p.m_particleId = particleId;
0073 return p;
0074 }
0075
0076
0077 Particle &setProcess(ProcessType proc) {
0078 m_process = proc;
0079 return *this;
0080 }
0081
0082 Particle setPdg(Acts::PdgParticle pdg) {
0083 m_pdg = pdg;
0084 return *this;
0085 }
0086
0087 Particle setCharge(Scalar charge) {
0088 m_charge = charge;
0089 return *this;
0090 }
0091
0092 Particle setMass(Scalar mass) {
0093 m_mass = mass;
0094 return *this;
0095 }
0096
0097 Particle &setParticleId(Barcode barcode) {
0098 m_particleId = barcode;
0099 return *this;
0100 }
0101
0102 Particle &setPosition4(const Vector4 &pos4) {
0103 m_position4 = pos4;
0104 return *this;
0105 }
0106
0107 Particle &setPosition4(const Vector3 &position, Scalar time) {
0108 m_position4.segment<3>(Acts::ePos0) = position;
0109 m_position4[Acts::eTime] = time;
0110 return *this;
0111 }
0112
0113 Particle &setPosition4(Scalar x, Scalar y, Scalar z, Scalar time) {
0114 m_position4[Acts::ePos0] = x;
0115 m_position4[Acts::ePos1] = y;
0116 m_position4[Acts::ePos2] = z;
0117 m_position4[Acts::eTime] = time;
0118 return *this;
0119 }
0120
0121 Particle &setDirection(const Vector3 &direction) {
0122 m_direction = direction;
0123 m_direction.normalize();
0124 return *this;
0125 }
0126
0127 Particle &setDirection(Scalar dx, Scalar dy, Scalar dz) {
0128 m_direction[Acts::ePos0] = dx;
0129 m_direction[Acts::ePos1] = dy;
0130 m_direction[Acts::ePos2] = dz;
0131 m_direction.normalize();
0132 return *this;
0133 }
0134
0135 Particle &setAbsoluteMomentum(Scalar absMomentum) {
0136 m_absMomentum = absMomentum;
0137 return *this;
0138 }
0139
0140
0141
0142
0143
0144
0145 Particle &correctEnergy(Scalar delta) {
0146 const auto newEnergy = std::hypot(m_mass, m_absMomentum) + delta;
0147 if (newEnergy <= m_mass) {
0148 m_absMomentum = Scalar{0};
0149 } else {
0150 m_absMomentum = std::sqrt(newEnergy * newEnergy - m_mass * m_mass);
0151 }
0152 return *this;
0153 }
0154
0155
0156 constexpr Barcode particleId() const { return m_particleId; }
0157
0158 constexpr ProcessType process() const { return m_process; }
0159
0160 constexpr Acts::PdgParticle pdg() const { return m_pdg; }
0161
0162 constexpr Acts::PdgParticle absolutePdg() const {
0163 return Acts::makeAbsolutePdgParticle(pdg());
0164 }
0165
0166 constexpr Scalar charge() const { return m_charge; }
0167
0168 constexpr Scalar absoluteCharge() const { return std::abs(m_charge); }
0169
0170 constexpr Scalar mass() const { return m_mass; }
0171
0172
0173 constexpr Acts::ParticleHypothesis hypothesis() const {
0174 return Acts::ParticleHypothesis(absolutePdg(), mass(), absoluteCharge());
0175 }
0176
0177 constexpr Scalar qOverP() const {
0178 return hypothesis().qOverP(absoluteMomentum(), charge());
0179 }
0180
0181
0182 constexpr const Vector4 &fourPosition() const { return m_position4; }
0183
0184 auto position() const { return m_position4.segment<3>(Acts::ePos0); }
0185
0186 Scalar time() const { return m_position4[Acts::eTime]; }
0187
0188 Vector4 fourMomentum() const {
0189 Vector4 mom4;
0190
0191 mom4[Acts::eMom0] = m_absMomentum * m_direction[Acts::ePos0];
0192 mom4[Acts::eMom1] = m_absMomentum * m_direction[Acts::ePos1];
0193 mom4[Acts::eMom2] = m_absMomentum * m_direction[Acts::ePos2];
0194 mom4[Acts::eEnergy] = energy();
0195 return mom4;
0196 }
0197
0198 const Vector3 &direction() const { return m_direction; }
0199
0200 Scalar theta() const { return Acts::VectorHelpers::theta(direction()); }
0201
0202 Scalar phi() const { return Acts::VectorHelpers::phi(direction()); }
0203
0204 Scalar transverseMomentum() const {
0205 return m_absMomentum * m_direction.segment<2>(Acts::eMom0).norm();
0206 }
0207
0208 constexpr Scalar absoluteMomentum() const { return m_absMomentum; }
0209
0210 Vector3 momentum() const { return absoluteMomentum() * direction(); }
0211
0212 Scalar energy() const { return std::hypot(m_mass, m_absMomentum); }
0213
0214
0215 constexpr bool isAlive() const { return Scalar{0} < m_absMomentum; }
0216
0217 constexpr bool isSecondary() const {
0218 return particleId().vertexSecondary() != 0 ||
0219 particleId().generation() != 0 || particleId().subParticle() != 0;
0220 }
0221
0222
0223
0224
0225
0226
0227 constexpr Particle &setProperTime(Scalar properTime) {
0228 m_properTime = properTime;
0229 return *this;
0230 }
0231
0232 constexpr Scalar properTime() const { return m_properTime; }
0233
0234
0235
0236
0237
0238 constexpr Particle &setMaterialPassed(Scalar pathInX0, Scalar pathInL0) {
0239 m_pathInX0 = pathInX0;
0240 m_pathInL0 = pathInL0;
0241 return *this;
0242 }
0243
0244 constexpr Scalar pathInX0() const { return m_pathInX0; }
0245
0246 constexpr Scalar pathInL0() const { return m_pathInL0; }
0247
0248
0249
0250
0251 Particle &setReferenceSurface(const Acts::Surface *surface) {
0252 m_referenceSurface = surface;
0253 return *this;
0254 }
0255
0256
0257 const Acts::Surface *referenceSurface() const { return m_referenceSurface; }
0258
0259
0260 bool hasReferenceSurface() const { return m_referenceSurface != nullptr; }
0261
0262
0263 Acts::Result<Acts::BoundTrackParameters> boundParameters(
0264 const Acts::GeometryContext &gctx) const {
0265 if (!hasReferenceSurface()) {
0266 return Acts::Result<Acts::BoundTrackParameters>::failure(
0267 std::error_code());
0268 }
0269 Acts::Result<Acts::Vector2> localResult =
0270 m_referenceSurface->globalToLocal(gctx, position(), direction());
0271 if (!localResult.ok()) {
0272 return localResult.error();
0273 }
0274 Acts::BoundVector params;
0275 params << localResult.value(), phi(), theta(), qOverP(), time();
0276 return Acts::BoundTrackParameters(referenceSurface()->getSharedPtr(),
0277 params, std::nullopt, hypothesis());
0278 }
0279
0280 Acts::CurvilinearTrackParameters curvilinearParameters() const {
0281 return Acts::CurvilinearTrackParameters(
0282 fourPosition(), direction(), qOverP(), std::nullopt, hypothesis());
0283 }
0284
0285
0286
0287
0288 constexpr Particle &setNumberOfHits(std::uint32_t nHits) {
0289 m_numberOfHits = nHits;
0290 return *this;
0291 }
0292
0293
0294 constexpr std::uint32_t numberOfHits() const { return m_numberOfHits; }
0295
0296
0297
0298
0299 constexpr Particle &setOutcome(ParticleOutcome outcome) {
0300 m_outcome = outcome;
0301 return *this;
0302 }
0303
0304
0305 constexpr ParticleOutcome outcome() const { return m_outcome; }
0306
0307 private:
0308
0309
0310 Barcode m_particleId;
0311
0312 ProcessType m_process = ProcessType::eUndefined;
0313
0314 Acts::PdgParticle m_pdg = Acts::PdgParticle::eInvalid;
0315
0316 Scalar m_charge = Scalar{0};
0317 Scalar m_mass = Scalar{0};
0318
0319 Vector3 m_direction = Vector3::UnitZ();
0320 Scalar m_absMomentum = Scalar{0};
0321 Vector4 m_position4 = Vector4::Zero();
0322
0323 Scalar m_properTime = Scalar{0};
0324
0325 Scalar m_pathInX0 = Scalar{0};
0326 Scalar m_pathInL0 = Scalar{0};
0327
0328 std::uint32_t m_numberOfHits = 0;
0329
0330 const Acts::Surface *m_referenceSurface{nullptr};
0331
0332 ParticleOutcome m_outcome = ParticleOutcome::Alive;
0333 };
0334
0335 std::ostream &operator<<(std::ostream &os, const Particle &particle);
0336
0337 }