Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-13 08:19:51

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/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/InternalNavigation.hpp"
0022 #include "Acts/Surfaces/CylinderBounds.hpp"
0023 #include "Acts/Surfaces/CylinderSurface.hpp"
0024 #include "ActsPlugins/Json/DetectorVolumeJsonConverter.hpp"
0025 #include "ActsTests/CommonHelpers/CylindricalTrackingGeometry.hpp"
0026 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0027 
0028 #include <fstream>
0029 #include <memory>
0030 #include <numbers>
0031 #include <vector>
0032 
0033 #include <nlohmann/json.hpp>
0034 
0035 using namespace Acts;
0036 
0037 namespace {
0038 /// Helper method that allows to use the already existing testing
0039 /// infrastructure with the new const-correct detector design
0040 ///
0041 std::vector<std::shared_ptr<Surface>> unpackSurfaces(
0042     const std::vector<Surface*>& surfaces) {
0043   std::vector<std::shared_ptr<Surface>> uSurfaces;
0044   uSurfaces.reserve(surfaces.size());
0045   for (auto* s : surfaces) {
0046     uSurfaces.push_back(s->getSharedPtr());
0047   }
0048   return uSurfaces;
0049 }
0050 
0051 }  // namespace
0052 
0053 namespace ActsTests {
0054 
0055 GeometryContext tContext;
0056 auto cGeometry = CylindricalTrackingGeometry(tContext);
0057 
0058 auto portalGenerator = Experimental::defaultPortalGenerator();
0059 
0060 BOOST_AUTO_TEST_SUITE(JsonSuite)
0061 
0062 BOOST_AUTO_TEST_CASE(SingleEmptyVolume) {
0063   // Create a single cylindrical volume
0064   Transform3 nominal = Transform3::Identity();
0065   auto bounds = std::make_unique<CylinderVolumeBounds>(0., 50., 100.);
0066 
0067   auto volume = Experimental::DetectorVolumeFactory::construct(
0068       portalGenerator, tContext, "EmptyVolume", nominal, std::move(bounds),
0069       Experimental::tryAllPortals());
0070 
0071   std::ofstream out;
0072 
0073   auto jVolume =
0074       DetectorVolumeJsonConverter::toJson(tContext, *volume, {volume.get()});
0075 
0076   out.open("single-empty-volume.json");
0077   out << jVolume.dump(4);
0078   out.close();
0079 
0080   auto in = std::ifstream("single-empty-volume.json",
0081                           std::ifstream::in | std::ifstream::binary);
0082 
0083   BOOST_CHECK(in.good());
0084   nlohmann::json jVolumeIn;
0085   in >> jVolumeIn;
0086   in.close();
0087 
0088   auto volumeIn = DetectorVolumeJsonConverter::fromJson(tContext, jVolumeIn);
0089 
0090   BOOST_CHECK_EQUAL(volumeIn->name(), volume->name());
0091   BOOST_CHECK(
0092       volumeIn->transform(tContext).isApprox(volume->transform(tContext)));
0093   BOOST_CHECK_EQUAL(volumeIn->surfaces().size(), volume->surfaces().size());
0094   BOOST_CHECK_EQUAL(volumeIn->volumes().size(), volume->volumes().size());
0095 }
0096 
0097 BOOST_AUTO_TEST_CASE(SingleSurfaceVolume) {
0098   // Create a single cylindrical volume
0099   Transform3 nominal = Transform3::Identity();
0100   auto volumeBounds = std::make_unique<CylinderVolumeBounds>(0., 50., 100.);
0101   auto surfaceBounds = std::make_unique<CylinderBounds>(25., 100.);
0102 
0103   auto cylinderSurface =
0104       Surface::makeShared<CylinderSurface>(nominal, std::move(surfaceBounds));
0105 
0106   auto volume = Experimental::DetectorVolumeFactory::construct(
0107       portalGenerator, tContext, "CylinderVolume", nominal,
0108       std::move(volumeBounds), {cylinderSurface}, {},
0109       Experimental::tryRootVolumes(), Experimental::tryAllPortalsAndSurfaces());
0110 
0111   std::ofstream out;
0112 
0113   auto jVolume =
0114       DetectorVolumeJsonConverter::toJson(tContext, *volume, {volume.get()});
0115 
0116   out.open("single-surface-volume.json");
0117   out << jVolume.dump(4);
0118   out.close();
0119 
0120   auto in = std::ifstream("single-surface-volume.json",
0121                           std::ifstream::in | std::ifstream::binary);
0122 
0123   BOOST_CHECK(in.good());
0124   nlohmann::json jVolumeIn;
0125   in >> jVolumeIn;
0126   in.close();
0127 
0128   auto volumeIn = DetectorVolumeJsonConverter::fromJson(tContext, jVolumeIn);
0129 
0130   BOOST_CHECK_EQUAL(volumeIn->name(), volume->name());
0131   BOOST_CHECK(
0132       volumeIn->transform(tContext).isApprox(volume->transform(tContext)));
0133   BOOST_CHECK_EQUAL(volumeIn->surfaces().size(), volume->surfaces().size());
0134   BOOST_CHECK_EQUAL(volumeIn->volumes().size(), volume->volumes().size());
0135 }
0136 
0137 BOOST_AUTO_TEST_CASE(EndcapVolumeWithSurfaces) {
0138   CylindricalTrackingGeometry::DetectorStore dStore;
0139 
0140   auto rSurfaces = cGeometry.surfacesRing(dStore, 6.4, 12.4, 36., 0.125, 0.,
0141                                           55., -800, 2., 22u);
0142 
0143   auto endcapSurfaces =
0144       std::make_shared<Experimental::LayerStructureBuilder::SurfacesHolder>(
0145           unpackSurfaces(rSurfaces));
0146   // Configure the layer structure builder
0147   Experimental::LayerStructureBuilder::Config lsConfig;
0148   lsConfig.auxiliary = "*** Endcap with 22 surfaces ***";
0149   lsConfig.surfacesProvider = endcapSurfaces;
0150   lsConfig.binnings = {
0151       {DirectedProtoAxis(AxisDirection::AxisPhi, AxisBoundaryType::Closed,
0152                          -std::numbers::pi, std::numbers::pi, 22u),
0153        1u}};
0154 
0155   auto layerBuilder = std::make_shared<Experimental::LayerStructureBuilder>(
0156       lsConfig, getDefaultLogger("EndcapInteralsBuilder", Logging::VERBOSE));
0157 
0158   Experimental::VolumeStructureBuilder::Config shapeConfig;
0159   shapeConfig.boundValues = {10, 100, 10., std::numbers::pi, 0.};
0160   shapeConfig.transform =
0161       Transform3{Transform3::Identity()}.pretranslate(Vector3(0., 0., -800.));
0162   shapeConfig.boundsType = VolumeBounds::BoundsType::eCylinder;
0163 
0164   auto shapeBuilder = std::make_shared<Experimental::VolumeStructureBuilder>(
0165       shapeConfig, getDefaultLogger("EndcapShapeBuilder", Logging::VERBOSE));
0166 
0167   Experimental::DetectorVolumeBuilder::Config dvCfg;
0168   dvCfg.auxiliary = "*** Test 1 - Cylinder with internal Surface ***";
0169   dvCfg.name = "CylinderWithSurface";
0170   dvCfg.externalsBuilder = shapeBuilder;
0171   dvCfg.internalsBuilder = layerBuilder;
0172 
0173   auto dvBuilder = std::make_shared<Experimental::DetectorVolumeBuilder>(
0174       dvCfg, getDefaultLogger("EndcapBuilder", Logging::VERBOSE));
0175 
0176   auto [volumes, portals, roots] = dvBuilder->construct(tContext);
0177   auto volume = volumes.front();
0178 
0179   auto jVolume =
0180       DetectorVolumeJsonConverter::toJson(tContext, *volume, {volume.get()});
0181 
0182   std::ofstream out;
0183   out.open("endcap-volume-with-surfaces.json");
0184   out << jVolume.dump(4);
0185   out.close();
0186 
0187   auto in = std::ifstream("endcap-volume-with-surfaces.json",
0188                           std::ifstream::in | std::ifstream::binary);
0189 
0190   BOOST_CHECK(in.good());
0191   nlohmann::json jVolumeIn;
0192   in >> jVolumeIn;
0193   in.close();
0194 
0195   auto volumeIn = DetectorVolumeJsonConverter::fromJson(tContext, jVolumeIn);
0196 
0197   BOOST_CHECK_EQUAL(volumeIn->name(), volume->name());
0198   BOOST_CHECK(
0199       volumeIn->transform(tContext).isApprox(volume->transform(tContext)));
0200   BOOST_CHECK_EQUAL(volumeIn->surfaces().size(), volume->surfaces().size());
0201   BOOST_CHECK_EQUAL(volumeIn->volumes().size(), volume->volumes().size());
0202 
0203   // Cross-check writing
0204   jVolume = DetectorVolumeJsonConverter::toJson(tContext, *volumeIn,
0205                                                 {volumeIn.get()});
0206   out.open("endcap-volume-with-surfaces-closure.json");
0207   out << jVolume.dump(4);
0208   out.close();
0209 }
0210 
0211 BOOST_AUTO_TEST_CASE(BarrelVolumeWithSurfaces) {
0212   CylindricalTrackingGeometry::DetectorStore dStore;
0213   auto cSurfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.145, 72,
0214                                               3., 2., {32u, 14u});
0215 
0216   auto barrelSurfaces =
0217       std::make_shared<Experimental::LayerStructureBuilder::SurfacesHolder>(
0218           unpackSurfaces(cSurfaces));
0219 
0220   // Configure the layer structure builder
0221   Experimental::LayerStructureBuilder::Config lsConfig;
0222   lsConfig.auxiliary = "*** Barrel with 448 surfaces ***";
0223   lsConfig.surfacesProvider = barrelSurfaces;
0224   lsConfig.binnings = {
0225       {DirectedProtoAxis(AxisDirection::AxisZ, AxisBoundaryType::Bound, -480.,
0226                          480., 14u),
0227        1u},
0228       {DirectedProtoAxis(AxisDirection::AxisPhi, AxisBoundaryType::Closed,
0229                          -std::numbers::pi, std::numbers::pi, 32u),
0230        1u}};
0231 
0232   auto barrelBuilder = std::make_shared<Experimental::LayerStructureBuilder>(
0233       lsConfig, getDefaultLogger("BarrelInternalsBuilder", Logging::VERBOSE));
0234 
0235   Experimental::VolumeStructureBuilder::Config shapeConfig;
0236   shapeConfig.boundValues = {60., 80., 800., std::numbers::pi, 0.};
0237   shapeConfig.boundsType = VolumeBounds::BoundsType::eCylinder;
0238 
0239   auto shapeBuilder = std::make_shared<Experimental::VolumeStructureBuilder>(
0240       shapeConfig, getDefaultLogger("BarrelShapeBuilder", Logging::VERBOSE));
0241 
0242   Experimental::DetectorVolumeBuilder::Config dvCfg;
0243   dvCfg.auxiliary = "*** Test 1 - Cylinder with internal Surface ***";
0244   dvCfg.name = "BarrelWithSurfaces";
0245   dvCfg.externalsBuilder = shapeBuilder;
0246   dvCfg.internalsBuilder = barrelBuilder;
0247 
0248   auto dvBuilder = std::make_shared<Experimental::DetectorVolumeBuilder>(
0249       dvCfg, getDefaultLogger("EndcapBuilder", Logging::VERBOSE));
0250 
0251   auto [volumes, portals, roots] = dvBuilder->construct(tContext);
0252 
0253   auto volume = volumes.front();
0254 
0255   auto jVolume =
0256       DetectorVolumeJsonConverter::toJson(tContext, *volume, {volume.get()});
0257 
0258   std::ofstream out;
0259   out.open("barrel-volume-with-surfaces.json");
0260   out << jVolume.dump(4);
0261   out.close();
0262 
0263   auto in = std::ifstream("barrel-volume-with-surfaces.json",
0264                           std::ifstream::in | std::ifstream::binary);
0265 
0266   BOOST_CHECK(in.good());
0267   nlohmann::json jVolumeIn;
0268   in >> jVolumeIn;
0269   in.close();
0270 
0271   auto volumeIn = DetectorVolumeJsonConverter::fromJson(tContext, jVolumeIn);
0272 
0273   BOOST_CHECK_EQUAL(volumeIn->name(), volume->name());
0274   BOOST_CHECK(
0275       volumeIn->transform(tContext).isApprox(volume->transform(tContext)));
0276   BOOST_CHECK_EQUAL(volumeIn->surfaces().size(), volume->surfaces().size());
0277   BOOST_CHECK_EQUAL(volumeIn->volumes().size(), volume->volumes().size());
0278 
0279   // Cross-check writing
0280   jVolume = DetectorVolumeJsonConverter::toJson(tContext, *volumeIn,
0281                                                 {volumeIn.get()});
0282   out.open("barrel-volume-with-surfaces-closure.json");
0283   out << jVolume.dump(4);
0284   out.close();
0285 }
0286 
0287 BOOST_AUTO_TEST_SUITE_END()
0288 
0289 }  // namespace ActsTests