Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
EventRecording.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file EventRecording.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 
10 
15 
16 #include <iostream>
17 #include <stdexcept>
18 
19 #include <FTFP_BERT.hh>
20 #include <G4RunManager.hh>
21 #include <G4VUserDetectorConstruction.hh>
22 #include <HepMC3/GenParticle.h>
23 
24 #include "EventAction.hpp"
26 #include "RunAction.hpp"
27 #include "SteppingAction.hpp"
28 
30  m_runManager = nullptr;
31 }
32 
36  : ActsExamples::IAlgorithm("EventRecording", level),
37  m_cfg(config),
38  m_runManager(std::make_unique<G4RunManager>()) {
39  if (m_cfg.inputParticles.empty()) {
40  throw std::invalid_argument("Missing input particle collection");
41  }
42  if (m_cfg.outputHepMcTracks.empty()) {
43  throw std::invalid_argument("Missing output event collection");
44  }
46  throw std::invalid_argument("Missing detector construction object");
47  }
48 
51 
52  // Now set up the Geant4 simulation
53 
54  // G4RunManager deals with the lifetime of these objects
55  m_runManager->SetUserInitialization(
56  m_cfg.detectorConstructionFactory->factorize().release());
57  m_runManager->SetUserInitialization(new FTFP_BERT);
59  m_runManager->SetUserAction(
61  m_runManager->SetUserAction(
63  m_cfg.seed2));
64  m_runManager->SetUserAction(
66  m_runManager->Initialize();
67 }
68 
70  const ActsExamples::AlgorithmContext& context) const {
71  // ensure exclusive access to the geant run manager
72  std::lock_guard<std::mutex> guard(m_runManagerLock);
73 
74  // Retrieve the initial particles
75  const auto initialParticles = m_inputParticles(context);
76 
77  // Storage of events that will be produced
78  std::vector<HepMC3::GenEvent> events;
79  events.reserve(initialParticles.size());
80 
81  for (const auto& part : initialParticles) {
82  // Prepare the particle gun
84  ->prepareParticleGun(part);
85 
86  // Begin with the simulation
87  m_runManager->BeamOn(1);
88 
89  // Test if the event was aborted
90  if (Geant4::HepMC3::SteppingAction::instance()->eventAborted()) {
91  continue;
92  }
93 
94  // Set event start time
95  HepMC3::GenEvent event =
97  HepMC3::FourVector shift(0., 0., 0., part.time() / Acts::UnitConstants::mm);
98  event.shift_position_by(shift);
99 
100  // Set beam particle properties
101  const Acts::Vector4 momentum4 =
102  part.fourMomentum() / Acts::UnitConstants::GeV;
103  HepMC3::FourVector beamMom4(momentum4[0], momentum4[1], momentum4[2],
104  momentum4[3]);
105  auto beamParticle = event.particles()[0];
106  beamParticle->set_momentum(beamMom4);
107  beamParticle->set_pid(part.pdg());
108 
109  if (m_cfg.processSelect.empty()) {
110  // Store the result
111  events.push_back(std::move(event));
112  } else {
113  bool storeEvent = false;
114  // Test if the event has a process of interest in it
115  for (const auto& vertex : event.vertices()) {
116  if (vertex->id() == -1) {
117  vertex->add_particle_in(beamParticle);
118  }
119  const std::vector<std::string> vertexAttributes =
120  vertex->attribute_names();
121  for (const auto& att : vertexAttributes) {
122  if ((vertex->attribute_as_string(att).find(m_cfg.processSelect) !=
123  std::string::npos) &&
124  !vertex->particles_in().empty() &&
125  vertex->particles_in()[0]->attribute<HepMC3::IntAttribute>(
126  "TrackID") &&
127  vertex->particles_in()[0]
128  ->attribute<HepMC3::IntAttribute>("TrackID")
129  ->value() == 1) {
130  storeEvent = true;
131  break;
132  }
133  }
134  if (storeEvent) {
135  break;
136  }
137  }
138  // Store the result
139  if (storeEvent) {
140  // Remove vertices w/o outgoing particles and particles w/o production
141  // vertices
142  while (true) {
143  bool sane = true;
144  for (const auto& v : event.vertices()) {
145  if (!v) {
146  continue;
147  }
148  if (v->particles_out().empty()) {
149  event.remove_vertex(v);
150  sane = false;
151  }
152  }
153  for (const auto& p : event.particles()) {
154  if (!p) {
155  continue;
156  }
157  if (!p->production_vertex()) {
158  event.remove_particle(p);
159  sane = false;
160  }
161  }
162  if (sane) {
163  break;
164  }
165  }
166  events.push_back(std::move(event));
167  }
168  }
169  }
170 
171  ACTS_INFO(initialParticles.size() << " initial particles provided");
172  ACTS_INFO(events.size() << " tracks generated");
173 
174  // Write the recorded material to the event store
175  m_outputEvents(context, std::move(events));
176 
178 }