Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-27 07:24:15

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #pragma once
0010 
0011 // Project include(s)
0012 #include "detray/definitions/algebra.hpp"
0013 #include "detray/utils/logging.hpp"
0014 
0015 // Detray plugin include(s)
0016 #include "detray/plugins/svgtools/illustrator.hpp"
0017 #include "detray/plugins/svgtools/styling/styling.hpp"
0018 #include "detray/plugins/svgtools/writer.hpp"
0019 
0020 // Detray IO include(s)
0021 #include "detray/io/utils/create_path.hpp"
0022 
0023 // System include(s)
0024 #include <algorithm>
0025 #include <filesystem>
0026 #include <iostream>
0027 #include <string>
0028 #include <unordered_set>
0029 
0030 namespace detray::detail {
0031 
0032 /// Find the unique volume indices that the trajectory crossed
0033 /// - intersection record
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 /// Find the unique volume indices that the trajectory crossed
0050 /// - intersection collection
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 /// Find the unique volume indices that the trajectory crossed
0068 /// - object tracer candidate collection
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 /// Transcribe the intersections from an intersection trace into a standalone
0087 /// vector.
0088 ///
0089 /// @param intersection_trace the input intersection trace
0090 ///
0091 /// @returns a vector of intersections in the same order as the input trace.
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     // Dummy record
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 /// @returns the svg of the intersections (truth and track) and the trajectory
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   // Get only the intersections from the traces
0122   auto truth_intersections = transcribe_intersections(truth_trace);
0123   auto recorded_intersections = transcribe_intersections(recorded_trace);
0124 
0125   // Was a dummy record removed before printing?
0126   if (truth_intersections.size() < truth_trace.size()) {
0127     highlight_idx.shift(-1);
0128   }
0129 
0130   // Draw the truth intersections as black crosses
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   // Draw an approximation of the trajectory with the recorded intersections
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 /// Display the geometry, intersection and track data via @c svgtools
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   // Gather all volumes that need to be displayed
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   // General options
0172   auto path = detray::io::create_path(outdir);
0173 
0174   actsvg::style::stroke stroke_black = actsvg::style::stroke();
0175 
0176   // x-y axis.
0177   auto xy_axis = actsvg::draw::x_y_axes("axes", {-1100, 1100}, {-1100, 1100},
0178                                         stroke_black, "x", "y");
0179   // z-r axis.
0180   auto zr_axis = actsvg::draw::x_y_axes("axes", {-3100, 3100}, {-5, 1100},
0181                                         stroke_black, "z", "r");
0182   // Creating the views.
0183   const actsvg::views::x_y xy{};
0184   const actsvg::views::z_r zr{};
0185 
0186   // xy - view
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   // zr - view
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 }  // namespace detray::detail