Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HepMCProcessExtractor.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file HepMCProcessExtractor.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 
13 
14 #include <stdexcept>
15 
16 #include <HepMC3/GenEvent.h>
17 #include <HepMC3/GenParticle.h>
18 #include <HepMC3/GenVertex.h>
19 
20 namespace {
21 
28 HepMC3::ConstGenParticlePtr searchProcessParticleById(
29  const HepMC3::ConstGenVertexPtr& vertex, const int id) {
30  // Loop over all outgoing particles
31  for (const auto& particle : vertex->particles_out()) {
32  const int trackid =
33  particle->attribute<HepMC3::IntAttribute>("TrackID")->value();
34  // Compare ID
35  if (trackid == id) {
36  return particle;
37  }
38  }
39  return nullptr;
40 }
41 
48 void setPassedMaterial(const HepMC3::ConstGenVertexPtr& vertex, const int id,
50  double x0 = 0.;
51  double l0 = 0.;
52  HepMC3::ConstGenParticlePtr currentParticle = nullptr;
53  HepMC3::ConstGenVertexPtr currentVertex = vertex;
54  // Loop backwards and test whether the track still exists
55  while (currentVertex && !currentVertex->particles_in().empty() &&
56  currentVertex->particles_in()[0]->attribute<HepMC3::IntAttribute>(
57  "TrackID") &&
58  currentVertex->particles_in()[0]
59  ->attribute<HepMC3::IntAttribute>("TrackID")
60  ->value() == id) {
61  // Get the step length
62  currentParticle = currentVertex->particles_in()[0];
63  const double stepLength =
64  currentParticle->attribute<HepMC3::DoubleAttribute>("StepLength")
65  ->value();
66  // Add the passed material
67  x0 +=
68  stepLength /
69  currentParticle->attribute<HepMC3::DoubleAttribute>("NextX0")->value();
70  l0 +=
71  stepLength /
72  currentParticle->attribute<HepMC3::DoubleAttribute>("NextL0")->value();
73  currentVertex = currentParticle->production_vertex();
74  }
75  // Assign the passed material to the particle
76  particle.setMaterialPassed(x0, l0);
77 }
78 
86 std::vector<ActsExamples::SimParticle> selectOutgoingParticles(
87  const HepMC3::ConstGenVertexPtr& vertex, const int trackID) {
88  std::vector<ActsExamples::SimParticle> finalStateParticles;
89 
90  // Identify the ingoing particle in the outgoing particles
91  HepMC3::ConstGenParticlePtr procPart =
92  searchProcessParticleById(vertex, trackID);
93 
94  // Test whether this particle survives or dies
95  HepMC3::ConstGenVertexPtr endVertex = procPart->end_vertex();
96  if (endVertex
97  ->attribute<HepMC3::StringAttribute>("NextProcessOf-" +
98  std::to_string(trackID))
99  ->value() != "Death") {
100  // Store the particle if it survives
101  finalStateParticles.push_back(
103  } else {
104  // Store the leftovers if it dies
105  for (const HepMC3::ConstGenParticlePtr& procPartOut :
106  endVertex->particles_out()) {
107  if (procPartOut->attribute<HepMC3::IntAttribute>("TrackID")->value() ==
108  trackID &&
109  procPartOut->end_vertex()) {
110  for (const HepMC3::ConstGenParticlePtr& dyingPartOut :
111  procPartOut->end_vertex()->particles_out()) {
112  finalStateParticles.push_back(
114  }
115  }
116  }
117  }
118 
119  // Record the particles produced in this process
120  const std::vector<std::string> attributes = endVertex->attribute_names();
121  for (const auto& att : attributes) {
122  // Search for initial parameters
123  if (att.find("InitialParametersOf") != std::string::npos) {
124  const std::vector<double> mom4 =
125  endVertex->attribute<HepMC3::VectorDoubleAttribute>(att)->value();
126  const HepMC3::FourVector& pos4 = endVertex->position();
127  const int id = stoi(att.substr(att.find("-") + 1));
128  HepMC3::ConstGenParticlePtr genParticle =
129  searchProcessParticleById(endVertex, id);
131  auto pid = static_cast<Acts::PdgParticle>(genParticle->pid());
132 
133  // Build an Acts particle out of the data
134  ActsExamples::SimParticle simParticle(barcode, pid);
135  simParticle.setPosition4(pos4.x(), pos4.y(), pos4.z(), pos4.t());
136  Acts::Vector3 mom3(mom4[0], mom4[1], mom4[2]);
137  simParticle.setDirection(mom3.normalized());
138  simParticle.setAbsoluteMomentum(mom3.norm());
139 
140  // Store the particle
141  finalStateParticles.push_back(simParticle);
142  }
143  }
144 
145  return finalStateParticles;
146 }
147 
152 void filterAndSort(
155  for (auto& interaction : interactions) {
156  for (auto cit = interaction.after.cbegin();
157  cit != interaction.after.cend();) {
158  // Test whether a particle fulfills the conditions
159  if (cit->pdg() < cfg.absPdgMin || cit->pdg() > cfg.absPdgMax ||
160  cit->absoluteMomentum() < cfg.pMin) {
161  interaction.after.erase(cit);
162  } else {
163  cit++;
164  }
165  }
166  }
167 
168  // Sort the particles based on their momentum
169  for (auto& interaction : interactions) {
170  std::sort(interaction.after.begin(), interaction.after.end(),
172  return a.absoluteMomentum() > b.absoluteMomentum();
173  });
174  }
175 }
176 } // namespace
177 
179 
183  : ActsExamples::IAlgorithm("HepMCProcessExtractor", level),
184  m_cfg(std::move(config)) {
185  if (m_cfg.inputEvents.empty()) {
186  throw std::invalid_argument("Missing input event collection");
187  }
188  if (m_cfg.outputSimulationProcesses.empty()) {
189  throw std::invalid_argument("Missing output collection");
190  }
191  if (m_cfg.extractionProcess.empty()) {
192  throw std::invalid_argument("Missing extraction process");
193  }
194 
197 }
198 
200  const ActsExamples::AlgorithmContext& context) const {
201  // Retrieve the initial particles
202  const auto events = m_inputEvents(context);
203 
205  for (const HepMC3::GenEvent& event : events) {
206  // Fast exit
207  if (event.particles().empty() || event.vertices().empty()) {
208  break;
209  }
210 
211  // Get the initial particle
212  HepMC3::ConstGenParticlePtr initialParticle = event.particles()[0];
213  ActsExamples::SimParticle simParticle =
214  HepMC3Particle::particle(initialParticle);
215 
216  // Get the final state particles
217  ActsExamples::SimParticle particleToInteraction;
218  std::vector<ActsExamples::SimParticle> finalStateParticles;
219  // Search the process vertex
220  bool vertexFound = false;
221  for (const auto& vertex : event.vertices()) {
222  const std::vector<std::string> attributes = vertex->attribute_names();
223  for (const auto& attribute : attributes) {
224  if (vertex->attribute_as_string(attribute).find(
225  m_cfg.extractionProcess) != std::string::npos) {
226  const int procID = stoi(attribute.substr(attribute.find("-") + 1));
227  // Get the particle before the interaction
228  particleToInteraction =
229  HepMC3Particle::particle(vertex->particles_in()[0]);
230  // Attach passed material to the particle
231  setPassedMaterial(vertex, procID, particleToInteraction);
232  // Record the final state particles
233  finalStateParticles = selectOutgoingParticles(vertex, procID);
234  vertexFound = true;
235  break;
236  }
237  }
238  if (vertexFound) {
239  break;
240  }
241  }
242  fractions.push_back(ActsExamples::ExtractedSimulationProcess{
243  simParticle, particleToInteraction, finalStateParticles});
244  }
245 
246  // Filter and sort the record
247  filterAndSort(m_cfg, fractions);
248 
249  ACTS_INFO(events.size() << " processed");
250 
251  // Write the recorded material to the event store
252  m_outputSimulationProcesses(context, std::move(fractions));
253 
255 }