ACTS
Experiment-independent tracking
Loading...
Searching...
No Matches
illustrator.hpp
1// This file is part of the ACTS project.
2//
3// Copyright (C) 2016 CERN for the benefit of the ACTS project
4//
5// This Source Code Form is subject to the terms of the Mozilla Public
6// License, v. 2.0. If a copy of the MPL was not distributed with this
7// file, You can obtain one at https://mozilla.org/MPL/2.0/.
8
9#pragma once
10
11// Project include(s)
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"
17
18// Detray plugins include(s)
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"
35
36// Actsvg include(s)
37#include "actsvg/meta.hpp"
38
39// System include(s)
40#include <array>
41#include <optional>
42#include <regex>
43#include <stdexcept>
44#include <vector>
45
46namespace detray::svgtools {
47
60template <concepts::detector detector_t>
61class illustrator {
62 using point3 = typename detector_t::point3_type;
63 using point3_container = std::vector<point3>;
64
65 public:
66 illustrator() = delete;
67
73 illustrator(const detector_t& detector,
74 const typename detector_t::name_map& name_map,
75 const styling::style& style =
77 : _detector{detector}, _name_map{name_map}, _style{style} {
78 DETRAY_INFO_HOST(
79 "Run SVG-illustrator for detector: " << detector.name(name_map));
80 }
81
83 const typename detector_t::name_map& names() { return _name_map; }
84
87 styling::style& style() { return _style; }
88
91 void show_info(bool toggle = true) {
92 DETRAY_VERBOSE_HOST("Show info: " << std::boolalpha << toggle
93 << std::noboolalpha);
94 _show_info = toggle;
95 }
96
98 void hide_eta_lines(bool toggle = true) {
99 DETRAY_VERBOSE_HOST("Hide eta lines: " << std::boolalpha << toggle
100 << std::noboolalpha);
101 _hide_eta_lines = toggle;
102 }
103
105 void hide_grids(bool toggle = true) {
106 DETRAY_VERBOSE_HOST("Hide surface grids: " << std::boolalpha << toggle
107 << std::noboolalpha);
108 _hide_grids = toggle;
109 }
110
112 void hide_material(bool toggle = true) {
113 DETRAY_VERBOSE_HOST("Hide material: " << std::boolalpha << toggle
114 << std::noboolalpha);
115 _hide_material = toggle;
116 }
117
119 void hide_portals(bool toggle = true) {
120 DETRAY_VERBOSE_HOST("Hide portal surfaces: " << std::boolalpha << toggle
121 << std::noboolalpha);
122 _hide_portals = toggle;
123 }
124
126 void hide_passives(bool toggle = true) {
127 DETRAY_VERBOSE_HOST("Hide passive surfaces: " << std::boolalpha << toggle
128 << std::noboolalpha);
129 _hide_passives = toggle;
130 }
131
133 void search_window(std::array<dindex, 2> window) {
134 DETRAY_VERBOSE_HOST("Search window for grids: [" << window.at(0) << ", "
135 << window.at(1) << "]");
136 _search_window = window;
137 }
138
139 std::string det_name() const { return _detector.name(_name_map); }
140
148 template <typename view_t>
149 inline auto draw_surface(
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));
155 }
156
157 const auto surface = detray::geometry::surface{_detector, index};
158
159 DETRAY_VERBOSE_HOST("Draw surface: " << surface);
160
161 actsvg::svg::object ret;
162 actsvg::svg::object material;
163 const auto& style = _style._detector_style._volume_style;
164
165 if (surface.is_portal()) {
166 auto p_portals = svgtools::conversion::portal(gctx, _detector, surface,
167 view, style._portal_style,
168 false, _hide_material);
169
170 for (auto& p_portal : p_portals) {
171 std::string id = p_portal._name + "_" + svg_id(view);
172
173 DETRAY_DEBUG_HOST("-> Portal SVG ID: " << id);
174
175 ret.add_object(actsvg::display::portal(std::move(id), p_portal, view));
176 }
177
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);
182 }
183 } else {
184 const auto& sf_style = surface.is_sensitive()
185 ? style._sensitive_surface_style
186 : style._passive_surface_style;
187
188 auto p_surfaces = svgtools::conversion::surface(
189 gctx, _detector, surface, view, sf_style, _hide_material);
190
191 // Draw the surfaces directly
192 for (auto& p_surface : p_surfaces) {
193 std::string id = p_surface._name + "_" + svg_id(view);
194
195 DETRAY_DEBUG_HOST("-> Surface SVG ID: " << id);
196
197 ret.add_object(
198 actsvg::display::surface(std::move(id), p_surface, view));
199 }
200
201 // The surface links to only one material for all masks
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);
206 }
207 }
208 // Add an optional info box
209 if (_show_info) {
210 auto p_information_section =
211 svgtools::conversion::information_section(gctx, surface);
212
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);
217 }
218
219 return std::tuple{ret, material};
220 }
221
230 template <detray::ranges::range range_t, typename view_t>
231 inline auto draw_surfaces(
232 const range_t& indices, const view_t& view,
233 const typename detector_t::geometry_context& gctx = {}) const {
234 DETRAY_VERBOSE_HOST("Draw surfaces...");
235
236 auto ret = svgtools::utils::group(det_name() + "_surfaces_" + svg_id(view));
237
238 auto material =
239 svgtools::utils::group(det_name() + "_material_" + svg_id(view));
240
241 for (const auto [i, index] : detray::views::enumerate(indices)) {
242 auto [sf_svg, mat_svg] = draw_surface(index, view, gctx);
243
244 ret.add_object(sf_svg);
245
246 // Material is optional
247 if (mat_svg.is_defined()) {
248 // Only add one gradient box
249 if (i == 0) {
250 material.add_object(mat_svg);
251 } else {
252 material.add_object(mat_svg._sub_objects.at(0));
253 }
254 }
255 }
256
257 return std::tuple{ret, material};
258 }
259
265 template <typename view_t>
266 inline auto draw_surface_material(const dindex index,
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));
271 }
272
273 const auto surface = detray::geometry::surface{_detector, index};
274
275 if (_hide_material) {
276 return actsvg::svg::object{};
277 }
278
279 DETRAY_VERBOSE_HOST("Draw material for surface: " << surface);
280
281 const styling::surface_material_style* mat_style{nullptr};
282 const auto& vol_style = _style._detector_style._volume_style;
283 switch (surface.id()) {
284 using enum surface_id;
285 case e_portal: {
286 mat_style = &vol_style._portal_style._surface_style._material_style;
287 break;
288 }
289 case e_sensitive: {
290 mat_style = &vol_style._sensitive_surface_style._material_style;
291 break;
292 }
293 case e_passive: {
294 mat_style = &vol_style._passive_surface_style._material_style;
295 break;
296 }
297 case e_unknown: {
298 throw std::runtime_error("Encountered surface of unknown type.");
299 break;
300 }
301 }
302
303 auto p_material = svgtools::conversion::surface_material(_detector, surface,
304 view, *mat_style);
305
306 std::string id = det_name() + "_material_map_" +
307 std::to_string(surface.index()) + svg_id(view);
308
309 DETRAY_DEBUG_HOST("-> Surface Material SVG ID: " << id);
310
311 return actsvg::display::surface_material(id, p_material);
312 }
313
321 template <detray::ranges::range range_t, typename view_t>
322 inline auto draw_surface_materials(const range_t& indices,
323 const view_t& view) const {
324 if (_hide_material) {
325 DETRAY_VERBOSE_HOST("Draw surface materials...");
326 }
327
328 auto ret = svgtools::utils::group(det_name() + "_surface_materials_" +
329 svg_id(view));
330
331 for (const auto [i, index] : detray::views::enumerate(indices)) {
332 auto mat_svg = draw_surface_material(index, view);
333
334 // Only add one gradient box
335 if (i == 0) {
336 ret.add_object(mat_svg);
337 } else {
338 ret.add_object(mat_svg._sub_objects.at(0));
339 }
340 }
341
342 return ret;
343 }
344
352 template <typename view_t>
353 inline auto draw_volume(
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);
360 }
361
362 const auto d_volume = tracking_volume{_detector, index};
363
364 DETRAY_VERBOSE_HOST("Draw volume " << "(" << svg_id(view) << "-view): "
365 << d_volume.name(_name_map));
366 DETRAY_DEBUG_HOST("-> " << d_volume);
367
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,
371 _search_window);
372
373 // Draw the basic volume
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);
378
379 actsvg::svg::object sf_grid_svg;
380
381 // Add the grid to the volume svg
382 auto grid_svg = actsvg::display::grid(id + "_grid", p_volume._surface_grid);
383
384 // zr and xy - views of volume including the portals
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));
388
389 if (!_hide_grids) {
390 DETRAY_VERBOSE_HOST("-> Added grid to volume SVG");
391 vol_svg.add_object(grid_svg);
392 }
393 }
394
395 if (!_hide_grids) {
396 // Draw surface grid svg, if volume has grid and the view fits
397 // the grid
398 sf_grid_svg = detray::svgtools::meta::display::surface_grid(
399 id, p_volume, gr_type, grid_svg, view);
400 }
401
402 DETRAY_DEBUG_HOST("-> Volume SVG ID: " << id);
403
404 return std::tuple{vol_svg, sf_grid_svg};
405 }
406
414 template <typename view_t>
415 inline auto draw_volume(
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!";
425 }
426
427 DETRAY_FATAL_HOST(err_str);
428 throw std::invalid_argument(err_str);
429 }
430
431 dindex index = _detector.volume(name, _name_map).index();
432
433 return draw_volume(index, view, gctx);
434 }
435
444 template <detray::ranges::range range_t, typename view_t>
445 inline auto draw_volumes(
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...");
449
450 // Overlay the volume svgs
451 auto vol_group =
452 svgtools::utils::group(det_name() + "_volumes_" + svg_id(view));
453
454 // The surface[grid] sheets per volume
455 std::vector<actsvg::svg::object> sf_grids;
456
457 for (const auto& vol_identifier : volume_ids) {
458 auto [vol_svg, sf_grid] = draw_volume(vol_identifier, view, gctx);
459
460 // The general volume display
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);
464 }
465 sf_grids.push_back(std::move(sf_grid));
466 }
467
468 return std::tuple(vol_group, std::move(sf_grids));
469 }
470
479 template <typename view_t>
480 inline auto draw_detector(
481 const view_t& view,
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...");
485
486 auto p_detector = svgtools::conversion::detector(
487 gctx, _detector, view, _style._detector_style, _hide_portals,
488 _hide_passives, _hide_grids);
489
490 std::string id = det_name() + "_" + svg_id(view);
491
492 auto det_svg = actsvg::display::detector(std::move(id), p_detector, view);
493
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");
497
498 auto p_eta_lines = svgtools::meta::proto::eta_lines{};
499
500 svgtools::styling::apply_style(p_eta_lines, _style._eta_lines_style);
501
502 // Hardcoded until we find a way to scale axes automatically
503 p_eta_lines._r = r_length;
504 p_eta_lines._z = z_length;
505
506 det_svg.add_object(
507 svgtools::meta::display::eta_lines("eta_lines_", p_eta_lines));
508 }
509 }
510
511 DETRAY_VERBOSE_HOST("Detector SVG ID: " << id);
512 DETRAY_INFO_HOST(
513 "Finished drawing detector: " << _detector.name(_name_map));
514
515 return det_svg;
516 }
517
525 template <typename view_t, concepts::point3D point_t>
526 inline auto draw_landmark(const std::string& prefix, const point_t& point,
527 const view_t& view) const {
528 auto p_landmark =
529 svgtools::conversion::landmark(point, _style._landmark_style);
530
531 return svgtools::meta::display::landmark(prefix + "_landmark", p_landmark,
532 view);
533 }
534
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,
555 _style._intersection_style);
556
557 return svgtools::meta::display::intersection(prefix, p_ir, view);
558 }
559
568 template <typename view_t, template <typename> class trajectory_t,
569 concepts::algebra algebra_t>
570 inline auto draw_trajectory(const std::string& prefix,
571 const trajectory_t<algebra_t>& trajectory,
572 const dscalar<algebra_t> path,
573 const view_t& view) const {
574 auto p_trajectory = svgtools::conversion::trajectory(
575 trajectory, _style._trajectory_style, path);
576
577 return svgtools::meta::display::trajectory(prefix + "_traj", p_trajectory,
578 view);
579 }
580
587 template <typename view_t, typename point3_container>
588 inline auto draw_trajectory(const std::string& prefix,
589 const point3_container& points,
590 const view_t& view) const {
591 auto p_trajectory =
592 svgtools::conversion::trajectory(points, _style._trajectory_style);
593
594 return svgtools::meta::display::trajectory(prefix + "_traj", p_trajectory,
595 view);
596 }
597
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...");
620
621 actsvg::svg::object ret;
622 ret._tag = "g";
623 ret._id = prefix;
624
625 if (!intersections.empty()) {
626 // Draw intersections with landmark style
627 auto p_ir = svgtools::conversion::intersection(
628 _detector, intersections, trajectory.dir(0.f), gctx, highlight_idx,
629 _style._landmark_style);
630
631 ret.add_object(svgtools::meta::display::intersection(prefix + "_record",
632 p_ir, view));
633
634 // The intersection record is always sorted by path length
635 const auto sf_back{
636 detray::geometry::surface{_detector, intersections.back().surface()}};
637 const auto sf_front{detray::geometry::surface{
638 _detector, intersections.front().surface()}};
639
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));
644
645 max_path = vector::norm(pos_back - trajectory.pos(0.f));
646 max_path =
647 math::max(max_path, vector::norm(pos_front - trajectory.pos(0.f)));
648 }
649
650 ret.add_object(
651 draw_trajectory(prefix + "_trajectory", trajectory, max_path, view));
652 return ret;
653 }
654
655 private:
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)};
660
661 return std::regex_replace(name, std::regex(" ยท "), "");
662 }
663
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};
674 styling::style _style = styling::tableau_colorblind::style;
675};
676
677} // namespace detray::svgtools
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
auto draw_intersections(const std::string &prefix, const std::vector< intersection_t > &intersections, const typename detector_t::vector3_type dir, const view_t &view, const dindex_range highlight_idx={detail::invalid_value< dindex >(), detail::invalid_value< dindex >()}, const typename detector_t::geometry_context &gctx={}) const
Converts a collection of intersections to an svg.
Definition illustrator.hpp:546
styling::style & style()
Access the illustrator style.
Definition illustrator.hpp:87
auto draw_surfaces(const range_t &indices, const view_t &view, const typename detector_t::geometry_context &gctx={}) const
Converts a multiple of detray surfaces of the detector to an svg.
Definition illustrator.hpp:231
void hide_passives(bool toggle=true)
Toggle passive surfaces.
Definition illustrator.hpp:126
auto draw_landmark(const std::string &prefix, const point_t &point, const view_t &view) const
Converts a point to an svg.
Definition illustrator.hpp:526
auto draw_volume(const std::string_view name, const view_t &view, const typename detector_t::geometry_context &gctx={}) const
Converts a detray volume of the detector to an svg.
Definition illustrator.hpp:415
auto draw_trajectory(const std::string &prefix, const trajectory_t< algebra_t > &trajectory, const dscalar< algebra_t > path, const view_t &view) const
Converts a trajectory to an svg.
Definition illustrator.hpp:570
auto draw_surface_materials(const range_t &indices, const view_t &view) const
Converts the material of multiple detray surfaces to an svg.
Definition illustrator.hpp:322
void hide_grids(bool toggle=true)
Toggle surface grids.
Definition illustrator.hpp:105
auto draw_intersections_and_trajectory(const std::string &prefix, const std::vector< intersection_t > &intersections, const trajectory_t &trajectory, const view_t &view, typename detector_t::scalar_type max_path=500.f, const dindex_range highlight_idx={detail::invalid_value< dindex >(), detail::invalid_value< dindex >()}, const typename detector_t::geometry_context &gctx={}) const
Converts a trajectory and its intersections to an svg with a related coloring.
Definition illustrator.hpp:611
std::string det_name() const
Definition illustrator.hpp:139
void hide_material(bool toggle=true)
Toggle surface material.
Definition illustrator.hpp:112
auto draw_volumes(const range_t &volume_ids, const view_t &view, const typename detector_t::geometry_context &gctx={}) const
Converts multiple detray volumes of the detector to an svg.
Definition illustrator.hpp:445
illustrator(const detector_t &detector, const typename detector_t::name_map &name_map, const styling::style &style=detray::svgtools::styling::tableau_colorblind::style)
Definition illustrator.hpp:73
auto draw_surface(const dindex index, const view_t &view, const typename detector_t::geometry_context &gctx={}) const
Converts a single detray surface of the detector to an svg.
Definition illustrator.hpp:149
void hide_portals(bool toggle=true)
Toggle portal surfaces.
Definition illustrator.hpp:119
auto draw_volume(const dindex index, const view_t &view, const typename detector_t::geometry_context &gctx={}) const
Converts a detray volume of the detector to an svg.
Definition illustrator.hpp:353
auto draw_detector(const view_t &view, const typename detector_t::geometry_context &gctx={}, const float r_length=1100.f, const float z_length=3100.f) const
Converts a detray detector to an svg.
Definition illustrator.hpp:480
void hide_eta_lines(bool toggle=true)
Toggle eta lines in detector rz-view.
Definition illustrator.hpp:98
void search_window(std::array< dindex, 2 > window)
Neighborhood search window for the grid display.
Definition illustrator.hpp:133
const detector_t::name_map & names()
Definition illustrator.hpp:83
void show_info(bool toggle=true)
Toggle info boxes.
Definition illustrator.hpp:91
auto draw_trajectory(const std::string &prefix, const point3_container &points, const view_t &view) const
Converts a trajectory to an svg.
Definition illustrator.hpp:588
auto draw_surface_material(const dindex index, const view_t &view) const
Converts the material map of a single detray surface to an svg.
Definition illustrator.hpp:266
const styling::style style
Complete style configuration using the Tableau colorblind palette.
Definition styling.hpp:316
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
A proto eta line.
Definition eta_lines.hpp:20
volume_style _volume_style
Style applied to volumes in the detector.
Definition styling.hpp:144
Global styling options.
Definition styling.hpp:184
landmark_style _intersection_style
Styling for intersections.
Definition styling.hpp:194
eta_lines_style _eta_lines_style
Styling for eta guide lines.
Definition styling.hpp:188
landmark_style _landmark_style
Styling for track landmarks.
Definition styling.hpp:192
detector_style _detector_style
Styling for detector geometry.
Definition styling.hpp:186
Style applied to an actsvg proto surface_material.
Definition styling.hpp:45