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