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