Skip to content

Commit

Permalink
Implement visualization tool, that reads a generic detector and displ…
Browse files Browse the repository at this point in the history
…ays it as svg and dot
  • Loading branch information
niermann999 committed Oct 20, 2023
1 parent 8aa0565 commit 52b32ab
Show file tree
Hide file tree
Showing 16 changed files with 334 additions and 79 deletions.
20 changes: 19 additions & 1 deletion core/include/detray/tools/generators.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,24 @@ dvector<point3_t> vertices(
return {lh_lc, rh_lc, rh_uc, lh_uc};
}

/** Generate vertices, specialized for masks: line
*
* @note template types are simply forwarded to mask
*
* @param sf is the surface that generates vertices
* @param ls is the number of line segments if
*
* @return a generated list of vertices
*/
template <typename point2_t, typename point3_t, bool cross_section,
template <class> typename intersector_t, typename links_t,
typename transform3_t>
dvector<point3_t> vertices(const mask<line<cross_section, intersector_t>,
links_t, transform3_t> & /*line_mask*/,
unsigned int /*lseg*/) {
return {};
}

/// Functor to produce vertices on a mask collection in a mask tuple container.
template <typename point2_t, typename point3_t>
struct vertexer {
Expand Down Expand Up @@ -271,4 +289,4 @@ std::vector<point2_t> r_phi_polygon(scalar_t rmin, scalar_t rmax,
return r_phi_poly;
}

} // namespace detray
} // namespace detray
Original file line number Diff line number Diff line change
Expand Up @@ -75,4 +75,4 @@ auto volume(const typename detector_t::geometry_context& context,
surfaces);
}

} // namespace detray::svgtools::conversion
} // namespace detray::svgtools::conversion
57 changes: 32 additions & 25 deletions plugins/svgtools/include/detray/plugins/svgtools/illustrator.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,8 @@ class illustrator {

illustrator(const detector_t& detector,
const typename detector_t::name_map& name_map,
const bool show_info)
: _detector{detector}, _name_map{name_map}, _show_info{show_info} {}

illustrator(const detector_t& detector,
const typename detector_t::name_map& name_map,
const bool show_info, const styling::style& style)
: _detector{detector},
_name_map{name_map},
_show_info{show_info},
_style{style} {}
const styling::style& style)
: _detector{detector}, _name_map{name_map}, _style{style} {}

