acts-project / acts

Experiment-independent toolkit for (charged) particle track reconstruction in (high energy) physics experiments implemented in modern C++
https://acts.readthedocs.io
Mozilla Public License 2.0
104 stars 167 forks source link

bug: navigation suggests `pathCorrection=inf` on cylinderSurface #3267

Open AJPfleger opened 4 months ago

AJPfleger commented 4 months ago

Issue

We might encounter a FPEDIV in the path correction of the cylinder surface. This could happen when we end up parallel to the cylinder.

https://github.com/acts-project/acts/blob/dc1a1d35f97d60d90a51ef3255501cf41b115bcd/Core/src/Surfaces/CylinderSurface.cpp#L164

Stacktrace

15:26:16    Sequencer      INFO      -----------------------------------
15:26:16    Sequencer      INFO      FPE summary for Algorithm: TrackFittingAlgorithm
15:26:16    Sequencer      INFO      -----------------------------------
15:26:16    Sequencer      INFO      - FLTDIV: (3 times) 
 0# Acts::CylinderSurface::pathCorrection(Acts::ContextType const&, Eigen::Matrix<double, 3, 1, 0, 3, 1> const&, Eigen::Matrix<double, 3, 1, 0, 3, 1> const&) const at /builds/acts/ci-bridge/src/Core/src/Surfaces/CylinderSurface.cpp:174
 1# Acts::Layer::compatibleSurfaces(Acts::ContextType const&, Eigen::Matrix<double, 3, 1, 0, 3, 1> const&, Eigen::Matrix<double, 3, 1, 0, 3, 1> const&, Acts::NavigationOptions<Acts::Surface> const&) const at /builds/acts/ci-bridge/src/Core/src/Geometry/Layer.cpp:151
 2# bool Acts::Navigator::resolveSurfaces<Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer>, Acts::Navigator>::State<Acts::PropagatorOptions<Acts::ActionList<Acts::Experimental::Gx2Fitter<Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer>, Acts::Navigator>, Acts::VectorMultiTrajectory>::Actor<Acts::GenericBoundTrackParameters<Acts::ParticleHypothesis> > >, Acts::AbortList<Acts::Experimental::Gx2Fitter<Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer>, Acts::Navigator>, Acts::VectorMultiTrajectory>::Aborter<Acts::GenericBoundTrackParameters<Acts::ParticleHypothesis> >, Acts::PathLimitReached> >, Acts::Experimental::Gx2FitterResult<Acts::VectorMultiTrajectory> >, Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer> >(Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer>, Acts::Navigator>::State<Acts::PropagatorOptions<Acts::ActionList<Acts::Experimental::Gx2Fitter<Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer>, Acts::Navigator>, Acts::VectorMultiTrajectory>::Actor<Acts::GenericBoundTrackParameters<Acts::ParticleHypothesis> > >, Acts::AbortList<Acts::Experimental::Gx2Fitter<Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer>, Acts::Navigator>, Acts::VectorMultiTrajectory>::Aborter<Acts::GenericBoundTrackParameters<Acts::ParticleHypothesis> >, Acts::PathLimitReached> >, Acts::Experimental::Gx2FitterResult<Acts::VectorMultiTrajectory> >&, Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer> const&) const [clone .isra.0] at /builds/acts/ci-bridge/src/Core/include/Acts/Propagator/Navigator.hpp:1055
 3# void Acts::Navigator::preStep<Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer>, Acts::Navigator>::State<Acts::PropagatorOptions<Acts::ActionList<Acts::Experimental::Gx2Fitter<Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer>, Acts::Navigator>, Acts::VectorMultiTrajectory>::Actor<Acts::GenericBoundTrackParameters<Acts::ParticleHypothesis> > >, Acts::AbortList<Acts::Experimental::Gx2Fitter<Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer>, Acts::Navigator>, Acts::VectorMultiTrajectory>::Aborter<Acts::GenericBoundTrackParameters<Acts::ParticleHypothesis> >, Acts::PathLimitReached> >, Acts::Experimental::Gx2FitterResult<Acts::VectorMultiTrajectory> >, Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer> >(Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer>, Acts::Navigator>::State<Acts::PropagatorOptions<Acts::ActionList<Acts::Experimental::Gx2Fitter<Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer>, Acts::Navigator>, Acts::VectorMultiTrajectory>::Actor<Acts::GenericBoundTrackParameters<Acts::ParticleHypothesis> > >, Acts::AbortList<Acts::Experimental::Gx2Fitter<Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer>, Acts::Navigator>, Acts::VectorMultiTrajectory>::Aborter<Acts::GenericBoundTrackParameters<Acts::ParticleHypothesis> >, Acts::PathLimitReached> >, Acts::Experimental::Gx2FitterResult<Acts::VectorMultiTrajectory> >&, Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer> const&) const at /builds/acts/ci-bridge/src/Core/include/Acts/Propagator/Navigator.hpp:356
 4# Acts::Result<void, std::error_code> Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer>, Acts::Navigator>::propagate<Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer>, Acts::Navigator>::State<Acts::PropagatorOptions<Acts::ActionList<Acts::Experimental::Gx2Fitter<Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer>, Acts::Navigator>, Acts::VectorMultiTrajectory>::Actor<Acts::GenericBoundTrackParameters<Acts::ParticleHypothesis> > >, Acts::AbortList<Acts::Experimental::Gx2Fitter<Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer>, Acts::Navigator>, Acts::VectorMultiTrajectory>::Aborter<Acts::GenericBoundTrackParameters<Acts::ParticleHypothesis> >, Acts::PathLimitReached> >, Acts::Experimental::Gx2FitterResult<Acts::VectorMultiTrajectory> > >(Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer>, Acts::Navigator>::State<Acts::PropagatorOptions<Acts::ActionList<Acts::Experimental::Gx2Fitter<Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer>, Acts::Navigator>, Acts::VectorMultiTrajectory>::Actor<Acts::GenericBoundTrackParameters<Acts::ParticleHypothesis> > >, Acts::AbortList<Acts::Experimental::Gx2Fitter<Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer>, Acts::Navigator>, Acts::VectorMultiTrajectory>::Aborter<Acts::GenericBoundTrackParameters<Acts::ParticleHypothesis> >, Acts::PathLimitReached> >, Acts::Experimental::Gx2FitterResult<Acts::VectorMultiTrajectory> >&) const at /builds/acts/ci-bridge/src/Core/include/Acts/Propagator/Propagator.ipp:48
 5# std::enable_if<!(false), Acts::Result<Acts::TrackContainer<Acts::VectorTrackContainer, Acts::VectorMultiTrajectory, std::shared_ptr>::TrackProxy, std::error_code> >::type Acts::Experimental::Gx2Fitter<Acts::Propagator<Acts::EigenStepper<Acts::StepperExtensionList<Acts::DefaultExtension>, Acts::detail::VoidAuctioneer>, Acts::Navigator>, Acts::VectorMultiTrajectory>::fit<__gnu_cxx::__normal_iterator<Acts::SourceLink const*, std::vector<Acts::SourceLink, std::allocator<Acts::SourceLink> > >, Acts::GenericBoundTrackParameters<Acts::ParticleHypothesis>, Acts::GenericBoundTrackParameters<Acts::ParticleHypothesis>, Acts::VectorTrackContainer, std::shared_ptr, false>(__gnu_cxx::__normal_iterator<Acts::SourceLink const*, std::vector<Acts::SourceLink, std::allocator<Acts::SourceLink> > >, __gnu_cxx::__normal_iterator<Acts::SourceLink const*, std::vector<Acts::SourceLink, std::allocator<Acts::SourceLink> > >, Acts::GenericBoundTrackParameters<Acts::ParticleHypothesis> const&, Acts::Experimental::Gx2FitterOptions<Acts::VectorMultiTrajectory> const&, Acts::TrackContainer<Acts::VectorTrackContainer, Acts::VectorMultiTrajectory, std::shared_ptr>&) const at /builds/acts/ci-bridge/src/Core/include/Acts/TrackFitting/GlobalChiSquareFitter.hpp:789
 6# (anonymous namespace)::GlobalChiSquareFitterFunctionImpl::operator()(std::vector<Acts::SourceLink, std::allocator<Acts::SourceLink> > const&, Acts::GenericBoundTrackParameters<Acts::ParticleHypothesis> const&, ActsExamples::TrackFitterFunction::GeneralFitterOptions const&, ActsExamples::MeasurementCalibratorAdapter const&, Acts::TrackContainer<Acts::VectorTrackContainer, Acts::VectorMultiTrajectory, std::shared_ptr>&) const at /builds/acts/ci-bridge/src/Examples/Algorithms/TrackFitting/src/GlobalChiSquareFitterFunction.cpp:110
 7# ActsExamples::TrackFittingAlgorithm::execute(ActsExamples::AlgorithmContext const&) const at /builds/acts/ci-bridge/src/Examples/Algorithms/TrackFitting/src/TrackFittingAlgorithm.cpp:148

