File indexing completed on 2025-01-18 09:11:36
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "EventAction.hpp"
0010
0011 #include "Acts/Utilities/Helpers.hpp"
0012
0013 #include <stdexcept>
0014
0015 #include <G4Event.hh>
0016 #include <G4RunManager.hh>
0017
0018 #include "SteppingAction.hpp"
0019
0020 namespace {
0021
0022
0023
0024
0025
0026
0027
0028 bool findAttribute(const HepMC3::ConstGenVertexPtr& vertex,
0029 const std::vector<std::string>& processFilter) {
0030
0031 if ((vertex->particles_in().size() == 1) &&
0032 (vertex->particles_out().size() == 1)) {
0033
0034 const std::vector<std::string> vertexAttributes = vertex->attribute_names();
0035 for (const auto& att : vertexAttributes) {
0036 const std::string process = vertex->attribute_as_string(att);
0037 if (Acts::rangeContainsValue(processFilter, process)) {
0038 return true;
0039 }
0040 }
0041 }
0042 return false;
0043 }
0044
0045
0046
0047
0048
0049
0050
0051 void reduceVertex(HepMC3::GenEvent& event, HepMC3::GenVertexPtr vertex,
0052 const std::vector<std::string>& processFilter) {
0053
0054 HepMC3::GenParticlePtr particleIn = vertex->particles_in()[0];
0055 HepMC3::GenParticlePtr particleOut = vertex->particles_out()[0];
0056
0057
0058 while (findAttribute(particleIn->production_vertex(), processFilter)) {
0059
0060
0061 HepMC3::GenVertexPtr currentVertex = particleOut->production_vertex();
0062 HepMC3::GenParticlePtr nextParticle = currentVertex->particles_in()[0];
0063
0064 if (particleIn->end_vertex()) {
0065 particleIn->end_vertex()->remove_particle_in(particleIn);
0066 }
0067 currentVertex->remove_particle_out(particleIn);
0068 event.remove_particle(particleIn);
0069
0070 particleIn = nextParticle;
0071 currentVertex->remove_particle_in(particleIn);
0072 event.remove_vertex(currentVertex);
0073 }
0074
0075 while (findAttribute(particleOut->end_vertex(), processFilter)) {
0076
0077
0078 HepMC3::GenVertexPtr currentVertex = particleOut->end_vertex();
0079 HepMC3::GenParticlePtr nextParticle = currentVertex->particles_out()[0];
0080
0081 if (particleOut->production_vertex()) {
0082 particleOut->production_vertex()->remove_particle_out(particleOut);
0083 }
0084 currentVertex->remove_particle_in(particleOut);
0085 event.remove_particle(particleOut);
0086
0087 particleOut = nextParticle;
0088 currentVertex->remove_particle_out(particleOut);
0089 event.remove_vertex(currentVertex);
0090 }
0091
0092
0093 auto reducedVertex = std::make_shared<HepMC3::GenVertex>();
0094 event.add_vertex(reducedVertex);
0095
0096 reducedVertex->add_particle_in(particleIn);
0097 reducedVertex->add_particle_out(particleOut);
0098
0099
0100 event.remove_vertex(vertex);
0101 vertex = reducedVertex;
0102 }
0103
0104
0105
0106
0107
0108
0109
0110 void followOutgoingParticles(HepMC3::GenEvent& event,
0111 const HepMC3::GenVertexPtr& vertex,
0112 const std::vector<std::string>& processFilter) {
0113
0114 if (findAttribute(vertex, processFilter)) {
0115 reduceVertex(event, vertex, processFilter);
0116 }
0117
0118 for (const auto& particle : vertex->particles_out()) {
0119 followOutgoingParticles(event, particle->end_vertex(), processFilter);
0120 }
0121 }
0122 }
0123
0124 namespace ActsExamples::Geant4::HepMC3 {
0125
0126 EventAction* EventAction::s_instance = nullptr;
0127
0128 EventAction* EventAction::instance() {
0129
0130 return s_instance;
0131 }
0132
0133 EventAction::EventAction(std::vector<std::string> processFilter)
0134 : G4UserEventAction(), m_processFilter(std::move(processFilter)) {
0135 if (s_instance != nullptr) {
0136 throw std::logic_error("Attempted to duplicate a singleton");
0137 } else {
0138 s_instance = this;
0139 }
0140 }
0141
0142 EventAction::~EventAction() {
0143 s_instance = nullptr;
0144 }
0145
0146 void EventAction::BeginOfEventAction(const G4Event* ) {
0147 SteppingAction::instance()->clear();
0148 m_event = ::HepMC3::GenEvent(::HepMC3::Units::GEV, ::HepMC3::Units::MM);
0149 m_event.add_beam_particle(std::make_shared<::HepMC3::GenParticle>());
0150 }
0151
0152 void EventAction::EndOfEventAction(const G4Event* ) {
0153
0154 if (m_event.vertices().empty()) {
0155 return;
0156 }
0157
0158 auto currentVertex = m_event.vertices()[0];
0159 for (auto& bp : m_event.beams()) {
0160 if (!bp->end_vertex()) {
0161 currentVertex->add_particle_in(bp);
0162 }
0163 }
0164 followOutgoingParticles(m_event, currentVertex, m_processFilter);
0165
0166
0167 while (true) {
0168 bool sane = true;
0169 for (const auto& v : m_event.vertices()) {
0170 if (!v) {
0171 continue;
0172 }
0173 if (v->particles_out().empty()) {
0174 m_event.remove_vertex(v);
0175 sane = false;
0176 }
0177 }
0178 for (const auto& p : m_event.particles()) {
0179 if (!p) {
0180 continue;
0181 }
0182 if (!p->production_vertex()) {
0183 m_event.remove_particle(p);
0184 sane = false;
0185 }
0186 }
0187 if (sane) {
0188 break;
0189 }
0190 }
0191 }
0192
0193 void EventAction::clear() {
0194 SteppingAction::instance()->clear();
0195 }
0196
0197 ::HepMC3::GenEvent& EventAction::event() {
0198 return m_event;
0199 }
0200 }