diff --git a/core/CMakeLists.txt b/core/CMakeLists.txt index d2d2af375..6f7a79264 100644 --- a/core/CMakeLists.txt +++ b/core/CMakeLists.txt @@ -74,6 +74,7 @@ traccc_add_library( traccc_core core TYPE SHARED "include/traccc/fitting/kalman_filter/kalman_fitter.hpp" "include/traccc/fitting/kalman_filter/kalman_step_aborter.hpp" "include/traccc/fitting/kalman_filter/statistics_updater.hpp" + "include/traccc/fitting/kalman_filter/two_filters_smoother.hpp" "include/traccc/fitting/details/fit_tracks.hpp" "include/traccc/fitting/kalman_fitting_algorithm.hpp" "src/fitting/kalman_fitting_algorithm.cpp" diff --git a/core/include/traccc/edm/track_parameters.hpp b/core/include/traccc/edm/track_parameters.hpp index 4b62da294..a2d0e00cb 100644 --- a/core/include/traccc/edm/track_parameters.hpp +++ b/core/include/traccc/edm/track_parameters.hpp @@ -48,4 +48,20 @@ inline void wrap_phi(bound_track_parameters& param) { param.set_phi(phi); } +// Covariance inflation used for track fitting +TRACCC_HOST_DEVICE +inline void inflate_covariance(bound_track_parameters& param, + const traccc::scalar inf_fac) { + auto& cov = param.covariance(); + for (unsigned int i = 0; i < e_bound_size; i++) { + for (unsigned int j = 0; j < e_bound_size; j++) { + if (i == j) { + getter::element(cov, i, i) *= inf_fac; + } else { + getter::element(cov, i, j) = 0.f; + } + } + } +} + } // namespace traccc diff --git a/core/include/traccc/edm/track_state.hpp b/core/include/traccc/edm/track_state.hpp index b46ef96c6..da253abff 100644 --- a/core/include/traccc/edm/track_state.hpp +++ b/core/include/traccc/edm/track_state.hpp @@ -37,6 +37,14 @@ struct fitting_result { // The number of holes (The number of sensitive surfaces which do not have a // measurement for the track pattern) unsigned int n_holes{0u}; + + // Reset the statistics + TRACCC_HOST_DEVICE + void reset_statistics() { + ndf = 0.f; + chi2 = 0.f; + n_holes = 0u; + } }; /// Fitting result per measurement @@ -160,6 +168,14 @@ struct track_state { TRACCC_HOST_DEVICE inline const scalar_type& filtered_chi2() const { return m_filtered_chi2; } + /// @return the non-const chi square of backward filter + TRACCC_HOST_DEVICE + inline scalar_type& backward_chi2() { return m_backward_chi2; } + + /// @return the const chi square of backward filter + TRACCC_HOST_DEVICE + inline const scalar_type& backward_chi2() const { return m_backward_chi2; } + /// @return the non-const filtered parameter TRACCC_HOST_DEVICE inline bound_track_parameters_type& filtered() { return m_filtered; } @@ -200,6 +216,7 @@ struct track_state { bound_track_parameters_type m_filtered; scalar_type m_smoothed_chi2 = 0.f; bound_track_parameters_type m_smoothed; + scalar_type m_backward_chi2 = 0.f; }; /// Declare all track_state collection types diff --git a/core/include/traccc/fitting/fitting_config.hpp b/core/include/traccc/fitting/fitting_config.hpp index 8aeac323a..a5040b023 100644 --- a/core/include/traccc/fitting/fitting_config.hpp +++ b/core/include/traccc/fitting/fitting_config.hpp @@ -25,6 +25,10 @@ struct fitting_config { /// Particle hypothesis detray::pdg_particle ptc_hypothesis = detray::muon(); + + /// Smoothing with backward filter + bool use_backward_filter = false; + traccc::scalar covariance_inflation_factor = 1e3f; }; } // namespace traccc diff --git a/core/include/traccc/fitting/kalman_filter/kalman_actor.hpp b/core/include/traccc/fitting/kalman_filter/kalman_actor.hpp index 56522bfb5..33e540691 100644 --- a/core/include/traccc/fitting/kalman_filter/kalman_actor.hpp +++ b/core/include/traccc/fitting/kalman_filter/kalman_actor.hpp @@ -11,6 +11,7 @@ #include "traccc/definitions/qualifiers.hpp" #include "traccc/edm/track_state.hpp" #include "traccc/fitting/kalman_filter/gain_matrix_updater.hpp" +#include "traccc/fitting/kalman_filter/two_filters_smoother.hpp" #include "traccc/utils/particle.hpp" // detray include(s). @@ -33,6 +34,7 @@ struct kalman_actor : detray::actor { state(vector_t&& track_states) : m_track_states(std::move(track_states)) { m_it = m_track_states.begin(); + m_it_rev = m_track_states.rbegin(); } /// Constructor with the vector of track states @@ -40,24 +42,42 @@ struct kalman_actor : detray::actor { state(const vector_t& track_states) : m_track_states(track_states) { m_it = m_track_states.begin(); + m_it_rev = m_track_states.rbegin(); } /// @return the reference of track state pointed by the iterator TRACCC_HOST_DEVICE - track_state_type& operator()() { return *m_it; } + track_state_type& operator()() { + if (!backward_mode) { + return *m_it; + } else { + return *m_it_rev; + } + } /// Reset the iterator TRACCC_HOST_DEVICE - void reset() { m_it = m_track_states.begin(); } + void reset() { + m_it = m_track_states.begin(); + m_it_rev = m_track_states.rbegin(); + } /// Advance the iterator TRACCC_HOST_DEVICE - void next() { m_it++; } + void next() { + if (!backward_mode) { + m_it++; + } else { + m_it_rev++; + } + } /// @return true if the iterator reaches the end of vector TRACCC_HOST_DEVICE - bool is_complete() const { - if (m_it == m_track_states.end()) { + bool is_complete() { + if (!backward_mode && m_it == m_track_states.end()) { + return true; + } else if (backward_mode && m_it_rev == m_track_states.rend()) { return true; } return false; @@ -69,9 +89,15 @@ struct kalman_actor : detray::actor { // iterator for forward filtering typename vector_t::iterator m_it; + // iterator for backward filtering + typename vector_t::reverse_iterator m_it_rev; + // The number of holes (The number of sensitive surfaces which do not // have a measurement for the track pattern) unsigned int n_holes{0u}; + + // Run back filtering for smoothing, if true + bool backward_mode = false; }; /// Actor operation to perform the Kalman filtering @@ -109,9 +135,24 @@ struct kalman_actor : detray::actor { // Run Kalman Gain Updater const auto sf = navigation.get_surface(); - const bool res = - sf.template visit_mask>( + bool res = false; + + // Forward filter + if (!actor_state.backward_mode) { + res = sf.template visit_mask>( + trk_state, propagation._stepping.bound_params()); + + // Update the propagation flow + stepping.bound_params() = trk_state.filtered(); + + // Set full jacobian + trk_state.jacobian() = stepping.full_jacobian(); + } + // Backward filter for smoothing + else { + res = sf.template visit_mask>( trk_state, propagation._stepping.bound_params()); + } // Abort if the Kalman update fails if (!res) { @@ -119,12 +160,6 @@ struct kalman_actor : detray::actor { return; } - // Update the propagation flow - stepping.bound_params() = trk_state.filtered(); - - // Set full jacobian - trk_state.jacobian() = stepping.full_jacobian(); - // Change the charge of hypothesized particles when the sign of qop // is changed (This rarely happens when qop is set with a poor seed // resolution) diff --git a/core/include/traccc/fitting/kalman_filter/kalman_fitter.hpp b/core/include/traccc/fitting/kalman_filter/kalman_fitter.hpp index 18a189ec9..895f0da4d 100644 --- a/core/include/traccc/fitting/kalman_filter/kalman_fitter.hpp +++ b/core/include/traccc/fitting/kalman_filter/kalman_fitter.hpp @@ -17,6 +17,7 @@ #include "traccc/fitting/kalman_filter/kalman_actor.hpp" #include "traccc/fitting/kalman_filter/kalman_step_aborter.hpp" #include "traccc/fitting/kalman_filter/statistics_updater.hpp" +#include "traccc/fitting/kalman_filter/two_filters_smoother.hpp" #include "traccc/utils/particle.hpp" // detray include(s). @@ -67,10 +68,17 @@ class kalman_fitter { detray::actor_chain; + using backward_actor_chain_type = + detray::actor_chain; + // Propagator type using propagator_type = detray::propagator; + using backward_propagator_type = + detray::propagator; + /// Constructor with a detector /// /// @param det the detector object @@ -104,6 +112,14 @@ class kalman_fitter { m_resetter_state, m_step_aborter_state); } + /// @return the actor chain state + TRACCC_HOST_DEVICE + typename backward_actor_chain_type::state backward_actor_state() { + return detray::tie(m_aborter_state, m_transporter_state, + m_fit_actor_state, m_interactor_state, + m_resetter_state, m_step_aborter_state); + } + /// Individual actor states typename aborter::state m_aborter_state{}; typename transporter::state m_transporter_state{}; @@ -132,17 +148,15 @@ class kalman_fitter { // Reset the iterator of kalman actor fitter_state.m_fit_actor_state.reset(); - if (i == 0) { - filter(seed_params, fitter_state); - } - // From the second iteration, seed parameter is the smoothed track - // parameter at the first surface - else { - const auto& new_seed_params = - fitter_state.m_fit_actor_state.m_track_states[0].smoothed(); + auto seed_params_cpy = + (i == 0) ? seed_params + : fitter_state.m_fit_actor_state.m_track_states[0] + .smoothed(); - filter(new_seed_params, fitter_state); - } + inflate_covariance(seed_params_cpy, + m_cfg.covariance_inflation_factor); + + filter(seed_params_cpy, fitter_state); } } @@ -178,6 +192,9 @@ class kalman_fitter { .template set_constraint( m_cfg.propagation.stepping.step_constraint); + // Reset fitter statistics + fitter_state.m_fit_res.reset_statistics(); + // Run forward filtering propagator.propagate(propagation, fitter_state()); @@ -194,14 +211,10 @@ class kalman_fitter { /// track and vertex fitting", R.Frühwirth, NIM A. /// /// @param fitter_state the state of kalman fitter - TRACCC_HOST_DEVICE - void smooth(state& fitter_state) { + TRACCC_HOST_DEVICE void smooth(state& fitter_state) { + auto& track_states = fitter_state.m_fit_actor_state.m_track_states; - // The smoothing algorithm requires the following: - // (1) the filtered track parameter of the current surface - // (2) the smoothed track parameter of the next surface - // // Since the smoothed track parameter of the last surface can be // considered to be the filtered one, we can reversly iterate the // algorithm to obtain the smoothed parameter of other surfaces @@ -210,14 +223,45 @@ class kalman_fitter { last.smoothed().set_covariance(last.filtered().covariance()); last.smoothed_chi2() = last.filtered_chi2(); - for (typename vector_type>::reverse_iterator - it = track_states.rbegin() + 1; - it != track_states.rend(); ++it) { + if (m_cfg.use_backward_filter) { + // Backward propagator for the two-filters method + backward_propagator_type propagator(m_cfg.propagation); + + // Set path limit + fitter_state.m_aborter_state.set_path_limit( + m_cfg.propagation.stepping.path_limit); + + typename backward_propagator_type::state propagation( + last.smoothed(), m_field, m_detector); + + inflate_covariance(propagation._stepping.bound_params(), + m_cfg.covariance_inflation_factor); + + propagation._navigation.set_volume( + last.smoothed().surface_link().volume()); - // Run kalman smoother - const detray::tracking_surface sf{m_detector, it->surface_link()}; - sf.template visit_mask>( - *it, *(it - 1)); + propagation._navigation.set_direction( + detray::navigation::direction::e_backward); + fitter_state.m_fit_actor_state.backward_mode = true; + + propagator.propagate(propagation, + fitter_state.backward_actor_state()); + + // Reset the backward mode to false + fitter_state.m_fit_actor_state.backward_mode = false; + + } else { + // Run the Rauch–Tung–Striebel (RTS) smoother + for (typename vector_type< + track_state>::reverse_iterator it = + track_states.rbegin() + 1; + it != track_states.rend(); ++it) { + + const detray::tracking_surface sf{m_detector, + it->surface_link()}; + sf.template visit_mask>( + *it, *(it - 1)); + } } } @@ -233,8 +277,8 @@ class kalman_fitter { const detray::tracking_surface sf{m_detector, trk_state.surface_link()}; - sf.template visit_mask>(fit_res, - trk_state); + sf.template visit_mask>( + fit_res, trk_state, m_cfg.use_backward_filter); } // Subtract the NDoF with the degree of freedom of the bound track (=5) diff --git a/core/include/traccc/fitting/kalman_filter/statistics_updater.hpp b/core/include/traccc/fitting/kalman_filter/statistics_updater.hpp index 873409326..4f31e5e97 100644 --- a/core/include/traccc/fitting/kalman_filter/statistics_updater.hpp +++ b/core/include/traccc/fitting/kalman_filter/statistics_updater.hpp @@ -30,7 +30,8 @@ struct statistics_updater { TRACCC_HOST_DEVICE inline void operator()( const mask_group_t& /*mask_group*/, const index_t& /*index*/, fitting_result& fit_res, - const track_state& trk_state) { + const track_state& trk_state, + const bool use_backward_filter) { if (!trk_state.is_hole) { @@ -41,7 +42,11 @@ struct statistics_updater { fit_res.ndf += static_cast(D); // total_chi2 = total_chi2 + chi2 - fit_res.chi2 += trk_state.smoothed_chi2(); + if (use_backward_filter) { + fit_res.chi2 += trk_state.backward_chi2(); + } else { + fit_res.chi2 += trk_state.filtered_chi2(); + } } } }; diff --git a/core/include/traccc/fitting/kalman_filter/two_filters_smoother.hpp b/core/include/traccc/fitting/kalman_filter/two_filters_smoother.hpp new file mode 100644 index 000000000..146b251c0 --- /dev/null +++ b/core/include/traccc/fitting/kalman_filter/two_filters_smoother.hpp @@ -0,0 +1,173 @@ +/** TRACCC library, part of the ACTS project (R&D line) + * + * (c) 2024 CERN for the benefit of the ACTS project + * + * Mozilla Public License Version 2.0 + */ + +#pragma once + +// Project include(s). +#include "traccc/definitions/qualifiers.hpp" +#include "traccc/definitions/track_parametrization.hpp" +#include "traccc/edm/track_state.hpp" + +namespace traccc { + +/// Type unrolling functor for two-filters smoother +template +struct two_filters_smoother { + + // Type declarations + using size_type = detray::dsize_type; + template + using matrix_type = detray::dmatrix; + using bound_vector_type = detray::bound_vector; + using bound_matrix_type = detray::bound_matrix; + + /// Two-filters smoother operation + /// + /// @param mask_group mask group that contains the mask of surface + /// @param index mask index of surface + /// @param trk_state track state of the surface + /// @param bound_params bound parameter + /// + /// @return true if the update succeeds + template + TRACCC_HOST_DEVICE inline bool operator()( + const mask_group_t& /*mask_group*/, const index_t& /*index*/, + track_state& trk_state, + bound_track_parameters& bound_params) const { + + using shape_type = typename mask_group_t::value_type::shape; + + const auto D = trk_state.get_measurement().meas_dim; + assert(D == 1u || D == 2u); + if (D == 1u) { + return smoothe<1u, shape_type>(trk_state, bound_params); + } else if (D == 2u) { + return smoothe<2u, shape_type>(trk_state, bound_params); + } + + return false; + } + + // Reference: The Optimun Linear Smoother as a Combination of Two Optimum + // Linear Filters + template + TRACCC_HOST_DEVICE inline bool smoothe( + track_state& trk_state, + bound_track_parameters& bound_params) const { + + assert(trk_state.filtered().surface_link() == + bound_params.surface_link()); + + static_assert(((D == 1u) || (D == 2u)), + "The measurement dimension should be 1 or 2"); + + const auto meas = trk_state.get_measurement(); + + matrix_type H = meas.subs.template projector(); + + // Measurement data on surface + const matrix_type& meas_local = + trk_state.template measurement_local(); + + // Predicted vector of bound track parameters + const matrix_type predicted_vec = + bound_params.vector(); + + // Predicted covaraince of bound track parameters + const matrix_type predicted_cov = + bound_params.covariance(); + + const matrix_type predicted_cov_inv = + matrix::inverse(predicted_cov); + const matrix_type filtered_cov_inv = + matrix::inverse(trk_state.filtered().covariance()); + + // Eq (3.38) of "Pattern Recognition, Tracking and Vertex + // Reconstruction in Particle Detectors" + const matrix_type smoothed_cov_inv = + predicted_cov_inv + filtered_cov_inv; + + const matrix_type smoothed_cov = + matrix::inverse(smoothed_cov_inv); + + // Eq (3.38) of "Pattern Recognition, Tracking and Vertex + // Reconstruction in Particle Detectors" + const matrix_type smoothed_vec = + smoothed_cov * (filtered_cov_inv * trk_state.filtered().vector() + + predicted_cov_inv * predicted_vec); + + trk_state.smoothed().set_vector(smoothed_vec); + trk_state.smoothed().set_covariance(smoothed_cov); + + const matrix_type residual_smt = meas_local - H * smoothed_vec; + + // Spatial resolution (Measurement covariance) + const matrix_type V = + trk_state.template measurement_covariance(); + + // Eq (3.39) of "Pattern Recognition, Tracking and Vertex + // Reconstruction in Particle Detectors" + const matrix_type R_smt = + V - H * smoothed_cov * matrix::transpose(H); + + // Eq (3.40) of "Pattern Recognition, Tracking and Vertex + // Reconstruction in Particle Detectors" + const matrix_type<1, 1> chi2_smt = matrix::transpose(residual_smt) * + matrix::inverse(R_smt) * + residual_smt; + + trk_state.smoothed_chi2() = getter::element(chi2_smt, 0, 0); + + /************************************* + * Set backward filtered parameter + *************************************/ + + const auto I66 = matrix::identity(); + const auto I_m = matrix::identity>(); + + const matrix_type M = + H * predicted_cov * matrix::transpose(H) + V; + + // Kalman gain matrix + const matrix_type<6, D> K = + predicted_cov * matrix::transpose(H) * matrix::inverse(M); + + // Calculate the filtered track parameters + const matrix_type<6, 1> filtered_vec = + predicted_vec + K * (meas_local - H * predicted_vec); + const matrix_type<6, 6> filtered_cov = (I66 - K * H) * predicted_cov; + + // Residual between measurement and (projected) filtered vector + const matrix_type residual = meas_local - H * filtered_vec; + + // Calculate backward chi2 + const matrix_type R = (I_m - H * K) * V; + const matrix_type<1, 1> chi2 = + matrix::transpose(residual) * matrix::inverse(R) * residual; + + // Return false if track is parallel to z-axis or phi is not finite + const scalar theta = bound_params.theta(); + if (theta <= 0.f || theta >= constant::pi || + !std::isfinite(bound_params.phi())) { + return false; + } + + // Update the bound track parameters + bound_params.set_vector(filtered_vec); + bound_params.set_covariance(filtered_cov); + + // Set backward chi2 + trk_state.backward_chi2() = getter::element(chi2, 0, 0); + + // Wrap the phi in the range of [-pi, pi] + wrap_phi(bound_params); + + return true; + } +}; + +} // namespace traccc diff --git a/performance/include/traccc/resolution/stat_plot_tool_config.hpp b/performance/include/traccc/resolution/stat_plot_tool_config.hpp index 5619e137b..2fb8f897f 100644 --- a/performance/include/traccc/resolution/stat_plot_tool_config.hpp +++ b/performance/include/traccc/resolution/stat_plot_tool_config.hpp @@ -24,7 +24,7 @@ struct stat_plot_tool_config { {"ndf", plot_helpers::binning("ndf", 35, -5.f, 30.f)}, {"chi2", plot_helpers::binning("chi2", 100, 0.f, 50.f)}, {"reduced_chi2", plot_helpers::binning("chi2/ndf", 100, 0.f, 10.f)}, - {"pval", plot_helpers::binning("pval", 100, 0.f, 1.f)}, + {"pval", plot_helpers::binning("pval", 50, 0.f, 1.f)}, {"chi2_local", plot_helpers::binning("chi2", 100, 0.f, 10.f)}}; }; diff --git a/tests/common/tests/kalman_fitting_telescope_test.hpp b/tests/common/tests/kalman_fitting_telescope_test.hpp index ef09cea0f..adf2df306 100644 --- a/tests/common/tests/kalman_fitting_telescope_test.hpp +++ b/tests/common/tests/kalman_fitting_telescope_test.hpp @@ -63,11 +63,11 @@ class KalmanFittingTelescopeTests /// Standard deviations for seed track parameters static constexpr std::array stddevs = { - 0.03f * detray::unit::mm, - 0.03f * detray::unit::mm, + 0.1f * detray::unit::mm, + 0.1f * detray::unit::mm, 0.017f, 0.017f, - 0.001f / detray::unit::GeV, + 0.05f / detray::unit::GeV, 1.f * detray::unit::ns}; void consistency_tests(const track_state_collection_types::host& diff --git a/tests/common/tests/kalman_fitting_test.cpp b/tests/common/tests/kalman_fitting_test.cpp index 49d3d3f3b..0f3ba1067 100644 --- a/tests/common/tests/kalman_fitting_test.cpp +++ b/tests/common/tests/kalman_fitting_test.cpp @@ -19,6 +19,8 @@ #ifdef TRACCC_HAVE_ROOT #include #include +#include +#include #include #endif // TRACCC_HAVE_ROOT @@ -81,6 +83,58 @@ void KalmanFittingTests::pull_value_tests( #endif // TRACCC_HAVE_ROOT } +void KalmanFittingTests::p_value_tests(std::string_view file_name) const { + + // Avoid unused variable warnings when building the code without ROOT. + (void)file_name; + +#ifdef TRACCC_HAVE_ROOT + // Open the file with the histograms. + std::unique_ptr ifile(TFile::Open(file_name.data(), "READ")); + if ((!ifile) || ifile->IsZombie()) { + throw std::runtime_error(std::string("Could not open file \"") + + file_name.data() + "\""); + } + + // Access the pvalue histogram. + TH1* pval_hist = dynamic_cast(ifile->Get("pval")); + if (!pval_hist) { + + throw std::runtime_error("Could not access p-value histogram in file " + + std::string(file_name.data()) + "\""); + } + + // Contant function used for the fit. + TF1 constant_func{"constant", "[0]", 0.f, 1.f}; + + // Set the seed to the number of data points divided by the number of bins + double exp_par = static_cast(pval_hist->GetEntries()) / + static_cast(pval_hist->GetNbinsX()); + + constant_func.SetParameters(0, exp_par); + + TFitResultPtr res = pval_hist->Fit("constant", "Q0S"); + + auto fit_par = constant_func.GetParameters(); + + // Some sanity checks + EXPECT_TRUE(fit_par[0] >= 1.f); + EXPECT_TRUE(exp_par >= 1.f); + + EXPECT_NEAR(pval_hist->GetMean(), 0.5f, 0.05f); + + // Fitted constant check (5% errror) + EXPECT_NEAR(fit_par[0], exp_par, exp_par * 0.05f) + << " fitted constant does not make sense"; + + // Make sure the pvalue from constant fit is higher than 0.01 + EXPECT_GE(res->Prob(), 0.01f) << " Poor constant fitting quality"; + +#else + std::cout << "P-value tests not performed without ROOT" << std::endl; +#endif // TRACCC_HAVE_ROOT +} + void KalmanFittingTests::ndf_tests( const fitting_result& fit_res, const track_state_collection_types::host& track_states_per_track) { diff --git a/tests/common/tests/kalman_fitting_test.hpp b/tests/common/tests/kalman_fitting_test.hpp index df75a10e1..8b973537c 100644 --- a/tests/common/tests/kalman_fitting_test.hpp +++ b/tests/common/tests/kalman_fitting_test.hpp @@ -64,6 +64,12 @@ class KalmanFittingTests : public testing::Test { void pull_value_tests(std::string_view file_name, const std::vector& hist_names) const; + /// Verify that P value distribtions follow the uniform + /// + /// @param file_name The name of the file holding the distributions + /// + void p_value_tests(std::string_view file_name) const; + /// Validadte the NDF /// /// @param host_det Detector object diff --git a/tests/cpu/test_ckf_sparse_tracks_telescope.cpp b/tests/cpu/test_ckf_sparse_tracks_telescope.cpp index 15f492b2f..46b51200d 100644 --- a/tests/cpu/test_ckf_sparse_tracks_telescope.cpp +++ b/tests/cpu/test_ckf_sparse_tracks_telescope.cpp @@ -111,6 +111,9 @@ TEST_P(CkfSparseTrackTelescopeTests, Run) { -100.f * unit::um; sim.get_config().propagation.navigation.max_mask_tolerance = 1.f * unit::mm; + sim.get_config().propagation.stepping.rk_error_tol = + 1e-8f * unit::mm; + sim.run(); /***************************** @@ -123,9 +126,10 @@ TEST_P(CkfSparseTrackTelescopeTests, Run) { // Finding algorithm configuration typename traccc::finding_config cfg; cfg.ptc_hypothesis = ptc; - cfg.chi2_max = 30.f; + cfg.chi2_max = 200.f; cfg.propagation.navigation.overstep_tolerance = -100.f * unit::um; cfg.propagation.navigation.max_mask_tolerance = 1.f * unit::mm; + cfg.propagation.stepping.rk_error_tol = 1e-8f * unit::mm; // Finding algorithm object traccc::host::combinatorial_kalman_filter_algorithm host_finding(cfg); @@ -136,6 +140,8 @@ TEST_P(CkfSparseTrackTelescopeTests, Run) { fit_cfg.propagation.navigation.overstep_tolerance = -100.f * unit::um; fit_cfg.propagation.navigation.max_mask_tolerance = 1.f * unit::mm; + fit_cfg.propagation.stepping.rk_error_tol = 1e-8f * unit::mm; + fit_cfg.use_backward_filter = true; traccc::host::kalman_fitting_algorithm host_fitting(fit_cfg, host_mr); // Iterate over events @@ -197,6 +203,12 @@ TEST_P(CkfSparseTrackTelescopeTests, Run) { "pull_d0", "pull_z0", "pull_phi", "pull_theta", "pull_qop"}; pull_value_tests(fit_writer_cfg.file_path, pull_names); + /******************** + * P-value test + ********************/ + + p_value_tests(fit_writer_cfg.file_path); + /******************** * Success rate test ********************/ @@ -211,44 +223,44 @@ INSTANTIATE_TEST_SUITE_P( CkfSparseTrackTelescopeValidation0, CkfSparseTrackTelescopeTests, ::testing::Values(std::make_tuple( "telescope_single_tracks", std::array{0.f, 0.f, 0.f}, - std::array{0.f, 200.f, 200.f}, + std::array{0.f, 400.f, 400.f}, std::array{1.f, 1.f}, std::array{0.f, 0.f}, std::array{0.f, 0.f}, detray::muon(), 1, 5000, - false, 20.f, 9u, 20.f, vector3{2 * detray::unit::T, 0, 0}))); + false, 20.f, 9u, 20.f, vector3{0, 0, 2 * detray::unit::T}))); INSTANTIATE_TEST_SUITE_P( CkfSparseTrackTelescopeValidation1, CkfSparseTrackTelescopeTests, ::testing::Values(std::make_tuple( "telescope_double_tracks", std::array{0.f, 0.f, 0.f}, - std::array{0.f, 200.f, 200.f}, + std::array{0.f, 400.f, 400.f}, std::array{1.f, 1.f}, std::array{0.f, 0.f}, std::array{0.f, 0.f}, detray::muon(), 2, 2500, - false, 20.f, 9u, 20.f, vector3{2 * detray::unit::T, 0, 0}))); + false, 20.f, 9u, 20.f, vector3{0, 0, 2 * detray::unit::T}))); INSTANTIATE_TEST_SUITE_P( CkfSparseTrackTelescopeValidation2, CkfSparseTrackTelescopeTests, ::testing::Values(std::make_tuple( "telescope_quadra_tracks", std::array{0.f, 0.f, 0.f}, - std::array{0.f, 200.f, 200.f}, + std::array{0.f, 400.f, 400.f}, std::array{1.f, 1.f}, std::array{0.f, 0.f}, std::array{0.f, 0.f}, detray::muon(), 4, 1250, - false, 20.f, 9u, 20.f, vector3{2 * detray::unit::T, 0, 0}))); + false, 20.f, 9u, 20.f, vector3{0, 0, 2 * detray::unit::T}))); INSTANTIATE_TEST_SUITE_P( CkfSparseTrackTelescopeValidation3, CkfSparseTrackTelescopeTests, ::testing::Values(std::make_tuple( "telescope_decade_tracks", std::array{0.f, 0.f, 0.f}, - std::array{0.f, 200.f, 200.f}, + std::array{0.f, 400.f, 400.f}, std::array{1.f, 1.f}, std::array{0.f, 0.f}, std::array{0.f, 0.f}, detray::muon(), 10, 500, - false, 20.f, 9u, 20.f, vector3{2 * detray::unit::T, 0, 0}))); + false, 20.f, 9u, 20.f, vector3{0, 0, 2 * detray::unit::T}))); INSTANTIATE_TEST_SUITE_P( CkfSparseTrackTelescopeValidation4, CkfSparseTrackTelescopeTests, ::testing::Values(std::make_tuple( "telescope_decade_tracks_random_charge", std::array{0.f, 0.f, 0.f}, - std::array{0.f, 200.f, 200.f}, + std::array{0.f, 400.f, 400.f}, std::array{1.f, 1.f}, std::array{0.f, 0.f}, std::array{0.f, 0.f}, detray::muon(), 10, 500, true, - 20.f, 9u, 20.f, vector3{2 * detray::unit::T, 0, 0}))); + 20.f, 9u, 20.f, vector3{0, 0, 2 * detray::unit::T}))); diff --git a/tests/cpu/test_kalman_fitter_telescope.cpp b/tests/cpu/test_kalman_fitter_telescope.cpp index 61a81034c..881ca7ec9 100644 --- a/tests/cpu/test_kalman_fitter_telescope.cpp +++ b/tests/cpu/test_kalman_fitter_telescope.cpp @@ -108,6 +108,8 @@ TEST_P(KalmanFittingTelescopeTests, Run) { -100.f * unit::um; sim.get_config().propagation.navigation.max_mask_tolerance = 1.f * unit::mm; + sim.get_config().propagation.stepping.rk_error_tol = + 1e-8f * unit::mm; sim.run(); /*************** @@ -123,6 +125,8 @@ TEST_P(KalmanFittingTelescopeTests, Run) { fit_cfg.propagation.navigation.overstep_tolerance = -100.f * unit::um; fit_cfg.propagation.navigation.max_mask_tolerance = 1.f * unit::mm; + fit_cfg.propagation.stepping.rk_error_tol = 1e-8f * unit::mm; + fit_cfg.use_backward_filter = true; traccc::host::kalman_fitting_algorithm fitting(fit_cfg, host_mr); // Iterate over events @@ -173,6 +177,12 @@ TEST_P(KalmanFittingTelescopeTests, Run) { "pull_d0", "pull_z0", "pull_phi", "pull_theta", "pull_qop"}; pull_value_tests(fit_writer_cfg.file_path, pull_names); + /******************** + * P-value test + ********************/ + + p_value_tests(fit_writer_cfg.file_path); + /******************** * Success rate test ********************/ @@ -189,8 +199,8 @@ INSTANTIATE_TEST_SUITE_P( "telescope_1_GeV_0_phi_muon", std::array{0.f, 0.f, 0.f}, std::array{0.f, 0.f, 0.f}, std::array{1.f, 1.f}, std::array{0.f, 0.f}, std::array{0.f, 0.f}, - detray::muon(), 100, 100, false, 20.f, 9u, 20.f, - vector3{2 * detray::unit::T, 0, 0}))); + detray::muon(), 100, 100, false, 20.f, 20u, 20.f, + vector3{0, 0, 2 * detray::unit::T}))); INSTANTIATE_TEST_SUITE_P( KalmanFitTelescopeValidation1, KalmanFittingTelescopeTests, @@ -199,7 +209,7 @@ INSTANTIATE_TEST_SUITE_P( std::array{0.f, 0.f, 0.f}, std::array{10.f, 10.f}, std::array{0.f, 0.f}, std::array{0.f, 0.f}, detray::muon(), 100, 100, - false, 20.f, 9u, 20.f, vector3{2 * detray::unit::T, 0, 0}))); + false, 20.f, 9u, 20.f, vector3{0, 0, 2 * detray::unit::T}))); INSTANTIATE_TEST_SUITE_P( KalmanFitTelescopeValidation2, KalmanFittingTelescopeTests, @@ -208,7 +218,7 @@ INSTANTIATE_TEST_SUITE_P( std::array{0.f, 0.f, 0.f}, std::array{100.f, 100.f}, std::array{0.f, 0.f}, std::array{0.f, 0.f}, detray::muon(), 100, 100, - false, 20.f, 9u, 20.f, vector3{2 * detray::unit::T, 0, 0}))); + false, 20.f, 9u, 20.f, vector3{0, 0, 2 * detray::unit::T}))); INSTANTIATE_TEST_SUITE_P( KalmanFitTelescopeValidation3, KalmanFittingTelescopeTests, @@ -218,7 +228,7 @@ INSTANTIATE_TEST_SUITE_P( std::array{0.f, 0.f, 0.f}, std::array{1.f, 1.f}, std::array{0.f, 0.f}, std::array{0.f, 0.f}, detray::antimuon(), 100, 100, false, 20.f, 9u, 20.f, - vector3{2 * detray::unit::T, 0, 0}))); + vector3{0, 0, 2 * detray::unit::T}))); INSTANTIATE_TEST_SUITE_P( KalmanFitTelescopeValidation4, KalmanFittingTelescopeTests, @@ -228,14 +238,4 @@ INSTANTIATE_TEST_SUITE_P( std::array{0.f, 0.f, 0.f}, std::array{1.f, 1.f}, std::array{0.f, 0.f}, std::array{0.f, 0.f}, detray::antimuon(), 100, 100, true, 20.f, 9u, 20.f, - vector3{2 * detray::unit::T, 0, 0}))); - -INSTANTIATE_TEST_SUITE_P( - KalmanFitTelescopeValidation5, KalmanFittingTelescopeTests, - ::testing::Values(std::make_tuple( - "telescope_1_GeV_0_phi_muon_z_Bfield", - std::array{0.f, 0.f, 0.f}, - std::array{0.f, 0.f, 0.f}, std::array{1.f, 1.f}, - std::array{0.f, 0.f}, std::array{0.f, 0.f}, - detray::muon(), 100, 100, false, 20.f, 9u, 20.f, - vector3{0, 0, 2 * detray::unit::T}))); + vector3{0, 0, 2 * detray::unit::T}))); \ No newline at end of file diff --git a/tests/cpu/test_kalman_fitter_wire_chamber.cpp b/tests/cpu/test_kalman_fitter_wire_chamber.cpp index 952a4e389..777f6d20d 100644 --- a/tests/cpu/test_kalman_fitter_wire_chamber.cpp +++ b/tests/cpu/test_kalman_fitter_wire_chamber.cpp @@ -124,6 +124,7 @@ TEST_P(KalmanFittingWireChamberTests, Run) { static_cast(mask_tolerance); fit_cfg.propagation.navigation.search_window = search_window; fit_cfg.ptc_hypothesis = ptc; + fit_cfg.covariance_inflation_factor = 1.f; traccc::host::kalman_fitting_algorithm fitting(fit_cfg, host_mr); // Iterate over events diff --git a/tests/cuda/test_kalman_fitter_telescope.cpp b/tests/cuda/test_kalman_fitter_telescope.cpp index f8368746e..b38a6ec1a 100644 --- a/tests/cuda/test_kalman_fitter_telescope.cpp +++ b/tests/cuda/test_kalman_fitter_telescope.cpp @@ -152,6 +152,7 @@ TEST_P(KalmanFittingTelescopeTests, Run) { fit_cfg.propagation.navigation.overstep_tolerance = -100.f * unit::um; fit_cfg.propagation.navigation.max_mask_tolerance = 1.f * unit::mm; + fit_cfg.use_backward_filter = true; traccc::cuda::fitting_algorithm device_fitting( fit_cfg, mr, copy, stream); @@ -209,6 +210,12 @@ TEST_P(KalmanFittingTelescopeTests, Run) { "pull_d0", "pull_z0", "pull_phi", "pull_theta", "pull_qop"}; pull_value_tests(fit_writer_cfg.file_path, pull_names); + /******************** + * P-value test + ********************/ + + p_value_tests(fit_writer_cfg.file_path); + /******************** * Success rate test ********************/ @@ -227,7 +234,7 @@ INSTANTIATE_TEST_SUITE_P( std::array{0.f, 0.f, 0.f}, std::array{1.f, 1.f}, std::array{0.f, 0.f}, std::array{0.f, 0.f}, detray::muon(), 100, 100, - false, 20.f, 9u, 20.f, vector3{2 * detray::unit::T, 0, 0}), + false, 20.f, 9u, 20.f, vector3{0, 0, 2 * detray::unit::T}), std::make_tuple("cuda_telescope_10_GeV_0_phi", std::array{0.f, 0.f, 0.f}, std::array{0.f, 0.f, 0.f}, @@ -235,7 +242,7 @@ INSTANTIATE_TEST_SUITE_P( std::array{0.f, 0.f}, std::array{0.f, 0.f}, detray::muon(), 100, 100, false, 20.f, 9u, 20.f, - vector3{2 * detray::unit::T, 0, 0}), + vector3{0, 0, 2 * detray::unit::T}), std::make_tuple("cuda_telescope_100_GeV_0_phi", std::array{0.f, 0.f, 0.f}, std::array{0.f, 0.f, 0.f}, @@ -243,7 +250,7 @@ INSTANTIATE_TEST_SUITE_P( std::array{0.f, 0.f}, std::array{0.f, 0.f}, detray::muon(), 100, 100, false, 20.f, 9u, 20.f, - vector3{2 * detray::unit::T, 0, 0}), + vector3{0, 0, 2 * detray::unit::T}), std::make_tuple("cuda_telescope_1_GeV_0_phi_antimuon", std::array{0.f, 0.f, 0.f}, std::array{0.f, 0.f, 0.f}, @@ -251,7 +258,7 @@ INSTANTIATE_TEST_SUITE_P( std::array{0.f, 0.f}, std::array{0.f, 0.f}, detray::antimuon(), 100, 100, false, 20.f, 9u, - 20.f, vector3{2 * detray::unit::T, 0, 0}), + 20.f, vector3{0, 0, 2 * detray::unit::T}), std::make_tuple("cuda_telescope_1_GeV_0_phi_random_charge", std::array{0.f, 0.f, 0.f}, std::array{0.f, 0.f, 0.f}, @@ -259,4 +266,4 @@ INSTANTIATE_TEST_SUITE_P( std::array{0.f, 0.f}, std::array{0.f, 0.f}, detray::muon(), 100, 100, true, 20.f, 9u, 20.f, - vector3{2 * detray::unit::T, 0, 0}))); + vector3{0, 0, 2 * detray::unit::T})));