Reproduce

Running truth_tracking_gx2f.py with 2.5 < |eta| < 3.0 can result in the above behaviour. When it happens, the gx2f pushed the updated parameters so far, that the first encountered surface is Pixels::Barrel instead of BeamPipe::Barrel:

oldChi2sum = 153.944
chi2sum = 1184.32
13:26:57    Gx2fFitter     DEBUG     chi2 not converging monotonically
13:26:57    Gx2fFitter     VERBOSE   nUpdate = 4/17
13:26:57    Gx2fFitter     VERBOSE   updated params:
loc0:      -31.48 +- 1            1.000
loc1:       10.62 +- 1            0.000  1.000
phi:       -2.856 +- 0.01745      0.000  0.000  1.000
theta:     0.1068 +- 0.01745      0.000  0.000  0.000  1.000
q/p:       0.1268 +- 0.1          0.000  0.000  0.000  0.000  1.000
time:      -239.7 +- 299.8        0.000  0.000  0.000  0.000  0.000  1.000
on surface undefined of type Acts::PerigeeSurface
13:26:57    Gx2fNavigato   VERBOSE   No Volume | Initialization.
13:26:57    Gx2fNavigato   VERBOSE   No Volume | Current surface set to start surface undefined
13:26:57    Gx2fNavigato   VERBOSE   No Volume | Slow start initialization through search.
13:26:57    Gx2fNavigato   VERBOSE   No Volume | Starting from position (-8.8604, 30.2046, 10.6162) and direction (-0.1023, -0.0300, 0.9943)
13:26:57    Gx2fNavigato   VERBOSE   No Volume | Start volume resolved.
13:26:57    Gx2fPropagat   VERBOSE   Path aborter limit set to 41316.4 (full helix = 82632.8, previous limit = 1.79769e+308)
13:26:57    Gx2fPropagat   VERBOSE   Entering propagation.
13:26:57    Gx2fFitterAc   VERBOSE   Surface undefined detected.
13:26:57    Gx2fFitterAc   INFO      Actor: This case is not implemented yet
13:26:57    Gx2fFitterAc   DEBUG     result.processedMeasurements: 0
inputMeasurements.size()13
13:26:57    Gx2fPropagat   VERBOSE   PathLimit aborter | Target stepSize (path limit) updated to ( +∞,  +∞, 41316.4,  +∞)
13:26:57    Gx2fPropagat   VERBOSE   Starting stepping loop.
13:26:57    Gx2fNavigato   VERBOSE   Pixels::Barrel | Entering navigator::preStep.
13:26:57    Gx2fNavigato   VERBOSE   Pixels::Barrel | Start layer to be resolved.
cosAlpha: 0

