ACTS
Experiment-independent tracking
Loading...
Searching...
No Matches
propagation_validation.hpp
1// This file is part of the ACTS project.
2//
3// Copyright (C) 2016 CERN for the benefit of the ACTS project
4//
5// This Source Code Form is subject to the terms of the Mozilla Public
6// License, v. 2.0. If a copy of the MPL was not distributed with this
7// file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9#pragma once
10
11// Project include(s).
12#include "detray/core/concepts.hpp"
13#include "detray/navigation/intersection/intersection.hpp"
14#include "detray/propagator/rk_stepper.hpp"
15#include "detray/utils/logging.hpp"
16
17// Detray test include(s)
18#include "detray/test/utils/perigee_stopper.hpp"
19#include "detray/test/validation/material_validation_utils.hpp"
20#include "detray/test/validation/navigation_validation_utils.hpp"
21
22// VecMem include(s).
23#include <vecmem/memory/host_memory_resource.hpp>
24
25// System include(s).
26#include <iostream>
27#include <memory>
28#include <optional>
29#include <string>
30
31namespace detray {
32
34template <concepts::scalar scalar_t>
54
66template <concepts::detector detector_t, typename bfield_view_t>
68 const detector_t& det, const typename detector_t::name_map& names,
69 const std::optional<bfield_view_t>& bfield,
72 tracks,
73 std::vector<dvector<intersection_record<detector_t>>>& truth_traces_fw) {
74 // 'false' if any failures were detected
75 bool test_successful{true};
76
77 using algebra_t = typename detector_t::algebra_type;
78 using scalar_t = dscalar<algebra_t>;
79 using stepper_t =
82 using data_record_t = intersection_record<detector_t>;
83
84 // Host memory resource
85 vecmem::host_memory_resource host_mr;
86
87 // Geometry context
88 const typename detector_t::geometry_context ctx{};
89
90 // Configure the test
92 test_cfg.n_tracks(tracks.size());
93 test_cfg.ptc_hypothesis(cfg.particle);
94 test_cfg.collect_sensitives_only(true);
95 test_cfg.fail_on_diff(false);
96 test_cfg.display_svg(cfg.display_svg);
97 test_cfg.display_only_missed(true);
98 test_cfg.verbose(false);
99
100 // Create the backward truth traces by reverting the order
101 std::vector<dvector<data_record_t>> truth_traces_bw;
102 truth_traces_bw.reserve(tracks.capacity());
103
104 for (const auto& truth_trace_fw : truth_traces_fw) {
105 // Revert the forward trace for the backward propagation
106 dvector<data_record_t> truth_trace_bw(truth_trace_fw.size());
107 std::ranges::reverse_copy(truth_trace_fw, truth_trace_bw.begin());
108
109 assert(!truth_trace_bw.empty());
110
111 truth_traces_bw.push_back(std::move(truth_trace_bw));
112 }
113
114 // Check truth data
115 if (truth_traces_fw.empty() || truth_traces_bw.empty()) {
116 DETRAY_ERROR_HOST("Propagation truth data empty");
117 return false;
118 }
119
120 // Make a tuple of references from a tuple
121 auto setup_actor_states = []<typename... T>(detray::dtuple<T...>& t) {
122 return detray::tie(detray::detail::get<T>(t)...);
123 };
124
125 // Define the actors
128
129 // Reusable actor states
130 typename interactor::state interactor_state{};
131 interactor_state.do_multiple_scattering = cfg.do_multiple_scattering;
132 interactor_state.do_energy_loss = cfg.do_energy_loss;
133
134 typename perigee_stopper::state stopper_state{};
135
136 std::cout << "-----------------------------------"
137 << "\nFORWARD - Propagation" << std::endl
138 << "-----------------------------------\n";
139
140 using parameter_updater = actor::parameter_updater<algebra_t, interactor>;
141
142 using actor_chain_t = actor_chain<parameter_updater>;
143
144 typename parameter_updater::state updater_state{};
145 updater_state.noise_estimation_cfg().n_stddev =
147 updater_state.noise_estimation_cfg().accumulated_error =
149 updater_state.noise_estimation_cfg().estimate_scattering_noise =
151
152 // Prepare the actor states for every track
155 state_tuples.reserve(tracks.size());
156 state_ref_tuples.reserve(tracks.size());
157
158 for (std::size_t i = 0u; i < tracks.size(); ++i) {
159 // Define the initial covariance
160 updater_state.init(tracks.at(i));
161
162 // Copy the configured updater state for this track
163 state_tuples.push_back(detray::make_tuple(updater_state, interactor_state));
164 state_ref_tuples.push_back(setup_actor_states(state_tuples.back()));
165 }
166
167 // Forward navigation
168 test_cfg.name(det.name(names) + "_GeV_fw");
169 test_cfg.navigation_direction(navigation::direction::e_forward);
170 const auto [trk_stats_fw, n_surfaces_fw, n_miss_nav_fw, n_miss_truth_fw,
171 step_traces_fw, track_mat_fw, mat_steps_fw] =
172 navigation_validator::compare_to_navigation<stepper_t, parameter_updater>(
173 test_cfg, host_mr, det, names, ctx, bfield, cfg.propagation,
174 truth_traces_fw, tracks, state_ref_tuples);
175
176 // Check stats
177 auto n_tracks{static_cast<double>(trk_stats_fw.n_tracks)};
178 if (static_cast<double>(trk_stats_fw.n_tracks_w_holes) / n_tracks >
179 cfg.max_percent_missed / 100.) {
180 DETRAY_ERROR_HOST("Too many tracks with missing surfaces");
181 test_successful = false;
182 }
183 if (static_cast<double>(trk_stats_fw.n_tracks_w_extra) / n_tracks >
184 cfg.max_percent_additional / 100.) {
185 DETRAY_ERROR_HOST("Too many tracks with additional surfaces");
186 test_successful = false;
187 }
188
189 std::cout << "\n-----------------------------------\n"
190 << "BACKWARD - Propagation" << std::endl
191 << "-----------------------------------\n";
192
194
195 // Prepare the actor states for every track
198 bw_state_tuples.reserve(tracks.size());
199 bw_state_ref_tuples.reserve(tracks.size());
200
201 for (std::size_t i = 0u; i < tracks.size(); ++i) {
202 // Define the initial covariance
203 updater_state.init(tracks.at(i));
204
205 // Copy the configured updater state for this track
206 bw_state_tuples.push_back(
207 detray::make_tuple(stopper_state, interactor_state, updater_state));
208 bw_state_ref_tuples.push_back(setup_actor_states(bw_state_tuples.back()));
209 }
210
211 // Backward navigation
212 test_cfg.name(det.name(names) + "_GeV_bw");
213 test_cfg.navigation_direction(navigation::direction::e_backward);
214 const auto [trk_stats_bw, n_surfaces_bw, n_miss_nav_bw, n_miss_truth_bw,
215 step_traces_bw, track_mat_bw, mat_steps_bw] =
216 navigation_validator::compare_to_navigation<stepper_t, parameter_updater,
218 test_cfg, host_mr, det, names, ctx, bfield, cfg.propagation,
219 truth_traces_bw, tracks, bw_state_ref_tuples);
220
221 // Make sure some data was collected
222 assert(trk_stats_fw.n_tracks > 0u);
223 assert(n_surfaces_fw.n_total() > 0u);
224 assert(trk_stats_bw.n_tracks > 0u);
225 assert(n_surfaces_bw.n_total() > 0u);
226
227 assert(trk_stats_fw.n_tracks == trk_stats_bw.n_tracks);
228
229 // Check, the amount of collected material between forward and backward
230 assert(step_traces_fw.size() == trk_stats_fw.n_tracks);
231 assert(mat_steps_fw.size() == trk_stats_fw.n_tracks);
232 assert(track_mat_fw.size() == trk_stats_fw.n_tracks);
233 assert(track_mat_fw.size() == track_mat_bw.size());
234 assert(step_traces_fw.size() == step_traces_bw.size());
235 assert(mat_steps_fw.size() == mat_steps_bw.size());
236
237 // Check stats
238 n_tracks = static_cast<double>(trk_stats_bw.n_tracks);
239 if (static_cast<double>(trk_stats_bw.n_tracks_w_holes) / n_tracks >
240 cfg.max_percent_missed / 100.) {
241 DETRAY_ERROR_HOST("Too many tracks with missing surfaces");
242 test_successful = false;
243 }
244 if (static_cast<double>(trk_stats_bw.n_tracks_w_extra) / n_tracks >
245 cfg.max_percent_additional / 100.) {
246 DETRAY_ERROR_HOST("Too many tracks with additional surfaces");
247 test_successful = false;
248 }
249
250 std::cout << "\n-----------------------------------\n"
251 << "MATERIAL TRACE" << std::endl
252 << "-----------------------------------\n";
253
254 constexpr double rel_mat_error{0.01};
255
256 // Material traces contain different surfaces
257 std::size_t n_bad_comp{0u};
258 // Overall integrated material differs while surface seq. is identical
259 std::size_t n_diff_mat{0u};
260
261 // Loop over tracks
262 for (std::size_t i = 0u; i < track_mat_fw.size(); ++i) {
263 // No material on that track (e.g. detector model without material)
264 if (mat_steps_fw[i].empty() && mat_steps_bw[i].empty()) {
265 continue;
266 }
267
268 std::remove_cvref_t<decltype(mat_steps_bw[i])> inv_mat_trace_bw{};
269 if (!mat_steps_bw[i].empty()) {
270 inv_mat_trace_bw.resize(mat_steps_bw[i].size());
271
272 // Revert the backward trace to compare to the forward trace
273 std::ranges::reverse_copy(mat_steps_bw[i], inv_mat_trace_bw.begin());
274
275 assert(mat_steps_bw[i].size() == inv_mat_trace_bw.size());
276 }
277
278 // Compare the material traces and total integrated material per trk
279 const auto [is_bad_comp, is_diff_mat] = material_validator::compare_traces(
280 mat_steps_fw[i], track_mat_fw[i], inv_mat_trace_bw, track_mat_bw[i], i,
281 rel_mat_error, test_cfg.verbose());
282
283 if (is_bad_comp) {
284 n_bad_comp++;
285 }
286 if (is_diff_mat) {
287 n_diff_mat++;
288 }
289 }
290
291 std::cout << "Total no. tracks with diff. material: "
292 << (n_bad_comp + n_diff_mat) << " ("
293 << 100. * static_cast<double>(n_bad_comp + n_diff_mat) / n_tracks
294 << "%)" << std::endl;
295
296 std::cout << "No. identical tracks with diff. material: " << n_diff_mat
297 << " (" << 100. * static_cast<double>(n_diff_mat) / n_tracks << "%)"
298 << std::endl;
299 std::cout << "-----------------------------------\n" << std::endl;
300
301 // Trigger test failures
302 if (n_diff_mat != 0) {
303 DETRAY_ERROR_HOST("" << n_diff_mat << " tracks have differing material");
304 test_successful = false;
305 }
306
307 return test_successful;
308}
309
310} // namespace detray
The interface to the actors and aborters in the propagation.
Definition actor_chain.hpp:35
Runge-Kutta-Nystrom 4th order stepper implementation.
Definition rk_stepper.hpp:51
Detray include(s).
Definition array_operators.hpp:18
get_scalar_t< A, T > dscalar
Scalar type for algebra A and value type T.
Definition algebra.hpp:64
constexpr detray::tuple< std::decay_t< Ts >... > make_tuple(Ts &&...vs)
Construct a tuple by decaying and forwarding its arguments.
Definition tuple.hpp:219
vecmem::vector< value_t > dvector
Vector container backed by vecmem.
Definition containers.hpp:34
constexpr detray::tuple< Ts &... > tie(Ts &...args)
Create a tuple of references to the supplied objects.
Definition tuple.hpp:211
detray::tuple< types... > dtuple
Tuple type used by detray storage and dispatch.
Definition containers.hpp:46
free_parameters_vector< algebra_t > free_track_parameters
The free track parameters consist only of the parameter vector.
Definition free_track_parameters.hpp:249
bool propagation_validation(const detector_t &det, const typename detector_t::name_map &names, const std::optional< bfield_view_t > &bfield, const propagation_validation_config< typename detector_t::scalar_type > &cfg, const std::vector< free_track_parameters< typename detector_t::algebra_type > > &tracks, std::vector< dvector< intersection_record< detector_t > > > &truth_traces_fw)
Run a detray propagation and compare the surfaces that were encountered against a reference of truth ...
Definition propagation_validation.hpp:67
Apply energy-loss and multiple-scattering effects at material surfaces.
Definition pointwise_material_interactor.hpp:33
Record of a surface intersection along a track.
Definition data_record.hpp:27
Negative muon hypothesis.
Definition pdg_particle.hpp:111
float accumulated_error
Percentage of total track path to assume as accumulated error.
Definition navigation_config.hpp:34
int n_scattering_stddev
Number of standard deviations to assume to model the scattering noise.
Definition navigation_config.hpp:36
bool estimate_scattering_noise
Add adaptive mask tolerance to navigation.
Definition navigation_config.hpp:38
Particle hypothesis identified by PDG number, mass, and electric charge.
Definition pdg_particle.hpp:24
Per-actor configuration for checking the perigee.
Definition perigee_stopper.hpp:36
Actor that exits from a navigation stream, if it has reached the perigee.
Definition perigee_stopper.hpp:31
Configuration of the propagation.
Definition propagation_config.hpp:23
navigation::config navigation
Navigation options controlling candidate selection and stopping.
Definition propagation_config.hpp:25
Configure the Kalman Filter comparison test.
Definition propagation_validation.hpp:35
float max_percent_additional
Maximum allowed percentage of tracks with additional surfaces.
Definition propagation_validation.hpp:52
bool do_energy_loss
Whether energy loss is enabled.
Definition propagation_validation.hpp:45
propagation::config propagation
Propagation settings for the validation.
Definition propagation_validation.hpp:37
bool do_multiple_scattering
Whether multiple scattering is enabled.
Definition propagation_validation.hpp:43
pdg_particle< scalar_t > particle
Particle hypothesis used for propagation.
Definition propagation_validation.hpp:40
float max_percent_missed
Maximum allowed percentage of tracks with missed surfaces.
Definition propagation_validation.hpp:50
bool display_svg
Whether SVG output is enabled.
Definition propagation_validation.hpp:48
Specific navigation policy for the Runge-Kutta stepper: Use the relative amount of step size correcti...
Definition policies.hpp:101
A stepper inspector that prints information about the current stepper state.
Definition inspectors.hpp:371
Configuration for a detector scan test.
Definition navigation_validation_config.hpp:30
bool collect_sensitives_only() const
Check whether only sensitive surfaces are collected.
Definition navigation_validation_config.hpp:95
bool fail_on_diff() const
Check whether validation stops at the first difference.
Definition navigation_validation_config.hpp:104
bool display_svg() const
Check whether SVG output is enabled.
Definition navigation_validation_config.hpp:98
navigation::direction navigation_direction() const
Get the navigation direction.
Definition navigation_validation_config.hpp:92
bool verbose() const
Check whether verbose output is enabled.
Definition navigation_validation_config.hpp:107
pdg_particle< scalar_type > ptc_hypothesis() const
Get the particle hypothesis.
Definition navigation_validation_config.hpp:89
std::size_t n_tracks() const
Get the maximum number of tracks.
Definition navigation_validation_config.hpp:86
bool display_only_missed() const
Check whether SVG output is limited to missed surfaces.
Definition navigation_validation_config.hpp:101
const std::string & name() const
GettersGet the test name.
Definition navigation_validation_config.hpp:77