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