However, we can also find sometimes values, that are just close to zero:

oldChi2sum = 1184.32
chi2sum = 4.08138
13:26:57    Gx2fFitter     VERBOSE   nUpdate = 5/17
13:26:57    Gx2fFitter     VERBOSE   updated params:
loc0:      -31.08 +- 1            1.000
loc1:       9.863 +- 1            0.000  1.000
phi:       -2.859 +- 0.01745      0.000  0.000  1.000
theta:     0.1068 +- 0.01745      0.000  0.000  0.000  1.000
q/p:       0.1254 +- 0.1          0.000  0.000  0.000  0.000  1.000
time:      -239.7 +- 299.8        0.000  0.000  0.000  0.000  0.000  1.000
on surface undefined of type Acts::PerigeeSurface
13:26:57    Gx2fNavigato   VERBOSE   No Volume | Initialization.
13:26:57    Gx2fNavigato   VERBOSE   No Volume | Current surface set to start surface undefined
13:26:57    Gx2fNavigato   VERBOSE   No Volume | Slow start initialization through search.
13:26:57    Gx2fNavigato   VERBOSE   No Volume | Starting from position (-8.6749, 29.8417, 9.8631) and direction (-0.1024, -0.0298, 0.9943)
13:26:57    Gx2fNavigato   VERBOSE   No Volume | Start volume resolved.
13:26:57    Gx2fPropagat   VERBOSE   Path aborter limit set to 41791.9 (full helix = 83583.9, previous limit = 1.79769e+308)
13:26:57    Gx2fPropagat   VERBOSE   Entering propagation.
13:26:57    Gx2fFitterAc   VERBOSE   Surface undefined detected.
13:26:57    Gx2fFitterAc   INFO      Actor: This case is not implemented yet
13:26:57    Gx2fFitterAc   DEBUG     result.processedMeasurements: 0
inputMeasurements.size()13
13:26:57    Gx2fPropagat   VERBOSE   PathLimit aborter | Target stepSize (path limit) updated to ( +∞,  +∞, 41791.9,  +∞)
13:26:57    Gx2fPropagat   VERBOSE   Starting stepping loop.
13:26:57    Gx2fNavigato   VERBOSE   Pixels::Barrel | Entering navigator::preStep.
13:26:57    Gx2fNavigato   VERBOSE   Pixels::Barrel | Start layer to be resolved.
cosAlpha: 3.46945e-18

