From ebed7e8e59b7a087095b54f94bee408a3a444e20 Mon Sep 17 00:00:00 2001 From: Joana Niermann Date: Fri, 27 Oct 2023 16:36:13 +0200 Subject: [PATCH] Add utility to generate detector files for the detray inbuilt detectors --- .../intersection/detail/trajectories.hpp | 3 + .../common/detail/detector_components_io.hpp | 7 +- io/include/detray/io/common/detail/utils.hpp | 22 +-- .../detray/io/common/detector_writer.hpp | 16 ++- io/include/detray/io/common/io_interface.hpp | 5 +- io/include/detray/io/json/json_writer.hpp | 11 +- tests/CMakeLists.txt | 1 + tests/detectors/CMakeLists.txt | 7 + tests/detectors/src/CMakeLists.txt | 24 ++++ .../src/generate_telescope_detector.cpp | 132 ++++++++++++++++++ tests/detectors/src/generate_toy_detector.cpp | 74 ++++++++++ tests/detectors/src/generate_wire_chamber.cpp | 78 +++++++++++ .../unit_tests/io/io_json_detector_writer.cpp | 4 +- .../detectors/create_telescope_detector.hpp | 4 + 14 files changed, 368 insertions(+), 20 deletions(-) create mode 100644 tests/detectors/CMakeLists.txt create mode 100644 tests/detectors/src/CMakeLists.txt create mode 100644 tests/detectors/src/generate_telescope_detector.cpp create mode 100644 tests/detectors/src/generate_toy_detector.cpp create mode 100644 tests/detectors/src/generate_wire_chamber.cpp diff --git a/core/include/detray/intersection/detail/trajectories.hpp b/core/include/detray/intersection/detail/trajectories.hpp index ff800806e..fbf608874 100644 --- a/core/include/detray/intersection/detail/trajectories.hpp +++ b/core/include/detray/intersection/detail/trajectories.hpp @@ -82,6 +82,9 @@ class ray { return this->dir(); } + /// @param dir new direction of the ray + DETRAY_HOST_DEVICE void set_dir(vector3 dir) { _dir = dir; } + /// @returns overstep tolerance to comply with track interface DETRAY_HOST_DEVICE scalar_type overstep_tolerance() const { return _overstep_tolerance; } diff --git a/io/include/detray/io/common/detail/detector_components_io.hpp b/io/include/detray/io/common/detail/detector_components_io.hpp index f33773ddc..37eb323d0 100644 --- a/io/include/detray/io/common/detail/detector_components_io.hpp +++ b/io/include/detray/io/common/detail/detector_components_io.hpp @@ -56,15 +56,16 @@ class detector_component_writers final { /// writers, while using the name map @param names for the detector virtual void write(const detector_t& det, const typename detector_t::name_map& names, - const std::ios_base::openmode mode) { + const std::ios_base::openmode mode, + const std::filesystem::path& file_path) { // We have to at least write a geometry assert(m_writers.size() != 0u && "No writers registered! Need at least a geometry writer"); // Call the write method on all optional writers std::for_each(m_writers.begin(), m_writers.end(), - [&det, &names, mode](writer_ptr_t& writer) { - writer->write(det, names, mode); + [&det, &names, mode, &file_path](writer_ptr_t& writer) { + writer->write(det, names, mode, file_path); }); } diff --git a/io/include/detray/io/common/detail/utils.hpp b/io/include/detray/io/common/detail/utils.hpp index d4529461e..621bb9c93 100644 --- a/io/include/detray/io/common/detail/utils.hpp +++ b/io/include/detray/io/common/detail/utils.hpp @@ -12,6 +12,7 @@ // System include(s). #include +#include #include #include #include @@ -19,14 +20,19 @@ namespace detray::detail { -/// Generate the filename for every distinct event -inline std::string get_event_filename(std::size_t event, - const std::string& suffix) { - std::stringstream stream; - stream << "event"; - stream << std::setfill('0') << std::setw(9) << event; - stream << suffix; - return stream.str(); +/// Check if a given file path exists and generate it if not +inline auto create_path(const std::string& outdir) { + + auto path = std::filesystem::path(outdir); + + if (not std::filesystem::exists(path)) { + std::error_code err; + if (!std::filesystem::create_directories(path, err)) { + throw std::runtime_error(err.message()); + } + } + + return path; } /// @returns a string that contains the current date and time diff --git a/io/include/detray/io/common/detector_writer.hpp b/io/include/detray/io/common/detector_writer.hpp index 30784239f..de09ad8bd 100644 --- a/io/include/detray/io/common/detector_writer.hpp +++ b/io/include/detray/io/common/detector_writer.hpp @@ -10,9 +10,11 @@ // Project include(s) #include "detray/io/common/detail/detector_components_io.hpp" #include "detray/io/common/detail/type_traits.hpp" +#include "detray/io/common/detail/utils.hpp" #include "detray/io/json/json_writer.hpp" // System include(s) +#include #include namespace detray { @@ -21,6 +23,8 @@ namespace io { /// @brief config struct for detector writing. struct detector_writer_config { + /// The path to the output files + std::string m_path{"./"}; /// The output file format detray::io::format m_format = detray::io::format::json; /// Replace files in case they already exists @@ -34,6 +38,7 @@ struct detector_writer_config { /// Getters /// @{ + const std::string& path() const { return m_path; } detray::io::format format() const { return m_format; } bool replace_files() const { return m_replace; } bool compactify_json() const { return m_compact_io; } @@ -43,6 +48,10 @@ struct detector_writer_config { /// Setters /// @{ + detector_writer_config& path(std::string p) { + m_path = std::move(p); + return *this; + } detector_writer_config& format(detray::io::format f) { m_format = f; return *this; @@ -114,12 +123,15 @@ void write_detector(detector_t& det, const typename detector_t::name_map& names, // How to open the file const std::ios_base::openmode out_mode{std::ios_base::out | std::ios_base::binary}; - auto mode = cfg.m_replace ? (out_mode | std::ios_base::trunc) : out_mode; + auto mode = + cfg.replace_files() ? (out_mode | std::ios_base::trunc) : out_mode; + + const auto file_path = detray::detail::create_path(cfg.path()); // Get the writer auto writer = detray::detail::assemble_writer(cfg); - writer.write(det, names, mode); + writer.write(det, names, mode, file_path); } } // namespace io diff --git a/io/include/detray/io/common/io_interface.hpp b/io/include/detray/io/common/io_interface.hpp index 218fb4da8..46287a19f 100644 --- a/io/include/detray/io/common/io_interface.hpp +++ b/io/include/detray/io/common/io_interface.hpp @@ -13,6 +13,7 @@ #include "detray/tools/detector_builder.hpp" // System include(s) +#include #include #include #include @@ -66,9 +67,11 @@ class writer_interface { /// Writes the respective detector component to file. Since the detector /// does not provide the volume names, the name map is also passed. + /// @note The existence of the file path has to be guaranteed by the caller virtual std::string write(const detector_t&, const typename detector_t::name_map&, - const std::ios_base::openmode) = 0; + const std::ios_base::openmode, + const std::filesystem::path&) = 0; protected: /// Serialize the common header information using the detector name diff --git a/io/include/detray/io/json/json_writer.hpp b/io/include/detray/io/json/json_writer.hpp index 5345d307f..538640afd 100644 --- a/io/include/detray/io/json/json_writer.hpp +++ b/io/include/detray/io/json/json_writer.hpp @@ -17,6 +17,7 @@ // System include(s) #include +#include #include #include #include @@ -43,9 +44,10 @@ class json_writer final : public common_writer_t { json_writer() : base_writer(".json") {} /// Writes the geometry to file with a given name - virtual std::string write(const detector_t &det, - const typename detector_t::name_map &names, - const std::ios_base::openmode mode) override { + virtual std::string write( + const detector_t &det, const typename detector_t::name_map &names, + const std::ios_base::openmode mode = std::ios::out | std::ios::binary, + const std::filesystem::path &file_path = {"./"}) override { // Assert output stream assert(((mode == std::ios_base::out) or (mode == (std::ios_base::out | std::ios_base::binary)) or @@ -62,7 +64,8 @@ class json_writer final : public common_writer_t { // Create a new file std::string file_stem{det_name + "_" + base_writer::tag}; - io::detail::file_handle file{file_stem, this->m_file_extension, mode}; + io::detail::file_handle file{file_path / file_stem, + this->m_file_extension, mode}; // Write some general information nlohmann::ordered_json out_json; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 63600fa1f..163969681 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -26,5 +26,6 @@ if( DETRAY_BENCHMARKS ) add_subdirectory( benchmarks ) endif() add_subdirectory( common ) +add_subdirectory( detectors ) add_subdirectory( unit_tests ) add_subdirectory( validation ) diff --git a/tests/detectors/CMakeLists.txt b/tests/detectors/CMakeLists.txt new file mode 100644 index 000000000..c704422f1 --- /dev/null +++ b/tests/detectors/CMakeLists.txt @@ -0,0 +1,7 @@ +# Detray library, part of the ACTS project (R&D line) +# +# (c) 2021-2023 CERN for the benefit of the ACTS project +# +# Mozilla Public License Version 2.0 + +add_subdirectory( src ) diff --git a/tests/detectors/src/CMakeLists.txt b/tests/detectors/src/CMakeLists.txt new file mode 100644 index 000000000..ae073ccc4 --- /dev/null +++ b/tests/detectors/src/CMakeLists.txt @@ -0,0 +1,24 @@ +#Detray library, part of the ACTS project(R& D line) +# +#(c) 2023 CERN for the benefit of the ACTS project +# +#Mozilla Public License Version 2.0 + +include( CMakeFindDependencyMacro ) + +find_dependency( Boost COMPONENTS program_options ) + +detray_add_executable(generate_toy_detector + "generate_toy_detector.cpp" + LINK_LIBRARIES Boost::program_options + detray::io detray::utils detray::core_array) + +detray_add_executable(generate_wire_chamber + "generate_wire_chamber.cpp" + LINK_LIBRARIES Boost::program_options + detray::io detray::utils detray::core_array) + +detray_add_executable(generate_telescope_detector + "generate_telescope_detector.cpp" + LINK_LIBRARIES Boost::program_options + detray::io detray::utils detray::core_array) diff --git a/tests/detectors/src/generate_telescope_detector.cpp b/tests/detectors/src/generate_telescope_detector.cpp new file mode 100644 index 000000000..8a0b616b2 --- /dev/null +++ b/tests/detectors/src/generate_telescope_detector.cpp @@ -0,0 +1,132 @@ +/** Detray library, part of the ACTS project (R&D line) + * + * (c) 2023 CERN for the benefit of the ACTS project + * + * Mozilla Public License Version 2.0 + */ + +// Project include(s) +#include "detray/definitions/units.hpp" +#include "detray/detectors/create_telescope_detector.hpp" +#include "detray/io/common/detector_writer.hpp" + +// Vecmem include(s) +#include + +// Boost +#include + +namespace po = boost::program_options; +using namespace detray; + +namespace { + +/// Generate and write a telescope detector, given the commandline variables +/// and a configuration for the detector writer @param writer_cfg +template +void write_telecope(const po::variables_map &vm, + io::detector_writer_config &writer_cfg, + std::vector &mask_params) { + + using detector_t = detector>; + using scalar_t = typename detector_t::scalar_type; + using transform3_t = typename detector_t::transform3; + + detray::tel_det_config tel_cfg{mask_params}; + + tel_cfg.n_surfaces(vm["modules"].as()); + tel_cfg.length(vm["length"].as()); + tel_cfg.mat_thickness(vm["thickness"].as()); + + std::string direction{vm["direction"].as()}; + detray::detail::ray r{}; + if (direction == "x") { + r.set_dir({1.f, 0.f, 0.f}); + } else if (direction == "y") { + r.set_dir({0.f, 1.f, 0.f}); + } else if (direction == "z") { + r.set_dir({0.f, 0.f, 1.f}); + } + tel_cfg.pilot_track(r); + + // Build the detector + vecmem::host_memory_resource host_mr; + auto [tel_det, tel_names] = create_telescope_detector(host_mr, tel_cfg); + + // Write to file + detray::io::write_detector(tel_det, tel_names, writer_cfg); +} + +} // anonymous namespace + +int main(int argc, char **argv) { + + using scalar_t = detray::scalar; + + // Options parsing + po::options_description desc("\nTelescope detector generation options"); + + std::vector mask_params{ + 20.f * unit::mm, + 20.f * unit::mm}; // < default values for rectangles + desc.add_options()("help", "produce help message")( + "outdir", po::value(), "Output directory for files")( + "write_volume_graph", "writes the volume graph to file")( + "compactify_json", "not implemented")( + "write_material", "toggle material output")("write_grids", + "toggle grid output")( + "modules", po::value()->default_value(10u), + "number of modules in telescope [1-20]")( + "type", po::value()->default_value("rectangle"), + "type of the telescope modules [rectangle, trapezoid, annulus, ring, " + "cylinder]")( + "params", po::value>(&mask_params)->multitoken(), + "Mask values for the shape given in 'type'")( + "length", + po::value()->default_value(500.f * unit::mm), + "length of the telescope [mm]")( + "thickness", + po::value()->default_value(1.f * unit::mm), + "thickness of the module silicon material")( + "direction", po::value()->default_value("z"), + "direction of the telescope in global frame [x, y, z]"); + + po::variables_map vm; + po::store(parse_command_line(argc, argv, desc, + po::command_line_style::unix_style ^ + po::command_line_style::allow_short), + vm); + po::notify(vm); + + // Help message + if (vm.count("help")) { + std::cout << desc << std::endl; + return EXIT_FAILURE; + } + + // Configuration + detray::io::detector_writer_config writer_cfg{}; + writer_cfg.format(detray::io::format::json).replace_files(false); + + // General options + std::string outdir{vm.count("outdir") ? vm["outdir"].as() + : "./telescope_detector/"}; + writer_cfg.path(std::move(outdir)); + writer_cfg.compactify_json(vm.count("compactify_json")); + writer_cfg.write_material(vm.count("write_material")); + writer_cfg.write_grids(vm.count("write_grids")); + + // Build the geometry + std::string type{vm["type"].as()}; + if (type == "rectangle") { + write_telecope>(vm, writer_cfg, mask_params); + } else if (type == "trapezoid") { + write_telecope>(vm, writer_cfg, mask_params); + } else if (type == "annulus") { + write_telecope>(vm, writer_cfg, mask_params); + } else if (type == "ring") { + write_telecope>(vm, writer_cfg, mask_params); + } else if (type == "cylinder") { + write_telecope>(vm, writer_cfg, mask_params); + } +} diff --git a/tests/detectors/src/generate_toy_detector.cpp b/tests/detectors/src/generate_toy_detector.cpp new file mode 100644 index 000000000..7545cd8ef --- /dev/null +++ b/tests/detectors/src/generate_toy_detector.cpp @@ -0,0 +1,74 @@ +/** Detray library, part of the ACTS project (R&D line) + * + * (c) 2023 CERN for the benefit of the ACTS project + * + * Mozilla Public License Version 2.0 + */ + +// Project include(s) +#include "detray/definitions/units.hpp" +#include "detray/detectors/create_toy_geometry.hpp" +#include "detray/io/common/detector_writer.hpp" + +// Vecmem include(s) +#include + +// Boost +#include + +int main(int argc, char **argv) { + + namespace po = boost::program_options; + using namespace detray; + + // Options parsing + po::options_description desc("\nToy detector generation options"); + + desc.add_options()("help", "produce help message")( + "outdir", po::value(), "Output directory for files")( + "write_volume_graph", "writes the volume graph to file")( + "compactify_json", "not implemented")( + "write_material", "toggle material output")("write_grids", + "toggle grid output")( + "barrel_layers", po::value()->default_value(4u), + "number of barrel layers [0-4]")( + "endcap_layers", po::value()->default_value(3u), + "number of endcap layers on either side [0-7]"); + + po::variables_map vm; + po::store(parse_command_line(argc, argv, desc, + po::command_line_style::unix_style ^ + po::command_line_style::allow_short), + vm); + po::notify(vm); + + // Help message + if (vm.count("help")) { + std::cout << desc << std::endl; + return EXIT_FAILURE; + } + + // Configuration + detray::toy_det_config toy_cfg{}; + detray::io::detector_writer_config writer_cfg{}; + writer_cfg.format(detray::io::format::json).replace_files(false); + + // General options + std::string outdir{vm.count("outdir") ? vm["outdir"].as() + : "./toy_detector/"}; + writer_cfg.path(std::move(outdir)); + writer_cfg.compactify_json(vm.count("compactify_json")); + writer_cfg.write_material(vm.count("write_material")); + writer_cfg.write_grids(vm.count("write_grids")); + + // Toy detector options + toy_cfg.n_brl_layers(vm["barrel_layers"].as()); + toy_cfg.n_edc_layers(vm["endcap_layers"].as()); + + // Build the geometry + vecmem::host_memory_resource host_mr; + auto [toy_det, toy_names] = create_toy_geometry(host_mr, toy_cfg); + + // Write to file + detray::io::write_detector(toy_det, toy_names, writer_cfg); +} diff --git a/tests/detectors/src/generate_wire_chamber.cpp b/tests/detectors/src/generate_wire_chamber.cpp new file mode 100644 index 000000000..040612abd --- /dev/null +++ b/tests/detectors/src/generate_wire_chamber.cpp @@ -0,0 +1,78 @@ +/** Detray library, part of the ACTS project (R&D line) + * + * (c) 2023 CERN for the benefit of the ACTS project + * + * Mozilla Public License Version 2.0 + */ + +// Project include(s) +#include "detray/definitions/units.hpp" +#include "detray/detectors/create_wire_chamber.hpp" +#include "detray/io/common/detector_writer.hpp" + +// Vecmem include(s) +#include + +// Boost +#include + +int main(int argc, char **argv) { + + namespace po = boost::program_options; + using namespace detray; + + using detector_t = detector<>; + using scalar_t = typename detector_t::scalar_type; + + // Options parsing + po::options_description desc("\nWire chamber generation options"); + + desc.add_options()("help", "produce help message")( + "outdir", po::value(), "Output directory for files")( + "write_volume_graph", "writes the volume graph to file")( + "compactify_json", "not implemented")( + "write_material", "toggle material output")("write_grids", + "toggle grid output")( + "layers", po::value()->default_value(10u), + "number of layers")( + "half_z", + po::value()->default_value(1000.f * unit::mm), + "half length z of the chamber [mm]"); + + po::variables_map vm; + po::store(parse_command_line(argc, argv, desc, + po::command_line_style::unix_style ^ + po::command_line_style::allow_short), + vm); + po::notify(vm); + + // Help message + if (vm.count("help")) { + std::cout << desc << std::endl; + return EXIT_FAILURE; + } + + // Configuration + detray::wire_chamber_config wire_cfg{}; + detray::io::detector_writer_config writer_cfg{}; + writer_cfg.format(detray::io::format::json).replace_files(false); + + // General options + std::string outdir{vm.count("outdir") ? vm["outdir"].as() + : "./wire_chamber/"}; + writer_cfg.path(std::move(outdir)); + writer_cfg.compactify_json(vm.count("compactify_json")); + writer_cfg.write_material(vm.count("write_material")); + writer_cfg.write_grids(vm.count("write_grids")); + + // Wire chamber options + wire_cfg.n_layers(vm["layers"].as()); + wire_cfg.half_z(vm["half_z"].as()); + + // Build the geometry + vecmem::host_memory_resource host_mr; + auto [wire_chamber, names] = create_wire_chamber(host_mr, wire_cfg); + + // Write to file + detray::io::write_detector(wire_chamber, names, writer_cfg); +} diff --git a/tests/unit_tests/io/io_json_detector_writer.cpp b/tests/unit_tests/io/io_json_detector_writer.cpp index 1735e15ee..61a775a26 100644 --- a/tests/unit_tests/io/io_json_detector_writer.cpp +++ b/tests/unit_tests/io/io_json_detector_writer.cpp @@ -55,7 +55,7 @@ TEST(io, json_telescope_geometry_writer) { create_telescope_detector(host_mr, tel_cfg.positions(positions)); json_geometry_writer geo_writer; - geo_writer.write(det, names, std::ios::out | std::ios::binary); + geo_writer.write(det, names); } /// Test the writing of the toy detector material to json @@ -70,7 +70,7 @@ TEST(io, json_telescope_material_writer) { create_telescope_detector(host_mr, tel_cfg.positions(positions)); json_homogeneous_material_writer mat_writer; - mat_writer.write(det, names, std::ios::out | std::ios::binary); + mat_writer.write(det, names); } /// Test the writing of the toy detector grids to json diff --git a/utils/include/detray/detectors/create_telescope_detector.hpp b/utils/include/detray/detectors/create_telescope_detector.hpp index 42ffaf5f1..960326934 100644 --- a/utils/include/detray/detectors/create_telescope_detector.hpp +++ b/utils/include/detray/detectors/create_telescope_detector.hpp @@ -43,6 +43,10 @@ struct tel_det_config { tel_det_config(const mask &m, const trajectory_t &t = {}) : m_mask(m), m_trajectory(t) {} + /// Construct from from mask parameter vector + tel_det_config(std::vector params, const trajectory_t &t = {}) + : m_mask(std::move(params), 0u), m_trajectory(t) {} + /// Construct from mask parameters (except volume link, which is not needed) template < typename... Args,