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