ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MultiTrajectoryTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file MultiTrajectoryTests.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/unit_test.hpp>
10 
19 
20 #include <iostream>
21 
22 using std::cout;
23 using std::endl;
24 
25 namespace Acts {
26 namespace Test {
27 
29 
33 
35  // generate arbitrary positive, definite matrix
36  Covariance rnd = Covariance::Random();
37  Covariance cov = rnd.transpose() * rnd;
38  return {cov, Vector3D(0, 0, 1), Vector3D(100, 1000, 400), -1, 0};
39 }
40 
42  return {make_params()};
43 }
44 
47 
48 // std::pair<TrackState<SourceLink, BoundParameters>,
49 // std::unique_ptr<FittableMeasurement<SourceLink>>>
51  auto plane = Surface::makeShared<PlaneSurface>(Vector3D{0., 0., 0.},
52  Vector3D{0., 0., 1.});
54 
55  ActsMatrixD<3, 3> mCov;
56  mCov << 1, 2, 3, 4, 5, 6, 7, 8, 9;
57 
58  ActsVectorD<3> mPar;
59  mPar << 2, 3, 4;
61  mPar[0], mPar[1], mPar[2]};
62 
63  auto fm = std::make_unique<FittableMeasurement<SourceLink>>(meas);
64 
65  SourceLink sl{fm.get()};
66  TrackState ts{sl};
67 
68  // add parameters
69 
70  // predicted
71  ParVec_t predPar;
72  predPar << 1, 2, M_PI / 4., M_PI / 2., 5, 0.;
73 
74  CovMat_t predCov;
75  predCov.setRandom();
76 
77  BoundParameters pred(gctx, predCov, predPar, plane);
78 
79  ts.parameter.predicted = pred;
80 
81  // filtered
82  ParVec_t filtPar;
83  filtPar << 6, 7, M_PI / 4., M_PI / 2., 10, 0.;
84 
85  CovMat_t filtCov;
86  filtCov.setRandom();
87 
88  BoundParameters filt(gctx, filtCov, filtPar, plane);
89 
90  ts.parameter.filtered = filt;
91 
92  // smoothed
93  ParVec_t smotPar;
94  smotPar << 11, 12, M_PI / 4., M_PI / 2., 15, 0.;
95 
96  CovMat_t smotCov;
97  smotCov.setRandom();
98 
99  BoundParameters smot(gctx, smotCov, smotPar, plane);
100 
101  ts.parameter.smoothed = smot;
102 
103  // "calibrate", keep original source link (stack address)
104  ts.measurement.calibrated =
105  decltype(meas){meas.referenceSurface().getSharedPtr(),
106  sl,
107  meas.covariance(),
108  meas.parameters()[0],
109  meas.parameters()[1],
110  meas.parameters()[2]};
111 
112  // make jacobian
113  CovMat_t jac;
114  jac.setRandom();
115 
116  ts.parameter.jacobian = jac;
117 
118  ts.parameter.chi2 = 78;
119  ts.parameter.pathLength = 42;
120 
121  return std::make_tuple(ts, std::move(fm), meas);
122 }
123 
124 BOOST_AUTO_TEST_CASE(multitrajectory_build) {
126 
127  // construct trajectory w/ multiple components
128  auto i0 = t.addTrackState(make_rand_trackstate());
129  // trajectory bifurcates here into multiple hypotheses
130  auto i1a = t.addTrackState(make_rand_trackstate(), i0);
131  auto i1b = t.addTrackState(make_rand_trackstate(), i0);
132  auto i2a = t.addTrackState(make_rand_trackstate(), i1a);
133  auto i2b = t.addTrackState(make_rand_trackstate(), i1b);
134 
135  // print each trajectory component
136  std::vector<size_t> act;
137  auto collect = [&](auto p) {
138  act.push_back(p.index());
139  // assert absence of things
140  BOOST_CHECK(!p.hasUncalibrated());
141  BOOST_CHECK(!p.hasCalibrated());
142  BOOST_CHECK(!p.hasFiltered());
143  BOOST_CHECK(!p.hasSmoothed());
144  BOOST_CHECK(!p.hasJacobian());
145  BOOST_CHECK(!p.hasProjector());
146  };
147 
148  std::vector<size_t> exp = {i2a, i1a, i0};
149  t.visitBackwards(i2a, collect);
150  BOOST_CHECK_EQUAL_COLLECTIONS(act.begin(), act.end(), exp.begin(), exp.end());
151 
152  act.clear();
153  exp = {i2b, i1b, i0};
154  t.visitBackwards(i2b, collect);
155  BOOST_CHECK_EQUAL_COLLECTIONS(act.begin(), act.end(), exp.begin(), exp.end());
156 
157  act.clear();
158  t.applyBackwards(i2b, collect);
159  BOOST_CHECK_EQUAL_COLLECTIONS(act.begin(), act.end(), exp.begin(), exp.end());
160 }
161 
162 BOOST_AUTO_TEST_CASE(visit_apply_abort) {
164 
165  // construct trajectory with three components
166  auto i0 = t.addTrackState(make_rand_trackstate());
167  auto i1 = t.addTrackState(make_rand_trackstate(), i0);
168  auto i2 = t.addTrackState(make_rand_trackstate(), i1);
169 
170  size_t n = 0;
171  t.applyBackwards(i2, [&](const auto&) {
172  n++;
173  return false;
174  });
175  BOOST_CHECK_EQUAL(n, 1u);
176 
177  n = 0;
178  t.applyBackwards(i2, [&](const auto& ts) {
179  n++;
180  if (ts.index() == i1) {
181  return false;
182  }
183  return true;
184  });
185  BOOST_CHECK_EQUAL(n, 2u);
186 
187  n = 0;
188  t.applyBackwards(i2, [&](const auto&) {
189  n++;
190  return true;
191  });
192  BOOST_CHECK_EQUAL(n, 3u);
193 }
194 
195 BOOST_AUTO_TEST_CASE(trackstate_add_bitmask) {
196  namespace PM = TrackStatePropMask;
197  auto bs1 = PM::Uncalibrated;
198 
199  BOOST_CHECK(ACTS_CHECK_BIT(bs1, PM::Uncalibrated));
200  BOOST_CHECK(!ACTS_CHECK_BIT(bs1, PM::Calibrated));
201 
202  auto bs2 = PM::Calibrated;
203 
204  BOOST_CHECK(!ACTS_CHECK_BIT(bs2, PM::Uncalibrated));
205  BOOST_CHECK(ACTS_CHECK_BIT(bs2, PM::Calibrated));
206 
207  auto bs3 = PM::Calibrated | PM::Uncalibrated;
208 
209  BOOST_CHECK(ACTS_CHECK_BIT(bs3, PM::Uncalibrated));
210  BOOST_CHECK(ACTS_CHECK_BIT(bs3, PM::Calibrated));
211 
212  BOOST_CHECK(ACTS_CHECK_BIT(PM::All, PM::Uncalibrated));
213  BOOST_CHECK(ACTS_CHECK_BIT(PM::All, PM::Calibrated));
214 
216  BOOST_CHECK(ACTS_CHECK_BIT(bs4, PM::Predicted));
217  BOOST_CHECK(ACTS_CHECK_BIT(bs4, PM::Uncalibrated));
218  BOOST_CHECK(ACTS_CHECK_BIT(bs4, PM::Jacobian));
219  BOOST_CHECK(!ACTS_CHECK_BIT(bs4, PM::Calibrated));
220  BOOST_CHECK(!ACTS_CHECK_BIT(bs4, PM::Filtered));
221  BOOST_CHECK(!ACTS_CHECK_BIT(bs4, PM::Smoothed));
222 
224 
225  auto ts = t.getTrackState(t.addTrackState(PM::All));
226  BOOST_CHECK(ts.hasPredicted());
227  BOOST_CHECK(ts.hasFiltered());
228  BOOST_CHECK(ts.hasSmoothed());
229  BOOST_CHECK(ts.hasUncalibrated());
230  BOOST_CHECK(ts.hasCalibrated());
231  BOOST_CHECK(ts.hasProjector());
232  BOOST_CHECK(ts.hasJacobian());
233 
235  BOOST_CHECK(!ts.hasPredicted());
236  BOOST_CHECK(!ts.hasFiltered());
237  BOOST_CHECK(!ts.hasSmoothed());
238  BOOST_CHECK(!ts.hasUncalibrated());
239  BOOST_CHECK(!ts.hasCalibrated());
240  BOOST_CHECK(!ts.hasProjector());
241  BOOST_CHECK(!ts.hasJacobian());
242 
244  BOOST_CHECK(ts.hasPredicted());
245  BOOST_CHECK(!ts.hasFiltered());
246  BOOST_CHECK(!ts.hasSmoothed());
247  BOOST_CHECK(!ts.hasUncalibrated());
248  BOOST_CHECK(!ts.hasCalibrated());
249  BOOST_CHECK(!ts.hasProjector());
250  BOOST_CHECK(!ts.hasJacobian());
251 
253  BOOST_CHECK(!ts.hasPredicted());
254  BOOST_CHECK(ts.hasFiltered());
255  BOOST_CHECK(!ts.hasSmoothed());
256  BOOST_CHECK(!ts.hasUncalibrated());
257  BOOST_CHECK(!ts.hasCalibrated());
258  BOOST_CHECK(!ts.hasProjector());
259  BOOST_CHECK(!ts.hasJacobian());
260 
262  BOOST_CHECK(!ts.hasPredicted());
263  BOOST_CHECK(!ts.hasFiltered());
264  BOOST_CHECK(ts.hasSmoothed());
265  BOOST_CHECK(!ts.hasUncalibrated());
266  BOOST_CHECK(!ts.hasCalibrated());
267  BOOST_CHECK(!ts.hasProjector());
268  BOOST_CHECK(!ts.hasJacobian());
269 
271  BOOST_CHECK(!ts.hasPredicted());
272  BOOST_CHECK(!ts.hasFiltered());
273  BOOST_CHECK(!ts.hasSmoothed());
274  BOOST_CHECK(ts.hasUncalibrated());
275  BOOST_CHECK(!ts.hasCalibrated());
276  BOOST_CHECK(!ts.hasProjector());
277  BOOST_CHECK(!ts.hasJacobian());
278 
280  BOOST_CHECK(!ts.hasPredicted());
281  BOOST_CHECK(!ts.hasFiltered());
282  BOOST_CHECK(!ts.hasSmoothed());
283  BOOST_CHECK(!ts.hasUncalibrated());
284  BOOST_CHECK(ts.hasCalibrated());
285  BOOST_CHECK(ts.hasProjector());
286  BOOST_CHECK(!ts.hasJacobian());
287 
289  BOOST_CHECK(!ts.hasPredicted());
290  BOOST_CHECK(!ts.hasFiltered());
291  BOOST_CHECK(!ts.hasSmoothed());
292  BOOST_CHECK(!ts.hasUncalibrated());
293  BOOST_CHECK(!ts.hasCalibrated());
294  BOOST_CHECK(!ts.hasProjector());
295  BOOST_CHECK(ts.hasJacobian());
296 }
297 
298 BOOST_AUTO_TEST_CASE(trackstate_proxy_cross_talk) {
299  // assert expected "cross-talk" between trackstate proxies
300  auto [ots, fm, meas] = make_trackstate();
301 
303 
304  t.addTrackState(ots);
305 
306  const auto& ct = t;
307  auto cts = ct.getTrackState(0);
308  auto ts = t.getTrackState(0);
309 
310  // assert expected value of chi2 and path length
311  BOOST_CHECK_EQUAL(cts.chi2(), 78u);
312  BOOST_CHECK_EQUAL(ts.chi2(), 78u);
313  BOOST_CHECK_EQUAL(cts.pathLength(), 42u);
314  BOOST_CHECK_EQUAL(ts.pathLength(), 42u);
315 
316  ParVec_t v;
317  CovMat_t cov;
318 
319  v.setRandom();
320  ts.predicted() = v;
321  BOOST_CHECK_EQUAL(cts.predicted(), v);
322  cov.setRandom();
323  ts.predictedCovariance() = cov;
324  BOOST_CHECK_EQUAL(cts.predictedCovariance(), cov);
325 
326  v.setRandom();
327  ts.filtered() = v;
328  BOOST_CHECK_EQUAL(cts.filtered(), v);
329  cov.setRandom();
330  ts.filteredCovariance() = cov;
331  BOOST_CHECK_EQUAL(cts.filteredCovariance(), cov);
332 
333  v.setRandom();
334  ts.smoothed() = v;
335  BOOST_CHECK_EQUAL(cts.smoothed(), v);
336  cov.setRandom();
337  ts.smoothedCovariance() = cov;
338  BOOST_CHECK_EQUAL(cts.smoothedCovariance(), cov);
339 
340  // make copy of fm
341  auto fm2 = std::make_unique<FittableMeasurement<SourceLink>>(*fm);
342  SourceLink sl2{fm2.get()};
343  ts.uncalibrated() = sl2;
344  BOOST_CHECK_EQUAL(cts.uncalibrated(), sl2);
345  BOOST_CHECK_NE(cts.uncalibrated(), SourceLink{fm.get()});
346 
347  CovMat_t newMeasCov;
348  newMeasCov.setRandom();
349  ts.calibratedCovariance() = newMeasCov;
350  BOOST_CHECK_EQUAL(cts.calibratedCovariance(), newMeasCov);
351 
352  ParVec_t newMeasPar;
353  newMeasPar.setRandom();
354  ts.calibrated() = newMeasPar;
355  BOOST_CHECK_EQUAL(cts.calibrated(), newMeasPar);
356 
357  size_t measdim = ts.effectiveCalibrated().rows();
358 
359  ActsMatrixXd eff{measdim, measdim};
360  eff.setRandom();
361  ts.effectiveCalibratedCovariance() = eff;
362  BOOST_CHECK_EQUAL(cts.effectiveCalibratedCovariance(), eff);
363  newMeasCov.topLeftCorner(eff.rows(), eff.rows()) = eff;
364  BOOST_CHECK_EQUAL(cts.calibratedCovariance(), newMeasCov);
365 
366  CovMat_t jac;
367  jac.setRandom();
368  ts.jacobian() = jac;
369  BOOST_CHECK_EQUAL(cts.jacobian(), jac);
370 
371  ts.chi2() = 98;
372  BOOST_CHECK_EQUAL(cts.chi2(), 98u);
373 
374  ts.pathLength() = 66;
375  BOOST_CHECK_EQUAL(cts.pathLength(), 66u);
376 }
377 
378 BOOST_AUTO_TEST_CASE(trackstate_reassignment) {
379  auto [ots, fm, meas] = make_trackstate();
380 
381  constexpr size_t maxmeasdim = MultiTrajectory<SourceLink>::MeasurementSizeMax;
382 
384  t.addTrackState(ots);
385 
386  auto ts = t.getTrackState(0);
387 
388  // assert measdim and contents of original measurement (just to be safe)
389  BOOST_CHECK_EQUAL(ts.calibratedSize(), meas.size());
390  BOOST_CHECK_EQUAL(ts.effectiveCalibrated(), meas.parameters());
391  BOOST_CHECK_EQUAL(ts.effectiveCalibratedCovariance(), meas.covariance());
392  BOOST_CHECK_EQUAL(ts.effectiveProjector(), meas.projector());
393 
394  // create new measurement
395  ActsSymMatrixD<2> mCov;
396  mCov.setRandom();
397  ActsVectorD<2> mPar;
398  mPar.setRandom();
400  meas.referenceSurface().getSharedPtr(), {}, mCov, mPar[0], mPar[1]};
401 
402  ts.setCalibrated(m2);
403 
404  BOOST_CHECK_EQUAL(ts.calibratedSize(), 2u);
405  BOOST_CHECK_EQUAL(ts.effectiveCalibrated(), mPar);
406  BOOST_CHECK_EQUAL(ts.effectiveCalibratedCovariance(), mCov);
407  BOOST_CHECK_EQUAL(ts.effectiveProjector(), m2.projector());
408 
409  // check if overallocated part is zeroed correctly
410  ActsVectorD<maxmeasdim> mParFull;
411  mParFull.setZero();
412  mParFull.head(2) = mPar;
413  BOOST_CHECK_EQUAL(ts.calibrated(), mParFull);
414 
416  mCovFull.setZero();
417  mCovFull.topLeftCorner(2, 2) = mCov;
418  BOOST_CHECK_EQUAL(ts.calibratedCovariance(), mCovFull);
419 
421  projFull.setZero();
422  projFull.topLeftCorner(m2.size(), maxmeasdim) = m2.projector();
423  BOOST_CHECK_EQUAL(ts.projector(), projFull);
424 }
425 
426 BOOST_AUTO_TEST_CASE(storage_consistency) {
428 
429  auto [ts, fm, om] = make_trackstate();
430 
431  // now put it into the collection
432  t.addTrackState(ts);
433 
434  // now investigate the proxy
435  auto tsProxy = t.getTrackState(0);
436 
437  // parameters
438  BOOST_CHECK(tsProxy.hasPredicted());
439  BOOST_CHECK_EQUAL(ts.parameter.predicted->parameters(), tsProxy.predicted());
440  BOOST_CHECK_EQUAL(*ts.parameter.predicted->covariance(),
441  tsProxy.predictedCovariance());
442 
443  BOOST_CHECK(tsProxy.hasFiltered());
444  BOOST_CHECK_EQUAL(ts.parameter.filtered->parameters(), tsProxy.filtered());
445  BOOST_CHECK_EQUAL(*ts.parameter.filtered->covariance(),
446  tsProxy.filteredCovariance());
447 
448  BOOST_CHECK(tsProxy.hasSmoothed());
449  BOOST_CHECK_EQUAL(ts.parameter.smoothed->parameters(), tsProxy.smoothed());
450  BOOST_CHECK_EQUAL(*ts.parameter.smoothed->covariance(),
451  tsProxy.smoothedCovariance());
452 
453  BOOST_CHECK_EQUAL(&tsProxy.referenceSurface(), &ts.referenceSurface());
454 
455  BOOST_CHECK(tsProxy.hasJacobian());
456  BOOST_CHECK_EQUAL(tsProxy.jacobian(), *ts.parameter.jacobian);
457 
458  BOOST_CHECK(tsProxy.hasProjector());
459  std::visit(
460  [&](const auto& meas) {
461  BOOST_CHECK_EQUAL(tsProxy.effectiveProjector(), meas.projector());
462  // measurement properties
463  BOOST_CHECK(tsProxy.hasCalibrated());
464  BOOST_CHECK_EQUAL(meas.parameters(), tsProxy.effectiveCalibrated());
465  ParVec_t mParFull;
466  mParFull.setZero();
467  mParFull.head(meas.size()) = meas.parameters();
468  BOOST_CHECK_EQUAL(mParFull, tsProxy.calibrated());
469 
470  BOOST_CHECK_EQUAL(meas.covariance(),
471  tsProxy.effectiveCalibratedCovariance());
472  CovMat_t mCovFull;
473  mCovFull.setZero();
474  mCovFull.topLeftCorner(meas.size(), meas.size()) = meas.covariance();
475  BOOST_CHECK_EQUAL(mCovFull, tsProxy.calibratedCovariance());
476 
477  // calibrated links to original measurement
478  BOOST_CHECK_EQUAL(meas.sourceLink(), tsProxy.calibratedSourceLink());
479 
480  // uncalibrated **is** a SourceLink
481  BOOST_CHECK(tsProxy.hasUncalibrated());
482  BOOST_CHECK_EQUAL(meas.sourceLink(), tsProxy.uncalibrated());
483 
484  // full projector, should be exactly equal
485  CovMat_t fullProj;
486  fullProj.setZero();
487  fullProj.topLeftCorner(
489  meas.projector();
490  BOOST_CHECK_EQUAL(tsProxy.projector(), fullProj);
491 
492  // projector with dynamic rows
493  // should be exactly equal
494  BOOST_CHECK_EQUAL(tsProxy.effectiveProjector(), meas.projector());
495  },
496  *ts.measurement.calibrated);
497 }
498 
499 } // namespace Test
500 
501 } // namespace Acts