Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Gx2fTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file Gx2fTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2023 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/unit_test.hpp>
10 
16 #include "Acts/Geometry/Layer.hpp"
34 
35 #include <vector>
36 
37 #include "FitterTestsCommon.hpp"
38 
39 using namespace Acts::UnitLiterals;
40 
43 
44 namespace Acts {
45 namespace Test {
46 
49  const ActsScalar x = 0.0_m, const ActsScalar y = 0.0_m,
50  const ActsScalar z = 0.0_m, const ActsScalar w = 42_ns,
51  const ActsScalar phi = 0_degree, const ActsScalar theta = 90_degree,
52  const ActsScalar p = 1_GeV, const ActsScalar q = 1_e) {
53  // create covariance matrix from reasonable standard deviations
54  Acts::BoundVector stddev;
55  stddev[Acts::eBoundLoc0] = 100_um;
56  stddev[Acts::eBoundLoc1] = 100_um;
57  stddev[Acts::eBoundTime] = 25_ns;
58  stddev[Acts::eBoundPhi] = 2_degree;
59  stddev[Acts::eBoundTheta] = 2_degree;
60  stddev[Acts::eBoundQOverP] = 1 / 100_GeV;
61  Acts::BoundSquareMatrix cov = stddev.cwiseProduct(stddev).asDiagonal();
62  // define a track in the transverse plane along x
63  Acts::Vector4 mPos4(x, y, z, w);
64  return Acts::CurvilinearTrackParameters(mPos4, phi, theta, q / p, cov,
66 }
67 
68 static std::vector<Acts::SourceLink> prepareSourceLinks(
69  const std::vector<TestSourceLink>& sourceLinks) {
70  std::vector<Acts::SourceLink> result;
71  std::transform(sourceLinks.begin(), sourceLinks.end(),
72  std::back_inserter(result),
73  [](const auto& sl) { return Acts::SourceLink{sl}; });
74  return result;
75 }
76 
77 std::shared_ptr<const TrackingGeometry> makeToyDetector(
78  const GeometryContext& tgContext, const size_t nSurfaces = 5) {
79  if (nSurfaces < 1) {
80  throw std::invalid_argument("At least 1 surfaces needs to be created.");
81  }
82  // Construct builder
84 
85  // Create configurations for surfaces
86  std::vector<CuboidVolumeBuilder::SurfaceConfig> surfaceConfig;
87  for (unsigned int i = 1; i <= nSurfaces; i++) {
88  // Position of the surfaces
90  cfg.position = {i * UnitConstants::m, 0, 0.};
91 
92  // Rotation of the surfaces
93  double rotationAngle = M_PI * 0.5;
94  Vector3 xPos(cos(rotationAngle), 0., sin(rotationAngle));
95  Vector3 yPos(0., 1., 0.);
96  Vector3 zPos(-sin(rotationAngle), 0., cos(rotationAngle));
97  cfg.rotation.col(0) = xPos;
98  cfg.rotation.col(1) = yPos;
99  cfg.rotation.col(2) = zPos;
101  // Boundaries of the surfaces
102  cfg.rBounds =
103  std::make_shared<const RectangleBounds>(RectangleBounds(0.5_m, 0.5_m));
104 
105  // Material of the surfaces
106  MaterialSlab matProp(makeBeryllium(), 0.5_mm);
107  cfg.surMat = std::make_shared<HomogeneousSurfaceMaterial>(matProp);
108 
109  // Thickness of the detector element
110  cfg.thickness = 1_um;
111 
113  [](const Transform3& trans,
114  const std::shared_ptr<const RectangleBounds>& bounds,
115  double thickness) {
116  return new DetectorElementStub(trans, bounds, thickness);
117  };
118  surfaceConfig.push_back(cfg);
119  }
120 
121  // Build layer configurations
122  std::vector<CuboidVolumeBuilder::LayerConfig> layerConfig;
123  for (auto& sCfg : surfaceConfig) {
125  cfg.surfaceCfg = {sCfg};
126  cfg.active = true;
127  cfg.envelopeX = {-0.1_mm, 0.1_mm};
128  cfg.envelopeY = {-0.1_mm, 0.1_mm};
129  cfg.envelopeZ = {-0.1_mm, 0.1_mm};
130  layerConfig.push_back(cfg);
131  }
132 
133  // Inner Volume - Build volume configuration
135  volumeConfig.length = {(nSurfaces + 1) * 1_m, 1_m, 1_m};
136  volumeConfig.position = {volumeConfig.length.x() / 2, 0., 0.};
137  volumeConfig.layerCfg = layerConfig;
138  volumeConfig.name = "Test volume";
139 
140  // Outer volume - Build TrackingGeometry configuration
142  config.length = {(nSurfaces + 1) * 1_m, 1_m, 1_m};
143  config.position = {volumeConfig.length.x() / 2, 0., 0.};
144  config.volumeCfg = {volumeConfig};
145 
146  cvb.setConfig(config);
147 
149 
150  tgbCfg.trackingVolumeBuilders.push_back(
151  [=](const auto& context, const auto& inner, const auto&) {
152  return cvb.trackingVolume(context, inner, nullptr);
153  });
154 
155  TrackingGeometryBuilder tgb(tgbCfg);
156 
157  std::unique_ptr<const TrackingGeometry> detector =
158  tgb.trackingGeometry(tgContext);
159  return detector;
160 }
161 
162 struct Detector {
163  // geometry
164  std::shared_ptr<const TrackingGeometry> geometry;
165 };
166 
167 BOOST_AUTO_TEST_SUITE(Gx2fTest)
168 
169 // This test checks if the call to the fitter works and no errors occur in the
170 // framework, without fitting and updating any parameters
173  ACTS_INFO("*** Test: NoFit -- Start");
174 
175  // Context objects
179  std::default_random_engine rng(42);
180 
182  const size_t nSurfaces = 5;
183  detector.geometry = makeToyDetector(geoCtx, nSurfaces);
184 
185  auto parametersMeasurements = makeParameters();
186  auto startParametersFit = makeParameters(7_mm, 11_mm, 15_mm, 42_ns, 10_degree,
187  80_degree, 1_GeV, 1_e);
188 
189  MeasurementResolution resPixel = {MeasurementType::eLoc01, {25_um, 50_um}};
191  {Acts::GeometryIdentifier().setVolume(0), resPixel}};
192 
193  // propagator
194  using SimPropagator =
196  SimPropagator simPropagator = makeStraightPropagator(detector.geometry);
197  auto measurements = createMeasurements(
198  simPropagator, geoCtx, magCtx, parametersMeasurements, resolutions, rng);
199  auto sourceLinks = prepareSourceLinks(measurements.sourceLinks);
200 
201  using Gx2Fitter =
203  Gx2Fitter fitter(simPropagator, gx2fLogger->clone());
204 
205  const Surface* rSurface = &parametersMeasurements.referenceSurface();
206 
208  extensions.calibrator
209  .connect<&testSourceLinkCalibrator<VectorMultiTrajectory>>();
210  TestSourceLink::SurfaceAccessor surfaceAccessor{*detector.geometry};
211  extensions.surfaceAccessor
212  .connect<&TestSourceLink::SurfaceAccessor::operator()>(&surfaceAccessor);
213 
214  Experimental::Gx2FitterOptions gx2fOptions(
215  geoCtx, magCtx, calCtx, extensions, PropagatorPlainOptions(), rSurface,
216  false, false, FreeToBoundCorrection(false), 0);
217 
220 
221  // Fit the track
222  auto res = fitter.fit(sourceLinks.begin(), sourceLinks.end(),
223  startParametersFit, gx2fOptions, tracks);
224 
225  BOOST_REQUIRE(res.ok());
226 
227  auto& track = *res;
228  BOOST_CHECK_EQUAL(track.tipIndex(), Acts::MultiTrajectoryTraits::kInvalid);
229  BOOST_CHECK(track.hasReferenceSurface());
230  BOOST_CHECK_EQUAL(track.nMeasurements(), 0u);
231  BOOST_CHECK_EQUAL(track.nHoles(), 0u);
232  BOOST_CHECK_EQUAL(track.parameters(), startParametersFit.parameters());
233  BOOST_CHECK_EQUAL(track.covariance(), BoundMatrix::Identity());
234 
235  ACTS_INFO("*** Test: NoFit -- Finish");
236 }
237 
238 BOOST_AUTO_TEST_CASE(Fit5Iterations) {
240  ACTS_INFO("*** Test: Fit5Iterations -- Start");
241 
242  // Create a test context
243  GeometryContext tgContext = GeometryContext();
244 
246  const size_t nSurfaces = 5;
247  detector.geometry = makeToyDetector(tgContext, nSurfaces);
248 
249  ACTS_DEBUG("Go to propagator");
250 
251  auto parametersMeasurements = makeParameters();
252  auto startParametersFit = makeParameters(7_mm, 11_mm, 15_mm, 42_ns, 10_degree,
253  80_degree, 1_GeV, 1_e);
254 
255  // Context objects
258  // Acts::CalibrationContext calCtx;
259  std::default_random_engine rng(42);
260 
261  MeasurementResolution resPixel = {MeasurementType::eLoc01, {25_um, 50_um}};
263  {Acts::GeometryIdentifier().setVolume(0), resPixel}};
264 
265  // simulation propagator
266  using SimPropagator =
268  SimPropagator simPropagator = makeStraightPropagator(detector.geometry);
269  auto measurements = createMeasurements(
270  simPropagator, geoCtx, magCtx, parametersMeasurements, resolutions, rng);
271  auto sourceLinks = prepareSourceLinks(measurements.sourceLinks);
272  ACTS_VERBOSE("sourceLinks.size() = " << sourceLinks.size());
273 
274  BOOST_REQUIRE_EQUAL(sourceLinks.size(), nSurfaces);
275 
276  ACTS_DEBUG("Start fitting");
277  ACTS_VERBOSE("startParameter unsmeared:\n" << parametersMeasurements);
278  ACTS_VERBOSE("startParameter fit:\n" << startParametersFit);
279 
280  const Surface* rSurface = &parametersMeasurements.referenceSurface();
281 
282  using RecoStepper = EigenStepper<>;
283  const auto recoPropagator =
284  makeConstantFieldPropagator<RecoStepper>(detector.geometry, 0_T);
285 
286  using RecoPropagator = decltype(recoPropagator);
287  using Gx2Fitter =
289  Gx2Fitter fitter(recoPropagator, gx2fLogger->clone());
290 
292  extensions.calibrator
293  .connect<&testSourceLinkCalibrator<VectorMultiTrajectory>>();
294  TestSourceLink::SurfaceAccessor surfaceAccessor{*detector.geometry};
295  extensions.surfaceAccessor
296  .connect<&TestSourceLink::SurfaceAccessor::operator()>(&surfaceAccessor);
297 
299  CalibrationContext calContext;
300 
301  const Experimental::Gx2FitterOptions gx2fOptions(
302  tgContext, mfContext, calContext, extensions, PropagatorPlainOptions(),
303  rSurface, false, false, FreeToBoundCorrection(false), 5);
304 
307 
308  // Fit the track
309  auto res = fitter.fit(sourceLinks.begin(), sourceLinks.end(),
310  startParametersFit, gx2fOptions, tracks);
311 
312  BOOST_REQUIRE(res.ok());
313 
314  auto& track = *res;
315  BOOST_CHECK_EQUAL(track.tipIndex(), nSurfaces - 1);
316  BOOST_CHECK(track.hasReferenceSurface());
317  BOOST_CHECK_EQUAL(track.nMeasurements(), nSurfaces);
318  BOOST_CHECK_EQUAL(track.nHoles(), 0u);
319  // We need quite coarse checks here, since on different builds
320  // the created measurements differ in the randomness
321  BOOST_CHECK_CLOSE(track.parameters()[eBoundLoc0], -11., 7e0);
322  BOOST_CHECK_CLOSE(track.parameters()[eBoundLoc1], -15., 6e0);
323  BOOST_CHECK_CLOSE(track.parameters()[eBoundPhi], 1e-5, 1e3);
324  BOOST_CHECK_CLOSE(track.parameters()[eBoundTheta], M_PI / 2, 1e-3);
325  BOOST_CHECK_EQUAL(track.parameters()[eBoundQOverP], 1);
326  BOOST_CHECK_CLOSE(track.parameters()[eBoundTime], 12591.2832360000, 1e-6);
327  BOOST_CHECK_CLOSE(track.covariance().determinant(), 1e-27, 4e0);
328 
329  ACTS_INFO("*** Test: Fit5Iterations -- Finish");
330 }
331 
332 BOOST_AUTO_TEST_CASE(MixedDetector) {
334  ACTS_INFO("*** Test: MixedDetector -- Start");
335 
336  // Create a test context
337  GeometryContext tgContext = GeometryContext();
338 
340  const size_t nSurfaces = 7;
341  detector.geometry = makeToyDetector(tgContext, nSurfaces);
342 
343  ACTS_DEBUG("Go to propagator");
344 
345  auto parametersMeasurements = makeParameters();
346  auto startParametersFit = makeParameters(7_mm, 11_mm, 15_mm, 42_ns, 10_degree,
347  80_degree, 1_GeV, 1_e);
348 
349  // Context objects
352  // Acts::CalibrationContext calCtx;
353  std::default_random_engine rng(42);
354 
355  MeasurementResolution resPixel = {MeasurementType::eLoc01, {25_um, 50_um}};
356  MeasurementResolution resStrip0 = {MeasurementType::eLoc0, {25_um}};
357  MeasurementResolution resStrip1 = {MeasurementType::eLoc1, {50_um}};
359  {Acts::GeometryIdentifier().setVolume(2).setLayer(2), resPixel},
360  {Acts::GeometryIdentifier().setVolume(2).setLayer(4), resStrip0},
361  {Acts::GeometryIdentifier().setVolume(2).setLayer(6), resStrip1},
362  {Acts::GeometryIdentifier().setVolume(2).setLayer(8), resPixel},
363  {Acts::GeometryIdentifier().setVolume(2).setLayer(10), resStrip0},
364  {Acts::GeometryIdentifier().setVolume(2).setLayer(12), resStrip1},
365  {Acts::GeometryIdentifier().setVolume(2).setLayer(14), resPixel},
366  };
367 
368  // simulation propagator
369  using SimPropagator =
371  SimPropagator simPropagator = makeStraightPropagator(detector.geometry);
372  auto measurements = createMeasurements(
373  simPropagator, geoCtx, magCtx, parametersMeasurements, resolutions, rng);
374  auto sourceLinks = prepareSourceLinks(measurements.sourceLinks);
375  ACTS_VERBOSE("sourceLinks.size() = " << sourceLinks.size());
376 
377  BOOST_REQUIRE_EQUAL(sourceLinks.size(), nSurfaces);
378 
379  ACTS_DEBUG("Start fitting");
380  ACTS_VERBOSE("startParameter unsmeared:\n" << parametersMeasurements);
381  ACTS_VERBOSE("startParameter fit:\n" << startParametersFit);
382 
383  const Surface* rSurface = &parametersMeasurements.referenceSurface();
384 
385  using RecoStepper = EigenStepper<>;
386  const auto recoPropagator =
387  makeConstantFieldPropagator<RecoStepper>(detector.geometry, 0_T);
388 
389  using RecoPropagator = decltype(recoPropagator);
390  using Gx2Fitter =
392  Gx2Fitter fitter(recoPropagator, gx2fLogger->clone());
393 
395  extensions.calibrator
396  .connect<&testSourceLinkCalibrator<VectorMultiTrajectory>>();
397  TestSourceLink::SurfaceAccessor surfaceAccessor{*detector.geometry};
398  extensions.surfaceAccessor
399  .connect<&TestSourceLink::SurfaceAccessor::operator()>(&surfaceAccessor);
400 
402  CalibrationContext calContext;
403 
404  const Experimental::Gx2FitterOptions gx2fOptions(
405  tgContext, mfContext, calContext, extensions, PropagatorPlainOptions(),
406  rSurface, false, false, FreeToBoundCorrection(false), 5);
407 
410 
411  // Fit the track
412  auto res = fitter.fit(sourceLinks.begin(), sourceLinks.end(),
413  startParametersFit, gx2fOptions, tracks);
414 
415  BOOST_REQUIRE(res.ok());
416 
417  auto& track = *res;
418  BOOST_CHECK_EQUAL(track.tipIndex(), nSurfaces - 1);
419  BOOST_CHECK(track.hasReferenceSurface());
420  BOOST_CHECK_EQUAL(track.nMeasurements(), nSurfaces);
421  BOOST_CHECK_EQUAL(track.nHoles(), 0u);
422  // We need quite coarse checks here, since on different builds
423  // the created measurements differ in the randomness
424  BOOST_CHECK_CLOSE(track.parameters()[eBoundLoc0], -11., 7e0);
425  BOOST_CHECK_CLOSE(track.parameters()[eBoundLoc1], -15., 6e0);
426  BOOST_CHECK_CLOSE(track.parameters()[eBoundPhi], 1e-5, 1e3);
427  BOOST_CHECK_CLOSE(track.parameters()[eBoundTheta], M_PI / 2, 1e-3);
428  BOOST_CHECK_EQUAL(track.parameters()[eBoundQOverP], 1);
429  BOOST_CHECK_CLOSE(track.parameters()[eBoundTime], 12591.2832360000, 1e-6);
430  BOOST_CHECK_CLOSE(track.covariance().determinant(), 2e-28, 1e0);
431 
432  ACTS_INFO("*** Test: MixedDetector -- Finish");
433 }
434 
435 BOOST_AUTO_TEST_SUITE_END()
436 } // namespace Test
437 } // namespace Acts