EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
PlaneSurfaceTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file PlaneSurfaceTests.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/output_test_stream.hpp>
11 #include <boost/test/unit_test.hpp>
12 
18 
19 #include <limits>
20 
21 namespace tt = boost::test_tools;
22 using boost::test_tools::output_test_stream;
23 namespace utf = boost::unit_test;
24 
25 namespace Acts {
26 
27 namespace Test {
28 
29 // Create a test context
31 
32 BOOST_AUTO_TEST_SUITE(PlaneSurfaces)
34 BOOST_AUTO_TEST_CASE(PlaneSurfaceConstruction) {
35  // PlaneSurface default constructor is deleted
36  // bounds object, rectangle type
37  auto rBounds = std::make_shared<const RectangleBounds>(3., 4.);
39  Translation3D translation{0., 1., 2.};
40  auto pTransform = Transform3D(translation);
41  // constructor with transform
42  BOOST_CHECK_EQUAL(
43  Surface::makeShared<PlaneSurface>(pTransform, rBounds)->type(),
46  auto planeSurfaceObject =
47  Surface::makeShared<PlaneSurface>(pTransform, rBounds);
48  auto copiedPlaneSurface =
49  Surface::makeShared<PlaneSurface>(*planeSurfaceObject);
50  BOOST_CHECK_EQUAL(copiedPlaneSurface->type(), Surface::Plane);
51  BOOST_CHECK(*copiedPlaneSurface == *planeSurfaceObject);
52  //
54  auto copiedTransformedPlaneSurface = Surface::makeShared<PlaneSurface>(
55  tgContext, *planeSurfaceObject, pTransform);
56  BOOST_CHECK_EQUAL(copiedTransformedPlaneSurface->type(), Surface::Plane);
57 
59  DetectorElementStub detElem;
60  BOOST_CHECK_THROW(
61  auto nullBounds = Surface::makeShared<PlaneSurface>(nullptr, detElem),
63 }
64 //
66 BOOST_AUTO_TEST_CASE(PlaneSurfaceProperties) {
67  // bounds object, rectangle type
68  auto rBounds = std::make_shared<const RectangleBounds>(3., 4.);
70  Translation3D translation{0., 1., 2.};
71  auto pTransform = Transform3D(translation);
72  auto planeSurfaceObject =
73  Surface::makeShared<PlaneSurface>(pTransform, rBounds);
74  // Is it in the right place?
75  Translation3D translation2{0., 2., 4.};
76  auto pTransform2 = Transform3D(translation2);
77  auto planeSurfaceObject2 =
78  Surface::makeShared<PlaneSurface>(pTransform2, rBounds);
80  BOOST_CHECK_EQUAL(planeSurfaceObject->type(), Surface::Plane);
81  //
83  Vector3D binningPosition{0., 1., 2.};
84  BOOST_CHECK_EQUAL(
85  planeSurfaceObject->binningPosition(tgContext, BinningValue::binX),
86  binningPosition);
87  //
89  Vector3D globalPosition{2.0, 2.0, 0.0};
90  Vector3D momentum{1.e6, 1.e6, 1.e6};
91  RotationMatrix3D expectedFrame;
92  expectedFrame << 1., 0., 0., 0., 1., 0., 0., 0., 1.;
93 
95  planeSurfaceObject->referenceFrame(tgContext, globalPosition, momentum),
96  expectedFrame, 1e-6, 1e-9);
97  //
99  Vector3D normal3D(0., 0., 1.);
100  BOOST_CHECK_EQUAL(planeSurfaceObject->normal(tgContext), normal3D);
101  //
103  BOOST_CHECK_EQUAL(planeSurfaceObject->bounds().type(),
105 
107  Vector2D localPosition{1.5, 1.7};
108  globalPosition =
109  planeSurfaceObject->localToGlobal(tgContext, localPosition, momentum);
110  //
111  // expected position is the translated one
112  Vector3D expectedPosition{1.5 + translation.x(), 1.7 + translation.y(),
113  translation.z()};
114 
115  CHECK_CLOSE_REL(globalPosition, expectedPosition, 1e-2);
116  //
118  localPosition =
119  planeSurfaceObject->globalToLocal(tgContext, globalPosition, momentum)
120  .value();
121  Vector2D expectedLocalPosition{1.5, 1.7};
122 
123  CHECK_CLOSE_REL(localPosition, expectedLocalPosition, 1e-2);
124 
126  Vector3D offSurface{0, 1, -2.};
127  BOOST_CHECK(planeSurfaceObject->isOnSurface(tgContext, globalPosition,
128  momentum, true));
129  BOOST_CHECK(
130  !planeSurfaceObject->isOnSurface(tgContext, offSurface, momentum, true));
131  //
132  // Test intersection
133  Vector3D direction{0., 0., 1.};
134  auto sfIntersection =
135  planeSurfaceObject->intersect(tgContext, offSurface, direction, true);
136  Intersection3D expectedIntersect{Vector3D{0, 1, 2}, 4.,
137  Intersection3D::Status::reachable};
138  BOOST_CHECK(bool(sfIntersection));
139  BOOST_CHECK_EQUAL(sfIntersection.intersection.position,
140  expectedIntersect.position);
141  BOOST_CHECK_EQUAL(sfIntersection.intersection.pathLength,
142  expectedIntersect.pathLength);
143  BOOST_CHECK_EQUAL(sfIntersection.object, planeSurfaceObject.get());
144  //
145 
147  CHECK_CLOSE_REL(planeSurfaceObject->pathCorrection(tgContext, offSurface,
148  momentum.normalized()),
149  std::sqrt(3), 0.01);
150  //
152  BOOST_CHECK_EQUAL(planeSurfaceObject->name(),
153  std::string("Acts::PlaneSurface"));
154  //
156  // TODO 2017-04-12 msmk: check how to correctly check output
157  // boost::test_tools::output_test_stream dumpOuput;
158  // planeSurfaceObject.toStream(dumpOuput);
159  // BOOST_CHECK(dumpOuput.is_equal(
160  // "Acts::PlaneSurface\n"
161  // " Center position (x, y, z) = (0.0000, 1.0000, 2.0000)\n"
162  // " Rotation: colX = (1.000000, 0.000000, 0.000000)\n"
163  // " colY = (0.000000, 1.000000, 0.000000)\n"
164  // " colZ = (0.000000, 0.000000, 1.000000)\n"
165  // " Bounds : Acts::ConeBounds: (tanAlpha, minZ, maxZ, averagePhi,
166  // halfPhiSector) = (0.4142136, 0.0000000, inf, 0.0000000,
167  // 3.1415927)"));
168 }
169 
170 BOOST_AUTO_TEST_CASE(PlaneSurfaceEqualityOperators) {
171  // rectangle bounds
172  auto rBounds = std::make_shared<const RectangleBounds>(3., 4.);
173  Translation3D translation{0., 1., 2.};
174  auto pTransform = Transform3D(translation);
175  auto planeSurfaceObject =
176  Surface::makeShared<PlaneSurface>(pTransform, rBounds);
177  auto planeSurfaceObject2 =
178  Surface::makeShared<PlaneSurface>(pTransform, rBounds);
179  //
181  BOOST_CHECK(*planeSurfaceObject == *planeSurfaceObject2);
182  //
183  BOOST_TEST_CHECKPOINT(
184  "Create and then assign a PlaneSurface object to the existing one");
186  auto assignedPlaneSurface =
187  Surface::makeShared<PlaneSurface>(Transform3D::Identity(), nullptr);
188  *assignedPlaneSurface = *planeSurfaceObject;
190  BOOST_CHECK(*assignedPlaneSurface == *planeSurfaceObject);
191 }
192 
194 BOOST_AUTO_TEST_CASE(PlaneSurfaceExtent) {
195  // First test - non-rotated
196  static const Transform3D planeZX =
197  AngleAxis3D(-0.5 * M_PI, Vector3D::UnitX()) *
198  AngleAxis3D(-0.5 * M_PI, Vector3D::UnitZ()) * Transform3D::Identity();
199 
200  double rHx = 2.;
201  double rHy = 4.;
202  double yPs = 3.;
203  auto rBounds = std::make_shared<RectangleBounds>(rHx, rHy);
204 
205  auto plane = Surface::makeShared<PlaneSurface>(
206  Transform3D(Translation3D(Vector3D(0., yPs, 0.)) * planeZX), rBounds);
207 
208  auto planeExtent = plane->polyhedronRepresentation(tgContext, 1).extent();
209 
210  CHECK_CLOSE_ABS(planeExtent.min(binZ), -rHx, s_onSurfaceTolerance);
211  CHECK_CLOSE_ABS(planeExtent.max(binZ), rHx, s_onSurfaceTolerance);
212  CHECK_CLOSE_ABS(planeExtent.min(binX), -rHy, s_onSurfaceTolerance);
213  CHECK_CLOSE_ABS(planeExtent.max(binX), rHy, s_onSurfaceTolerance);
214  CHECK_CLOSE_ABS(planeExtent.min(binY), yPs, s_onSurfaceTolerance);
215  CHECK_CLOSE_ABS(planeExtent.max(binY), yPs, s_onSurfaceTolerance);
216  CHECK_CLOSE_ABS(planeExtent.min(binR), yPs, s_onSurfaceTolerance);
217  CHECK_CLOSE_ABS(planeExtent.max(binR), std::sqrt(yPs * yPs + rHy * rHy),
219 
220  // Now rotate
221  double alpha = 0.123;
222  auto planeRot = Surface::makeShared<PlaneSurface>(
223  Transform3D(Translation3D(Vector3D(0., yPs, 0.)) *
224  AngleAxis3D(alpha, Vector3D(0., 0., 1.)) * planeZX),
225  rBounds);
226 
227  auto planeExtentRot =
228  planeRot->polyhedronRepresentation(tgContext, 1).extent();
229  CHECK_CLOSE_ABS(planeExtentRot.min(binZ), -rHx, s_onSurfaceTolerance);
230  CHECK_CLOSE_ABS(planeExtentRot.max(binZ), rHx, s_onSurfaceTolerance);
231  CHECK_CLOSE_ABS(planeExtentRot.min(binX), -rHy * std::cos(alpha),
233  CHECK_CLOSE_ABS(planeExtentRot.max(binX), rHy * std::cos(alpha),
235  CHECK_CLOSE_ABS(planeExtentRot.min(binY), yPs - rHy * std::sin(alpha),
237  CHECK_CLOSE_ABS(planeExtentRot.max(binY), yPs + rHy * std::sin(alpha),
239  CHECK_CLOSE_ABS(planeExtentRot.min(binR), yPs * std::cos(alpha),
241 }
242 
244 BOOST_AUTO_TEST_CASE(PlaneSurfaceAlignment) {
245  // bounds object, rectangle type
246  auto rBounds = std::make_shared<const RectangleBounds>(3., 4.);
248  Translation3D translation{0., 1., 2.};
249  auto pTransform = Transform3D(translation);
250  auto planeSurfaceObject =
251  Surface::makeShared<PlaneSurface>(pTransform, rBounds);
252  const auto& rotation = pTransform.rotation();
253  // The local frame z axis
254  const Vector3D localZAxis = rotation.col(2);
255  // Check the local z axis is aligned to global z axis
256  CHECK_CLOSE_ABS(localZAxis, Vector3D(0., 0., 1.), 1e-15);
257 
259  Vector2D localPosition{1, 2};
260  Vector3D momentum{0, 0, 1};
261  Vector3D direction = momentum.normalized();
263  Vector3D globalPosition =
264  planeSurfaceObject->localToGlobal(tgContext, localPosition, momentum);
265 
266  // Call the function to calculate the derivative of local frame axes w.r.t its
267  // rotation
268  const auto& [rotToLocalXAxis, rotToLocalYAxis, rotToLocalZAxis] =
270 
271  // (a) Test the derivative of path length w.r.t. alignment parameters
272  const AlignmentRowVector& alignToPath =
273  planeSurfaceObject->alignmentToPathDerivative(tgContext, rotToLocalZAxis,
274  globalPosition, direction);
275  // The expected results
276  AlignmentRowVector expAlignToPath = AlignmentRowVector::Zero();
277  expAlignToPath << 0, 0, 1, 2, -1, 0;
278  // Check if the calculated derivative is as expected
279  CHECK_CLOSE_ABS(alignToPath, expAlignToPath, 1e-10);
280 
281  // (b) Test the derivative of bound track parameters local position w.r.t.
282  // position in local 3D Cartesian coordinates
283  const auto& loc3DToLocBound =
284  planeSurfaceObject->localCartesianToBoundLocalDerivative(tgContext,
285  globalPosition);
286  // For plane surface, this should be identity matrix
287  CHECK_CLOSE_ABS(loc3DToLocBound, LocalCartesianToBoundLocalMatrix::Identity(),
288  1e-10);
289 
290  // (c) Test the derivative of bound parameters (only test loc0, loc1 here)
291  // w.r.t. alignment parameters
292  FreeVector derivatives = FreeVector::Zero();
293  derivatives.segment<3>(0) = momentum;
294  const AlignmentToBoundMatrix& alignToBound =
295  planeSurfaceObject->alignmentToBoundDerivative(tgContext, derivatives,
296  globalPosition, direction);
297  const AlignmentRowVector& alignToloc0 = alignToBound.block<1, 6>(0, 0);
298  const AlignmentRowVector& alignToloc1 = alignToBound.block<1, 6>(1, 0);
299  // The expected results
300  AlignmentRowVector expAlignToloc0;
301  expAlignToloc0 << -1, 0, 0, 0, 0, 2;
302  AlignmentRowVector expAlignToloc1;
303  expAlignToloc1 << 0, -1, 0, 0, 0, -1;
304  // Check if the calculated derivatives are as expected
305  CHECK_CLOSE_ABS(alignToloc0, expAlignToloc0, 1e-10);
306  CHECK_CLOSE_ABS(alignToloc1, expAlignToloc1, 1e-10);
307 }
308 
309 BOOST_AUTO_TEST_SUITE_END()
310 
311 } // namespace Test
312 
313 } // namespace Acts