Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-05 08:18:37

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 // Detray core include(s)
0010 #include "detray/core/detector.hpp"
0011 
0012 // Detray propagation include(s)
0013 #include "detray/propagator/propagation_config.hpp"
0014 
0015 // Detray event generator include(s)
0016 #include "detray/test/common/event_generator/uniform_track_generator_config.hpp"
0017 
0018 // Detray test include(s)
0019 #include "detray/test/cpu/material_scan.hpp"
0020 #include "detray/test/cpu/material_validation.hpp"
0021 #include "detray/test/framework/register_checks.hpp"
0022 #include "detray/test/framework/test_configuration.hpp"
0023 #include "detray/test/framework/whiteboard.hpp"
0024 #include "detray/test/validation/material_validation_config.hpp"
0025 
0026 // Detray algebra plugin + detector metadata
0027 #include "algebra/array.hpp"
0028 #include "detray/definitions/algebra.hpp"
0029 #include "detray/detectors/default_metadata.hpp"
0030 
0031 // GTest include(s)
0032 #include <gtest/gtest.h>
0033 
0034 // Pybind11 include(s)
0035 #include <pybind11/pybind11.h>
0036 #include <pybind11/stl.h>
0037 
0038 // System include(s)
0039 #include <cstddef>
0040 #include <cstdint>
0041 #include <functional>
0042 #include <memory>
0043 #include <sstream>
0044 #include <stdexcept>
0045 #include <string>
0046 #include <tuple>
0047 #include <utility>
0048 
0049 namespace py = pybind11;
0050 
0051 namespace {
0052 
0053 using scalar_t = DETRAY_CUSTOM_SCALARTYPE;
0054 using algebra_t = detray::array<scalar_t>;
0055 using detector_t = detray::detector<detray::default_metadata<algebra_t>>;
0056 using material_scan_config_t = detray::test::material_scan<detector_t>::config;
0057 using propagation_config_t = detray::propagation::config;
0058 using track_generator_config_t =
0059     detray::uniform_track_generator_config<scalar_t>;
0060 using material_validation_config_t =
0061     detray::test::material_validation_config<algebra_t>;
0062 using base_config_t = detray::test::configuration<scalar_t>;
0063 
0064 template <typename T>
0065 std::string to_string(const T &obj) {
0066   std::ostringstream os;
0067   os << obj;
0068   return os.str();
0069 }
0070 
0071 /// Run gtest for checks registered in @p register_checks_fn
0072 ///
0073 /// Since the gtest state is global, this implementation can be run only once.
0074 int run_gtest(const std::function<void()> &register_checks_fn) {
0075   static bool already_run = false;
0076   if (already_run) {
0077     throw std::runtime_error("gtest can only be run once per process");
0078   }
0079   already_run = true;
0080 
0081   ::testing::InitGoogleTest();
0082   register_checks_fn();
0083   return RUN_ALL_TESTS();
0084 }
0085 
0086 /// Run the CPU material validation for the given detector.
0087 int run_material_validation(const detector_t &det,
0088                             const detray::name_map &names,
0089                             const material_scan_config_t &scan_cfg,
0090                             const material_validation_config_t &val_cfg) {
0091   detector_t::geometry_context ctx{};
0092   auto wb = std::make_shared<detray::test::whiteboard>();
0093 
0094   return run_gtest([&] {
0095     detray::test::register_checks<detray::test::material_scan>(
0096         det, names, scan_cfg, ctx, wb);
0097     detray::test::register_checks<detray::test::material_validation>(
0098         det, names, val_cfg, ctx, wb);
0099   });
0100 }
0101 
0102 }  // namespace
0103 
0104 PYBIND11_MODULE(DetrayTestsPythonBindings, m) {
0105   m.doc() = "Detray tests bindings";
0106 
0107   py::class_<track_generator_config_t>(m, "TrackGeneratorConfig")
0108       .def(py::init<>())
0109       .def_property(
0110           "seed", [](const track_generator_config_t &c) { return c.seed(); },
0111           [](track_generator_config_t &c, std::uint64_t s) { c.seed(s); },
0112           "Monte-Carlo seed")
0113       .def(
0114           "nTracks",
0115           [](const track_generator_config_t &c) { return c.n_tracks(); },
0116           "Total number of tracks")
0117       .def_property(
0118           "phiRange",
0119           [](const track_generator_config_t &c) {
0120             const auto r = c.phi_range();
0121             return std::make_pair(r[0], r[1]);
0122           },
0123           [](track_generator_config_t &c,
0124              const std::pair<scalar_t, scalar_t> &r) {
0125             c.phi_range(r.first, r.second);
0126           },
0127           "Phi range (min, max) (native rad)")
0128       .def_property(
0129           "thetaRange",
0130           [](const track_generator_config_t &c) {
0131             const auto r = c.theta_range();
0132             return std::make_pair(r[0], r[1]);
0133           },
0134           [](track_generator_config_t &c,
0135              const std::pair<scalar_t, scalar_t> &r) {
0136             c.theta_range(r.first, r.second);
0137           },
0138           "Theta range (min, max) (native rad)")
0139       .def_property(
0140           "etaRange",
0141           [](const track_generator_config_t &c) {
0142             const auto r = c.eta_range();
0143             return std::make_pair(r[0], r[1]);
0144           },
0145           [](track_generator_config_t &c,
0146              const std::pair<scalar_t, scalar_t> &r) {
0147             c.eta_range(r.first, r.second);
0148           },
0149           "Eta range (min, max)")
0150       .def_property(
0151           "phiSteps",
0152           [](const track_generator_config_t &c) { return c.phi_steps(); },
0153           [](track_generator_config_t &c, std::size_t n) { c.phi_steps(n); },
0154           "Number of phi steps")
0155       .def_property(
0156           "thetaSteps",
0157           [](const track_generator_config_t &c) { return c.theta_steps(); },
0158           [](track_generator_config_t &c, std::size_t n) { c.theta_steps(n); },
0159           "Number of theta steps")
0160       .def_property(
0161           "etaSteps",
0162           [](const track_generator_config_t &c) { return c.eta_steps(); },
0163           [](track_generator_config_t &c, std::size_t n) { c.eta_steps(n); },
0164           "Number of eta steps")
0165       .def_property(
0166           "uniformEta",
0167           [](const track_generator_config_t &c) { return c.uniform_eta(); },
0168           [](track_generator_config_t &c, bool b) { c.uniform_eta(b); },
0169           "Whether to step uniformly in eta")
0170       .def_property(
0171           "origin",
0172           [](const track_generator_config_t &c) {
0173             const auto &o = c.origin();
0174             return std::make_tuple(o[0], o[1], o[2]);
0175           },
0176           [](track_generator_config_t &c,
0177              const std::tuple<scalar_t, scalar_t, scalar_t> &o) {
0178             c.origin(std::get<0>(o), std::get<1>(o), std::get<2>(o));
0179           },
0180           "Track origin")
0181       .def(
0182           "pT",
0183           [](track_generator_config_t &c,
0184              scalar_t p) -> track_generator_config_t & { return c.p_T(p); },
0185           py::arg("p"), py::return_value_policy::reference,
0186           "Set the transverse momentum magnitude")
0187       .def(
0188           "pTot",
0189           [](track_generator_config_t &c,
0190              scalar_t p) -> track_generator_config_t & { return c.p_tot(p); },
0191           py::arg("p"), py::return_value_policy::reference,
0192           "Set the total momentum magnitude")
0193       .def(
0194           "momRange",
0195           [](const track_generator_config_t &c) {
0196             const auto r = c.mom_range();
0197             return std::make_pair(r[0], r[1]);
0198           },
0199           "Momentum range")
0200       .def_property(
0201           "randomizeCharge",
0202           [](const track_generator_config_t &c) {
0203             return c.randomize_charge();
0204           },
0205           [](track_generator_config_t &c, bool b) { c.randomize_charge(b); },
0206           "Randomly flip the charge sign")
0207       .def_property(
0208           "time", [](const track_generator_config_t &c) { return c.time(); },
0209           [](track_generator_config_t &c, scalar_t t) { c.time(t); },
0210           "Track time")
0211       .def_property(
0212           "charge",
0213           [](const track_generator_config_t &c) { return c.charge(); },
0214           [](track_generator_config_t &c, scalar_t q) { c.charge(q); },
0215           "Track charge")
0216       .def(
0217           "isPT", [](const track_generator_config_t &c) { return c.is_pT(); },
0218           "Whether the momentum magnitude is interpreted as transverse")
0219       .def("__repr__", &to_string<track_generator_config_t>);
0220 
0221   py::class_<base_config_t>(m, "TestConfig")
0222       .def_property(
0223           "tol", [](const base_config_t &c) { return c.tol(); },
0224           [](base_config_t &c, scalar_t t) { c.tol(t); },
0225           "Tolerance to compare two floating point values")
0226       .def_property(
0227           "propagation",
0228           [](base_config_t &c) -> propagation_config_t & {
0229             return c.propagation();
0230           },
0231           [](base_config_t &c, const propagation_config_t &v) {
0232             c.propagation() = v;
0233           },
0234           py::return_value_policy::reference_internal,
0235           "Propagation configuration");
0236 
0237   py::class_<material_validation_config_t, base_config_t>(
0238       m, "MaterialValidationConfig")
0239       .def(py::init<>())
0240       .def_property(
0241           "name",
0242           [](const material_validation_config_t &c) { return c.name(); },
0243           [](material_validation_config_t &c, const std::string &n) {
0244             c.name(n);
0245           },
0246           "Name of the test")
0247       .def_property(
0248           "materialFile",
0249           [](const material_validation_config_t &c) {
0250             return c.material_file();
0251           },
0252           [](material_validation_config_t &c, const std::string &f) {
0253             c.material_file(f);
0254           },
0255           "Name of the output file with the navigation material traces")
0256       .def_property(
0257           "nTracks",
0258           [](const material_validation_config_t &c) { return c.n_tracks(); },
0259           [](material_validation_config_t &c, std::size_t n) { c.n_tracks(n); },
0260           "Maximal number of test tracks to run")
0261       .def_property(
0262           "relativeError",
0263           [](const material_validation_config_t &c) {
0264             return c.relative_error();
0265           },
0266           [](material_validation_config_t &c, scalar_t re) {
0267             c.relative_error(re);
0268           },
0269           "Allowed relative discrepancy between truth and navigation material")
0270       .def("__repr__", &to_string<material_validation_config_t>);
0271 
0272   py::class_<material_scan_config_t, base_config_t>(m, "MaterialScanConfig")
0273       .def(py::init<>())
0274       .def_property(
0275           "name", [](const material_scan_config_t &c) { return c.name(); },
0276           [](material_scan_config_t &c, const std::string &n) { c.name(n); },
0277           "Name of the test")
0278       .def_property(
0279           "materialFile",
0280           [](const material_scan_config_t &c) { return c.material_file(); },
0281           [](material_scan_config_t &c, const std::string &f) {
0282             c.material_file(f);
0283           },
0284           "Name of the output file with the material traces")
0285       .def_property(
0286           "overlapsRemoval",
0287           [](const material_scan_config_t &c) { return c.overlaps_removal(); },
0288           [](material_scan_config_t &c, bool o) { c.overlaps_removal(o); },
0289           "Perform overlaps removal")
0290       .def_property(
0291           "overlapsTol",
0292           [](const material_scan_config_t &c) { return c.overlaps_tol(); },
0293           [](material_scan_config_t &c, scalar_t t) { c.overlaps_tol(t); },
0294           "Tolerance for considering surfaces to be overlapping")
0295       .def_property(
0296           "trackGenerator",
0297           [](material_scan_config_t &c) -> track_generator_config_t & {
0298             return c.track_generator();
0299           },
0300           [](material_scan_config_t &c, const track_generator_config_t &v) {
0301             c.track_generator() = v;
0302           },
0303           py::return_value_policy::reference_internal,
0304           "Track generator configuration")
0305       .def("__repr__", &to_string<material_scan_config_t>);
0306 
0307   m.def("runMaterialValidation", &run_material_validation, py::arg("detector"),
0308         py::arg("names"), py::arg("scanConfig"), py::arg("validationConfig"),
0309         "Run the CPU material validation for the given detector.");
0310 }