File indexing completed on 2025-08-06 08:11:43
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Detector/DetectorVolume.hpp"
0013 #include "Acts/Detector/DetectorVolumeBuilder.hpp"
0014 #include "Acts/Detector/LayerStructureBuilder.hpp"
0015 #include "Acts/Detector/PortalGenerators.hpp"
0016 #include "Acts/Detector/VolumeStructureBuilder.hpp"
0017 #include "Acts/Geometry/ConeVolumeBounds.hpp"
0018 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0019 #include "Acts/Geometry/GeometryContext.hpp"
0020 #include "Acts/Navigation/DetectorVolumeFinders.hpp"
0021 #include "Acts/Navigation/SurfaceCandidatesUpdaters.hpp"
0022 #include "Acts/Plugins/Json/DetectorVolumeJsonConverter.hpp"
0023 #include "Acts/Surfaces/CylinderBounds.hpp"
0024 #include "Acts/Surfaces/CylinderSurface.hpp"
0025 #include "Acts/Tests/CommonHelpers/CylindricalTrackingGeometry.hpp"
0026 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0027
0028 #include <fstream>
0029 #include <memory>
0030 #include <vector>
0031
0032 #include <nlohmann/json.hpp>
0033
0034 namespace {
0035
0036
0037
0038 std::vector<std::shared_ptr<Acts::Surface>> unpackSurfaces(
0039 const std::vector<const Acts::Surface*>& surfaces) {
0040 std::vector<std::shared_ptr<Acts::Surface>> uSurfaces;
0041 uSurfaces.reserve(surfaces.size());
0042 for (const auto s : surfaces) {
0043 auto* ncs = const_cast<Acts::Surface*>(s);
0044 uSurfaces.push_back(ncs->getSharedPtr());
0045 }
0046 return uSurfaces;
0047 }
0048
0049 }
0050
0051 Acts::GeometryContext tContext;
0052 auto cGeometry = Acts::Test::CylindricalTrackingGeometry(tContext);
0053
0054 auto portalGenerator = Acts::Experimental::defaultPortalGenerator();
0055
0056 BOOST_AUTO_TEST_SUITE(DetectorVolumeJsonConverter)
0057
0058 BOOST_AUTO_TEST_CASE(SingleEmptyVolume) {
0059
0060 Acts::Transform3 nominal = Acts::Transform3::Identity();
0061 auto bounds = std::make_unique<Acts::CylinderVolumeBounds>(0., 50., 100.);
0062
0063 auto volume = Acts::Experimental::DetectorVolumeFactory::construct(
0064 portalGenerator, tContext, "EmptyVolume", nominal, std::move(bounds),
0065 Acts::Experimental::tryAllPortals());
0066
0067 std::ofstream out;
0068
0069 auto jVolume = Acts::DetectorVolumeJsonConverter::toJson(tContext, *volume,
0070 {volume.get()});
0071
0072 out.open("single-empty-volume.json");
0073 out << jVolume.dump(4);
0074 out.close();
0075
0076 auto in = std::ifstream("single-empty-volume.json",
0077 std::ifstream::in | std::ifstream::binary);
0078
0079 BOOST_CHECK(in.good());
0080 nlohmann::json jVolumeIn;
0081 in >> jVolumeIn;
0082 in.close();
0083
0084 auto volumeIn =
0085 Acts::DetectorVolumeJsonConverter::fromJson(tContext, jVolumeIn);
0086
0087 BOOST_CHECK_EQUAL(volumeIn->name(), volume->name());
0088 BOOST_CHECK(
0089 volumeIn->transform(tContext).isApprox(volume->transform(tContext)));
0090 BOOST_CHECK_EQUAL(volumeIn->surfaces().size(), volume->surfaces().size());
0091 BOOST_CHECK_EQUAL(volumeIn->volumes().size(), volume->volumes().size());
0092
0093
0094 Acts::DetectorVolumeJsonConverter::Options detrayOptions;
0095 detrayOptions.transformOptions.writeIdentity = true;
0096 detrayOptions.transformOptions.transpose = true;
0097 detrayOptions.surfaceOptions.transformOptions =
0098 detrayOptions.transformOptions;
0099 detrayOptions.portalOptions.surfaceOptions = detrayOptions.surfaceOptions;
0100
0101 auto jVolumeDetray = Acts::DetectorVolumeJsonConverter::toJsonDetray(
0102 tContext, *volume, {volume.get()}, detrayOptions);
0103
0104 out.open("single-empty-volume-detray.json");
0105 out << jVolumeDetray.dump(4);
0106 out.close();
0107 }
0108
0109 BOOST_AUTO_TEST_CASE(SingleSurfaceVolume) {
0110
0111 Acts::Transform3 nominal = Acts::Transform3::Identity();
0112 auto volumeBounds =
0113 std::make_unique<Acts::CylinderVolumeBounds>(0., 50., 100.);
0114 auto surfaceBounds = std::make_unique<Acts::CylinderBounds>(25., 100.);
0115
0116 auto cylinderSurface = Acts::Surface::makeShared<Acts::CylinderSurface>(
0117 nominal, std::move(surfaceBounds));
0118
0119 auto volume = Acts::Experimental::DetectorVolumeFactory::construct(
0120 portalGenerator, tContext, "CylinderVolume", nominal,
0121 std::move(volumeBounds), {cylinderSurface}, {},
0122 Acts::Experimental::tryRootVolumes(),
0123 Acts::Experimental::tryAllPortalsAndSurfaces());
0124
0125 std::ofstream out;
0126
0127 auto jVolume = Acts::DetectorVolumeJsonConverter::toJson(tContext, *volume,
0128 {volume.get()});
0129
0130 out.open("single-surface-volume.json");
0131 out << jVolume.dump(4);
0132 out.close();
0133
0134 auto in = std::ifstream("single-surface-volume.json",
0135 std::ifstream::in | std::ifstream::binary);
0136
0137 BOOST_CHECK(in.good());
0138 nlohmann::json jVolumeIn;
0139 in >> jVolumeIn;
0140 in.close();
0141
0142 auto volumeIn =
0143 Acts::DetectorVolumeJsonConverter::fromJson(tContext, jVolumeIn);
0144
0145 BOOST_CHECK_EQUAL(volumeIn->name(), volume->name());
0146 BOOST_CHECK(
0147 volumeIn->transform(tContext).isApprox(volume->transform(tContext)));
0148 BOOST_CHECK_EQUAL(volumeIn->surfaces().size(), volume->surfaces().size());
0149 BOOST_CHECK_EQUAL(volumeIn->volumes().size(), volume->volumes().size());
0150 }
0151
0152 BOOST_AUTO_TEST_CASE(EndcapVolumeWithSurfaces) {
0153 Acts::Test::CylindricalTrackingGeometry::DetectorStore dStore;
0154
0155 auto rSurfaces = cGeometry.surfacesRing(dStore, 6.4, 12.4, 36., 0.125, 0.,
0156 55., -800, 2., 22u);
0157
0158 auto endcapSurfaces = std::make_shared<
0159 Acts::Experimental::LayerStructureBuilder::SurfacesHolder>(
0160 unpackSurfaces(rSurfaces));
0161
0162 Acts::Experimental::LayerStructureBuilder::Config lsConfig;
0163 lsConfig.auxiliary = "*** Endcap with 22 surfaces ***";
0164 lsConfig.surfacesProvider = endcapSurfaces;
0165 lsConfig.binnings = {Acts::Experimental::ProtoBinning(
0166 Acts::binPhi, Acts::detail::AxisBoundaryType::Closed, -M_PI, M_PI, 22u,
0167 1u)};
0168
0169 auto layerBuilder =
0170 std::make_shared<Acts::Experimental::LayerStructureBuilder>(
0171 lsConfig, Acts::getDefaultLogger("EndcapInteralsBuilder",
0172 Acts::Logging::VERBOSE));
0173
0174 Acts::Experimental::VolumeStructureBuilder::Config shapeConfig;
0175 shapeConfig.boundValues = {10, 100, 10., M_PI, 0.};
0176 shapeConfig.transform = Acts::Transform3(Acts::Transform3::Identity())
0177 .pretranslate(Acts::Vector3(0., 0., -800.));
0178 shapeConfig.boundsType = Acts::VolumeBounds::BoundsType::eCylinder;
0179
0180 auto shapeBuilder =
0181 std::make_shared<Acts::Experimental::VolumeStructureBuilder>(
0182 shapeConfig,
0183 Acts::getDefaultLogger("EndcapShapeBuilder", Acts::Logging::VERBOSE));
0184
0185 Acts::Experimental::DetectorVolumeBuilder::Config dvCfg;
0186 dvCfg.auxiliary = "*** Test 1 - Cylinder with internal Surface ***";
0187 dvCfg.name = "CylinderWithSurface";
0188 dvCfg.externalsBuilder = shapeBuilder;
0189 dvCfg.internalsBuilder = layerBuilder;
0190
0191 auto dvBuilder = std::make_shared<Acts::Experimental::DetectorVolumeBuilder>(
0192 dvCfg, Acts::getDefaultLogger("EndcapBuilder", Acts::Logging::VERBOSE));
0193
0194 auto [volumes, portals, roots] = dvBuilder->construct(tContext);
0195 auto volume = volumes.front();
0196
0197 auto jVolume = Acts::DetectorVolumeJsonConverter::toJson(tContext, *volume,
0198 {volume.get()});
0199
0200 std::ofstream out;
0201 out.open("endcap-volume-with-surfaces.json");
0202 out << jVolume.dump(4);
0203 out.close();
0204
0205 auto in = std::ifstream("endcap-volume-with-surfaces.json",
0206 std::ifstream::in | std::ifstream::binary);
0207
0208 BOOST_CHECK(in.good());
0209 nlohmann::json jVolumeIn;
0210 in >> jVolumeIn;
0211 in.close();
0212
0213 auto volumeIn =
0214 Acts::DetectorVolumeJsonConverter::fromJson(tContext, jVolumeIn);
0215
0216 BOOST_CHECK_EQUAL(volumeIn->name(), volume->name());
0217 BOOST_CHECK(
0218 volumeIn->transform(tContext).isApprox(volume->transform(tContext)));
0219 BOOST_CHECK_EQUAL(volumeIn->surfaces().size(), volume->surfaces().size());
0220 BOOST_CHECK_EQUAL(volumeIn->volumes().size(), volume->volumes().size());
0221
0222
0223 jVolume = Acts::DetectorVolumeJsonConverter::toJson(tContext, *volumeIn,
0224 {volumeIn.get()});
0225 out.open("endcap-volume-with-surfaces-closure.json");
0226 out << jVolume.dump(4);
0227 out.close();
0228 }
0229
0230 BOOST_AUTO_TEST_CASE(BarrelVolumeWithSurfaces) {
0231 Acts::Test::CylindricalTrackingGeometry::DetectorStore dStore;
0232 auto cSurfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.145, 72,
0233 3., 2., {32u, 14u});
0234
0235 auto barrelSurfaces = std::make_shared<
0236 Acts::Experimental::LayerStructureBuilder::SurfacesHolder>(
0237 unpackSurfaces(cSurfaces));
0238
0239
0240 Acts::Experimental::LayerStructureBuilder::Config lsConfig;
0241 lsConfig.auxiliary = "*** Barrel with 448 surfaces ***";
0242 lsConfig.surfacesProvider = barrelSurfaces;
0243 lsConfig.binnings = {Acts::Experimental::ProtoBinning{
0244 Acts::binZ, Acts::detail::AxisBoundaryType::Bound,
0245 -480., 480., 14u, 1u},
0246 Acts::Experimental::ProtoBinning(
0247 Acts::binPhi, Acts::detail::AxisBoundaryType::Closed,
0248 -M_PI, M_PI, 32u, 1u)};
0249
0250 auto barrelBuilder =
0251 std::make_shared<Acts::Experimental::LayerStructureBuilder>(
0252 lsConfig, Acts::getDefaultLogger("BarrelInternalsBuilder",
0253 Acts::Logging::VERBOSE));
0254
0255 Acts::Experimental::VolumeStructureBuilder::Config shapeConfig;
0256 shapeConfig.boundValues = {60., 80., 800., M_PI, 0.};
0257 shapeConfig.boundsType = Acts::VolumeBounds::BoundsType::eCylinder;
0258
0259 auto shapeBuilder =
0260 std::make_shared<Acts::Experimental::VolumeStructureBuilder>(
0261 shapeConfig,
0262 Acts::getDefaultLogger("BarrelShapeBuilder", Acts::Logging::VERBOSE));
0263
0264 Acts::Experimental::DetectorVolumeBuilder::Config dvCfg;
0265 dvCfg.auxiliary = "*** Test 1 - Cylinder with internal Surface ***";
0266 dvCfg.name = "BarrelWithSurfaces";
0267 dvCfg.externalsBuilder = shapeBuilder;
0268 dvCfg.internalsBuilder = barrelBuilder;
0269
0270 auto dvBuilder = std::make_shared<Acts::Experimental::DetectorVolumeBuilder>(
0271 dvCfg, Acts::getDefaultLogger("EndcapBuilder", Acts::Logging::VERBOSE));
0272
0273 auto [volumes, portals, roots] = dvBuilder->construct(tContext);
0274
0275 auto volume = volumes.front();
0276
0277 auto jVolume = Acts::DetectorVolumeJsonConverter::toJson(tContext, *volume,
0278 {volume.get()});
0279
0280 std::ofstream out;
0281 out.open("barrel-volume-with-surfaces.json");
0282 out << jVolume.dump(4);
0283 out.close();
0284
0285 auto in = std::ifstream("barrel-volume-with-surfaces.json",
0286 std::ifstream::in | std::ifstream::binary);
0287
0288 BOOST_CHECK(in.good());
0289 nlohmann::json jVolumeIn;
0290 in >> jVolumeIn;
0291 in.close();
0292
0293 auto volumeIn =
0294 Acts::DetectorVolumeJsonConverter::fromJson(tContext, jVolumeIn);
0295
0296 BOOST_CHECK_EQUAL(volumeIn->name(), volume->name());
0297 BOOST_CHECK(
0298 volumeIn->transform(tContext).isApprox(volume->transform(tContext)));
0299 BOOST_CHECK_EQUAL(volumeIn->surfaces().size(), volume->surfaces().size());
0300 BOOST_CHECK_EQUAL(volumeIn->volumes().size(), volume->volumes().size());
0301
0302
0303 jVolume = Acts::DetectorVolumeJsonConverter::toJson(tContext, *volumeIn,
0304 {volumeIn.get()});
0305 out.open("barrel-volume-with-surfaces-closure.json");
0306 out << jVolume.dump(4);
0307 out.close();
0308 }
0309
0310 BOOST_AUTO_TEST_SUITE_END()