EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ImpactPointEstimatorTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ImpactPointEstimatorTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2019 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 
20 #include "Acts/Utilities/Units.hpp"
23 
24 using namespace Acts::UnitLiterals;
26 
27 namespace Acts {
28 namespace Test {
29 
31 using Propagator = Propagator<EigenStepper<ConstantBField>>;
32 // Create a test context
35 
36 // Track d0 distribution
37 std::uniform_real_distribution<> d0Dist(-0.01_mm, 0.01_mm);
38 // Track z0 distribution
39 std::uniform_real_distribution<> z0Dist(-0.2_mm, 0.2_mm);
40 // Track pT distribution
41 std::uniform_real_distribution<> pTDist(0.4_GeV, 10._GeV);
42 // Track phi distribution
43 std::uniform_real_distribution<> phiDist(-M_PI, M_PI);
44 // Track theta distribution
45 std::uniform_real_distribution<> thetaDist(1.0, M_PI - 1.0);
46 // Track IP resolution distribution
47 std::uniform_real_distribution<> resIPDist(0., 100._um);
48 // Track angular distribution
49 std::uniform_real_distribution<> resAngDist(0., 0.1);
50 // Track q/p resolution distribution
51 std::uniform_real_distribution<> resQoPDist(-0.1, 0.1);
52 // Track charge helper distribution
53 std::uniform_real_distribution<> qDist(-1, 1);
54 // Vertex x/y position distribution
55 std::uniform_real_distribution<> vXYDist(-0.1_mm, 0.1_mm);
56 // Vertex z position distribution
57 std::uniform_real_distribution<> vZDist(-20_mm, 20_mm);
58 // Number of tracks distritbution
59 std::uniform_int_distribution<> nTracksDist(3, 10);
60 
63 BOOST_AUTO_TEST_CASE(impactpoint_estimator_params_distance_test) {
64  // Debug mode
65  bool debugMode = false;
66  // Number of tests
67  unsigned int nTests = 10;
68 
69  // Set up RNG
70  int mySeed = 31415;
71  std::mt19937 gen(mySeed);
72 
73  // Set up constant B-Field
74  ConstantBField bField(Vector3D(0., 0., 2._T));
75 
76  // Set up Eigenstepper
78 
79  // Set up propagator with void navigator
80  auto propagator = std::make_shared<Propagator>(stepper);
81 
82  // Set up the ImpactPointEstimator
84  IPEstimator::Config ipEstCfg(bField, propagator);
85  IPEstimator ipEstimator(ipEstCfg);
86  IPEstimator::State state(magFieldContext);
87 
88  // Reference position
89  Vector3D refPosition(0., 0., 0.);
90 
91  // Start running tests
92  for (unsigned int i = 0; i < nTests; i++) {
93  // Create a track
94  // Resolutions
95  double resD0 = resIPDist(gen);
96  double resZ0 = resIPDist(gen);
97  double resPh = resAngDist(gen);
98  double resTh = resAngDist(gen);
99  double resQp = resQoPDist(gen);
100 
101  // Covariance matrix
102  Covariance covMat;
103  covMat << resD0 * resD0, 0., 0., 0., 0., 0., 0., resZ0 * resZ0, 0., 0., 0.,
104  0., 0., 0., resPh * resPh, 0., 0., 0., 0., 0., 0., resTh * resTh, 0.,
105  0., 0., 0., 0., 0., resQp * resQp, 0., 0., 0., 0., 0., 0., 1.;
106 
107  // The charge
108  double q = qDist(gen) < 0 ? -1. : 1.;
109  // Impact parameters (IP)
110  double d0 = d0Dist(gen);
111  double z0 = z0Dist(gen);
112 
113  if (debugMode) {
114  std::cout << "IP: (" << d0 << "," << z0 << ")" << std::endl;
115  }
116 
117  // The track parameters
119  paramVec[eBoundLoc0] = d0;
120  paramVec[eBoundLoc1] = z0;
121  paramVec[eBoundTime] = 0;
122  paramVec[eBoundPhi] = phiDist(gen);
123  paramVec[eBoundTheta] = thetaDist(gen);
124  paramVec[eBoundQOverP] = q / pTDist(gen);
125 
126  // Corresponding surface
127  std::shared_ptr<PerigeeSurface> perigeeSurface =
128  Surface::makeShared<PerigeeSurface>(refPosition);
129 
130  // Creating the track
131  BoundTrackParameters myTrack(perigeeSurface, paramVec, std::move(covMat));
132 
133  // Distance in transverse plane
134  double transverseDist = std::sqrt(std::pow(d0, 2) + std::pow(z0, 2));
135 
136  // Estimate 3D distance
137  auto distanceRes = ipEstimator.calculate3dDistance(geoContext, myTrack,
138  refPosition, state);
139  BOOST_CHECK(distanceRes.ok());
140 
141  double distance = *distanceRes;
142 
143  BOOST_CHECK(distance < transverseDist);
144 
145  if (debugMode) {
146  std::cout << std::setprecision(10)
147  << "Distance in transverse plane: " << transverseDist
148  << std::endl;
149  std::cout << std::setprecision(10) << "Distance in 3D: " << distance
150  << std::endl;
151  }
152 
153  auto res = ipEstimator.estimate3DImpactParameters(
154  geoContext, magFieldContext, myTrack, refPosition, state);
155 
156  BOOST_CHECK(res.ok());
157 
158  BoundTrackParameters trackAtIP3d = std::move(**res);
159 
160  const auto& myTrackParams = myTrack.parameters();
161  const auto& trackIP3dParams = trackAtIP3d.parameters();
162 
163  // d0 and z0 should have changed
164  BOOST_CHECK_NE(myTrackParams[BoundIndices::eBoundLoc0],
165  trackIP3dParams[BoundIndices::eBoundLoc0]);
166  BOOST_CHECK_NE(myTrackParams[BoundIndices::eBoundLoc1],
167  trackIP3dParams[BoundIndices::eBoundLoc1]);
168  // Theta along helix and q/p shoud remain the same
170  trackIP3dParams[BoundIndices::eBoundTheta], 1e-5);
172  trackIP3dParams[BoundIndices::eBoundQOverP], 1e-5);
173 
174  if (debugMode) {
175  std::cout << std::setprecision(10) << "Old track parameters: \n"
176  << myTrackParams << std::endl;
177  std::cout << std::setprecision(10) << "Parameters at IP3d: \n"
178  << trackIP3dParams << std::endl;
179  }
180  } // end for loop tests
181 }
182 
185 BOOST_AUTO_TEST_CASE(impactpoint_estimator_compatibility_test) {
186  // Debug mode
187  bool debugMode = false;
188  // Number of tests
189  unsigned int nTests = 10;
190 
191  // Set up RNG
192  int mySeed = 31415;
193  std::mt19937 gen(mySeed);
194 
195  // Set up constant B-Field
197 
198  // Set up Eigenstepper
200 
201  // Set up propagator with void navigator
202  auto propagator = std::make_shared<Propagator>(stepper);
203 
204  // Set up the ImpactPointEstimator
206  IPEstimator::Config ipEstCfg(bField, propagator);
207  IPEstimator ipEstimator(ipEstCfg);
208  IPEstimator::State state(magFieldContext);
209 
210  // Reference position
211  Vector3D refPosition(0., 0., 0.);
212 
213  // Lists to store distances and comp values
214  std::vector<double> distancesList;
215  std::vector<double> compatibilityList;
216 
217  // Generate covariance matrix values once
218  // for all cov matrices below
219  // Resolutions
220  double resD0 = resIPDist(gen);
221  double resZ0 = resIPDist(gen);
222  double resPh = resAngDist(gen);
223  double resTh = resAngDist(gen);
224  double resQp = resQoPDist(gen);
225 
226  // Start running tests
227  for (unsigned int i = 0; i < nTests; i++) {
228  // Covariance matrix
230  BoundTrackParameters::CovarianceMatrix::Zero();
231  covMat(eBoundLoc0, eBoundLoc0) = resD0 * resD0;
232  covMat(eBoundLoc1, eBoundLoc1) = resZ0 * resZ0;
233  covMat(eBoundTime, eBoundTime) = 1;
234  covMat(eBoundPhi, eBoundPhi) = resPh * resPh;
235  covMat(eBoundTheta, eBoundTheta) = resTh * resTh;
236  covMat(eBoundQOverP, eBoundQOverP) = resQp * resQp;
237  // The track parameters
239  paramVec[eBoundLoc0] = d0Dist(gen);
240  paramVec[eBoundLoc1] = z0Dist(gen);
241  paramVec[eBoundTime] = 0;
242  paramVec[eBoundPhi] = phiDist(gen);
243  paramVec[eBoundTheta] = thetaDist(gen);
244  paramVec[eBoundQOverP] = (qDist(gen) < 0 ? -1. : 1.) / pTDist(gen);
245 
246  // Corresponding surface
247  auto perigeeSurface = Surface::makeShared<PerigeeSurface>(refPosition);
248  // Creating the track
249  BoundTrackParameters myTrack(perigeeSurface, paramVec, std::move(covMat));
250 
251  // Estimate 3D distance
252  auto distanceRes = ipEstimator.calculate3dDistance(geoContext, myTrack,
253  refPosition, state);
254  BOOST_CHECK(distanceRes.ok());
255 
256  distancesList.push_back(*distanceRes);
257 
258  auto res = ipEstimator.estimate3DImpactParameters(
259  geoContext, magFieldContext, myTrack, refPosition, state);
260 
261  BOOST_CHECK(res.ok());
262 
263  BoundTrackParameters params = std::move(**res);
264 
265  auto compRes =
266  ipEstimator.get3dVertexCompatibility(geoContext, &params, refPosition);
267 
268  BOOST_CHECK(compRes.ok());
269 
270  compatibilityList.push_back(*compRes);
271 
272  } // end create tracks loop
273 
274  // Now test for all above constructed tracks
275  // if distances and compatibility values are
276  // compatible with one another
277  for (unsigned int i = 0; i < nTests; i++) {
278  for (unsigned int j = i + 1; j < nTests; j++) {
279  double relDiffComp =
280  (compatibilityList[i] - compatibilityList[j]) / compatibilityList[i];
281 
282  double relDiffDist =
283  (distancesList[i] - distancesList[j]) / distancesList[i];
284 
285  if (debugMode) {
286  std::cout << "Comparing track " << i << " with track " << j
287  << std::endl;
288  std::cout << "\t" << i << ": Comp.: " << compatibilityList[i]
289  << ", dist.: " << distancesList[i] << std::endl;
290  std::cout << "\t" << j << ": Comp.: " << compatibilityList[j]
291  << ", dist.: " << distancesList[j] << std::endl;
292  std::cout << "\t Rel.diff.: Comp(1-2)/1: " << relDiffComp
293  << ", Dist(1-2)/1: " << relDiffDist << std::endl;
294  }
295 
296  // Relative differences of compatibility values and distances
297  // should have the same sign, i.e. the following product
298  // should always be positive
299  // double res = relDiffComp * relDiffDist;
300 
301  // TODO 2020-09-09 msmk
302  // this fails for one track after the the track parameters cleanup.
303  // i do not understand what this tests and/or how to fix it. Bastian
304  // has to look at this.
305  // BOOST_CHECK_GE(res, 0);
306  }
307  }
308 }
309 
313 BOOST_AUTO_TEST_CASE(impactpoint_estimator_athena_test) {
314  // Set up constant B-Field
315  ConstantBField bField(Vector3D(0., 0., 1.9971546939_T));
316 
317  // Set up Eigenstepper
319 
320  // Set up propagator with void navigator
321  auto propagator = std::make_shared<Propagator>(stepper);
322 
323  // Set up the ImpactPointEstimator
325  IPEstimator::Config ipEstCfg(bField, propagator);
326  IPEstimator ipEstimator(ipEstCfg);
327  IPEstimator::State state(magFieldContext);
328 
329  // Use same values as in Athena unit test
330  Vector3D pos1(2_mm, 1_mm, -10_mm);
331  Vector3D mom1(400_MeV, 600_MeV, 200_MeV);
332  Vector3D vtxPos(1.2_mm, 0.8_mm, -7_mm);
333 
334  // Start creating some track parameters
335  std::shared_ptr<PerigeeSurface> perigeeSurface =
336  Surface::makeShared<PerigeeSurface>(pos1);
337  // Some fixed track parameter values
338  BoundTrackParameters params1(perigeeSurface, geoContext,
339  makeVector4(pos1, 0_ns), mom1, mom1.norm(), 1,
340  Covariance::Identity());
341 
342  auto res1 =
343  ipEstimator.calculate3dDistance(geoContext, params1, vtxPos, state);
344  BOOST_CHECK(res1.ok());
345  double distance = (*res1);
346 
347  // Desired result from Athena unit test
348  const double result = 3.10391_mm;
349  CHECK_CLOSE_ABS(distance, result, 0.00001_mm);
350 
351  auto res2 = ipEstimator.estimate3DImpactParameters(
352  geoContext, magFieldContext, params1, vtxPos, state);
353  BOOST_CHECK(res2.ok());
354  BoundTrackParameters endParams = std::move(**res2);
355  Vector3D surfaceCenter = endParams.referenceSurface().center(geoContext);
356 
357  BOOST_CHECK_EQUAL(surfaceCenter, vtxPos);
358 }
359 
363 BOOST_AUTO_TEST_CASE(impactpoint_estimator_parameter_estimation_test) {
364  // Number of tracks to test with
365  unsigned int nTracks = 10;
366 
367  // Set up RNG
368  int mySeed = 31415;
369  std::mt19937 gen(mySeed);
370 
371  // Set up constant B-Field
372  ConstantBField bField(0.0, 0.0, 1_T);
373 
374  // Set up Eigenstepper
376 
377  // Set up propagator with void navigator
378  auto propagator = std::make_shared<Propagator>(stepper);
379 
380  // Create perigee surface
381  std::shared_ptr<PerigeeSurface> perigeeSurface =
382  Surface::makeShared<PerigeeSurface>(Vector3D(0., 0., 0.));
383 
384  // Create position of vertex and perigee surface
385  double x = vXYDist(gen);
386  double y = vXYDist(gen);
387  double z = vZDist(gen);
388 
389  Vector4D vertexPosition(x, y, z, 0.);
390 
391  // Constraint for vertex fit
392  Vertex<BoundTrackParameters> myConstraint;
393  // Some abitrary values
394  SymMatrix4D myCovMat = SymMatrix4D::Zero();
395  myCovMat(0, 0) = 30.;
396  myCovMat(1, 1) = 30.;
397  myCovMat(2, 2) = 30.;
398  myCovMat(3, 3) = 30.;
399  myConstraint.setFullCovariance(std::move(myCovMat));
400  myConstraint.setFullPosition(vertexPosition);
401 
402  // Calculate d0 and z0 corresponding to vertex position
403  double d0_v = std::sqrt(x * x + y * y);
404  double z0_v = z;
405 
406  // Set up the ImpactPointEstimator
408  IPEstimator::Config ipEstCfg(bField, propagator);
409  IPEstimator ipEstimator(ipEstCfg);
410  IPEstimator::State state(magFieldContext);
411 
412  // Construct random track emerging from vicinity of vertex position
413  // Vector to store track objects used for vertex fit
414  for (unsigned int iTrack = 0; iTrack < nTracks; iTrack++) {
415  // Construct positive or negative charge randomly
416  double q = qDist(gen) < 0 ? -1. : 1.;
417 
418  // Construct random track parameters
419  BoundVector paramVec;
420  paramVec << d0_v + d0Dist(gen), z0_v + z0Dist(gen), phiDist(gen),
421  thetaDist(gen), q / pTDist(gen), 0.;
422 
423  // Resolutions
424  double resD0 = resIPDist(gen);
425  double resZ0 = resIPDist(gen);
426  double resPh = resAngDist(gen);
427  double resTh = resAngDist(gen);
428  double resQp = resQoPDist(gen);
429 
430  // Fill vector of track objects with simple covariance matrix
431  Covariance covMat;
432  covMat << resD0 * resD0, 0., 0., 0., 0., 0., 0., resZ0 * resZ0, 0., 0., 0.,
433  0., 0., 0., resPh * resPh, 0., 0., 0., 0., 0., 0., resTh * resTh, 0.,
434  0., 0., 0., 0., 0., resQp * resQp, 0., 0., 0., 0., 0., 0., 1.;
435 
436  BoundTrackParameters track(perigeeSurface, paramVec, std::move(covMat));
437 
438  // Check if IP are retrieved
439  ImpactParametersAndSigma output =
440  ipEstimator
441  .estimateImpactParameters(track, myConstraint, geoContext,
443  .value();
444  BOOST_CHECK_NE(output.IPd0, 0.);
445  BOOST_CHECK_NE(output.IPz0, 0.);
446  }
447 }
448 
449 } // namespace Test
450 } // namespace Acts