Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-09-17 08:04:38

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
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/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 <numbers>
0036 #include <vector>
0037 
0038 #include <nlohmann/json.hpp>
0039 
0040 namespace {
0041 
0042 /// Helper method that allows to use the already existing testing
0043 /// infrastructure with the new const-correct detector design
0044 ///
0045 std::vector<std::shared_ptr<Acts::Surface>> unpackSurfaces(
0046     const std::vector<Acts::Surface*>& surfaces) {
0047   std::vector<std::shared_ptr<Acts::Surface>> uSurfaces;
0048   uSurfaces.reserve(surfaces.size());
0049   for (auto* s : surfaces) {
0050     uSurfaces.push_back(s->getSharedPtr());
0051   }
0052   return uSurfaces;
0053 }
0054 
0055 Acts::DetectorJsonConverter::Options detrayOptions() {
0056   // Detray format test - manipulate for detray
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 }  // namespace
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   // Create a single cylindrical volume
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   // Create a single cylindrical volume
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   // Detector store
0154   Acts::Test::CylindricalTrackingGeometry::DetectorStore dStore;
0155 
0156   // Endcaps
0157   std::vector<std::shared_ptr<Acts::Experimental::IDetectorComponentBuilder>>
0158       endcapBuilders;
0159   for (auto [ie, ep] : Acts::enumerate(std::vector<double>({-710., 710.}))) {
0160     auto rSurfaces = cGeometry.surfacesRing(dStore, 6.4, 12.4, 36., 0.125, 0.,
0161                                             55., ep, 2., 22u);
0162 
0163     auto endcapSurfaces = std::make_shared<
0164         Acts::Experimental::LayerStructureBuilder::SurfacesHolder>(
0165         unpackSurfaces(rSurfaces));
0166     // Configure the layer structure builder
0167     Acts::Experimental::LayerStructureBuilder::Config lsConfig;
0168     lsConfig.auxiliary = "*** Endcap with 22 surfaces ***";
0169     lsConfig.surfacesProvider = endcapSurfaces;
0170     lsConfig.binnings = {
0171         {Acts::DirectedProtoAxis(Acts::AxisDirection::AxisPhi,
0172                                  Acts::AxisBoundaryType::Closed,
0173                                  -std::numbers::pi, std::numbers::pi, 22u),
0174          1u}};
0175 
0176     auto layerBuilder =
0177         std::make_shared<Acts::Experimental::LayerStructureBuilder>(
0178             lsConfig, Acts::getDefaultLogger("EndcapInteralsBuilder",
0179                                              Acts::Logging::VERBOSE));
0180 
0181     Acts::Experimental::VolumeStructureBuilder::Config shapeConfig;
0182     shapeConfig.boundValues = {18, 100, 10., std::numbers::pi, 0.};
0183     shapeConfig.transform =
0184         Acts::Transform3{Acts::Transform3::Identity()}.pretranslate(
0185             Acts::Vector3(0., 0., ep));
0186     shapeConfig.boundsType = Acts::VolumeBounds::BoundsType::eCylinder;
0187 
0188     auto shapeBuilder =
0189         std::make_shared<Acts::Experimental::VolumeStructureBuilder>(
0190             shapeConfig, Acts::getDefaultLogger("EndcapShapeBuilder",
0191                                                 Acts::Logging::VERBOSE));
0192 
0193     Acts::Experimental::DetectorVolumeBuilder::Config dvCfg;
0194     dvCfg.name = "EndcapWithSurfaces_" + std::to_string(ie);
0195     dvCfg.externalsBuilder = shapeBuilder;
0196     dvCfg.internalsBuilder = layerBuilder;
0197 
0198     auto dvBuilder =
0199         std::make_shared<Acts::Experimental::DetectorVolumeBuilder>(
0200             dvCfg,
0201             Acts::getDefaultLogger("EndcapBuilder", Acts::Logging::VERBOSE));
0202     endcapBuilders.push_back(dvBuilder);
0203   }
0204 
0205   // Central barrel
0206   Acts::Experimental::VolumeStructureBuilder::Config innerShapeConfig;
0207   innerShapeConfig.boundValues = {18., 60., 700., std::numbers::pi, 0.};
0208   innerShapeConfig.boundsType = Acts::VolumeBounds::BoundsType::eCylinder;
0209 
0210   auto innerShapeBuilder =
0211       std::make_shared<Acts::Experimental::VolumeStructureBuilder>(
0212           innerShapeConfig,
0213           Acts::getDefaultLogger("InnerShapeBuilder", Acts::Logging::VERBOSE));
0214 
0215   Acts::Experimental::DetectorVolumeBuilder::Config ivCfg;
0216   ivCfg.name = "InnerBarrelGap";
0217   ivCfg.externalsBuilder = innerShapeBuilder;
0218 
0219   auto ivBuilder = std::make_shared<Acts::Experimental::DetectorVolumeBuilder>(
0220       ivCfg, Acts::getDefaultLogger("InnerBarrel", Acts::Logging::VERBOSE));
0221 
0222   ///  Barrel surfaces
0223   auto cSurfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.145, 72,
0224                                               3., 2., {32u, 14u});
0225 
0226   auto barrelSurfaces = std::make_shared<
0227       Acts::Experimental::LayerStructureBuilder::SurfacesHolder>(
0228       unpackSurfaces(cSurfaces));
0229 
0230   // Configure the layer structure builder
0231   Acts::Experimental::LayerStructureBuilder::Config lsConfig;
0232   lsConfig.auxiliary = "*** Barrel with 448 surfaces ***";
0233   lsConfig.surfacesProvider = barrelSurfaces;
0234   lsConfig.binnings = {
0235       {Acts::DirectedProtoAxis(Acts::AxisDirection::AxisZ,
0236                                Acts::AxisBoundaryType::Bound, -480., 480., 14u),
0237        1u},
0238       {Acts::DirectedProtoAxis(Acts::AxisDirection::AxisPhi,
0239                                Acts::AxisBoundaryType::Closed,
0240                                -std::numbers::pi, std::numbers::pi, 32u),
0241        1u}};
0242 
0243   auto barrelBuilder =
0244       std::make_shared<Acts::Experimental::LayerStructureBuilder>(
0245           lsConfig, Acts::getDefaultLogger("BarrelInternalsBuilder",
0246                                            Acts::Logging::VERBOSE));
0247 
0248   Acts::Experimental::VolumeStructureBuilder::Config shapeConfig;
0249   shapeConfig.boundValues = {60., 80., 700., std::numbers::pi, 0.};
0250   shapeConfig.boundsType = Acts::VolumeBounds::BoundsType::eCylinder;
0251 
0252   auto shapeBuilder =
0253       std::make_shared<Acts::Experimental::VolumeStructureBuilder>(
0254           shapeConfig,
0255           Acts::getDefaultLogger("BarrelShapeBuilder", Acts::Logging::VERBOSE));
0256 
0257   Acts::Experimental::DetectorVolumeBuilder::Config dvCfg;
0258   dvCfg.name = "BarrelWithSurfaces";
0259   dvCfg.externalsBuilder = shapeBuilder;
0260   dvCfg.internalsBuilder = barrelBuilder;
0261 
0262   auto dvBuilder = std::make_shared<Acts::Experimental::DetectorVolumeBuilder>(
0263       dvCfg, Acts::getDefaultLogger("BarrelBuilder", Acts::Logging::VERBOSE));
0264 
0265   // Outer shape
0266   Acts::Experimental::VolumeStructureBuilder::Config outerShapeConfig;
0267   outerShapeConfig.boundValues = {80., 100., 700., std::numbers::pi, 0.};
0268   outerShapeConfig.boundsType = Acts::VolumeBounds::BoundsType::eCylinder;
0269 
0270   auto outerShapeBuilder =
0271       std::make_shared<Acts::Experimental::VolumeStructureBuilder>(
0272           outerShapeConfig,
0273           Acts::getDefaultLogger("OuterShapeBuilder", Acts::Logging::VERBOSE));
0274 
0275   Acts::Experimental::DetectorVolumeBuilder::Config ovCfg;
0276   ovCfg.name = "OuterBarrelGap";
0277   ovCfg.externalsBuilder = outerShapeBuilder;
0278 
0279   auto ovBuilder = std::make_shared<Acts::Experimental::DetectorVolumeBuilder>(
0280       ovCfg, Acts::getDefaultLogger("OuterBarrel", Acts::Logging::VERBOSE));
0281 
0282   // Build the combined barrel
0283   Acts::Experimental::CylindricalContainerBuilder::Config ccBarrelBuilderCfg;
0284   ccBarrelBuilderCfg.builders = {ivBuilder, dvBuilder, ovBuilder};
0285   ccBarrelBuilderCfg.binning = {Acts::AxisDirection::AxisR};
0286 
0287   auto ccBarrelBuilder =
0288       std::make_shared<Acts::Experimental::CylindricalContainerBuilder>(
0289           ccBarrelBuilderCfg,
0290           Acts::getDefaultLogger("BarrelBuilder", Acts::Logging::VERBOSE));
0291 
0292   // Builder the combined endcap barrel system
0293   Acts::Experimental::CylindricalContainerBuilder::Config ccBarrelEcBuilderCfg;
0294   ccBarrelEcBuilderCfg.builders = {endcapBuilders[0u], ccBarrelBuilder,
0295                                    endcapBuilders[1u]};
0296   ccBarrelEcBuilderCfg.binning = {Acts::AxisDirection::AxisZ};
0297 
0298   auto ccBarrelEndcapBuilder =
0299       std::make_shared<Acts::Experimental::CylindricalContainerBuilder>(
0300           ccBarrelEcBuilderCfg, Acts::getDefaultLogger("BarrelEndcapBuilder",
0301                                                        Acts::Logging::VERBOSE));
0302 
0303   // Beam Pipe
0304   Acts::Experimental::VolumeStructureBuilder::Config bpShapeConfig;
0305   bpShapeConfig.boundValues = {0., 18., 720., std::numbers::pi, 0.};
0306   bpShapeConfig.boundsType = Acts::VolumeBounds::BoundsType::eCylinder;
0307 
0308   auto bpShapeBuilder =
0309       std::make_shared<Acts::Experimental::VolumeStructureBuilder>(
0310           bpShapeConfig, Acts::getDefaultLogger("BeamPipeShapeBuilder",
0311                                                 Acts::Logging::VERBOSE));
0312 
0313   Acts::Experimental::DetectorVolumeBuilder::Config bpCfg;
0314   bpCfg.name = "BeamPipe";
0315   bpCfg.externalsBuilder = bpShapeBuilder;
0316 
0317   auto bpBuilder = std::make_shared<Acts::Experimental::DetectorVolumeBuilder>(
0318       bpCfg, Acts::getDefaultLogger("BeamPipe", Acts::Logging::VERBOSE));
0319 
0320   // Full detector
0321   Acts::Experimental::CylindricalContainerBuilder::Config detCompBuilderCfg;
0322   detCompBuilderCfg.builders = {bpBuilder, ccBarrelEndcapBuilder};
0323   detCompBuilderCfg.binning = {Acts::AxisDirection::AxisR};
0324 
0325   auto detCompBuilder =
0326       std::make_shared<Acts::Experimental::CylindricalContainerBuilder>(
0327           detCompBuilderCfg);
0328 
0329   auto gigConfig = Acts::Experimental::GeometryIdGenerator::Config();
0330   auto gig =
0331       std::make_shared<Acts::Experimental::GeometryIdGenerator>(gigConfig);
0332 
0333   Acts::Experimental::DetectorBuilder::Config detBuilderCfg;
0334   detBuilderCfg.name = "Detector";
0335   detBuilderCfg.builder = detCompBuilder;
0336   detBuilderCfg.geoIdGenerator = gig;
0337 
0338   auto detBuilder =
0339       std::make_shared<Acts::Experimental::DetectorBuilder>(detBuilderCfg);
0340 
0341   auto detector = detBuilder->construct(tContext);
0342 
0343   auto jDetector = Acts::DetectorJsonConverter::toJson(tContext, *detector);
0344 
0345   std::ofstream out;
0346 
0347   out.open("barrel-endcap-detector.json");
0348   out << jDetector.dump(4);
0349   out.close();
0350 
0351   auto in = std::ifstream("barrel-endcap-detector.json",
0352                           std::ifstream::in | std::ifstream::binary);
0353 
0354   BOOST_CHECK(in.good());
0355   nlohmann::json jDetectorIn;
0356   in >> jDetectorIn;
0357   in.close();
0358 
0359   auto detectorIn =
0360       Acts::DetectorJsonConverter::fromJson(tContext, jDetectorIn);
0361 
0362   BOOST_CHECK_EQUAL(detectorIn->name(), detector->name());
0363 
0364   auto jDetectorInOut =
0365       Acts::DetectorJsonConverter::toJson(tContext, *detectorIn);
0366 
0367   out.open("barrel-endcap-detector-closure.json");
0368   out << jDetectorInOut.dump(4);
0369   out.close();
0370 
0371   auto jDetectorDetray = Acts::DetectorJsonConverter::toJsonDetray(
0372       tContext, *detector, detrayOptions());
0373 
0374   out.open("barrel-endcap-detector-detray.json");
0375   out << jDetectorDetray.dump(4);
0376   out.close();
0377 }
0378 
0379 BOOST_AUTO_TEST_SUITE_END()