ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
FatrasSimulationBase.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file FatrasSimulationBase.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019 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 
11 #include <boost/program_options.hpp>
12 
47 
48 namespace {
49 
51 struct HitSurfaceSelector {
52  bool sensitive = false;
53  bool material = false;
54  bool passive = false;
55 
57  bool operator()(const Acts::Surface& surface) const {
58  if (sensitive and surface.associatedDetectorElement()) {
59  return true;
60  }
61  if (material and surface.surfaceMaterial()) {
62  return true;
63  }
64  if (passive) {
65  return true;
66  }
67  return false;
68  }
69 };
70 
82 template <typename magnetic_field_t>
83 void setupSimulationAlgorithms(
84  const FW::Options::Variables& variables, FW::Sequencer& sequencer,
85  std::shared_ptr<const FW::RandomNumbers> randomNumbers,
86  std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry,
87  magnetic_field_t&& magneticField) {
88  // Read the log level
89  Acts::Logging::Level logLevel = FW::Options::readLogLevel(variables);
90 
91  // Convert generated events to selected particles
92  auto select = FW::ParticleSelector::readConfig(variables);
93  select.inputEvent = "event_generated";
94  select.outputEvent = "event_selected";
95  sequencer.addAlgorithm(
96  std::make_shared<FW::ParticleSelector>(select, logLevel));
98  flatten.inputEvent = select.outputEvent;
99  flatten.outputParticles = "particles_selected";
100  sequencer.addAlgorithm(std::make_shared<FW::FlattenEvent>(flatten, logLevel));
101 
102  // setup propagator-related types
103  // use the default navigation
104  using Navigator = Acts::Navigator;
105  // propagate charged particles numerically in the given magnetic field
106  using ChargedStepper = Acts::EigenStepper<magnetic_field_t>;
107  using ChargedPropagator = Acts::Propagator<ChargedStepper, Navigator>;
108  // propagate neutral particles with just straight lines
109  using NeutralStepper = Acts::StraightLineStepper;
110  using NeutralPropagator = Acts::Propagator<NeutralStepper, Navigator>;
111 
112  // setup simulator-related types
114  // charged particles w/ standard em physics list and selectable hits
115  using ChargedSelector =
117  using ChargedSimulator = ActsFatras::ParticleSimulator<
119  HitSurfaceSelector>;
120  // neutral particles w/o physics and no hits
121  using NeutralSelector =
123  using NeutralSimulator = ActsFatras::ParticleSimulator<
125  // full simulator type for charged and neutrals
126  using Simulator = ActsFatras::Simulator<ChargedSelector, ChargedSimulator,
127  NeutralSelector, NeutralSimulator>;
128  // final algorihm type
129  using SimulationAlgorithm = FW::FatrasAlgorithm<Simulator>;
130 
131  // construct the simulator
132  Navigator navigator(trackingGeometry);
133  // construct the charged simulator
134  ChargedStepper chargedStepper(std::move(magneticField));
135  ChargedPropagator chargedPropagator(std::move(chargedStepper), navigator);
136  ChargedSimulator chargedSimulator(std::move(chargedPropagator), logLevel);
137  // construct the neutral simulator
138  NeutralStepper neutralStepper;
139  NeutralPropagator neutralPropagator(std::move(neutralStepper), navigator);
140  NeutralSimulator neutralSimulator(std::move(neutralPropagator), logLevel);
141  // construct the combined simulator
142  Simulator simulator(std::move(chargedSimulator), std::move(neutralSimulator));
143 
144  // construct/add the simulation algorithm
145  auto fatras = FW::Options::readFatrasConfig(variables, std::move(simulator));
146  fatras.inputParticles = flatten.outputParticles;
147  fatras.outputParticlesInitial = "particles_initial";
148  fatras.outputParticlesFinal = "particles_final";
149  fatras.outputHits = "hits";
150  fatras.randomNumbers = randomNumbers;
151  sequencer.addAlgorithm(
152  std::make_shared<SimulationAlgorithm>(fatras, logLevel));
153 
154  // Output directory
155  const auto outputDir = FW::ensureWritableDirectory(
156  variables["output-dir"].template as<std::string>());
157 
158  // Write simulation information as CSV files
159  if (variables["output-csv"].template as<bool>()) {
160  FW::CsvParticleWriter::Config writeInitial;
161  writeInitial.inputParticles = fatras.outputParticlesInitial;
162  writeInitial.outputDir = outputDir;
163  writeInitial.outputStem = fatras.outputParticlesInitial;
164  sequencer.addWriter(
165  std::make_shared<FW::CsvParticleWriter>(writeInitial, logLevel));
167  writeFinal.inputParticles = fatras.outputParticlesFinal;
168  writeFinal.outputDir = outputDir;
169  writeFinal.outputStem = fatras.outputParticlesFinal;
170  sequencer.addWriter(
171  std::make_shared<FW::CsvParticleWriter>(writeFinal, logLevel));
172  }
173 
174  // Write simulation information as ROOT files
175  if (variables["output-root"].template as<bool>()) {
176  // write initial simulated particles
177  FW::RootParticleWriter::Config writeInitial;
178  writeInitial.inputParticles = fatras.outputParticlesInitial;
179  writeInitial.filePath =
180  FW::joinPaths(outputDir, fatras.outputParticlesInitial + ".root");
181  sequencer.addWriter(
182  std::make_shared<FW::RootParticleWriter>(writeInitial, logLevel));
183 
184  // write final simulated particles
186  writeFinal.inputParticles = fatras.outputParticlesFinal;
187  writeFinal.filePath =
188  FW::joinPaths(outputDir, fatras.outputParticlesFinal + ".root");
189  sequencer.addWriter(
190  std::make_shared<FW::RootParticleWriter>(writeFinal, logLevel));
191 
192  // write simulated hits
194  writeHits.inputSimulatedHits = fatras.outputHits;
195  writeHits.filePath = FW::joinPaths(outputDir, fatras.outputHits + ".root");
196  sequencer.addWriter(
197  std::make_shared<FW::RootSimHitWriter>(writeHits, logLevel));
198  }
199 }
200 
201 } // namespace
202 
204  const FW::Options::Variables& variables, FW::Sequencer& sequencer,
205  std::shared_ptr<const RandomNumbers> randomNumbers,
206  std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry) {
207  auto magneticFieldVariant = FW::Options::readBField(variables);
208  std::visit(
209  [&](auto&& inputField) {
210  using magnetic_field_t =
211  typename std::decay_t<decltype(inputField)>::element_type;
212  Acts::SharedBField<magnetic_field_t> magneticField(inputField);
213  setupSimulationAlgorithms(variables, sequencer, randomNumbers,
214  trackingGeometry, std::move(magneticField));
215  },
216  magneticFieldVariant);
217 }