Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
NumericalTrackLinearizer.ipp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file NumericalTrackLinearizer.ipp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2023 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
12 
13 template <typename propagator_t, typename propagator_options_t>
16  linearizeTrack(const BoundTrackParameters& params, double linPointTime,
17  const Surface& perigeeSurface,
19  const Acts::MagneticFieldContext& mctx,
20  State& /*state*/) const {
21  // Create propagator options
22  propagator_options_t pOptions(gctx, mctx);
23 
24  // Length scale at which we consider to be sufficiently close to the Perigee
25  // surface to skip the propagation.
26  pOptions.targetTolerance = m_cfg.targetTolerance;
27 
28  // Get intersection of the track with the Perigee if the particle would
29  // move on a straight line.
30  // This allows us to determine whether we need to propagate the track
31  // forward or backward to arrive at the PCA.
32  auto intersection =
33  perigeeSurface
34  .intersect(gctx, params.position(gctx), params.direction(), false)
35  .closest();
36 
37  // Setting the propagation direction using the intersection length from
38  // above.
39  // We handle zero path length as forward propagation, but we could actually
40  // skip the whole propagation in this case.
41  pOptions.direction =
42  Direction::fromScalarZeroAsPositive(intersection.pathLength());
43 
44  // Propagate to the PCA of the reference point
45  auto result = m_cfg.propagator->propagate(params, perigeeSurface, pOptions);
46  if (not result.ok()) {
47  return result.error();
48  }
49 
50  // Extracting the Perigee representation of the track wrt the reference point
51  auto endParams = *result->endParameters;
52  BoundVector perigeeParams = endParams.parameters();
53 
54  // Covariance and weight matrix at the PCA to the reference point
55  BoundSquareMatrix parCovarianceAtPCA = endParams.covariance().value();
56  BoundSquareMatrix weightAtPCA = parCovarianceAtPCA.inverse();
57 
58  // Vector containing the track parameters at the PCA
59  // Note that we parametrize the track using the following parameters:
60  // (x, y, z, t, phi, theta, q/p),
61  // where
62  // -) (x, y, z, t) is the global 4D position of the PCA
63  // -) phi and theta are the global angles of the momentum at the PCA
64  // -) q/p is the charge divided by the total momentum at the PCA
66 
67  // 4D PCA and the momentum of the track at the PCA
68  // These quantities will be used in the computation of the constant term in
69  // the Taylor expansion
70  Vector4 pca;
71  Vector3 momentumAtPCA;
72 
73  // Fill "paramVec", "pca", and "momentumAtPCA"
74  {
75  Vector3 globalCoords = endParams.position(gctx);
76  ActsScalar globalTime = endParams.time();
77  ActsScalar phi = perigeeParams(BoundIndices::eBoundPhi);
79  ActsScalar qOvP = perigeeParams(BoundIndices::eBoundQOverP);
80 
81  paramVec << globalCoords, globalTime, phi, theta, qOvP;
82  pca << globalCoords, globalTime;
83  momentumAtPCA << phi, theta, qOvP;
84  }
85 
86  // Complete Jacobian (consists of positionJacobian and momentumJacobian)
87  ActsMatrix<eBoundSize, eLinSize> completeJacobian =
88  ActsMatrix<eBoundSize, eLinSize>::Zero(eBoundSize, eLinSize);
89 
90  // Perigee parameters wrt the reference point after wiggling
91  BoundVector newPerigeeParams;
92 
93  // Check if wiggled angle theta are within definition range [0, pi]
94  if (paramVec(eLinTheta) + m_cfg.delta > M_PI) {
95  ACTS_ERROR(
96  "Wiggled theta outside range, choose a smaller wiggle (i.e., delta)! "
97  "You might need to decrease targetTolerance as well.")
98  }
99 
100  // Wiggling each of the parameters at the PCA and computing the Perigee
101  // parametrization of the resulting new track. This allows us to approximate
102  // the numerical derivatives.
103  for (unsigned int i = 0; i < eLinSize; i++) {
104  Acts::ActsVector<eLinSize> paramVecCopy = paramVec;
105  // Wiggle
106  paramVecCopy(i) += m_cfg.delta;
107 
108  // Create curvilinear track object from our parameters. This is needed for
109  // the propagation. Note that we work without covariance since we don't need
110  // it to compute the derivative.
111  Vector3 wiggledDir = makeDirectionFromPhiTheta(paramVecCopy(eLinPhi),
112  paramVecCopy(eLinTheta));
113  // Since we work in 4D we have eLinPosSize = 4
114  CurvilinearTrackParameters wiggledCurvilinearParams(
115  paramVecCopy.template head<eLinPosSize>(), wiggledDir,
116  paramVecCopy(eLinQOverP), std::nullopt, ParticleHypothesis::pion());
117 
118  // Obtain propagation direction
119  intersection =
120  perigeeSurface
121  .intersect(gctx, paramVecCopy.template head<3>(), wiggledDir, false)
122  .closest();
123  pOptions.direction =
124  Direction::fromScalarZeroAsPositive(intersection.pathLength());
125 
126  // Propagate to the new PCA and extract Perigee parameters
127  auto newResult = m_cfg.propagator->propagate(wiggledCurvilinearParams,
128  perigeeSurface, pOptions);
129  if (not newResult.ok()) {
130  return newResult.error();
131  }
132  newPerigeeParams = (*newResult->endParameters).parameters();
133 
134  // Computing the numerical derivatives and filling the Jacobian
135  completeJacobian.array().col(i) =
136  (newPerigeeParams - perigeeParams) / m_cfg.delta;
137  // We need to account for the periodicity of phi. We overwrite the
138  // previously computed value for better readability.
139  completeJacobian(eLinPhi, i) =
140  Acts::detail::difference_periodic(newPerigeeParams(eLinPhi),
141  perigeeParams(eLinPhi), 2 * M_PI) /
142  m_cfg.delta;
143  }
144 
145  // Extracting positionJacobian and momentumJacobian from the complete Jacobian
146  ActsMatrix<eBoundSize, eLinPosSize> positionJacobian =
147  completeJacobian.block<eBoundSize, eLinPosSize>(0, 0);
148  ActsMatrix<eBoundSize, eLinMomSize> momentumJacobian =
149  completeJacobian.block<eBoundSize, eLinMomSize>(0, eLinPosSize);
150 
151  // Constant term of Taylor expansion (Eq. 5.38 in Ref. (1))
152  BoundVector constTerm =
153  perigeeParams - positionJacobian * pca - momentumJacobian * momentumAtPCA;
154 
155  Vector4 linPoint;
156  linPoint.head<3>() = perigeeSurface.center(gctx);
157  linPoint[3] = linPointTime;
158 
159  return LinearizedTrack(perigeeParams, parCovarianceAtPCA, weightAtPCA,
160  linPoint, positionJacobian, momentumJacobian, pca,
161  momentumAtPCA, constTerm);
162 }