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 
11 #include <random>
12 
13 template <typename propagator_t>
14 std::optional<Acts::BoundSymMatrix>
15 PropagationAlgorithm<propagator_t>::generateCovariance(
17  std::normal_distribution<double>& gauss) const {
18  if (m_cfg.covarianceTransport) {
19  // We start from the correlation matrix
20  Acts::BoundSymMatrix newCov(m_cfg.correlations);
21  // Then we draw errors according to the error values
22  Acts::BoundVector covs_smeared = m_cfg.covariances;
23  for (size_t k = 0; k < size_t(covs_smeared.size()); ++k) {
24  covs_smeared[k] *= gauss(rnd);
25  }
26  // and apply a double loop
27  for (size_t i = 0; i < size_t(newCov.rows()); ++i) {
28  for (size_t j = 0; j < size_t(newCov.cols()); ++j) {
29  (newCov)(i, j) *= covs_smeared[i];
30  (newCov)(i, j) *= covs_smeared[j];
31  }
32  }
33  return newCov;
34  }
35  return std::nullopt;
36 }
37 
38 template <typename propagator_t>
39 PropagationAlgorithm<propagator_t>::PropagationAlgorithm(
41  Acts::Logging::Level loglevel)
42  : BareAlgorithm("PropagationAlgorithm", loglevel), m_cfg(cfg) {}
43 
49 template <typename propagator_t>
50 template <typename parameters_t>
52  const AlgorithmContext& context, const parameters_t& startParameters,
53  double pathLength) const {
54  ACTS_DEBUG("Test propagation/extrapolation starts");
55 
56  PropagationOutput pOutput;
57 
58  // This is the outside in mode
59  if (m_cfg.mode == 0) {
60  // The step length logger for testing & end of world aborter
61  using MaterialInteractor = Acts::MaterialInteractor;
62  using SteppingLogger = Acts::detail::SteppingLogger;
64 
65  // Action list and abort list
67  using AbortList = Acts::AbortList<EndOfWorld>;
68  using PropagatorOptions =
70 
71  PropagatorOptions options(context.geoContext, context.magFieldContext,
72  Acts::LoggerWrapper{logger()});
73  options.pathLimit = pathLength;
74 
75  // Activate loop protection at some pt value
76  options.loopProtection =
77  (startParameters.transverseMomentum() < 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  return pOutput;
103 }
104 
105 template <typename propagator_t>
107  const AlgorithmContext& context) const {
108  // Create a random number generator
110  m_cfg.randomNumberSvc->spawnGenerator(context);
111 
112  // Standard gaussian distribution for covarianmces
113  std::normal_distribution<double> gauss(0., 1.);
114 
115  // Setup random number distributions for some quantities
116  std::uniform_real_distribution<double> phiDist(m_cfg.phiRange.first,
117  m_cfg.phiRange.second);
118  std::uniform_real_distribution<double> etaDist(m_cfg.etaRange.first,
119  m_cfg.etaRange.second);
120  std::uniform_real_distribution<double> ptDist(m_cfg.ptRange.first,
121  m_cfg.ptRange.second);
122  std::uniform_real_distribution<double> qDist(0., 1.);
123 
124  std::shared_ptr<const Acts::PerigeeSurface> surface =
125  Acts::Surface::makeShared<Acts::PerigeeSurface>(
126  Acts::Vector3D(0., 0., 0.));
127 
128  // Output : the propagation steps
129  std::vector<std::vector<Acts::detail::Step>> propagationSteps;
130  propagationSteps.reserve(m_cfg.ntests);
131 
132  // Output (optional): the recorded material
133  std::vector<RecordedMaterialTrack> recordedMaterial;
134  if (m_cfg.recordMaterialInteractions) {
135  recordedMaterial.reserve(m_cfg.ntests);
136  }
137 
138  // loop over number of particles
139  for (size_t it = 0; it < m_cfg.ntests; ++it) {
141  double d0 = m_cfg.d0Sigma * gauss(rng);
142  double z0 = m_cfg.z0Sigma * gauss(rng);
143  double phi = phiDist(rng);
144  double eta = etaDist(rng);
145  double theta = 2 * atan(exp(-eta));
146  double pt = ptDist(rng);
147  double p = pt / sin(theta);
148  double charge = qDist(rng) > 0.5 ? 1. : -1.;
149  double qop = charge / p;
150  double t = m_cfg.tSigma * gauss(rng);
151  // parameters
152  Acts::BoundVector pars;
153  pars << d0, z0, phi, theta, qop, t;
154  // some screen output
155 
156  Acts::Vector3D sPosition(0., 0., 0.);
157  Acts::Vector3D sMomentum(0., 0., 0.);
158 
159  // The covariance generation
160  auto cov = generateCovariance(rng, gauss);
161 
162  // execute the test for charged particles
163  PropagationOutput pOutput;
164  if (charge) {
165  // charged extrapolation - with hit recording
166  Acts::BoundTrackParameters startParameters(surface, std::move(pars),
167  std::move(cov));
168  sPosition = startParameters.position(context.geoContext);
169  sMomentum = startParameters.momentum();
170  pOutput = executeTest(context, startParameters);
171  } else {
172  // execute the test for neeutral particles
173  Acts::NeutralBoundTrackParameters neutralParameters(
174  surface, std::move(pars), std::move(cov));
175  sPosition = neutralParameters.position(context.geoContext);
176  sMomentum = neutralParameters.momentum();
177  pOutput = executeTest(context, neutralParameters);
178  }
179  // Record the propagator steps
180  propagationSteps.push_back(std::move(pOutput.first));
181  if (m_cfg.recordMaterialInteractions &&
182  pOutput.second.materialInteractions.size()) {
183  // Create a recorded material track
184  RecordedMaterialTrack rmTrack;
185  // Start position
186  rmTrack.first.first = std::move(sPosition);
187  // Start momentum
188  rmTrack.first.second = std::move(sMomentum);
189  // The material
190  rmTrack.second = std::move(pOutput.second);
191  // push it it
192  recordedMaterial.push_back(std::move(rmTrack));
193  }
194  }
195 
196  // Write the propagation step data to the event store
197  context.eventStore.add(m_cfg.propagationStepCollection,
198  std::move(propagationSteps));
199 
200  // Write the recorded material to the event store
201  if (m_cfg.recordMaterialInteractions) {
202  context.eventStore.add(m_cfg.propagationMaterialCollection,
203  std::move(recordedMaterial));
204  }
205 
206  return ProcessCode::SUCCESS;
207 }