1717#include " traccc/utils/particle.hpp"
1818
1919// detray include(s).
20+ #include < detray/navigation/direct_navigator.hpp>
21+ #include < detray/navigation/navigator.hpp>
2022#include < detray/propagator/base_actor.hpp>
2123
2224// vecmem include(s)
2325#include < vecmem/containers/device_vector.hpp>
2426
27+ // System include(s)
28+ #include < cstdlib>
29+
2530namespace traccc {
2631
2732enum class kalman_actor_direction {
@@ -57,6 +62,7 @@ struct kalman_actor_state {
5762 void reset () {
5863 m_it = m_track_states.begin ();
5964 m_it_rev = m_track_states.rbegin ();
65+ n_holes = 0u ;
6066 }
6167
6268 // / Advance the iterator
@@ -71,12 +77,107 @@ struct kalman_actor_state {
7177
7278 // / @return true if the iterator reaches the end of vector
7379 TRACCC_HOST_DEVICE
74- bool is_complete () {
75- if (!backward_mode && m_it == m_track_states.end ()) {
76- return true ;
77- } else if (backward_mode && m_it_rev == m_track_states.rend ()) {
78- return true ;
80+ bool is_complete () const {
81+ return ((!backward_mode && m_it == m_track_states.end ()) ||
82+ (backward_mode && m_it_rev == m_track_states.rend ()));
83+ }
84+
85+ // / @returns the current number of holes in this state
86+ TRACCC_HOST_DEVICE
87+ unsigned int count_missed () const {
88+ unsigned int n_missed{0u };
89+
90+ if (backward_mode) {
91+ for (const auto & trk_state : m_track_states) {
92+ if (trk_state.smoothed ().is_invalid ()) {
93+ ++n_missed;
94+ }
95+ }
96+ } else {
97+ for (const auto & trk_state : m_track_states) {
98+ if (trk_state.filtered ().is_invalid ()) {
99+ ++n_missed;
100+ }
101+ }
79102 }
103+
104+ return n_missed;
105+ }
106+
107+ template <typename nav_state_t >
108+ void evaluate_hole (const nav_state_t & navigation) {
109+ if (navigation.is_good_candidate ()) {
110+ ++n_holes;
111+ }
112+ }
113+
114+ // / @return true if the iterator reaches the end of vector
115+ // / @TODO: Remove once direct navigator is used in forward pass
116+ template <typename propagation_state_t >
117+ TRACCC_HOST_DEVICE bool check_matching_surface (
118+ propagation_state_t & propagation) {
119+
120+ auto & navigation = propagation._navigation ;
121+ auto & trk_state = (*this )();
122+
123+ // Surface was found, continue with KF algorithm
124+ if (navigation.barcode () == trk_state.surface_link ()) {
125+ // Count a hole, if track finding did not find a measurement
126+ if (trk_state.is_hole ) {
127+ evaluate_hole (navigation);
128+ }
129+ // If track finding did not find measurement on this surface: skip
130+ return !trk_state.is_hole ;
131+ }
132+
133+ // Skipped surfaces: adjust iterator and remove counted hole
134+ // (only relevant if using non-direct navigation, e.g. forward truth
135+ // fitting or different prop. config between CKF asnd KF)
136+ // TODO: Remove again
137+ using detector_t = typename propagation_state_t ::detector_type;
138+ using nav_state_t = typename propagation_state_t ::navigator_state_type;
139+ if constexpr (!std::same_as<nav_state_t ,
140+ typename detray::direct_navigator<
141+ detector_t >::state>) {
142+ int i{1 };
143+ if (backward_mode) {
144+ // If we are on the last state and the navigation surface does
145+ // not match, it must be an additional surface
146+ // -> continue navigation until matched
147+ if (m_it_rev + 1 == m_track_states.rend ()) {
148+ evaluate_hole (navigation);
149+ return false ;
150+ }
151+ // Check if the current navigation surfaces can be found on a
152+ // later track state. That means the current track state was
153+ // skipped by the navigator: Advance the internal iterator
154+ for (auto itr = m_it_rev + 1 ; itr != m_track_states.rend ();
155+ ++itr) {
156+ if (itr->surface_link () == navigation.barcode ()) {
157+ m_it_rev += i;
158+ return true ;
159+ }
160+ ++i;
161+ }
162+ } else {
163+ if (m_it + 1 == m_track_states.end ()) {
164+ evaluate_hole (navigation);
165+ return false ;
166+ }
167+ for (auto itr = m_it + 1 ; itr != m_track_states.end (); ++itr) {
168+ if (itr->surface_link () == navigation.barcode ()) {
169+ m_it += i;
170+ return true ;
171+ }
172+ ++i;
173+ }
174+ }
175+ }
176+
177+ // Mismatch was not from missed state: Is a hole
178+ ++n_holes;
179+
180+ // After additional surface, keep navigating until match is found
80181 return false ;
81182 }
82183
@@ -89,8 +190,7 @@ struct kalman_actor_state {
89190 // iterator for backward filtering
90191 typename track_state_coll::reverse_iterator m_it_rev;
91192
92- // The number of holes (The number of sensitive surfaces which do not
93- // have a measurement for the track pattern)
193+ // Count the number of encountered surfaces without measurement
94194 unsigned int n_holes{0u };
95195
96196 // Run back filtering for smoothing, if true
@@ -118,7 +218,6 @@ struct kalman_actor : detray::actor {
118218 auto & stepping = propagation._stepping ;
119219 auto & navigation = propagation._navigation ;
120220
121- // If the iterator reaches the end, terminate the propagation
122221 if (actor_state.is_complete ()) {
123222 propagation._heartbeat &= navigation.exit ();
124223 return ;
@@ -127,21 +226,19 @@ struct kalman_actor : detray::actor {
127226 // triggered only for sensitive surfaces
128227 if (navigation.is_on_sensitive ()) {
129228
130- auto & trk_state = actor_state ();
229+ // Did the navigation switch direction?
230+ actor_state.backward_mode =
231+ navigation.direction () ==
232+ detray::navigation::direction::e_backward;
131233
132- // Increase the hole counts if the propagator fails to find the next
133- // measurement
134- if (navigation.barcode () != trk_state.surface_link ()) {
135- if (!actor_state.backward_mode ) {
136- actor_state.n_holes ++;
137- }
234+ // Increase the hole count if the propagator stops at an additional
235+ // surface and wait for the next sensitive surface to match
236+ if (!actor_state.check_matching_surface (propagation)) {
138237 return ;
139238 }
140239
141- // This track state is not a hole
142- if (!actor_state.backward_mode ) {
143- trk_state.is_hole = false ;
144- }
240+ auto & trk_state = actor_state ();
241+ auto & bound_param = stepping.bound_params ();
145242
146243 // Run Kalman Gain Updater
147244 const auto sf = navigation.get_surface ();
@@ -157,11 +254,10 @@ struct kalman_actor : detray::actor {
157254 kalman_actor_direction::BIDIRECTIONAL) {
158255 // Forward filter
159256 res = gain_matrix_updater<algebra_t >{}(
160- trk_state, propagation._stepping .bound_params (),
161- is_line);
257+ trk_state, bound_param, is_line);
162258
163259 // Update the propagation flow
164- stepping. bound_params () = trk_state.filtered ();
260+ bound_param = trk_state.filtered ();
165261 } else {
166262 assert (false );
167263 }
@@ -170,10 +266,14 @@ struct kalman_actor : detray::actor {
170266 kalman_actor_direction::BACKWARD_ONLY ||
171267 direction_e ==
172268 kalman_actor_direction::BIDIRECTIONAL) {
269+ // Forward filter did not find this state: skip
270+ if (trk_state.filtered ().is_invalid ()) {
271+ actor_state.next ();
272+ return ;
273+ }
173274 // Backward filter for smoothing
174275 res = two_filters_smoother<algebra_t >{}(
175- trk_state, propagation._stepping .bound_params (),
176- is_line);
276+ trk_state, bound_param, is_line);
177277 } else {
178278 assert (false );
179279 }
@@ -190,8 +290,7 @@ struct kalman_actor : detray::actor {
190290 // is changed (This rarely happens when qop is set with a poor seed
191291 // resolution)
192292 propagation.set_particle (detail::correct_particle_hypothesis (
193- stepping.particle_hypothesis (),
194- propagation._stepping .bound_params ()));
293+ stepping.particle_hypothesis (), bound_param));
195294
196295 // Update iterator
197296 actor_state.next ();
0 commit comments