File indexing completed on 2026-05-27 07:24:15
0001
0002
0003
0004
0005
0006
0007
0008
0009 #pragma once
0010
0011
0012 #include "detray/definitions/algebra.hpp"
0013 #include "detray/utils/logging.hpp"
0014
0015
0016 #include "detray/plugins/svgtools/illustrator.hpp"
0017 #include "detray/plugins/svgtools/styling/styling.hpp"
0018 #include "detray/plugins/svgtools/writer.hpp"
0019
0020
0021 #include "detray/io/utils/create_path.hpp"
0022
0023
0024 #include <algorithm>
0025 #include <filesystem>
0026 #include <iostream>
0027 #include <string>
0028 #include <unordered_set>
0029
0030 namespace detray::detail {
0031
0032
0033
0034 template <typename record_t>
0035 std::unordered_set<dindex> get_volume_indices(
0036 const std::vector<record_t> &intersection_record) {
0037 std::unordered_set<dindex> volumes{};
0038 volumes.reserve(intersection_record.size());
0039 for (const auto &single_ir : intersection_record) {
0040 if (single_ir.intersection.surface().identifier().is_invalid()) {
0041 continue;
0042 }
0043 volumes.insert(single_ir.vol_idx);
0044 }
0045
0046 return volumes;
0047 }
0048
0049
0050
0051 template <typename surface_t, concepts::algebra algebra_t>
0052 std::unordered_set<dindex> get_volume_indices(
0053 const dvector<detray::intersection2D<
0054 surface_t, algebra_t, intersection::contains_pos>> &intersections) {
0055 std::unordered_set<dindex> volumes{};
0056 volumes.reserve(intersections.size());
0057 for (const auto &intr : intersections) {
0058 if (intr.surface().identifier().is_invalid()) {
0059 continue;
0060 }
0061 volumes.insert(intr.surface().volume());
0062 }
0063
0064 return volumes;
0065 }
0066
0067
0068
0069 template <template <typename> class candidate_t, typename surface_t,
0070 concepts::algebra algebra_t>
0071 std::unordered_set<dindex> get_volume_indices(
0072 const dvector<candidate_t<detray::intersection2D<
0073 surface_t, algebra_t, intersection::contains_pos>>> &candidates) {
0074 std::unordered_set<dindex> volumes{};
0075 volumes.reserve(candidates.size());
0076 for (const auto &cand : candidates) {
0077 if (cand.intersection.surface().identifier().is_invalid()) {
0078 continue;
0079 }
0080 volumes.insert(cand.intersection.surface().volume());
0081 }
0082
0083 return volumes;
0084 }
0085
0086
0087
0088
0089
0090
0091
0092 template <typename record_t, typename ALLOC>
0093 auto transcribe_intersections(
0094 const std::vector<record_t, ALLOC> &intersection_trace) {
0095 using intersection_t = typename record_t::intersection_type;
0096
0097 std::vector<intersection_t> intersections{};
0098 intersections.reserve(intersection_trace.size());
0099 for (auto &ir : intersection_trace) {
0100
0101 if (ir.intersection.surface().identifier().is_invalid()) {
0102 continue;
0103 }
0104 intersections.push_back(ir.intersection);
0105 }
0106
0107 return intersections;
0108 }
0109
0110
0111 template <typename detector_t, typename truth_trace_t, class traj_t,
0112 typename recorded_trace_t, typename view_t>
0113 auto draw_intersection_and_traj_svg(
0114 const typename detector_t::geometry_context gctx,
0115 detray::svgtools::illustrator<detector_t> &il,
0116 const truth_trace_t &truth_trace, const traj_t &traj,
0117 const std::string &traj_name, const recorded_trace_t &recorded_trace,
0118 const view_t &view,
0119 dindex_range highlight_idx = {detail::invalid_value<dindex>(),
0120 detail::invalid_value<dindex>()}) {
0121
0122 auto truth_intersections = transcribe_intersections(truth_trace);
0123 auto recorded_intersections = transcribe_intersections(recorded_trace);
0124
0125
0126 if (truth_intersections.size() < truth_trace.size()) {
0127 highlight_idx.shift(-1);
0128 }
0129
0130
0131 actsvg::svg::object svg_traj;
0132 if (!truth_intersections.empty()) {
0133 svg_traj = il.draw_intersections("truth_trace", truth_intersections,
0134 traj.dir(0.f), view, highlight_idx, gctx);
0135 }
0136
0137
0138 const auto path{math::max(math::fabs(truth_intersections.front().path()),
0139 math::fabs(truth_intersections.back().path()))};
0140 if (!recorded_intersections.empty()) {
0141 svg_traj.add_object(il.draw_intersections_and_trajectory(
0142 traj_name, recorded_intersections, traj, view, path, highlight_idx,
0143 gctx));
0144 } else {
0145 svg_traj.add_object(il.draw_trajectory(traj_name, traj, path, view));
0146 }
0147
0148 return svg_traj;
0149 }
0150
0151
0152 template <typename detector_t, typename truth_trace_t, class traj_t,
0153 typename recorded_trace_t>
0154 inline void svg_display(
0155 const typename detector_t::geometry_context gctx,
0156 detray::svgtools::illustrator<detector_t> &il,
0157 const truth_trace_t &truth_trace, const traj_t &traj,
0158 const std::string &traj_name,
0159 const std::string &outfile = "detector_display",
0160 const recorded_trace_t &recorded_trace = {},
0161 dindex_range highlight_idx = {detail::invalid_value<dindex>(),
0162 detail::invalid_value<dindex>()},
0163 const bool verbose = true, const std::string &outdir = "./plots/") {
0164
0165 auto volumes = get_volume_indices(truth_trace);
0166 if (!recorded_trace.empty()) {
0167 const auto more_volumes = get_volume_indices(truth_trace);
0168 volumes.insert(more_volumes.begin(), more_volumes.end());
0169 }
0170
0171
0172 auto path = detray::io::create_path(outdir);
0173
0174 actsvg::style::stroke stroke_black = actsvg::style::stroke();
0175
0176
0177 auto xy_axis = actsvg::draw::x_y_axes("axes", {-1100, 1100}, {-1100, 1100},
0178 stroke_black, "x", "y");
0179
0180 auto zr_axis = actsvg::draw::x_y_axes("axes", {-3100, 3100}, {-5, 1100},
0181 stroke_black, "z", "r");
0182
0183 const actsvg::views::x_y xy{};
0184 const actsvg::views::z_r zr{};
0185
0186
0187 auto svg_traj =
0188 draw_intersection_and_traj_svg(gctx, il, truth_trace, traj, traj_name,
0189 recorded_trace, xy, highlight_idx);
0190
0191 const auto [vol_xy_svg, _] = il.draw_volumes(volumes, xy, gctx);
0192 detray::svgtools::write_svg(
0193 path / (outfile + "_" + vol_xy_svg._id + "_" + traj_name),
0194 {xy_axis, vol_xy_svg, svg_traj});
0195
0196
0197 svg_traj =
0198 draw_intersection_and_traj_svg(gctx, il, truth_trace, traj, traj_name,
0199 recorded_trace, zr, highlight_idx);
0200
0201 const auto vol_zr_svg = il.draw_detector(zr, gctx);
0202 detray::svgtools::write_svg(
0203 path / (outfile + "_" + vol_zr_svg._id + "_" + traj_name),
0204 {zr_axis, vol_zr_svg, svg_traj});
0205
0206 if (verbose) {
0207 DETRAY_INFO_HOST("Wrote svgs for debugging in: " << path << "\n");
0208 }
0209 }
0210
0211 }