Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DetectorVolumeSvgConverterTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file DetectorVolumeSvgConverterTests.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2022 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 #include <boost/test/unit_test.hpp>
10 
25 
26 #include <fstream>
27 #include <memory>
28 #include <vector>
29 
30 namespace {
34 std::vector<std::shared_ptr<Acts::Surface>> unpackSurfaces(
35  const std::vector<const Acts::Surface*>& surfaces) {
36  std::vector<std::shared_ptr<Acts::Surface>> uSurfaces;
37  uSurfaces.reserve(surfaces.size());
38  for (const auto& s : surfaces) {
39  auto* ncs = const_cast<Acts::Surface*>(s);
40  uSurfaces.push_back(ncs->getSharedPtr());
41  }
42  return uSurfaces;
43 }
44 
45 } // namespace
46 
48 
50 auto nominal = Acts::Transform3::Identity();
51 
52 BOOST_AUTO_TEST_SUITE(ActSvg)
53 
54 BOOST_AUTO_TEST_CASE(TubeCylindricalDetectorVolume) {
56 
57  // The volume definitions
58  Acts::ActsScalar rInner = 10.;
59  Acts::ActsScalar rOuter = 100.;
60  Acts::ActsScalar zHalfL = 300.;
61 
62  Acts::Svg::Style portalStyle;
63  portalStyle.fillColor = {255, 255, 255};
64  portalStyle.fillOpacity = 0.;
65 
66  // A tube cylinder
67  auto tubeCylinderBounds =
68  std::make_unique<Acts::CylinderVolumeBounds>(rInner, rOuter, zHalfL);
69 
70  auto tubeCylinderVolume =
72  portalGenerator, tContext, "TubeCylinderVolume", nominal,
73  std::move(tubeCylinderBounds), Acts::Experimental::tryAllPortals());
74 
76  volumeOptions.portalOptions.volumeIndices[tubeCylinderVolume.get()] = 0u;
77 
78  auto [pVolume, pGrid] = Acts::Svg::DetectorVolumeConverter::convert(
79  tContext, *tubeCylinderVolume, volumeOptions);
80  pVolume._name = tubeCylinderVolume->name();
81 
82  // Colorize in red
83  actsvg::style::color red({{255, 0, 0}});
84  red._opacity = 0.1;
85  std::vector<actsvg::style::color> colors = {red};
86  pVolume.colorize(colors);
87 
88  // As sheet
89  auto pv = Acts::Svg::View::zr(pVolume, pVolume._name);
90  Acts::Svg::toFile({pv}, pVolume._name + "_zr.svg");
91 }
92 
93 BOOST_AUTO_TEST_CASE(TubeSectorCylindricalDetectorVolume) {
95 
96  // The volume definitions
97  Acts::ActsScalar rInner = 10.;
98  Acts::ActsScalar rOuter = 100.;
99  Acts::ActsScalar zHalfL = 300.;
100  Acts::ActsScalar phiSector = 0.25 * M_PI;
101  std::vector<Acts::ActsScalar> avgPhi = {0., 0.75};
102  std::vector<std::string> avgPhiTag = {"zero", "nonzero"};
103 
104  Acts::Svg::Style portalStyle;
105  portalStyle.fillColor = {255, 255, 255};
106  portalStyle.fillOpacity = 0.;
107 
108  std::vector<actsvg::svg::object> volumesXY;
109  for (auto [iphi, aphi] : Acts::enumerate(avgPhi)) {
110  // A tube cylinder
111  auto sectorCylinderBounds = std::make_unique<Acts::CylinderVolumeBounds>(
112  rInner, rOuter, zHalfL, phiSector, aphi);
113 
114  auto sectorCylinderVolume =
116  portalGenerator, tContext, "SectoralCylinderVolume", nominal,
117  std::move(sectorCylinderBounds),
119 
121  volumeOptions.portalOptions.volumeIndices[sectorCylinderVolume.get()] = 0u;
122 
123  auto [pVolume, pGrid] = Acts::Svg::DetectorVolumeConverter::convert(
124  tContext, *sectorCylinderVolume, volumeOptions);
125 
126  // Colorize in blue
127  actsvg::style::color blue({{0, 0, 255}});
128  blue._opacity = 0.1;
129  std::vector<actsvg::style::color> colors = {blue};
130  pVolume.colorize(colors);
131 
132  volumesXY.push_back(Acts::Svg::View::xy(pVolume, pVolume._name));
133  }
134 
135  Acts::Svg::toFile(volumesXY, "SectorVolumes_xy.svg");
136 }
137 
138 BOOST_AUTO_TEST_CASE(EndcapVolumeWithSurfaces) {
140 
141  auto rSurfaces = cGeometry.surfacesRing(dStore, 6.4, 12.4, 36., 0.125, 0.,
142  55., -800, 2., 22u);
143 
144  auto endcapSurfaces = std::make_shared<
146  unpackSurfaces(rSurfaces));
147  // Configure the layer structure builder
149  lsConfig.auxiliary = "*** Endcap with 22 surfaces ***";
150  lsConfig.surfacesProvider = endcapSurfaces;
151  lsConfig.binnings = {Acts::Experimental::ProtoBinning(
152  Acts::binPhi, Acts::detail::AxisBoundaryType::Closed, -M_PI, M_PI, 22u,
153  1u)};
154 
155  auto layerBuilder =
156  std::make_shared<Acts::Experimental::LayerStructureBuilder>(
157  lsConfig, Acts::getDefaultLogger("EndcapInteralsBuilder",
159 
161  shapeConfig.boundValues = {10, 100, 10., M_PI, 0.};
162  shapeConfig.transform = Acts::Transform3(Acts::Transform3::Identity())
163  .pretranslate(Acts::Vector3(0., 0., -800.));
164  shapeConfig.boundsType = Acts::VolumeBounds::BoundsType::eCylinder;
165 
166  auto shapeBuilder =
167  std::make_shared<Acts::Experimental::VolumeStructureBuilder>(
168  shapeConfig,
169  Acts::getDefaultLogger("EndcapShapeBuilder", Acts::Logging::VERBOSE));
170 
172  dvCfg.auxiliary = "*** Test 1 - Cylinder with internal Surface ***";
173  dvCfg.name = "CylinderWithSurface";
174  dvCfg.externalsBuilder = shapeBuilder;
175  dvCfg.internalsBuilder = layerBuilder;
176 
177  auto dvBuilder = std::make_shared<Acts::Experimental::DetectorVolumeBuilder>(
178  dvCfg, Acts::getDefaultLogger("EndcapBuilder", Acts::Logging::VERBOSE));
179 
180  auto [volumes, portals, roots] = dvBuilder->construct(tContext);
181 
182  auto volume = volumes.front();
184  volumeOptions.portalOptions.volumeIndices[volume.get()] = 0u;
185 
187  surfaceOptions.style.fillColor = {50, 121, 168};
188  surfaceOptions.style.fillOpacity = 0.5;
189  volumeOptions.surfaceOptions = surfaceOptions;
190 
191  auto [pVolume, pGrid] = Acts::Svg::DetectorVolumeConverter::convert(
192  tContext, *volume, volumeOptions);
193 
194  // x-y view
195  auto volumeXY = Acts::Svg::View::xy(pVolume, pVolume._name);
196  Acts::Svg::toFile({volumeXY}, "EndcapVolume_xy.svg");
197 
198  // z-r view
199  auto volumeZR = Acts::Svg::View::zr(pVolume, pVolume._name);
200  Acts::Svg::toFile({volumeZR}, "EndcapVolume_zr.svg");
201 
202  // The grid surfaces
203  auto gridXY = Acts::Svg::View::xy(pGrid, "EndcapVolume_grid_xy");
204  Acts::Svg::toFile({gridXY}, "EndcapVolume_grid_xy.svg");
205 }
206 
207 BOOST_AUTO_TEST_CASE(BarrelVolumeWithSurfaces) {
209  auto cSurfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.145, 72,
210  3., 2., {32u, 14u});
211 
212  auto barrelSurfaces = std::make_shared<
214  unpackSurfaces(cSurfaces));
215 
216  // Configure the layer structure builder
218  lsConfig.auxiliary = "*** Barrel with 448 surfaces ***";
219  lsConfig.surfacesProvider = barrelSurfaces;
220  lsConfig.binnings = {Acts::Experimental::ProtoBinning{
221  Acts::binZ, Acts::detail::AxisBoundaryType::Bound,
222  -480., 480., 14u, 1u},
224  Acts::binPhi, Acts::detail::AxisBoundaryType::Closed,
225  -M_PI, M_PI, 32u, 1u)};
226 
227  auto barrelBuilder =
228  std::make_shared<Acts::Experimental::LayerStructureBuilder>(
229  lsConfig, Acts::getDefaultLogger("BarrelInternalsBuilder",
231 
233  shapeConfig.boundValues = {60., 80., 800., M_PI, 0.};
234  shapeConfig.boundsType = Acts::VolumeBounds::BoundsType::eCylinder;
235 
236  auto shapeBuilder =
237  std::make_shared<Acts::Experimental::VolumeStructureBuilder>(
238  shapeConfig,
239  Acts::getDefaultLogger("BarrelShapeBuilder", Acts::Logging::VERBOSE));
240 
242  dvCfg.auxiliary = "*** Test 1 - Cylinder with internal Surface ***";
243  dvCfg.name = "CylinderWithSurface";
244  dvCfg.externalsBuilder = shapeBuilder;
245  dvCfg.internalsBuilder = barrelBuilder;
246 
247  auto dvBuilder = std::make_shared<Acts::Experimental::DetectorVolumeBuilder>(
248  dvCfg, Acts::getDefaultLogger("EndcapBuilder", Acts::Logging::VERBOSE));
249 
250  auto [volumes, portals, roots] = dvBuilder->construct(tContext);
251 
252  auto volume = volumes.front();
254  volumeOptions.portalOptions.volumeIndices[volume.get()] = 0u;
255 
257  surfaceOptions.style.fillColor = {50, 121, 168};
258  surfaceOptions.style.fillOpacity = 0.5;
259  volumeOptions.surfaceOptions = surfaceOptions;
260 
261  auto [pVolume, pGrid] = Acts::Svg::DetectorVolumeConverter::convert(
262  tContext, *volume, volumeOptions);
263 
264  // x-y view
265  auto volumeXY = Acts::Svg::View::xy(pVolume, pVolume._name);
266  Acts::Svg::toFile({volumeXY}, "BarrelVolume_xy.svg");
267 
268  // z-r view
269  auto volumeZR = Acts::Svg::View::zr(pVolume, pVolume._name);
270  Acts::Svg::toFile({volumeZR}, "BarrelVolume_zr.svg");
271 
272  // The grid surfaces
273  auto gridZPhi = Acts::Svg::View::zphi(pGrid, "BarrelVolume_grid_zphi");
274  Acts::Svg::toFile({gridZPhi}, "BarrelVolume_grid_zphi.svg");
275 }
276 
277 BOOST_AUTO_TEST_SUITE_END()