Skip to content

Commit 69af486

Browse files
authored
Merge pull request #753 from asalzburger/feat-allow-material-maps-custom-boundaries
feat: allow to read material map boundaries
2 parents feee5b4 + 044da40 commit 69af486

File tree

6 files changed

+184
-48
lines changed

6 files changed

+184
-48
lines changed

core/include/detray/builders/grid_factory.hpp

+133-38
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,11 @@ namespace detray {
3636
/// @tparam serialzier_t type of the serializer to the storage represenations
3737
/// @tparam algebra_t the matrix/vector/point types to use
3838
/// @tparam container_t the container types to use
39+
///
40+
/// throughout:
41+
/// @note that bin_edges is only used for variable binning
42+
/// @note that if non-zero axis_spans are provided the values of the
43+
/// mask is overwritten
3944
template <typename bin_t, template <std::size_t> class serializer_t,
4045
typename algebra_t = ALGEBRA_PLUGIN<detray::scalar>>
4146
class grid_factory {
@@ -76,12 +81,14 @@ class grid_factory {
7681
typename phi_binning = axis::regular<host_container_types, scalar_type>,
7782
std::enable_if_t<std::is_enum_v<decltype(r_bounds::label)>, bool> =
7883
true>
79-
auto new_grid(const mask<annulus2D> &grid_bounds,
80-
const std::array<std::size_t, 2UL> n_bins,
81-
const std::vector<std::pair<loc_bin_index<annulus2D>, dindex>>
82-
&bin_capacities = {},
83-
const std::array<std::vector<scalar_type>, 2UL> &bin_edges = {
84-
{}}) const {
84+
auto new_grid(
85+
const mask<annulus2D> &grid_bounds,
86+
const std::array<std::size_t, 2UL> n_bins,
87+
const std::vector<std::pair<loc_bin_index<annulus2D>, dindex>>
88+
&bin_capacities = {},
89+
const std::array<std::vector<scalar_type>, 2UL> &bin_edges = {{}},
90+
const std::array<std::vector<scalar_type>, 2UL> &axis_spans = {
91+
{}}) const {
8592

8693
static_assert(
8794
std::is_same_v<phi_bounds, axis::circular<>>,
@@ -96,13 +103,25 @@ class grid_factory {
96103
constexpr auto e_phi_axis = static_cast<dindex>(axes_t::label1);
97104

98105
auto b_values = grid_bounds.values();
106+
// Overwrite the mask values if axis spans are provided
107+
if (!axis_spans[0UL].empty()) {
108+
assert(axis_spans[0UL].size() == 2UL);
109+
b_values[boundary::e_min_r] = axis_spans[0UL].at(0UL);
110+
b_values[boundary::e_max_r] = axis_spans[0UL].at(1UL);
111+
}
112+
scalar_type min_phi = b_values[boundary::e_average_phi] -
113+
b_values[boundary::e_min_phi_rel];
114+
scalar_type max_phi = b_values[boundary::e_average_phi] +
115+
b_values[boundary::e_max_phi_rel];
116+
if (!axis_spans[1UL].empty()) {
117+
assert(axis_spans[1UL].size() == 2UL);
118+
min_phi = axis_spans[1UL].at(0UL);
119+
max_phi = axis_spans[1UL].at(1UL);
120+
}
99121

100122
return new_grid<local_frame>(
101-
{b_values[boundary::e_min_r], b_values[boundary::e_max_r],
102-
b_values[boundary::e_average_phi] -
103-
b_values[boundary::e_min_phi_rel],
104-
b_values[boundary::e_average_phi] +
105-
b_values[boundary::e_max_phi_rel]},
123+
{b_values[boundary::e_min_r], b_values[boundary::e_max_r], min_phi,
124+
max_phi},
106125
{n_bins[e_r_axis], n_bins[e_phi_axis]}, bin_capacities,
107126
{bin_edges[e_r_axis], bin_edges[e_phi_axis]},
108127
types::list<r_bounds, phi_bounds>{},
@@ -121,12 +140,14 @@ class grid_factory {
121140
typename z_binning = axis::regular<host_container_types, scalar_type>,
122141
std::enable_if_t<std::is_enum_v<decltype(x_bounds::label)>, bool> =
123142
true>
124-
auto new_grid(const mask<cuboid3D> &grid_bounds,
125-
const std::array<std::size_t, 3UL> n_bins,
126-
const std::vector<std::pair<loc_bin_index<cuboid3D>, dindex>>
127-
&bin_capacities = {},
128-
const std::array<std::vector<scalar_type>, 3UL> &bin_edges = {
129-
{}}) const {
143+
auto new_grid(
144+
const mask<cuboid3D> &grid_bounds,
145+
const std::array<std::size_t, 3UL> n_bins,
146+
const std::vector<std::pair<loc_bin_index<cuboid3D>, dindex>>
147+
&bin_capacities = {},
148+
const std::array<std::vector<scalar_type>, 3UL> &bin_edges = {{}},
149+
const std::array<std::vector<scalar_type>, 3UL> &axis_spans = {
150+
{}}) const {
130151
// Axes boundaries and local indices
131152
using boundary = cuboid3D::boundaries;
132153
using axes_t = axes<cuboid3D>::template type<algebra_t>;
@@ -136,7 +157,23 @@ class grid_factory {
136157
constexpr auto e_y_axis = static_cast<dindex>(axes_t::label1);
137158
constexpr auto e_z_axis = static_cast<dindex>(axes_t::label2);
138159

160+
// Overwrite the mask values if axis spans are provided
139161
auto b_values = grid_bounds.values();
162+
if (!axis_spans[0UL].empty()) {
163+
assert(axis_spans[0UL].size() == 2UL);
164+
b_values[boundary::e_min_x] = axis_spans[0UL].at(0UL);
165+
b_values[boundary::e_max_x] = axis_spans[0UL].at(1UL);
166+
}
167+
if (!axis_spans[1UL].empty()) {
168+
assert(axis_spans[1UL].size() == 2UL);
169+
b_values[boundary::e_min_y] = axis_spans[1UL].at(0UL);
170+
b_values[boundary::e_max_y] = axis_spans[1UL].at(1UL);
171+
}
172+
if (!axis_spans[2UL].empty()) {
173+
assert(axis_spans[2UL].size() == 2UL);
174+
b_values[boundary::e_min_z] = axis_spans[2UL].at(0UL);
175+
b_values[boundary::e_max_z] = axis_spans[2UL].at(1UL);
176+
}
140177

141178
return new_grid<local_frame>(
142179
{b_values[boundary::e_min_x], b_values[boundary::e_max_x],
@@ -165,7 +202,8 @@ class grid_factory {
165202
const std::array<std::size_t, 2UL> n_bins,
166203
const std::vector<std::pair<loc_bin_index<cylinder2D>, dindex>>
167204
&bin_capacities = {},
168-
const std::array<std::vector<scalar_type>, 2UL> &bin_edges = {
205+
const std::array<std::vector<scalar_type>, 2UL> &bin_edges = {{}},
206+
const std::array<std::vector<scalar_type>, 2UL> &axis_spans = {
169207
{}}) const {
170208

171209
static_assert(
@@ -181,7 +219,11 @@ class grid_factory {
181219
constexpr auto e_z_axis = static_cast<dindex>(axes_t::label1);
182220

183221
auto b_values = grid_bounds.values();
184-
222+
if (!axis_spans[1UL].empty()) {
223+
assert(axis_spans[1UL].size() == 2UL);
224+
b_values[boundary::e_lower_z] = axis_spans[1UL].at(0UL);
225+
b_values[boundary::e_upper_z] = axis_spans[1UL].at(1UL);
226+
}
185227
return new_grid<local_frame>(
186228
{-constant<scalar_type>::pi, constant<scalar_type>::pi,
187229
b_values[boundary::e_lower_z], b_values[boundary::e_upper_z]},
@@ -202,13 +244,14 @@ class grid_factory {
202244
typename z_binning = axis::regular<host_container_types, scalar_type>,
203245
std::enable_if_t<std::is_enum_v<decltype(rphi_bounds::label)>, bool> =
204246
true>
205-
auto new_grid(const mask<concentric_cylinder2D> &grid_bounds,
206-
const std::array<std::size_t, 2UL> n_bins,
207-
const std::vector<
208-
std::pair<loc_bin_index<concentric_cylinder2D>, dindex>>
209-
&bin_capacities = {},
210-
const std::array<std::vector<scalar_type>, 2UL> &bin_edges = {
211-
{}}) const {
247+
auto new_grid(
248+
const mask<concentric_cylinder2D> &grid_bounds,
249+
const std::array<std::size_t, 2UL> n_bins,
250+
const std::vector<std::pair<loc_bin_index<concentric_cylinder2D>,
251+
dindex>> &bin_capacities = {},
252+
const std::array<std::vector<scalar_type>, 2UL> &bin_edges = {{}},
253+
const std::array<std::vector<scalar_type>, 2UL> &axis_spans = {
254+
{}}) const {
212255

213256
static_assert(
214257
std::is_same_v<rphi_bounds, axis::circular<axis::label::e_rphi>>,
@@ -223,6 +266,11 @@ class grid_factory {
223266
constexpr auto e_z_axis = static_cast<dindex>(axes_t::label1);
224267

225268
auto b_values = grid_bounds.values();
269+
if (!axis_spans[1UL].empty()) {
270+
assert(axis_spans[1UL].size() == 2UL);
271+
b_values[boundary::e_lower_z] = axis_spans[1UL].at(0UL);
272+
b_values[boundary::e_upper_z] = axis_spans[1UL].at(1UL);
273+
}
226274

227275
return new_grid<local_frame>(
228276
{-constant<scalar_type>::pi, constant<scalar_type>::pi,
@@ -250,7 +298,8 @@ class grid_factory {
250298
const std::array<std::size_t, 3UL> n_bins,
251299
const std::vector<std::pair<loc_bin_index<cylinder3D>, dindex>>
252300
&bin_capacities = {},
253-
const std::array<std::vector<scalar_type>, 3UL> &bin_edges = {
301+
const std::array<std::vector<scalar_type>, 3UL> &bin_edges = {{}},
302+
const std::array<std::vector<scalar_type>, 3UL> &axis_spans = {
254303
{}}) const {
255304

256305
static_assert(
@@ -267,11 +316,29 @@ class grid_factory {
267316
constexpr auto e_z_axis = static_cast<dindex>(axes_t::label2);
268317

269318
auto b_values = grid_bounds.values();
319+
// Overwrite the mask values if axis spans are provided
320+
if (!axis_spans[0UL].empty()) {
321+
assert(axis_spans[0UL].size() == 2UL);
322+
b_values[boundary::e_min_r] = axis_spans[0UL].at(0UL);
323+
b_values[boundary::e_max_r] = axis_spans[0UL].at(1UL);
324+
}
325+
scalar_type min_phi = -constant<scalar_type>::pi;
326+
scalar_type max_phi = constant<scalar_type>::pi;
327+
if (!axis_spans[1UL].empty()) {
328+
assert(axis_spans[1UL].size() == 2UL);
329+
min_phi = axis_spans[1UL].at(0UL);
330+
max_phi = axis_spans[1UL].at(1UL);
331+
}
332+
if (!axis_spans[2UL].empty()) {
333+
assert(axis_spans[2UL].size() == 2UL);
334+
b_values[boundary::e_min_z] = axis_spans[2UL].at(0UL);
335+
b_values[boundary::e_max_z] = axis_spans[2UL].at(1UL);
336+
}
270337

271338
return new_grid<local_frame>(
272-
{b_values[boundary::e_min_r], b_values[boundary::e_max_r],
273-
b_values[boundary::e_min_phi], b_values[boundary::e_max_phi],
274-
-b_values[boundary::e_min_z], b_values[boundary::e_max_z]},
339+
{b_values[boundary::e_min_r], b_values[boundary::e_max_r], min_phi,
340+
max_phi, -b_values[boundary::e_min_z],
341+
b_values[boundary::e_max_z]},
275342
{n_bins[e_r_axis], n_bins[e_phi_axis], n_bins[e_z_axis]},
276343
bin_capacities,
277344
{bin_edges[e_r_axis], bin_edges[e_phi_axis], bin_edges[e_z_axis]},
@@ -289,12 +356,14 @@ class grid_factory {
289356
typename phi_binning = axis::regular<host_container_types, scalar_type>,
290357
std::enable_if_t<std::is_enum_v<decltype(r_bounds::label)>, bool> =
291358
true>
292-
auto new_grid(const mask<ring2D> &grid_bounds,
293-
const std::array<std::size_t, 2UL> n_bins,
294-
const std::vector<std::pair<loc_bin_index<ring2D>, dindex>>
295-
&bin_capacities = {},
296-
const std::array<std::vector<scalar_type>, 2UL> &bin_edges = {
297-
{}}) const {
359+
auto new_grid(
360+
const mask<ring2D> &grid_bounds,
361+
const std::array<std::size_t, 2UL> n_bins,
362+
const std::vector<std::pair<loc_bin_index<ring2D>, dindex>>
363+
&bin_capacities = {},
364+
const std::array<std::vector<scalar_type>, 2UL> &bin_edges = {{}},
365+
const std::array<std::vector<scalar_type>, 2UL> &axis_spans = {
366+
{}}) const {
298367

299368
static_assert(std::is_same_v<phi_bounds, axis::circular<>>,
300369
"Phi axis bounds need to be circular for ring shape");
@@ -308,6 +377,12 @@ class grid_factory {
308377
constexpr auto e_phi_axis = static_cast<dindex>(axes_t::label1);
309378

310379
auto b_values = grid_bounds.values();
380+
// Overwrite the mask values if axis spans are provided
381+
if (!axis_spans[0UL].empty()) {
382+
assert(axis_spans[0UL].size() == 2UL);
383+
b_values[boundary::e_inner_r] = axis_spans[0UL].at(0UL);
384+
b_values[boundary::e_outer_r] = axis_spans[0UL].at(1UL);
385+
}
311386

312387
return new_grid<local_frame>(
313388
{b_values[boundary::e_inner_r], b_values[boundary::e_outer_r],
@@ -333,7 +408,8 @@ class grid_factory {
333408
const std::array<std::size_t, 2UL> n_bins,
334409
const std::vector<std::pair<loc_bin_index<rectangle2D>, dindex>>
335410
&bin_capacities = {},
336-
const std::array<std::vector<scalar_type>, 2UL> &bin_edges = {
411+
const std::array<std::vector<scalar_type>, 2UL> &bin_edges = {{}},
412+
const std::array<std::vector<scalar_type>, 2UL> &axis_spans = {
337413
{}}) const {
338414
// Axes boundaries and local indices
339415
using boundary = rectangle2D::boundaries;
@@ -344,6 +420,15 @@ class grid_factory {
344420
constexpr auto e_y_axis = static_cast<dindex>(axes_t::label1);
345421

346422
auto b_values = grid_bounds.values();
423+
// Overwrite the mask values if axis spans are provided
424+
if (!axis_spans[0UL].empty()) {
425+
assert(axis_spans[0UL].size() == 2UL);
426+
b_values[boundary::e_half_x] = axis_spans[0UL].at(1UL);
427+
}
428+
if (!axis_spans[1UL].empty()) {
429+
assert(axis_spans[1UL].size() == 2UL);
430+
b_values[boundary::e_half_y] = axis_spans[1UL].at(1UL);
431+
}
347432

348433
return new_grid<local_frame>(
349434
{-b_values[boundary::e_half_x], b_values[boundary::e_half_x],
@@ -369,7 +454,8 @@ class grid_factory {
369454
const std::array<std::size_t, 2UL> n_bins,
370455
const std::vector<std::pair<loc_bin_index<trapezoid2D>, dindex>>
371456
&bin_capacities = {},
372-
const std::array<std::vector<scalar_type>, 2UL> &bin_edges = {
457+
const std::array<std::vector<scalar_type>, 2UL> &bin_edges = {{}},
458+
const std::array<std::vector<scalar_type>, 2UL> &axis_spans = {
373459
{}}) const {
374460
// Axes boundaries and local indices
375461
using boundary = trapezoid2D::boundaries;
@@ -380,6 +466,15 @@ class grid_factory {
380466
constexpr auto e_y_axis = static_cast<dindex>(axes_t::label1);
381467

382468
auto b_values = grid_bounds.values();
469+
// Overwrite the mask values if axis spans are provided
470+
if (!axis_spans[0UL].empty()) {
471+
assert(axis_spans[0UL].size() == 2UL);
472+
b_values[boundary::e_half_length_1] = axis_spans[0UL].at(1UL);
473+
}
474+
if (!axis_spans[1UL].empty()) {
475+
assert(axis_spans[1UL].size() == 2UL);
476+
b_values[boundary::e_half_length_2] = axis_spans[1UL].at(1UL);
477+
}
383478

384479
return new_grid<local_frame>({-b_values[boundary::e_half_length_1],
385480
b_values[boundary::e_half_length_1],

core/include/detray/builders/material_map_builder.hpp

+18-4
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ class material_map_builder : public volume_decorator<detector_t> {
8787
auto mat_factory = std::dynamic_pointer_cast<
8888
material_map_factory<detector_t, axis::multi_bin<DIM>>>(sf_factory);
8989
if (mat_factory) {
90-
(*mat_factory)(this->surfaces(), m_bin_data, m_n_bins);
90+
(*mat_factory)(this->surfaces(), m_bin_data, m_n_bins,
91+
m_axis_spans);
9192
}
9293
auto mat_generator =
9394
std::dynamic_pointer_cast<material_map_generator<detector_t>>(
@@ -122,12 +123,19 @@ class material_map_builder : public volume_decorator<detector_t> {
122123
continue;
123124
}
124125

126+
// Construct and append the material map for a given surface shape
127+
std::array<std::vector<scalar_type>, DIM> axis_spans{};
128+
auto axis_spans_itr = m_axis_spans.find(sf_idx - 1u);
129+
if (axis_spans_itr != m_axis_spans.end()) {
130+
axis_spans = axis_spans_itr->second;
131+
}
132+
125133
// Construct and append the material map for a given surface shape
126134
auto sf = surface{det, sf_desc};
127135
[[maybe_unused]] auto [mat_id, mat_idx] = sf.template visit_mask<
128136
detail::add_sf_material_map<materials_t>>(
129137
m_factory, m_bin_data.at(sf_idx - 1u), m_n_bins.at(sf_idx - 1u),
130-
det.material_store());
138+
axis_spans, det.material_store());
131139

132140
// Make sure the linking was precomputed correctly
133141
assert(mat_id == sf_desc.material().id());
@@ -189,6 +197,8 @@ class material_map_builder : public volume_decorator<detector_t> {
189197
std::map<dindex, std::vector<bin_data_type>> m_bin_data;
190198
/// Number of bins for the material grid axes
191199
std::map<dindex, std::array<std::size_t, DIM>> m_n_bins{};
200+
/// The Axis spans for the material grid axes
201+
std::map<dindex, std::array<std::vector<scalar_type>, DIM>> m_axis_spans{};
192202
/// Helper to generate empty grids
193203
mat_map_factory_t m_factory{};
194204
};
@@ -211,13 +221,16 @@ template <typename materials_t>
211221
struct add_sf_material_map {
212222

213223
template <typename coll_t, typename index_t, typename mat_factory_t,
214-
typename bin_data_t, std::size_t DIM, typename material_store_t>
224+
typename bin_data_t, std::size_t DIM, typename material_store_t,
225+
typename scalar_t>
215226
DETRAY_HOST inline std::pair<typename materials_t::id, dindex> operator()(
216227
[[maybe_unused]] const coll_t& coll,
217228
[[maybe_unused]] const index_t& index,
218229
[[maybe_unused]] const mat_factory_t& mat_factory,
219230
[[maybe_unused]] std::vector<bin_data_t>& bin_data,
220231
[[maybe_unused]] const std::array<std::size_t, DIM>& n_bins,
232+
[[maybe_unused]] const std::array<std::vector<scalar_t>, DIM>&
233+
axis_spans,
221234
[[maybe_unused]] material_store_t& mat_store) const {
222235

223236
using mask_shape_t = typename coll_t::value_type::shape;
@@ -230,7 +243,8 @@ struct add_sf_material_map {
230243
if constexpr (!is_line && mask_shape_t::dim == DIM) {
231244
// Map a grid onto the surface mask
232245
const auto& sf_mask = coll[index];
233-
auto mat_grid = mat_factory.new_grid(sf_mask, n_bins);
246+
auto mat_grid =
247+
mat_factory.new_grid(sf_mask, n_bins, {}, {}, axis_spans);
234248

235249
// The detector only knows the non-owning grid types
236250
using non_owning_t =

0 commit comments

Comments
 (0)