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