Solution

There have been a few attempts to solve this issue:

In the end, we decided not to treat the symptoms, but rather find the underlying issue.

Since it only occurred for the GX2F, this issue might solve itself during further development. However, I don't see it as the GX2F's responsible to check if the navigation will work with newly suggested parameters.

andiwand commented 4 months ago
13:26:57    Gx2fFitter     VERBOSE   updated params:
loc0:      -31.48 +- 1            1.000
loc1:       10.62 +- 1            0.000  1.000
phi:       -2.856 +- 0.01745      0.000  0.000  1.000
theta:     0.1068 +- 0.01745      0.000  0.000  0.000  1.000
q/p:       0.1268 +- 0.1          0.000  0.000  0.000  0.000  1.000
time:      -239.7 +- 299.8        0.000  0.000  0.000  0.000  0.000  1.000

This suggests that the fitter is unstable for certain inputs / scenarios. I would argue that the navigation is supposed to break in this scenario.

Note that eta for these parameters is almost 3 which is at the edge of what the ODD can handle usually.

I also quickly checked the input vectors and they are practically orthogonal in XY.

In [8]: p = np.array([-8.8604, 30.2046, 10.6162])
In [9]: p[:2] / np.linalg.norm(p[:2])
Out[9]: array([-0.2814848 ,  0.95956569])
In [10]: d = np.array([-0.1023, -0.0300, 0.9943])
In [11]: d[:2] / np.linalg.norm(d[:2])
Out[11]: array([-0.95958925, -0.28140447])

All in all I would argue that this is not a bug of the navigation but a bug of the fitter as the start parameters for the propagation are unphysical for what it is trying to fit.

github-actions[bot] commented 3 months ago

This issue/PR has been automatically marked as stale because it has not had recent activity. The stale label will be removed if any interaction occurs.

AJPfleger commented 2 months ago

3411 does not solve the underlying issue but rather avoids getting there in the first place. I would keep it open for now.

github-actions[bot] commented 1 month ago

This issue/PR has been automatically marked as stale because it has not had recent activity. The stale label will be removed if any interaction occurs.

github-actions[bot] commented 1 week ago

This issue/PR has been automatically marked as stale because it has not had recent activity. The stale label will be removed if any interaction occurs.