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/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 /// Helper method that allows to use the already existing testing
0036 /// infrastructure with the new const-correct detector design
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 }  // namespace
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   // Create a single cylindrical volume
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   // Detray format test - manipulate for detray
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   // Create a single cylindrical volume
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   // Configure the layer structure builder
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   // Cross-check writing
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   // Configure the layer structure builder
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   // Cross-check writing
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()