LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
Propagator.cxx
Go to the documentation of this file.
1 
12 #include "cetlib_except/exception.h"
16 
17 namespace trkf {
18 
27  double tcut,
28  bool doDedx,
29  const std::shared_ptr<const Interactor>& interactor)
30  : fDetProp{detProp}, fTcut(tcut), fDoDedx(doDedx), fInteractor(interactor)
31  {}
32 
34  Propagator::~Propagator() = default;
35 
52  std::optional<double> Propagator::vec_prop(KTrack& trk,
53  const std::shared_ptr<const Surface>& psurf,
55  bool doDedx,
56  TrackMatrix* prop_matrix,
57  TrackError* noise_matrix) const
58  {
59  std::optional<double> result{std::nullopt};
60 
61  // Get the inverse momentum (assumed to be track parameter four).
62 
63  double pinv = trk.getVector()(4);
64 
65  // If dE/dx is not requested, or if inverse momentum is zero, then
66  // it is safe to propagate in one step. In this case, just pass
67  // the call to short_vec_prop with unlimited distance.
68 
69  bool dedx = getDoDedx() && doDedx;
70  if (!dedx || pinv == 0.)
71  result = short_vec_prop(trk, psurf, dir, dedx, prop_matrix, noise_matrix);
72 
73  else {
74 
75  // dE/dx is requested. In this case we limit the maximum
76  // propagation distance such that the kinetic energy of the
77  // particle should not change by more thatn 10%.
78 
79  // Initialize propagation matrix to unit matrix (if specified).
80 
81  int nvec = trk.getVector().size();
82  if (prop_matrix) *prop_matrix = ublas::identity_matrix<TrackVector::value_type>(nvec);
83 
84  // Initialize noise matrix to zero matrix (if specified).
85 
86  if (noise_matrix) {
87  noise_matrix->resize(nvec, nvec, false);
88  noise_matrix->clear();
89  }
90 
91  // Remember the starting track.
92 
93  KTrack trk0(trk);
94 
95  // Make pointer variables pointing to local versions of the
96  // propagation and noise matrices, or null if not specified.
97 
98  TrackMatrix local_prop_matrix;
99  TrackMatrix* plocal_prop_matrix = (prop_matrix == 0 ? 0 : &local_prop_matrix);
100  TrackError local_noise_matrix;
101  TrackError* plocal_noise_matrix = (noise_matrix == 0 ? 0 : &local_noise_matrix);
102 
103  // Cumulative propagation distance.
104 
105  double s = 0.;
106 
107  // Begin stepping loop.
108  // We put a maximum iteration count to prevent infinite loops caused by
109  // floating point pathologies. The iteration count is large enough to reach
110  // any point in the tpc using the minimum step size (for a reasonable tpc).
111 
112  bool done = false;
113  int nitmax = 10000; // Maximum number of iterations.
114  int nit = 0; // Iteration count.
115  while (!done) {
116 
117  // If the iteration count exceeds the maximum, return failure.
118 
119  ++nit;
120  if (nit > nitmax) {
121  trk = trk0;
122  result = std::nullopt;
123  return result;
124  }
125 
126  // Estimate maximum step distance according to the above
127  // stated principle.
128 
129  pinv = trk.getVector()(4);
130  double mass = trk.Mass();
131  double p = 1. / std::abs(pinv);
132  double e = std::hypot(p, mass);
133  double t = p * p / (e + mass);
134  double dedx = 0.001 * fDetProp.Eloss(p, mass, fTcut);
135  double smax = 0.1 * t / dedx;
136  if (smax <= 0.)
137  throw cet::exception("Propagator") << __func__ << ": maximum step " << smax << "\n";
138 
139  // Always allow a step of at least 0.3 cm (about one wire spacing).
140 
141  if (smax < 0.3) smax = 0.3;
142 
143  // First do a test propagation (without dE/dx and errors) to
144  // find the distance to the destination surface.
145 
146  KTrack trktest(trk);
147  std::optional<double> dist = short_vec_prop(trktest, psurf, dir, false, 0, 0);
148 
149  // If the test propagation failed, return failure.
150 
151  if (!dist) {
152  trk = trk0;
153  return dist;
154  }
155 
156  // Generate destionation surface for this step (either final
157  // destination, or some intermediate surface).
158 
159  std::shared_ptr<const Surface> pstep;
160  if (std::abs(*dist) <= smax) {
161  done = true;
162  pstep = psurf;
163  }
164  else {
165 
166  // Generate intermediate surface.
167  // First get point where track will intersect intermediate surface.
168 
169  double xyz0[3]; // Starting point.
170  trk.getPosition(xyz0);
171  double xyz1[3]; // Destination point.
172  trktest.getPosition(xyz1);
173  double frac = smax / std::abs(*dist);
174  double xyz[3]; // Intermediate point.
175  xyz[0] = xyz0[0] + frac * (xyz1[0] - xyz0[0]);
176  xyz[1] = xyz0[1] + frac * (xyz1[1] - xyz0[1]);
177  xyz[2] = xyz0[2] + frac * (xyz1[2] - xyz0[2]);
178 
179  // Choose orientation of intermediate surface perpendicular
180  // to track.
181 
182  double mom[3];
183  trk.getMomentum(mom);
184 
185  // Make intermediate surface object.
186 
187  pstep = std::shared_ptr<const Surface>(
188  new SurfXYZPlane(xyz[0], xyz[1], xyz[2], mom[0], mom[1], mom[2]));
189  }
190 
191  // Do the actual step propagation.
192 
193  dist = short_vec_prop(trk, pstep, dir, doDedx, plocal_prop_matrix, plocal_noise_matrix);
194 
195  // If the step propagation failed, return failure.
196 
197  if (!dist) {
198  trk = trk0;
199  return dist;
200  }
201 
202  // Update cumulative propagation distance.
203 
204  s += *dist;
205 
206  // Update cumulative propagation matrix (left-multiply).
207 
208  if (prop_matrix != 0) {
209  TrackMatrix temp = prod(*plocal_prop_matrix, *prop_matrix);
210  *prop_matrix = temp;
211  }
212 
213  // Update cumulative noise matrix.
214 
215  if (noise_matrix != 0) {
216  TrackMatrix temp = prod(*noise_matrix, trans(*plocal_prop_matrix));
217  TrackMatrix temp2 = prod(*plocal_prop_matrix, temp);
218  *noise_matrix = ublas::symmetric_adaptor<TrackMatrix>(temp2);
219  *noise_matrix += *plocal_noise_matrix;
220  }
221  }
222 
223  // Set the final result (distance + success).
224 
225  result = std::make_optional(s);
226  }
227 
228  // Done.
229 
230  return result;
231  }
232 
249  std::optional<double> Propagator::lin_prop(KTrack& trk,
250  const std::shared_ptr<const Surface>& psurf,
252  bool doDedx,
253  KTrack* ref,
254  TrackMatrix* prop_matrix,
255  TrackError* noise_matrix) const
256  {
257  // Default result.
258 
259  std::optional<double> result;
260 
261  if (ref == 0)
262  result = vec_prop(trk, psurf, dir, doDedx, prop_matrix, noise_matrix);
263  else {
264 
265  // A reference track has been provided.
266 
267  // It is an error (throw exception) if the reference track and
268  // the track to be propagted are not on the same surface.
269 
270  if (!trk.getSurface()->isEqual(*(ref->getSurface())))
271  throw cet::exception("Propagator")
272  << "Input track and reference track not on same surface.\n";
273 
274  // Remember the starting track and reference track.
275 
276  KTrack trk0(trk);
277  KTrack ref0(*ref);
278 
279  // Propagate the reference track. Make sure we calculate the
280  // propagation matrix.
281 
282  TrackMatrix prop_temp;
283  if (prop_matrix == 0) prop_matrix = &prop_temp;
284 
285  // Do the propgation. The returned result will be the result of
286  // this propagatrion.
287 
288  result = vec_prop(*ref, psurf, dir, doDedx, prop_matrix, noise_matrix);
289  if (!!result) {
290 
291  // Propagation of reference track succeeded. Update the track
292  // state vector and surface of the track to be propagated.
293 
294  TrackVector diff = trk.getSurface()->getDiff(trk.getVector(), ref0.getVector());
295  TrackVector newvec = ref->getVector() + prod(*prop_matrix, diff);
296 
297  // Store updated state vector and surface.
298 
299  trk.setVector(newvec);
300  trk.setSurface(psurf);
301  trk.setDirection(ref->getDirection());
302  if (!trk.getSurface()->isEqual(*(ref->getSurface())))
303  throw cet::exception("Propagator") << __func__ << ": surface mismatch";
304 
305  // Final validity check. In case of failure, restore the track
306  // and reference track to their starting values.
307 
308  if (!trk.isValid()) {
309  result = std::nullopt;
310  trk = trk0;
311  *ref = ref0;
312  }
313  }
314  else {
315 
316  // Propagation failed.
317  // Restore the reference track to its starting value, so that we ensure
318  // the reference track and the actual track remain on the same surface.
319 
320  trk = trk0;
321  *ref = ref0;
322  }
323  }
324 
325  // Done.
326 
327  return result;
328  }
329 
343  std::optional<double> Propagator::err_prop(KETrack& tre,
344  const std::shared_ptr<const Surface>& psurf,
346  bool doDedx,
347  KTrack* ref,
348  TrackMatrix* prop_matrix) const
349  {
350  // Propagate without error, get propagation matrix.
351 
352  TrackMatrix prop_temp;
353  if (prop_matrix == 0) prop_matrix = &prop_temp;
354  std::optional<double> result = lin_prop(tre, psurf, dir, doDedx, ref, prop_matrix, 0);
355 
356  // If propagation succeeded, update track error matrix.
357 
358  if (!!result) {
359  TrackMatrix temp = prod(tre.getError(), trans(*prop_matrix));
360  TrackMatrix temp2 = prod(*prop_matrix, temp);
361  TrackError newerr = ublas::symmetric_adaptor<TrackMatrix>(temp2);
362  tre.setError(newerr);
363  }
364 
365  // Done.
366 
367  return result;
368  }
369 
382  std::optional<double> Propagator::noise_prop(KETrack& tre,
383  const std::shared_ptr<const Surface>& psurf,
385  bool doDedx,
386  KTrack* ref) const
387  {
388  // Propagate without error, get propagation matrix and noise matrix.
389 
390  TrackMatrix prop_matrix;
391  TrackError noise_matrix;
392  std::optional<double> result =
393  lin_prop(tre, psurf, dir, doDedx, ref, &prop_matrix, &noise_matrix);
394 
395  // If propagation succeeded, update track error matrix.
396 
397  if (!!result) {
398  TrackMatrix temp = prod(tre.getError(), trans(prop_matrix));
399  TrackMatrix temp2 = prod(prop_matrix, temp);
400  TrackError newerr = ublas::symmetric_adaptor<TrackMatrix>(temp2);
401  newerr += noise_matrix;
402  tre.setError(newerr);
403  }
404 
405  // Done.
406 
407  return result;
408  }
409 
447  std::optional<double> Propagator::dedx_prop(double pinv,
448  double mass,
449  double s,
450  double* deriv) const
451  {
452  // For infinite initial momentum, return with success status,
453  // still infinite momentum.
454 
455  if (pinv == 0.) return std::make_optional(0.);
456 
457  // Set the default return value to be uninitialized with value 0.
458 
459  std::optional<double> result{std::nullopt};
460 
461  // Calculate final energy.
462 
463  double p1 = 1. / std::abs(pinv);
464  double e1 = std::hypot(p1, mass);
465  double de = -0.001 * s * fDetProp.Eloss(p1, mass, fTcut);
466  double emid = e1 + 0.5 * de;
467  if (emid > mass) {
468  double pmid = std::sqrt(emid * emid - mass * mass);
469  double e2 = e1 - 0.001 * s * fDetProp.Eloss(pmid, mass, fTcut);
470  if (e2 > mass) {
471  double p2 = std::sqrt(e2 * e2 - mass * mass);
472  double pinv2 = 1. / p2;
473  if (pinv < 0.) pinv2 = -pinv2;
474 
475  // Calculation was successful, update result.
476 
477  result = std::make_optional(pinv2);
478 
479  // Also calculate derivative, if requested.
480 
481  if (deriv != 0) *deriv = pinv2 * pinv2 * pinv2 * e2 / (pinv * pinv * pinv * e1);
482  }
483  }
484 
485  // Done.
486 
487  return result;
488  }
489 } // end namespace trkf
const TrackError & getError() const
Track error matrix.
Definition: KETrack.h:52
Utilities related to art service access.
double Mass() const
Based on pdg code.
Definition: KTrack.cxx:116
const std::shared_ptr< const Surface > & getSurface() const
Surface.
Definition: KTrack.h:53
General planar surface.
KSymMatrix< 5 >::type TrackError
Track error matrix, dimension 5x5.
void setVector(const TrackVector &vec)
Set state vector.
Definition: KTrack.h:65
void setDirection(Surface::TrackDirection dir)
Set direction.
Definition: KTrack.h:66
constexpr auto abs(T v)
Returns the absolute value of the argument.
double fTcut
Maximum delta ray energy for dE/dx.
Definition: Propagator.h:165
virtual std::optional< double > short_vec_prop(KTrack &trk, const std::shared_ptr< const Surface > &psurf, PropDirection dir, bool doDedx, TrackMatrix *prop_matrix=0, TrackError *noise_matrix=0) const =0
Propagate without error (short distance).
virtual ~Propagator()
Destructor.
void setError(const TrackError &err)
Set error matrix.
Definition: KETrack.h:58
std::optional< double > vec_prop(KTrack &trk, const std::shared_ptr< const Surface > &psurf, PropDirection dir, bool doDedx, TrackMatrix *prop_matrix=0, TrackError *noise_matrix=0) const
Propagate without error (long distance).
Definition: Propagator.cxx:52
std::optional< double > noise_prop(KETrack &tre, const std::shared_ptr< const Surface > &psurf, PropDirection dir, bool doDedx, KTrack *ref=0) const
Propagate with error and noise.
Definition: Propagator.cxx:382
void setSurface(const std::shared_ptr< const Surface > &psurf)
Set surface.
Definition: KTrack.h:64
KMatrix< 5, 5 >::type TrackMatrix
General 5x5 matrix.
detinfo::DetectorPropertiesData const & fDetProp
Definition: Propagator.h:164
std::optional< double > lin_prop(KTrack &trk, const std::shared_ptr< const Surface > &psurf, PropDirection dir, bool doDedx, KTrack *ref=0, TrackMatrix *prop_matrix=0, TrackError *noise_matrix=0) const
Linearized propagate without error.
Definition: Propagator.cxx:249
void getPosition(double xyz[3]) const
Get position of track.
Definition: KTrack.cxx:157
std::optional< double > err_prop(KETrack &tre, const std::shared_ptr< const Surface > &psurf, PropDirection dir, bool doDedx, KTrack *ref=0, TrackMatrix *prop_matrix=0) const
Propagate with error, but without noise.
Definition: Propagator.cxx:343
Base class for Kalman filter track propagator.
KVector< 5 >::type TrackVector
Track state vector, dimension 5.
double Eloss(double mom, double mass, double tcut) const
Restricted mean energy loss (dE/dx)
bool getDoDedx() const
Definition: Propagator.h:108
const TrackVector & getVector() const
Track state vector.
Definition: KTrack.h:54
TDirectory * dir
Definition: macro.C:5
constexpr double dist(const TReal *x, const TReal *y, const unsigned int dimension)
std::optional< double > dedx_prop(double pinv, double mass, double s, double *deriv=0) const
Method to calculate updated momentum due to dE/dx.
Definition: Propagator.cxx:447
void getMomentum(double mom[3]) const
Get momentum vector of track.
Definition: KTrack.cxx:201
Surface::TrackDirection getDirection() const
Track direction.
Definition: KTrack.cxx:64
std::shared_ptr< const Interactor > fInteractor
Interactor (for calculating noise).
Definition: Propagator.h:167
bool fDoDedx
Energy loss enable flag.
Definition: Propagator.h:166
Float_t e
Definition: plot.C:35
Propagator(detinfo::DetectorPropertiesData const &detProp, double tcut, bool doDedx, const std::shared_ptr< const Interactor > &interactor)
Constructor.
Definition: Propagator.cxx:26
cet::coded_exception< error, detail::translate > exception
Definition: exception.h:33
bool isValid() const
Test if track is valid.
Definition: KTrack.cxx:81
PropDirection
Propagation direction enum.
Definition: Propagator.h:94