File indexing completed on 2026-05-27 07:24:17
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include "detray/definitions/algebra.hpp"
0011 #include "detray/utils/consistency_checker.hpp"
0012 #include "detray/utils/logging.hpp"
0013
0014
0015 #include "detray/io/backend/geometry_reader.hpp"
0016 #include "detray/io/backend/geometry_writer.hpp"
0017 #include "detray/io/frontend/detector_reader.hpp"
0018 #include "detray/io/frontend/detector_writer.hpp"
0019 #include "detray/io/json/json_converter.hpp"
0020
0021
0022 #include "detray/test/common/build_telescope_detector.hpp"
0023 #include "detray/test/common/build_toy_detector.hpp"
0024 #include "detray/test/common/build_wire_chamber.hpp"
0025 #include "detray/test/cpu/toy_detector_test.hpp"
0026
0027
0028 #include <vecmem/memory/host_memory_resource.hpp>
0029
0030
0031 #include <gtest/gtest.h>
0032
0033
0034 #include <filesystem>
0035 #include <ios>
0036
0037 using namespace detray;
0038
0039 namespace {
0040
0041
0042
0043 bool compare_files(const std::string& file_name1, const std::string& file_name2,
0044 std::size_t skip = 15u) {
0045 auto file1 =
0046 io::file_handle(file_name1, std::ios_base::in | std::ios_base::binary);
0047 auto file2 =
0048 io::file_handle(file_name2, std::ios_base::in | std::ios_base::binary);
0049
0050 std::string line1;
0051 std::string line2;
0052
0053
0054 std::size_t i{1u};
0055 while (std::getline(*file1, line1)) {
0056 if (std::getline(*file2, line2)) {
0057 if (skip < i && line1 != line2) {
0058 DETRAY_ERROR_HOST("In line " << i << ":" << std::endl
0059 << line1 << std::endl
0060 << line2);
0061 return false;
0062 }
0063 } else {
0064 DETRAY_ERROR_HOST("Could not read next line from file 2:"
0065 << std::endl
0066 << "In line " << i << ":" << std::endl
0067 << line1);
0068 return false;
0069 }
0070 ++i;
0071 }
0072
0073
0074 if (std::getline(*file2, line2)) {
0075 DETRAY_ERROR_HOST("Could not read next line from file 1:"
0076 << std::endl
0077 << "In line " << i << ":" << std::endl
0078 << line2);
0079 return false;
0080 }
0081
0082
0083 return true;
0084 }
0085
0086
0087
0088 template <std::size_t CAP = 0u, typename detector_t>
0089 auto test_detector_json_io(
0090 const detector_t& det, const typename detector_t::name_map& names,
0091 std::map<std::string, std::string, std::less<>>& file_names,
0092 vecmem::host_memory_resource& host_mr) {
0093 auto writer_cfg = io::detector_writer_config{}
0094 .format(io::format::json)
0095 .replace_files(true)
0096 .write_grids(true)
0097 .write_material(true);
0098 io::write_detector(det, names, writer_cfg);
0099
0100
0101 io::detector_reader_config reader_cfg{};
0102 reader_cfg.verbose_check(true);
0103 for (auto& [_, name] : file_names) {
0104 reader_cfg.add_file(name);
0105 }
0106
0107 auto [det2, names2] = io::read_detector<detector_t, CAP>(host_mr, reader_cfg);
0108
0109
0110 writer_cfg.replace_files(false);
0111 io::write_detector(det2, names2, writer_cfg);
0112
0113
0114 std::string geometry_file{names.get_detector_name() + "_geometry_2.json"};
0115 EXPECT_TRUE(compare_files(file_names["geometry"], geometry_file));
0116 std::filesystem::remove(geometry_file);
0117 std::filesystem::remove(file_names["geometry"]);
0118
0119
0120 if (auto search = file_names.find("homogeneous_material");
0121 search != file_names.end()) {
0122 std::string hom_mat_file{names.get_detector_name() +
0123 "_homogeneous_material_2.json"};
0124 EXPECT_TRUE(
0125 compare_files(file_names["homogeneous_material"], hom_mat_file));
0126 std::filesystem::remove(hom_mat_file);
0127 std::filesystem::remove(file_names["homogeneous_material"]);
0128 }
0129
0130
0131 if (auto search = file_names.find("material_maps");
0132 search != file_names.end()) {
0133 std::string mat_map_file{names.get_detector_name() +
0134 "_material_maps_2.json"};
0135 EXPECT_TRUE(compare_files(file_names["material_maps"], mat_map_file));
0136 std::filesystem::remove(mat_map_file);
0137 std::filesystem::remove(file_names["material_maps"]);
0138 }
0139
0140
0141 if (auto search = file_names.find("surface_grids");
0142 search != file_names.end()) {
0143 std::string grids_file{names.get_detector_name() + "_surface_grids_2.json"};
0144 EXPECT_TRUE(compare_files(file_names["surface_grids"], grids_file));
0145 std::filesystem::remove(grids_file);
0146 std::filesystem::remove(file_names["surface_grids"]);
0147 }
0148
0149 return std::make_pair(std::move(det2), std::move(names2));
0150 }
0151
0152 }
0153
0154
0155 GTEST_TEST(io, json_telescope_detector_reader) {
0156 using test_algebra = test::algebra;
0157 using scalar = test::scalar;
0158
0159 mask<rectangle2D, test_algebra> rec2{0u, 100.f, 100.f};
0160
0161
0162 std::vector<scalar> positions = {1.f, 50.f, 100.f, 150.f, 200.f, 250.f,
0163 300.f, 350.f, 400.f, 450.f, 500.f};
0164
0165 tel_det_config tel_cfg{rec2};
0166 tel_cfg.positions(positions);
0167
0168
0169 vecmem::host_memory_resource host_mr;
0170 auto [tel_det, tel_names] =
0171 build_telescope_detector<test_algebra>(host_mr, tel_cfg);
0172
0173 std::map<std::string, std::string, std::less<>> file_names;
0174 file_names["geometry"] = "telescope_detector_geometry.json";
0175 file_names["homogeneous_material"] =
0176 "telescope_detector_homogeneous_material.json";
0177
0178 auto [det_io, names_io] =
0179 test_detector_json_io(tel_det, tel_names, file_names, host_mr);
0180
0181 const auto& mat_store = det_io.material_store();
0182 const auto& slabs =
0183 mat_store.get<decltype(tel_det)::material::id::e_material_slab>();
0184
0185 EXPECT_EQ(det_io.volumes().size(), 1u);
0186 EXPECT_EQ(slabs.size(), positions.size());
0187 }
0188
0189
0190 GTEST_TEST(io, json_toy_geometry) {
0191 using metadata_t = test::toy_metadata;
0192 using test_algebra = metadata_t::algebra_type;
0193 using detector_t = detector<metadata_t>;
0194 using scalar = test::scalar;
0195
0196
0197 vecmem::host_memory_resource host_mr;
0198 toy_det_config<scalar> toy_cfg{};
0199 toy_cfg.use_material_maps(false);
0200 auto [toy_det, names] = build_toy_detector<test_algebra>(host_mr, toy_cfg);
0201
0202
0203 io::json_converter<detector_t, io::geometry_writer> geo_writer;
0204 auto file_name = geo_writer.write(
0205 toy_det, names, std::ios::out | std::ios::binary | std::ios::trunc);
0206
0207
0208 typename detector_t::name_map volume_name_map{};
0209 volume_name_map.set_detector_name("toy_detector");
0210
0211
0212 detector_builder<metadata_t> toy_builder;
0213 io::json_converter<detector_t, io::geometry_reader> geo_reader;
0214 geo_reader.read(toy_builder, file_name);
0215 auto det = toy_builder.build(host_mr, volume_name_map);
0216
0217
0218
0219
0220
0221 using default_metadata_t = test::default_metadata;
0222 detector_builder<default_metadata_t> comp_builder;
0223 io::json_converter<detector<default_metadata_t>, io::geometry_reader>
0224 comp_geo_reader;
0225 comp_geo_reader.read(comp_builder, file_name);
0226 volume_name_map.clear_names();
0227 auto comp_det = comp_builder.build(host_mr, volume_name_map);
0228
0229 using mask_id = detector<default_metadata_t>::masks::id;
0230 const auto& masks = comp_det.mask_store();
0231
0232 EXPECT_EQ(comp_det.volumes().size(), 22u);
0233 EXPECT_EQ(comp_det.surfaces().size(), 3230);
0234 EXPECT_EQ(comp_det.transform_store().size(), 3252);
0235 EXPECT_EQ(masks.template size<mask_id::e_rectangle2D>(), 2492u);
0236 EXPECT_EQ(masks.template size<mask_id::e_trapezoid2D>(), 648u);
0237 EXPECT_EQ(masks.template size<mask_id::e_annulus2D>(), 0u);
0238 EXPECT_EQ(masks.template size<mask_id::e_cylinder2D>(), 0u);
0239 EXPECT_EQ(masks.template size<mask_id::e_concentric_cylinder2D>(), 56u);
0240 EXPECT_EQ(masks.template size<mask_id::e_ring2D>(), 60u);
0241 EXPECT_EQ(masks.template size<mask_id::e_ring2D>(), 60u);
0242 EXPECT_EQ(masks.template size<mask_id::e_straw_tube>(), 0u);
0243 EXPECT_EQ(masks.template size<mask_id::e_drift_cell>(), 0u);
0244
0245 detail::check_consistency(comp_det);
0246 }
0247
0248
0249 GTEST_TEST(io, json_toy_detector_roundtrip_homogeneous_material) {
0250 using test_algebra = test::algebra;
0251 using scalar = test::scalar;
0252
0253
0254 vecmem::host_memory_resource host_mr;
0255 toy_det_config<scalar> toy_cfg{};
0256 toy_cfg.use_material_maps(false);
0257 const auto [toy_det, toy_names] =
0258 build_toy_detector<test_algebra>(host_mr, toy_cfg);
0259
0260 std::map<std::string, std::string, std::less<>> file_names;
0261 file_names["geometry"] = "toy_detector_geometry.json";
0262 file_names["homogeneous_material"] = "toy_detector_homogeneous_material.json";
0263 file_names["surface_grids"] = "toy_detector_surface_grids.json";
0264
0265 auto [det_io, names_io] =
0266 test_detector_json_io<1u>(toy_det, toy_names, file_names, host_mr);
0267
0268
0269 std::filesystem::remove("toy_detector_material_maps.json");
0270 std::filesystem::remove("toy_detector_material_maps_2.json");
0271
0272
0273
0274 }
0275
0276
0277 GTEST_TEST(io, json_toy_detector_roundtrip_material_maps) {
0278 using test_algebra = test::algebra;
0279 using scalar = test::scalar;
0280
0281
0282 vecmem::host_memory_resource host_mr;
0283 toy_det_config<scalar> toy_cfg{};
0284 toy_cfg.use_material_maps(true);
0285 const auto [toy_det, toy_names] =
0286 build_toy_detector<test_algebra>(host_mr, toy_cfg);
0287
0288 std::map<std::string, std::string, std::less<>> file_names;
0289 file_names["geometry"] = "toy_detector_geometry.json";
0290 file_names["homogeneous_material"] = "toy_detector_homogeneous_material.json";
0291 file_names["material_maps"] = "toy_detector_material_maps.json";
0292 file_names["surface_grids"] = "toy_detector_surface_grids.json";
0293
0294 auto [det_io, names_io] =
0295 test_detector_json_io<1u>(toy_det, toy_names, file_names, host_mr);
0296
0297
0298
0299 }
0300
0301
0302 GTEST_TEST(io, json_wire_chamber_reader) {
0303 using test_algebra = test::algebra;
0304 using scalar = test::scalar;
0305
0306
0307 vecmem::host_memory_resource host_mr;
0308 wire_chamber_config<scalar> wire_cfg{};
0309 auto [wire_det, wire_names] =
0310 build_wire_chamber<test_algebra>(host_mr, wire_cfg);
0311
0312 std::map<std::string, std::string, std::less<>> file_names;
0313 file_names["geometry"] = "wire_chamber_geometry.json";
0314 file_names["homogeneous_material"] = "wire_chamber_homogeneous_material.json";
0315 file_names["surface_grids"] = "wire_chamber_surface_grids.json";
0316
0317 auto [det_io, names_io] =
0318 test_detector_json_io(wire_det, wire_names, file_names, host_mr);
0319
0320
0321 std::filesystem::remove("wire_chamber_material_maps.json");
0322 std::filesystem::remove("wire_chamber_material_maps_2.json");
0323
0324 EXPECT_EQ(det_io.volumes().size(), 11u);
0325 }