File indexing completed on 2025-01-18 09:11:37
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsExamples/HepMC/HepMCProcessExtractor.hpp"
0010
0011 #include "ActsExamples/Framework/WhiteBoard.hpp"
0012 #include "ActsExamples/Io/HepMC3/HepMC3Particle.hpp"
0013
0014 #include <algorithm>
0015 #include <stdexcept>
0016
0017 #include <HepMC3/GenEvent.h>
0018 #include <HepMC3/GenParticle.h>
0019 #include <HepMC3/GenVertex.h>
0020
0021 namespace ActsExamples {
0022
0023 namespace {
0024
0025
0026
0027
0028
0029
0030
0031 HepMC3::ConstGenParticlePtr searchProcessParticleById(
0032 const HepMC3::ConstGenVertexPtr& vertex, const int id) {
0033
0034 for (const auto& particle : vertex->particles_out()) {
0035 const int trackid =
0036 particle->attribute<HepMC3::IntAttribute>("TrackID")->value();
0037
0038 if (trackid == id) {
0039 return particle;
0040 }
0041 }
0042 return nullptr;
0043 }
0044
0045
0046
0047
0048
0049
0050
0051 void setPassedMaterial(const HepMC3::ConstGenVertexPtr& vertex, const int id,
0052 SimParticle& particle) {
0053 double x0 = 0.;
0054 double l0 = 0.;
0055 HepMC3::ConstGenParticlePtr currentParticle = nullptr;
0056 HepMC3::ConstGenVertexPtr currentVertex = vertex;
0057
0058 while (currentVertex && !currentVertex->particles_in().empty() &&
0059 currentVertex->particles_in()[0]->attribute<HepMC3::IntAttribute>(
0060 "TrackID") &&
0061 currentVertex->particles_in()[0]
0062 ->attribute<HepMC3::IntAttribute>("TrackID")
0063 ->value() == id) {
0064
0065 currentParticle = currentVertex->particles_in()[0];
0066 const double stepLength =
0067 currentParticle->attribute<HepMC3::DoubleAttribute>("StepLength")
0068 ->value();
0069
0070 x0 +=
0071 stepLength /
0072 currentParticle->attribute<HepMC3::DoubleAttribute>("NextX0")->value();
0073 l0 +=
0074 stepLength /
0075 currentParticle->attribute<HepMC3::DoubleAttribute>("NextL0")->value();
0076 currentVertex = currentParticle->production_vertex();
0077 }
0078
0079 particle.final().setMaterialPassed(x0, l0);
0080 }
0081
0082
0083
0084
0085
0086
0087
0088
0089 std::vector<SimParticle> selectOutgoingParticles(
0090 const HepMC3::ConstGenVertexPtr& vertex, const int trackID) {
0091 std::vector<SimParticle> finalStateParticles;
0092
0093
0094 HepMC3::ConstGenParticlePtr procPart =
0095 searchProcessParticleById(vertex, trackID);
0096
0097
0098 HepMC3::ConstGenVertexPtr endVertex = procPart->end_vertex();
0099 if (endVertex
0100 ->attribute<HepMC3::StringAttribute>("NextProcessOf-" +
0101 std::to_string(trackID))
0102 ->value() != "Death") {
0103
0104 finalStateParticles.push_back(HepMC3Particle::particle(procPart));
0105 } else {
0106
0107 for (const HepMC3::ConstGenParticlePtr& procPartOut :
0108 endVertex->particles_out()) {
0109 if (procPartOut->attribute<HepMC3::IntAttribute>("TrackID")->value() ==
0110 trackID &&
0111 procPartOut->end_vertex()) {
0112 for (const HepMC3::ConstGenParticlePtr& dyingPartOut :
0113 procPartOut->end_vertex()->particles_out()) {
0114 finalStateParticles.push_back(HepMC3Particle::particle(dyingPartOut));
0115 }
0116 }
0117 }
0118 }
0119
0120
0121 const std::vector<std::string> attributes = endVertex->attribute_names();
0122 for (const auto& att : attributes) {
0123
0124 if (att.find("InitialParametersOf") != std::string::npos) {
0125 const std::vector<double> mom4 =
0126 endVertex->attribute<HepMC3::VectorDoubleAttribute>(att)->value();
0127 const HepMC3::FourVector& pos4 = endVertex->position();
0128 const int id = stoi(att.substr(att.find("-") + 1));
0129 HepMC3::ConstGenParticlePtr genParticle =
0130 searchProcessParticleById(endVertex, id);
0131 ActsFatras::Barcode barcode = ActsFatras::Barcode().setParticle(id);
0132 auto pid = static_cast<Acts::PdgParticle>(genParticle->pid());
0133
0134
0135 SimParticleState simParticle(barcode, pid);
0136 simParticle.setPosition4(pos4.x(), pos4.y(), pos4.z(), pos4.t());
0137 Acts::Vector3 mom3(mom4[0], mom4[1], mom4[2]);
0138 simParticle.setDirection(mom3.normalized());
0139 simParticle.setAbsoluteMomentum(mom3.norm());
0140
0141
0142 finalStateParticles.push_back(SimParticle(simParticle, simParticle));
0143 }
0144 }
0145
0146 return finalStateParticles;
0147 }
0148
0149
0150
0151
0152
0153 void filterAndSort(const HepMCProcessExtractor::Config& cfg,
0154 ExtractedSimulationProcessContainer& interactions) {
0155 for (auto& interaction : interactions) {
0156 for (auto cit = interaction.after.cbegin();
0157 cit != interaction.after.cend();) {
0158
0159 if (cit->pdg() < cfg.absPdgMin || cit->pdg() > cfg.absPdgMax ||
0160 cit->absoluteMomentum() < cfg.pMin) {
0161 interaction.after.erase(cit);
0162 } else {
0163 cit++;
0164 }
0165 }
0166 }
0167
0168
0169 for (auto& interaction : interactions) {
0170 std::ranges::sort(interaction.after, std::greater{},
0171 [](const auto& a) { return a.absoluteMomentum(); });
0172 }
0173 }
0174
0175 }
0176
0177 HepMCProcessExtractor::~HepMCProcessExtractor() = default;
0178
0179 HepMCProcessExtractor::HepMCProcessExtractor(
0180 HepMCProcessExtractor::Config config, Acts::Logging::Level level)
0181 : IAlgorithm("HepMCProcessExtractor", level), m_cfg(std::move(config)) {
0182 if (m_cfg.inputEvents.empty()) {
0183 throw std::invalid_argument("Missing input event collection");
0184 }
0185 if (m_cfg.outputSimulationProcesses.empty()) {
0186 throw std::invalid_argument("Missing output collection");
0187 }
0188 if (m_cfg.extractionProcess.empty()) {
0189 throw std::invalid_argument("Missing extraction process");
0190 }
0191
0192 m_inputEvents.initialize(m_cfg.inputEvents);
0193 m_outputSimulationProcesses.initialize(m_cfg.outputSimulationProcesses);
0194 }
0195
0196 ProcessCode HepMCProcessExtractor::execute(
0197 const AlgorithmContext& context) const {
0198
0199 const auto events = m_inputEvents(context);
0200
0201 ExtractedSimulationProcessContainer fractions;
0202 for (const HepMC3::GenEvent& event : events) {
0203
0204 if (event.particles().empty() || event.vertices().empty()) {
0205 break;
0206 }
0207
0208
0209 HepMC3::ConstGenParticlePtr initialParticle = event.particles()[0];
0210 SimParticle simParticle = HepMC3Particle::particle(initialParticle);
0211
0212
0213 SimParticle particleToInteraction;
0214 std::vector<SimParticle> finalStateParticles;
0215
0216 bool vertexFound = false;
0217 for (const auto& vertex : event.vertices()) {
0218 const std::vector<std::string> attributes = vertex->attribute_names();
0219 for (const auto& attribute : attributes) {
0220 if (vertex->attribute_as_string(attribute).find(
0221 m_cfg.extractionProcess) != std::string::npos) {
0222 const int procID = stoi(attribute.substr(attribute.find("-") + 1));
0223
0224 particleToInteraction =
0225 HepMC3Particle::particle(vertex->particles_in()[0]);
0226
0227 setPassedMaterial(vertex, procID, particleToInteraction);
0228
0229 finalStateParticles = selectOutgoingParticles(vertex, procID);
0230 vertexFound = true;
0231 break;
0232 }
0233 }
0234 if (vertexFound) {
0235 break;
0236 }
0237 }
0238 fractions.push_back(ExtractedSimulationProcess{
0239 simParticle, particleToInteraction, finalStateParticles});
0240 }
0241
0242
0243 filterAndSort(m_cfg, fractions);
0244
0245 ACTS_INFO(events.size() << " processed");
0246
0247
0248 m_outputSimulationProcesses(context, std::move(fractions));
0249
0250 return ProcessCode::SUCCESS;
0251 }
0252
0253 }