12#include "detray/core/concepts.hpp"
13#include "detray/definitions/algebra.hpp"
14#include "detray/geometry/surface.hpp"
15#include "detray/utils/logging.hpp"
16#include "detray/utils/ranges.hpp"
19#include "detray/plugins/svgtools/conversion/detector.hpp"
20#include "detray/plugins/svgtools/conversion/grid.hpp"
21#include "detray/plugins/svgtools/conversion/information_section.hpp"
22#include "detray/plugins/svgtools/conversion/intersection.hpp"
23#include "detray/plugins/svgtools/conversion/landmark.hpp"
24#include "detray/plugins/svgtools/conversion/surface.hpp"
25#include "detray/plugins/svgtools/conversion/surface_material.hpp"
26#include "detray/plugins/svgtools/conversion/trajectory.hpp"
27#include "detray/plugins/svgtools/conversion/volume.hpp"
28#include "detray/plugins/svgtools/meta/display/geometry.hpp"
29#include "detray/plugins/svgtools/meta/display/information.hpp"
30#include "detray/plugins/svgtools/meta/display/surface_grid.hpp"
31#include "detray/plugins/svgtools/meta/display/tracking.hpp"
32#include "detray/plugins/svgtools/meta/proto/eta_lines.hpp"
33#include "detray/plugins/svgtools/styling/styling.hpp"
34#include "detray/plugins/svgtools/utils/groups.hpp"
37#include "actsvg/meta.hpp"
46namespace detray::svgtools {
60template <concepts::detector detector_t>
62 using point3 =
typename detector_t::point3_type;
63 using point3_container = std::vector<point3>;
66 illustrator() =
delete;
74 const typename detector_t::name_map&
name_map,
79 "Run SVG-illustrator for detector: " << detector.
name(
name_map));
83 const typename detector_t::name_map&
names() {
return _name_map; }
92 DETRAY_VERBOSE_HOST(
"Show info: " << std::boolalpha << toggle
99 DETRAY_VERBOSE_HOST(
"Hide eta lines: " << std::boolalpha << toggle
100 << std::noboolalpha);
101 _hide_eta_lines = toggle;
106 DETRAY_VERBOSE_HOST(
"Hide surface grids: " << std::boolalpha << toggle
107 << std::noboolalpha);
108 _hide_grids = toggle;
113 DETRAY_VERBOSE_HOST(
"Hide material: " << std::boolalpha << toggle
114 << std::noboolalpha);
115 _hide_material = toggle;
120 DETRAY_VERBOSE_HOST(
"Hide portal surfaces: " << std::boolalpha << toggle
121 << std::noboolalpha);
122 _hide_portals = toggle;
127 DETRAY_VERBOSE_HOST(
"Hide passive surfaces: " << std::boolalpha << toggle
128 << std::noboolalpha);
129 _hide_passives = toggle;
134 DETRAY_VERBOSE_HOST(
"Search window for grids: [" << window.at(0) <<
", "
135 << window.at(1) <<
"]");
136 _search_window = window;
139 std::string
det_name()
const {
return _detector.name(_name_map); }
148 template <
typename view_t>
150 const dindex index,
const view_t& view,
151 const typename detector_t::geometry_context& gctx = {})
const {
152 if (index >= _detector.surfaces().size()) {
153 throw std::invalid_argument(
"Surface index too large: " +
154 std::to_string(index));
159 DETRAY_VERBOSE_HOST(
"Draw surface: " << surface);
161 actsvg::svg::object ret;
162 actsvg::svg::object material;
165 if (surface.is_portal()) {
166 auto p_portals = svgtools::conversion::portal(gctx, _detector, surface,
167 view,
style._portal_style,
168 false, _hide_material);
170 for (
auto& p_portal : p_portals) {
171 std::string
id = p_portal._name +
"_" + svg_id(view);
173 DETRAY_DEBUG_HOST(
"-> Portal SVG ID: " <<
id);
175 ret.add_object(actsvg::display::portal(std::move(
id), p_portal, view));
178 if (!_hide_material && surface.has_material()) {
179 std::string id_0 = p_portals.at(0)._name +
"_" + svg_id(view);
180 material = actsvg::display::surface_material(
181 id_0 +
"_material_map", p_portals.at(0)._surface._material);
184 const auto& sf_style = surface.is_sensitive()
185 ?
style._sensitive_surface_style
186 :
style._passive_surface_style;
188 auto p_surfaces = svgtools::conversion::surface(
189 gctx, _detector, surface, view, sf_style, _hide_material);
192 for (
auto& p_surface : p_surfaces) {
193 std::string
id = p_surface._name +
"_" + svg_id(view);
195 DETRAY_DEBUG_HOST(
"-> Surface SVG ID: " <<
id);
198 actsvg::display::surface(std::move(
id), p_surface, view));
202 if (!_hide_material && surface.has_material()) {
203 std::string id_0 = p_surfaces.at(0)._name +
"_" + svg_id(view);
204 material = actsvg::display::surface_material(
205 id_0 +
"_material_map", p_surfaces.at(0)._material);
210 auto p_information_section =
211 svgtools::conversion::information_section(gctx, surface);
213 auto info_box = svgtools::meta::display::information_section(
214 ret._id +
"_info_box", p_information_section, view,
215 _info_screen_offset, ret);
216 ret.add_object(info_box);
219 return std::tuple{ret, material};
230 template <detray::ranges::range range_t,
typename view_t>
232 const range_t& indices,
const view_t& view,
233 const typename detector_t::geometry_context& gctx = {})
const {
234 DETRAY_VERBOSE_HOST(
"Draw surfaces...");
236 auto ret = svgtools::utils::group(
det_name() +
"_surfaces_" + svg_id(view));
239 svgtools::utils::group(
det_name() +
"_material_" + svg_id(view));
242 auto [sf_svg, mat_svg] =
draw_surface(index, view, gctx);
244 ret.add_object(sf_svg);
247 if (mat_svg.is_defined()) {
252 material.add_object(mat_svg._sub_objects.at(0));
257 return std::tuple{ret, material};
265 template <
typename view_t>
267 const view_t& view)
const {
268 if (index >= _detector.surfaces().size()) {
269 throw std::invalid_argument(
"Surface index too large: " +
270 std::to_string(index));
275 if (_hide_material) {
276 return actsvg::svg::object{};
279 DETRAY_VERBOSE_HOST(
"Draw material for surface: " << surface);
282 const auto& vol_style = _style._detector_style._volume_style;
283 switch (surface.id()) {
286 mat_style = &vol_style._portal_style._surface_style._material_style;
290 mat_style = &vol_style._sensitive_surface_style._material_style;
294 mat_style = &vol_style._passive_surface_style._material_style;
298 throw std::runtime_error(
"Encountered surface of unknown type.");
303 auto p_material = svgtools::conversion::surface_material(_detector, surface,
306 std::string
id =
det_name() +
"_material_map_" +
307 std::to_string(surface.index()) + svg_id(view);
309 DETRAY_DEBUG_HOST(
"-> Surface Material SVG ID: " <<
id);
311 return actsvg::display::surface_material(
id, p_material);
321 template <detray::ranges::range range_t,
typename view_t>
323 const view_t& view)
const {
324 if (_hide_material) {
325 DETRAY_VERBOSE_HOST(
"Draw surface materials...");
328 auto ret = svgtools::utils::group(
det_name() +
"_surface_materials_" +
336 ret.add_object(mat_svg);
338 ret.add_object(mat_svg._sub_objects.at(0));
352 template <
typename view_t>
354 const dindex index,
const view_t& view,
355 const typename detector_t::geometry_context& gctx = {})
const {
356 if (index >= _detector.volumes().size()) {
357 std::string err_str{
"Volume index too large: " + std::to_string(index)};
358 DETRAY_FATAL_HOST(err_str);
359 throw std::invalid_argument(err_str);
362 const auto d_volume = tracking_volume{_detector, index};
364 DETRAY_VERBOSE_HOST(
"Draw volume " <<
"(" << svg_id(view) <<
"-view): "
365 << d_volume.name(_name_map));
366 DETRAY_DEBUG_HOST(
"-> " << d_volume);
368 auto [p_volume, gr_type] = svgtools::conversion::volume(
369 gctx, _detector, d_volume, view, _style._detector_style._volume_style,
370 _hide_portals, _hide_passives, _hide_grids, _hide_material,
374 p_volume._name = d_volume.name(_name_map);
375 p_volume._name = std::regex_replace(p_volume._name, std::regex(
"/"),
"_");
376 std::string
id = p_volume._name +
"_" + svg_id(view);
377 auto vol_svg = svgtools::utils::group(
id);
379 actsvg::svg::object sf_grid_svg;
382 auto grid_svg = actsvg::display::grid(
id +
"_grid", p_volume._surface_grid);
385 if constexpr (!std::is_same_v<view_t, actsvg::views::z_phi> &&
386 !std::is_same_v<view_t, actsvg::views::z_rphi>) {
387 vol_svg.add_object(actsvg::display::volume(
id, p_volume, view));
390 DETRAY_VERBOSE_HOST(
"-> Added grid to volume SVG");
391 vol_svg.add_object(grid_svg);
398 sf_grid_svg = detray::svgtools::meta::display::surface_grid(
399 id, p_volume, gr_type, grid_svg, view);
402 DETRAY_DEBUG_HOST(
"-> Volume SVG ID: " <<
id);
404 return std::tuple{vol_svg, sf_grid_svg};
414 template <
typename view_t>
416 const std::string_view name,
const view_t& view,
417 const typename detector_t::geometry_context& gctx = {})
const {
418 if (_name_map.empty() || !_name_map.contains(name)) {
419 std::string err_str{
"Could not identify volume by name '" +
420 std::string{name} +
"'"};
421 if (_name_map.empty()) {
422 err_str +=
": name map empty!";
423 }
else if (!_name_map.contains(name)) {
424 err_str +=
": name map does not contain voume name!";
427 DETRAY_FATAL_HOST(err_str);
428 throw std::invalid_argument(err_str);
431 dindex index = _detector.volume(name, _name_map).index();
444 template <detray::ranges::range range_t,
typename view_t>
446 const range_t& volume_ids,
const view_t& view,
447 const typename detector_t::geometry_context& gctx = {})
const {
448 DETRAY_VERBOSE_HOST(
"Draw volumes...");
452 svgtools::utils::group(
det_name() +
"_volumes_" + svg_id(view));
455 std::vector<actsvg::svg::object> sf_grids;
457 for (
const auto& vol_identifier : volume_ids) {
458 auto [vol_svg, sf_grid] =
draw_volume(vol_identifier, view, gctx);
461 if constexpr (!std::is_same_v<view_t, actsvg::views::z_phi> &&
462 !std::is_same_v<view_t, actsvg::views::z_rphi>) {
463 vol_group.add_object(vol_svg);
465 sf_grids.push_back(std::move(sf_grid));
468 return std::tuple(vol_group, std::move(sf_grids));
479 template <
typename view_t>
482 const typename detector_t::geometry_context& gctx = {},
483 const float r_length = 1100.f,
const float z_length = 3100.f)
const {
484 DETRAY_VERBOSE_HOST(
"Draw detector...");
486 auto p_detector = svgtools::conversion::detector(
488 _hide_passives, _hide_grids);
490 std::string
id =
det_name() +
"_" + svg_id(view);
492 auto det_svg = actsvg::display::detector(std::move(
id), p_detector, view);
494 if constexpr (std::is_same_v<view_t, actsvg::views::z_r>) {
495 if (!_hide_eta_lines) {
496 DETRAY_VERBOSE_HOST(
"Drawing eta lines");
503 p_eta_lines._r = r_length;
504 p_eta_lines._z = z_length;
507 svgtools::meta::display::eta_lines(
"eta_lines_", p_eta_lines));
511 DETRAY_VERBOSE_HOST(
"Detector SVG ID: " <<
id);
513 "Finished drawing detector: " << _detector.name(_name_map));
525 template <
typename view_t, concepts::po
int3D po
int_t>
527 const view_t& view)
const {
529 svgtools::conversion::landmark(point, _style._landmark_style);
531 return svgtools::meta::display::landmark(prefix +
"_landmark", p_landmark,
545 template <
typename view_t,
typename intersection_t>
547 const std::string& prefix,
548 const std::vector<intersection_t>& intersections,
549 const typename detector_t::vector3_type dir,
const view_t& view,
550 const dindex_range highlight_idx = {detail::invalid_value<dindex>(),
551 detail::invalid_value<dindex>()},
552 const typename detector_t::geometry_context& gctx = {})
const {
553 auto p_ir = svgtools::conversion::intersection(_detector, intersections,
554 dir, gctx, highlight_idx,
557 return svgtools::meta::display::intersection(prefix, p_ir, view);
568 template <
typename view_t,
template <
typename>
class trajectory_t,
569 concepts::algebra algebra_t>
571 const trajectory_t<algebra_t>& trajectory,
573 const view_t& view)
const {
574 auto p_trajectory = svgtools::conversion::trajectory(
575 trajectory, _style._trajectory_style, path);
577 return svgtools::meta::display::trajectory(prefix +
"_traj", p_trajectory,
587 template <
typename view_t,
typename po
int3_container>
589 const point3_container& points,
590 const view_t& view)
const {
592 svgtools::conversion::trajectory(points, _style._trajectory_style);
594 return svgtools::meta::display::trajectory(prefix +
"_traj", p_trajectory,
610 template <
typename view_t,
class trajectory_t,
typename intersection_t>
612 const std::string& prefix,
613 const std::vector<intersection_t>& intersections,
614 const trajectory_t& trajectory,
const view_t& view,
615 typename detector_t::scalar_type max_path = 500.f,
616 const dindex_range highlight_idx = {detail::invalid_value<dindex>(),
617 detail::invalid_value<dindex>()},
618 const typename detector_t::geometry_context& gctx = {})
const {
619 DETRAY_VERBOSE_HOST(
"Draw intersections and trajectory...");
621 actsvg::svg::object ret;
625 if (!intersections.empty()) {
627 auto p_ir = svgtools::conversion::intersection(
628 _detector, intersections, trajectory.dir(0.f), gctx, highlight_idx,
631 ret.add_object(svgtools::meta::display::intersection(prefix +
"_record",
637 const auto sf_front{detray::geometry::surface{
638 _detector, intersections.front().surface()}};
640 const auto pos_back = sf_back.local_to_global(
641 gctx, intersections.back().local(), trajectory.dir(0.f));
642 const auto pos_front = sf_front.local_to_global(
643 gctx, intersections.front().local(), trajectory.dir(0.f));
645 max_path = vector::norm(pos_back - trajectory.pos(0.f));
647 math::max(max_path, vector::norm(pos_front - trajectory.pos(0.f)));
657 template <
typename view_t>
658 std::string svg_id(
const view_t& view)
const {
659 std::string name{view._axis_names.at(0) + view._axis_names.at(1)};
661 return std::regex_replace(name, std::regex(
" ยท "),
"");
664 const actsvg::point2 _info_screen_offset{-300, 300};
665 const detector_t& _detector;
666 const typename detector_t::name_map& _name_map;
667 bool _show_info =
true;
668 bool _hide_eta_lines =
false;
669 bool _hide_grids =
false;
670 bool _hide_material =
true;
671 bool _hide_portals =
false;
672 bool _hide_passives =
false;
673 std::array<dindex, 2> _search_window = {2u, 2u};
std::string name(const name_map &names) const
Return the detector name from the supplied name map.
Definition detector.hpp:228
Facade for a detray detector surface.
Definition surface.hpp:36
get_scalar_t< A, T > dscalar
Scalar type for algebra A and value type T.
Definition algebra.hpp:64
detail::index_range< dindex > dindex_range
Index ranges and sequences.
Definition indexing.hpp:24
unsigned int dindex
Default index type.
Definition indexing.hpp:18
surface_id
surface type, resolved during navigation.
Definition geometry.hpp:41
Material composition properties and density data used by interactions.
Definition material.hpp:36
Map volume indices to volume names and vice versa.
Definition name_map.hpp:23
Range adaptor that creates an enumerate view, optionally starting at a selected index.
Definition enumerate.hpp:266