ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PropagationAlgorithm.ipp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PropagationAlgorithm.ipp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2017 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 #include <random>
11 
12 template <typename propagator_t>
13 std::optional<Acts::BoundSymMatrix>
14 PropagationAlgorithm<propagator_t>::generateCovariance(
15  FW::RandomEngine& rnd, std::normal_distribution<double>& gauss) const {
16  if (m_cfg.covarianceTransport) {
17  // We start from the correlation matrix
18  Acts::BoundSymMatrix newCov(m_cfg.correlations);
19  // Then we draw errors according to the error values
20  Acts::BoundVector covs_smeared = m_cfg.covariances;
21  for (size_t k = 0; k < size_t(covs_smeared.size()); ++k) {
22  covs_smeared[k] *= gauss(rnd);
23  }
24  // and apply a double loop
25  for (size_t i = 0; i < size_t(newCov.rows()); ++i) {
26  for (size_t j = 0; j < size_t(newCov.cols()); ++j) {
27  (newCov)(i, j) *= covs_smeared[i];
28  (newCov)(i, j) *= covs_smeared[j];
29  }
30  }
31  return newCov;
32  }
33  return std::nullopt;
34 }
35 
36 template <typename propagator_t>
37 PropagationAlgorithm<propagator_t>::PropagationAlgorithm(
39  Acts::Logging::Level loglevel)
40  : BareAlgorithm("PropagationAlgorithm", loglevel), m_cfg(cfg) {}
41 
47 template <typename propagator_t>
48 template <typename parameters_t>
50  const AlgorithmContext& context, const parameters_t& startParameters,
51  double pathLength) const {
52  ACTS_DEBUG("Test propagation/extrapolation starts");
53 
54  PropagationOutput pOutput;
55 
56  // This is the outside in mode
57  if (m_cfg.mode == 0) {
58  // The step length logger for testing & end of world aborter
59  using MaterialInteractor = Acts::MaterialInteractor;
60  using SteppingLogger = Acts::detail::SteppingLogger;
63 
64  // Action list and abort list
65  using ActionList =
67  using AbortList = Acts::AbortList<EndOfWorld>;
68  using PropagatorOptions = Acts::PropagatorOptions<ActionList, AbortList>;
69 
70  PropagatorOptions options(context.geoContext, context.magFieldContext);
71  options.pathLimit = pathLength;
72  options.debug = m_cfg.debugOutput;
73 
74  // Activate loop protection at some pt value
75  options.loopProtection =
76  (Acts::VectorHelpers::perp(startParameters.momentum()) <
77  m_cfg.ptLoopers);
78 
79  // Switch the material interaction on/off & eventually into logging mode
80  auto& mInteractor = options.actionList.get<MaterialInteractor>();
81  mInteractor.multipleScattering = m_cfg.multipleScattering;
82  mInteractor.energyLoss = m_cfg.energyLoss;
83  mInteractor.recordInteractions = m_cfg.recordMaterialInteractions;
84 
85  // Set a maximum step size
86  options.maxStepSize = m_cfg.maxStepSize;
87 
88  // Propagate using the propagator
89  const auto& result =
90  m_cfg.propagator.propagate(startParameters, options).value();
91  auto steppingResults = result.template get<SteppingLogger::result_type>();
92 
93  // Set the stepping result
94  pOutput.first = std::move(steppingResults.steps);
95  // Also set the material recording result - if configured
96  if (m_cfg.recordMaterialInteractions) {
97  auto materialResult =
98  result.template get<MaterialInteractor::result_type>();
99  pOutput.second = std::move(materialResult);
100  }
101 
102  // screen output if requested
103  if (m_cfg.debugOutput) {
104  auto& debugResult = result.template get<DebugOutput::result_type>();
105  ACTS_VERBOSE(debugResult.debugString);
106  }
107  }
108  return pOutput;
109 }
110 
111 template <typename propagator_t>
113  const AlgorithmContext& context) const {
114  // Create a random number generator
115  FW::RandomEngine rng = m_cfg.randomNumberSvc->spawnGenerator(context);
116 
117  // Standard gaussian distribution for covarianmces
118  std::normal_distribution<double> gauss(0., 1.);
119 
120  // Setup random number distributions for some quantities
121  std::uniform_real_distribution<double> phiDist(m_cfg.phiRange.first,
122  m_cfg.phiRange.second);
123  std::uniform_real_distribution<double> etaDist(m_cfg.etaRange.first,
124  m_cfg.etaRange.second);
125  std::uniform_real_distribution<double> ptDist(m_cfg.ptRange.first,
126  m_cfg.ptRange.second);
127  std::uniform_real_distribution<double> qDist(0., 1.);
128 
129  std::shared_ptr<const Acts::PerigeeSurface> surface =
130  Acts::Surface::makeShared<Acts::PerigeeSurface>(
131  Acts::Vector3D(0., 0., 0.));
132 
133  // Output : the propagation steps
134  std::vector<std::vector<Acts::detail::Step>> propagationSteps;
135  propagationSteps.reserve(m_cfg.ntests);
136 
137  // Output (optional): the recorded material
138  std::vector<RecordedMaterialTrack> recordedMaterial;
139  if (m_cfg.recordMaterialInteractions) {
140  recordedMaterial.reserve(m_cfg.ntests);
141  }
142 
143  // loop over number of particles
144  for (size_t it = 0; it < m_cfg.ntests; ++it) {
146  double d0 = m_cfg.d0Sigma * gauss(rng);
147  double z0 = m_cfg.z0Sigma * gauss(rng);
148  double phi = phiDist(rng);
149  double eta = etaDist(rng);
150  double theta = 2 * atan(exp(-eta));
151  double pt = ptDist(rng);
152  double p = pt / sin(theta);
153  double charge = qDist(rng) > 0.5 ? 1. : -1.;
154  double qop = charge / p;
155  double t = m_cfg.tSigma * gauss(rng);
156  // parameters
157  Acts::BoundVector pars;
158  pars << d0, z0, phi, theta, qop, t;
159  // some screen output
160 
161  Acts::Vector3D sPosition(0., 0., 0.);
162  Acts::Vector3D sMomentum(0., 0., 0.);
163 
164  // The covariance generation
165  auto cov = generateCovariance(rng, gauss);
166 
167  // execute the test for charged particles
168  PropagationOutput pOutput;
169  if (charge) {
170  // charged extrapolation - with hit recording
171  Acts::BoundParameters startParameters(context.geoContext, std::move(cov),
172  std::move(pars), surface);
173  sPosition = startParameters.position();
174  sMomentum = startParameters.momentum();
175  pOutput = executeTest<Acts::TrackParameters>(context, startParameters);
176  } else {
177  // execute the test for neeutral particles
178  Acts::NeutralBoundParameters neutralParameters(
179  context.geoContext, std::move(cov), std::move(pars), surface);
180  sPosition = neutralParameters.position();
181  sMomentum = neutralParameters.momentum();
182  pOutput =
183  executeTest<Acts::NeutralParameters>(context, neutralParameters);
184  }
185  // Record the propagator steps
186  propagationSteps.push_back(std::move(pOutput.first));
187  if (m_cfg.recordMaterialInteractions &&
188  pOutput.second.materialInteractions.size()) {
189  // Create a recorded material track
190  RecordedMaterialTrack rmTrack;
191  // Start position
192  rmTrack.first.first = std::move(sPosition);
193  // Start momentum
194  rmTrack.first.second = std::move(sMomentum);
195  // The material
196  rmTrack.second = std::move(pOutput.second);
197  // push it it
198  recordedMaterial.push_back(std::move(rmTrack));
199  }
200  }
201 
202  // Write the propagation step data to the event store
203  context.eventStore.add(m_cfg.propagationStepCollection,
204  std::move(propagationSteps));
205 
206  // Write the recorded material to the event store
207  if (m_cfg.recordMaterialInteractions) {
208  context.eventStore.add(m_cfg.propagationMaterialCollection,
209  std::move(recordedMaterial));
210  }
211 
212  return ProcessCode::SUCCESS;
213 }