TrackStatePropagator.cxx
Go to the documentation of this file.
6 
7 using namespace recob::tracking;
8 
9 namespace trkf {
10 
11  TrackStatePropagator::TrackStatePropagator(double minStep,
12  double maxElossFrac,
13  int maxNit,
14  double tcut,
15  double wrongDirDistTolerance,
16  bool propPinvErr)
17  : fMinStep(minStep)
18  , fMaxElossFrac(maxElossFrac)
19  , fMaxNit(maxNit)
20  , fTcut(tcut)
21  , fWrongDirDistTolerance(wrongDirDistTolerance)
22  , fPropPinvErr(propPinvErr)
23  {
24  larprop = lar::providerFrom<detinfo::LArPropertiesService>();
25  }
26 
28 
31  const detinfo::DetectorPropertiesData& detProp,
32  const TrackState& origin,
33  const Plane& target,
34  bool dodedx,
35  bool domcs,
36  PropDirection dir) const
37  {
38  //
39  // 1- find distance to target plane
40  auto [distance, sperp] = distancePairToPlane(success, origin, target);
41  //
42  if ((distance < -fWrongDirDistTolerance && dir == FORWARD) ||
44  success = false;
45  return origin;
46  }
47  //
48  // 2- propagate 3d position by distance, form propagated state on plane parallel to origin plane
50  origin.position(), origin.momentum() * origin.parameters()[4], distance);
51  TrackState tmpState(
52  SVector5(0., 0., origin.parameters()[2], origin.parameters()[3], origin.parameters()[4]),
53  origin.covariance(),
54  Plane(p, origin.plane().direction()),
55  origin.isTrackAlongPlaneDir(),
56  origin.pID());
57  //
58  // 3- rotate state to target plane
59  double dw2dw1 = 0;
60  tmpState = rotateToPlane(success, tmpState, target, dw2dw1);
61  SVector5 par5d = tmpState.parameters();
62  SMatrixSym55 cov5d = tmpState.covariance();
63  //
64  // 4- compute jacobian to propagate uncertainties
65  SMatrix55 pm = ROOT::Math::SMatrixIdentity(); //diagonal elements are 1
66  pm(0, 2) = sperp; // du2/d(dudw1);
67  pm(1, 3) = sperp; // dv2/d(dvdw1);
68  //
69  // 5- apply material effects, performing more iterations if the distance is long
70  bool arrived = false;
71  int nit = 0; // Iteration count.
72  double deriv = 1.;
73  SMatrixSym55 noise_matrix;
74  while (!arrived) {
75  ++nit;
76  if (nit > fMaxNit) {
77  success = false;
78  return origin;
79  }
80  // Estimate maximum step distance, such that fMaxElossFrac of initial energy is lost by dedx
81  const double mass = origin.mass();
82  const double p = 1. / par5d[4];
83  const double e = std::hypot(p, mass);
84  const double t = e - mass;
85  const double dedx = 0.001 * detProp.Eloss(std::abs(p), mass, fTcut);
86  const double range = t / dedx;
87  const double smax = std::max(fMinStep, fMaxElossFrac * range);
88  double s = distance;
89  if (domcs && smax > 0 && std::abs(s) > smax) {
90  if (fMaxNit == 1) {
91  success = false;
92  return origin;
93  }
94  s = (s > 0 ? smax : -smax);
95  distance -= s;
96  }
97  else
98  arrived = true;
99  // now apply material effects
100  if (domcs) {
101  bool flip = false;
102  if (origin.isTrackAlongPlaneDir() == true && dw2dw1 < 0.) flip = true;
103  if (origin.isTrackAlongPlaneDir() == false && dw2dw1 > 0.) flip = true;
104  bool ok = apply_mcs(detProp,
105  par5d[2],
106  par5d[3],
107  par5d[4],
108  origin.mass(),
109  s,
110  range,
111  p,
112  e * e,
113  flip,
114  noise_matrix);
115  if (!ok) {
116  success = false;
117  return origin;
118  }
119  }
120  if (dodedx) { apply_dedx(par5d(4), detProp, dedx, e, origin.mass(), s, deriv); }
121  }
122  if (fPropPinvErr) pm(4, 4) *= deriv;
123  //
124  // 6- create final track state
125  cov5d = ROOT::Math::Similarity(pm, cov5d); //*rj
126  cov5d = cov5d + noise_matrix;
127  TrackState trackState(
128  par5d, cov5d, target, origin.momentum().Dot(target.direction()) > 0, origin.pID());
129  return trackState;
130  }
131 
132  TrackState
134  const TrackState& origin,
135  const Plane& target,
136  double& dw2dw1) const
137  {
138  const bool isTrackAlongPlaneDir = origin.momentum().Dot(target.direction()) > 0;
139  //
140  SVector5 par5 = origin.parameters();
141  const double sinA1 = origin.plane().sinAlpha();
142  const double cosA1 = origin.plane().cosAlpha();
143  const double sinA2 = target.sinAlpha();
144  const double cosA2 = target.cosAlpha();
145  const double sinB1 = origin.plane().sinBeta();
146  const double cosB1 = origin.plane().cosBeta();
147  const double sinB2 = target.sinBeta();
148  const double cosB2 = target.cosBeta();
149  const double sindB = -sinB1 * cosB2 + cosB1 * sinB2;
150  const double cosdB = cosB1 * cosB2 + sinB1 * sinB2;
151  const double ruu = cosA1 * cosA2 + sinA1 * sinA2 * cosdB;
152  const double ruv = sinA2 * sindB;
153  const double ruw = sinA1 * cosA2 - cosA1 * sinA2 * cosdB;
154  const double rvu = -sinA1 * sindB;
155  const double rvv = cosdB;
156  const double rvw = cosA1 * sindB;
157  const double rwu = cosA1 * sinA2 - sinA1 * cosA2 * cosdB;
158  const double rwv = -cosA2 * sindB;
159  const double rww = sinA1 * sinA2 + cosA1 * cosA2 * cosdB;
160  dw2dw1 = par5[2] * rwu + par5[3] * rwv + rww;
161  if (dw2dw1 == 0.) {
162  success = false;
163  return origin;
164  }
165  const double dudw2 = (par5[2] * ruu + par5[3] * ruv + ruw) / dw2dw1;
166  const double dvdw2 = (par5[2] * rvu + par5[3] * rvv + rvw) / dw2dw1;
167  SMatrix55 pm;
168  //
169  pm(0, 0) = ruu - dudw2 * rwu; // du2/du1
170  pm(1, 0) = rvu - dvdw2 * rwu; // dv2/du1
171  pm(2, 0) = 0.; // d(dudw2)/du1
172  pm(3, 0) = 0.; // d(dvdw2)/du1
173  pm(4, 0) = 0.; // d(pinv2)/du1
174  //
175  pm(0, 1) = ruv - dudw2 * rwv; // du2/dv1
176  pm(1, 1) = rvv - dvdw2 * rwv; // dv2/dv1
177  pm(2, 1) = 0.; // d(dudw2)/dv1
178  pm(3, 1) = 0.; // d(dvdw2)/dv1
179  pm(4, 1) = 0.; // d(pinv2)/dv1
180  //
181  pm(0, 2) = 0.; // du2/d(dudw1);
182  pm(1, 2) = 0.; // dv2/d(dudw1);
183  pm(2, 2) = (ruu - dudw2 * rwu) / dw2dw1; // d(dudw2)/d(dudw1);
184  pm(3, 2) = (rvu - dvdw2 * rwu) / dw2dw1; // d(dvdw2)/d(dudw1);
185  pm(4, 2) = 0.; // d(pinv2)/d(dudw1);
186  //
187  pm(0, 3) = 0.; // du2/d(dvdw1);
188  pm(1, 3) = 0.; // dv2/d(dvdw1);
189  pm(2, 3) = (ruv - dudw2 * rwv) / dw2dw1; // d(dudw2)/d(dvdw1);
190  pm(3, 3) = (rvv - dvdw2 * rwv) / dw2dw1; // d(dvdw2)/d(dvdw1);
191  pm(4, 3) = 0.; // d(pinv2)/d(dvdw1);
192  //
193  pm(0, 4) = 0.; // du2/d(pinv1);
194  pm(1, 4) = 0.; // dv2/d(pinv1);
195  pm(2, 4) = 0.; // d(dudw2)/d(pinv1);
196  pm(3, 4) = 0.; // d(dvdw2)/d(pinv1);
197  pm(4, 4) = 1.; // d(pinv2)/d(pinv1);
198  //
199  par5[0] = (origin.position().X() - target.position().X()) * cosA2 +
200  (origin.position().Y() - target.position().Y()) * sinA2 * sinB2 -
201  (origin.position().Z() - target.position().Z()) * sinA2 * cosB2;
202  par5[1] = (origin.position().Y() - target.position().Y()) * cosB2 +
203  (origin.position().Z() - target.position().Z()) * sinB2;
204  par5[2] = dudw2;
205  par5[3] = dvdw2;
206  //
207  success = true;
208  return TrackState(par5,
209  ROOT::Math::Similarity(pm, origin.covariance()),
210  Plane(origin.position(), target.direction()),
211  isTrackAlongPlaneDir,
212  origin.pID());
213  }
214 
215  double
217  const Point_t& origpos,
218  const Vector_t& origmom,
219  const Plane& target) const
220  {
221  const Point_t& targpos = target.position();
222  const Vector_t& targdir = target.direction();
223  //check that origmom is not along the plane, i.e. targdir.Dot(origmom.Unit())=0
224  if (targdir.Dot(origmom.Unit()) == 0) {
225  success = false;
226  return DBL_MAX;
227  }
228  //distance along track direction
229  double s = targdir.Dot(targpos - origpos) / targdir.Dot(origmom.Unit());
230  success = true;
231  return s;
232  }
233 
234  double
236  const Point_t& origpos,
237  const Plane& target) const
238  {
239  const Point_t& targpos = target.position();
240  const Vector_t& targdir = target.direction();
241  //point-plane distance projected along direction orthogonal to the plane
242  double sperp = targdir.Dot(targpos - origpos);
243  success = true;
244  return sperp;
245  }
246 
247  std::pair<double, double>
249  const Point_t& origpos,
250  const Vector_t& origmom,
251  const Plane& target) const
252  {
253  const Point_t& targpos = target.position();
254  const Vector_t& targdir = target.direction();
255  //check that origmom is not along the plane, i.e. targdir.Dot(origmom.Unit())=0
256  if (targdir.Dot(origmom.Unit()) == 0) {
257  success = false;
258  return std::pair<double, double>(DBL_MAX, DBL_MAX);
259  }
260  //point-plane distance projected along direction orthogonal to the plane
261  double sperp = targdir.Dot(targpos - origpos);
262  //distance along track direction
263  double s = sperp / targdir.Dot(origmom.Unit());
264  success = true;
265  return std::pair<double, double>(s, sperp);
266  }
267 
268  void
270  detinfo::DetectorPropertiesData const& detProp,
271  double dedx,
272  double e1,
273  double mass,
274  double s,
275  double& deriv) const
276  {
277  // For infinite initial momentum, return with infinite momentum.
278  if (pinv == 0.) return;
279  //
280  const double emid = e1 - 0.5 * s * dedx;
281  if (emid > mass) {
282  const double pmid = std::sqrt(emid * emid - mass * mass);
283  const double e2 = e1 - 0.001 * s * detProp.Eloss(pmid, mass, fTcut);
284  if (e2 > mass) {
285  const double p2 = std::sqrt(e2 * e2 - mass * mass);
286  double pinv2 = 1. / p2;
287  if (pinv < 0.) pinv2 = -pinv2;
288  // derivative
289  deriv = pinv2 * pinv2 * pinv2 * e2 / (pinv * pinv * pinv * e1);
290  // update result.
291  pinv = pinv2;
292  }
293  }
294  return;
295  }
296 
297  bool
299  double dudw,
300  double dvdw,
301  double pinv,
302  double mass,
303  double s,
304  double range,
305  double p,
306  double e2,
307  bool flipSign,
308  SMatrixSym55& noise_matrix) const
309  {
310  // If distance is zero, or momentum is infinite, return zero noise.
311 
312  if (pinv == 0. || s == 0.) return true;
313 
314  // Use crude estimate of the range of the track.
315  if (range > 100.) range = 100.;
316  const double p2 = p * p;
317 
318  // Calculate the radiation length in cm.
319  const double x0 = larprop->RadiationLength() / detProp.Density();
320 
321  // Calculate projected rms scattering angle.
322  // Use the estimted range in the logarithm factor.
323  // Use the incremental propagation distance in the square root factor.
324  const double betainv = std::sqrt(1. + pinv * pinv * mass * mass);
325  const double theta_fact = (0.0136 * pinv * betainv) * (1. + 0.038 * std::log(range / x0));
326  const double theta02 = theta_fact * theta_fact * std::abs(s / x0);
327 
328  // Calculate some common factors needed for multiple scattering.
329  const double ufact2 = 1. + dudw * dudw;
330  const double vfact2 = 1. + dvdw * dvdw;
331  const double uvfact2 = 1. + dudw * dudw + dvdw * dvdw;
332  const double uvfact = std::sqrt(uvfact2);
333  const double uv = dudw * dvdw;
334  const double dist2_3 = s * s / 3.;
335  double dist_2 = std::abs(s) / 2.;
336  if (flipSign) dist_2 = -dist_2;
337 
338  // Calculate energy loss fluctuations.
339 
340  const double evar = 1.e-6 * detProp.ElossVar(p, mass) * std::abs(s); // E variance (GeV^2).
341  const double pinvvar = evar * e2 / (p2 * p2 * p2); // Inv. p variance (1/GeV^2)
342 
343  // Update elements of noise matrix.
344 
345  // Position submatrix.
346  noise_matrix(0, 0) += dist2_3 * theta02 * ufact2; // sigma^2(u,u)
347  noise_matrix(1, 0) += dist2_3 * theta02 * uv; // sigma^2(u,v)
348  noise_matrix(1, 1) += dist2_3 * theta02 * vfact2; // sigma^2(v,v)
349 
350  // Slope submatrix.
351  noise_matrix(2, 2) += theta02 * uvfact2 * ufact2; // sigma^2(u', u')
352  noise_matrix(3, 2) += theta02 * uvfact2 * uv; // sigma^2(v', u')
353  noise_matrix(3, 3) += theta02 * uvfact2 * vfact2; // sigma^2(v', v')
354 
355  // Same-view position-slope correlations.
356  noise_matrix(2, 0) += dist_2 * theta02 * uvfact * ufact2; // sigma^2(u', u)
357  noise_matrix(3, 1) += dist_2 * theta02 * uvfact * vfact2; // sigma^2(v', v)
358 
359  // Opposite-view position-slope correlations.
360  noise_matrix(2, 1) += dist_2 * theta02 * uvfact * uv; // sigma^2(u', v)
361  noise_matrix(3, 0) += dist_2 * theta02 * uvfact * uv; // sigma^2(v', u)
362 
363  // Momentum correlations (zero).
364  // noise_matrix(4,0) += 0.; // sigma^2(pinv, u)
365  // noise_matrix(4,1) += 0.; // sigma^2(pinv, v)
366  // noise_matrix(4,2) += 0.; // sigma^2(pinv, u')
367  // noise_matrix(4,3) += 0.; // sigma^2(pinv, v')
368 
369  // Energy loss fluctuations.
370  if (fPropPinvErr) noise_matrix(4, 4) += pinvvar; // sigma^2(pinv, pinv)
371 
372  // Done (success).
373  return true;
374  }
375 
376 } // end namespace trkf
double cosAlpha() const
Return cached values of trigonometric function for angles defining the plane.
recob::tracking::Plane Plane
Class for track parameters (and errors) defined on a recob::tracking::Plane.
Definition: TrackState.h:79
Vector_t const & direction() const
Reference direction orthogonal to the plane.
Definition: TrackingPlane.h:70
int fMaxNit
Maximum number of iterations.
double ElossVar(double mom, double mass) const
Energy loss fluctuation ( )
const Vector_t & momentum() const
momentum of the track
Definition: TrackState.h:98
const SVector5 & parameters() const
track parameters defined on the plane
Definition: TrackState.h:90
recob::tracking::SMatrixSym55 SMatrixSym55
Definition: TrackState.h:15
double cosBeta() const
string dir
recob::tracking::SMatrix55 SMatrix55
Definition: TrackState.h:14
TrackState propagateToPlane(bool &success, const detinfo::DetectorPropertiesData &detProp, const TrackState &origin, const Plane &target, bool dodedx, bool domcs, PropDirection dir=FORWARD) const
Main function for propagation of a TrackState to a Plane.
double distanceToPlane(bool &success, const Point_t &origpos, const Vector_t &origdir, const Plane &target) const
Distance of a TrackState (Point and Vector) to a Plane, along the TrackState direction.
bool apply_mcs(detinfo::DetectorPropertiesData const &detProp, double dudw, double dvdw, double pinv, double mass, double s, double range, double p, double e2, bool flipSign, SMatrixSym55 &noise_matrix) const
Apply multiple coulomb scattering.
recob::tracking::Point_t Point_t
double mass() const
mass hypthesis of the track
Definition: TrackState.h:102
double fMinStep
Minimum propagation step length guaranteed.
std::enable_if_t< std::is_arithmetic_v< T >, T > hypot(T x, T y)
Definition: hypot.h:60
void apply_dedx(double &pinv, detinfo::DetectorPropertiesData const &detProp, double dedx, double e1, double mass, double s, double &deriv) const
Apply energy loss.
const Point_t & position() const
position of the track
Definition: TrackState.h:96
T abs(T value)
double fTcut
Maximum delta ray energy for dE/dx.
bool isTrackAlongPlaneDir() const
is the track momentum along the plane direction?
Definition: TrackState.h:116
const double e
recob::tracking::SVector5 SVector5
Definition: TrackState.h:12
PropDirection
Propagation direction enum.
int pID() const
particle id hypthesis of the track
Definition: TrackState.h:100
Point_t const & position() const
Reference position on the plane.
Definition: TrackingPlane.h:66
TrackState rotateToPlane(bool &success, const TrackState &origin, const Plane &target) const
Rotation of a TrackState to a Plane (zero distance propagation)
Point_t propagatedPosByDistance(const Point_t &origpos, const Vector_t &origdir, double distance) const
Quick accesss to the propagated position given a distance.
p
Definition: test.py:223
double perpDistanceToPlane(bool &success, const Point_t &origpos, const Plane &target) const
Distance of a TrackState (Point) to a Plane along the direction orthogonal to the Plane...
double Density(double temperature=0.) const
Returns argon density at a given temperature.
double distance(double x1, double y1, double z1, double x2, double y2, double z2)
static int max(int a, int b)
std::pair< double, double > distancePairToPlane(bool &success, const Point_t &origpos, const Vector_t &origdir, const Plane &target) const
Return both direction types in one go.
const detinfo::LArProperties * larprop
Class defining a plane for tracking. It provides various functionalities to convert track parameters ...
Definition: TrackingPlane.h:37
double Eloss(double mom, double mass, double tcut) const
Restricted mean energy loss (dE/dx)
bool fPropPinvErr
Propagate error on 1/p or not (in order to avoid infs, it should be set to false when 1/p not updated...
double fWrongDirDistTolerance
Allowed propagation distance in the wrong direction.
double sinAlpha() const
virtual double RadiationLength() const =0
const SMatrixSym55 & covariance() const
track parameter covariance matrix on the plane
Definition: TrackState.h:92
double fMaxElossFrac
Maximum propagation step length based on fraction of energy loss.
double sinBeta() const
const Plane & plane() const
plane where the parameters are defined
Definition: TrackState.h:94
recob::tracking::Vector_t Vector_t
static QCString * s
Definition: config.cpp:1042
constexpr Point origin()
Returns a origin position with a point of the specified type.
Definition: geo_vectors.h:227