Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
IndexedSurfacesSvgConverter.hpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file IndexedSurfacesSvgConverter.hpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2023 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 http://mozilla.org/MPL/2.0/.
8 
9 #pragma once
10 
13 #include "Acts/Geometry/Extent.hpp"
23 #include <actsvg/core.hpp>
24 #include <actsvg/meta.hpp>
25 
26 #include <tuple>
27 #include <vector>
28 
29 namespace Acts {
30 
31 namespace Experimental {
32 
33 using namespace detail::GridAxisGenerators;
34 
35 // Generate the possible axes in this case
36 static auto s_possibleAxes =
37  std::tuple<EqBound, EqOpen, EqClosed,
38  // All 1D Var options
40  // All 2D EqEq options
44  // All 2D EqVar options
48  // All 2D VarEq options
52  // All 2D VarEq options
56 
57 } // namespace Experimental
58 
59 namespace Svg {
60 
61 using ProtoSurface = actsvg::proto::surface<std::vector<Vector3>>;
64  std::tuple<std::vector<ProtoSurface>, ProtoGrid,
65  std::vector<std::vector<std::size_t>>>;
66 
67 namespace IndexedSurfacesConverter {
69 struct Options {
74 };
75 
86 template <typename surface_container, typename index_grid>
88  const surface_container& surfaces,
89  const index_grid& indexGrid,
90  const Options& cOptions) {
91  // The return surfaces
92  std::vector<ProtoSurface> pSurfaces;
93  pSurfaces.reserve(surfaces.size());
94 
95  // Make a local copy of the grid Options, in case we have to estimate
96  // an additional bound
97  GridConverter::Options gridOptions = cOptions.gridOptions;
98  Extent constrain;
99 
100  // Estimate the radial extension
101  // - for 1D phi
102  // - for 2D z-phi or phi-z
103  bool estimateR =
104  (index_grid::grid_type::DIM == 1 and indexGrid.casts[0u] == binPhi) or
105  (index_grid::grid_type::DIM == 2 and
106  (indexGrid.casts[0u] == binPhi or indexGrid.casts[1u] == binPhi));
107 
108  for (auto [is, s] : enumerate(surfaces)) {
109  // Create the surface converter options
110  SurfaceConverter::Options sOptions;
111  // Try to see if you have predefined surface styles
112  auto sfIter = cOptions.surfaceStyles.find(s->geometryId());
113  if (sfIter != cOptions.surfaceStyles.end()) {
114  sOptions.style = *sfIter;
115  }
116  auto pSurface = SurfaceConverter::convert(gctx, *s, sOptions);
117  // Run the r estimation
118  if (estimateR) {
119  auto sExtent = s->polyhedronRepresentation(gctx, 4u).extent();
120  if constexpr (index_grid::grid_type::DIM == 2u) {
121  pSurface._radii[0u] = sExtent.medium(binR);
122  }
123  constrain.extend(sExtent, {binR});
124  }
125  pSurfaces.push_back(pSurface);
126  }
127 
128  // Adjust the grid options
129  if constexpr (index_grid::grid_type::DIM == 1u) {
130  if (indexGrid.casts[0u] == binPhi) {
131  auto estRangeR = constrain.range(binR);
132  std::array<ActsScalar, 2u> rRange = {estRangeR.min(), estRangeR.max()};
133  gridOptions.optionalBound = {rRange, binR};
134  }
135  }
136 
137  // Create the grid
138  ProtoGrid pGrid =
139  GridConverter::convert(indexGrid.grid, indexGrid.casts, gridOptions);
140 
141  auto axes = indexGrid.grid.axes();
142 
143  // Specify the highlight indices
144  std::vector<std::vector<std::size_t>> highlightIndices;
145 
146  // 1D connections
147  if constexpr (index_grid::grid_type::DIM == 1u) {
148  for (unsigned int ib0 = 1u; ib0 <= axes[0u]->getNBins(); ++ib0) {
149  typename index_grid::grid_type::index_t lbin;
150  lbin[0u] = ib0;
151  highlightIndices.push_back(indexGrid.grid.atLocalBins(lbin));
152  // Register the bin naming
153  pGrid._bin_ids.push_back(std::string("- bin : [") + std::to_string(ib0) +
154  std::string("]"));
155  }
156  }
157  // 2D connections
158  if constexpr (index_grid::grid_type::DIM == 2u) {
159  for (unsigned int ib0 = 1u; ib0 <= axes[0u]->getNBins(); ++ib0) {
160  for (unsigned int ib1 = 1u; ib1 <= axes[1u]->getNBins(); ++ib1) {
161  typename index_grid::grid_type::index_t lbin;
162  lbin[0u] = ib0;
163  lbin[1u] = ib1;
164  highlightIndices.push_back(indexGrid.grid.atLocalBins(lbin));
165  // Register the bin naming
166  pGrid._bin_ids.push_back(std::string("- bin : [") +
167  std::to_string(ib0) + std::string(", ") +
168  std::to_string(ib1) + std::string("]"));
169  if (estimateR) {
170  pGrid._reference_r = constrain.medium(binR);
171  }
172  }
173  }
174  }
175  return std::tie(pSurfaces, pGrid, highlightIndices);
176 }
177 
191 template <typename surface_container, typename instance_type>
192 void convert(const GeometryContext& gctx, const surface_container& surfaces,
193  const Options& cOptions, ProtoIndexedSurfaceGrid& sgi,
195  [[maybe_unused]] const instance_type& refInstance) {
196  using GridType =
197  typename instance_type::template grid_type<std::vector<std::size_t>>;
198  // Defining a Delegate type
201  using SubDelegateType = Experimental::IndexedSurfacesImpl<GridType>;
202 
203  // Get the instance
204  const auto* instance = delegate.instance();
205  auto castedDelegate = dynamic_cast<const DelegateType*>(instance);
206  if (castedDelegate != nullptr) {
207  // Get the surface updator
208  auto indexedSurfaces = std::get<SubDelegateType>(castedDelegate->updators);
209  auto [pSurfaces, pGrid, pIndices] =
210  convertImpl(gctx, surfaces, indexedSurfaces, cOptions);
211  std::get<0u>(sgi) = pSurfaces;
212  std::get<1u>(sgi) = pGrid;
213  std::get<2u>(sgi) = pIndices;
214  }
215 }
216 
220 template <typename surface_container, typename tuple_type, std::size_t... I>
222  const surface_container& surfaces, const Options& cOptions,
225  const tuple_type& axesTuple, std::index_sequence<I...>) {
226  (convert(gctx, surfaces, cOptions, sgi, delegate, std::get<I>(axesTuple)),
227  ...);
228 }
229 
241 template <typename surface_container>
243  const GeometryContext& gctx, const surface_container& surfaces,
245  const Options& cOptions) {
246  // Prep work what is to be filled
247  std::vector<ProtoSurface> pSurfaces;
248  ProtoGrid pGrid;
249  std::vector<std::vector<std::size_t>> indices;
250  ProtoIndexedSurfaceGrid sgi = {pSurfaces, pGrid, indices};
251  // Convert if dynamic cast happens to work
253  gctx, surfaces, cOptions, sgi, delegate, Experimental::s_possibleAxes,
254  std::make_index_sequence<
255  std::tuple_size<decltype(Experimental::s_possibleAxes)>::value>());
256  // Return the newly filled ones
257  return sgi;
258 }
259 
260 } // namespace IndexedSurfacesConverter
261 
262 namespace View {
263 
270 static inline actsvg::svg::object xy(const ProtoIndexedSurfaceGrid& pIndexGrid,
271  const std::string& identification) {
272  auto [pSurfaces, pGrid, pIndices] = pIndexGrid;
273 
274  // Create the master object
275  actsvg::svg::object xyIndexedGrid;
276  xyIndexedGrid._id = identification;
277  xyIndexedGrid._tag = "g";
278 
279  // The surfaces
280  std::vector<actsvg::svg::object> sObs;
281  for (const auto& s : pSurfaces) {
282  if (pGrid._type == actsvg::proto::grid::e_z_phi) {
283  sObs.push_back(Acts::Svg::View::zrphi(s, s._name));
284  } else {
285  sObs.push_back(Acts::Svg::View::xy(s, s._name));
286  }
287  }
288 
289  // The grid
290  auto gOb =
291  actsvg::display::grid(identification + std::string("_grid"), pGrid);
292 
293  // The connectors
294  actsvg::connectors::connect_action(gOb._sub_objects, sObs, pIndices);
295 
296  // Add them all
297  xyIndexedGrid.add_objects(sObs);
298 
299  auto xmax = xyIndexedGrid._x_range[1u];
300  // The association info boxes
301  for (auto [ig, gTile] : enumerate(gOb._sub_objects)) {
302  // Target surface text
303  std::vector<std::string> binText;
304  binText.push_back("Source:");
305  binText.push_back(pGrid._bin_ids[ig]);
306  binText.push_back("Target:");
307  for (const auto& sis : pIndices[ig]) {
308  binText.push_back(std::string("- object: ") + std::to_string(sis));
309  }
310  // Make the connected text
311  std::string cTextId =
312  identification + std::string("_ct_") + std::to_string(ig);
313  auto cText = actsvg::draw::connected_text(
314  "bla", {static_cast<actsvg::scalar>(1.1 * xmax), 0}, binText,
315  actsvg::style::font{}, actsvg::style::transform{}, gTile);
316  xyIndexedGrid.add_object(cText);
317  }
318  xyIndexedGrid.add_object(gOb);
319  // Return the grid
320  return xyIndexedGrid;
321 }
322 
332 static inline actsvg::svg::object zphi(
333  const ProtoIndexedSurfaceGrid& pIndexGrid,
334  const std::string& identification) {
335  return xy(pIndexGrid, identification);
336 }
337 
338 } // namespace View
339 } // namespace Svg
340 } // namespace Acts