Skip to content

Commit 33a83f7

Browse files
authored
ref: remove abstract interface from backend io (#668)
Remove the io_interface from the backend readers and writers and simplify the templating. Renames the methods of the backend readers and writers to convert and splits some headers up, so that reading and writing are now separated completely. The type definitions of the full reader/writer implementation is now done in the frontend and only if the detector type under construction contains the respective component. This might make the compilation for e.g. telescope detectors a bit easier.
1 parent 528283d commit 33a83f7

34 files changed

+1133
-1026
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
/** Detray library, part of the ACTS project (R&D line)
2+
*
3+
* (c) 2023-2024 CERN for the benefit of the ACTS project
4+
*
5+
* Mozilla Public License Version 2.0
6+
*/
7+
8+
#pragma once
9+
10+
// Project include(s)
11+
#include "detray/io/frontend/payloads.hpp"
12+
#include "detray/io/frontend/utils/io_metadata.hpp"
13+
14+
// System include(s)
15+
#include <string_view>
16+
17+
namespace detray::io::detail {
18+
19+
// Convert basic information like links and header data
20+
namespace basic_converter {
21+
22+
/// @returns a link from its io payload @param link_data
23+
inline dindex convert(const single_link_payload& link_data) {
24+
return static_cast<dindex>(link_data.link);
25+
}
26+
27+
/// Convert a link @param idx into its io payload
28+
inline single_link_payload convert(const std::size_t idx) {
29+
single_link_payload link_data;
30+
link_data.link = idx;
31+
32+
return link_data;
33+
}
34+
35+
/// Convert a typed link with a type id @param id and and index
36+
/// @param idx into its io payload
37+
template <typename type_id>
38+
inline typed_link_payload<type_id> convert(const type_id id,
39+
const std::size_t idx) {
40+
typed_link_payload<type_id> link_data;
41+
42+
link_data.type = id;
43+
link_data.index = idx;
44+
45+
return link_data;
46+
}
47+
48+
/// Convert the common header information using the detector name
49+
/// @param det_name and the file tag @param tag that describes the data file
50+
/// content
51+
inline common_header_payload convert(const std::string_view det_name,
52+
const std::string_view tag) {
53+
common_header_payload header_data;
54+
55+
header_data.version = io::detail::get_detray_version();
56+
header_data.detector = det_name;
57+
header_data.tag = tag;
58+
header_data.date = io::detail::get_current_date();
59+
60+
return header_data;
61+
}
62+
63+
} // namespace basic_converter
64+
65+
} // namespace detray::io::detail

io/include/detray/io/common/detail/grid_reader.hpp

+42-44
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@
1212
#include "detray/builders/detector_builder.hpp"
1313
#include "detray/builders/grid_factory.hpp"
1414
#include "detray/definitions/indexing.hpp"
15+
#include "detray/io/common/detail/basic_converter.hpp"
1516
#include "detray/io/common/detail/type_info.hpp"
16-
#include "detray/io/common/io_interface.hpp"
1717
#include "detray/io/frontend/payloads.hpp"
1818
#include "detray/utils/ranges.hpp"
1919
#include "detray/utils/type_list.hpp"
@@ -27,47 +27,39 @@
2727

2828
namespace detray::io::detail {
2929

30-
/// @brief Abstract base class for surface grid readers
30+
/// @brief Grid reader backend
3131
///
32-
/// @tparam detector_t the detector the grid belongs to
3332
/// @tparam value_t bin entry type
3433
/// @tparam grid_builder_t the grid builder to be used
3534
/// @tparam CAP the storage capacity of a single bin
3635
/// @tparam DIM the dimension of the grid
3736
/// @tparam bin_filler_t helper to fill all bins of a grid
3837
/// @tparam serializer_t memory layout of the grid
39-
template <class detector_t, typename value_t,
38+
template <typename value_t,
4039
template <typename, typename, typename, typename>
4140
class grid_builder_t,
4241
typename CAP = std::integral_constant<std::size_t, 0>,
4342
typename DIM = std::integral_constant<std::size_t, 2>,
4443
typename bin_filler_t = fill_by_pos,
4544
template <std::size_t> class serializer_t = simple_serializer>
46-
class grid_reader : public reader_interface<detector_t> {
45+
class grid_reader {
4746

48-
using base_type = reader_interface<detector_t>;
4947
/// IO accelerator ids do not need to coincide with the detector ids,
5048
/// because they are shared with ACTS
5149
using acc_type = io::accel_id;
52-
using algebra_t = typename detector_t::transform3;
53-
using scalar_t = typename algebra_t::scalar_type;
5450

5551
static constexpr std::size_t dim{DIM()};
5652
static constexpr std::size_t bin_capacity{CAP()};
5753

5854
public:
59-
/// Same constructors for this class as for base_type
60-
using base_type::base_type;
61-
62-
protected:
63-
/// Deserialize the detector grids @param grids_data from their IO payload
64-
template <typename content_t, typename grid_id_t>
65-
static void deserialize(
55+
/// Convert the detector grids @param grids_data from their IO payload
56+
template <typename detector_t, typename content_t, typename grid_id_t>
57+
static void convert(
6658
detector_builder<typename detector_t::metadata, volume_builder>
6759
&det_builder,
6860
const detector_grids_payload<content_t, grid_id_t> &grids_data) {
6961

70-
// Deserialize the grids volume by volume
62+
// Convert the grids volume by volume
7163
for (const auto &[_, grid_data_coll] : grids_data.grids) {
7264
for (const auto &[i, grid_data] :
7365
detray::views::enumerate(grid_data_coll)) {
@@ -81,8 +73,9 @@ class grid_reader : public reader_interface<detector_t> {
8173
}
8274

8375
// Don't start at zero, since that is the brute force method
84-
deserialize(bounds, binnings, std::make_pair(i + 1, grid_data),
85-
det_builder);
76+
convert<detector_t>(bounds, binnings,
77+
std::make_pair(i + 1, grid_data),
78+
det_builder);
8679
}
8780
}
8881
}
@@ -96,18 +89,17 @@ class grid_reader : public reader_interface<detector_t> {
9689
///
9790
/// @param bound_ids runtime queue of bounds type ids (read from file)
9891
/// @param binning_ids runtime queue of binning type ids (read from file)
99-
template <typename bounds_ts = types::list<>,
92+
template <typename detector_t, typename bounds_ts = types::list<>,
10093
typename binning_ts = types::list<>, typename... Ts>
101-
static void deserialize(std::queue<axis::bounds> &bound_ids,
102-
std::queue<axis::binning> &binning_ids,
103-
Ts &&... data) {
94+
static void convert(std::queue<axis::bounds> &bound_ids,
95+
std::queue<axis::binning> &binning_ids, Ts &&... data) {
10496
using namespace axis;
10597

10698
constexpr std::size_t n_bounds_types{types::size<bounds_ts>};
10799

108100
// Base case: If the bounds types are filled, continue with the binnings
109101
if constexpr (n_bounds_types == dim) {
110-
return deserialize<bounds_ts, binning_ts>(
102+
return convert<detector_t, bounds_ts, binning_ts>(
111103
binning_ids, std::forward<Ts>(data)...);
112104
} else if (!bound_ids.empty()) {
113105
// The axis label, e.g. x, y or z by number
@@ -122,18 +114,18 @@ class grid_reader : public reader_interface<detector_t> {
122114
case bounds::e_closed: {
123115
using new_bounds_ts =
124116
types::push_back<bounds_ts, closed<lb>>;
125-
return deserialize<new_bounds_ts, binning_ts>(
117+
return convert<detector_t, new_bounds_ts, binning_ts>(
126118
bound_ids, binning_ids, std::forward<Ts>(data)...);
127119
}
128120
case bounds::e_open: {
129121
using new_bounds_ts = types::push_back<bounds_ts, open<lb>>;
130-
return deserialize<new_bounds_ts, binning_ts>(
122+
return convert<detector_t, new_bounds_ts, binning_ts>(
131123
bound_ids, binning_ids, std::forward<Ts>(data)...);
132124
}
133125
case bounds::e_circular: {
134126
using new_bounds_ts =
135127
types::push_back<bounds_ts, circular<lb>>;
136-
return deserialize<new_bounds_ts, binning_ts>(
128+
return convert<detector_t, new_bounds_ts, binning_ts>(
137129
bound_ids, binning_ids, std::forward<Ts>(data)...);
138130
}
139131
// Test some edge cases
@@ -155,19 +147,20 @@ class grid_reader : public reader_interface<detector_t> {
155147
/// identified from the IO ids so far (start with empty list)
156148
///
157149
/// @param binning_ids runtime queue of binning type ids (read from file)
158-
template <typename bounds_ts, typename binning_ts, typename... Ts,
150+
template <typename detector_t, typename bounds_ts, typename binning_ts,
151+
typename... Ts,
159152
std::enable_if_t<types::size<bounds_ts> == dim, bool> = true>
160-
static void deserialize(std::queue<axis::binning> &binning_ids,
161-
Ts &&... data) {
153+
static void convert(std::queue<axis::binning> &binning_ids, Ts &&... data) {
162154

163155
using namespace axis;
164156

157+
using scalar_t = typename detector_t::scalar_type;
165158
using regular_binning_t = regular<host_container_types, scalar_t>;
166159
using irregular_binning_t = irregular<host_container_types, scalar_t>;
167160

168161
// Base case: If the binning types are filled, continue with the frame
169162
if constexpr (types::size<binning_ts> == dim) {
170-
return deserialize<bounds_ts, binning_ts>(
163+
return convert<detector_t, bounds_ts, binning_ts>(
171164
std::forward<Ts>(data)...);
172165
} else if (!binning_ids.empty()) {
173166

@@ -178,13 +171,13 @@ class grid_reader : public reader_interface<detector_t> {
178171
case binning::e_regular: {
179172
using new_binning_ts =
180173
types::push_back<binning_ts, regular_binning_t>;
181-
return deserialize<bounds_ts, new_binning_ts>(
174+
return convert<detector_t, bounds_ts, new_binning_ts>(
182175
binning_ids, std::forward<Ts>(data)...);
183176
}
184177
case binning::e_irregular: {
185178
using new_binning_ts =
186179
types::push_back<binning_ts, irregular_binning_t>;
187-
return deserialize<bounds_ts, new_binning_ts>(
180+
return convert<detector_t, bounds_ts, new_binning_ts>(
188181
binning_ids, std::forward<Ts>(data)...);
189182
}
190183
// Test some edge cases
@@ -206,15 +199,18 @@ class grid_reader : public reader_interface<detector_t> {
206199
///
207200
/// @param grid_data grid IO payload (read from file)
208201
/// @param det_builder gather the grid data and build the final volume
209-
template <typename bounds_ts, typename binning_ts, typename content_t,
202+
template <typename detector_t, typename bounds_ts, typename binning_ts,
203+
typename content_t,
210204
std::enable_if_t<types::size<bounds_ts> == dim and
211205
types::size<binning_ts> == dim,
212206
bool> = true>
213-
static void deserialize(
207+
static void convert(
214208
const std::pair<dindex, grid_payload<content_t>> &grid_data,
215209
detector_builder<typename detector_t::metadata, volume_builder>
216210
&det_builder) {
217211

212+
using algebra_t = typename detector_t::transform3;
213+
218214
// Throw expection if the accelerator link type id is invalid
219215
auto print_error = [](io::accel_id grid_link) -> void {
220216
if (grid_link == io::accel_id::unknown) {
@@ -238,17 +234,17 @@ class grid_reader : public reader_interface<detector_t> {
238234
switch (grid_data.second.grid_link.type) {
239235
// rectangle, trapezoid, (triangle) grids
240236
case io::accel_id::cartesian2_grid: {
241-
return deserialize<cartesian2<algebra_t>>(
237+
return convert<detector_t, cartesian2<algebra_t>>(
242238
grid_data, det_builder, bounds, binnings);
243239
}
244240
// ring/disc, annulus grids
245241
case io::accel_id::polar2_grid: {
246-
return deserialize<polar2<algebra_t>>(
242+
return convert<detector_t, polar2<algebra_t>>(
247243
grid_data, det_builder, bounds, binnings);
248244
}
249245
// 2D cylinder grid
250246
case io::accel_id::cylinder2_grid: {
251-
return deserialize<cylindrical2<algebra_t>>(
247+
return convert<detector_t, cylindrical2<algebra_t>>(
252248
grid_data, det_builder, bounds, binnings);
253249
}
254250
default: {
@@ -260,12 +256,12 @@ class grid_reader : public reader_interface<detector_t> {
260256
switch (grid_data.second.grid_link.type) {
261257
// cuboid grid
262258
case io::accel_id::cuboid3_grid: {
263-
return deserialize<cartesian3<algebra_t>>(
259+
return convert<detector_t, cartesian3<algebra_t>>(
264260
grid_data, det_builder, bounds, binnings);
265261
}
266262
// 3D cylinder grid
267263
case io::accel_id::cylinder3_grid: {
268-
return deserialize<cylindrical3<algebra_t>>(
264+
return convert<detector_t, cylindrical3<algebra_t>>(
269265
grid_data, det_builder, bounds, binnings);
270266
}
271267
default: {
@@ -279,22 +275,23 @@ class grid_reader : public reader_interface<detector_t> {
279275
}
280276

281277
/// @brief End of recursion: build the grid from the @param grid_data
282-
template <typename local_frame_t, typename content_t, typename... bounds_ts,
283-
typename... binning_ts,
278+
template <typename detector_t, typename local_frame_t, typename content_t,
279+
typename... bounds_ts, typename... binning_ts,
284280
std::enable_if_t<sizeof...(bounds_ts) == dim and
285281
sizeof...(binning_ts) == dim,
286282
bool> = true>
287-
static void deserialize(
283+
static void convert(
288284
const std::pair<dindex, grid_payload<content_t>> &grid_idx_and_data,
289285
detector_builder<typename detector_t::metadata, volume_builder>
290286
&det_builder,
291287
types::list<bounds_ts...>, types::list<binning_ts...>) {
292288

289+
using scalar_t = typename detector_t::scalar_type;
290+
293291
// Assemble the grid type
294292
using axes_t =
295293
axis::multi_axis<false, local_frame_t,
296294
axis::single_axis<bounds_ts, binning_ts>...>;
297-
// Ok for now: Only have this serializer
298295
using bin_t =
299296
std::conditional_t<bin_capacity == 0, bins::dynamic_array<value_t>,
300297
bins::static_array<value_t, bin_capacity>>;
@@ -304,7 +301,8 @@ class grid_reader : public reader_interface<detector_t> {
304301
"Grid dimension does not meet dimension of grid reader");
305302

306303
const auto &[sf_type, grid_data] = grid_idx_and_data;
307-
const auto volume_idx{base_type::deserialize(grid_data.owner_link)};
304+
const auto volume_idx{
305+
detail::basic_converter::convert(grid_data.owner_link)};
308306

309307
// Error output
310308
std::stringstream err_stream;

0 commit comments

Comments
 (0)