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/CylindricalContainerBuilder.hpp"
0013 #include "Acts/Detector/Detector.hpp"
0014 #include "Acts/Detector/DetectorBuilder.hpp"
0015 #include "Acts/Detector/DetectorVolume.hpp"
0016 #include "Acts/Detector/DetectorVolumeBuilder.hpp"
0017 #include "Acts/Detector/GeometryIdGenerator.hpp"
0018 #include "Acts/Detector/LayerStructureBuilder.hpp"
0019 #include "Acts/Detector/PortalGenerators.hpp"
0020 #include "Acts/Detector/VolumeStructureBuilder.hpp"
0021 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0022 #include "Acts/Geometry/GeometryContext.hpp"
0023 #include "Acts/Navigation/DetectorVolumeFinders.hpp"
0024 #include "Acts/Navigation/SurfaceCandidatesUpdaters.hpp"
0025 #include "Acts/Plugins/Json/DetectorJsonConverter.hpp"
0026 #include "Acts/Surfaces/CylinderBounds.hpp"
0027 #include "Acts/Surfaces/CylinderSurface.hpp"
0028 #include "Acts/Surfaces/Surface.hpp"
0029 #include "Acts/Tests/CommonHelpers/CylindricalTrackingGeometry.hpp"
0030 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0031 #include "Acts/Utilities/Enumerate.hpp"
0032
0033 #include <fstream>
0034 #include <memory>
0035 #include <vector>
0036
0037 #include <nlohmann/json.hpp>
0038
0039 namespace {
0040
0041
0042
0043
0044 std::vector<std::shared_ptr<Acts::Surface>> unpackSurfaces(
0045 const std::vector<const Acts::Surface*>& surfaces) {
0046 std::vector<std::shared_ptr<Acts::Surface>> uSurfaces;
0047 uSurfaces.reserve(surfaces.size());
0048 for (const auto s : surfaces) {
0049 auto* ncs = const_cast<Acts::Surface*>(s);
0050 uSurfaces.push_back(ncs->getSharedPtr());
0051 }
0052 return uSurfaces;
0053 }
0054
0055 Acts::DetectorJsonConverter::Options detrayOptions() {
0056
0057 Acts::DetectorVolumeJsonConverter::Options detrayOptions;
0058 detrayOptions.transformOptions.writeIdentity = true;
0059 detrayOptions.transformOptions.transpose = true;
0060 detrayOptions.surfaceOptions.transformOptions =
0061 detrayOptions.transformOptions;
0062 detrayOptions.portalOptions.surfaceOptions = detrayOptions.surfaceOptions;
0063 return Acts::DetectorJsonConverter::Options{detrayOptions};
0064 }
0065
0066 }
0067
0068 Acts::GeometryContext tContext;
0069 auto cGeometry = Acts::Test::CylindricalTrackingGeometry(tContext);
0070
0071 BOOST_AUTO_TEST_SUITE(DetectorJsonConverter)
0072
0073 BOOST_AUTO_TEST_CASE(SingleEmptyVolumeDetector) {
0074 auto portalGenerator = Acts::Experimental::defaultPortalGenerator();
0075
0076
0077 Acts::Transform3 nominal = Acts::Transform3::Identity();
0078 auto bounds = std::make_unique<Acts::CylinderVolumeBounds>(0., 50., 100.);
0079
0080 auto volume = Acts::Experimental::DetectorVolumeFactory::construct(
0081 portalGenerator, tContext, "Volume", nominal, std::move(bounds),
0082 Acts::Experimental::tryAllPortals());
0083
0084 std::vector<std::shared_ptr<Acts::Experimental::DetectorVolume>> volumes = {
0085 volume};
0086
0087 Acts::Experimental::GeometryIdGenerator::Config generatorConfig;
0088 Acts::Experimental::GeometryIdGenerator generator(
0089 generatorConfig,
0090 Acts::getDefaultLogger("SequentialIdGenerator", Acts::Logging::VERBOSE));
0091 auto cache = generator.generateCache();
0092 for (auto& vol : volumes) {
0093 generator.assignGeometryId(cache, *vol);
0094 }
0095
0096 auto detector = Acts::Experimental::Detector::makeShared(
0097 "Detector", volumes, Acts::Experimental::tryRootVolumes());
0098
0099 auto jDetector = Acts::DetectorJsonConverter::toJson(tContext, *detector);
0100
0101 std::ofstream out;
0102 out.open("single-empty-volume-detector.json");
0103 out << jDetector.dump(4);
0104 out.close();
0105 }
0106
0107 BOOST_AUTO_TEST_CASE(SingleVolumeOneSurfaceDetector) {
0108 auto portalGenerator = Acts::Experimental::defaultPortalGenerator();
0109
0110
0111 Acts::Transform3 nominal = Acts::Transform3::Identity();
0112 auto bounds = std::make_unique<Acts::CylinderVolumeBounds>(0., 50., 100.);
0113
0114 auto cylinderBounds = std::make_shared<Acts::CylinderBounds>(30., 90.);
0115 auto surface =
0116 Acts::Surface::makeShared<Acts::CylinderSurface>(nominal, cylinderBounds);
0117
0118 auto volume = Acts::Experimental::DetectorVolumeFactory::construct(
0119 portalGenerator, tContext, "Volume", nominal, std::move(bounds),
0120 {surface}, {}, Acts::Experimental::tryNoVolumes(),
0121 Acts::Experimental::tryAllPortalsAndSurfaces());
0122
0123 std::vector<std::shared_ptr<Acts::Experimental::DetectorVolume>> volumes = {
0124 volume};
0125
0126 Acts::Experimental::GeometryIdGenerator::Config generatorConfig;
0127 Acts::Experimental::GeometryIdGenerator generator(
0128 generatorConfig,
0129 Acts::getDefaultLogger("SequentialIdGenerator", Acts::Logging::VERBOSE));
0130 auto cache = generator.generateCache();
0131 for (auto& vol : volumes) {
0132 generator.assignGeometryId(cache, *vol);
0133 }
0134
0135 auto detector = Acts::Experimental::Detector::makeShared(
0136 "Detector", volumes, Acts::Experimental::tryRootVolumes());
0137
0138 auto jDetector = Acts::DetectorJsonConverter::toJson(tContext, *detector);
0139
0140 std::ofstream out;
0141 out.open("single-volume-one-surface-detector.json");
0142 out << jDetector.dump(4);
0143 out.close();
0144
0145 out.open("single-volume-one-surface-detector-detray.json");
0146 out << Acts::DetectorJsonConverter::toJsonDetray(tContext, *detector,
0147 detrayOptions())
0148 .dump(4);
0149 out.close();
0150 }
0151
0152 BOOST_AUTO_TEST_CASE(BeamPipeEndcapBarrelDetector) {
0153
0154 Acts::Test::CylindricalTrackingGeometry::DetectorStore dStore;
0155
0156
0157 std::vector<std::shared_ptr<Acts::Experimental::IDetectorComponentBuilder>>
0158 endcapBuilders;
0159 for (auto [ie, ep] :
0160 Acts::enumerate(std::vector<Acts::ActsScalar>({-710., 710.}))) {
0161 auto rSurfaces = cGeometry.surfacesRing(dStore, 6.4, 12.4, 36., 0.125, 0.,
0162 55., ep, 2., 22u);
0163
0164 auto endcapSurfaces = std::make_shared<
0165 Acts::Experimental::LayerStructureBuilder::SurfacesHolder>(
0166 unpackSurfaces(rSurfaces));
0167
0168 Acts::Experimental::LayerStructureBuilder::Config lsConfig;
0169 lsConfig.auxiliary = "*** Endcap with 22 surfaces ***";
0170 lsConfig.surfacesProvider = endcapSurfaces;
0171 lsConfig.binnings = {Acts::Experimental::ProtoBinning(
0172 Acts::binPhi, Acts::detail::AxisBoundaryType::Closed, -M_PI, M_PI, 22u,
0173 1u)};
0174
0175 auto layerBuilder =
0176 std::make_shared<Acts::Experimental::LayerStructureBuilder>(
0177 lsConfig, Acts::getDefaultLogger("EndcapInteralsBuilder",
0178 Acts::Logging::VERBOSE));
0179
0180 Acts::Experimental::VolumeStructureBuilder::Config shapeConfig;
0181 shapeConfig.boundValues = {18, 100, 10., M_PI, 0.};
0182 shapeConfig.transform = Acts::Transform3(Acts::Transform3::Identity())
0183 .pretranslate(Acts::Vector3(0., 0., ep));
0184 shapeConfig.boundsType = Acts::VolumeBounds::BoundsType::eCylinder;
0185
0186 auto shapeBuilder =
0187 std::make_shared<Acts::Experimental::VolumeStructureBuilder>(
0188 shapeConfig, Acts::getDefaultLogger("EndcapShapeBuilder",
0189 Acts::Logging::VERBOSE));
0190
0191 Acts::Experimental::DetectorVolumeBuilder::Config dvCfg;
0192 dvCfg.name = "EndcapWithSurfaces_" + std::to_string(ie);
0193 dvCfg.externalsBuilder = shapeBuilder;
0194 dvCfg.internalsBuilder = layerBuilder;
0195
0196 auto dvBuilder =
0197 std::make_shared<Acts::Experimental::DetectorVolumeBuilder>(
0198 dvCfg,
0199 Acts::getDefaultLogger("EndcapBuilder", Acts::Logging::VERBOSE));
0200 endcapBuilders.push_back(dvBuilder);
0201 }
0202
0203
0204 Acts::Experimental::VolumeStructureBuilder::Config innerShapeConfig;
0205 innerShapeConfig.boundValues = {18., 60., 700., M_PI, 0.};
0206 innerShapeConfig.boundsType = Acts::VolumeBounds::BoundsType::eCylinder;
0207
0208 auto innerShapeBuilder =
0209 std::make_shared<Acts::Experimental::VolumeStructureBuilder>(
0210 innerShapeConfig,
0211 Acts::getDefaultLogger("InnerShapeBuilder", Acts::Logging::VERBOSE));
0212
0213 Acts::Experimental::DetectorVolumeBuilder::Config ivCfg;
0214 ivCfg.name = "InnerBarrelGap";
0215 ivCfg.externalsBuilder = innerShapeBuilder;
0216
0217 auto ivBuilder = std::make_shared<Acts::Experimental::DetectorVolumeBuilder>(
0218 ivCfg, Acts::getDefaultLogger("InnerBarrel", Acts::Logging::VERBOSE));
0219
0220
0221 auto cSurfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.145, 72,
0222 3., 2., {32u, 14u});
0223
0224 auto barrelSurfaces = std::make_shared<
0225 Acts::Experimental::LayerStructureBuilder::SurfacesHolder>(
0226 unpackSurfaces(cSurfaces));
0227
0228
0229 Acts::Experimental::LayerStructureBuilder::Config lsConfig;
0230 lsConfig.auxiliary = "*** Barrel with 448 surfaces ***";
0231 lsConfig.surfacesProvider = barrelSurfaces;
0232 lsConfig.binnings = {Acts::Experimental::ProtoBinning{
0233 Acts::binZ, Acts::detail::AxisBoundaryType::Bound,
0234 -480., 480., 14u, 1u},
0235 Acts::Experimental::ProtoBinning(
0236 Acts::binPhi, Acts::detail::AxisBoundaryType::Closed,
0237 -M_PI, M_PI, 32u, 1u)};
0238
0239 auto barrelBuilder =
0240 std::make_shared<Acts::Experimental::LayerStructureBuilder>(
0241 lsConfig, Acts::getDefaultLogger("BarrelInternalsBuilder",
0242 Acts::Logging::VERBOSE));
0243
0244 Acts::Experimental::VolumeStructureBuilder::Config shapeConfig;
0245 shapeConfig.boundValues = {60., 80., 700., M_PI, 0.};
0246 shapeConfig.boundsType = Acts::VolumeBounds::BoundsType::eCylinder;
0247
0248 auto shapeBuilder =
0249 std::make_shared<Acts::Experimental::VolumeStructureBuilder>(
0250 shapeConfig,
0251 Acts::getDefaultLogger("BarrelShapeBuilder", Acts::Logging::VERBOSE));
0252
0253 Acts::Experimental::DetectorVolumeBuilder::Config dvCfg;
0254 dvCfg.name = "BarrelWithSurfaces";
0255 dvCfg.externalsBuilder = shapeBuilder;
0256 dvCfg.internalsBuilder = barrelBuilder;
0257
0258 auto dvBuilder = std::make_shared<Acts::Experimental::DetectorVolumeBuilder>(
0259 dvCfg, Acts::getDefaultLogger("BarrelBuilder", Acts::Logging::VERBOSE));
0260
0261
0262 Acts::Experimental::VolumeStructureBuilder::Config outerShapeConfig;
0263 outerShapeConfig.boundValues = {80., 100., 700., M_PI, 0.};
0264 outerShapeConfig.boundsType = Acts::VolumeBounds::BoundsType::eCylinder;
0265
0266 auto outerShapeBuilder =
0267 std::make_shared<Acts::Experimental::VolumeStructureBuilder>(
0268 outerShapeConfig,
0269 Acts::getDefaultLogger("OuterShapeBuilder", Acts::Logging::VERBOSE));
0270
0271 Acts::Experimental::DetectorVolumeBuilder::Config ovCfg;
0272 ovCfg.name = "OuterBarrelGap";
0273 ovCfg.externalsBuilder = outerShapeBuilder;
0274
0275 auto ovBuilder = std::make_shared<Acts::Experimental::DetectorVolumeBuilder>(
0276 ovCfg, Acts::getDefaultLogger("OuterBarrel", Acts::Logging::VERBOSE));
0277
0278
0279 Acts::Experimental::CylindricalContainerBuilder::Config ccBarrelBuilderCfg;
0280 ccBarrelBuilderCfg.builders = {ivBuilder, dvBuilder, ovBuilder};
0281 ccBarrelBuilderCfg.binning = {Acts::binR};
0282
0283 auto ccBarrelBuilder =
0284 std::make_shared<Acts::Experimental::CylindricalContainerBuilder>(
0285 ccBarrelBuilderCfg,
0286 Acts::getDefaultLogger("BarrelBuilder", Acts::Logging::VERBOSE));
0287
0288
0289 Acts::Experimental::CylindricalContainerBuilder::Config ccBarrelEcBuilderCfg;
0290 ccBarrelEcBuilderCfg.builders = {endcapBuilders[0u], ccBarrelBuilder,
0291 endcapBuilders[1u]};
0292 ccBarrelEcBuilderCfg.binning = {Acts::binZ};
0293
0294 auto ccBarrelEndcapBuilder =
0295 std::make_shared<Acts::Experimental::CylindricalContainerBuilder>(
0296 ccBarrelEcBuilderCfg, Acts::getDefaultLogger("BarrelEndcapBuilder",
0297 Acts::Logging::VERBOSE));
0298
0299
0300 Acts::Experimental::VolumeStructureBuilder::Config bpShapeConfig;
0301 bpShapeConfig.boundValues = {0., 18., 720., M_PI, 0.};
0302 bpShapeConfig.boundsType = Acts::VolumeBounds::BoundsType::eCylinder;
0303
0304 auto bpShapeBuilder =
0305 std::make_shared<Acts::Experimental::VolumeStructureBuilder>(
0306 bpShapeConfig, Acts::getDefaultLogger("BeamPipeShapeBuilder",
0307 Acts::Logging::VERBOSE));
0308
0309 Acts::Experimental::DetectorVolumeBuilder::Config bpCfg;
0310 bpCfg.name = "BeamPipe";
0311 bpCfg.externalsBuilder = bpShapeBuilder;
0312
0313 auto bpBuilder = std::make_shared<Acts::Experimental::DetectorVolumeBuilder>(
0314 bpCfg, Acts::getDefaultLogger("BeamPipe", Acts::Logging::VERBOSE));
0315
0316
0317 Acts::Experimental::CylindricalContainerBuilder::Config detCompBuilderCfg;
0318 detCompBuilderCfg.builders = {bpBuilder, ccBarrelEndcapBuilder};
0319 detCompBuilderCfg.binning = {Acts::binR};
0320
0321 auto detCompBuilder =
0322 std::make_shared<Acts::Experimental::CylindricalContainerBuilder>(
0323 detCompBuilderCfg);
0324
0325 auto gigConfig = Acts::Experimental::GeometryIdGenerator::Config();
0326 auto gig =
0327 std::make_shared<Acts::Experimental::GeometryIdGenerator>(gigConfig);
0328
0329 Acts::Experimental::DetectorBuilder::Config detBuilderCfg;
0330 detBuilderCfg.name = "Detector";
0331 detBuilderCfg.builder = detCompBuilder;
0332 detBuilderCfg.geoIdGenerator = gig;
0333
0334 auto detBuilder =
0335 std::make_shared<Acts::Experimental::DetectorBuilder>(detBuilderCfg);
0336
0337 auto detector = detBuilder->construct(tContext);
0338
0339 auto jDetector = Acts::DetectorJsonConverter::toJson(tContext, *detector);
0340
0341 std::ofstream out;
0342
0343 out.open("barrel-endcap-detector.json");
0344 out << jDetector.dump(4);
0345 out.close();
0346
0347 auto in = std::ifstream("barrel-endcap-detector.json",
0348 std::ifstream::in | std::ifstream::binary);
0349
0350 BOOST_CHECK(in.good());
0351 nlohmann::json jDetectorIn;
0352 in >> jDetectorIn;
0353 in.close();
0354
0355 auto detectorIn =
0356 Acts::DetectorJsonConverter::fromJson(tContext, jDetectorIn);
0357
0358 BOOST_CHECK_EQUAL(detectorIn->name(), detector->name());
0359
0360 auto jDetectorInOut =
0361 Acts::DetectorJsonConverter::toJson(tContext, *detectorIn);
0362
0363 out.open("barrel-endcap-detector-closure.json");
0364 out << jDetectorInOut.dump(4);
0365 out.close();
0366
0367 auto jDetectorDetray = Acts::DetectorJsonConverter::toJsonDetray(
0368 tContext, *detector, detrayOptions());
0369
0370 out.open("barrel-endcap-detector-detray.json");
0371 out << jDetectorDetray.dump(4);
0372 out.close();
0373 }
0374
0375 BOOST_AUTO_TEST_SUITE_END()