diff --git a/Core/include/Acts/TrackFitting/BetheHeitlerApprox.hpp b/Core/include/Acts/TrackFitting/BetheHeitlerApprox.hpp index 653bef7e899..666ebf6aa23 100644 --- a/Core/include/Acts/TrackFitting/BetheHeitlerApprox.hpp +++ b/Core/include/Acts/TrackFitting/BetheHeitlerApprox.hpp @@ -125,6 +125,7 @@ class AtlasBetheHeitlerApprox { constexpr static double m_singleGaussianLimit = 0.002; double m_lowLimit = 0.10; double m_highLimit = 0.20; + bool m_clampToRange = false; public: /// Construct the Bethe-Heitler approximation description with two @@ -138,16 +139,19 @@ class AtlasBetheHeitlerApprox { /// @param highTransform whether the high data need to be transformed /// @param lowLimit the upper limit for the low data /// @param highLimit the upper limit for the high data + /// @param clampToRange whether to clamp the input x/x0 to the allowed range constexpr AtlasBetheHeitlerApprox(const Data &lowData, const Data &highData, bool lowTransform, bool highTransform, double lowLimit = 0.1, - double highLimit = 0.2) + double highLimit = 0.2, + bool clampToRange = false) : m_lowData(lowData), m_highData(highData), m_lowTransform(lowTransform), m_highTransform(highTransform), m_lowLimit(lowLimit), - m_highLimit(highLimit) {} + m_highLimit(highLimit), + m_clampToRange(clampToRange) {} /// Returns the number of components the returned mixture will have constexpr auto numComponents() const { return NComponents; } @@ -155,7 +159,13 @@ class AtlasBetheHeitlerApprox { /// Checks if an input is valid for the parameterization /// /// @param x pathlength in terms of the radiation length - constexpr bool validXOverX0(ActsScalar x) const { return x < m_highLimit; } + constexpr bool validXOverX0(ActsScalar x) const { + if (m_clampToRange) { + return true; + } else { + return x < m_highLimit; + } + } /// Generates the mixture from the polynomials and reweights them, so /// that the sum of all weights is 1 @@ -164,6 +174,11 @@ class AtlasBetheHeitlerApprox { auto mixture(ActsScalar x) const { using Array = boost::container::static_vector; + + if (m_clampToRange) { + x = std::clamp(x, 0.0, m_highLimit); + } + // Build a polynom auto poly = [](ActsScalar xx, const std::array &coeffs) { @@ -238,9 +253,11 @@ class AtlasBetheHeitlerApprox { /// the parameterization for high x/x0 /// @param lowLimit the upper limit for the low x/x0-data /// @param highLimit the upper limit for the high x/x0-data + /// @param clampToRange forwarded to constructor static auto loadFromFiles(const std::string &low_parameters_path, const std::string &high_parameters_path, - double lowLimit = 0.1, double highLimit = 0.2) { + double lowLimit = 0.1, double highLimit = 0.2, + bool clampToRange = false) { auto read_file = [](const std::string &filepath) { std::ifstream file(filepath); @@ -284,7 +301,8 @@ class AtlasBetheHeitlerApprox { const auto [highData, highTransform] = read_file(high_parameters_path); return AtlasBetheHeitlerApprox(lowData, highData, lowTransform, - highTransform, lowLimit, highLimit); + highTransform, lowLimit, highLimit, + clampToRange); } }; @@ -292,6 +310,7 @@ class AtlasBetheHeitlerApprox { /// configuration, that are stored as static data in the source code. /// This may not be an optimal configuration, but should allow to run /// the GSF without the need to load files -AtlasBetheHeitlerApprox<6, 5> makeDefaultBetheHeitlerApprox(); +AtlasBetheHeitlerApprox<6, 5> makeDefaultBetheHeitlerApprox( + bool clampToRange = false); } // namespace Acts diff --git a/Core/src/TrackFitting/BetheHeitlerApprox.cpp b/Core/src/TrackFitting/BetheHeitlerApprox.cpp index b19b9921902..272d6e08c8d 100644 --- a/Core/src/TrackFitting/BetheHeitlerApprox.cpp +++ b/Core/src/TrackFitting/BetheHeitlerApprox.cpp @@ -8,7 +8,8 @@ #include "Acts/TrackFitting/BetheHeitlerApprox.hpp" -Acts::AtlasBetheHeitlerApprox<6, 5> Acts::makeDefaultBetheHeitlerApprox() { +Acts::AtlasBetheHeitlerApprox<6, 5> Acts::makeDefaultBetheHeitlerApprox( + bool clampToRange) { // Tracking/TrkFitter/TrkGaussianSumFilterUtils/Data/BetheHeitler_cdf_nC6_O5.par // clang-format off constexpr static AtlasBetheHeitlerApprox<6, 5>::Data cdf_cmps6_order5_data = {{ @@ -51,6 +52,7 @@ Acts::AtlasBetheHeitlerApprox<6, 5> Acts::makeDefaultBetheHeitlerApprox() { }}; // clang-format on - return AtlasBetheHeitlerApprox<6, 5>( - cdf_cmps6_order5_data, cdf_cmps6_order5_data, true, true, 0.2, 0.2); + return AtlasBetheHeitlerApprox<6, 5>(cdf_cmps6_order5_data, + cdf_cmps6_order5_data, true, true, 0.2, + 0.2, clampToRange); } diff --git a/Examples/Python/python/acts/examples/reconstruction.py b/Examples/Python/python/acts/examples/reconstruction.py index 3bb898ca998..371345a17b5 100644 --- a/Examples/Python/python/acts/examples/reconstruction.py +++ b/Examples/Python/python/acts/examples/reconstruction.py @@ -1375,8 +1375,13 @@ def addTruthTrackingGsf( ) -> None: customLogLevel = acts.examples.defaultLogging(s, logLevel) + # NOTE we specify clampToRange as True to silence warnings in the test about + # queries to the loss distribution outside the specified range, since no dedicated + # approximation for the ODD is done yet. + bha = acts.examples.AtlasBetheHeitlerApprox.makeDefault(clampToRange=True) + gsfOptions = { - "betheHeitlerApprox": acts.examples.AtlasBetheHeitlerApprox.makeDefault(), + "betheHeitlerApprox": bha, "maxComponents": 12, "componentMergeMethod": acts.examples.ComponentMergeMethod.maxWeight, "mixtureReductionAlgorithm": acts.examples.MixtureReductionAlgorithm.KLDistance, diff --git a/Examples/Python/src/TrackFitting.cpp b/Examples/Python/src/TrackFitting.cpp index 20c6010c8ee..c8dc72f9eef 100644 --- a/Examples/Python/src/TrackFitting.cpp +++ b/Examples/Python/src/TrackFitting.cpp @@ -39,6 +39,7 @@ namespace py = pybind11; using namespace ActsExamples; using namespace Acts; +using namespace py::literals; namespace Acts::Python { @@ -106,12 +107,17 @@ void addTrackFitting(Context& ctx) { .value("KLDistance", MixtureReductionAlgorithm::KLDistance); py::class_(mex, "AtlasBetheHeitlerApprox") - .def_static("loadFromFiles", - &ActsExamples::BetheHeitlerApprox::loadFromFiles, - py::arg("lowParametersPath"), py::arg("highParametersPath"), - py::arg("lowLimit") = 0.1, py::arg("highLimit") = 0.2) - .def_static("makeDefault", - []() { return Acts::makeDefaultBetheHeitlerApprox(); }); + .def_static( + "loadFromFiles", &ActsExamples::BetheHeitlerApprox::loadFromFiles, + "lowParametersPath"_a, "highParametersPath"_a, "lowLimit"_a = 0.1, + "highLimit"_a = 0.2, "clampToRange"_a = false) + .def_static( + "makeDefault", + [](bool clampToRange) { + return Acts::makeDefaultBetheHeitlerApprox(clampToRange); + }, + "clampToRange"_a = false); + mex.def( "makeGsfFitterFunction", [](std::shared_ptr trackingGeometry, diff --git a/Examples/Python/tests/root_file_hashes.txt b/Examples/Python/tests/root_file_hashes.txt index 39df454b3e8..54c81ea9ba1 100644 --- a/Examples/Python/tests/root_file_hashes.txt +++ b/Examples/Python/tests/root_file_hashes.txt @@ -74,10 +74,10 @@ test_exatrkx[cpu-torch]__performance_track_finding.root: 36b3045589c4c17c038dbc8 test_exatrkx[gpu-onnx]__performance_track_finding.root: 9090de10ffb1489d3f1993e2a3081a3038227e3e5c453e98a9a4f33ea3d6d817 test_exatrkx[gpu-torch]__performance_track_finding.root: 36b3045589c4c17c038dbc87943366f4af4440f7eea6887afb763871ac149b05 test_ML_Ambiguity_Solver__performance_ambiML.root: 284ff5c3a08c0b810938e4ac2f8ba8fe2babb17d4c202b624ed69fff731a9006 -test_refitting[odd]__trackstates_gsf_refit.root: a61fe2d80d5d10d3b3505000e8abb589d88302bf5f54b625948793418f2a7fe8 -test_refitting[odd]__tracksummary_gsf_refit.root: 082789fc1a85e578b3cf9a750723d2dcee01b5019e871c6a63e0b271f4e907b1 -test_refitting[generic]__trackstates_gsf_refit.root: 9fa7af9eff12081504c0d648f6debae64f6996e0ca610cf58187d23aa5a13251 -test_refitting[generic]__tracksummary_gsf_refit.root: 35b5ac6f208cae093fff94038d217a2e9915a5ce075da2a95718dda696f2d4a2 +test_refitting[odd]__trackstates_gsf_refit.root: e297749dc1e7eda3b8dea13defa0499986c584740d93e723a901b498b8e90c71 +test_refitting[odd]__tracksummary_gsf_refit.root: d5085882e45a0b699194dff9f40a36e9291227bf65f9aaaf9087f9242ef5ae22 +test_refitting[generic]__trackstates_gsf_refit.root: 4424fdf2f27575db825c1a59f8e53a1595946211cbd5b2c8d3a2f71cdcc77ae9 +test_refitting[generic]__tracksummary_gsf_refit.root: 562deecee4cfb97ceee72eff53d63da079e3249fb62d6bcd556e6f27d495dfd9 test_truth_tracking_kalman[generic-False-0.0]__trackstates_kf.root: 9f77962b92037cb760b1629a602b1dae61f45e659c45d9a87baa784f6190960e test_truth_tracking_kalman[generic-False-0.0]__tracksummary_kf.root: 562deecee4cfb97ceee72eff53d63da079e3249fb62d6bcd556e6f27d495dfd9 test_truth_tracking_kalman[generic-False-1000.0]__trackstates_kf.root: 56a1bd989b9c1316b9098c65fa75df9e6683e62e35ae68d8f72d27220be0fd7d diff --git a/Examples/Python/tests/test_examples.py b/Examples/Python/tests/test_examples.py index 0e34a8a3c1c..d5bb593ca9f 100644 --- a/Examples/Python/tests/test_examples.py +++ b/Examples/Python/tests/test_examples.py @@ -689,7 +689,7 @@ def test_refitting(tmp_path, detector_config, assert_root_hash): field = acts.ConstantBField(acts.Vector3(0, 0, 2 * u.T)) seq = Sequencer( - events=3, + events=10, numThreads=1, ) diff --git a/Examples/Scripts/Python/truth_tracking_gsf_refitting.py b/Examples/Scripts/Python/truth_tracking_gsf_refitting.py index 797bfc59569..e8b41c9aae8 100755 --- a/Examples/Scripts/Python/truth_tracking_gsf_refitting.py +++ b/Examples/Scripts/Python/truth_tracking_gsf_refitting.py @@ -25,8 +25,13 @@ def runRefittingGsf( s=s, ) + # NOTE we specify clampToRange as True to silence warnings in the test about + # queries to the loss distribution outside the specified range, since no dedicated + # approximation for the ODD is done yet. + bha = acts.examples.AtlasBetheHeitlerApprox.makeDefault(clampToRange=True) + gsfOptions = { - "betheHeitlerApprox": acts.examples.AtlasBetheHeitlerApprox.makeDefault(), + "betheHeitlerApprox": bha, "maxComponents": 12, "componentMergeMethod": acts.examples.ComponentMergeMethod.maxWeight, "mixtureReductionAlgorithm": acts.examples.MixtureReductionAlgorithm.KLDistance,