9 #include <boost/test/unit_test.hpp>
42 #include <boost/math/distributions/chi_squared.hpp>
44 using namespace Acts::UnitLiterals;
54 using Resolution = std::pair<BoundIndices, double>;
56 using VolumeResolution = std::map<GeometryIdentifier::Value, ElementResolution>;
58 std::map<GeometryIdentifier::Value, VolumeResolution>;
60 std::normal_distribution<double>
gauss(0., 1.);
63 ActsSymMatrixD<1>
cov1D;
77 struct MeasurementCreator {
79 MeasurementCreator() =
default;
89 std::vector<FittableMeasurement<SourceLink>>
outliers;
101 template <
typename propagator_state_t,
typename stepper_t>
102 void operator()(propagator_state_t& state,
const stepper_t&
stepper,
105 auto surface = state.navigation.currentSurface;
107 auto geoID =
surface->geometryId();
108 auto volumeID = geoID.volume();
109 auto layerID = geoID.layer();
111 auto vResolution = detectorResolution.find(volumeID);
112 if (vResolution != detectorResolution.end()) {
114 auto lResolution = vResolution->second.find(layerID);
115 if (lResolution != vResolution->second.end()) {
119 ->globalToLocal(state.geoContext,
120 stepper.position(state.stepping),
121 stepper.direction(state.stepping))
124 if (lResolution->second.size() == 1) {
125 double sp = lResolution->second[0].second;
128 if (lResolution->second[0].first ==
eBoundLoc0) {
132 result.measurements.push_back(std::move(m0));
136 result.outliers.push_back(std::move(o0));
141 result.measurements.push_back(std::move(m1));
145 result.outliers.push_back(std::move(o1));
147 }
else if (lResolution->second.size() == 2) {
149 double sx = lResolution->second[
eBoundLoc0].second;
150 double sy = lResolution->second[
eBoundLoc1].second;
151 cov2D << sx * sx, 0., 0., sy * sy;
158 result.measurements.push_back(std::move(m01));
163 result.outliers.push_back(std::move(o01));
191 template <
typename propagator_state_t,
typename stepper_t>
194 if (state.navigation.currentSurface &&
195 state.navigation.currentSurface->surfaceMaterial() &&
196 state.stepping.cov != Covariance::Zero()) {
198 std::normal_distribution<double> scatterAngle(
207 auto direction = stepper.direction(state.stepping);
208 double theta = std::acos(direction.z());
209 double phi = std::atan2(direction.y(), direction.x());
211 state.stepping.update(
212 stepper.position(state.stepping),
213 {std::sin(theta + dTheta) *
std::cos(phi + dPhi),
214 std::sin(theta + dTheta) * std::sin(phi + dPhi),
216 std::max(stepper.momentum(state.stepping) -
225 double measurementSignificanceCutoff = 0;
227 double chi2Tolerance = 10
e-5;
236 template <
typename track_state_t>
240 if (not state.hasCalibrated() or not state.hasPredicted()) {
245 const auto& predicted = state.predicted();
247 const auto& predicted_covariance = state.predictedCovariance();
252 state.calibrated(), state.calibratedCovariance(),
253 state.calibratedSize(),
254 [&](
const auto calibrated,
const auto calibrated_covariance) {
255 constexpr
size_t measdim = decltype(calibrated)::RowsAtCompileTime;
260 state.projector().template topLeftCorner<measdim, eBoundSize>();
263 const par_t residual = calibrated - H * predicted;
266 chi2 = (residual.transpose() *
267 ((calibrated_covariance +
268 H * predicted_covariance * H.transpose()))
275 if (
std::abs(chi2) < chi2Tolerance) {
279 boost::math::chi_squared chiDist(state.calibratedSize());
281 double pValue = 1 - boost::math::cdf(chiDist, chi2);
283 return pValue > measurementSignificanceCutoff ?
false :
true;
308 MeasurementPropagator mPropagator(mStepper, mNavigator);
309 Vector4D mPos4(-3_m, 0., 0., 42_ns);
327 pixelVolumeRes[2] = pixelElementRes;
328 pixelVolumeRes[4] = pixelElementRes;
331 stripVolumeRes[2] = stripElementResI;
332 stripVolumeRes[4] = stripElementResO;
333 stripVolumeRes[6] = stripElementResI;
334 stripVolumeRes[8] = stripElementResO;
337 detRes[2] = pixelVolumeRes;
338 detRes[3] = stripVolumeRes;
347 auto mResult = mPropagator.propagate(mStart, mOptions).value();
351 std::vector<FittableMeasurement<SourceLink>> measurements = std::move(
352 mResult.template get<MeasurementCreator::result_type>().measurements);
353 BOOST_CHECK_EQUAL(measurements.size(), 6
u);
356 std::vector<SourceLink> sourcelinks;
358 std::back_inserter(sourcelinks),
364 rNavigator.resolvePassive =
false;
365 rNavigator.resolveMaterial =
true;
366 rNavigator.resolveSensitive =
true;
371 RecoStepper rStepper(bField);
373 RecoPropagator rPropagator(rStepper, rNavigator);
377 cov << 1000_um, 0., 0., 0., 0., 0., 0., 1000_um, 0., 0., 0., 0., 0., 0., 0.05,
378 0., 0., 0., 0., 0., 0., 0.05, 0., 0., 0., 0., 0., 0., 0.01, 0., 0., 0.,
404 auto fitRes = kFitter.fit(sourcelinks, rStart, kfOptions);
405 BOOST_CHECK(fitRes.ok());
406 auto& fittedTrack = *fitRes;
407 auto fittedParameters = fittedTrack.fittedParameters.value();
410 const auto& [trackParamsCov, stateRowIndices] =
412 fittedTrack.trackTip);
415 BOOST_CHECK_EQUAL(stateRowIndices.size(), 6);
416 BOOST_CHECK_EQUAL(stateRowIndices.at(fittedTrack.trackTip), 30);
417 BOOST_CHECK_EQUAL(trackParamsCov.rows(), 6 *
eBoundSize);
420 fitRes = kFitter.fit(sourcelinks, rStart, kfOptions);
421 BOOST_CHECK(fitRes.ok());
422 auto& fittedAgainTrack = *fitRes;
423 auto fittedAgainParameters = fittedAgainTrack.fittedParameters.value();
426 fittedAgainParameters.parameters().template head<5>(), 1
e-5);
428 fittedAgainParameters.parameters().template tail<1>(), 1
e-5);
431 kfOptions.referenceSurface =
nullptr;
432 fitRes = kFitter.fit(sourcelinks, rStart, kfOptions);
433 BOOST_CHECK(fitRes.ok());
434 auto fittedWithoutTargetSurface = *fitRes;
436 BOOST_CHECK(fittedWithoutTargetSurface.fittedParameters == std::nullopt);
439 kfOptions.referenceSurface = rSurface;
442 std::vector<SourceLink> shuffledMeasurements = {
443 sourcelinks[3], sourcelinks[2], sourcelinks[1],
444 sourcelinks[4], sourcelinks[5], sourcelinks[0]};
447 fitRes = kFitter.fit(shuffledMeasurements, rStart, kfOptions);
448 BOOST_CHECK(fitRes.ok());
449 auto& fittedShuffledTrack = *fitRes;
450 auto fittedShuffledParameters = fittedShuffledTrack.fittedParameters.value();
453 fittedShuffledParameters.parameters().template head<5>(),
456 fittedShuffledParameters.parameters().template tail<1>(),
460 std::vector<SourceLink> measurementsWithHole = {
461 sourcelinks[0], sourcelinks[1], sourcelinks[2], sourcelinks[4],
465 fitRes = kFitter.fit(measurementsWithHole, rStart, kfOptions);
466 BOOST_CHECK(fitRes.ok());
467 auto& fittedWithHoleTrack = *fitRes;
468 auto fittedWithHoleParameters = fittedWithHoleTrack.fittedParameters.value();
471 const auto& [holeTrackTrackParamsCov, holeTrackStateRowIndices] =
473 fittedWithHoleTrack.trackTip);
476 BOOST_CHECK_EQUAL(holeTrackStateRowIndices.size(), 6);
477 BOOST_CHECK_EQUAL(holeTrackStateRowIndices.at(fittedWithHoleTrack.trackTip),
479 BOOST_CHECK_EQUAL(holeTrackTrackParamsCov.rows(), 6 *
eBoundSize);
482 BOOST_CHECK_EQUAL(fittedWithHoleTrack.missedActiveSurfaces.size(), 1
u);
489 fittedWithHoleParameters.parameters(),
493 kfOptions.backwardFiltering =
true;
495 fitRes = kFitter.fit(sourcelinks, rStart, kfOptions);
496 BOOST_CHECK(fitRes.ok());
497 auto fittedWithBwdFiltering = *fitRes;
499 BOOST_CHECK(fittedWithBwdFiltering.forwardFiltered);
500 BOOST_CHECK(not fittedWithBwdFiltering.smoothed);
503 auto trackTip = fittedWithBwdFiltering.trackTip;
504 auto mj = fittedWithBwdFiltering.fittedStates;
505 size_t nSmoothed = 0;
506 mj.visitBackwards(trackTip, [&](
const auto& state) {
507 if (state.hasSmoothed())
510 BOOST_CHECK_EQUAL(nSmoothed, 6
u);
513 kfOptions.backwardFiltering =
false;
517 std::vector<FittableMeasurement<SourceLink>> outliers = std::move(
518 mResult.template get<MeasurementCreator::result_type>().outliers);
521 std::vector<SourceLink> measurementsWithOneOutlier = {
522 sourcelinks[0], sourcelinks[1], sourcelinks[2],
523 SourceLink{&outliers[3]}, sourcelinks[4], sourcelinks[5]};
526 fitRes = kFitter.fit(measurementsWithOneOutlier, rStart, kfOptions);
527 BOOST_CHECK(fitRes.ok());
528 auto& fittedWithOneOutlier = *fitRes;
531 trackTip = fittedWithOneOutlier.trackTip;
532 mj = fittedWithOneOutlier.fittedStates;
533 size_t nOutliers = 0;
534 mj.visitBackwards(trackTip, [&](
const auto& state) {
535 auto typeFlags = state.typeFlags();
540 BOOST_CHECK_EQUAL(nOutliers, 1
u);