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