/// @brief Converts a detray surface in the detector to an svg.
/// @param identification the id of the svg object.
Expand All @@ -74,18 +66,24 @@ class illustrator {
actsvg::svg::object svg_sur;
std::array<int, 3> color;
if (surface.is_portal()) {
auto p_portal = svgtools::conversion::portal<point3_container>(
context, _detector, surface);
svgtools::styling::apply_style(p_portal,
_style._volume_style._portal_style);
std::copy(p_portal._surface._fill._fc._rgb.begin(),
p_portal._surface._fill._fc._rgb.end(), color.begin());
svg_sur = actsvg::display::portal(identification, p_portal, view);
} else {
if (not _hide_portals) {
auto p_portal = svgtools::conversion::portal<point3_container>(
context, _detector, surface);
svgtools::styling::apply_style(
p_portal, _style._volume_style._portal_style,
_style._do_random_coloring);
std::copy(p_portal._surface._fill._fc._rgb.begin(),
p_portal._surface._fill._fc._rgb.end(),
color.begin());
svg_sur =
actsvg::display::portal(identification, p_portal, view);
}
} else if (not(surface.is_passive() and _hide_passives)) {
auto p_surface = svgtools::conversion::surface<point3_container>(
context, surface);
svgtools::styling::apply_style(p_surface,
_style._volume_style._surface_style);
_style._volume_style._surface_style,
_style._do_random_coloring);
std::copy(p_surface._fill._fc._rgb.begin(),
p_surface._fill._fc._rgb.end(), color.begin());
svg_sur = actsvg::display::surface(identification, p_surface, view);
Expand Down Expand Up @@ -147,8 +145,8 @@ class illustrator {
_detector.volume_by_index(static_cast<detray::dindex>(index));
auto surface_descs =
svgtools::utils::surface_lookup(_detector, d_volume);
for (std::size_t i = 0; i < surface_descs.size(); i++) {
const auto surface_index = surface_descs[i].index();
for (const auto& sf_desc : surface_descs) {
const auto surface_index = sf_desc.index();
ret.add_object(draw_surface(
identification + "_surface" + std::to_string(surface_index),
context, surface_index, view));
Expand All @@ -164,11 +162,11 @@ class illustrator {
/// convert.
/// @param view the display view.
/// @returns @c actsvg::svg::object of the detector's volumes.
template <typename iterator_t, typename view_t>
template <typename range_t, typename view_t>
inline auto draw_volumes(
const std::string& identification,
const typename detector_t::geometry_context& context,
const iterator_t& indices, const view_t& view) const {
const range_t& indices, const view_t& view) const {
actsvg::svg::object ret;
ret._tag = "g";
ret._id = identification;
Expand Down Expand Up @@ -272,15 +270,24 @@ class illustrator {
return ret;
}

/// Toggle info boxes
void show_info(bool toggle = true) { _show_info = toggle; }
/// Toggle portal surfaces
void hide_portals(bool toggle = true) { _hide_portals = toggle; }
/// Toggle passive surfaces
void hide_passives(bool toggle = true) { _hide_passives = toggle; }

private:
using point3 = std::array<actsvg::scalar, 3>;
using point3_container = std::vector<point3>;

const actsvg::point2 _info_screen_offset{-400, 400};
const detector_t& _detector;
const typename detector_t::name_map& _name_map;
const bool _show_info = false;
bool _show_info = false;
bool _hide_portals = false;
bool _hide_passives = false;
const styling::style _style = styling::style1;
};

} // namespace detray::svgtools
} // namespace detray::svgtools
Original file line number Diff line number Diff line change
Expand Up @@ -29,20 +29,30 @@ auto pick_random(container_t container) {

// 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 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 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 celadon{190, 230, 206};
Expand Down Expand Up @@ -79,6 +89,27 @@ std::vector<actsvg::style::color> green_theme(const actsvg::scalar opacity) {
{shamrock_green, opacity}};
}

// Same color circle that is used in matplot plugin
struct tableau_colorblind10 {
static std::vector<actsvg::style::color> grey_tones(
const actsvg::scalar opacity) {
return {{dark_grey, opacity},
{mortar, opacity},
{suva_grey, opacity},
{very_light_grey, opacity}};
}
static std::vector<actsvg::style::color> blue_tones(
const actsvg::scalar opacity) {
return {{cerulean, opacity}, {picton_blue, opacity}, {sail, opacity}};
}
static std::vector<actsvg::style::color> red_tones(
const actsvg::scalar opacity) {
return {{tenne, opacity},
{pumpkin, opacity},
{macaroni_and_cheese, opacity}};
}
};

} // namespace colors

struct landmark_style {
Expand Down Expand Up @@ -115,29 +146,41 @@ struct style {
volume_style _volume_style;
landmark_style _intersection_style;
trajectory_style _trajectory_style;
bool _do_random_coloring = true;
};

const surface_style surface_style1{colors::blue_theme(0.8f), 3.f};

const surface_style surface_style2{colors::red_theme(0.8f), 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(0.8f), 5.f};

const trajectory_style trajectory_style1{colors::green_theme(1.f), 1.f};

const style style1{volume_style1, landmark_style1, trajectory_style1};
const style style1{volume_style1, landmark_style1, trajectory_style1, true};
const style tableau_colorblind{volume_style2, landmark_style1,
trajectory_style1, false};

/// @brief Sets the style of the proto surface.
template <typename point3_container_t>
void apply_style(actsvg::proto::surface<point3_container_t>& p_surface,
const surface_style& styling) {
auto fill_color = colors::pick_random(styling._fill_colors);
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);
p_surface._stroke =
actsvg::style::stroke(fill_color, styling._stroke_width);
Expand All @@ -154,8 +197,11 @@ void apply_style(
/// @brief Sets the style of the proto portal.
template <typename point3_container_t>
void apply_style(actsvg::proto::portal<point3_container_t>& p_portal,
const portal_style& styling) {
auto fill_color = colors::pick_random(styling._surface_style._fill_colors);
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);
Expand All @@ -170,12 +216,12 @@ void apply_style(actsvg::proto::portal<point3_container_t>& p_portal,
/// @brief Sets the style of the proto volume.
template <typename point3_container_t>
void apply_style(actsvg::proto::volume<point3_container_t>& p_volume,
const volume_style& styling) {
const volume_style& styling, bool do_random_coloring) {
for (auto& p_surface : p_volume._v_surfaces) {
apply_style(p_surface, styling._surface_style);
apply_style(p_surface, styling._surface_style, do_random_coloring);
}
for (auto& p_portals : p_volume._portals) {
apply_style(p_portals, styling._portal_style);
apply_style(p_portals, styling._portal_style, do_random_coloring);
}
}

Expand Down
24 changes: 15 additions & 9 deletions plugins/svgtools/include/detray/plugins/svgtools/writer.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,40 +9,46 @@

// Project include(s)
#include "detray/io/common/detail/file_handle.hpp"
#include "detray/io/common/detector_writer.hpp"

// Actsvg include(s)
#include "actsvg/core.hpp"

// System include(s)
#include <ios>
#include <string>
#include <vector>

namespace detray::svgtools {

/// @brief Writes a collection of svgs objects to a single file.
template <typename container_t>
inline void write_svg(const std::string& path, const container_t& svgs) {
inline void write_svg(const std::string& path, const container_t& svgs,
bool replace = true) {
actsvg::svg::file file;
for (const actsvg::svg::object& obj : svgs) {
file.add_object(obj);
}
detray::io::detail::file_handle stream{path, "",
std::ios::out | std::ios::trunc};
std::ios_base::openmode io_mode =
replace ? std::ios::out | std::ios::trunc : std::ios::out;

detray::io::detail::file_handle stream{path, ".svg", io_mode};
*stream << file;
}

/// @brief Writes an svg object to a file.
/// @note To avoid conflict, the ids of the svg objects must be unique.
inline void write_svg(const std::string& path, const actsvg::svg::object& svg) {
write_svg(path, std::array{svg});
inline void write_svg(const std::string& path, const actsvg::svg::object& svg,
bool replace = true) {
write_svg(path, std::array{svg}, replace);
}

/// @brief Writes an svg objects to a file.
/// @note To avoid conflict, the ids of the svg objects must be unique.
inline void write_svg(const std::string& path,
const std::initializer_list<actsvg::svg::object>& svgs) {
const std::initializer_list<actsvg::svg::object>& svgs,
bool replace = true) {
std::vector<actsvg::svg::object> arg = svgs;
write_svg(path, arg);
write_svg(path, arg, replace);
}

} // namespace detray::svgtools
} // namespace detray::svgtools
9 changes: 4 additions & 5 deletions tests/unit_tests/svgtools/detectors.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,16 @@ int main(int, char**) {
toy_detector_t::geometry_context context{};

// Creating the svg generator for the detector.
detray::svgtools::illustrator il{det, names, true};
detray::svgtools::illustrator il{det, names};
il.show_info(true);

// Get the svg of the toy detetector in x-y view.
const auto svg_xy = il.draw_detector("detector_xy", context, xy);
// Write the svg of toy detector.
detray::svgtools::write_svg("test_svgtools_detector_xy.svg",
{xy_axis, svg_xy});
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", context, zr);
// Write the svg of toy detector in z-r view
detray::svgtools::write_svg("test_svgtools_detector_zr.svg",
{zr_axis, svg_zr});
detray::svgtools::write_svg("test_svgtools_detector_zr", {zr_axis, svg_zr});
}
10 changes: 5 additions & 5 deletions tests/unit_tests/svgtools/groups.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,31 +45,31 @@ int main(int, char**) {

const auto svg_surface_group_xy = il.draw_surfaces(
"my_surface_group1_xy", context, surface_group_indices, xy);
detray::svgtools::write_svg("test_svgtools_surface_group_xy.svg",
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", context, surface_group_indices, zr);
detray::svgtools::write_svg("test_svgtools_surface_group_zr.svg",
detray::svgtools::write_svg("test_svgtools_surface_group_zr",
{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", context, volume_group_indices, xy);
detray::svgtools::write_svg("test_svgtools_volume_group_xy.svg",
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", context, volume_group_indices, zr);
detray::svgtools::write_svg("test_svgtools_volume_group_zr.svg",
detray::svgtools::write_svg("test_svgtools_volume_group_zr",
{axes, svg_volume_group_zr});

// Writing SVGs to a combined file.
// NOTE: The all svg object's identification must be unique in the
// file!
detray::svgtools::write_svg(
"test_svgtools_volume_and_surface_group.svg",
"test_svgtools_volume_and_surface_group",
{axes, svg_surface_group_xy, svg_volume_group_zr});
}
Loading

0 comments on commit 52b32ab

Please sign in to comment.