EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
RiddersPropagator.ipp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file RiddersPropagator.ipp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2017-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 
9 template <typename propagator_t>
10 template <typename parameters_t, typename propagator_options_t>
12  const parameters_t& start, const propagator_options_t& options) const
15  typename propagator_options_t::action_list_type>> {
16  using ThisResult = Result<
18  typename propagator_options_t::action_list_type>>;
19 
20  // Propagate the nominal parameters
21  auto nominalRet = m_propagator.propagate(start, options);
22  if (not nominalRet.ok()) {
23  return ThisResult::failure(nominalRet.error());
24  }
25 
26  // Extract results from the nominal propagation
27  auto nominalResult = std::move(nominalRet).value();
28  const BoundVector& nominalParameters =
29  nominalResult.endParameters->parameters();
30  // Use the curvilinear surface of the propagated parameters as target
31  const Surface& surface = nominalResult.endParameters->referenceSurface();
32 
33  // Steps for estimating derivatives
34  std::vector<double> deviations = {-4e-4, -2e-4, 2e-4, 4e-4};
35 
36  // Allow larger distances for the oscillation
37  propagator_options_t opts = options;
38  opts.pathLimit *= 2.;
39 
40  // Derivations of each parameter around the nominal parameters
41  std::array<std::vector<BoundVector>, eBoundSize> derivatives;
42 
43  // Wiggle each dimension individually
44  for (unsigned int i = 0; i < eBoundSize; i++) {
45  derivatives[i] =
46  wiggleDimension(opts, start, i, surface, nominalParameters, deviations);
47  }
48  // Exchange the result by Ridders Covariance
49  const FullBoundParameterSet& parSet =
50  nominalResult.endParameters->getParameterSet();
51  FullBoundParameterSet* mParSet = const_cast<FullBoundParameterSet*>(&parSet);
52  if (start.covariance()) {
53  mParSet->setCovariance(
54  calculateCovariance(derivatives, *start.covariance(), deviations));
55  }
56 
57  return ThisResult::success(std::move(nominalResult));
58 }
59 
60 template <typename propagator_t>
61 template <typename parameters_t, typename propagator_options_t>
63  const parameters_t& start, const Surface& target,
64  const propagator_options_t& options) const
67  typename propagator_options_t::action_list_type>> {
68  using ThisResult = Result<action_list_t_result_t<
69  BoundTrackParameters, typename propagator_options_t::action_list_type>>;
70 
71  // Propagate the nominal parameters
72  auto nominalRet = m_propagator.propagate(start, target, options);
73  if (not nominalRet.ok()) {
74  return ThisResult::failure(nominalRet.error());
75  }
76 
77  // Extract results from the nominal propagation
78  auto nominalResult = std::move(nominalRet).value();
79  const BoundVector& nominalParameters =
80  nominalResult.endParameters->parameters();
81 
82  // Steps for estimating derivatives
83  std::vector<double> deviations = {-4e-4, -2e-4, 2e-4, 4e-4};
84  if (target.type() == Surface::Disc) {
85  deviations = {{-3e-5, -1e-5, 1e-5, 3e-5}};
86  }
87 
88  // - for planar surfaces the dest surface is a perfect destination
89  // surface for the numerical propagation, as reference frame
90  // aligns with the referenceSurface.transform().rotation() at
91  // at any given time
92  //
93  // - for straw & cylinder, where the error is given
94  // in the reference frame that re-aligns with a slightly different
95  // intersection solution
96 
97  // Allow larger distances for the oscillation
98  propagator_options_t opts = options;
99  opts.pathLimit *= 2.;
100 
101  // Derivations of each parameter around the nominal parameters
102  std::array<std::vector<BoundVector>, eBoundSize> derivatives;
103 
104  // Wiggle each dimension individually
105  for (unsigned int i = 0; i < eBoundSize; i++) {
106  derivatives[i] =
107  wiggleDimension(opts, start, i, target, nominalParameters, deviations);
108  }
109  // Exchange the result by Ridders Covariance
110  const FullBoundParameterSet& parSet =
111  nominalResult.endParameters->getParameterSet();
112  FullBoundParameterSet* mParSet = const_cast<FullBoundParameterSet*>(&parSet);
113  if (start.covariance()) {
114  // Test if target is disc - this may lead to inconsistent results
115  if (target.type() == Surface::Disc) {
116  for (const std::vector<BoundVector>& deriv : derivatives) {
117  if (inconsistentDerivativesOnDisc(deriv)) {
118  // Set covariance to zero and return
119  // TODO: This should be changed to indicate that something went
120  // wrong
121  mParSet->setCovariance(Covariance::Zero());
122  return ThisResult::success(std::move(nominalResult));
123  }
124  }
125  }
126  mParSet->setCovariance(
127  calculateCovariance(derivatives, *start.covariance(), deviations));
128  }
129  return ThisResult::success(std::move(nominalResult));
130 }
131 
132 template <typename propagator_t>
134  const std::vector<Acts::BoundVector>& derivatives) const {
135  // Test each component with each other
136  for (unsigned int i = 0; i < derivatives.size(); i++) {
137  bool jumpedAngle = true;
138  for (unsigned int j = 0; j < derivatives.size(); j++) {
139  // If there is at least one with a similar angle then it seems to work
140  // properly
141  if (i != j &&
142  std::abs(derivatives[i](1) - derivatives[j](1)) < 0.5 * M_PI) {
143  jumpedAngle = false;
144  break;
145  }
146  }
147  // Break if a jump was detected
148  if (jumpedAngle) {
149  return true;
150  }
151  }
152  return false;
153 }
154 
155 template <typename propagator_t>
156 template <typename options_t, typename parameters_t>
157 std::vector<Acts::BoundVector>
159  const options_t& options, const parameters_t& startPars,
160  const unsigned int param, const Surface& target,
161  const Acts::BoundVector& nominal,
162  const std::vector<double>& deviations) const {
163  // Storage of the results
164  std::vector<BoundVector> derivatives;
165  derivatives.reserve(deviations.size());
166  for (double h : deviations) {
167  // Treatment for theta
168  if (param == eBoundTheta) {
169  const double current_theta = startPars.template get<eBoundTheta>();
170  if (current_theta + h > M_PI) {
171  h = M_PI - current_theta;
172  }
173  if (current_theta + h < 0) {
174  h = -current_theta;
175  }
176  }
177 
178  // Modify start parameter
179  BoundVector values = startPars.parameters();
180  values[param] += h;
181 
182  // Propagate with updated start parameters
183  BoundTrackParameters tp(startPars.referenceSurface().getSharedPtr(), values,
184  startPars.covariance());
185  const auto& r = m_propagator.propagate(tp, target, options).value();
186  // Collect the slope
187  derivatives.push_back((r.endParameters->parameters() - nominal) / h);
188 
189  // Correct for a possible variation of phi around
190  if (param == 2) {
191  double phi0 = nominal(Acts::eBoundPhi);
192  double phi1 = r.endParameters->parameters()(Acts::eBoundPhi);
193  if (std::abs(phi1 + 2. * M_PI - phi0) < std::abs(phi1 - phi0))
194  derivatives.back()[Acts::eBoundPhi] = (phi1 + 2. * M_PI - phi0) / h;
195  else if (std::abs(phi1 - 2. * M_PI - phi0) < std::abs(phi1 - phi0))
196  derivatives.back()[Acts::eBoundPhi] = (phi1 - 2. * M_PI - phi0) / h;
197  }
198  }
199  return derivatives;
200 }
201 
202 template <typename propagator_t>
204  const std::array<std::vector<Acts::BoundVector>, Acts::eBoundSize>&
205  derivatives,
206  const Acts::BoundSymMatrix& startCov,
207  const std::vector<double>& deviations) const -> const Covariance {
208  Jacobian jacobian;
209  jacobian.setIdentity();
210  jacobian.col(eBoundLoc0) = fitLinear(derivatives[eBoundLoc0], deviations);
211  jacobian.col(eBoundLoc1) = fitLinear(derivatives[eBoundLoc1], deviations);
212  jacobian.col(eBoundPhi) = fitLinear(derivatives[eBoundPhi], deviations);
213  jacobian.col(eBoundTheta) = fitLinear(derivatives[eBoundTheta], deviations);
214  jacobian.col(eBoundQOverP) = fitLinear(derivatives[eBoundQOverP], deviations);
215  jacobian.col(eBoundTime) = fitLinear(derivatives[eBoundTime], deviations);
216  return jacobian * startCov * jacobian.transpose();
217 }
218 
219 template <typename propagator_t>
221  const std::vector<Acts::BoundVector>& values,
222  const std::vector<double>& deviations) const {
223  BoundVector A;
224  BoundVector C;
225  A.setZero();
226  C.setZero();
227  double B = 0;
228  double D = 0;
229  const unsigned int N = deviations.size();
230 
231  for (unsigned int i = 0; i < N; ++i) {
232  A += deviations.at(i) * values.at(i);
233  B += deviations.at(i);
234  C += values.at(i);
235  D += deviations.at(i) * deviations.at(i);
236  }
237 
238  BoundVector b = (N * A - B * C) / (N * D - B * B);
239  BoundVector a = (C - B * b) / N;
240 
241  return a;
242 }