Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
LineSurfaceTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file LineSurfaceTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2017-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 #include <boost/test/data/test_case.hpp>
10 #include <boost/test/tools/old/interface.hpp>
11 #include <boost/test/tools/output_test_stream.hpp>
12 #include <boost/test/unit_test.hpp>
13 
36 
37 #include <algorithm>
38 #include <cmath>
39 #include <memory>
40 #include <optional>
41 #include <ostream>
42 #include <stdexcept>
43 #include <string>
44 #include <tuple>
45 #include <vector>
46 
47 namespace utf = boost::unit_test;
48 
49 namespace Acts {
50 class AssertionFailureException;
51 
52 namespace Test {
53 
54 // Create a test context
56 
57 // using boost::test_tools::output_test_stream;
58 
59 BOOST_AUTO_TEST_SUITE(Surfaces)
60 
61 
62 BOOST_AUTO_TEST_CASE(LineSurface_Constructors_test) {
63  // Default ctor is deleted
64  // LineSurfaceStub l;
65  // ctor with translation, radius, halfz
66  Translation3 translation{0., 1., 2.};
68  auto pTransform = Transform3(translation);
69  const double radius{2.0}, halfz{20.};
70  BOOST_CHECK(LineSurfaceStub(pTransform, radius, halfz).constructedOk());
71  // ctor with nullptr for LineBounds
72  BOOST_CHECK(LineSurfaceStub(pTransform).constructedOk());
73  // ctor with LineBounds
74  auto pLineBounds = std::make_shared<const LineBounds>(2., 10.0);
75  BOOST_CHECK(LineSurfaceStub(pTransform, pLineBounds).constructedOk());
76  // ctor with LineBounds, detector element, Identifier
77  auto pMaterial =
78  std::make_shared<const HomogeneousSurfaceMaterial>(makePercentSlab());
79  DetectorElementStub detElement{pTransform, pLineBounds, 0.2, pMaterial};
80  BOOST_CHECK(LineSurfaceStub(pLineBounds, detElement).constructedOk());
81  LineSurfaceStub lineToCopy(pTransform, 2.0, 20.);
82  // Copy ctor
83  BOOST_CHECK(LineSurfaceStub(lineToCopy).constructedOk());
84  // Copied and transformed ctor
85  BOOST_CHECK(
86  LineSurfaceStub(tgContext, lineToCopy, transform).constructedOk());
87 
89  DetectorElementStub detElem;
90  BOOST_CHECK_THROW(LineSurfaceStub nullBounds(nullptr, detElem),
92 
93  BOOST_TEST_MESSAGE(
94  "All LineSurface constructors are callable without problem");
95 }
96 
98 BOOST_AUTO_TEST_CASE(LineSurface_allNamedMethods_test) {
99  // binningPosition()
100  Translation3 translation{0., 1., 2.};
102  LineSurfaceStub line(transform, 2.0, 20.);
103  Vector3 referencePosition{0., 1., 2.};
104  CHECK_CLOSE_ABS(referencePosition, line.binningPosition(tgContext, binX),
105  1e-6);
106  //
107  // bounds()
108  auto pLineBounds = std::make_shared<const LineBounds>(2., 10.0);
109  LineSurfaceStub boundedLine(transform, pLineBounds);
110  const LineBounds& bounds =
111  dynamic_cast<const LineBounds&>(boundedLine.bounds());
112  BOOST_CHECK_EQUAL(bounds, LineBounds(2., 10.0));
113  //
114  // globalToLocal()
115  Vector3 gpos{0., 1., 0.};
116  const Vector3 mom{20., 0., 0.}; // needs more realistic parameters
117  Vector2 localPosition =
118  line.globalToLocal(tgContext, gpos, mom.normalized()).value();
119  const Vector2 expectedResult{0, -2};
120  CHECK_CLOSE_ABS(expectedResult, localPosition, 1e-6);
121  //
122  // intersection
123  const Vector3 direction{0., 1., 2.};
124  BoundaryCheck bcheck(false);
125  auto sfIntersection =
126  line.intersect(tgContext, {0., 0., 0.}, direction.normalized(), bcheck)
127  .closest();
128  BOOST_CHECK(sfIntersection);
129  Vector3 expectedIntersection(0, 1., 2.);
130  CHECK_CLOSE_ABS(sfIntersection.position(), expectedIntersection,
131  1e-6); // need more tests..
132  BOOST_CHECK_EQUAL(sfIntersection.object(), &line);
133  //
134  // isOnSurface
135  const Vector3 insidePosition{0., 2.5, 0.};
136  BOOST_CHECK(line.isOnSurface(tgContext, insidePosition, mom,
137  false)); // need better test here
138  const Vector3 outsidePosition{100., 100., 200.};
139  BOOST_CHECK(!line.isOnSurface(tgContext, outsidePosition, mom, true));
140  //
141  // localToGlobal
142  Vector3 returnedGlobalPosition{0., 0., 0.};
143  // Vector2 localPosition{0., 0.};
144  const Vector3 momentum{300., 200., 0.}; // find better values!
145  returnedGlobalPosition =
146  line.localToGlobal(tgContext, localPosition, momentum.normalized());
147  const Vector3 expectedGlobalPosition{0, 1, 0};
148  CHECK_CLOSE_ABS(returnedGlobalPosition, expectedGlobalPosition, 1e-6);
149  //
150  // referenceFrame
151  Vector3 globalPosition{0., 0., 0.};
152  auto returnedRotationMatrix =
153  line.referenceFrame(tgContext, globalPosition, momentum.normalized());
154  double v0 = std::cos(std::atan(2. / 3.));
155  double v1 = std::sin(std::atan(2. / 3.));
156  RotationMatrix3 expectedRotationMatrix;
157  expectedRotationMatrix << -v1, 0., v0, v0, 0., v1, 0., 1., -0.;
158  // std::cout<<returnedRotationMatrix<<std::endl;
159  // std::cout<<expectedRotationMatrix<<std::endl;
160  CHECK_CLOSE_OR_SMALL(returnedRotationMatrix, expectedRotationMatrix, 1e-6,
161  1e-9);
162  //
163  // name()
164  boost::test_tools::output_test_stream output;
165  output << line.name();
166  BOOST_CHECK(output.is_equal("Acts::LineSurface"));
167  //
168  // normal does not exist without known momentum direction for line surface
169  BOOST_CHECK_THROW(line.normal(tgContext), std::runtime_error);
170  //
171  // pathCorrection is always 1 for the line surface
173  line.pathCorrection(tgContext, Vector3::Zero(), Vector3::UnitX()), 1,
174  1e-6);
175 }
176 
178 BOOST_AUTO_TEST_CASE(LineSurface_assignment_test) {
179  Translation3 translation{0., 1., 2.};
181  LineSurfaceStub originalLine(transform, 2.0, 20.);
182  LineSurfaceStub assignedLine(transform, 1.0, 1.0);
183  BOOST_CHECK(assignedLine != originalLine); // operator != from base
184  assignedLine = originalLine;
185  BOOST_CHECK(assignedLine == originalLine); // operator == from base
186 }
187 
189 BOOST_AUTO_TEST_CASE(LineSurfaceAlignment) {
190  Translation3 translation{0., 1., 2.};
192  LineSurfaceStub line(transform, 2.0, 20.);
193 
194  const auto& rotation = transform.rotation();
195  // The local frame z axis
196  const Vector3 localZAxis = rotation.col(2);
197  // Check the local z axis is aligned to global z axis
198  CHECK_CLOSE_ABS(localZAxis, Vector3(0., 0., 1.), 1e-15);
199 
200  // Define the track (global) position and direction
201  Vector3 globalPosition{1, 2, 4};
202  Vector3 momentum{-1, 1, 1};
203  Vector3 direction = momentum.normalized();
204  // Construct a free parameters
205  FreeVector parameters = FreeVector::Zero();
206  parameters.head<3>() = globalPosition;
207  parameters.segment<3>(eFreeDir0) = direction;
208 
209  // (a) Test the derivative of path length w.r.t. alignment parameters
210  const AlignmentToPathMatrix& alignToPath =
211  line.alignmentToPathDerivative(tgContext, parameters);
212  // The expected results
213  AlignmentToPathMatrix expAlignToPath = AlignmentToPathMatrix::Zero();
214  const double value = std::sqrt(3) / 2;
215  expAlignToPath << -value, value, 0, -3 * value, -value, 0;
216  // Check if the calculated derivative is as expected
217  CHECK_CLOSE_ABS(alignToPath, expAlignToPath, 1e-10);
218 
219  // (b) Test the derivative of bound track parameters local position w.r.t.
220  // position in local 3D Cartesian coordinates
221  const auto& loc3DToLocBound =
222  line.localCartesianToBoundLocalDerivative(tgContext, globalPosition);
223  // Check if the result is as expected
224  ActsMatrix<2, 3> expLoc3DToLocBound = ActsMatrix<2, 3>::Zero();
225  expLoc3DToLocBound << 1 / std::sqrt(2), 1 / std::sqrt(2), 0, 0, 0, 1;
226  CHECK_CLOSE_ABS(loc3DToLocBound, expLoc3DToLocBound, 1e-10);
227 }
228 
229 BOOST_AUTO_TEST_CASE(LineSurfaceTransformRoundTrip) {
230  LineSurfaceStub surface(Transform3::Identity());
231 
232  auto roundTrip = [&surface](const Vector3& pos, const Vector3& dir) {
233  auto intersection = surface.intersect(tgContext, pos, dir).closest();
234  Vector3 global = intersection.position();
235  Vector2 local = *surface.globalToLocal(tgContext, global, dir);
236  Vector3 global2 = surface.localToGlobal(tgContext, local, dir);
237  return std::make_tuple(global, local, global2);
238  };
239 
240  {
241  Vector3 pos = {-0.02801, 0.00475611, 0.285106};
242  Vector3 dir = Vector3(-0.03951, -0.221457, -0.564298).normalized();
243 
244  auto [global, local, global2] = roundTrip(pos, dir);
245 
246  CHECK_CLOSE_ABS(global, global2, 1e-10);
247  }
248 
249  {
250  Vector3 pos = {-64.2892, 65.2697, -0.839014};
251  Vector3 dir = Vector3(-0.236602, -0.157616, 0.956786).normalized();
252 
253  auto [global, local, global2] = roundTrip(pos, dir);
254 
255  CHECK_CLOSE_ABS(global, global2, 1e-10);
256  }
257 }
258 
259 BOOST_AUTO_TEST_CASE(LineSurfaceTransformRoundTripEtaStability) {
260  LineSurfaceStub surface(Transform3::Identity());
261 
262  // eta=6 is already crashing
263  const std::vector<double> etas = {0, 1, 2, 3, 4, 5};
264 
265  for (double eta : etas) {
266  Vector3 pca = {5, 0, 0};
267  Vector3 dir = makeDirectionFromPhiEta(M_PI_2, eta);
268  Vector3 pos = pca + dir;
269 
270  auto intersection = surface.intersect(tgContext, pos, dir).closest();
271 
272  Vector3 global = intersection.position();
273  Vector2 local = *surface.globalToLocal(tgContext, global, dir);
274  Vector3 global2 = surface.localToGlobal(tgContext, local, dir);
275 
276  CHECK_CLOSE_ABS(global, global2, 1e-10);
277  CHECK_CLOSE_ABS(pca, global2, 1e-10);
278  }
279 }
280 
281 BOOST_AUTO_TEST_CASE(LineSurfaceIntersection) {
282  using namespace Acts::UnitLiterals;
283 
284  double eps = 1e-10;
285 
286  Vector3 direction = Vector3(1, 1, 100).normalized();
287  BoundVector boundVector;
288  boundVector << 1_cm, 1_cm, VectorHelpers::phi(direction),
289  VectorHelpers::theta(direction), 1, 0;
290  double pathLimit = 1_cm;
291 
292  auto surface = std::make_shared<LineSurfaceStub>(Transform3::Identity());
293 
294  BoundTrackParameters initialParams{surface, boundVector, std::nullopt,
296 
297  Propagator<StraightLineStepper> propagator({});
298 
299  CurvilinearTrackParameters displacedParameters{
300  Vector4::Zero(), Vector3::Zero(), 1, std::nullopt,
302  {
305  options.pathLimit = pathLimit;
306 
307  auto result = propagator.propagate(initialParams, options);
308  BOOST_CHECK(result.ok());
309  BOOST_CHECK(result.value().endParameters);
310 
311  displacedParameters = result.value().endParameters.value();
312  }
313 
314  auto intersection =
315  surface
316  ->intersect(tgContext, displacedParameters.position(tgContext),
317  displacedParameters.direction())
318  .closest();
319  CHECK_CLOSE_ABS(intersection.pathLength(), pathLimit, eps);
320 
321  BoundTrackParameters endParameters{surface, BoundVector::Zero(), std::nullopt,
323  {
325  options.direction = Acts::Direction::Forward;
326  options.maxStepSize = 1_mm;
327 
328  auto result = propagator.propagate(displacedParameters, *surface, options);
329  BOOST_CHECK(result.ok());
330  BOOST_CHECK(result.value().endParameters);
331  CHECK_CLOSE_ABS(result.value().pathLength, pathLimit, eps);
332  endParameters = result.value().endParameters.value();
333  }
334 
335  CHECK_CLOSE_ABS(initialParams.parameters(), endParameters.parameters(), eps);
336 }
337 
338 BOOST_AUTO_TEST_SUITE_END()
339 
340 } // namespace Test
341 
342 } // namespace Acts