EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DiscSurface.ipp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file DiscSurface.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 
9 inline Vector2D DiscSurface::localPolarToCartesian(
10  const Vector2D& lpolar) const {
11  return Vector2D(lpolar[eBoundLoc0] * cos(lpolar[eBoundLoc1]),
12  lpolar[eBoundLoc0] * sin(lpolar[eBoundLoc1]));
13 }
14 
15 inline Vector2D DiscSurface::localCartesianToPolar(
16  const Vector2D& lcart) const {
17  return Vector2D(sqrt(lcart[eBoundLoc0] * lcart[eBoundLoc0] +
18  lcart[eBoundLoc1] * lcart[eBoundLoc1]),
19  atan2(lcart[eBoundLoc1], lcart[eBoundLoc0]));
20 }
21 
22 inline void DiscSurface::initJacobianToGlobal(const GeometryContext& gctx,
23  BoundToFreeMatrix& jacobian,
24  const Vector3D& position,
25  const Vector3D& direction,
26  const BoundVector& pars) const {
27  // The trigonometry required to convert the direction to spherical
28  // coordinates and then compute the sines and cosines again can be
29  // surprisingly expensive from a performance point of view.
30  //
31  // Here, we can avoid it because the direction is by definition a unit
32  // vector, with the following coordinate conversions...
33  const double x = direction(0); // == cos(phi) * sin(theta)
34  const double y = direction(1); // == sin(phi) * sin(theta)
35  const double z = direction(2); // == cos(theta)
36 
37  // ...which we can invert to directly get the sines and cosines:
38  const double cos_theta = z;
39  const double sin_theta = sqrt(x * x + y * y);
40  const double inv_sin_theta = 1. / sin_theta;
41  const double cos_phi = x * inv_sin_theta;
42  const double sin_phi = y * inv_sin_theta;
43  // retrieve the reference frame
44  const auto rframe = referenceFrame(gctx, position, direction);
45 
46  // special polar coordinates for the Disc
47  double lrad = pars[eBoundLoc0];
48  double lphi = pars[eBoundLoc1];
49  double lcos_phi = cos(lphi);
50  double lsin_phi = sin(lphi);
51  // the local error components - rotated from reference frame
52  jacobian.block<3, 1>(0, eBoundLoc0) =
53  lcos_phi * rframe.block<3, 1>(0, 0) + lsin_phi * rframe.block<3, 1>(0, 1);
54  jacobian.block<3, 1>(0, eBoundLoc1) =
55  lrad * (lcos_phi * rframe.block<3, 1>(0, 1) -
56  lsin_phi * rframe.block<3, 1>(0, 0));
57  // the time component
58  jacobian(3, eBoundTime) = 1;
59  // the momentum components
60  jacobian(4, eBoundPhi) = (-sin_theta) * sin_phi;
61  jacobian(4, eBoundTheta) = cos_theta * cos_phi;
62  jacobian(5, eBoundPhi) = sin_theta * cos_phi;
63  jacobian(5, eBoundTheta) = cos_theta * sin_phi;
64  jacobian(6, eBoundTheta) = (-sin_theta);
65  jacobian(7, eBoundQOverP) = 1;
66 }
67 
68 inline RotationMatrix3D DiscSurface::initJacobianToLocal(
69  const GeometryContext& gctx, FreeToBoundMatrix& jacobian,
70  const Vector3D& position, const Vector3D& direction) const {
71  using VectorHelpers::perp;
72  using VectorHelpers::phi;
73  // Optimized trigonometry on the propagation direction
74  const double x = direction(0); // == cos(phi) * sin(theta)
75  const double y = direction(1); // == sin(phi) * sin(theta)
76  const double z = direction(2); // == cos(theta)
77  // can be turned into cosine/sine
78  const double cosTheta = z;
79  const double sinTheta = sqrt(x * x + y * y);
80  const double invSinTheta = 1. / sinTheta;
81  const double cosPhi = x * invSinTheta;
82  const double sinPhi = y * invSinTheta;
83  // The measurement frame of the surface
84  RotationMatrix3D rframeT =
85  referenceFrame(gctx, position, direction).transpose();
86  // calculate the transformation to local coorinates
87  const Vector3D pos_loc = transform(gctx).inverse() * position;
88  const double lr = perp(pos_loc);
89  const double lphi = phi(pos_loc);
90  const double lcphi = cos(lphi);
91  const double lsphi = sin(lphi);
92  // rotate into the polar coorindates
93  auto lx = rframeT.block<1, 3>(0, 0);
94  auto ly = rframeT.block<1, 3>(1, 0);
95  jacobian.block<1, 3>(0, 0) = lcphi * lx + lsphi * ly;
96  jacobian.block<1, 3>(1, 0) = (lcphi * ly - lsphi * lx) / lr;
97  // Time element
98  jacobian(eBoundTime, 3) = 1;
99  // Directional and momentum elements for reference frame surface
100  jacobian(eBoundPhi, 4) = -sinPhi * invSinTheta;
101  jacobian(eBoundPhi, 5) = cosPhi * invSinTheta;
102  jacobian(eBoundTheta, 4) = cosPhi * cosTheta;
103  jacobian(eBoundTheta, 5) = sinPhi * cosTheta;
104  jacobian(eBoundTheta, 6) = -sinTheta;
105  jacobian(eBoundQOverP, 7) = 1;
106  // return the transposed reference frame
107  return rframeT;
108 }
109 
111  const GeometryContext& gctx, const Vector3D& position,
112  const Vector3D& direction, const BoundaryCheck& bcheck) const {
113  // Get the contextual transform
114  auto gctxTransform = transform(gctx);
115  // Use the intersection helper for planar surfaces
116  auto intersection =
117  PlanarHelper::intersect(gctxTransform, position, direction);
118  // Evaluate boundary check if requested (and reachable)
119  if (intersection.status != Intersection3D::Status::unreachable and bcheck and
120  m_bounds != nullptr) {
121  // Built-in local to global for speed reasons
122  const auto& tMatrix = gctxTransform.matrix();
123  const Vector3D vecLocal(intersection.position - tMatrix.block<3, 1>(0, 3));
124  const Vector2D lcartesian =
125  tMatrix.block<3, 2>(0, 0).transpose() * vecLocal;
126  if (bcheck.type() == BoundaryCheck::Type::eAbsolute and
127  m_bounds->coversFullAzimuth()) {
128  double tolerance = s_onSurfaceTolerance + bcheck.tolerance()[eBoundLoc0];
129  if (not m_bounds->insideRadialBounds(VectorHelpers::perp(lcartesian),
130  tolerance)) {
131  intersection.status = Intersection3D::Status::missed;
132  }
133  } else if (not insideBounds(localCartesianToPolar(lcartesian), bcheck)) {
134  intersection.status = Intersection3D::Status::missed;
135  }
136  }
137  return {intersection, this};
138 }
139 
141 DiscSurface::localCartesianToBoundLocalDerivative(
142  const GeometryContext& gctx, const Vector3D& position) const {
143  using VectorHelpers::perp;
144  using VectorHelpers::phi;
145  // The local frame transform
146  const auto& sTransform = transform(gctx);
147  // calculate the transformation to local coorinates
148  const Vector3D localPos = sTransform.inverse() * position;
149  const double lr = perp(localPos);
150  const double lphi = phi(localPos);
151  const double lcphi = std::cos(lphi);
152  const double lsphi = std::sin(lphi);
153  LocalCartesianToBoundLocalMatrix loc3DToLocBound =
154  LocalCartesianToBoundLocalMatrix::Zero();
155  loc3DToLocBound << lcphi, lsphi, 0, -lsphi / lr, lcphi / lr, 0;
156 
157  return loc3DToLocBound;
158 }
159 
160 inline Vector3D DiscSurface::normal(const GeometryContext& gctx,
161  const Vector2D& /*unused*/) const {
162  // fast access via tranform matrix (and not rotation())
163  const auto& tMatrix = transform(gctx).matrix();
164  return Vector3D(tMatrix(0, 2), tMatrix(1, 2), tMatrix(2, 2));
165 }
166 
167 inline Vector3D DiscSurface::binningPosition(const GeometryContext& gctx,
168  BinningValue bValue) const {
169  if (bValue == binR) {
170  double r = m_bounds->binningValueR();
171  double phi = m_bounds->binningValuePhi();
172  return Vector3D(r * cos(phi), r * sin(phi), center(gctx).z());
173  }
174  return center(gctx);
175 }
176 
177 inline double DiscSurface::binningPositionValue(const GeometryContext& gctx,
178  BinningValue bValue) const {
179  // only modify binR
180  if (bValue == binR) {
181  return VectorHelpers::perp(center(gctx)) + m_bounds->binningValueR();
182  }
183  return GeometryObject::binningPositionValue(gctx, bValue);
184 }
185 
186 inline double DiscSurface::pathCorrection(const GeometryContext& gctx,
187  const Vector3D& position,
188  const Vector3D& direction) const {
190  return 1. / std::abs(Surface::normal(gctx, position).dot(direction));
191 }