Skip to content

Commit c5e3e62

Browse files
authored
Add tests for momentum resolution validation (acts-project#820)
1 parent 6fe03f5 commit c5e3e62

File tree

7 files changed

+549
-12
lines changed

7 files changed

+549
-12
lines changed

performance/include/traccc/utils/ranges.hpp

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,29 @@
1616

1717
namespace traccc {
1818

19+
template <typename scalar_t>
20+
TRACCC_HOST_DEVICE inline scalar_t eta_to_theta(const scalar_t eta) {
21+
return 2.f * math::atan(std::exp(-eta));
22+
}
23+
24+
template <typename scalar_t>
25+
TRACCC_HOST_DEVICE inline scalar_t theta_to_eta(const scalar_t theta) {
26+
return -math::log(math::tan(theta * 0.5f));
27+
}
28+
1929
template <typename range_t>
2030
TRACCC_HOST_DEVICE inline range_t eta_to_theta_range(const range_t& eta_range) {
2131
// @NOTE: eta_range[0] is converted to theta_range[1] and eta_range[1]
2232
// to theta_range[0] because theta(minEta) > theta(maxEta)
23-
return {2.f * math::atan(std::exp(-eta_range[1])),
24-
2.f * math::atan(std::exp(-eta_range[0]))};
33+
return {eta_to_theta(eta_range[1]), eta_to_theta(eta_range[0])};
2534
}
2635

2736
template <typename range_t>
2837
TRACCC_HOST_DEVICE inline range_t theta_to_eta_range(
2938
const range_t& theta_range) {
3039
// @NOTE: theta_range[0] is converted to eta_range[1] and theta_range[1]
3140
// to eta_range[0]
32-
return {-math::log(math::tan(theta_range[1] * 0.5f)),
33-
-math::log(math::tan(theta_range[0] * 0.5f))};
41+
return {theta_to_eta(theta_range[1]), theta_to_eta(theta_range[0])};
3442
}
3543

3644
} // namespace traccc

tests/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@ add_library( traccc_tests_common STATIC
1313
"common/tests/cca_test.hpp"
1414
"common/tests/ckf_telescope_test.hpp"
1515
"common/tests/data_test.hpp"
16+
"common/tests/kalman_fitting_momentum_resolution_test.hpp"
1617
"common/tests/kalman_fitting_test.hpp"
1718
"common/tests/kalman_fitting_telescope_test.hpp"
1819
"common/tests/kalman_fitting_toy_detector_test.hpp"
1920
"common/tests/kalman_fitting_wire_chamber_test.hpp"
21+
"common/tests/kalman_fitting_momentum_resolution_test.cpp"
2022
"common/tests/kalman_fitting_test.cpp" )
2123
target_include_directories( traccc_tests_common
2224
PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/common )
Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
/** TRACCC library, part of the ACTS project (R&D line)
2+
*
3+
* (c) 2025 CERN for the benefit of the ACTS project
4+
*
5+
* Mozilla Public License Version 2.0
6+
*/
7+
8+
#include <cmath>
9+
10+
// Local include(s).
11+
#include "kalman_fitting_momentum_resolution_test.hpp"
12+
13+
// ROOT include(s).
14+
#ifdef TRACCC_HAVE_ROOT
15+
#include <TF1.h>
16+
#include <TFile.h>
17+
#include <TFitResult.h>
18+
#include <TFitResultPtr.h>
19+
#include <TH1.h>
20+
#endif // TRACCC_HAVE_ROOT
21+
22+
// System include(s).
23+
#include <iostream>
24+
#include <memory>
25+
#include <stdexcept>
26+
27+
namespace traccc {
28+
29+
void KalmanFittingMomentumResolutionTests::consistency_tests(
30+
const track_state_collection_types::host& track_states_per_track) const {
31+
32+
// The nubmer of track states is supposed be equal to the number
33+
// of planes
34+
ASSERT_EQ(track_states_per_track.size(), std::get<11>(GetParam()));
35+
}
36+
37+
void KalmanFittingMomentumResolutionTests::momentum_resolution_tests([
38+
[maybe_unused]] std::string_view file_name) const {
39+
40+
#ifdef TRACCC_HAVE_ROOT
41+
42+
// Open the file with the histograms.
43+
std::unique_ptr<TFile> ifile(TFile::Open(file_name.data(), "READ"));
44+
if ((!ifile) || ifile->IsZombie()) {
45+
throw std::runtime_error(std::string("Could not open file \"") +
46+
file_name.data() + "\"");
47+
}
48+
49+
// Access the histogram.
50+
TH1* residual_qopT_hist = dynamic_cast<TH1*>(ifile->Get("res_qopT"));
51+
if (!residual_qopT_hist) {
52+
throw std::runtime_error(
53+
std::string("Could not access histogram residual_qopT in file \"") +
54+
file_name.data() + "\"");
55+
}
56+
57+
// Function used for the fit.
58+
TF1 gaus{"gaus", "gaus", -5, 5};
59+
double fit_par[3];
60+
61+
// Set the mean seed to 0
62+
gaus.SetParameters(1, 0.);
63+
gaus.SetParLimits(1, -1., 1.);
64+
65+
// Set the standard deviation seed to 0.01
66+
gaus.SetParameters(2, 0.01f);
67+
gaus.SetParLimits(2, 0.f, 0.1f);
68+
69+
auto res = residual_qopT_hist->Fit("gaus", "Q0S");
70+
71+
gaus.GetParameters(&fit_par[0]);
72+
73+
// Mean check
74+
EXPECT_NEAR(fit_par[1], 0, 0.05) << " Residual qopT mean value error";
75+
76+
// Expected momentum resolution
77+
const std::size_t N = std::get<11>(GetParam());
78+
const auto smearing = std::get<15>(GetParam());
79+
const scalar epsilon = smearing[0u];
80+
const scalar Bz = std::get<13>(GetParam())[2u];
81+
const scalar spacing = std::get<12>(GetParam());
82+
const scalar L = static_cast<scalar>(N - 1u) * spacing;
83+
84+
// Curvature (1/helix_radius) resolution from detector noise Eq. (35.61) of
85+
// PDG 2024
86+
const scalar dkres =
87+
epsilon / (L * L) * math::sqrt(720.f / static_cast<scalar>(N + 4));
88+
89+
// Curvature (1/helix_radius) resolution from multiple scattering Eq.
90+
// (35.63) of PDG 2024
91+
// @NOTE: The calculation of the multiple scattering term is in work in
92+
// progress. Currently we are validating the momentum resolution without any
93+
// material on the modules, therefore, the multiple scattering contribution
94+
// to the momentum resolution is set to zero.
95+
const scalar dkms = 0.f;
96+
97+
// Eq. (35.60) of PDG 2024
98+
const scalar dk = math::sqrt(dkres * dkres + dkms * dkms);
99+
100+
// σ(q/pT) = σ(k/B) = σ(k)/B
101+
const scalar expected_sigma_qopT = dk / Bz;
102+
103+
// Check if the standard deviation of the qopT residuals is within the
104+
// theoretically expected range.
105+
EXPECT_NEAR(fit_par[2], expected_sigma_qopT, expected_sigma_qopT * 0.05f)
106+
<< " Residual qopT sigma value error";
107+
108+
#else
109+
std::cout << "Pull value tests not performed without ROOT" << std::endl;
110+
#endif // TRACCC_HAVE_ROOT
111+
112+
return;
113+
}
114+
115+
void KalmanFittingMomentumResolutionTests::SetUp() {
116+
117+
vecmem::host_memory_resource host_mr;
118+
119+
const scalar offset = std::get<10>(GetParam());
120+
const unsigned int n_planes = std::get<11>(GetParam());
121+
const scalar spacing = std::get<12>(GetParam());
122+
123+
std::vector<scalar> plane_positions;
124+
for (unsigned int i = 0; i < n_planes; i++) {
125+
plane_positions.push_back(offset * unit<scalar>::mm +
126+
static_cast<scalar>(i) * spacing *
127+
unit<scalar>::mm);
128+
}
129+
130+
/// Plane alignment direction (aligned to x-axis)
131+
const vector3 bfield = std::get<13>(GetParam());
132+
133+
const auto p = std::get<3>(GetParam());
134+
const detray::detail::helix<traccc::default_algebra> hlx(
135+
{0, 0, 0}, 0, {1, 0, 0}, -1.f / p, &bfield);
136+
137+
constexpr scalar rect_half_length = 500.f;
138+
constexpr detray::mask<detray::rectangle2D, traccc::default_algebra>
139+
rectangle{0u, rect_half_length, rect_half_length};
140+
141+
detray::tel_det_config<default_algebra, detray::rectangle2D,
142+
detray::detail::helix>
143+
tel_cfg(rectangle, hlx);
144+
tel_cfg.positions(plane_positions);
145+
tel_cfg.module_material(std::get<14>(GetParam()));
146+
tel_cfg.mat_thickness(thickness);
147+
tel_cfg.envelope(rect_half_length);
148+
149+
// Create telescope detector
150+
auto [det, name_map] = build_telescope_detector(host_mr, tel_cfg);
151+
152+
// Write detector file
153+
auto writer_cfg = detray::io::detector_writer_config{}
154+
.format(detray::io::format::json)
155+
.replace_files(true)
156+
.write_material(true)
157+
.path(std::get<0>(GetParam()));
158+
detray::io::write_detector(det, name_map, writer_cfg);
159+
}
160+
161+
} // namespace traccc
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
/** TRACCC library, part of the ACTS project (R&D line)
2+
*
3+
* (c) 2025 CERN for the benefit of the ACTS project
4+
*
5+
* Mozilla Public License Version 2.0
6+
*/
7+
8+
#pragma once
9+
10+
// Project include(s).
11+
#include "kalman_fitting_test.hpp"
12+
13+
// Detray include(s).
14+
#include "detray/geometry/mask.hpp"
15+
#include "detray/geometry/shapes/rectangle2D.hpp"
16+
#include "detray/io/frontend/detector_writer.hpp"
17+
#include "detray/navigation/detail/ray.hpp"
18+
#include "detray/test/utils/detectors/build_telescope_detector.hpp"
19+
20+
namespace traccc {
21+
22+
/// Momentum Resolution Test with Telescope Detector
23+
///
24+
/// Test parameters:
25+
/// (1) name
26+
/// (2) origin
27+
/// (3) origin stddev
28+
/// (4) momentum range
29+
/// (5) eta range
30+
/// (6) phi range
31+
/// (7) particle type
32+
/// (8) number of tracks per event
33+
/// (9) number of events
34+
/// (10) random charge
35+
/// (11) offset from origin of the first plane in mm
36+
/// (12) Number of planes
37+
/// (13) Spacing between planes in mm
38+
/// (14) Magnetic field
39+
/// (15) Module material
40+
/// (16) Measurement smearing
41+
class KalmanFittingMomentumResolutionTests
42+
: public KalmanFittingTests,
43+
public testing::WithParamInterface<std::tuple<
44+
std::string, std::array<scalar, 3u>, std::array<scalar, 3u>, scalar,
45+
scalar, scalar, detray::pdg_particle<scalar>, unsigned int,
46+
unsigned int, bool, scalar, unsigned int, scalar, vector3,
47+
detray::material<scalar>, std::array<scalar, 2u>>> {
48+
49+
public:
50+
/// Plane thickness
51+
static constexpr scalar thickness = 0.5f * detray::unit<scalar>::mm;
52+
53+
/// Standard deviations for seed track parameters
54+
std::array<scalar, e_bound_size> stddevs = {
55+
5.f * detray::unit<scalar>::mm,
56+
5.f * detray::unit<scalar>::mm,
57+
0.05f,
58+
0.05f,
59+
0.1f / detray::unit<scalar>::GeV,
60+
1.f * detray::unit<scalar>::ns};
61+
62+
void consistency_tests(
63+
const track_state_collection_types::host& track_states_per_track) const;
64+
65+
void momentum_resolution_tests(std::string_view file_name) const;
66+
67+
protected:
68+
virtual void SetUp() override;
69+
};
70+
71+
} // namespace traccc

tests/cpu/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ traccc_add_test(cpu
1414
"test_clusterization_resolution.cpp"
1515
"test_copy.cpp"
1616
"test_kalman_fitter_hole_count.cpp"
17+
"test_kalman_fitter_momentum_resolution.cpp"
1718
"test_kalman_fitter_telescope.cpp"
1819
"test_kalman_fitter_wire_chamber.cpp"
1920
"test_ranges.cpp"

0 commit comments

Comments
 (0)