ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LineSurface.ipp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file LineSurface.ipp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2018 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 
10 // LineSurface.ipp, Acts project
12 
13 inline void LineSurface::localToGlobal(const GeometryContext& gctx,
14  const Vector2D& lposition,
15  const Vector3D& momentum,
16  Vector3D& position) const {
17  const auto& sTransform = transform(gctx);
18  const auto& tMatrix = sTransform.matrix();
19  Vector3D lineDirection(tMatrix(0, 2), tMatrix(1, 2), tMatrix(2, 2));
20 
21  // get the vector perpendicular to the momentum and the straw axis
22  Vector3D radiusAxisGlobal(lineDirection.cross(momentum));
23  Vector3D locZinGlobal = sTransform * Vector3D(0., 0., lposition[eLOC_Z]);
24  // add eLOC_R * radiusAxis
25  position = Vector3D(locZinGlobal +
26  lposition[eLOC_R] * radiusAxisGlobal.normalized());
27 }
28 
29 inline bool LineSurface::globalToLocal(const GeometryContext& gctx,
30  const Vector3D& position,
31  const Vector3D& momentum,
32  Vector2D& lposition) const {
33  using VectorHelpers::perp;
34 
35  const auto& sTransform = transform(gctx);
36  const auto& tMatrix = sTransform.matrix();
37  Vector3D lineDirection(tMatrix(0, 2), tMatrix(1, 2), tMatrix(2, 2));
38  // Bring the global position into the local frame
39  Vector3D loc3Dframe = sTransform.inverse() * position;
40  // construct localPosition with sign*perp(candidate) and z.()
41  lposition = Vector2D(perp(loc3Dframe), loc3Dframe.z());
42  Vector3D sCenter(tMatrix(0, 3), tMatrix(1, 3), tMatrix(2, 3));
43  Vector3D decVec(position - sCenter);
44  // assign the right sign
45  double sign = ((lineDirection.cross(momentum)).dot(decVec) < 0.) ? -1. : 1.;
46  lposition[eLOC_R] *= sign;
47  return true;
48 }
49 
50 inline std::string LineSurface::name() const {
51  return "Acts::LineSurface";
52 }
53 
54 inline const RotationMatrix3D LineSurface::referenceFrame(
55  const GeometryContext& gctx, const Vector3D& /*unused*/,
56  const Vector3D& momentum) const {
57  RotationMatrix3D mFrame;
58  const auto& tMatrix = transform(gctx).matrix();
59  Vector3D measY(tMatrix(0, 2), tMatrix(1, 2), tMatrix(2, 2));
60  Vector3D measX(measY.cross(momentum).normalized());
61  Vector3D measDepth(measX.cross(measY));
62  // assign the columnes
63  mFrame.col(0) = measX;
64  mFrame.col(1) = measY;
65  mFrame.col(2) = measDepth;
66  // return the rotation matrix
67  return mFrame;
68 }
69 
70 inline double LineSurface::pathCorrection(const GeometryContext& /*unused*/,
71  const Vector3D& /*pos*/,
72  const Vector3D& /*mom*/) const {
73  return 1.;
74 }
75 
76 inline const Vector3D LineSurface::binningPosition(
77  const GeometryContext& gctx, BinningValue /*bValue*/) const {
78  return center(gctx);
79 }
80 
82  const Vector2D& /*lpos*/) const {
83  const auto& tMatrix = transform(gctx).matrix();
84  return Vector3D(tMatrix(0, 2), tMatrix(1, 2), tMatrix(2, 2));
85 }
86 
87 inline const SurfaceBounds& LineSurface::bounds() const {
88  if (m_bounds) {
89  return (*m_bounds.get());
90  }
91  return s_noBounds;
92 }
93 
95  const GeometryContext& gctx, const Vector3D& position,
96  const Vector3D& direction, const BoundaryCheck& bcheck) const {
97  // following nominclature found in header file and doxygen documentation
98  // line one is the straight track
99  const Vector3D& ma = position;
100  const Vector3D& ea = direction;
101  // line two is the line surface
102  const auto& tMatrix = transform(gctx).matrix();
103  Vector3D mb = tMatrix.block<3, 1>(0, 3).transpose();
104  Vector3D eb = tMatrix.block<3, 1>(0, 2).transpose();
105  // now go ahead and solve for the closest approach
106  Vector3D mab(mb - ma);
107  double eaTeb = ea.dot(eb);
108  double denom = 1 - eaTeb * eaTeb;
109  // validity parameter
110  Intersection::Status status = Intersection::Status::unreachable;
111  if (denom * denom > s_onSurfaceTolerance * s_onSurfaceTolerance) {
112  double u = (mab.dot(ea) - mab.dot(eb) * eaTeb) / denom;
113  // Check if we are on the surface already
114  status = (u * u < s_onSurfaceTolerance * s_onSurfaceTolerance)
115  ? Intersection::Status::onSurface
116  : Intersection::Status::reachable;
117  Vector3D result = (ma + u * ea);
118  // Evaluate the boundary check if requested
119  // m_bounds == nullptr prevents unecessary calulations for PerigeeSurface
120  if (bcheck and m_bounds) {
121  // At closest approach: check inside R or and inside Z
122  const Vector3D vecLocal(result - mb);
123  double cZ = vecLocal.dot(eb);
124  double hZ =
125  m_bounds->get(LineBounds::eHalfLengthZ) + s_onSurfaceTolerance;
126  if ((cZ * cZ > hZ * hZ) or
127  ((vecLocal - cZ * eb).norm() >
128  m_bounds->get(LineBounds::eR) + s_onSurfaceTolerance)) {
129  status = Intersection::Status::missed;
130  }
131  }
132  return Intersection(result, u, status);
133  }
134  // return a false intersection
135  return Intersection(position, std::numeric_limits<double>::max(), status);
136 }
137 
138 inline void LineSurface::initJacobianToGlobal(const GeometryContext& gctx,
139  BoundToFreeMatrix& jacobian,
140  const Vector3D& position,
141  const Vector3D& direction,
142  const BoundVector& pars) const {
143  // The trigonometry required to convert the direction to spherical
144  // coordinates and then compute the sines and cosines again can be
145  // surprisingly expensive from a performance point of view.
146  //
147  // Here, we can avoid it because the direction is by definition a unit
148  // vector, with the following coordinate conversions...
149  const double x = direction(0); // == cos(phi) * sin(theta)
150  const double y = direction(1); // == sin(phi) * sin(theta)
151  const double z = direction(2); // == cos(theta)
152 
153  // ...which we can invert to directly get the sines and cosines:
154  const double cos_theta = z;
155  const double sin_theta = sqrt(x * x + y * y);
156  const double inv_sin_theta = 1. / sin_theta;
157  const double cos_phi = x * inv_sin_theta;
158  const double sin_phi = y * inv_sin_theta;
159  // retrieve the reference frame
160  const auto rframe = referenceFrame(gctx, position, direction);
161  // the local error components - given by the reference frame
162  jacobian.topLeftCorner<3, 2>() = rframe.topLeftCorner<3, 2>();
163  // the time component
164  jacobian(3, eT) = 1;
165  // the momentum components
166  jacobian(4, ePHI) = (-sin_theta) * sin_phi;
167  jacobian(4, eTHETA) = cos_theta * cos_phi;
168  jacobian(5, ePHI) = sin_theta * cos_phi;
169  jacobian(5, eTHETA) = cos_theta * sin_phi;
170  jacobian(6, eTHETA) = (-sin_theta);
171  jacobian(7, eQOP) = 1;
172 
173  // the projection of direction onto ref frame normal
174  double ipdn = 1. / direction.dot(rframe.col(2));
175  // build the cross product of d(D)/d(ePHI) components with y axis
176  auto dDPhiY = rframe.block<3, 1>(0, 1).cross(jacobian.block<3, 1>(4, ePHI));
177  // and the same for the d(D)/d(eTheta) components
178  auto dDThetaY =
179  rframe.block<3, 1>(0, 1).cross(jacobian.block<3, 1>(4, eTHETA));
180  // and correct for the x axis components
181  dDPhiY -= rframe.block<3, 1>(0, 0) * (rframe.block<3, 1>(0, 0).dot(dDPhiY));
182  dDThetaY -=
183  rframe.block<3, 1>(0, 0) * (rframe.block<3, 1>(0, 0).dot(dDThetaY));
184  // set the jacobian components for global d/ phi/Theta
185  jacobian.block<3, 1>(0, ePHI) = dDPhiY * pars[eLOC_0] * ipdn;
186  jacobian.block<3, 1>(0, eTHETA) = dDThetaY * pars[eLOC_0] * ipdn;
187 }
188 
189 inline const BoundRowVector LineSurface::derivativeFactors(
190  const GeometryContext& gctx, const Vector3D& position,
191  const Vector3D& direction, const RotationMatrix3D& rft,
192  const BoundToFreeMatrix& jacobian) const {
193  // the vector between position and center
194  ActsRowVectorD<3> pc = (position - center(gctx)).transpose();
195  // the longitudinal component vector (alogn local z)
196  ActsRowVectorD<3> locz = rft.block<1, 3>(1, 0);
197  // build the norm vector comonent by subtracting the longitudinal one
198  double long_c = locz * direction;
199  ActsRowVectorD<3> norm_vec = direction.transpose() - long_c * locz;
200  // calculate the s factors for the dependency on X
201  const BoundRowVector s_vec =
202  norm_vec * jacobian.topLeftCorner<3, eBoundParametersSize>();
203  // calculate the d factors for the dependency on Tx
204  const BoundRowVector d_vec =
205  locz * jacobian.block<3, eBoundParametersSize>(4, 0);
206  // normalisation of normal & longitudinal components
207  double norm = 1. / (1. - long_c * long_c);
208  // create a matrix representation
211  long_mat.colwise() += locz.transpose();
212  // build the combined normal & longitudinal components
213  return (norm *
214  (s_vec - pc * (long_mat * d_vec.asDiagonal() -
215  jacobian.block<3, eBoundParametersSize>(4, 0))));
216 }