LArSoft  v09_90_00
Liquid Argon Software toolkit - https://larsoft.org/
PropYZLine.cxx
Go to the documentation of this file.
1 
12 #include "cetlib_except/exception.h"
17 #include <cmath>
18 
19 namespace trkf {
20 
28  PropYZLine::PropYZLine(detinfo::DetectorPropertiesData const& detProp, double tcut, bool doDedx)
29  : Propagator(detProp,
30  tcut,
31  doDedx,
32  (tcut >= 0. ? std::make_shared<const InteractGeneral>(detProp, tcut) :
33  std::shared_ptr<const Interactor>{}))
34  {}
35 
50  std::optional<double> PropYZLine::short_vec_prop(KTrack& trk,
51  const std::shared_ptr<const Surface>& psurf,
53  bool doDedx,
54  TrackMatrix* prop_matrix,
55  TrackError* noise_matrix) const
56  {
57  // Set the default return value to be unitialized with value 0.
58 
59  std::optional<double> result{std::nullopt};
60 
61  // Get destination surface and surface parameters.
62  // Return failure if wrong surface type.
63 
64  const SurfYZLine* to = dynamic_cast<const SurfYZLine*>(&*psurf);
65  if (to == 0) return result;
66  double x02 = to->x0();
67  double y02 = to->y0();
68  double z02 = to->z0();
69  double phi2 = to->phi();
70 
71  // Remember starting track.
72 
73  KTrack trk0(trk);
74 
75  // Get track position.
76 
77  double xyz[3];
78  trk.getPosition(xyz);
79  double x01 = xyz[0];
80  double y01 = xyz[1];
81  double z01 = xyz[2];
82 
83  // Propagate to origin surface.
84 
85  TrackMatrix local_prop_matrix;
86  TrackMatrix* plocal_prop_matrix = (prop_matrix == 0 ? 0 : &local_prop_matrix);
87  std::optional<double> result1 = origin_vec_prop(trk, psurf, plocal_prop_matrix);
88  if (!result1) return result1;
89 
90  // Get the intermediate track state vector and track parameters.
91 
92  const TrackVector& vec = trk.getVector();
93  if (vec.size() != 5)
94  throw cet::exception("PropYZLine")
95  << "Track state vector has wrong size" << vec.size() << "\n";
96  double r1 = vec(0);
97  double v1 = vec(1);
98  double phid1 = vec(2);
99  double eta1 = vec(3);
100  double pinv = vec(4);
101 
102  // Calculate transcendental functions.
103 
104  double sinphid1 = std::sin(phid1);
105  double cosphid1 = std::cos(phid1);
106  double sh1 = std::sinh(eta1);
107  double ch1 = std::cosh(eta1);
108  double sinphi2 = std::sin(phi2);
109  double cosphi2 = std::cos(phi2);
110 
111  // Calculate the initial position in the intermediate coordinate system.
112 
113  double u1 = -r1 * sinphid1;
114  double w1 = r1 * cosphid1;
115 
116  // Calculate initial position in the destination coordinate system.
117 
118  double u2 = x01 - x02 + u1;
119  double v2 = (y01 - y02) * cosphi2 + (z01 - z02) * sinphi2 + v1;
120  double w2 = -(y01 - y02) * sinphi2 + (z01 - z02) * cosphi2 + w1;
121 
122  // Calculate the impact parameter in the destination coordinate system.
123 
124  double r2 = w2 * cosphid1 - u2 * sinphid1;
125 
126  // Calculate the perpendicular propagation distance.
127 
128  double d2 = -(w2 * sinphid1 + u2 * cosphid1);
129 
130  // Calculate the final position in the destination coordinate system.
131 
132  //double u2p = -r2 * sinphid1;
133  double v2p = v2 + d2 * sh1;
134  //double w2p = r2 * cosphid1;
135 
136  // Calculate the signed propagation distance.
137 
138  double s = d2 * ch1;
139 
140  // Check if propagation was in the right direction.
141  // (Compare sign of s with requested direction).
142 
143  bool sok = (dir == Propagator::UNKNOWN || (dir == Propagator::FORWARD && s >= 0.) ||
144  (dir == Propagator::BACKWARD && s <= 0.));
145 
146  // If wrong direction, return failure without updating the track
147  // or propagation matrix.
148 
149  if (!sok) {
150  trk = trk0;
151  return result;
152  }
153 
154  // Find final momentum.
155 
156  double deriv = 1.;
157  auto pinv2 = std::make_optional(pinv);
158  if (getDoDedx() && doDedx && s != 0.) {
159  double* pderiv = (prop_matrix != 0 ? &deriv : 0);
160  pinv2 = dedx_prop(pinv, trk.Mass(), s, pderiv);
161  }
162 
163  // Return failure in case of range out.
164 
165  if (!pinv2) {
166  trk = trk0;
167  return result;
168  }
169 
170  // Update default result to success and store propagation distance.
171 
172  result = std::make_optional(s);
173 
174  // Update propagation matrix (if requested).
175 
176  if (prop_matrix != 0) {
177  TrackMatrix pm;
178  pm.resize(vec.size(), vec.size(), false);
179 
180  // Calculate partial derivatives.
181 
182  pm(0, 0) = 1.; // dr2/dr1
183  pm(1, 0) = 0.; // dv2/dr1
184  pm(2, 0) = 0.; // d(phi2)/dr1
185  pm(3, 0) = 0.; // d(eta2)/dr1
186  pm(4, 0) = 0.; // d(pinv2)/dr1
187 
188  pm(0, 1) = 0.; // dr2/dv1
189  pm(1, 1) = 1.; // dv2/dv1
190  pm(2, 1) = 0.; // d(phi2)/dv1
191  pm(3, 1) = 0.; // d(eta2)/dv1
192  pm(4, 1) = 0.; // d(pinv2)/dv1
193 
194  pm(0, 2) = d2; // dr2/d(phi1);
195  pm(1, 2) = -r2 * sh1; // dv2/d(phi1);
196  pm(2, 2) = 1.; // d(phi2)/d(phi1);
197  pm(3, 2) = 0.; // d(eta2)/d(phi1);
198  pm(4, 2) = 0.; // d(pinv2)/d(phi1);
199 
200  pm(0, 3) = 0.; // dr2/d(eta1);
201  pm(1, 3) = d2 * ch1; // dv2/d(eta1);
202  pm(2, 3) = 0.; // d(phi2)/d(eta1);
203  pm(3, 3) = 1.; // d(eta2)/d(eta1);
204  pm(4, 3) = 0.; // d(pinv2)/d(eta1);
205 
206  pm(0, 4) = 0.; // dr2/d(pinv1);
207  pm(1, 4) = 0.; // dv2/d(pinv1);
208  pm(2, 4) = 0.; // d(phi2)/d(pinv1);
209  pm(3, 4) = 0.; // d(eta2)/d(pinv1);
210  pm(4, 4) = deriv; // d(pinv2)/d(pinv1);
211 
212  // Compose the final propagation matrix from zero-distance propagation and
213  // parallel surface propagation.
214 
215  *prop_matrix = prod(pm, *plocal_prop_matrix);
216  }
217 
218  // Update noise matrix (if requested).
219 
220  if (noise_matrix != 0) {
221  noise_matrix->resize(vec.size(), vec.size(), false);
222  if (getInteractor().get() != 0) {
223  bool ok = getInteractor()->noise(trk, s, *noise_matrix);
224  if (!ok) {
225  trk = trk0;
226  return std::nullopt;
227  }
228  }
229  else
230  noise_matrix->clear();
231  }
232 
233  // Construct track vector at destination surface.
234 
235  TrackVector vec2(vec.size());
236  vec2(0) = r2;
237  vec2(1) = v2p;
238  vec2(2) = phid1;
239  vec2(3) = eta1;
240  vec2(4) = *pinv2;
241 
242  // Update track.
243 
244  trk.setSurface(psurf);
245  trk.setVector(vec2);
246 
247  // Done.
248 
249  return result;
250  }
251 
265  std::optional<double> PropYZLine::origin_vec_prop(KTrack& trk,
266  const std::shared_ptr<const Surface>& porient,
267  TrackMatrix* prop_matrix) const
268  {
269  // Set the default return value to be unitialized with value 0.
270 
271  std::optional<double> result{std::nullopt};
272 
273  // Remember starting track.
274 
275  KTrack trk0(trk);
276 
277  // Get initial track parameters and direction.
278  // Note the initial track can be on any type of surface.
279 
280  TrackVector vec = trk.getVector(); // Modifiable copy.
281  if (vec.size() != 5)
282  throw cet::exception("PropYZPlane")
283  << "Track state vector has wrong size" << vec.size() << "\n";
285 
286  // Get track position.
287 
288  double xyz[3];
289  trk.getPosition(xyz);
290  double x02 = xyz[0];
291  double y02 = xyz[1];
292  double z02 = xyz[2];
293 
294  // Generate the origin surface, which will be the destination surface.
295  // Return failure if orientation surface is the wrong type.
296 
297  const SurfYZLine* orient = dynamic_cast<const SurfYZLine*>(&*porient);
298  if (orient == 0) return result;
299  double phi2 = orient->phi();
300  std::shared_ptr<const Surface> porigin(new SurfYZLine(x02, y02, z02, phi2));
301 
302  // Test initial surface types.
303 
304  if (const SurfYZLine* from = dynamic_cast<const SurfYZLine*>(&*trk.getSurface())) {
305 
306  // Initial surface is SurfYZLine.
307  // Get surface paramters.
308 
309  double phi1 = from->phi();
310 
311  // Transform track to origin surface.
312 
313  bool ok = transformYZLine(phi1, phi2, vec, dir, prop_matrix);
314  result = std::make_optional(0.);
315  if (!ok) return std::nullopt;
316  }
317  else if (const SurfYZPlane* from = dynamic_cast<const SurfYZPlane*>(&*trk.getSurface())) {
318 
319  // Initial surface is SurfYZPlane.
320  // Get surface paramters.
321 
322  double phi1 = from->phi();
323 
324  // Transform track to origin surface.
325 
326  bool ok = transformYZPlane(phi1, phi2, vec, dir, prop_matrix);
327  result = std::make_optional(0.);
328  if (!ok) return std::nullopt;
329  }
330  else if (const SurfXYZPlane* from = dynamic_cast<const SurfXYZPlane*>(&*trk.getSurface())) {
331 
332  // Initial surface is SurfXYZPlane.
333  // Get surface paramters.
334 
335  double theta1 = from->theta();
336  double phi1 = from->phi();
337 
338  // Transform track to origin surface.
339 
340  bool ok = transformXYZPlane(theta1, phi1, phi2, vec, dir, prop_matrix);
341  result = std::make_optional(0.);
342  if (!ok) return std::nullopt;
343  }
344 
345  // Update track.
346 
347  trk.setSurface(porigin);
348  trk.setVector(vec);
349  trk.setDirection(dir);
350 
351  // Final validity check.
352 
353  if (!trk.isValid()) {
354  trk = trk0;
355  result = std::nullopt;
356  }
357 
358  // Done.
359 
360  return result;
361  }
362 
363  // Transform track parameters from SurfYZLine to SurfYZLine.
364 
365  bool PropYZLine::transformYZLine(double phi1,
366  double phi2,
367  TrackVector& vec,
369  TrackMatrix* prop_matrix) const
370  {
371  // Calculate surface transcendental functions.
372 
373  double sindphi = std::sin(phi2 - phi1);
374  double cosdphi = std::cos(phi2 - phi1);
375 
376  // Get the initial track parameters.
377 
378  double r1 = vec(0);
379  double phid1 = vec(2);
380  double eta1 = vec(3);
381 
382  // Calculate elements of rotation matrix from initial coordinate
383  // system to destination coordinte system.
384 
385  double rvv = cosdphi;
386  double rvw = sindphi;
387 
388  double rwv = -sindphi;
389  double rww = cosdphi;
390 
391  // Calculate track transcendental functions.
392 
393  double sinphid1 = std::sin(phid1);
394  double cosphid1 = std::cos(phid1);
395  double sh1 = 1. / std::cosh(eta1); // sech(eta1)
396  double th1 = std::tanh(eta1);
397 
398  // Calculate initial position in Cartesian coordinates.
399 
400  double u1 = -r1 * sinphid1;
401  double w1 = r1 * cosphid1;
402 
403  // Calculate direction in destination coordinate system.
404 
405  double du2 = sh1 * cosphid1;
406  double dv2 = th1 * cosdphi + sh1 * sinphid1 * sindphi;
407  double dw2 = -th1 * sindphi + sh1 * sinphid1 * cosdphi;
408  double duw2 = std::hypot(du2, dw2);
409 
410  // Calculate final direction track parameters.
411 
412  double phid2 = atan2(dw2, du2);
413  double eta2 = std::asinh(dv2 / duw2);
414 
415  // Update propagation matrix (if requested).
416 
417  if (prop_matrix != 0) {
418  TrackMatrix& pm = *prop_matrix;
419  pm.resize(vec.size(), vec.size(), false);
420 
421  // Calculate partial derivatives.
422 
423  // Partials of initial positions and directions wrt initial t.p.'s.
424 
425  double du1dr1 = -sinphid1;
426  double du1dphi1 = -w1;
427 
428  double dw1dr1 = cosphid1;
429  double dw1dphi1 = u1;
430 
431  double ddu1dphi1 = -sinphid1 * sh1;
432  double ddu1deta1 = -cosphid1 * sh1 * th1;
433 
434  double ddv1deta1 = sh1 * sh1;
435 
436  double ddw1dphi1 = cosphid1 * sh1;
437  double ddw1deta1 = -sinphid1 * sh1 * th1;
438 
439  // Rotate partials to destination coordinate system.
440 
441  double du2dr1 = du1dr1;
442  double dv2dr1 = rvw * dw1dr1;
443  double dw2dr1 = rww * dw1dr1;
444 
445  double dv2dv1 = rvv;
446  double dw2dv1 = rwv;
447 
448  double du2dphi1 = du1dphi1;
449  double dv2dphi1 = rvw * dw1dphi1;
450  double dw2dphi1 = rww * dw1dphi1;
451 
452  double ddu2dphi1 = ddu1dphi1;
453  double ddv2dphi1 = rvw * ddw1dphi1;
454  double ddw2dphi1 = rww * ddw1dphi1;
455 
456  double ddu2deta1 = ddu1deta1;
457  double ddv2deta1 = rvv * ddv1deta1 + rvw * ddw1deta1;
458  double ddw2deta1 = rwv * ddv1deta1 + rww * ddw1deta1;
459 
460  // Partials of final t.p. wrt final position and direction.
461 
462  double dr2du2 = -dw2 / duw2;
463  double dr2dw2 = du2 / duw2;
464 
465  double dphi2ddu2 = -dw2 / (duw2 * duw2);
466  double dphi2ddw2 = du2 / (duw2 * duw2);
467 
468  double deta2ddv2 = 1. / (duw2 * duw2);
469 
470  // Partials of final t.p. wrt initial t.p.
471 
472  double dr2dr1 = dr2du2 * du2dr1 + dr2dw2 * dw2dr1;
473  double dr2dv1 = dr2dw2 * dw2dv1;
474  double dr2dphi1 = dr2du2 * du2dphi1 + dr2dw2 * dw2dphi1;
475 
476  double dphi2dphi1 = dphi2ddu2 * ddu2dphi1 + dphi2ddw2 * ddw2dphi1;
477  double dphi2deta1 = dphi2ddu2 * ddu2deta1 + dphi2ddw2 * ddw2deta1;
478 
479  double deta2dphi1 = deta2ddv2 * ddv2dphi1;
480  double deta2deta1 = deta2ddv2 * ddv2deta1;
481 
482  // We still need to calculate the corretion due to the dependence of the
483  // propagation distance on the initial track parameters. This correction is
484  // needed even though the actual propagation distance is zero.
485 
486  // This correction only effects the v track parameter, since the v parameter
487  // the only parameter that actually dependes on the propagation distance.
488 
489  // Partials of propagation distance wrt position and direction in the destination
490  // coordinate system.
491 
492  double dsdu2 = -du2 / (duw2 * duw2);
493  double dsdw2 = -dw2 / (duw2 * duw2);
494 
495  // Partials of propagation distance wrt initial t.p.
496 
497  double dsdr1 = dsdu2 * du2dr1 + dsdw2 * dw2dr1;
498  double dsdv1 = dsdw2 * dw2dv1;
499  double dsdphi1 = dsdu2 * du2dphi1 + dsdw2 * dw2dphi1;
500 
501  // Calculate correction to v parameter partials wrt initial t.p. due to path length.
502 
503  dv2dr1 += dv2 * dsdr1;
504  dv2dv1 += dv2 * dsdv1;
505  dv2dphi1 += dv2 * dsdphi1;
506 
507  // Fill derivative matrix.
508 
509  pm(0, 0) = dr2dr1; // dr2/dr1
510  pm(1, 0) = dv2dr1; // dv2/dr1
511  pm(2, 0) = 0.; // d(phi2)/dr1
512  pm(3, 0) = 0.; // d(eta2)/dr1
513  pm(4, 0) = 0.; // d(pinv2)/dr1
514 
515  pm(0, 1) = dr2dv1; // dr2/dv1
516  pm(1, 1) = dv2dv1; // dv2/dv1
517  pm(2, 1) = 0.; // d(phi2)/dv1
518  pm(3, 1) = 0.; // d(eta2)/dv1
519  pm(4, 1) = 0.; // d(pinv2)/dv1
520 
521  pm(0, 2) = dr2dphi1; // dr2/d(phi1);
522  pm(1, 2) = dv2dphi1; // dv2/d(phi1);
523  pm(2, 2) = dphi2dphi1; // d(phi2)/d(phi1);
524  pm(3, 2) = deta2dphi1; // d(eta2)/d(phi1);
525  pm(4, 2) = 0.; // d(pinv2)/d(phi1);
526 
527  pm(0, 3) = 0.; // dr2/d(eta1);
528  pm(1, 3) = 0.; // dv2/d(eta1);
529  pm(2, 3) = dphi2deta1; // d(phi2)/d(eta1);
530  pm(3, 3) = deta2deta1; // d(eta2)/d(eta1);
531  pm(4, 3) = 0.; // d(pinv2)/d(eta1);
532 
533  pm(0, 4) = 0.; // dr2/d(pinv1);
534  pm(1, 4) = 0.; // dv2/d(pinv1);
535  pm(2, 4) = 0.; // d(phi2)/d(pinv1);
536  pm(3, 4) = 0.; // d(eta2)/d(pinv1);
537  pm(4, 4) = 1.; // d(pinv2)/d(pinv1);
538  }
539 
540  // Update track vector.
541 
542  vec(0) = 0.;
543  vec(1) = 0.;
544  vec(2) = phid2;
545  vec(3) = eta2;
546 
547  // Done (success).
548 
549  return true;
550  }
551 
552  // Transform track parameters from SurfYZPlane to SurfYZLine.
553 
555  double phi2,
556  TrackVector& vec,
558  TrackMatrix* prop_matrix) const
559  {
560  // Calculate surface transcendental functions.
561 
562  double sindphi = std::sin(phi2 - phi1);
563  double cosdphi = std::cos(phi2 - phi1);
564 
565  // Get the initial track parameters.
566 
567  double dudw1 = vec(2);
568  double dvdw1 = vec(3);
569 
570  // Make sure initial track has a valid direction.
571 
572  double dirf = 1.;
573  if (dir == Surface::BACKWARD)
574  dirf = -1.;
575  else if (dir != Surface::FORWARD)
576  return false;
577 
578  // Calculate elements of rotation matrix from initial coordinate
579  // system to destination coordinte system.
580 
581  double rvv = cosdphi;
582  double rvw = sindphi;
583 
584  double rwv = -sindphi;
585  double rww = cosdphi;
586 
587  // Calculate direction in the starting coordinate system.
588 
589  double dw1 = dirf / std::sqrt(1. + dudw1 * dudw1 + dvdw1 * dvdw1);
590  double du1 = dudw1 * dw1;
591  double dv1 = dvdw1 * dw1;
592 
593  // Rotate direction vector into destination coordinate system.
594 
595  double du2 = du1;
596  double dv2 = rvv * dv1 + rvw * dw1;
597  double dw2 = rwv * dv1 + rww * dw1;
598  double duw2 = std::hypot(du2, dw2);
599 
600  // Calculate final direction track parameters.
601 
602  double phid2 = atan2(dw2, du2);
603  double eta2 = std::asinh(dv2 / duw2);
604 
605  // Update propagation matrix (if requested).
606 
607  if (prop_matrix != 0) {
608  TrackMatrix& pm = *prop_matrix;
609  pm.resize(vec.size(), vec.size(), false);
610 
611  // Calculate partial derivatives.
612 
613  // Partials of initial positions and directions wrt initial t.p.'s.
614 
615  double ddu1ddudw1 = (1. + dvdw1 * dvdw1) * dw1 * dw1 * dw1;
616  double ddu1ddvdw1 = -dudw1 * dvdw1 * dw1 * dw1 * dw1;
617 
618  double ddv1ddudw1 = -dudw1 * dvdw1 * dw1 * dw1 * dw1;
619  double ddv1ddvdw1 = (1. + dudw1 * dudw1) * dw1 * dw1 * dw1;
620 
621  double ddw1ddudw1 = -dudw1 * dw1 * dw1 * dw1;
622  double ddw1ddvdw1 = -dvdw1 * dw1 * dw1 * dw1;
623 
624  // Rotate partials to destination coordinate system.
625 
626  double dv2dv1 = rvv;
627  double dw2dv1 = rwv;
628 
629  double ddu2ddudw1 = ddu1ddudw1;
630  double ddv2ddudw1 = rvv * ddv1ddudw1 + rvw * ddw1ddudw1;
631  double ddw2ddudw1 = rwv * ddv1ddudw1 + rww * ddw1ddudw1;
632 
633  double ddu2ddvdw1 = ddu1ddvdw1;
634  double ddv2ddvdw1 = rvv * ddv1ddvdw1 + rvw * ddw1ddvdw1;
635  double ddw2ddvdw1 = rwv * ddv1ddvdw1 + rww * ddw1ddvdw1;
636 
637  // Partials of final t.p. wrt final position and direction.
638 
639  double dr2du2 = -dw2 / duw2;
640  double dr2dw2 = du2 / duw2;
641 
642  double dphi2ddu2 = -dw2 / (duw2 * duw2);
643  double dphi2ddw2 = du2 / (duw2 * duw2);
644 
645  double deta2ddv2 = 1. / (duw2 * duw2);
646 
647  // Partials of final t.p. wrt initial t.p.
648 
649  double dr2du1 = dr2du2;
650  double dr2dv1 = dr2dw2 * dw2dv1;
651 
652  double dphi2ddudw1 = dphi2ddu2 * ddu2ddudw1 + dphi2ddw2 * ddw2ddudw1;
653  double dphi2ddvdw1 = dphi2ddu2 * ddu2ddvdw1 + dphi2ddw2 * ddw2ddvdw1;
654 
655  double deta2ddudw1 = deta2ddv2 * ddv2ddudw1;
656  double deta2ddvdw1 = deta2ddv2 * ddv2ddvdw1;
657 
658  // We still need to calculate the corretion due to the dependence of the
659  // propagation distance on the initial track parameters. This correction is
660  // needed even though the actual propagation distance is zero.
661 
662  // This correction only effects the v track parameter, since the v parameter
663  // the only parameter that actually dependes on the propagation distance.
664 
665  // Partials of propagation distance wrt position and direction in the destination
666  // coordinate system.
667 
668  double dsdu2 = -du2 / (duw2 * duw2);
669  double dsdw2 = -dw2 / (duw2 * duw2);
670 
671  // Partials of propagation distance wrt initial t.p.
672 
673  double dsdu1 = dsdu2;
674  double dsdv1 = dsdw2 * dw2dv1;
675 
676  // Calculate correction to v parameter partials wrt initial t.p. due to path length.
677 
678  double dv2du1 = dv2 * dsdu1;
679  dv2dv1 += dv2 * dsdv1;
680 
681  // Fill matrix.
682 
683  pm(0, 0) = dr2du1; // dr2/du1
684  pm(1, 0) = dv2du1; // dv2/du1
685  pm(2, 0) = 0.; // d(phi2)/du1
686  pm(3, 0) = 0.; // d(eta2)/du1
687  pm(4, 0) = 0.; // d(pinv2)/du1
688 
689  pm(0, 1) = dr2dv1; // dr2/dv1
690  pm(1, 1) = dv2dv1; // dv2/dv1
691  pm(2, 1) = 0.; // d(phi2)/dv1
692  pm(3, 1) = 0.; // d(eta2)/dv1
693  pm(4, 1) = 0.; // d(pinv2)/dv1
694 
695  pm(0, 2) = 0.; // dr2/d(dudw1);
696  pm(1, 2) = 0.; // dv2/d(dudw1);
697  pm(2, 2) = dphi2ddudw1; // d(dudw2)/d(dudw1);
698  pm(3, 2) = deta2ddudw1; // d(eta2)/d(dudw1);
699  pm(4, 2) = 0.; // d(pinv2)/d(dudw1);
700 
701  pm(0, 3) = 0.; // dr2/d(dvdw1);
702  pm(1, 3) = 0.; // dv2/d(dvdw1);
703  pm(2, 3) = dphi2ddvdw1; // d(phi2)/d(dvdw1);
704  pm(3, 3) = deta2ddvdw1; // d(eta2)/d(dvdw1);
705  pm(4, 3) = 0.; // d(pinv2)/d(dvdw1);
706 
707  pm(0, 4) = 0.; // dr2/d(pinv1);
708  pm(1, 4) = 0.; // dv2/d(pinv1);
709  pm(2, 4) = 0.; // d(phi2)/d(pinv1);
710  pm(3, 4) = 0.; // d(eta2)/d(pinv1);
711  pm(4, 4) = 1.; // d(pinv2)/d(pinv1);
712  }
713 
714  // Update track vector.
715 
716  vec(0) = 0.;
717  vec(1) = 0.;
718  vec(2) = phid2;
719  vec(3) = eta2;
720 
721  // Done (success).
722 
723  return true;
724  }
725 
726  // Transform track parameters from SurfXYZPlane to SurfYZLine.
727 
728  bool PropYZLine::transformXYZPlane(double theta1,
729  double phi1,
730  double phi2,
731  TrackVector& vec,
733  TrackMatrix* prop_matrix) const
734  {
735  // Calculate surface transcendental functions.
736 
737  double sinth1 = std::sin(theta1);
738  double costh1 = std::cos(theta1);
739 
740  double sindphi = std::sin(phi2 - phi1);
741  double cosdphi = std::cos(phi2 - phi1);
742 
743  // Get the initial track parameters.
744 
745  double dudw1 = vec(2);
746  double dvdw1 = vec(3);
747 
748  // Make sure initial track has a valid direction.
749 
750  double dirf = 1.;
751  if (dir == Surface::BACKWARD)
752  dirf = -1.;
753  else if (dir != Surface::FORWARD)
754  return false;
755 
756  // Calculate elements of rotation matrix from initial coordinate
757  // system to destination coordinte system.
758 
759  double ruu = costh1;
760  double ruw = sinth1;
761 
762  double rvu = -sinth1 * sindphi;
763  double rvv = cosdphi;
764  double rvw = costh1 * sindphi;
765 
766  double rwu = -sinth1 * cosdphi;
767  double rwv = -sindphi;
768  double rww = costh1 * cosdphi;
769 
770  // Calculate direction in the starting coordinate system.
771 
772  double dw1 = dirf / std::sqrt(1. + dudw1 * dudw1 + dvdw1 * dvdw1);
773  double du1 = dudw1 * dw1;
774  double dv1 = dvdw1 * dw1;
775 
776  // Rotate direction vector into destination coordinate system.
777 
778  double du2 = ruu * du1 + ruw * dw1;
779  double dv2 = rvu * du1 + rvv * dv1 + rvw * dw1;
780  double dw2 = rwu * du1 + rwv * dv1 + rww * dw1;
781  double duw2 = std::hypot(du2, dw2);
782 
783  // Calculate final direction track parameters.
784 
785  double phid2 = atan2(dw2, du2);
786  double eta2 = std::asinh(dv2 / duw2);
787 
788  // Update propagation matrix (if requested).
789 
790  if (prop_matrix != 0) {
791  TrackMatrix& pm = *prop_matrix;
792  pm.resize(vec.size(), vec.size(), false);
793 
794  // Calculate partial derivatives.
795 
796  // Partials of initial positions and directions wrt initial t.p.'s.
797 
798  double ddu1ddudw1 = (1. + dvdw1 * dvdw1) * dw1 * dw1 * dw1;
799  double ddu1ddvdw1 = -dudw1 * dvdw1 * dw1 * dw1 * dw1;
800 
801  double ddv1ddudw1 = -dudw1 * dvdw1 * dw1 * dw1 * dw1;
802  double ddv1ddvdw1 = (1. + dudw1 * dudw1) * dw1 * dw1 * dw1;
803 
804  double ddw1ddudw1 = -dudw1 * dw1 * dw1 * dw1;
805  double ddw1ddvdw1 = -dvdw1 * dw1 * dw1 * dw1;
806 
807  // Rotate partials to destination coordinate system.
808 
809  double du2du1 = ruu;
810  double dv2du1 = rvu;
811  double dw2du1 = rwu;
812 
813  double dv2dv1 = rvv;
814  double dw2dv1 = rwv;
815 
816  double ddu2ddudw1 = ruu * ddu1ddudw1 + ruw * ddw1ddudw1;
817  double ddv2ddudw1 = rvu * ddu1ddudw1 + rvv * ddv1ddudw1 + rvw * ddw1ddudw1;
818  double ddw2ddudw1 = rwu * ddu1ddudw1 + rwv * ddv1ddudw1 + rww * ddw1ddudw1;
819 
820  double ddu2ddvdw1 = ruu * ddu1ddvdw1 + ruw * ddw1ddvdw1;
821  double ddv2ddvdw1 = rvu * ddu1ddvdw1 + rvv * ddv1ddvdw1 + rvw * ddw1ddvdw1;
822  double ddw2ddvdw1 = rwu * ddu1ddvdw1 + rwv * ddv1ddvdw1 + rww * ddw1ddvdw1;
823 
824  // Partials of final t.p. wrt final position and direction.
825 
826  double dr2du2 = -dw2 / duw2;
827  double dr2dw2 = du2 / duw2;
828 
829  double dphi2ddu2 = -dw2 / (duw2 * duw2);
830  double dphi2ddw2 = du2 / (duw2 * duw2);
831 
832  double deta2ddv2 = 1. / (duw2 * duw2);
833 
834  // Partials of final t.p. wrt initial t.p.
835 
836  double dr2du1 = dr2du2 * du2du1 + dr2dw2 * dw2du1;
837  double dr2dv1 = dr2dw2 * dw2dv1;
838 
839  double dphi2ddudw1 = dphi2ddu2 * ddu2ddudw1 + dphi2ddw2 * ddw2ddudw1;
840  double dphi2ddvdw1 = dphi2ddu2 * ddu2ddvdw1 + dphi2ddw2 * ddw2ddvdw1;
841 
842  double deta2ddudw1 = deta2ddv2 * ddv2ddudw1;
843  double deta2ddvdw1 = deta2ddv2 * ddv2ddvdw1;
844 
845  // We still need to calculate the corretion due to the dependence of the
846  // propagation distance on the initial track parameters. This correction is
847  // needed even though the actual propagation distance is zero.
848 
849  // This correction only effects the v track parameter, since the v parameter
850  // the only parameter that actually dependes on the propagation distance.
851 
852  // Partials of propagation distance wrt position and direction in the destination
853  // coordinate system.
854 
855  double dsdu2 = -du2 / (duw2 * duw2);
856  double dsdw2 = -dw2 / (duw2 * duw2);
857 
858  // Partials of propagation distance wrt initial t.p.
859 
860  double dsdu1 = dsdu2 * du2du1 + dsdw2 * dw2du1;
861  double dsdv1 = dsdw2 * dw2dv1;
862 
863  // Calculate correction to v parameter partials wrt initial t.p. due to path length.
864 
865  dv2du1 += dv2 * dsdu1;
866  dv2dv1 += dv2 * dsdv1;
867 
868  // Fill matrix.
869 
870  pm(0, 0) = dr2du1; // dr2/du1
871  pm(1, 0) = dv2du1; // dv2/du1
872  pm(2, 0) = 0.; // d(phi2)/du1
873  pm(3, 0) = 0.; // d(eta2)/du1
874  pm(4, 0) = 0.; // d(pinv2)/du1
875 
876  pm(0, 1) = dr2dv1; // dr2/dv1
877  pm(1, 1) = dv2dv1; // dv2/dv1
878  pm(2, 1) = 0.; // d(phi2)/dv1
879  pm(3, 1) = 0.; // d(eta2)/dv1
880  pm(4, 1) = 0.; // d(pinv2)/dv1
881 
882  pm(0, 2) = 0.; // dr2/d(dudw1);
883  pm(1, 2) = 0.; // dv2/d(dudw1);
884  pm(2, 2) = dphi2ddudw1; // d(dudw2)/d(dudw1);
885  pm(3, 2) = deta2ddudw1; // d(eta2)/d(dudw1);
886  pm(4, 2) = 0.; // d(pinv2)/d(dudw1);
887 
888  pm(0, 3) = 0.; // dr2/d(dvdw1);
889  pm(1, 3) = 0.; // dv2/d(dvdw1);
890  pm(2, 3) = dphi2ddvdw1; // d(phi2)/d(dvdw1);
891  pm(3, 3) = deta2ddvdw1; // d(eta2)/d(dvdw1);
892  pm(4, 3) = 0.; // d(pinv2)/d(dvdw1);
893 
894  pm(0, 4) = 0.; // dr2/d(pinv1);
895  pm(1, 4) = 0.; // dv2/d(pinv1);
896  pm(2, 4) = 0.; // d(phi2)/d(pinv1);
897  pm(3, 4) = 0.; // d(eta2)/d(pinv1);
898  pm(4, 4) = 1.; // d(pinv2)/d(pinv1);
899  }
900 
901  // Update track vector.
902 
903  vec(0) = 0.;
904  vec(1) = 0.;
905  vec(2) = phid2;
906  vec(3) = eta2;
907 
908  // Done (success).
909 
910  return true;
911  }
912 } // end namespace trkf
TrackDirection
Track direction enum.
Definition: Surface.h:54
bool transformXYZPlane(double theta1, double phi1, double phi2, TrackVector &vec, Surface::TrackDirection &dir, TrackMatrix *prop_matrix) const
Transform xyz plane -> yz line.
Definition: PropYZLine.cxx:728
Interactor for planar surfaces.
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.
std::optional< double > origin_vec_prop(KTrack &trk, const std::shared_ptr< const Surface > &porient, TrackMatrix *prop_matrix=0) const override
Propagate without error to surface whose origin parameters coincide with track position.
Definition: PropYZLine.cxx:265
KSymMatrix< 5 >::type TrackError
Track error matrix, dimension 5x5.
bool transformYZLine(double phi1, double phi2, TrackVector &vec, Surface::TrackDirection &dir, TrackMatrix *prop_matrix) const
Transform yz line -> yz line.
Definition: PropYZLine.cxx:365
void setVector(const TrackVector &vec)
Set state vector.
Definition: KTrack.h:65
void setDirection(Surface::TrackDirection dir)
Set direction.
Definition: KTrack.h:66
Planar surface parallel to x-axis.
STL namespace.
const std::shared_ptr< const Interactor > & getInteractor() const
Definition: Propagator.h:109
void setSurface(const std::shared_ptr< const Surface > &psurf)
Set surface.
Definition: KTrack.h:64
KMatrix< 5, 5 >::type TrackMatrix
General 5x5 matrix.
Propagate to SurfYZLine surface.
void getPosition(double xyz[3]) const
Get position of track.
Definition: KTrack.cxx:157
std::optional< double > short_vec_prop(KTrack &trk, const std::shared_ptr< const Surface > &surf, Propagator::PropDirection dir, bool doDedx, TrackMatrix *prop_matrix=0, TrackError *noise_matrix=0) const override
Propagate without error.
Definition: PropYZLine.cxx:50
bool transformYZPlane(double phi1, double phi2, TrackVector &vec, Surface::TrackDirection &dir, TrackMatrix *prop_matrix) const
Transform yz plane -> yz line.
Definition: PropYZLine.cxx:554
KVector< 5 >::type TrackVector
Track state vector, dimension 5.
double z0() const
Z origin.
Definition: SurfYZLine.h:92
bool getDoDedx() const
Definition: Propagator.h:108
const TrackVector & getVector() const
Track state vector.
Definition: KTrack.h:54
double x0() const
X origin.
Definition: SurfYZLine.h:90
TDirectory * dir
Definition: macro.C:5
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
PropYZLine(detinfo::DetectorPropertiesData const &detProp, double tcut, bool doDedx)
Definition: PropYZLine.cxx:28
Surface::TrackDirection getDirection() const
Track direction.
Definition: KTrack.cxx:64
double phi() const
Rotation angle about x-axis.
Definition: SurfYZLine.h:93
double y0() const
Y origin.
Definition: SurfYZLine.h:91
Line surface perpendicular to x-axis.
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