Analysis Software
Documentation for sPHENIX simulation 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 
17 #include "Acts/Geometry/Extent.hpp"
29 
30 #include <algorithm>
31 #include <cmath>
32 #include <memory>
33 #include <string>
34 #include <utility>
35 
36 namespace tt = boost::test_tools;
37 using boost::test_tools::output_test_stream;
38 namespace utf = boost::unit_test;
39 
40 namespace Acts {
41 
42 namespace Test {
43 
44 // Create a test context
46 
47 BOOST_AUTO_TEST_SUITE(PlaneSurfaces)
49 BOOST_AUTO_TEST_CASE(PlaneSurfaceConstruction) {
50  // PlaneSurface default constructor is deleted
51  // bounds object, rectangle type
52  auto rBounds = std::make_shared<const RectangleBounds>(3., 4.);
54  Translation3 translation{0., 1., 2.};
55  auto pTransform = Transform3(translation);
56  // constructor with transform
57  BOOST_CHECK_EQUAL(
58  Surface::makeShared<PlaneSurface>(pTransform, rBounds)->type(),
61  auto planeSurfaceObject =
62  Surface::makeShared<PlaneSurface>(pTransform, rBounds);
63  auto copiedPlaneSurface =
64  Surface::makeShared<PlaneSurface>(*planeSurfaceObject);
65  BOOST_CHECK_EQUAL(copiedPlaneSurface->type(), Surface::Plane);
66  BOOST_CHECK(*copiedPlaneSurface == *planeSurfaceObject);
67  //
69  auto copiedTransformedPlaneSurface = Surface::makeShared<PlaneSurface>(
70  tgContext, *planeSurfaceObject, pTransform);
71  BOOST_CHECK_EQUAL(copiedTransformedPlaneSurface->type(), Surface::Plane);
72 
74  DetectorElementStub detElem;
75  BOOST_CHECK_THROW(
76  auto nullBounds = Surface::makeShared<PlaneSurface>(nullptr, detElem),
78 }
79 //
81 BOOST_AUTO_TEST_CASE(PlaneSurfaceProperties) {
82  // bounds object, rectangle type
83  auto rBounds = std::make_shared<const RectangleBounds>(3., 4.);
85  Translation3 translation{0., 1., 2.};
86  auto pTransform = Transform3(translation);
87  auto planeSurfaceObject =
88  Surface::makeShared<PlaneSurface>(pTransform, rBounds);
89  // Is it in the right place?
90  Translation3 translation2{0., 2., 4.};
91  auto pTransform2 = Transform3(translation2);
92  auto planeSurfaceObject2 =
93  Surface::makeShared<PlaneSurface>(pTransform2, rBounds);
95  BOOST_CHECK_EQUAL(planeSurfaceObject->type(), Surface::Plane);
96  //
98  Vector3 binningPosition{0., 1., 2.};
99  BOOST_CHECK_EQUAL(
100  planeSurfaceObject->binningPosition(tgContext, BinningValue::binX),
101  binningPosition);
102  //
104  Vector3 globalPosition{2.0, 2.0, 0.0};
105  Vector3 momentum{1.e6, 1.e6, 1.e6};
106  RotationMatrix3 expectedFrame;
107  expectedFrame << 1., 0., 0., 0., 1., 0., 0., 0., 1.;
108 
110  planeSurfaceObject->referenceFrame(tgContext, globalPosition, momentum),
111  expectedFrame, 1e-6, 1e-9);
112  //
114  Vector3 normal3D(0., 0., 1.);
115  BOOST_CHECK_EQUAL(planeSurfaceObject->normal(tgContext), normal3D);
116  //
118  BOOST_CHECK_EQUAL(planeSurfaceObject->bounds().type(),
120 
122  Vector2 localPosition{1.5, 1.7};
123  globalPosition =
124  planeSurfaceObject->localToGlobal(tgContext, localPosition, momentum);
125  //
126  // expected position is the translated one
127  Vector3 expectedPosition{1.5 + translation.x(), 1.7 + translation.y(),
128  translation.z()};
129 
130  CHECK_CLOSE_REL(globalPosition, expectedPosition, 1e-2);
131  //
133  localPosition =
134  planeSurfaceObject->globalToLocal(tgContext, globalPosition, momentum)
135  .value();
136  Vector2 expectedLocalPosition{1.5, 1.7};
137 
138  CHECK_CLOSE_REL(localPosition, expectedLocalPosition, 1e-2);
139 
140  Vector3 globalPositionOff =
141  globalPosition +
142  planeSurfaceObject->normal(tgContext, localPosition) * 0.1;
143 
144  BOOST_CHECK(
145  planeSurfaceObject->globalToLocal(tgContext, globalPositionOff, momentum)
146  .error());
147  BOOST_CHECK(planeSurfaceObject
148  ->globalToLocal(tgContext, globalPositionOff, momentum, 0.05)
149  .error());
150  BOOST_CHECK(planeSurfaceObject
151  ->globalToLocal(tgContext, globalPositionOff, momentum, 0.2)
152  .ok());
153 
155  Vector3 offSurface{0, 1, -2.};
156  BOOST_CHECK(planeSurfaceObject->isOnSurface(tgContext, globalPosition,
157  momentum, true));
158  BOOST_CHECK(
159  !planeSurfaceObject->isOnSurface(tgContext, offSurface, momentum, true));
160  //
161  // Test intersection
162  Vector3 direction{0., 0., 1.};
163  auto sfIntersection =
164  planeSurfaceObject->intersect(tgContext, offSurface, direction, true)
165  .closest();
166  Intersection3D expectedIntersect{Vector3{0, 1, 2}, 4.,
167  Intersection3D::Status::reachable};
168  BOOST_CHECK(sfIntersection);
169  BOOST_CHECK_EQUAL(sfIntersection.position(), expectedIntersect.position());
170  BOOST_CHECK_EQUAL(sfIntersection.pathLength(),
171  expectedIntersect.pathLength());
172  BOOST_CHECK_EQUAL(sfIntersection.object(), planeSurfaceObject.get());
173  //
174 
176  CHECK_CLOSE_REL(planeSurfaceObject->pathCorrection(tgContext, offSurface,
177  momentum.normalized()),
178  std::sqrt(3), 0.01);
179  //
181  BOOST_CHECK_EQUAL(planeSurfaceObject->name(),
182  std::string("Acts::PlaneSurface"));
183  //
185  // TODO 2017-04-12 msmk: check how to correctly check output
186  // boost::test_tools::output_test_stream dumpOuput;
187  // planeSurfaceObject.toStream(dumpOuput);
188  // BOOST_CHECK(dumpOuput.is_equal(
189  // "Acts::PlaneSurface\n"
190  // " Center position (x, y, z) = (0.0000, 1.0000, 2.0000)\n"
191  // " Rotation: colX = (1.000000, 0.000000, 0.000000)\n"
192  // " colY = (0.000000, 1.000000, 0.000000)\n"
193  // " colZ = (0.000000, 0.000000, 1.000000)\n"
194  // " Bounds : Acts::ConeBounds: (tanAlpha, minZ, maxZ, averagePhi,
195  // halfPhiSector) = (0.4142136, 0.0000000, inf, 0.0000000,
196  // 3.1415927)"));
197 }
198 
199 BOOST_AUTO_TEST_CASE(PlaneSurfaceEqualityOperators) {
200  // rectangle bounds
201  auto rBounds = std::make_shared<const RectangleBounds>(3., 4.);
202  Translation3 translation{0., 1., 2.};
203  auto pTransform = Transform3(translation);
204  auto planeSurfaceObject =
205  Surface::makeShared<PlaneSurface>(pTransform, rBounds);
206  auto planeSurfaceObject2 =
207  Surface::makeShared<PlaneSurface>(pTransform, rBounds);
208  //
210  BOOST_CHECK(*planeSurfaceObject == *planeSurfaceObject2);
211  //
212  BOOST_TEST_CHECKPOINT(
213  "Create and then assign a PlaneSurface object to the existing one");
215  auto assignedPlaneSurface =
216  Surface::makeShared<PlaneSurface>(Transform3::Identity(), nullptr);
217  *assignedPlaneSurface = *planeSurfaceObject;
219  BOOST_CHECK(*assignedPlaneSurface == *planeSurfaceObject);
220 }
221 
223 BOOST_AUTO_TEST_CASE(PlaneSurfaceExtent) {
224  // First test - non-rotated
225  static const Transform3 planeZX = AngleAxis3(-0.5 * M_PI, Vector3::UnitX()) *
226  AngleAxis3(-0.5 * M_PI, Vector3::UnitZ()) *
227  Transform3::Identity();
228 
229  double rHx = 2.;
230  double rHy = 4.;
231  double yPs = 3.;
232  auto rBounds = std::make_shared<RectangleBounds>(rHx, rHy);
233 
234  auto plane = Surface::makeShared<PlaneSurface>(
235  Transform3(Translation3(Vector3(0., yPs, 0.)) * planeZX), rBounds);
236 
237  auto planeExtent = plane->polyhedronRepresentation(tgContext, 1).extent();
238 
239  CHECK_CLOSE_ABS(planeExtent.min(binZ), -rHx, s_onSurfaceTolerance);
240  CHECK_CLOSE_ABS(planeExtent.max(binZ), rHx, s_onSurfaceTolerance);
241  CHECK_CLOSE_ABS(planeExtent.min(binX), -rHy, s_onSurfaceTolerance);
242  CHECK_CLOSE_ABS(planeExtent.max(binX), rHy, s_onSurfaceTolerance);
243  CHECK_CLOSE_ABS(planeExtent.min(binY), yPs, s_onSurfaceTolerance);
244  CHECK_CLOSE_ABS(planeExtent.max(binY), yPs, s_onSurfaceTolerance);
245  CHECK_CLOSE_ABS(planeExtent.min(binR), yPs, s_onSurfaceTolerance);
246  CHECK_CLOSE_ABS(planeExtent.max(binR), std::hypot(yPs, rHy),
248 
249  // Now rotate
250  double alpha = 0.123;
251  auto planeRot = Surface::makeShared<PlaneSurface>(
252  Transform3(Translation3(Vector3(0., yPs, 0.)) *
253  AngleAxis3(alpha, Vector3(0., 0., 1.)) * planeZX),
254  rBounds);
255 
256  auto planeExtentRot =
257  planeRot->polyhedronRepresentation(tgContext, 1).extent();
258  CHECK_CLOSE_ABS(planeExtentRot.min(binZ), -rHx, s_onSurfaceTolerance);
259  CHECK_CLOSE_ABS(planeExtentRot.max(binZ), rHx, s_onSurfaceTolerance);
260  CHECK_CLOSE_ABS(planeExtentRot.min(binX), -rHy * std::cos(alpha),
262  CHECK_CLOSE_ABS(planeExtentRot.max(binX), rHy * std::cos(alpha),
264  CHECK_CLOSE_ABS(planeExtentRot.min(binY), yPs - rHy * std::sin(alpha),
266  CHECK_CLOSE_ABS(planeExtentRot.max(binY), yPs + rHy * std::sin(alpha),
268  CHECK_CLOSE_ABS(planeExtentRot.min(binR), yPs * std::cos(alpha),
270 }
271 
273 BOOST_AUTO_TEST_CASE(PlaneSurfaceAlignment) {
274  // bounds object, rectangle type
275  auto rBounds = std::make_shared<const RectangleBounds>(3., 4.);
276  // Test clone method
277  Translation3 translation{0., 1., 2.};
278  auto pTransform = Transform3(translation);
279  auto planeSurfaceObject =
280  Surface::makeShared<PlaneSurface>(pTransform, rBounds);
281  const auto& rotation = pTransform.rotation();
282  // The local frame z axis
283  const Vector3 localZAxis = rotation.col(2);
284  // Check the local z axis is aligned to global z axis
285  CHECK_CLOSE_ABS(localZAxis, Vector3(0., 0., 1.), 1e-15);
286 
287  // Define the track (local) position and direction
288  Vector2 localPosition{1, 2};
289  Vector3 momentum{0, 0, 1};
290  Vector3 direction = momentum.normalized();
291  // Get the global position
292  Vector3 globalPosition =
293  planeSurfaceObject->localToGlobal(tgContext, localPosition, momentum);
294  // Construct a free parameters
295  FreeVector parameters = FreeVector::Zero();
296  parameters.head<3>() = globalPosition;
297  parameters.segment<3>(eFreeDir0) = direction;
298 
299  // (a) Test the derivative of path length w.r.t. alignment parameters
300  const AlignmentToPathMatrix& alignToPath =
301  planeSurfaceObject->alignmentToPathDerivative(tgContext, parameters);
302  // The expected results
303  AlignmentToPathMatrix expAlignToPath = AlignmentToPathMatrix::Zero();
304  expAlignToPath << 0, 0, 1, 2, -1, 0;
305  // Check if the calculated derivative is as expected
306  CHECK_CLOSE_ABS(alignToPath, expAlignToPath, 1e-10);
307 
308  // (b) Test the derivative of bound track parameters local position w.r.t.
309  // position in local 3D Cartesian coordinates
310  const auto& loc3DToLocBound =
311  planeSurfaceObject->localCartesianToBoundLocalDerivative(tgContext,
312  globalPosition);
313  // For plane surface, this should be identity matrix
314  CHECK_CLOSE_ABS(loc3DToLocBound, (ActsMatrix<2, 3>::Identity()), 1e-10);
315 
316  // (c) Test the derivative of bound parameters (only test loc0, loc1 here)
317  // w.r.t. alignment parameters
318  FreeVector derivatives = FreeVector::Zero();
319  derivatives.head<3>() = direction;
320  const AlignmentToBoundMatrix& alignToBound =
321  planeSurfaceObject->alignmentToBoundDerivative(tgContext, parameters,
322  derivatives);
323  const AlignmentToPathMatrix alignToloc0 =
324  alignToBound.block<1, 6>(eBoundLoc0, eAlignmentCenter0);
325  const AlignmentToPathMatrix alignToloc1 =
326  alignToBound.block<1, 6>(eBoundLoc1, eAlignmentCenter0);
327  // The expected results
328  AlignmentToPathMatrix expAlignToloc0;
329  expAlignToloc0 << -1, 0, 0, 0, 0, 2;
330  AlignmentToPathMatrix expAlignToloc1;
331  expAlignToloc1 << 0, -1, 0, 0, 0, -1;
332  // Check if the calculated derivatives are as expected
333  CHECK_CLOSE_ABS(alignToloc0, expAlignToloc0, 1e-10);
334  CHECK_CLOSE_ABS(alignToloc1, expAlignToloc1, 1e-10);
335 }
336 
337 BOOST_AUTO_TEST_SUITE_END()
338 
339 } // namespace Test
340 
341 } // namespace Acts