File indexing completed on 2026-06-27 07:58:40
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011 #include "ActsExamples/Utilities/GroupBy.hpp"
0012 #include "ActsFatras/EventData/Particle.hpp"
0013 #include "ActsFatras/EventData/ParticleOutcome.hpp"
0014
0015 #include <boost/container/flat_set.hpp>
0016
0017 namespace ActsExamples {
0018
0019 using SimBarcode = ::ActsFatras::Barcode;
0020 using SimBarcodeContainer = ::boost::container::flat_set<SimBarcode>;
0021
0022 using SimParticleState = ::ActsFatras::Particle;
0023
0024 class SimParticle final {
0025 public:
0026
0027 SimParticle() = default;
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038 SimParticle(SimBarcode particleId, Acts::PdgParticle pdg, double charge,
0039 double mass)
0040 : m_initial(particleId, pdg, charge, mass),
0041 m_final(particleId, pdg, charge, mass) {}
0042
0043
0044
0045
0046
0047
0048
0049 SimParticle(SimBarcode particleId, Acts::PdgParticle pdg)
0050 : m_initial(particleId, pdg), m_final(particleId, pdg) {}
0051
0052 SimParticle(const SimParticleState& initial,
0053 const SimParticleState& finalState)
0054 : m_initial(initial), m_final(finalState) {
0055 if (m_initial.particleId() != m_final.particleId()) {
0056 throw std::invalid_argument("Particle id mismatch");
0057 }
0058 }
0059
0060 const SimParticleState& initialState() const { return m_initial; }
0061 const SimParticleState& finalState() const { return m_final; }
0062
0063 SimParticleState& initialState() { return m_initial; }
0064 SimParticleState& finalState() { return m_final; }
0065
0066
0067
0068
0069
0070
0071 SimParticle withParticleId(SimBarcode particleId) const {
0072 return SimParticle(initialState().withParticleId(particleId),
0073 finalState().withParticleId(particleId));
0074 }
0075
0076
0077 SimParticle& setProcess(ActsFatras::ProcessType proc) {
0078 initialState().setProcess(proc);
0079 finalState().setProcess(proc);
0080 return *this;
0081 }
0082
0083 SimParticle& setPdg(Acts::PdgParticle pdg) {
0084 initialState().setPdg(pdg);
0085 finalState().setPdg(pdg);
0086 return *this;
0087 }
0088
0089 SimParticle& setCharge(double charge) {
0090 initialState().setCharge(charge);
0091 finalState().setCharge(charge);
0092 return *this;
0093 }
0094
0095 SimParticle& setMass(double mass) {
0096 initialState().setMass(mass);
0097 finalState().setMass(mass);
0098 return *this;
0099 }
0100
0101 SimParticle& setParticleId(SimBarcode barcode) {
0102 initialState().setParticleId(barcode);
0103 finalState().setParticleId(barcode);
0104 return *this;
0105 }
0106
0107
0108 SimBarcode particleId() const { return initialState().particleId(); }
0109
0110 ActsFatras::ProcessType process() const { return initialState().process(); }
0111
0112 Acts::PdgParticle pdg() const { return initialState().pdg(); }
0113
0114 Acts::PdgParticle absolutePdg() const { return initialState().absolutePdg(); }
0115
0116 double charge() const { return initialState().charge(); }
0117
0118 double absoluteCharge() const { return initialState().absoluteCharge(); }
0119
0120 double mass() const { return initialState().mass(); }
0121
0122
0123 bool isSecondary() const { return initialState().isSecondary(); }
0124
0125
0126 Acts::ParticleHypothesis hypothesis() const {
0127 return initialState().hypothesis();
0128 }
0129
0130 double qOverP() const { return initialState().qOverP(); }
0131
0132
0133 const Acts::Vector4& fourPosition() const {
0134 return initialState().fourPosition();
0135 }
0136
0137 auto position() const { return initialState().position(); }
0138
0139 double time() const { return initialState().time(); }
0140
0141 Acts::Vector4 fourMomentum() const { return initialState().fourMomentum(); }
0142
0143 const Acts::Vector3& direction() const { return initialState().direction(); }
0144
0145 double theta() const { return initialState().theta(); }
0146
0147 double phi() const { return initialState().phi(); }
0148
0149 double transverseMomentum() const {
0150 return initialState().transverseMomentum();
0151 }
0152
0153 double absoluteMomentum() const { return initialState().absoluteMomentum(); }
0154
0155 Acts::Vector3 momentum() const { return initialState().momentum(); }
0156
0157 double energy() const { return initialState().energy(); }
0158
0159
0160 double energyLoss() const {
0161 return initialState().energy() - finalState().energy();
0162 }
0163
0164
0165 double pathInX0() const { return finalState().pathInX0(); }
0166
0167 double pathInL0() const { return finalState().pathInL0(); }
0168
0169
0170 std::uint32_t numberOfHits() const { return finalState().numberOfHits(); }
0171
0172
0173 ActsFatras::ParticleOutcome outcome() const { return finalState().outcome(); }
0174
0175 private:
0176 SimParticleState m_initial;
0177 SimParticleState m_final;
0178 };
0179
0180 std::ostream& operator<<(std::ostream& os, const SimParticle& particle);
0181
0182 namespace detail {
0183 struct CompareParticleId {
0184 using is_transparent = void;
0185 bool operator()(const SimParticleState& lhs,
0186 const SimParticleState& rhs) const {
0187 return lhs.particleId() < rhs.particleId();
0188 }
0189 bool operator()(const SimParticle& lhs, const SimParticle& rhs) const {
0190 return lhs.particleId() < rhs.particleId();
0191 }
0192 bool operator()(SimBarcode lhs, const SimParticleState& rhs) const {
0193 return lhs < rhs.particleId();
0194 }
0195 bool operator()(SimBarcode lhs, const SimParticle& rhs) const {
0196 return lhs < rhs.particleId();
0197 }
0198 bool operator()(const SimParticleState& lhs, SimBarcode rhs) const {
0199 return lhs.particleId() < rhs;
0200 }
0201 bool operator()(const SimParticle& lhs, SimBarcode rhs) const {
0202 return lhs.particleId() < rhs;
0203 }
0204 };
0205 struct PrimaryVertexIdGetter {
0206 SimBarcode operator()(const SimParticleState& particle) const {
0207 return SimBarcode().withVertexPrimary(
0208 particle.particleId().vertexPrimary());
0209 }
0210 SimBarcode operator()(const SimParticle& particle) const {
0211 return SimBarcode().withVertexPrimary(
0212 particle.particleId().vertexPrimary());
0213 }
0214 };
0215 struct SecondaryVertexIdGetter {
0216 SimBarcode operator()(const SimParticleState& particle) const {
0217 return SimBarcode()
0218 .withVertexPrimary(particle.particleId().vertexPrimary())
0219 .withVertexSecondary(particle.particleId().vertexSecondary());
0220 }
0221 SimBarcode operator()(const SimParticle& particle) const {
0222 return SimBarcode()
0223 .withVertexPrimary(particle.particleId().vertexPrimary())
0224 .withVertexSecondary(particle.particleId().vertexSecondary());
0225 }
0226 };
0227 struct VertexIdGetter {
0228 SimBarcode operator()(const SimParticleState& particle) const {
0229 return particle.particleId().vertexId();
0230 }
0231 SimBarcode operator()(const SimParticle& particle) const {
0232 return particle.particleId().vertexId();
0233 }
0234 };
0235 }
0236
0237 using SimParticleStateContainer =
0238 ::boost::container::flat_set<SimParticleState, detail::CompareParticleId>;
0239
0240
0241 using SimParticleContainer =
0242 ::boost::container::flat_set<SimParticle, detail::CompareParticleId>;
0243
0244
0245 inline GroupBy<SimParticleContainer::const_iterator,
0246 detail::PrimaryVertexIdGetter>
0247 groupByPrimaryVertex(const SimParticleContainer& container) {
0248 return makeGroupBy(container, detail::PrimaryVertexIdGetter());
0249 }
0250
0251
0252
0253
0254
0255 inline GroupBy<SimParticleContainer::const_iterator,
0256 detail::SecondaryVertexIdGetter>
0257 groupBySecondaryVertex(const SimParticleContainer& container) {
0258 return makeGroupBy(container, detail::SecondaryVertexIdGetter());
0259 }
0260
0261
0262
0263
0264
0265 inline GroupBy<SimParticleContainer::const_iterator, detail::VertexIdGetter>
0266 groupByVertexId(const SimParticleContainer& container) {
0267 return makeGroupBy(container, detail::VertexIdGetter());
0268 }
0269
0270 }