Skip to content

Commit a16aa93

Browse files
Fix a number of assertions during track finding and reorder Kalman checks such that they perform an early reject before data is written to the track states (#1311)
Co-authored-by: Stephen Nicholas Swatman <stephen.nicholas.swatman@cern.ch>
1 parent c2e6dd3 commit a16aa93

6 files changed

Lines changed: 101 additions & 85 deletions

File tree

core/include/traccc/edm/track_parameters.hpp

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include "traccc/definitions/qualifiers.hpp"
1515
#include "traccc/definitions/track_parametrization.hpp"
1616
#include "traccc/edm/container.hpp"
17+
#include "traccc/utils/logging.hpp"
1718
#include "traccc/utils/trigonometric_helpers.hpp"
1819

1920
// detray include(s).
@@ -47,17 +48,45 @@ using bound_matrix = detray::bound_matrix<algebra_t>;
4748
using bound_track_parameters_collection_types =
4849
collection_types<bound_track_parameters<>>;
4950

50-
// Wrap the phi of track parameters to [-pi,pi]
51+
// Wrap the phi of a track parameter vector to [-pi,pi]
5152
template <detray::concepts::algebra algebra_t>
52-
TRACCC_HOST_DEVICE constexpr void normalize_angles(
53-
bound_track_parameters<algebra_t>& param) {
53+
TRACCC_HOST_DEVICE constexpr bool normalize_angles(
54+
bound_vector<algebra_t>& vec) {
5455
traccc::scalar phi;
5556
traccc::scalar theta;
5657

57-
std::tie(phi, theta) = detail::wrap_phi_theta(param.phi(), param.theta());
58+
const traccc::scalar in_theta{getter::element(vec, e_bound_theta, 0)};
59+
if (math::fmod(in_theta, 2.f * constant<traccc::scalar>::pi) == 0.f ||
60+
in_theta == 0.f) {
61+
TRACCC_WARNING_HOST_DEVICE("Hit theta pole before normalization: %f",
62+
in_theta);
63+
return false;
64+
}
65+
66+
std::tie(phi, theta) =
67+
detail::wrap_phi_theta(getter::element(vec, e_bound_phi, 0), in_theta);
68+
69+
if (theta <= 0.f || theta >= 2.f * constant<traccc::scalar>::pi) {
70+
TRACCC_WARNING_HOST_DEVICE("Hit theta pole after normalization: %f",
71+
theta);
72+
return false;
73+
}
74+
75+
// Assertions of the detray bound track parameters
76+
assert(math::fabs(phi) <= constant<traccc::scalar>::pi);
77+
assert(theta <= constant<traccc::scalar>::pi);
5878

59-
param.set_phi(phi);
60-
param.set_theta(theta);
79+
getter::element(vec, e_bound_phi, 0) = phi;
80+
getter::element(vec, e_bound_theta, 0) = theta;
81+
82+
return true;
83+
}
84+
85+
// Wrap the phi of bound track parameters to [-pi,pi]
86+
template <detray::concepts::algebra algebra_t>
87+
TRACCC_HOST_DEVICE constexpr bool normalize_angles(
88+
bound_parameters_vector<algebra_t>& param_vec) {
89+
return normalize_angles<algebra_t>(param_vec.vector());
6190
}
6291

6392
/// Covariance inflation used for track fitting

core/include/traccc/fitting/kalman_filter/gain_matrix_updater.hpp

Lines changed: 22 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -126,23 +126,10 @@ struct gain_matrix_updater {
126126
TRACCC_DEBUG_HOST("-> K:\n" << K);
127127

128128
// Calculate the filtered track parameters
129-
const matrix_type<6, 1> filtered_vec =
129+
matrix_type<6, 1> filtered_vec =
130130
predicted_vec + K * (meas_local - H * predicted_vec);
131-
const matrix_type<6, 6> i_minus_kh = I66 - K * H;
132-
matrix_type<6, 6> filtered_cov =
133-
i_minus_kh * predicted_cov * matrix::transpose(i_minus_kh) +
134-
K * V * matrix::transpose(K);
135131

136132
TRACCC_DEBUG_HOST("-> Filtered param:\n" << filtered_vec);
137-
TRACCC_DEBUG_HOST("-> Filtered cov:\n" << filtered_cov);
138-
139-
// Check the covariance for consistency
140-
// @TODO: Need to understand why negative variance happens
141-
if (constexpr traccc::scalar min_var{-0.01f};
142-
!details::regularize_covariance<algebra_t>(filtered_cov, min_var)) {
143-
TRACCC_ERROR_HOST_DEVICE("Negative variance after filtering");
144-
return kalman_fitter_status::ERROR_UPDATER_INVALID_COVARIANCE;
145-
}
146133

147134
// Return false if track is parallel to z-axis or phi is not finite
148135
if (!std::isfinite(getter::element(filtered_vec, e_bound_theta, 0))) {
@@ -163,6 +150,21 @@ struct gain_matrix_updater {
163150
return kalman_fitter_status::ERROR_QOP_ZERO;
164151
}
165152

153+
const matrix_type<6, 6> i_minus_kh = I66 - K * H;
154+
matrix_type<6, 6> filtered_cov =
155+
i_minus_kh * predicted_cov * matrix::transpose(i_minus_kh) +
156+
K * V * matrix::transpose(K);
157+
158+
TRACCC_DEBUG_HOST("-> Filtered cov:\n" << filtered_cov);
159+
160+
// Check the covariance for consistency
161+
// @TODO: Need to understand why negative variance happens
162+
if (constexpr traccc::scalar min_var{-0.01f};
163+
!details::regularize_covariance<algebra_t>(filtered_cov, min_var)) {
164+
TRACCC_ERROR_HOST_DEVICE("Negative variance after filtering");
165+
return kalman_fitter_status::ERROR_UPDATER_INVALID_COVARIANCE;
166+
}
167+
166168
// Residual between measurement and (projected) filtered vector
167169
const matrix_type<D, 1> residual = meas_local - H * filtered_vec;
168170

@@ -192,29 +194,17 @@ struct gain_matrix_updater {
192194
return kalman_fitter_status::ERROR_UPDATER_CHI2_NOT_FINITE;
193195
}
194196

197+
// Wrap the phi and theta angles in their valid ranges
198+
if (!normalize_angles<algebra_t>(filtered_vec)) {
199+
TRACCC_ERROR_HOST_DEVICE("Hit theta pole in filtering!");
200+
return kalman_fitter_status::ERROR_THETA_POLE;
201+
}
202+
195203
// Set the chi2 for this track and measurement
196204
trk_state.filtered_params().set_vector(filtered_vec);
197205
trk_state.filtered_params().set_covariance(filtered_cov);
198206
trk_state.filtered_chi2() = chi2_val;
199207

200-
if (math::fmod(trk_state.filtered_params().theta(),
201-
2.f * constant<traccc::scalar>::pi) == 0.f) {
202-
TRACCC_ERROR_HOST_DEVICE(
203-
"Hit theta pole after filtering : %f (unrecoverable error "
204-
"pre-normalization)",
205-
trk_state.filtered_params().theta());
206-
return kalman_fitter_status::ERROR_THETA_POLE;
207-
}
208-
209-
// Wrap the phi and theta angles in their valid ranges
210-
normalize_angles(trk_state.filtered_params());
211-
212-
const scalar theta = trk_state.filtered_params().theta();
213-
if (theta <= 0.f || theta >= 2.f * constant<traccc::scalar>::pi) {
214-
TRACCC_ERROR_HOST_DEVICE("Hit theta pole in filtering : %f", theta);
215-
return kalman_fitter_status::ERROR_THETA_POLE;
216-
}
217-
218208
assert(!trk_state.filtered_params().is_invalid());
219209

220210
return kalman_fitter_status::SUCCESS;

core/include/traccc/fitting/kalman_filter/kalman_actor.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -414,7 +414,7 @@ struct kalman_actor : detray::base_actor {
414414
direction_e ==
415415
kalman_actor_direction::BIDIRECTIONAL) {
416416
// Wrap the phi and theta angles in their valid ranges
417-
normalize_angles(bound_param);
417+
normalize_angles<algebra_t>(bound_param);
418418

419419
// Forward filter
420420
TRACCC_DEBUG_HOST_DEVICE("Run filtering...");

core/include/traccc/fitting/kalman_filter/two_filters_smoother.hpp

Lines changed: 42 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -101,35 +101,35 @@ struct two_filters_smoother {
101101

102102
// Eq (3.38) of "Pattern Recognition, Tracking and Vertex
103103
// Reconstruction in Particle Detectors"
104-
const matrix_type<e_bound_size, 1u> smoothed_vec =
104+
matrix_type<e_bound_size, 1u> smoothed_vec =
105105
smoothed_cov *
106106
(filtered_cov_inv * trk_state.filtered_params().vector() +
107107
predicted_cov_inv * predicted_vec);
108108

109-
trk_state.smoothed_params().set_vector(smoothed_vec);
110-
111109
// Return false if track is parallel to z-axis or phi is not finite
112-
if (!std::isfinite(trk_state.smoothed_params().theta())) {
110+
if (!std::isfinite(getter::element(smoothed_vec, e_bound_theta, 0))) {
113111
TRACCC_ERROR_HOST_DEVICE(
114112
"Theta is infinite after smoothing (Matrix inversion)");
115113
return kalman_fitter_status::ERROR_INVERSION;
116114
}
117115

118-
if (!std::isfinite(trk_state.smoothed_params().phi())) {
116+
if (!std::isfinite(getter::element(smoothed_vec, e_bound_phi, 0))) {
119117
TRACCC_ERROR_HOST_DEVICE(
120118
"Phi is infinite after smoothing (Matrix inversion)");
121119
return kalman_fitter_status::ERROR_INVERSION;
122120
}
123121

124-
if (math::fabs(trk_state.smoothed_params().qop()) == 0.f) {
122+
if (math::fabs(getter::element(smoothed_vec, e_bound_qoverp, 0)) ==
123+
0.f) {
125124
TRACCC_ERROR_HOST_DEVICE("q/p is zero after smoothing");
126125
return kalman_fitter_status::ERROR_QOP_ZERO;
127126
}
128127

129-
trk_state.smoothed_params().set_covariance(smoothed_cov);
130-
131128
// Wrap the phi and theta angles in their valid ranges
132-
normalize_angles(trk_state.smoothed_params());
129+
if (!normalize_angles<algebra_t>(smoothed_vec)) {
130+
TRACCC_ERROR_HOST_DEVICE("Hit theta pole after smoothing!");
131+
return kalman_fitter_status::ERROR_THETA_POLE;
132+
}
133133

134134
const subspace<algebra_t, e_bound_size> subs(
135135
measurements.at(trk_state.measurement_index()).subspace());
@@ -192,8 +192,6 @@ struct two_filters_smoother {
192192
return kalman_fitter_status::ERROR_SMOOTHER_CHI2_NOT_FINITE;
193193
}
194194

195-
trk_state.smoothed_chi2() = getter::element(chi2_smt, 0, 0);
196-
197195
/*************************************
198196
* Set backward filtered parameter
199197
*************************************/
@@ -222,45 +220,49 @@ struct two_filters_smoother {
222220
TRACCC_DEBUG_HOST("K:\n" << K);
223221

224222
// Calculate the filtered track parameters
225-
const matrix_type<6, 1> filtered_vec =
223+
matrix_type<6, 1> filtered_vec =
226224
predicted_vec + K * (meas_local - H * predicted_vec);
227-
const matrix_type<6, 6> i_minus_kh = I66 - K * H;
228-
matrix_type<6, 6> filtered_cov =
229-
i_minus_kh * predicted_cov * matrix::transpose(i_minus_kh) +
230-
K * V * matrix::transpose(K);
231-
232-
// Check the covariance for consistency
233-
// @TODO: Need to understand why negative variance happens
234-
if (constexpr traccc::scalar min_var{-0.01f};
235-
!details::regularize_covariance<algebra_t>(filtered_cov, min_var)) {
236-
TRACCC_ERROR_HOST_DEVICE("Negative variance after filtering");
237-
return kalman_fitter_status::ERROR_SMOOTHER_INVALID_COVARIANCE;
238-
}
239-
240-
// Update the bound track parameters
241-
bound_params.set_vector(filtered_vec);
242225

243226
// Return false if track is parallel to z-axis or phi is not finite
244-
if (!std::isfinite(bound_params.theta())) {
227+
if (!std::isfinite(getter::element(filtered_vec, e_bound_theta, 0))) {
245228
TRACCC_ERROR_HOST_DEVICE(
246229
"Theta is infinite after filering in smoother (Matrix "
247230
"inversion)");
248231
return kalman_fitter_status::ERROR_INVERSION;
249232
}
250233

251-
if (!std::isfinite(bound_params.phi())) {
234+
if (!std::isfinite(getter::element(filtered_vec, e_bound_phi, 0))) {
252235
TRACCC_ERROR_HOST_DEVICE(
253236
"Phi is infinite after filering in smoother (Matrix "
254237
"inversion)");
255238
return kalman_fitter_status::ERROR_INVERSION;
256239
}
257240

258-
if (math::fabs(bound_params.qop()) == 0.f) {
241+
if (math::fabs(getter::element(filtered_vec, e_bound_qoverp, 0)) ==
242+
0.f) {
259243
TRACCC_ERROR_HOST_DEVICE("q/p is zero after filering in smoother");
260244
return kalman_fitter_status::ERROR_QOP_ZERO;
261245
}
262246

263-
bound_params.set_covariance(filtered_cov);
247+
// Wrap the phi and theta angles in their valid ranges
248+
if (!normalize_angles<algebra_t>(filtered_vec)) {
249+
TRACCC_ERROR_HOST_DEVICE(
250+
"Hit theta pole after filtering in smoother!");
251+
return kalman_fitter_status::ERROR_THETA_POLE;
252+
}
253+
254+
const matrix_type<6, 6> i_minus_kh = I66 - K * H;
255+
matrix_type<6, 6> filtered_cov =
256+
i_minus_kh * predicted_cov * matrix::transpose(i_minus_kh) +
257+
K * V * matrix::transpose(K);
258+
259+
// Check the covariance for consistency
260+
// @TODO: Need to understand why negative variance happens
261+
if (constexpr traccc::scalar min_var{-0.01f};
262+
!details::regularize_covariance<algebra_t>(filtered_cov, min_var)) {
263+
TRACCC_ERROR_HOST_DEVICE("Negative variance after filtering");
264+
return kalman_fitter_status::ERROR_SMOOTHER_INVALID_COVARIANCE;
265+
}
264266

265267
// Residual between measurement and (projected) filtered vector
266268
const matrix_type<D, 1> residual = meas_local - H * filtered_vec;
@@ -291,21 +293,18 @@ struct two_filters_smoother {
291293
return kalman_fitter_status::ERROR_SMOOTHER_CHI2_NOT_FINITE;
292294
}
293295

294-
// Set backward chi2
296+
// Update the smoothed track parameters
297+
trk_state.smoothed_params().set_vector(smoothed_vec);
298+
trk_state.smoothed_params().set_covariance(smoothed_cov);
299+
trk_state.smoothed_chi2() = getter::element(chi2_smt, 0, 0);
295300
trk_state.backward_chi2() = chi2_val;
296-
297-
// Wrap the phi and theta angles in their valid ranges
298-
normalize_angles(bound_params);
299-
300-
const scalar theta = bound_params.theta();
301-
if (theta <= 0.f || theta >= 2.f * constant<traccc::scalar>::pi) {
302-
TRACCC_ERROR_HOST_DEVICE("Hit theta pole after smoothing : %f",
303-
theta);
304-
return kalman_fitter_status::ERROR_THETA_POLE;
305-
}
306-
307301
trk_state.set_smoothed();
308302

303+
// Update the filtered track parameters
304+
bound_params.set_vector(filtered_vec);
305+
bound_params.set_covariance(filtered_cov);
306+
307+
assert(!trk_state.smoothed_params().is_invalid());
309308
assert(!bound_params.is_invalid());
310309

311310
return kalman_fitter_status::SUCCESS;

device/common/include/traccc/finding/device/impl/build_tracks.ipp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,9 +220,7 @@ TRACCC_HOST_DEVICE inline void build_tracks(
220220
#ifndef NDEBUG
221221
// Assert that we did not make any duplicate track states.
222222
for (const auto& i : track.constituent_links()) {
223-
assert(i.type == edm::track_constituent_link::measurement);
224223
for (const auto& j : track.constituent_links()) {
225-
assert(j.type == edm::track_constituent_link::measurement);
226224
if (i.index != j.index) {
227225
// TODO: Re-enable me!
228226
// assert(measurements.at(i->index).identifier() !=

device/common/include/traccc/finding/device/impl/find_tracks.ipp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ TRACCC_HOST_DEVICE inline void find_tracks(
379379
* $\chi^2$ value will be.
380380
*/
381381
traccc::scalar highest =
382-
static_cast<traccc::scalar>(0.f);
382+
static_cast<traccc::scalar>(-1.f);
383383

384384
for (unsigned int i = 0;
385385
i < cfg.max_num_branches_per_surface; ++i) {

0 commit comments

Comments
 (0)