File indexing completed on 2025-09-15 08:15:41
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Detector/DetectorVolume.hpp"
0012 #include "Acts/Detector/DetectorVolumeBuilder.hpp"
0013 #include "Acts/Detector/LayerStructureBuilder.hpp"
0014 #include "Acts/Detector/PortalGenerators.hpp"
0015 #include "Acts/Detector/VolumeStructureBuilder.hpp"
0016 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0017 #include "Acts/Geometry/GeometryContext.hpp"
0018 #include "Acts/Navigation/InternalNavigation.hpp"
0019 #include "Acts/Navigation/NavigationStateUpdaters.hpp"
0020 #include "Acts/Plugins/ActSVG/DetectorVolumeSvgConverter.hpp"
0021 #include "Acts/Plugins/ActSVG/IndexedSurfacesSvgConverter.hpp"
0022 #include "Acts/Tests/CommonHelpers/CylindricalTrackingGeometry.hpp"
0023 #include "Acts/Utilities/Enumerate.hpp"
0024 #include "Acts/Utilities/Logger.hpp"
0025
0026 #include <fstream>
0027 #include <memory>
0028 #include <numbers>
0029 #include <vector>
0030
0031 namespace {
0032
0033
0034
0035 std::vector<std::shared_ptr<Acts::Surface>> unpackSurfaces(
0036 const std::vector<Acts::Surface*>& surfaces) {
0037 std::vector<std::shared_ptr<Acts::Surface>> uSurfaces;
0038 uSurfaces.reserve(surfaces.size());
0039 for (auto* s : surfaces) {
0040 uSurfaces.push_back(s->getSharedPtr());
0041 }
0042 return uSurfaces;
0043 }
0044
0045 }
0046
0047 Acts::GeometryContext tContext;
0048
0049 auto cGeometry = Acts::Test::CylindricalTrackingGeometry(tContext);
0050 auto nominal = Acts::Transform3::Identity();
0051
0052 BOOST_AUTO_TEST_SUITE(ActSvg)
0053
0054 BOOST_AUTO_TEST_CASE(TubeCylindricalDetectorVolume) {
0055 auto portalGenerator = Acts::Experimental::defaultPortalGenerator();
0056
0057
0058 double rInner = 10.;
0059 double rOuter = 100.;
0060 double zHalfL = 300.;
0061
0062 Acts::Svg::Style portalStyle;
0063 portalStyle.fillColor = {255, 255, 255};
0064 portalStyle.fillOpacity = 0.;
0065
0066
0067 auto tubeCylinderBounds =
0068 std::make_unique<Acts::CylinderVolumeBounds>(rInner, rOuter, zHalfL);
0069
0070 auto tubeCylinderVolume =
0071 Acts::Experimental::DetectorVolumeFactory::construct(
0072 portalGenerator, tContext, "TubeCylinderVolume", nominal,
0073 std::move(tubeCylinderBounds), Acts::Experimental::tryAllPortals());
0074
0075 Acts::Svg::DetectorVolumeConverter::Options volumeOptions;
0076 volumeOptions.portalOptions.volumeIndices[tubeCylinderVolume.get()] = 0u;
0077
0078 auto [pVolume, pGrid] = Acts::Svg::DetectorVolumeConverter::convert(
0079 tContext, *tubeCylinderVolume, volumeOptions);
0080 pVolume._name = tubeCylinderVolume->name();
0081
0082
0083 actsvg::style::color red({{255, 0, 0}});
0084 red._opacity = 0.1;
0085 std::vector<actsvg::style::color> colors = {red};
0086 pVolume.colorize(colors);
0087
0088
0089 auto pv = Acts::Svg::View::zr(pVolume, pVolume._name);
0090 Acts::Svg::toFile({pv}, pVolume._name + "_zr.svg");
0091 }
0092
0093 BOOST_AUTO_TEST_CASE(TubeSectorCylindricalDetectorVolume) {
0094 auto portalGenerator = Acts::Experimental::defaultPortalGenerator();
0095
0096
0097 double rInner = 10.;
0098 double rOuter = 100.;
0099 double zHalfL = 300.;
0100 double phiSector = std::numbers::pi / 4.;
0101 std::vector<double> avgPhi = {0., 0.75};
0102 std::vector<std::string> avgPhiTag = {"zero", "nonzero"};
0103
0104 Acts::Svg::Style portalStyle;
0105 portalStyle.fillColor = {255, 255, 255};
0106 portalStyle.fillOpacity = 0.;
0107
0108 std::vector<actsvg::svg::object> volumesXY;
0109 for (auto [iphi, aphi] : Acts::enumerate(avgPhi)) {
0110
0111 auto sectorCylinderBounds = std::make_unique<Acts::CylinderVolumeBounds>(
0112 rInner, rOuter, zHalfL, phiSector, aphi);
0113
0114 auto sectorCylinderVolume =
0115 Acts::Experimental::DetectorVolumeFactory::construct(
0116 portalGenerator, tContext, "SectoralCylinderVolume", nominal,
0117 std::move(sectorCylinderBounds),
0118 Acts::Experimental::tryAllPortals());
0119
0120 Acts::Svg::DetectorVolumeConverter::Options volumeOptions;
0121 volumeOptions.portalOptions.volumeIndices[sectorCylinderVolume.get()] = 0u;
0122
0123 auto [pVolume, pGrid] = Acts::Svg::DetectorVolumeConverter::convert(
0124 tContext, *sectorCylinderVolume, volumeOptions);
0125
0126
0127 actsvg::style::color blue({{0, 0, 255}});
0128 blue._opacity = 0.1;
0129 std::vector<actsvg::style::color> colors = {blue};
0130 pVolume.colorize(colors);
0131
0132 volumesXY.push_back(Acts::Svg::View::xy(pVolume, pVolume._name));
0133 }
0134
0135 Acts::Svg::toFile(volumesXY, "SectorVolumes_xy.svg");
0136 }
0137
0138 BOOST_AUTO_TEST_CASE(EndcapVolumeWithSurfaces) {
0139 Acts::Test::CylindricalTrackingGeometry::DetectorStore dStore;
0140
0141 auto rSurfaces = cGeometry.surfacesRing(dStore, 6.4, 12.4, 36., 0.125, 0.,
0142 55., -800, 2., 22u);
0143
0144 auto endcapSurfaces = std::make_shared<
0145 Acts::Experimental::LayerStructureBuilder::SurfacesHolder>(
0146 unpackSurfaces(rSurfaces));
0147
0148 Acts::Experimental::LayerStructureBuilder::Config lsConfig;
0149 lsConfig.auxiliary = "*** Endcap with 22 surfaces ***";
0150 lsConfig.surfacesProvider = endcapSurfaces;
0151 lsConfig.binnings = {
0152 {Acts::DirectedProtoAxis(Acts::AxisDirection::AxisPhi,
0153 Acts::AxisBoundaryType::Closed,
0154 -std::numbers::pi, std::numbers::pi, 22u),
0155 1u}};
0156
0157 auto layerBuilder =
0158 std::make_shared<Acts::Experimental::LayerStructureBuilder>(
0159 lsConfig, Acts::getDefaultLogger("EndcapInteralsBuilder",
0160 Acts::Logging::VERBOSE));
0161
0162 Acts::Experimental::VolumeStructureBuilder::Config shapeConfig;
0163 shapeConfig.boundValues = {10, 100, 10., std::numbers::pi, 0.};
0164 shapeConfig.transform =
0165 Acts::Transform3{Acts::Transform3::Identity()}.pretranslate(
0166 Acts::Vector3(0., 0., -800.));
0167 shapeConfig.boundsType = Acts::VolumeBounds::BoundsType::eCylinder;
0168
0169 auto shapeBuilder =
0170 std::make_shared<Acts::Experimental::VolumeStructureBuilder>(
0171 shapeConfig,
0172 Acts::getDefaultLogger("EndcapShapeBuilder", Acts::Logging::VERBOSE));
0173
0174 Acts::Experimental::DetectorVolumeBuilder::Config dvCfg;
0175 dvCfg.auxiliary = "*** Test 1 - Cylinder with internal Surface ***";
0176 dvCfg.name = "CylinderWithSurface";
0177 dvCfg.externalsBuilder = shapeBuilder;
0178 dvCfg.internalsBuilder = layerBuilder;
0179
0180 auto dvBuilder = std::make_shared<Acts::Experimental::DetectorVolumeBuilder>(
0181 dvCfg, Acts::getDefaultLogger("EndcapBuilder", Acts::Logging::VERBOSE));
0182
0183 auto [volumes, portals, roots] = dvBuilder->construct(tContext);
0184
0185 auto volume = volumes.front();
0186 Acts::Svg::DetectorVolumeConverter::Options volumeOptions;
0187 volumeOptions.portalOptions.volumeIndices[volume.get()] = 0u;
0188
0189 Acts::Svg::SurfaceConverter::Options surfaceOptions;
0190 surfaceOptions.style.fillColor = {50, 121, 168};
0191 surfaceOptions.style.fillOpacity = 0.5;
0192 volumeOptions.surfaceOptions = surfaceOptions;
0193
0194 auto [pVolume, pGrid] = Acts::Svg::DetectorVolumeConverter::convert(
0195 tContext, *volume, volumeOptions);
0196
0197
0198 auto volumeXY = Acts::Svg::View::xy(pVolume, pVolume._name);
0199 Acts::Svg::toFile({volumeXY}, "EndcapVolume_xy.svg");
0200
0201
0202 auto volumeZR = Acts::Svg::View::zr(pVolume, pVolume._name);
0203 Acts::Svg::toFile({volumeZR}, "EndcapVolume_zr.svg");
0204
0205
0206 auto gridXY = Acts::Svg::View::xy(pGrid, "EndcapVolume_grid_xy");
0207 Acts::Svg::toFile({gridXY}, "EndcapVolume_grid_xy.svg");
0208 }
0209
0210 BOOST_AUTO_TEST_CASE(BarrelVolumeWithSurfaces) {
0211 Acts::Test::CylindricalTrackingGeometry::DetectorStore dStore;
0212 auto cSurfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.145, 72,
0213 3., 2., {32u, 14u});
0214
0215 auto barrelSurfaces = std::make_shared<
0216 Acts::Experimental::LayerStructureBuilder::SurfacesHolder>(
0217 unpackSurfaces(cSurfaces));
0218
0219
0220 Acts::Experimental::LayerStructureBuilder::Config lsConfig;
0221 lsConfig.auxiliary = "*** Barrel with 448 surfaces ***";
0222 lsConfig.surfacesProvider = barrelSurfaces;
0223 lsConfig.binnings = {
0224 {Acts::DirectedProtoAxis{Acts::AxisDirection::AxisZ,
0225 Acts::AxisBoundaryType::Bound, -480., 480., 14u},
0226 1u},
0227 {Acts::DirectedProtoAxis(Acts::AxisDirection::AxisPhi,
0228 Acts::AxisBoundaryType::Closed,
0229 -std::numbers::pi, std::numbers::pi, 32u),
0230 1u}};
0231
0232 auto barrelBuilder =
0233 std::make_shared<Acts::Experimental::LayerStructureBuilder>(
0234 lsConfig, Acts::getDefaultLogger("BarrelInternalsBuilder",
0235 Acts::Logging::VERBOSE));
0236
0237 Acts::Experimental::VolumeStructureBuilder::Config shapeConfig;
0238 shapeConfig.boundValues = {60., 80., 800., std::numbers::pi, 0.};
0239 shapeConfig.boundsType = Acts::VolumeBounds::BoundsType::eCylinder;
0240
0241 auto shapeBuilder =
0242 std::make_shared<Acts::Experimental::VolumeStructureBuilder>(
0243 shapeConfig,
0244 Acts::getDefaultLogger("BarrelShapeBuilder", Acts::Logging::VERBOSE));
0245
0246 Acts::Experimental::DetectorVolumeBuilder::Config dvCfg;
0247 dvCfg.auxiliary = "*** Test 1 - Cylinder with internal Surface ***";
0248 dvCfg.name = "CylinderWithSurface";
0249 dvCfg.externalsBuilder = shapeBuilder;
0250 dvCfg.internalsBuilder = barrelBuilder;
0251
0252 auto dvBuilder = std::make_shared<Acts::Experimental::DetectorVolumeBuilder>(
0253 dvCfg, Acts::getDefaultLogger("EndcapBuilder", Acts::Logging::VERBOSE));
0254
0255 auto [volumes, portals, roots] = dvBuilder->construct(tContext);
0256
0257 auto volume = volumes.front();
0258 Acts::Svg::DetectorVolumeConverter::Options volumeOptions;
0259 volumeOptions.portalOptions.volumeIndices[volume.get()] = 0u;
0260
0261 Acts::Svg::SurfaceConverter::Options surfaceOptions;
0262 surfaceOptions.style.fillColor = {50, 121, 168};
0263 surfaceOptions.style.fillOpacity = 0.5;
0264 volumeOptions.surfaceOptions = surfaceOptions;
0265
0266 auto [pVolume, pGrid] = Acts::Svg::DetectorVolumeConverter::convert(
0267 tContext, *volume, volumeOptions);
0268
0269
0270 auto volumeXY = Acts::Svg::View::xy(pVolume, pVolume._name);
0271 Acts::Svg::toFile({volumeXY}, "BarrelVolume_xy.svg");
0272
0273
0274 auto volumeZR = Acts::Svg::View::zr(pVolume, pVolume._name);
0275 Acts::Svg::toFile({volumeZR}, "BarrelVolume_zr.svg");
0276
0277
0278 auto gridZPhi = Acts::Svg::View::zphi(pGrid, "BarrelVolume_grid_zphi");
0279 Acts::Svg::toFile({gridZPhi}, "BarrelVolume_grid_zphi.svg");
0280 }
0281
0282 BOOST_AUTO_TEST_SUITE_END()