Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
SpacePointUtility.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file SpacePointUtility.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2022 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 
16 
17 #include <algorithm>
18 #include <cmath>
19 #include <memory>
20 
21 namespace Acts {
22 
24  const Vector3& pos1, const Vector3& pos2, const Vector3& posVertex,
25  const double maxDistance, const double maxAngleTheta2,
26  const double maxAnglePhi2) const {
27  // Check if measurements are close enough to each other
28  if ((pos1 - pos2).norm() > maxDistance) {
30  }
31 
32  // Calculate the angles of the vectors
33  double phi1 = VectorHelpers::phi(pos1 - posVertex);
34  double theta1 = VectorHelpers::theta(pos1 - posVertex);
35  double phi2 = VectorHelpers::phi(pos2 - posVertex);
36  double theta2 = VectorHelpers::theta(pos2 - posVertex);
37  // Calculate the squared difference between the theta angles
38  double diffTheta2 = (theta1 - theta2) * (theta1 - theta2);
39  if (diffTheta2 > maxAngleTheta2) {
41  }
42  // Calculate the squared difference between the phi angles
43  double diffPhi2 = (phi1 - phi2) * (phi1 - phi2);
44  if (diffPhi2 > maxAnglePhi2) {
46  }
47  // Return the squared distance between both vector
48  return Result<double>::success(diffTheta2 + diffPhi2);
49 }
50 
51 std::pair<Vector3, Vector2> SpacePointUtility::globalCoords(
52  const GeometryContext& gctx, const SourceLink& slink,
53  const SourceLinkSurfaceAccessor& surfaceAccessor, const BoundVector& par,
54  const BoundSquareMatrix& cov) const {
55  const Surface* surface = surfaceAccessor(slink);
56  Vector2 localPos(par[eBoundLoc0], par[eBoundLoc1]);
57  SquareMatrix2 localCov = cov.block<2, 2>(eBoundLoc0, eBoundLoc0);
58  Vector3 globalPos = surface->localToGlobal(gctx, localPos, Vector3());
59  RotationMatrix3 rotLocalToGlobal =
60  surface->referenceFrame(gctx, globalPos, Vector3());
61 
62  // the space point requires only the variance of the transverse and
63  // longitudinal position. reduce computations by transforming the
64  // covariance directly from local to rho/z.
65  //
66  // compute Jacobian from global coordinates to rho/z
67  //
68  // rho = sqrt(x² + y²)
69  // drho/d{x,y} = (1 / sqrt(x² + y²)) * 2 * {x,y}
70  // = 2 * {x,y} / r
71  // dz/dz = 1
72  //
73  auto x = globalPos[ePos0];
74  auto y = globalPos[ePos1];
75  auto scale = 2 / std::hypot(x, y);
77  jacXyzToRhoZ(0, ePos0) = scale * x;
78  jacXyzToRhoZ(0, ePos1) = scale * y;
79  jacXyzToRhoZ(1, ePos2) = 1;
80  // compute Jacobian from local coordinates to rho/z
81  ActsMatrix<2, 2> jac =
82  jacXyzToRhoZ * rotLocalToGlobal.block<3, 2>(ePos0, ePos0);
83  // compute rho/z variance
84  ActsVector<2> var = (jac * localCov * jac.transpose()).diagonal();
85 
86  auto gcov = Vector2(var[0], var[1]);
87  return std::make_pair(globalPos, gcov);
88 }
89 
91  const GeometryContext& gctx, const SourceLink& slinkFront,
92  const SourceLink& slinkBack,
93  const SourceLinkSurfaceAccessor& surfaceAccessor,
94  const std::function<std::pair<const BoundVector, const BoundSquareMatrix>(
95  SourceLink)>& paramCovAccessor,
96  const Vector3& globalPos, const double theta) const {
97  const auto var1 = paramCovAccessor(slinkFront).second(0, 0);
98  const auto var2 = paramCovAccessor(slinkBack).second(0, 0);
99 
100  // strip1 and strip2 are tilted at +/- theta/2
101  double sigma_x = std::hypot(var1, var2) / (2 * sin(theta * 0.5));
102  double sigma_y = std::hypot(var1, var2) / (2 * cos(theta * 0.5));
103 
104  // projection to the surface with strip1.
105  double sig_x1 = sigma_x * cos(0.5 * theta) + sigma_y * sin(0.5 * theta);
106  double sig_y1 = sigma_y * cos(0.5 * theta) + sigma_x * sin(0.5 * theta);
107  SquareMatrix2 lcov;
108  lcov << sig_x1, 0, 0, sig_y1;
109 
110  const Surface& surface = *surfaceAccessor(slinkFront);
111 
112  auto gcov = rhoZCovariance(gctx, surface, globalPos, lcov);
113  return gcov;
114 }
115 
117  const Surface& surface,
118  const Vector3& globalPos,
119  const SquareMatrix2& localCov) const {
120  Vector3 globalFakeMom(1, 1, 1);
121 
122  RotationMatrix3 rotLocalToGlobal =
123  surface.referenceFrame(gctx, globalPos, globalFakeMom);
124 
125  auto x = globalPos[ePos0];
126  auto y = globalPos[ePos1];
127  auto scale = 2 / std::hypot(x, y);
128  ActsMatrix<2, 3> jacXyzToRhoZ = ActsMatrix<2, 3>::Zero();
129  jacXyzToRhoZ(0, ePos0) = scale * x;
130  jacXyzToRhoZ(0, ePos1) = scale * y;
131  jacXyzToRhoZ(1, ePos2) = 1;
132  // compute Jacobian from local coordinates to rho/z
133  ActsMatrix<2, 2> jac =
134  jacXyzToRhoZ * rotLocalToGlobal.block<3, 2>(ePos0, ePos0);
135  // compute rho/z variance
136  ActsVector<2> var = (jac * localCov * jac.transpose()).diagonal();
137 
138  auto gcov = Vector2(var[0], var[1]);
139 
140  return gcov;
141 }
142 
144  const std::pair<Vector3, Vector3>& stripEnds1,
145  const std::pair<Vector3, Vector3>& stripEnds2, const Vector3& posVertex,
146  SpacePointParameters& spParams, const double stripLengthTolerance) const {
167 
168  spParams.firstBtmToTop = stripEnds1.first - stripEnds1.second;
169  spParams.secondBtmToTop = stripEnds2.first - stripEnds2.second;
170  spParams.vtxToFirstMid2 =
171  stripEnds1.first + stripEnds1.second - 2 * posVertex;
172  spParams.vtxToSecondMid2 =
173  stripEnds2.first + stripEnds2.second - 2 * posVertex;
175  spParams.firstBtmToTop.cross(spParams.vtxToFirstMid2);
177  spParams.secondBtmToTop.cross(spParams.vtxToSecondMid2);
178  spParams.m =
179  -spParams.vtxToFirstMid2.dot(spParams.secondBtmToTopXvtxToSecondMid2) /
180  spParams.firstBtmToTop.dot(spParams.secondBtmToTopXvtxToSecondMid2);
181  spParams.n =
182  -spParams.vtxToSecondMid2.dot(spParams.firstBtmToTopXvtxToFirstMid2) /
183  spParams.secondBtmToTop.dot(spParams.firstBtmToTopXvtxToFirstMid2);
184 
185  // Set the limit for the parameter
186  if (spParams.limit == 1. && stripLengthTolerance != 0.) {
187  spParams.limit = 1. + stripLengthTolerance;
188  }
189 
190  // Check if m and n can be resolved in the interval (-1, 1)
191  if (fabs(spParams.m) <= spParams.limit &&
192  fabs(spParams.n) <= spParams.limit) {
193  return Result<void>::success();
194  }
196 }
197 
199  SpacePointParameters& spParams, double stripLengthGapTolerance) const {
200  // Consider some cases that would allow an easy exit
201  // Check if the limits are allowed to be increased
202  if (stripLengthGapTolerance <= 0.) {
204  }
205 
206  spParams.mag_firstBtmToTop = spParams.firstBtmToTop.norm();
207  // Increase the limits. This allows a check if the point is just slightly
208  // outside the SDE
209  spParams.limitExtended =
210  spParams.limit + stripLengthGapTolerance / spParams.mag_firstBtmToTop;
211 
212  // Check if m is just slightly outside
213  if (fabs(spParams.m) > spParams.limitExtended) {
215  }
216  // Calculate n if not performed previously
217  if (spParams.n == 0.) {
218  spParams.n =
219  -spParams.vtxToSecondMid2.dot(spParams.firstBtmToTopXvtxToFirstMid2) /
220  spParams.secondBtmToTop.dot(spParams.firstBtmToTopXvtxToFirstMid2);
221  }
222  // Check if n is just slightly outside
223  if (fabs(spParams.n) > spParams.limitExtended) {
225  }
243 
244  // Calculate the scaling factor to project lengths of the second SDE on the
245  // first SDE
246  double secOnFirstScale =
247  spParams.firstBtmToTop.dot(spParams.secondBtmToTop) /
248  (spParams.mag_firstBtmToTop * spParams.mag_firstBtmToTop);
249  // Check if both overshoots are in the same direction
250  if (spParams.m > 1. && spParams.n > 1.) {
251  // Calculate the overshoots
252  double mOvershoot = spParams.m - 1.;
253  double nOvershoot =
254  (spParams.n - 1.) * secOnFirstScale; // Perform projection
255  // Resolve worse overshoot
256  double biggerOvershoot = std::max(mOvershoot, nOvershoot);
257  // Move m and n towards 0
258  spParams.m -= biggerOvershoot;
259  spParams.n -= (biggerOvershoot / secOnFirstScale);
260  // Check if this recovered the space point
261 
262  if (fabs(spParams.m) < spParams.limit &&
263  fabs(spParams.n) < spParams.limit) {
264  return Result<void>::success();
265  } else {
267  }
268  }
269  // Check if both overshoots are in the same direction
270  if (spParams.m < -1. && spParams.n < -1.) {
271  // Calculate the overshoots
272  double mOvershoot = -(spParams.m + 1.);
273  double nOvershoot =
274  -(spParams.n + 1.) * secOnFirstScale; // Perform projection
275  // Resolve worse overshoot
276  double biggerOvershoot = std::max(mOvershoot, nOvershoot);
277  // Move m and n towards 0
278  spParams.m += biggerOvershoot;
279  spParams.n += (biggerOvershoot / secOnFirstScale);
280  // Check if this recovered the space point
281  if (fabs(spParams.m) < spParams.limit &&
282  fabs(spParams.n) < spParams.limit) {
283  return Result<void>::success();
284  }
285  }
286  // No solution could be found
288 }
289 
291  const std::pair<Vector3, Vector3>& stripEnds1,
292  const std::pair<Vector3, Vector3>& stripEnds2,
293  SpacePointParameters& spParams) const {
304 
305  spParams.firstBtmToTop = stripEnds1.first - stripEnds1.second;
306  spParams.secondBtmToTop = stripEnds2.first - stripEnds2.second;
307 
308  Vector3 ac = stripEnds2.first - stripEnds1.first;
309  double qr = (spParams.firstBtmToTop).dot(spParams.secondBtmToTop);
310  double denom = spParams.firstBtmToTop.dot(spParams.firstBtmToTop) - qr * qr;
311  // Check for numerical stability
312  if (fabs(denom) > 1e-6) {
313  // Return lambda0
315  (ac.dot(spParams.secondBtmToTop) * qr -
316  ac.dot(spParams.firstBtmToTop) *
317  (spParams.secondBtmToTop).dot(spParams.secondBtmToTop)) /
318  denom);
319  }
321 }
322 
323 } // namespace Acts