Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:11:43

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2023 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 http://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/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 /// Helper method that allows to use the already existing testing
0042 /// infrastructure with the new const-correct detector design
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   // 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] :
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     // Configure the layer structure builder
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   // Central barrel
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   ///  Barrel surfaces
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   // Configure the layer structure builder
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   // Outer shape
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   // Build the combined barrel
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   // Builder the combined endcap barrel system
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   // Beam Pipe
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   // Full detector
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()