Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
EventAction.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file EventAction.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2020 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
9 #include "EventAction.hpp"
10 
11 #include <stdexcept>
12 
13 #include <G4Event.hh>
14 #include <G4RunManager.hh>
15 
16 #include "SteppingAction.hpp"
17 
18 namespace {
19 
26 bool findAttribute(const HepMC3::ConstGenVertexPtr& vertex,
27  const std::vector<std::string>& processFilter) {
28  // Consider only 1->1 vertices to keep a correct history
29  if ((vertex->particles_in().size() == 1) &&
30  (vertex->particles_out().size() == 1)) {
31  // Test for all attributes if one matches the filter pattern
32  const std::vector<std::string> vertexAttributes = vertex->attribute_names();
33  for (const auto& att : vertexAttributes) {
34  const std::string process = vertex->attribute_as_string(att);
35  if (std::find(processFilter.begin(), processFilter.end(), process) !=
36  processFilter.end()) {
37  return true;
38  }
39  }
40  }
41  return false;
42 }
43 
50 void reduceVertex(HepMC3::GenEvent& event, HepMC3::GenVertexPtr vertex,
51  const std::vector<std::string>& processFilter) {
52  // Store the particles associated to the vertex
53  HepMC3::GenParticlePtr particleIn = vertex->particles_in()[0];
54  HepMC3::GenParticlePtr particleOut = vertex->particles_out()[0];
55 
56  // Walk backwards to find all vertices in a row that match the pattern
57  while (findAttribute(particleIn->production_vertex(), processFilter)) {
58  // Take the particles before the vertex and remove particles & vertices in
59  // between
60  HepMC3::GenVertexPtr currentVertex = particleOut->production_vertex();
61  HepMC3::GenParticlePtr nextParticle = currentVertex->particles_in()[0];
62  // Cut connections from particle and remove it
63  if (particleIn->end_vertex()) {
64  particleIn->end_vertex()->remove_particle_in(particleIn);
65  }
66  currentVertex->remove_particle_out(particleIn);
67  event.remove_particle(particleIn);
68  // Cut connections from vertext and remove it
69  particleIn = nextParticle;
70  currentVertex->remove_particle_in(particleIn);
71  event.remove_vertex(currentVertex);
72  }
73  // Walk forwards to find all vertices in a row that match the pattern
74  while (findAttribute(particleOut->end_vertex(), processFilter)) {
75  // Take the particles after the vertex and remove particles & vertices in
76  // between
77  HepMC3::GenVertexPtr currentVertex = particleOut->end_vertex();
78  HepMC3::GenParticlePtr nextParticle = currentVertex->particles_out()[0];
79  // Cut connections from particle and remove it
80  if (particleOut->production_vertex()) {
81  particleOut->production_vertex()->remove_particle_out(particleOut);
82  }
83  currentVertex->remove_particle_in(particleOut);
84  event.remove_particle(particleOut);
85  // Cut connections from vertext and remove it
86  particleOut = nextParticle;
87  currentVertex->remove_particle_out(particleOut);
88  event.remove_vertex(currentVertex);
89  }
90 
91  // Build the dummy vertex
92  auto reducedVertex = std::make_shared<HepMC3::GenVertex>();
93  event.add_vertex(reducedVertex);
94 
95  reducedVertex->add_particle_in(particleIn);
96  reducedVertex->add_particle_out(particleOut);
97 
98  // Remove and replace the old vertex
99  event.remove_vertex(vertex);
100  vertex = reducedVertex;
101 }
102 
109 void followOutgoingParticles(HepMC3::GenEvent& event,
110  const HepMC3::GenVertexPtr& vertex,
111  const std::vector<std::string>& processFilter) {
112  // Replace and reduce vertex if it should be filtered
113  if (findAttribute(vertex, processFilter)) {
114  reduceVertex(event, vertex, processFilter);
115  }
116  // Move forward to the next vertices
117  for (const auto& particle : vertex->particles_out()) {
118  followOutgoingParticles(event, particle->end_vertex(), processFilter);
119  }
120 }
121 } // namespace
122 
123 namespace ActsExamples::Geant4::HepMC3 {
124 
126 
128  // Static access function via G4RunManager
129  return s_instance;
130 }
131 
132 EventAction::EventAction(std::vector<std::string> processFilter)
133  : G4UserEventAction(), m_processFilter(std::move(processFilter)) {
134  if (s_instance != nullptr) {
135  throw std::logic_error("Attempted to duplicate a singleton");
136  } else {
137  s_instance = this;
138  }
139 }
140 
142  s_instance = nullptr;
143 }
144 
145 void EventAction::BeginOfEventAction(const G4Event* /*event*/) {
147  m_event = ::HepMC3::GenEvent(::HepMC3::Units::GEV, ::HepMC3::Units::MM);
148  m_event.add_beam_particle(std::make_shared<::HepMC3::GenParticle>());
149 }
150 
151 void EventAction::EndOfEventAction(const G4Event* /*event*/) {
152  // Fast exit if the event is empty
153  if (m_event.vertices().empty()) {
154  return;
155  }
156  // Filter irrelevant processes
157  auto currentVertex = m_event.vertices()[0];
158  for (auto& bp : m_event.beams()) {
159  if (!bp->end_vertex()) {
160  currentVertex->add_particle_in(bp);
161  }
162  }
163  followOutgoingParticles(m_event, currentVertex, m_processFilter);
164  // Remove vertices w/o outgoing particles and particles w/o production
165  // vertices
166  while (true) {
167  bool sane = true;
168  for (const auto& v : m_event.vertices()) {
169  if (!v) {
170  continue;
171  }
172  if (v->particles_out().empty()) {
173  m_event.remove_vertex(v);
174  sane = false;
175  }
176  }
177  for (const auto& p : m_event.particles()) {
178  if (!p) {
179  continue;
180  }
181  if (!p->production_vertex()) {
182  m_event.remove_particle(p);
183  sane = false;
184  }
185  }
186  if (sane) {
187  break;
188  }
189  }
190 }
191 
194 }
195 
196 ::HepMC3::GenEvent& EventAction::event() {
197  return m_event;
198 }
199 } // namespace ActsExamples::Geant4::HepMC3