diff --git a/core/include/detray/core/detector.hpp b/core/include/detray/core/detector.hpp index a1b1df3121..b626860414 100644 --- a/core/include/detray/core/detector.hpp +++ b/core/include/detray/core/detector.hpp @@ -324,6 +324,12 @@ class detector { return _surfaces[bcd.index()]; } + /// @returns a surface using its index - const + DETRAY_HOST_DEVICE + constexpr auto surface(dindex sf_idx) const -> const surface_type & { + return _surfaces[sf_idx]; + } + /// @returns the overall number of surfaces in the detector DETRAY_HOST_DEVICE constexpr auto n_surfaces() const -> dindex { diff --git a/core/include/detray/geometry/detail/surface_kernels.hpp b/core/include/detray/geometry/detail/surface_kernels.hpp index ea0694f969..450dc784ab 100644 --- a/core/include/detray/geometry/detail/surface_kernels.hpp +++ b/core/include/detray/geometry/detail/surface_kernels.hpp @@ -47,6 +47,16 @@ struct surface_kernels { } }; + /// A functor to retrieve the masks shape name + struct get_shape_name { + template + DETRAY_HOST inline std::string operator()(const mask_group_t&, + const index_t&) const { + + return mask_group_t::value_type::shape::name; + } + }; + /// A functor to run the mask self check. Puts error messages into @param os struct mask_self_check { template diff --git a/core/include/detray/geometry/detector_volume.hpp b/core/include/detray/geometry/detector_volume.hpp index 3f6a87ec28..e79a10b12d 100644 --- a/core/include/detray/geometry/detector_volume.hpp +++ b/core/include/detray/geometry/detector_volume.hpp @@ -58,7 +58,7 @@ class detector_volume { /// Constructor from detector @param det and volume index @param vol_idx in /// that detector. constexpr detector_volume(const detector_t &det, const dindex vol_idx) - : detector_volume(det, det.volume_by_index(vol_idx)) {} + : detector_volume(det, det.volumes()[vol_idx]) {} /// Equality operator /// diff --git a/core/include/detray/geometry/surface.hpp b/core/include/detray/geometry/surface.hpp index 00c909be8f..52d66e6a0f 100644 --- a/core/include/detray/geometry/surface.hpp +++ b/core/include/detray/geometry/surface.hpp @@ -64,6 +64,11 @@ class surface { constexpr surface(const detector_t &det, const geometry::barcode bcd) : surface(det, det.surface(bcd)) {} + /// Constructor from detector @param det and surface index @param sf_idx + DETRAY_HOST_DEVICE + constexpr surface(const detector_t &det, const dindex sf_idx) + : surface(det, det.surface(sf_idx)) {} + /// Conversion to surface interface around constant detector type template , bool> = true> @@ -133,6 +138,12 @@ class surface { return visit_mask(); } + /// @returns the mask shape name + DETRAY_HOST + std::string shape_name() const { + return visit_mask(); + } + /// @returns the coordinate transform matrix of the surface DETRAY_HOST_DEVICE constexpr auto transform(const context &ctx) const -> const transform3 & { diff --git a/plugins/svgtools/include/detray/plugins/svgtools/conversion/detector.hpp b/plugins/svgtools/include/detray/plugins/svgtools/conversion/detector.hpp new file mode 100644 index 0000000000..77d90662d3 --- /dev/null +++ b/plugins/svgtools/include/detray/plugins/svgtools/conversion/detector.hpp @@ -0,0 +1,46 @@ +/** Detray library, part of the ACTS project (R&D line) + * + * (c) 2023 CERN for the benefit of the ACTS project + * + * Mozilla Public License Version 2.0 + */ + +#pragma once + +// Project include(s) +#include "detray/geometry/detector_volume.hpp" +#include "detray/plugins/svgtools/conversion/volume.hpp" + +// Actsvg include(s) +#include "actsvg/proto/detector.hpp" + +namespace detray::svgtools::conversion { + +/// @brief Generates the proto detector object +/// +/// @param context The geometry context. +/// @param detector The detector object. +/// @param hide_portals whether to display portals. +/// @param hide_passives whether to display passive surfaces. +/// +/// @returns An actsvg proto volume representing the volume. +template +auto detector(const typename detector_t::geometry_context& context, + const detector_t& detector, const view_t& view, + bool hide_portals = false, bool hide_passives = false, + bool hide_grids = false) { + + actsvg::proto::detector p_detector; + + for (const auto& vol_desc : detector.volumes()) { + + p_detector._volumes.push_back( + svgtools::conversion::volume( + context, detector, detector_volume{detector, vol_desc}, view, + hide_portals, hide_passives, hide_grids)); + } + + return p_detector; +} + +} // namespace detray::svgtools::conversion diff --git a/plugins/svgtools/include/detray/plugins/svgtools/conversion/grid.hpp b/plugins/svgtools/include/detray/plugins/svgtools/conversion/grid.hpp index f2514f7b6b..88335f7124 100644 --- a/plugins/svgtools/include/detray/plugins/svgtools/conversion/grid.hpp +++ b/plugins/svgtools/include/detray/plugins/svgtools/conversion/grid.hpp @@ -60,19 +60,19 @@ inline auto grid_type_and_edges(const grid_t& grid, const view_t&) { dvector edges_r{r, r}; if constexpr (std::is_same_v) { - return std::tuple(actsvg::proto::grid::e_r_phi, edges_r, edges_phi); + return std::tuple(actsvg::proto::grid::e_r_phi, r, edges_r, edges_phi); } if constexpr (std::is_same_v) { - return std::tuple(actsvg::proto::grid::e_x_y, edges_z, edges_r); + return std::tuple(actsvg::proto::grid::e_x_y, r, edges_z, edges_r); } if constexpr (std::is_same_v) { - return std::tuple(actsvg::proto::grid::e_z_phi, edges_z, edges_phi); + return std::tuple(actsvg::proto::grid::e_z_phi, r, edges_z, edges_phi); } if constexpr (std::is_same_v) { - return std::tuple(actsvg::proto::grid::e_z_phi, edges_z, edges_rphi); + return std::tuple(actsvg::proto::grid::e_z_phi, r, edges_z, edges_rphi); } - return std::tuple(actsvg::proto::grid::e_x_y, dvector{}, + return std::tuple(actsvg::proto::grid::e_x_y, r, dvector{}, dvector{}); } @@ -91,12 +91,14 @@ inline auto grid_type_and_edges(const grid_t& grid, const view_t&) { auto edges_r = grid.template get_axis().bin_edges(); auto edges_phi = grid.template get_axis().bin_edges(); + // The axes are always sorted + scalar_t r{edges_r.back()}; if constexpr (std::is_same_v) { - return std::tuple(actsvg::proto::grid::e_r_phi, edges_r, edges_phi); + return std::tuple(actsvg::proto::grid::e_r_phi, r, edges_r, edges_phi); } - return std::tuple(actsvg::proto::grid::e_x_y, dvector{}, + return std::tuple(actsvg::proto::grid::e_x_y, r, dvector{}, dvector{}); } @@ -116,8 +118,9 @@ struct type_and_edge_getter { return grid_type_and_edges(group[index], view); } - return std::tuple(actsvg::proto::grid::e_x_y, dvector{}, - dvector{}); + return std::tuple(actsvg::proto::grid::e_x_y, + detray::detail::invalid_value(), + dvector{}, dvector{}); } }; @@ -143,12 +146,13 @@ std::optional grid(const detector_t& detector, actsvg::proto::grid p_grid; if (not link.is_invalid()) { - const auto [type, edges0, edges1] = + const auto [type, r, edges0, edges1] = detector.accelerator_store() .template visit>(link, view); p_grid._type = type; + p_grid._reference_r = static_cast(r); std::transform(edges0.cbegin(), edges0.cend(), std::back_inserter(p_grid._edges_0), diff --git a/plugins/svgtools/include/detray/plugins/svgtools/conversion/information_section.hpp b/plugins/svgtools/include/detray/plugins/svgtools/conversion/information_section.hpp index 83fd420c55..156aac8177 100644 --- a/plugins/svgtools/include/detray/plugins/svgtools/conversion/information_section.hpp +++ b/plugins/svgtools/include/detray/plugins/svgtools/conversion/information_section.hpp @@ -41,11 +41,12 @@ inline auto information_section( const detray::surface& d_surface) { svgtools::meta::proto::information_section is; is._title = d_surface.is_portal() ? "Portal" : "Surface"; - const auto position = d_surface.center(context); + const auto position = + d_surface.transform(context).point_to_global(d_surface.centroid()); is._info = {"Idx: " + std::to_string(d_surface.index()), point_to_string(position)}; is._position = svgtools::conversion::point(position); return is; } -} // namespace detray::svgtools::conversion \ No newline at end of file +} // namespace detray::svgtools::conversion diff --git a/plugins/svgtools/include/detray/plugins/svgtools/conversion/portal.hpp b/plugins/svgtools/include/detray/plugins/svgtools/conversion/portal.hpp index f465feebf6..d4779e51e7 100644 --- a/plugins/svgtools/include/detray/plugins/svgtools/conversion/portal.hpp +++ b/plugins/svgtools/include/detray/plugins/svgtools/conversion/portal.hpp @@ -23,18 +23,23 @@ namespace detray::svgtools::conversion { template auto portal(const typename detector_t::geometry_context& context, const detector_t& detector, - const detray::surface& d_portal) { + const detray::surface& d_portal, + bool hide_links = false) { assert(d_portal.is_portal()); + using p_portal_t = actsvg::proto::portal; + p_portal_t p_portal; - if (svgtools::utils::is_not_world_portal(d_portal)) { + p_portal._name = "portal_" + std::to_string(d_portal.index()); + if (!hide_links && svgtools::utils::is_not_world_portal(d_portal)) { p_portal._volume_links = { svgtools::conversion::link(context, detector, d_portal)}; } p_portal._surface = svgtools::conversion::surface(context, d_portal); + return p_portal; } -} // namespace detray::svgtools::conversion \ No newline at end of file +} // namespace detray::svgtools::conversion diff --git a/plugins/svgtools/include/detray/plugins/svgtools/conversion/surface.hpp b/plugins/svgtools/include/detray/plugins/svgtools/conversion/surface.hpp index b2c7cd5264..14819506e8 100644 --- a/plugins/svgtools/include/detray/plugins/svgtools/conversion/surface.hpp +++ b/plugins/svgtools/include/detray/plugins/svgtools/conversion/surface.hpp @@ -205,8 +205,14 @@ struct surface_converter { template auto surface(const typename detector_t::geometry_context& context, const detray::surface& d_surface) { - return d_surface.template visit_mask>( - d_surface.transform(context)); + + auto p_surface = + d_surface.template visit_mask>( + d_surface.transform(context)); + + p_surface._name = "surface_" + std::to_string(d_surface.index()); + + return p_surface; } } // namespace detray::svgtools::conversion diff --git a/plugins/svgtools/include/detray/plugins/svgtools/conversion/volume.hpp b/plugins/svgtools/include/detray/plugins/svgtools/conversion/volume.hpp index 4b005a93a7..6329389483 100644 --- a/plugins/svgtools/include/detray/plugins/svgtools/conversion/volume.hpp +++ b/plugins/svgtools/include/detray/plugins/svgtools/conversion/volume.hpp @@ -9,70 +9,63 @@ // Project include(s) #include "detray/geometry/detector_volume.hpp" +#include "detray/geometry/surface.hpp" +#include "detray/plugins/svgtools/conversion/grid.hpp" #include "detray/plugins/svgtools/conversion/portal.hpp" #include "detray/plugins/svgtools/conversion/surface.hpp" #include "detray/plugins/svgtools/utils/volume_utils.hpp" // Actsvg include(s) -#include "actsvg/proto/portal.hpp" -#include "actsvg/proto/surface.hpp" #include "actsvg/proto/volume.hpp" -// System include(s) -#include - namespace detray::svgtools::conversion { -/// @brief Calculates the proto volume of a collection of detray surfaces. +/// @brief Generates the proto volume of a detray volume. /// -/// @param context The context. -/// @param d_surfaces The detray surfaces. +/// @param context The geometry context. +/// @param detector The detractor the volume belongs to. +/// @param d_volume The detray volume. +/// @param hide_portals whether to display the volumes portals. +/// @param hide_passives whether to display the contained passive surfaces. /// /// @returns An actsvg proto volume representing the volume. -template +template auto volume(const typename detector_t::geometry_context& context, const detector_t& detector, - const std::vector>& d_surfaces) { - using p_volume_t = actsvg::proto::volume; - using p_portal_t = actsvg::proto::portal; - using p_surface_t = actsvg::proto::surface; - p_volume_t p_volume; - std::vector surfaces; - std::vector portals; - for (const auto& item : d_surfaces) { - if (item.is_portal()) { - auto portal = svgtools::conversion::portal( - context, detector, item); - portals.push_back(portal); - } else { - auto surface = svgtools::conversion::surface( - context, item); - surfaces.push_back(surface); + const detray::detector_volume& d_volume, + const view_t& view, bool hide_portals = false, + bool hide_passives = false, bool hide_grids = false) { + + actsvg::proto::volume p_volume; + p_volume._index = d_volume.index(); + + for (const auto& desc : + svgtools::utils::surface_lookup(detector, d_volume)) { + + const auto sf = detray::surface{detector, desc}; + + if (sf.is_portal()) { + if (!hide_portals) { + auto portal = svgtools::conversion::portal( + context, detector, sf, false); + p_volume._portals.push_back(portal); + } + } else if (!(sf.is_passive() && hide_passives)) { + auto surface = + svgtools::conversion::surface(context, sf); + p_volume._v_surfaces.push_back(surface); } } - p_volume._v_surfaces = surfaces; - p_volume._portals = portals; - return p_volume; -} -/// @brief Calculates the proto volume of a detray volume. -/// -/// @param context The context. -/// @param d_volume The detray volume. -/// -/// @returns An actsvg proto volume representing the volume. -template -auto volume(const typename detector_t::geometry_context& context, - const detector_t& detector, - const detray::detector_volume& d_volume) { - std::vector> surfaces{}; - const auto descriptors = - svgtools::utils::surface_lookup(detector, d_volume); - for (const auto& desc : descriptors) { - surfaces.push_back(detray::surface{detector, desc}); + // Convert grid, if present + if (!hide_grids) { + if (auto p_grid_ptr = svgtools::conversion::grid( + detector, p_volume._index, view)) { + p_volume._surface_grid = *p_grid_ptr; + } } - return svgtools::conversion::volume(context, detector, - surfaces); + + return p_volume; } } // namespace detray::svgtools::conversion diff --git a/plugins/svgtools/include/detray/plugins/svgtools/illustrator.hpp b/plugins/svgtools/include/detray/plugins/svgtools/illustrator.hpp index 76a92da1b3..7f4fbc23d7 100644 --- a/plugins/svgtools/include/detray/plugins/svgtools/illustrator.hpp +++ b/plugins/svgtools/include/detray/plugins/svgtools/illustrator.hpp @@ -9,6 +9,7 @@ // Project include(s) #include "detray/geometry/surface.hpp" +#include "detray/plugins/svgtools/conversion/detector.hpp" #include "detray/plugins/svgtools/conversion/grid.hpp" #include "detray/plugins/svgtools/conversion/information_section.hpp" #include "detray/plugins/svgtools/conversion/intersection.hpp" @@ -21,7 +22,6 @@ #include "detray/plugins/svgtools/styling/styling.hpp" #include "detray/plugins/svgtools/utils/groups.hpp" #include "detray/plugins/svgtools/utils/volume_utils.hpp" -#include "detray/utils/ranges.hpp" // Actsvg include(s) #include "actsvg/meta.hpp" @@ -62,7 +62,7 @@ class illustrator { illustrator(const detector_t& detector, const typename detector_t::name_map& name_map, const styling::style& style = - detray::svgtools::styling::tableau_colorblind) + detray::svgtools::styling::tableau_colorblind::style) : _detector{detector}, _name_map{name_map}, _style{style} {} /// @returns the detector and volume names @@ -80,9 +80,8 @@ class illustrator { /// Toggle passive surfaces void hide_passives(bool toggle = true) { _hide_passives = toggle; } - /// @brief Converts a detray surface in the detector to an svg. + /// @brief Converts a single detray surface of the detector to an svg. /// - /// @param prefix the id of the svg object. /// @param index the index of the surface in the detector. /// @param view the display view. /// @param gctx the geometry context. @@ -90,66 +89,51 @@ class illustrator { /// @returns @c actsvg::svg::object of the detector's surface. template inline auto draw_surface( - const std::string& prefix, const std::size_t index, const view_t& view, + const std::size_t index, const view_t& view, const typename detector_t::geometry_context& gctx = {}) const { - const auto surface = detray::surface{ - _detector, - _detector.surface_lookup()[static_cast(index)]}; + const auto surface = + detray::surface{_detector, static_cast(index)}; - auto ret = svgtools::utils::group(prefix); - actsvg::svg::object svg_sur; - std::array color; + actsvg::svg::object ret; + const auto& style = _style._detector_style._volume_style; if (surface.is_portal()) { - if (!_hide_portals) { - auto p_portal = svgtools::conversion::portal( - gctx, _detector, surface); - - svgtools::styling::apply_style( - p_portal, _style._volume_style._portal_style, - _style._do_random_coloring); + auto p_portal = svgtools::conversion::portal( + gctx, _detector, surface, false); - std::copy(p_portal._surface._fill._fc._rgb.begin(), - p_portal._surface._fill._fc._rgb.end(), - color.begin()); + svgtools::styling::apply_style(p_portal, style._portal_style); - svg_sur = actsvg::display::portal(prefix, p_portal, view); - } - } else if (!(surface.is_passive() && _hide_passives)) { + // Draw the portal directly + std::string id = p_portal._name + "_" + svg_id(view); + ret = actsvg::display::portal(std::move(id), p_portal, view); + } else { auto p_surface = svgtools::conversion::surface(gctx, surface); - svgtools::styling::apply_style(p_surface, - _style._volume_style._surface_style, - _style._do_random_coloring); + svgtools::styling::apply_style(p_surface, style._surface_style); - std::copy(p_surface._fill._fc._rgb.begin(), - p_surface._fill._fc._rgb.end(), color.begin()); - - svg_sur = actsvg::display::surface(prefix, p_surface, view); + // Draw the surface directly + std::string id = p_surface._name + "_" + svg_id(view); + ret = actsvg::display::surface(std::move(id), p_surface, view); } - if (_show_info && - !(_hide_portals && _hide_passives && !surface.is_sensitive())) { + // Add an optional info box + if (_show_info) { auto p_information_section = svgtools::conversion::information_section(gctx, surface); - std::copy(color.begin(), color.end(), - p_information_section._color.begin()); - ret.add_object(svgtools::meta::display::information_section( - prefix + "_sf_" + std::to_string(index), p_information_section, - view, _info_screen_offset, svg_sur)); + auto info_box = svgtools::meta::display::information_section( + ret._id + "_info_box", p_information_section, view, + _info_screen_offset, ret); + ret.add_object(info_box); } - ret.add_object(svg_sur); return ret; } - /// @brief Converts a collection of detray surfaces in the detector to an - /// svg. + /// @brief Converts a multiple of detray surfaces of the detector to an svg. /// - /// @param prefix the id of the svg object. /// @param indices the collection of surface indices in the detector to /// convert. /// @param view the display view. @@ -158,46 +142,22 @@ class illustrator { /// @returns @c actsvg::svg::object of the detector's surfaces. template inline auto draw_surfaces( - const std::string& prefix, const iterator_t& indices, - const view_t& view, + const iterator_t& indices, const view_t& view, const typename detector_t::geometry_context& gctx = {}) const { - auto ret = svgtools::utils::group(prefix); - for (const auto index : indices) { - const auto svg = draw_surface(prefix, index, view, gctx); - ret.add_object(svg); - } - return ret; - } - - /// @brief Converts a surface grid to svg. - /// - /// @param prefix the id of the svg object. - /// @param index the index of the grid's volume - /// @param view the display view. - /// - /// @return @c actsvg::svg::object of the trajectory and intersections - template - std::optional draw_grid(const std::string& prefix, - const std::size_t index, - const view_t& view) const { - - if (auto p_grid_ptr = svgtools::conversion::grid( - _detector, index, view)) { - svgtools::styling::apply_style(*p_grid_ptr, _style._grid_style); + auto ret = svgtools::utils::group(_name_map.at(0) + "_surfaces_" + + svg_id(view)); - std::string name{prefix + "_" + - _name_map.at(static_cast(index)) + - "_grid"}; - return actsvg::display::grid(std::move(name), *p_grid_ptr); + for (const auto index : indices) { + const auto svg = draw_surface(index, view, gctx); + ret.add_object(svg); } - return {}; + return ret; } - /// @brief Converts a detray volume in the detector to an svg. + /// @brief Converts a detray volume of the detector to an svg. /// - /// @param prefix the id of the svg object. /// @param index the index of the volume in the detector. /// @param view the display view. /// @param gctx the geometry context. @@ -205,32 +165,34 @@ class illustrator { /// @returns @c actsvg::svg::object of the detector's volume. template inline auto draw_volume( - const std::string& prefix, const std::size_t index, const view_t& view, + const std::size_t index, const view_t& view, const typename detector_t::geometry_context& gctx = {}) const { - auto ret = svgtools::utils::group( - prefix + "_" + _name_map.at(static_cast(index))); + const auto d_volume = + detector_volume{_detector, static_cast(index)}; + + auto p_volume = svgtools::conversion::volume( + gctx, _detector, d_volume, view, _hide_portals, _hide_passives, + _hide_grids); - const auto surface_indices = - svgtools::utils::surface_indices(_detector, index); - const auto sf_svg = draw_surfaces(prefix, surface_indices, view, gctx); + // Apply the specific styling + svgtools::styling::apply_style(p_volume, + _style._detector_style._volume_style); - ret.add_object(sf_svg); + std::string id = d_volume.name(_name_map) + "_" + svg_id(view); + auto vol_svg = actsvg::display::volume(std::move(id), p_volume, view); if (!_hide_grids) { - const auto grid_svg = draw_grid(prefix, index, view); - if (grid_svg.has_value()) { - ret.add_object(grid_svg.value()); - } + auto grid_svg = + actsvg::display::grid(id + "_grid", p_volume._surface_grid); + vol_svg.add_object(grid_svg); } - return ret; + return vol_svg; } - /// @brief Converts a collection of detray volumes in the detector to an - /// svg. + /// @brief Converts multiple detray volumes of the detector to an svg. /// - /// @param prefix the id of the svg object. /// @param indices the collection of volume indices in the detector to /// convert. /// @param view the display view. @@ -239,13 +201,13 @@ class illustrator { /// @returns @c actsvg::svg::object of the detector's volumes. template inline auto draw_volumes( - const std::string& prefix, const range_t& indices, const view_t& view, + const range_t& indices, const view_t& view, const typename detector_t::geometry_context& gctx = {}) const { - auto ret = svgtools::utils::group(prefix); + auto ret = svgtools::utils::group(_name_map.at(0) + "_volumes_" + + svg_id(view)); for (const auto index : indices) { - const auto vol_svg = draw_volume(prefix, index, view, gctx); - ret.add_object(vol_svg); + ret.add_object(draw_volume(index, view, gctx)); } return ret; @@ -253,18 +215,24 @@ class illustrator { /// @brief Converts a detray detector to an svg. /// - /// @param prefix the id of the svg object. /// @param view the display view. /// @param gctx the geometry context. /// /// @returns @c actsvg::svg::object of the detector. template inline auto draw_detector( - const std::string& prefix, const view_t& view, + const view_t& view, const typename detector_t::geometry_context& gctx = {}) const { - auto indices = - detray::views::iota(std::size_t{0u}, _detector.volumes().size()); - return draw_volumes(prefix, indices, view, gctx); + + auto p_detector = svgtools::conversion::detector( + gctx, _detector, view, _hide_portals, _hide_passives, _hide_grids); + + // Apply the specific styling + svgtools::styling::apply_style(p_detector, _style._detector_style); + + std::string id = _name_map.at(0) + "_" + svg_id(view); + + return actsvg::display::detector(std::move(id), p_detector, view); } /// @brief Converts a point to an svg. @@ -278,8 +246,7 @@ class illustrator { inline auto draw_landmark(const std::string& prefix, const point_t& point, const view_t& view) const { auto p_landmark = svgtools::conversion::landmark(point); - svgtools::styling::apply_style(p_landmark, _style._landmark_style, - _style._do_random_coloring); + svgtools::styling::apply_style(p_landmark, _style._landmark_style); return svgtools::meta::display::landmark(prefix + "_landmark", p_landmark, view); } @@ -329,8 +296,7 @@ class illustrator { auto p_ir = svgtools::conversion::intersection( _detector, intersections, dir, gctx); - svgtools::styling::apply_style(p_ir, _style._intersection_style, - _style._do_random_coloring); + svgtools::styling::apply_style(p_ir, _style._intersection_style); return svgtools::meta::display::intersection(prefix, p_ir, view); } @@ -351,8 +317,7 @@ class illustrator { auto p_trajectory = svgtools::conversion::trajectory(trajectory, path); - svgtools::styling::apply_style(p_trajectory, _style._trajectory_style, - _style._do_random_coloring); + svgtools::styling::apply_style(p_trajectory, _style._trajectory_style); return svgtools::meta::display::trajectory(prefix + "_traj", p_trajectory, view); @@ -369,9 +334,11 @@ class illustrator { inline auto draw_trajectory(const std::string& prefix, const point3_container& points, const view_t& view) const { + auto p_trajectory = svgtools::conversion::trajectory(points); - svgtools::styling::apply_style(p_trajectory, _style._trajectory_style, - _style._do_random_coloring); + + svgtools::styling::apply_style(p_trajectory, _style._trajectory_style); + return svgtools::meta::display::trajectory(prefix + "_traj", p_trajectory, view); } @@ -428,21 +395,15 @@ class illustrator { ret._id = prefix; if (not intersections.empty()) { - auto i_style = svgtools::styling::copy_fill_colors( - _style._intersection_style, _style._trajectory_style); - i_style._fill_colors[0]._opacity = 0.5f; - i_style._marker_type = "o"; auto p_ir = svgtools::conversion::intersection( _detector, intersections, trajectory.dir(0.f), gctx); - svgtools::styling::apply_style(p_ir, i_style, - _style._do_random_coloring); + svgtools::styling::apply_style(p_ir, _style._landmark_style); ret.add_object(svgtools::meta::display::intersection( prefix + "_record", p_ir, view)); // The intersection record is always sorted by path length - // const auto max_path{intersections.back().path}; const auto sf{ detray::surface{_detector, intersections.back().sf_desc}}; const auto final_pos = sf.local_to_global( @@ -456,6 +417,12 @@ class illustrator { } private: + /// @returns the string id of a view + template + std::string svg_id(const view_t& view) const { + return view._axis_names[0] + view._axis_names[1]; + } + const actsvg::point2 _info_screen_offset{-300, 300}; const detector_t& _detector; const typename detector_t::name_map& _name_map; @@ -463,7 +430,7 @@ class illustrator { bool _hide_grids = false; bool _hide_portals = false; bool _hide_passives = false; - styling::style _style = styling::style1; + styling::style _style = styling::tableau_colorblind::style; }; } // namespace detray::svgtools diff --git a/plugins/svgtools/include/detray/plugins/svgtools/styling/colors.hpp b/plugins/svgtools/include/detray/plugins/svgtools/styling/colors.hpp new file mode 100644 index 0000000000..e0a28c9f4f --- /dev/null +++ b/plugins/svgtools/include/detray/plugins/svgtools/styling/colors.hpp @@ -0,0 +1,112 @@ +/** Detray library, part of the ACTS project (R&D line) + * + * (c) 2023 CERN for the benefit of the ACTS project + * + * Mozilla Public License Version 2.0 + */ + +#pragma once + +// Actsvg include(s) +#include "actsvg/core/style.hpp" + +// System include(s) +#include +#include + +namespace detray::svgtools::styling::colors { + +/// @brief Picks a random element in the container. +template +auto pick_random(container_t container) { + const auto idx = static_cast(std::rand()) % container.size(); + return container[idx]; +} + +// Black +constexpr std::array black{0, 0, 0}; +constexpr std::array dark_grey{171, 171, 171}; +constexpr std::array mortar{89, 89, 89}; +constexpr std::array suva_grey{137, 137, 137}; +constexpr std::array very_light_grey{207, 207, 207}; + +// Red tones +constexpr std::array red{255, 0, 0}; +constexpr std::array cardinal{167, 51, 63}; +constexpr std::array madder{165, 28, 48}; +constexpr std::array auburn{167, 51, 63}; +constexpr std::array burgundy{116, 18, 29}; +constexpr std::array chocolate_cosmos{88, 12, 31}; +constexpr std::array macaroni_and_cheese{255, 188, 121}; +constexpr std::array pumpkin{255, 128, 14}; +constexpr std::array tenne{200, 82, 0}; + +// Blue tones +constexpr std::array blue{0, 0, 255}; +constexpr std::array celestial_blue{62, 146, 204}; +constexpr std::array cerulean{0, 107, 164}; +constexpr std::array lapis_lazulli{42, 98, 143}; +constexpr std::array picton_blue{95, 158, 209}; +constexpr std::array prussian_blue1{19, 41, 61}; +constexpr std::array prussian_blue2{22, 50, 79}; +constexpr std::array indigo_dye{24, 67, 90}; +constexpr std::array sail{162, 200, 236}; + +// Green tones +constexpr std::array green{0, 255, 0}; +constexpr std::array celadon{190, 230, 206}; +constexpr std::array aquamarine1{188, 255, 219}; +constexpr std::array aquamarine2{141, 255, 205}; +constexpr std::array emerald{104, 216, 155}; +constexpr std::array shamrock_green{79, 157, 105}; + +std::vector black_theme(const actsvg::scalar opacity) { + return {{black, opacity}}; +} + +std::vector red_theme(const actsvg::scalar opacity) { + return {{cardinal, opacity}, + {madder, opacity}, + {auburn, opacity}, + {burgundy, opacity}, + {chocolate_cosmos, opacity}}; +} + +std::vector blue_theme(const actsvg::scalar opacity) { + return {{celestial_blue, opacity}, + {lapis_lazulli, opacity}, + {prussian_blue1, opacity}, + {prussian_blue2, opacity}, + {indigo_dye, opacity}}; +} + +std::vector green_theme(const actsvg::scalar opacity) { + return {{emerald, opacity}, + {shamrock_green, opacity}, + {celadon, opacity}, + {aquamarine1, opacity}, + {aquamarine2, opacity}}; +} + +// Same color circle that is used in matplot plugin +struct tableau_colorblind10 { + static std::vector grey_tones( + const actsvg::scalar opacity) { + return {{dark_grey, opacity}, + {mortar, opacity}, + {suva_grey, opacity}, + {very_light_grey, opacity}}; + } + static std::vector blue_tones( + const actsvg::scalar opacity) { + return {{cerulean, opacity}, {picton_blue, opacity}, {sail, opacity}}; + } + static std::vector red_tones( + const actsvg::scalar opacity) { + return {{tenne, opacity}, + {pumpkin, opacity}, + {macaroni_and_cheese, opacity}}; + } +}; + +} // namespace detray::svgtools::styling::colors diff --git a/plugins/svgtools/include/detray/plugins/svgtools/styling/styling.hpp b/plugins/svgtools/include/detray/plugins/svgtools/styling/styling.hpp index 599fb140bf..f536bd5581 100644 --- a/plugins/svgtools/include/detray/plugins/svgtools/styling/styling.hpp +++ b/plugins/svgtools/include/detray/plugins/svgtools/styling/styling.hpp @@ -7,12 +7,20 @@ #pragma once +// Project include(s) +#include "detray/plugins/svgtools/meta/proto/intersection.hpp" +#include "detray/plugins/svgtools/meta/proto/landmark.hpp" +#include "detray/plugins/svgtools/meta/proto/trajectory.hpp" +#include "detray/plugins/svgtools/styling/colors.hpp" + // Actsvg include(s) #include "actsvg/core.hpp" #include "actsvg/core/style.hpp" +#include "actsvg/proto/grid.hpp" +#include "actsvg/proto/portal.hpp" +#include "actsvg/proto/surface.hpp" +#include "actsvg/proto/volume.hpp" #include "actsvg/styles/defaults.hpp" -#include "detray/plugins/svgtools/meta/proto/intersection.hpp" -#include "detray/plugins/svgtools/meta/proto/landmark.hpp" // System include(s) #include @@ -20,191 +28,173 @@ namespace detray::svgtools::styling { -namespace colors { - -/// @brief Picks a random element in the container. -template -auto pick_random(container_t container) { - const auto idx = static_cast(std::rand()) % container.size(); - return container[idx]; -} - -// Black -constexpr std::array black{0, 0, 0}; -constexpr std::array dark_grey{171, 171, 171}; -constexpr std::array mortar{89, 89, 89}; -constexpr std::array suva_grey{137, 137, 137}; -constexpr std::array very_light_grey{207, 207, 207}; - -// Red tones -constexpr std::array red{255, 0, 0}; -constexpr std::array cardinal{167, 51, 63}; -constexpr std::array madder{165, 28, 48}; -constexpr std::array auburn{167, 51, 63}; -constexpr std::array burgundy{116, 18, 29}; -constexpr std::array chocolate_cosmos{88, 12, 31}; -constexpr std::array macaroni_and_cheese{255, 188, 121}; -constexpr std::array pumpkin{255, 128, 14}; -constexpr std::array tenne{200, 82, 0}; - -// Blue tones -constexpr std::array blue{0, 0, 255}; -constexpr std::array celestial_blue{62, 146, 204}; -constexpr std::array cerulean{0, 107, 164}; -constexpr std::array lapis_lazulli{42, 98, 143}; -constexpr std::array picton_blue{95, 158, 209}; -constexpr std::array prussian_blue1{19, 41, 61}; -constexpr std::array prussian_blue2{22, 50, 79}; -constexpr std::array indigo_dye{24, 67, 90}; -constexpr std::array sail{162, 200, 236}; - -// Green tones -constexpr std::array green{0, 255, 0}; -constexpr std::array celadon{190, 230, 206}; -constexpr std::array aquamarine1{188, 255, 219}; -constexpr std::array aquamarine2{141, 255, 205}; -constexpr std::array emerald{104, 216, 155}; -constexpr std::array shamrock_green{79, 157, 105}; - -std::vector black_theme(const actsvg::scalar opacity) { - return {{black, opacity}}; -} - -std::vector red_theme(const actsvg::scalar opacity) { - return {{cardinal, opacity}, - {madder, opacity}, - {auburn, opacity}, - {burgundy, opacity}, - {chocolate_cosmos, opacity}}; -} - -std::vector blue_theme(const actsvg::scalar opacity) { - return {{celestial_blue, opacity}, - {lapis_lazulli, opacity}, - {prussian_blue1, opacity}, - {prussian_blue2, opacity}, - {indigo_dye, opacity}}; -} - -std::vector green_theme(const actsvg::scalar opacity) { - return {{emerald, opacity}, - {shamrock_green, opacity}, - {celadon, opacity}, - {aquamarine1, opacity}, - {aquamarine2, opacity}}; -} +/// Style applied to an actsvg proto surface +struct surface_style { -// Same color circle that is used in matplot plugin -struct tableau_colorblind10 { - static std::vector grey_tones( - const actsvg::scalar opacity) { - return {{dark_grey, opacity}, - {mortar, opacity}, - {suva_grey, opacity}, - {very_light_grey, opacity}}; - } - static std::vector blue_tones( - const actsvg::scalar opacity) { - return {{cerulean, opacity}, {picton_blue, opacity}, {sail, opacity}}; - } - static std::vector red_tones( - const actsvg::scalar opacity) { - return {{tenne, opacity}, - {pumpkin, opacity}, - {macaroni_and_cheese, opacity}}; + surface_style(actsvg::style::color fill_color = + colors::tableau_colorblind10::red_tones(0.4f).front(), + actsvg::scalar stroke_width = 0.4f) + : _fill_color{fill_color}, _stroke_width{stroke_width} { + + _stroke_color = fill_color; + _highlight_rgb = colors::macaroni_and_cheese; + _highlights = {}; + _highlight_stroke_rgb = _highlight_rgb; + _highlight_stroke_width = stroke_width; + _font_size = 14u; + _n_segments = 72u; } -}; - -} // namespace colors + // Fill color + actsvg::style::color _fill_color; -struct grid_style { - actsvg::style::color _stroke_color; + // Stroke actsvg::scalar _stroke_width; -}; + actsvg::style::color _stroke_color; -struct landmark_style { - std::vector _fill_colors; - actsvg::scalar _stroke_width; - actsvg::scalar _marker_size; - std::string _marker_type; -}; + // Highlights + std::array _highlight_rgb; + std::vector _highlights; + std::array _highlight_stroke_rgb; + actsvg::scalar _highlight_stroke_width; -struct trajectory_style { - std::vector _fill_colors; - actsvg::scalar _stroke_width; -}; - -struct surface_style { - std::vector _fill_colors; - actsvg::scalar _stroke_width; + unsigned int _font_size; + // Granularity of vertex approximation of arcs + unsigned int _n_segments; }; +/// Style applied to an actsvg proto portal link struct link_style { actsvg::scalar _marker_size; }; +/// Style applied to an actsvg proto portal struct portal_style { surface_style _surface_style; link_style _link_style; - bool _hide_links; }; +/// Style applied to an actsvg proto grid +struct grid_style { + actsvg::style::color _stroke_color; + actsvg::scalar _stroke_width; +}; + +/// Style applied to an actsvg proto volume struct volume_style { surface_style _surface_style; portal_style _portal_style; + grid_style _grid_style; }; -struct style { +/// Style applied to an actsvg proto detector +struct detector_style { volume_style _volume_style; - landmark_style _intersection_style; - trajectory_style _trajectory_style; grid_style _grid_style; - landmark_style _landmark_style; - bool _do_random_coloring = true; }; -const surface_style surface_style1{colors::blue_theme(0.5f), 3.f}; -const surface_style surface_style2{colors::red_theme(0.5f), 3.f}; -const surface_style surface_style3{ - colors::tableau_colorblind10::grey_tones(0.8f), 1.f}; -const surface_style surface_style4{ - colors::tableau_colorblind10::blue_tones(0.3f), 1.5f}; -const surface_style surface_style5{ - colors::tableau_colorblind10::red_tones(0.4f), 1.f}; - -const link_style link_style1{1.2f}; - -const portal_style portal_style1{surface_style2, link_style1, false}; -const portal_style portal_style2{surface_style4, link_style1, false}; - -const volume_style volume_style1{surface_style1, portal_style1}; -const volume_style volume_style2{surface_style5, portal_style2}; - -const landmark_style landmark_style1{colors::black_theme(1.f), 0.8f, 5.f, "x"}; -const landmark_style landmark_style2{colors::black_theme(1.f), 0.8f, 3.f, "o"}; +/// Style applied to a proto landmark +struct landmark_style { + actsvg::style::color _fill_color; + actsvg::scalar _stroke_width; + actsvg::scalar _marker_size; + std::string _marker_type; +}; -const grid_style grid_style1{colors::red_theme(1.f)[0], 1.f}; -const grid_style grid_style2{colors::tableau_colorblind10::blue_tones(1.f)[2], - 1.2f}; +/// Style applied to a proto trajectory +struct trajectory_style { + // Give different tracks different colors + actsvg::style::color _fill_color; + actsvg::scalar _stroke_width; +}; -const trajectory_style trajectory_style1{colors::green_theme(1.f), 1.f}; +/// Global styling options +struct style { + detector_style _detector_style; + trajectory_style _trajectory_style; + landmark_style _landmark_style; + landmark_style _intersection_style; +}; -const style style1{volume_style1, landmark_style1, trajectory_style1, - grid_style1, landmark_style2}; -const style tableau_colorblind{volume_style2, landmark_style1, - trajectory_style1, grid_style2, - landmark_style2, false}; +/// The default styling +namespace svg_default { + +// Surface styles +const styling::surface_style surface_style{colors::blue_theme(0.5f).front(), + 3.f}; +const styling::surface_style surface_style_portal{ + colors::red_theme(0.5f).front(), 3.f}; + +// Portal style +const styling::link_style link_style{1.2f}; +const styling::portal_style portal_style{surface_style_portal, link_style}; + +// Volume style +const styling::grid_style grid_style{colors::red_theme(1.f).front(), 1.f}; +const styling::volume_style volume_style{surface_style, portal_style, + grid_style}; + +// Detector style +const styling::detector_style detector_style{volume_style, grid_style}; + +// Intersection points and track state style +const styling::landmark_style intersection_style{ + colors::black_theme(1.f).front(), 0.8f, 5.f, "x"}; +const styling::landmark_style landmark_style{colors::green_theme(1.f).front(), + 0.8f, 3.f, "o"}; + +// Trajectory style +const styling::trajectory_style trajectory_style{ + colors::green_theme(1.f).front(), 1.f}; + +// Full style +const styling::style style{detector_style, trajectory_style, landmark_style, + intersection_style}; +} // namespace svg_default + +/// Styling that matches data plotting +namespace tableau_colorblind { + +// Surface styles +const styling::surface_style surface_style_passive{ + colors::tableau_colorblind10::grey_tones(0.8f).front(), 1.f}; +const styling::surface_style surface_style_portal{ + colors::tableau_colorblind10::blue_tones(0.2f).front(), 1.5f}; +const styling::surface_style surface_style_sensitive{ + colors::tableau_colorblind10::red_tones(0.3f).front(), 1.f}; + +// Portal style +const styling::portal_style portal_style{surface_style_portal, + svg_default::link_style}; + +// Volume style +const styling::grid_style grid_style{ + colors::tableau_colorblind10::blue_tones(1.f)[2], 1.f}; +const styling::volume_style volume_style{surface_style_sensitive, portal_style, + grid_style}; + +// Detector style +const styling::detector_style detector_style{volume_style, grid_style}; + +// Full style +const styling::style style{detector_style, svg_default::trajectory_style, + svg_default::landmark_style, + svg_default::intersection_style}; +} // namespace tableau_colorblind /// @brief Sets the style of the proto surface. template void apply_style(actsvg::proto::surface& p_surface, - const surface_style& styling, bool do_random_coloring = true) { - auto fill_color = do_random_coloring - ? colors::pick_random(styling._fill_colors) - : styling._fill_colors.front(); - p_surface._fill = actsvg::style::fill(fill_color); + const surface_style& styling) { + // Fill color + p_surface._fill = actsvg::style::fill(styling._fill_color); + p_surface._fill._fc._hl_rgb = styling._highlight_rgb; + p_surface._fill._fc._highlight = styling._highlights; + + // Stroke p_surface._stroke = - actsvg::style::stroke(fill_color, styling._stroke_width); + actsvg::style::stroke(styling._stroke_color, styling._stroke_width); + p_surface._stroke._sc._hl_rgb = styling._highlight_stroke_rgb; + p_surface._stroke._hl_width = styling._highlight_stroke_width; } /// @brief Sets the style of the proto link. @@ -218,17 +208,10 @@ void apply_style( /// @brief Sets the style of the proto portal. template void apply_style(actsvg::proto::portal& p_portal, - const portal_style& styling, bool do_random_coloring = true) { - auto fill_color = - do_random_coloring - ? colors::pick_random(styling._surface_style._fill_colors) - : styling._surface_style._fill_colors.front(); - p_portal._surface._fill = actsvg::style::fill(fill_color); - p_portal._surface._stroke = - actsvg::style::stroke(fill_color, styling._surface_style._stroke_width); - if (styling._hide_links) { - p_portal._volume_links = {}; - } + const portal_style& styling) { + + apply_style(p_portal._surface, styling._surface_style); + for (auto& volume_link : p_portal._volume_links) { apply_style(volume_link, styling._link_style); } @@ -238,30 +221,40 @@ void apply_style(actsvg::proto::portal& p_portal, void apply_style(actsvg::proto::grid& p_grid, const grid_style& styling) { p_grid._stroke._sc = styling._stroke_color; p_grid._stroke._width = styling._stroke_width; + // Use dashed lines for the grid + p_grid._stroke._dasharray = {4}; } /// @brief Sets the style of the proto volume. template void apply_style(actsvg::proto::volume& p_volume, - const volume_style& styling, bool do_random_coloring) { + const volume_style& styling) { for (auto& p_surface : p_volume._v_surfaces) { - apply_style(p_surface, styling._surface_style, do_random_coloring); + apply_style(p_surface, styling._surface_style); } for (auto& p_portals : p_volume._portals) { - apply_style(p_portals, styling._portal_style, do_random_coloring); + apply_style(p_portals, styling._portal_style); + } + apply_style(p_volume._surface_grid, styling._grid_style); +} + +/// @brief Sets the style of the proto volume. +template +void apply_style(actsvg::proto::detector& p_detector, + const detector_style& styling) { + for (auto& p_volume : p_detector._volumes) { + apply_style(p_volume, styling._volume_style); } } /// @brief Sets the style of the proto landmark. template void apply_style(meta::proto::landmark& p_landmark, - const landmark_style& styling, bool do_random_coloring) { - auto fill_color = do_random_coloring - ? colors::pick_random(styling._fill_colors) - : styling._fill_colors.front(); - const auto fill = actsvg::style::fill(fill_color); + const landmark_style& styling) { + + const auto fill = actsvg::style::fill(styling._fill_color); const auto stroke = - actsvg::style::stroke(fill_color, styling._stroke_width); + actsvg::style::stroke(styling._fill_color, styling._stroke_width); const auto marker = actsvg::style::marker{ styling._marker_type, styling._marker_size, fill, stroke}; @@ -271,12 +264,12 @@ void apply_style(meta::proto::landmark& p_landmark, /// @brief Sets the style of the proto intersection record. template void apply_style(meta::proto::intersection& p_intersection, - const landmark_style& styling, bool do_random_coloring) { - auto fill_color = do_random_coloring - ? colors::pick_random(styling._fill_colors) - : styling._fill_colors.front(); + const landmark_style& styling) { + const auto stroke = - actsvg::style::stroke(fill_color, styling._stroke_width); + actsvg::style::stroke(styling._fill_color, styling._stroke_width); + + auto fill_color = styling._fill_color; fill_color._opacity *= 0.5f; const auto fill = actsvg::style::fill(fill_color); @@ -291,18 +284,9 @@ void apply_style(meta::proto::intersection& p_intersection, /// @brief Sets the style of the proto trajectory. template void apply_style(meta::proto::trajectory& p_trajectory, - const trajectory_style& styling, bool do_random_coloring) { - auto fill_color = do_random_coloring - ? colors::pick_random(styling._fill_colors) - : styling._fill_colors.front(); + const trajectory_style& styling) { p_trajectory._stroke = - actsvg::style::stroke(fill_color, styling._stroke_width); -} - -template -auto copy_fill_colors(style1_t target, const style2_t& reference) { - target._fill_colors = reference._fill_colors; - return target; + actsvg::style::stroke(styling._fill_color, styling._stroke_width); } } // namespace detray::svgtools::styling diff --git a/tests/unit_tests/svgtools/detectors.cpp b/tests/unit_tests/svgtools/detectors.cpp index 56ee88807c..bc326e6aac 100644 --- a/tests/unit_tests/svgtools/detectors.cpp +++ b/tests/unit_tests/svgtools/detectors.cpp @@ -44,12 +44,12 @@ int main(int, char**) { il.show_info(true); // Get the svg of the toy detetector in x-y view. - const auto svg_xy = il.draw_detector("detector_xy", xy); + const auto svg_xy = il.draw_detector(xy); // Write the svg of toy detector. detray::svgtools::write_svg("test_svgtools_detector_xy", {xy_axis, svg_xy}); // Get the svg of the toy detetector in z-r view. - const auto svg_zr = il.draw_detector("detector_zr", zr); + const auto svg_zr = il.draw_detector(zr); // Write the svg of toy detector in z-r view detray::svgtools::write_svg("test_svgtools_detector_zr", {zr_axis, svg_zr}); } diff --git a/tests/unit_tests/svgtools/grids.cpp b/tests/unit_tests/svgtools/grids.cpp index 4420ac954f..5d7364f7d9 100644 --- a/tests/unit_tests/svgtools/grids.cpp +++ b/tests/unit_tests/svgtools/grids.cpp @@ -39,16 +39,10 @@ int main(int, char**) { 10UL, 11UL, 12UL, 13UL, 14UL, 15UL, 16UL, 17UL, 18UL, 19UL}; for (const auto i : indices) { - std::string name = "volume" + std::to_string(i) + "_grid"; - // Draw the grid for volume i. - if (auto grid_svg_ptr = il.draw_grid(name, i, view)) { - // Draw volume i. - const auto volume_svg = il.draw_volume("volume", i, view); - // Write volume i and its grid - // (the grid is last in the list since we want it to be displayed on - // top of the volume). - detray::svgtools::write_svg(name + ".svg", - {volume_svg, *grid_svg_ptr}); - } + // Draw volume i. + il.hide_grids(false); + const auto volume_svg = il.draw_volume(i, view); + // Write volume i and its grid + detray::svgtools::write_svg(volume_svg._id, volume_svg); } } diff --git a/tests/unit_tests/svgtools/groups.cpp b/tests/unit_tests/svgtools/groups.cpp index 451c0c3ef9..3fe4765ad5 100644 --- a/tests/unit_tests/svgtools/groups.cpp +++ b/tests/unit_tests/svgtools/groups.cpp @@ -44,25 +44,23 @@ int main(int, char**) { const std::array surface_group_indices{1UL, 100UL, 10UL, 200UL}; const auto svg_surface_group_xy = - il.draw_surfaces("my_surface_group1_xy", surface_group_indices, xy); + il.draw_surfaces(surface_group_indices, xy); detray::svgtools::write_svg("test_svgtools_surface_group_xy", {axes, svg_surface_group_xy}); const auto svg_surface_group_zr = - il.draw_surfaces("my_surface_group1_zr", surface_group_indices, zr); + il.draw_surfaces(surface_group_indices, zr); detray::svgtools::write_svg("test_svgtools_surface_group_zr.svg", {axes, svg_surface_group_zr}); // Visualisation of a group of volumes. const std::array volume_group_indices{3UL, 5UL}; - const auto svg_volume_group_xy = - il.draw_volumes("my_volume_group1_xy", volume_group_indices, xy); + const auto svg_volume_group_xy = il.draw_volumes(volume_group_indices, xy); detray::svgtools::write_svg("test_svgtools_volume_group_xy", {axes, svg_volume_group_xy}); - const auto svg_volume_group_zr = - il.draw_volumes("my_volume_group1_zr", volume_group_indices, zr); + const auto svg_volume_group_zr = il.draw_volumes(volume_group_indices, zr); detray::svgtools::write_svg("test_svgtools_volume_group_zr", {axes, svg_volume_group_zr}); diff --git a/tests/unit_tests/svgtools/intersections.cpp b/tests/unit_tests/svgtools/intersections.cpp index ca6b7ff53d..f94bfefb56 100644 --- a/tests/unit_tests/svgtools/intersections.cpp +++ b/tests/unit_tests/svgtools/intersections.cpp @@ -52,7 +52,7 @@ int main(int, char**) { const detray::svgtools::illustrator il{det, names}; // Drawing the detector. - const auto svg_det = il.draw_detector("detector", view); + const auto svg_det = il.draw_detector(view); // Creating the rays. using generator_t = diff --git a/tests/unit_tests/svgtools/surfaces.cpp b/tests/unit_tests/svgtools/surfaces.cpp index 1b25d92b5a..6410f30e32 100644 --- a/tests/unit_tests/svgtools/surfaces.cpp +++ b/tests/unit_tests/svgtools/surfaces.cpp @@ -50,9 +50,9 @@ int main(int, char**) { for (std::size_t i : indices) { std::string name = "test_svgtools_surface" + std::to_string(i); // Visualization of surface/portal i: - const auto svg_xy = il.draw_surface(name, i, xy); + const auto svg_xy = il.draw_surface(i, xy); detray::svgtools::write_svg(name + "_xy", {axes, svg_xy}); - const auto svg_zr = il.draw_surface(name, i, zr); + const auto svg_zr = il.draw_surface(i, zr); detray::svgtools::write_svg(name + "_zr", {axes, svg_zr}); } } diff --git a/tests/unit_tests/svgtools/trajectories.cpp b/tests/unit_tests/svgtools/trajectories.cpp index 7365e878eb..7be152ce31 100644 --- a/tests/unit_tests/svgtools/trajectories.cpp +++ b/tests/unit_tests/svgtools/trajectories.cpp @@ -51,7 +51,7 @@ int main(int, char**) { // Show the relevant volumes in the detector. const auto svg_volumes = - il.draw_volumes("detector", std::vector{7UL, 9UL, 11UL, 13UL}, view); + il.draw_volumes(std::vector{7UL, 9UL, 11UL, 13UL}, view); // Creating a ray. using transform3_t = typename detector_t::transform3; diff --git a/tests/unit_tests/svgtools/volumes.cpp b/tests/unit_tests/svgtools/volumes.cpp index 5fa1915ac2..b0046212cb 100644 --- a/tests/unit_tests/svgtools/volumes.cpp +++ b/tests/unit_tests/svgtools/volumes.cpp @@ -42,7 +42,9 @@ int main(int, char**) { const auto [det, names] = detray::create_toy_geometry(host_mr); // Creating the svg generator for the detector. - const detray::svgtools::illustrator il{det, names}; + detray::svgtools::illustrator il{det, names}; + // Only test volume conversion here + il.hide_grids(true); // Indexes of the volumes in the detector to be visualized. std::array indices{0UL, 1UL, 2UL, 3UL, 4UL, 5UL, 6UL, @@ -52,9 +54,9 @@ int main(int, char**) { for (std::size_t i : indices) { std::string name = "test_svgtools_volume" + std::to_string(i); // Visualization of volume i: - const auto svg_xy = il.draw_volume(name, i, xy); + const auto svg_xy = il.draw_volume(i, xy); detray::svgtools::write_svg(name + "_xy", {axes, svg_xy}); - const auto svg_zr = il.draw_volume(name, i, zr); + const auto svg_zr = il.draw_volume(i, zr); detray::svgtools::write_svg(name + "_zr", {axes, svg_zr}); } } diff --git a/tests/unit_tests/svgtools/web.cpp b/tests/unit_tests/svgtools/web.cpp index c10ad119b3..37c721b66c 100644 --- a/tests/unit_tests/svgtools/web.cpp +++ b/tests/unit_tests/svgtools/web.cpp @@ -60,19 +60,10 @@ int main(int, char**) { // Draw the volumes and include them in the svg vector. for (std::size_t i : indices) { - std::string name = "Volume_" + std::to_string(i); - const auto svg = il.draw_volume(name, i, view); + const auto svg = il.draw_volume(i, view); svgs.push_back(svg); } - // Draw the grids and include them in the svg vector. - for (const auto i : indices) { - std::string name = "Grid_" + std::to_string(i); - if (auto svg_ptr = il.draw_grid(name, i, view)) { - svgs.push_back(*svg_ptr); - } - } - // Draw some example trajectories and include them in the svg vector (along // with their intersections). for (const auto qop : std::vector{-4, -8, -16}) { diff --git a/tests/validation/include/detray/validation/detail/svg_display.hpp b/tests/validation/include/detray/validation/detail/svg_display.hpp index d4a76ee9d5..0358f7b9d3 100644 --- a/tests/validation/include/detray/validation/detail/svg_display.hpp +++ b/tests/validation/include/detray/validation/detail/svg_display.hpp @@ -8,6 +8,7 @@ #pragma once // Project include(s) +#include "detray/io/common/detail/utils.hpp" #include "detray/plugins/svgtools/illustrator.hpp" #include "detray/plugins/svgtools/styling/styling.hpp" #include "detray/plugins/svgtools/writer.hpp" @@ -98,13 +99,7 @@ inline void svg_display( } // General options - auto path = std::filesystem::path(outdir); - if (not std::filesystem::exists(path)) { - std::error_code err; - if (!std::filesystem::create_directories(path, err)) { - throw std::runtime_error(err.message()); - } - } + auto path = detray::detail::create_path(outdir); actsvg::style::stroke stroke_black = actsvg::style::stroke(); @@ -122,18 +117,16 @@ inline void svg_display( auto svg_traj = draw_intersection_and_traj_svg( gctx, il, intersections_truth, traj, traj_name, intersections, xy); - std::string name_xy = outfile + "_xy"; - const auto vol_xy_svg = il.draw_volumes(name_xy, volumes, xy, gctx); - detray::svgtools::write_svg(path / name_xy, + const auto vol_xy_svg = il.draw_volumes(volumes, xy, gctx); + detray::svgtools::write_svg(path / (outfile + "_" + vol_xy_svg._id), {xy_axis, vol_xy_svg, svg_traj}); // zr - view svg_traj = draw_intersection_and_traj_svg( gctx, il, intersections_truth, traj, traj_name, intersections, zr); - std::string name_zr = outfile + "_zr"; - const auto vol_zr_svg = il.draw_detector(name_zr, zr, gctx); - detray::svgtools::write_svg(path / name_zr, + const auto vol_zr_svg = il.draw_detector(zr, gctx); + detray::svgtools::write_svg(path / (outfile + "_" + vol_zr_svg._id), {zr_axis, vol_zr_svg, svg_traj}); std::cout << "INFO: Wrote debugging data in: " << path << "\n" << std::endl; diff --git a/tests/validation/include/detray/validation/detector_helix_scan.hpp b/tests/validation/include/detray/validation/detector_helix_scan.hpp index a9d4acf319..76a465bb79 100644 --- a/tests/validation/include/detray/validation/detector_helix_scan.hpp +++ b/tests/validation/include/detray/validation/detector_helix_scan.hpp @@ -46,7 +46,7 @@ class helix_scan : public test::fixture_base<> { trk_gen_config_t m_trk_gen_cfg{}; // Visualization style to be applied to the svgs detray::svgtools::styling::style m_style = - detray::svgtools::styling::tableau_colorblind; + detray::svgtools::styling::tableau_colorblind::style; /// Getters /// @{ diff --git a/tests/validation/include/detray/validation/detector_ray_scan.hpp b/tests/validation/include/detray/validation/detector_ray_scan.hpp index d70f9d68a8..6d5a074161 100644 --- a/tests/validation/include/detray/validation/detector_ray_scan.hpp +++ b/tests/validation/include/detray/validation/detector_ray_scan.hpp @@ -81,7 +81,7 @@ class ray_scan : public test::fixture_base<> { trk_gen_config_t m_trk_gen_cfg{}; // Visualization style to be applied to the svgs detray::svgtools::styling::style m_style = - detray::svgtools::styling::tableau_colorblind; + detray::svgtools::styling::tableau_colorblind::style; /// Getters /// @{ diff --git a/tests/validation/include/detray/validation/helix_navigation.hpp b/tests/validation/include/detray/validation/helix_navigation.hpp index 42d7ef909e..fd5348b2d1 100644 --- a/tests/validation/include/detray/validation/helix_navigation.hpp +++ b/tests/validation/include/detray/validation/helix_navigation.hpp @@ -51,7 +51,7 @@ class helix_navigation : public test::fixture_base<> { trk_gen_config_t m_trk_gen_cfg{}; // Visualization style to be applied to the svgs detray::svgtools::styling::style m_style = - detray::svgtools::styling::tableau_colorblind; + detray::svgtools::styling::tableau_colorblind::style; /// Getters /// @{ diff --git a/tests/validation/include/detray/validation/straight_line_navigation.hpp b/tests/validation/include/detray/validation/straight_line_navigation.hpp index ca6fe21fd7..e91dc07ddd 100644 --- a/tests/validation/include/detray/validation/straight_line_navigation.hpp +++ b/tests/validation/include/detray/validation/straight_line_navigation.hpp @@ -51,7 +51,7 @@ class straight_line_navigation : public test::fixture_base<> { trk_gen_config_t m_trk_gen_cfg{}; // Visualization style to be applied to the svgs detray::svgtools::styling::style m_style = - detray::svgtools::styling::tableau_colorblind; + detray::svgtools::styling::tableau_colorblind::style; /// Getters /// @{ diff --git a/tests/validation/src/detector_display.cpp b/tests/validation/src/detector_display.cpp index 964a957937..8e6ffc232e 100644 --- a/tests/validation/src/detector_display.cpp +++ b/tests/validation/src/detector_display.cpp @@ -8,6 +8,7 @@ // Project include(s) #include "detray/core/detector.hpp" #include "detray/geometry/volume_graph.hpp" +#include "detray/io/common/detail/utils.hpp" #include "detray/io/common/detector_reader.hpp" #include "detray/plugins/svgtools/illustrator.hpp" #include "detray/plugins/svgtools/writer.hpp" @@ -39,7 +40,7 @@ int main(int argc, char **argv) { using detector_t = detray::detector<>; // Visualization style to be applied to the svgs - auto style = detray::svgtools::styling::tableau_colorblind; + auto style = detray::svgtools::styling::tableau_colorblind::style; // Filter out the google test flags ::testing::InitGoogleTest(&argc, argv); @@ -80,13 +81,7 @@ int main(int argc, char **argv) { // General options std::string outdir{vm.count("outdir") ? vm["outdir"].as() : "./plots/"}; - auto path = std::filesystem::path(outdir); - if (not std::filesystem::exists(path)) { - std::error_code err; - if (!std::filesystem::create_directories(path, err)) { - throw std::runtime_error(err.message()); - } - } + auto path = detray::detail::create_path(outdir); // Input files if (vm.count("geometry_file")) { @@ -113,6 +108,7 @@ int main(int argc, char **argv) { il.show_info(vm.count("show_info")); il.hide_portals(vm.count("hide_portals")); il.hide_passives(vm.count("hide_passives")); + il.hide_grids(!vm.count("grid_file")); actsvg::style::stroke stroke_black = actsvg::style::stroke(); @@ -122,42 +118,52 @@ int main(int argc, char **argv) { // z-r axis. auto zr_axis = actsvg::draw::x_y_axes("axes", {-2000, 2000}, {-5, 250}, stroke_black, "z", "r"); + // z-r axis. + auto zrphi_axis = actsvg::draw::x_y_axes("axes", {-2000, 2000}, {-300, 300}, + stroke_black, "z", "r-phi"); // Creating the views. const actsvg::views::x_y xy; const actsvg::views::z_r zr; + const actsvg::views::z_rphi zrphi; // Display the volumes if (not volumes.empty()) { - std::string name_xy = names.at(0) + "_volume_display_xy"; - const auto vol_xy_svg = il.draw_volumes(name_xy, volumes, xy, gctx); - detray::svgtools::write_svg(path / name_xy, {xy_axis, vol_xy_svg}); + const auto vol_xy_svg = il.draw_volumes(volumes, xy, gctx); + detray::svgtools::write_svg(path / vol_xy_svg._id, + {xy_axis, vol_xy_svg}); - std::string name_zr = names.at(0) + "_volume_display_zr"; - const auto vol_zr_svg = il.draw_volumes(name_zr, volumes, zr, gctx); - detray::svgtools::write_svg(path / name_zr, {zr_axis, vol_zr_svg}); + const auto vol_zr_svg = il.draw_volumes(volumes, zr, gctx); + detray::svgtools::write_svg(path / vol_zr_svg._id, + {zr_axis, vol_zr_svg}); + + const auto det_zrphi_svg = il.draw_volumes(volumes, zrphi, gctx); + detray::svgtools::write_svg(path / det_zrphi_svg._id, + {zrphi_axis, det_zrphi_svg}); } // Display the surfaces if (not surfaces.empty()) { - std::string name_xy = names.at(0) + "_surface_display_xy"; - const auto sf_xy_svg = il.draw_surfaces(name_xy, surfaces, xy, gctx); - detray::svgtools::write_svg(path / name_xy, {xy_axis, sf_xy_svg}); + const auto sf_xy_svg = il.draw_surfaces(surfaces, xy, gctx); + detray::svgtools::write_svg(path / sf_xy_svg._id, {xy_axis, sf_xy_svg}); + + const auto sf_zr_svg = il.draw_surfaces(surfaces, zr, gctx); + detray::svgtools::write_svg(path / sf_zr_svg._id, {zr_axis, sf_zr_svg}); - std::string name_zr = names.at(0) + "_surface_display_zr"; - const auto sf_zr_svg = il.draw_surfaces(name_zr, surfaces, zr, gctx); - detray::svgtools::write_svg(path / name_zr, {zr_axis, sf_zr_svg}); + const auto det_zrphi_svg = il.draw_surfaces(surfaces, zrphi, gctx); + detray::svgtools::write_svg(path / det_zrphi_svg._id, + {zrphi_axis, det_zrphi_svg}); } // If nothing was specified, display the whole detector if (volumes.empty() and surfaces.empty()) { - std::string name_xy = names.at(0) + "_display_xy"; - const auto det_xy_svg = il.draw_detector(name_xy, xy, gctx); - detray::svgtools::write_svg(path / name_xy, {xy_axis, det_xy_svg}); + const auto det_xy_svg = il.draw_detector(xy, gctx); + detray::svgtools::write_svg(path / det_xy_svg._id, + {xy_axis, det_xy_svg}); - std::string name_zr = names.at(0) + "_display_zr"; - const auto det_zr_svg = il.draw_detector(name_zr, zr, gctx); - detray::svgtools::write_svg(path / name_zr, {zr_axis, det_zr_svg}); + const auto det_zr_svg = il.draw_detector(zr, gctx); + detray::svgtools::write_svg(path / det_zr_svg._id, + {zr_axis, det_zr_svg}); } // Display the detector volume graph