From 6ba5c07f0f1ce26c57dbf6234cc61b6b261cd3d6 Mon Sep 17 00:00:00 2001 From: Attila Krasznahorkay <30694331+krasznaa@users.noreply.github.com> Date: Wed, 20 Nov 2024 18:02:38 +0100 Subject: [PATCH] Cell CSV Writing, main branch (2024.11.20.) (#777) * Implemented cell CSV writing. While also adding a unit test for that code. * Made it possible to write Detray geometry IDs with the cells. * Made it possible to read cells with "Detray geometry IDs". * Make the test a little more robust against errors. --- io/CMakeLists.txt | 2 + io/include/traccc/io/read_cells.hpp | 12 +++++- io/include/traccc/io/write.hpp | 8 +++- io/src/csv/read_cells.cpp | 14 +++++-- io/src/csv/read_cells.hpp | 5 ++- io/src/csv/write_cells.cpp | 58 ++++++++++++++++++++++++++++ io/src/csv/write_cells.hpp | 32 ++++++++++++++++ io/src/read_cells.cpp | 11 ++++-- io/src/write.cpp | 13 ++++++- tests/io/test_csv.cpp | 59 +++++++++++++++++++++++++++++ 10 files changed, 201 insertions(+), 13 deletions(-) create mode 100644 io/src/csv/write_cells.cpp create mode 100644 io/src/csv/write_cells.hpp diff --git a/io/CMakeLists.txt b/io/CMakeLists.txt index 0b3c04b3e0..61886c1fc7 100644 --- a/io/CMakeLists.txt +++ b/io/CMakeLists.txt @@ -59,6 +59,8 @@ traccc_add_library( traccc_io io TYPE SHARED "src/csv/make_cell_reader.cpp" "src/csv/read_cells.hpp" "src/csv/read_cells.cpp" + "src/csv/write_cells.hpp" + "src/csv/write_cells.cpp" "src/csv/read_spacepoints.hpp" "src/csv/read_spacepoints.cpp" "src/csv/make_measurement_reader.cpp" diff --git a/io/include/traccc/io/read_cells.hpp b/io/include/traccc/io/read_cells.hpp index afcd450d17..2e953d8cf3 100644 --- a/io/include/traccc/io/read_cells.hpp +++ b/io/include/traccc/io/read_cells.hpp @@ -31,11 +31,15 @@ namespace traccc::io { /// @param[in] dd The detector description to point the cells at /// @param[in] format The format of the cell data files (to read) /// @param[in] deduplicate Whether to deduplicate the cells +/// @param[in] use_acts_geometry_id Whether to treat the geometry ID as an +/// "Acts geometry ID", or a +/// "Detray geometry ID" /// void read_cells(edm::silicon_cell_collection::host& cells, std::size_t event, std::string_view directory, const silicon_detector_description::host* dd = nullptr, - data_format format = data_format::csv, bool deduplicate = true); + data_format format = data_format::csv, bool deduplicate = true, + bool use_acts_geometry_id = true); /// Read cell data into memory /// @@ -46,10 +50,14 @@ void read_cells(edm::silicon_cell_collection::host& cells, std::size_t event, /// @param[in] dd The detector description to point the cells at /// @param[in] format The format of the cell data files (to read) /// @param[in] deduplicate Whether to deduplicate the cells +/// @param[in] use_acts_geometry_id Whether to treat the geometry ID as an +/// "Acts geometry ID", or a +/// "Detray geometry ID" /// void read_cells(edm::silicon_cell_collection::host& cells, std::string_view filename, const silicon_detector_description::host* dd = nullptr, - data_format format = data_format::csv, bool deduplicate = true); + data_format format = data_format::csv, bool deduplicate = true, + bool use_acts_geometry_id = true); } // namespace traccc::io diff --git a/io/include/traccc/io/write.hpp b/io/include/traccc/io/write.hpp index 9d6ed8cc45..88b89a8850 100644 --- a/io/include/traccc/io/write.hpp +++ b/io/include/traccc/io/write.hpp @@ -12,6 +12,7 @@ #include "traccc/edm/silicon_cell_collection.hpp" #include "traccc/edm/spacepoint.hpp" #include "traccc/edm/track_candidate.hpp" +#include "traccc/geometry/silicon_detector_description.hpp" #include "traccc/io/data_format.hpp" #include "traccc/io/digitization_config.hpp" @@ -30,10 +31,15 @@ namespace traccc::io { /// @param directory is the directory for the output cell file /// @param format is the data format (e.g. csv or binary) of output file /// @param cells is the cell collection to write +/// @param dd is the silicon detector description +/// @param use_acts_geometry_id is a flag to use the ACTS geometry ID (or the +/// Detray one) /// void write(std::size_t event, std::string_view directory, traccc::data_format format, - traccc::edm::silicon_cell_collection::const_view cells); + traccc::edm::silicon_cell_collection::const_view cells, + traccc::silicon_detector_description::const_view dd = {}, + bool use_acts_geometry_id = true); /// Function for hit file writing /// diff --git a/io/src/csv/read_cells.cpp b/io/src/csv/read_cells.cpp index 5b9707a24a..24ec43ff93 100644 --- a/io/src/csv/read_cells.cpp +++ b/io/src/csv/read_cells.cpp @@ -111,8 +111,8 @@ namespace traccc::io::csv { void read_cells(edm::silicon_cell_collection::host& cells, std::string_view filename, - const silicon_detector_description::host* dd, - bool deduplicate) { + const silicon_detector_description::host* dd, bool deduplicate, + bool use_acts_geometry_id) { // Clear the output container. cells.resize(0u); @@ -125,8 +125,14 @@ void read_cells(edm::silicon_cell_collection::host& cells, // to indices inside the detector description. std::map geomIdMap; if (dd) { - for (unsigned int i = 0; i < dd->acts_geometry_id().size(); ++i) { - geomIdMap[dd->acts_geometry_id()[i]] = i; + if (use_acts_geometry_id) { + for (unsigned int i = 0; i < dd->acts_geometry_id().size(); ++i) { + geomIdMap[dd->acts_geometry_id()[i]] = i; + } + } else { + for (unsigned int i = 0; i < dd->geometry_id().size(); ++i) { + geomIdMap[dd->geometry_id()[i].value()] = i; + } } } diff --git a/io/src/csv/read_cells.hpp b/io/src/csv/read_cells.hpp index 82039ad706..1dad12d39d 100644 --- a/io/src/csv/read_cells.hpp +++ b/io/src/csv/read_cells.hpp @@ -22,10 +22,13 @@ namespace traccc::io::csv { /// @param[in] filename The name of the file to read /// @param[in] dd The detector description to point the cells at /// @param[in] deduplicate Whether to deduplicate the cells +/// @param[in] use_acts_geometry_id Whether to treat the geometry ID as an +/// "Acts geometry ID", or a +/// "Detray geometry ID" /// void read_cells(edm::silicon_cell_collection::host& cells, std::string_view filename, const silicon_detector_description::host* dd = nullptr, - bool deduplicate = true); + bool deduplicate = true, bool use_acts_geometry_id = true); } // namespace traccc::io::csv diff --git a/io/src/csv/write_cells.cpp b/io/src/csv/write_cells.cpp new file mode 100644 index 0000000000..097bfbbd65 --- /dev/null +++ b/io/src/csv/write_cells.cpp @@ -0,0 +1,58 @@ +/** TRACCC library, part of the ACTS project (R&D line) + * + * (c) 2024 CERN for the benefit of the ACTS project + * + * Mozilla Public License Version 2.0 + */ + +// Local include(s). +#include "write_cells.hpp" + +// System include(s). +#include +#include + +namespace traccc::io::csv { + +void write_cells(std::string_view filename, + traccc::edm::silicon_cell_collection::const_view cells_view, + traccc::silicon_detector_description::const_view dd_view, + bool use_acts_geometry_id) { + + // Make sure that a valid detector description would've been given to the + // function. + if (dd_view.capacity() == 0u) { + throw std::invalid_argument("Detector description must be provided"); + } + + // Open the file for writing. + std::ofstream ofile(filename.data()); + if (!ofile.is_open()) { + throw std::runtime_error("Could not open file " + + std::string(filename)); + } + + // Create device objects. + const edm::silicon_cell_collection::const_device cells(cells_view); + const silicon_detector_description::const_device dd(dd_view); + + // Write the header. + ofile << "geometry_id,measurement_id,channel0,channel1,timestamp,value\n"; + + // Write out each cell. + for (edm::silicon_cell_collection::const_device::size_type i = 0; + i < cells.size(); ++i) { + + // Get the cell. + const auto cell = cells.at(i); + + // Write the cell info to the file. + ofile << (use_acts_geometry_id + ? dd.acts_geometry_id().at(cell.module_index()) + : dd.geometry_id().at(cell.module_index()).value()) + << ",0," << cell.channel0() << ',' << cell.channel1() << ',' + << cell.time() << ',' << cell.activation() << '\n'; + } +} + +} // namespace traccc::io::csv diff --git a/io/src/csv/write_cells.hpp b/io/src/csv/write_cells.hpp new file mode 100644 index 0000000000..bf2dcf04d3 --- /dev/null +++ b/io/src/csv/write_cells.hpp @@ -0,0 +1,32 @@ +/** TRACCC library, part of the ACTS project (R&D line) + * + * (c) 2024 CERN for the benefit of the ACTS project + * + * Mozilla Public License Version 2.0 + */ + +#pragma once + +// Project include(s). +#include "traccc/edm/silicon_cell_collection.hpp" +#include "traccc/geometry/silicon_detector_description.hpp" + +// System include(s). +#include + +namespace traccc::io::csv { + +/// Function for cell file writing to CSV files +/// +/// @param filename The name of the file to write the data to +/// @param cells Cell collection to write +/// @param dd Silicon detector description +/// @param use_acts_geometry_id Flag to use the ACTS geometry ID (or the Detray +/// one) +/// +void write_cells(std::string_view filename, + traccc::edm::silicon_cell_collection::const_view cells, + traccc::silicon_detector_description::const_view dd, + bool use_acts_geometry_id); + +} // namespace traccc::io::csv diff --git a/io/src/read_cells.cpp b/io/src/read_cells.cpp index 087b70fc92..de6df18d56 100644 --- a/io/src/read_cells.cpp +++ b/io/src/read_cells.cpp @@ -20,7 +20,8 @@ namespace traccc::io { void read_cells(edm::silicon_cell_collection::host& cells, std::size_t event, std::string_view directory, const silicon_detector_description::host* dd, - data_format format, bool deduplicate) { + data_format format, bool deduplicate, + bool use_acts_geometry_id) { switch (format) { case data_format::csv: @@ -30,7 +31,7 @@ void read_cells(edm::silicon_cell_collection::host& cells, std::size_t event, std::filesystem::path( get_event_filename(event, "-cells.csv"))) .native()), - dd, format, deduplicate); + dd, format, deduplicate, use_acts_geometry_id); break; case data_format::binary: @@ -51,11 +52,13 @@ void read_cells(edm::silicon_cell_collection::host& cells, std::size_t event, void read_cells(edm::silicon_cell_collection::host& cells, std::string_view filename, const silicon_detector_description::host* dd, - data_format format, bool deduplicate) { + data_format format, bool deduplicate, + bool use_acts_geometry_id) { switch (format) { case data_format::csv: - csv::read_cells(cells, filename, dd, deduplicate); + csv::read_cells(cells, filename, dd, deduplicate, + use_acts_geometry_id); break; case data_format::binary: diff --git a/io/src/write.cpp b/io/src/write.cpp index 39d3f69534..6b3ddbf041 100644 --- a/io/src/write.cpp +++ b/io/src/write.cpp @@ -8,6 +8,7 @@ // Local include(s). #include "traccc/io/write.hpp" +#include "csv/write_cells.hpp" #include "json/write_digitization_config.hpp" #include "obj/write_seeds.hpp" #include "obj/write_spacepoints.hpp" @@ -23,7 +24,9 @@ namespace traccc::io { void write(std::size_t event, std::string_view directory, traccc::data_format format, - traccc::edm::silicon_cell_collection::const_view cells) { + traccc::edm::silicon_cell_collection::const_view cells, + traccc::silicon_detector_description::const_view dd, + bool use_acts_geometry_id) { switch (format) { case data_format::binary: @@ -34,6 +37,14 @@ void write(std::size_t event, std::string_view directory, .native()), traccc::edm::silicon_cell_collection::const_device{cells}); break; + case data_format::csv: + csv::write_cells( + get_absolute_path((std::filesystem::path(directory) / + std::filesystem::path( + get_event_filename(event, "-cells.csv"))) + .native()), + cells, dd, use_acts_geometry_id); + break; default: throw std::invalid_argument("Unsupported data format"); } diff --git a/tests/io/test_csv.cpp b/tests/io/test_csv.cpp index 01784b9305..7a1be0562c 100644 --- a/tests/io/test_csv.cpp +++ b/tests/io/test_csv.cpp @@ -14,6 +14,7 @@ #include "traccc/io/read_measurements.hpp" #include "traccc/io/read_particles.hpp" #include "traccc/io/read_spacepoints.hpp" +#include "traccc/io/write.hpp" // Test include(s). #include "tests/data_test.hpp" @@ -24,6 +25,9 @@ // GTest include(s). #include +// System include(s). +#include + class io : public traccc::tests::data_test {}; // This defines the local frame test suite @@ -152,3 +156,58 @@ TEST_F(io, csv_read_odd_single_muon) { } EXPECT_EQ(n_muons, 4u); } + +TEST_F(io, csv_write_odd_single_muon_cells) { + + // Memory resource used by the test. + vecmem::host_memory_resource mr; + + // Read the ODD detector description. + traccc::silicon_detector_description::host dd{mr}; + traccc::io::read_detector_description( + dd, "geometries/odd/odd-detray_geometry_detray.json", + "geometries/odd/odd-digi-geometric-config.json"); + + // Lambda comparing two cell collections. + auto compare_cells = + [](const traccc::edm::silicon_cell_collection::host& a, + const traccc::edm::silicon_cell_collection::host& b) -> void { + ASSERT_EQ(a.size(), b.size()); + for (traccc::edm::silicon_cell_collection::host::size_type i = 0; + i < a.size(); ++i) { + EXPECT_EQ(a.at(i), b.at(i)); + } + }; + + // Cell collections to use in the test. + traccc::edm::silicon_cell_collection::host orig{mr}, copy{mr}; + + // Lambda performing the test with either using "Acts geometry IDs" or + // "Detray ones". + auto perform_test = [&](bool use_acts_geometry_id) { + // Test the I/O for 10 events. + for (std::size_t event = 0; event < 10; ++event) { + + // Read the cells for the current event. + traccc::io::read_cells(orig, event, "odd/geant4_1muon_1GeV/", &dd); + + // Write the cells into a temporary file. + traccc::io::write(event, + std::filesystem::temp_directory_path().native(), + traccc::data_format::csv, vecmem::get_data(orig), + vecmem::get_data(dd), use_acts_geometry_id); + + // Read the cells back in. + traccc::io::read_cells( + copy, event, std::filesystem::temp_directory_path().native(), + &dd, traccc::data_format::csv, false, use_acts_geometry_id); + + // Compare the two cell collections. + compare_cells(orig, copy); + } + }; + + // Perform the test with both "Acts geometry IDs" and "Detray ones". + perform_test(true); + perform_test(false); +}