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