File indexing completed on 2025-09-13 08:15:00
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<Acts::Surface*>& surfaces) {
0041 std::vector<std::shared_ptr<Acts::Surface>> uSurfaces;
0042 uSurfaces.reserve(surfaces.size());
0043 for (auto* s : surfaces) {
0044 uSurfaces.push_back(s->getSharedPtr());
0045 }
0046 return uSurfaces;
0047 }
0048
0049 }
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
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
0094 BOOST_AUTO_TEST_CASE(SingleSurfaceVolume) {
0095
0096 Acts::Transform3 nominal = Acts::Transform3::Identity();
0097 auto volumeBounds =
0098 std::make_unique<Acts::CylinderVolumeBounds>(0., 50., 100.);
0099 auto surfaceBounds = std::make_unique<Acts::CylinderBounds>(25., 100.);
0100
0101 auto cylinderSurface = Acts::Surface::makeShared<Acts::CylinderSurface>(
0102 nominal, std::move(surfaceBounds));
0103
0104 auto volume = Acts::Experimental::DetectorVolumeFactory::construct(
0105 portalGenerator, tContext, "CylinderVolume", nominal,
0106 std::move(volumeBounds), {cylinderSurface}, {},
0107 Acts::Experimental::tryRootVolumes(),
0108 Acts::Experimental::tryAllPortalsAndSurfaces());
0109
0110 std::ofstream out;
0111
0112 auto jVolume = Acts::DetectorVolumeJsonConverter::toJson(tContext, *volume,
0113 {volume.get()});
0114
0115 out.open("single-surface-volume.json");
0116 out << jVolume.dump(4);
0117 out.close();
0118
0119 auto in = std::ifstream("single-surface-volume.json",
0120 std::ifstream::in | std::ifstream::binary);
0121
0122 BOOST_CHECK(in.good());
0123 nlohmann::json jVolumeIn;
0124 in >> jVolumeIn;
0125 in.close();
0126
0127 auto volumeIn =
0128 Acts::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 Acts::Test::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 = std::make_shared<
0144 Acts::Experimental::LayerStructureBuilder::SurfacesHolder>(
0145 unpackSurfaces(rSurfaces));
0146
0147 Acts::Experimental::LayerStructureBuilder::Config lsConfig;
0148 lsConfig.auxiliary = "*** Endcap with 22 surfaces ***";
0149 lsConfig.surfacesProvider = endcapSurfaces;
0150 lsConfig.binnings = {
0151 {Acts::DirectedProtoAxis(Acts::AxisDirection::AxisPhi,
0152 Acts::AxisBoundaryType::Closed,
0153 -std::numbers::pi, std::numbers::pi, 22u),
0154 1u}};
0155
0156 auto layerBuilder =
0157 std::make_shared<Acts::Experimental::LayerStructureBuilder>(
0158 lsConfig, Acts::getDefaultLogger("EndcapInteralsBuilder",
0159 Acts::Logging::VERBOSE));
0160
0161 Acts::Experimental::VolumeStructureBuilder::Config shapeConfig;
0162 shapeConfig.boundValues = {10, 100, 10., std::numbers::pi, 0.};
0163 shapeConfig.transform =
0164 Acts::Transform3{Acts::Transform3::Identity()}.pretranslate(
0165 Acts::Vector3(0., 0., -800.));
0166 shapeConfig.boundsType = Acts::VolumeBounds::BoundsType::eCylinder;
0167
0168 auto shapeBuilder =
0169 std::make_shared<Acts::Experimental::VolumeStructureBuilder>(
0170 shapeConfig,
0171 Acts::getDefaultLogger("EndcapShapeBuilder", Acts::Logging::VERBOSE));
0172
0173 Acts::Experimental::DetectorVolumeBuilder::Config dvCfg;
0174 dvCfg.auxiliary = "*** Test 1 - Cylinder with internal Surface ***";
0175 dvCfg.name = "CylinderWithSurface";
0176 dvCfg.externalsBuilder = shapeBuilder;
0177 dvCfg.internalsBuilder = layerBuilder;
0178
0179 auto dvBuilder = std::make_shared<Acts::Experimental::DetectorVolumeBuilder>(
0180 dvCfg, Acts::getDefaultLogger("EndcapBuilder", Acts::Logging::VERBOSE));
0181
0182 auto [volumes, portals, roots] = dvBuilder->construct(tContext);
0183 auto volume = volumes.front();
0184
0185 auto jVolume = Acts::DetectorVolumeJsonConverter::toJson(tContext, *volume,
0186 {volume.get()});
0187
0188 std::ofstream out;
0189 out.open("endcap-volume-with-surfaces.json");
0190 out << jVolume.dump(4);
0191 out.close();
0192
0193 auto in = std::ifstream("endcap-volume-with-surfaces.json",
0194 std::ifstream::in | std::ifstream::binary);
0195
0196 BOOST_CHECK(in.good());
0197 nlohmann::json jVolumeIn;
0198 in >> jVolumeIn;
0199 in.close();
0200
0201 auto volumeIn =
0202 Acts::DetectorVolumeJsonConverter::fromJson(tContext, jVolumeIn);
0203
0204 BOOST_CHECK_EQUAL(volumeIn->name(), volume->name());
0205 BOOST_CHECK(
0206 volumeIn->transform(tContext).isApprox(volume->transform(tContext)));
0207 BOOST_CHECK_EQUAL(volumeIn->surfaces().size(), volume->surfaces().size());
0208 BOOST_CHECK_EQUAL(volumeIn->volumes().size(), volume->volumes().size());
0209
0210
0211 jVolume = Acts::DetectorVolumeJsonConverter::toJson(tContext, *volumeIn,
0212 {volumeIn.get()});
0213 out.open("endcap-volume-with-surfaces-closure.json");
0214 out << jVolume.dump(4);
0215 out.close();
0216 }
0217
0218 BOOST_AUTO_TEST_CASE(BarrelVolumeWithSurfaces) {
0219 Acts::Test::CylindricalTrackingGeometry::DetectorStore dStore;
0220 auto cSurfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.145, 72,
0221 3., 2., {32u, 14u});
0222
0223 auto barrelSurfaces = std::make_shared<
0224 Acts::Experimental::LayerStructureBuilder::SurfacesHolder>(
0225 unpackSurfaces(cSurfaces));
0226
0227
0228 Acts::Experimental::LayerStructureBuilder::Config lsConfig;
0229 lsConfig.auxiliary = "*** Barrel with 448 surfaces ***";
0230 lsConfig.surfacesProvider = barrelSurfaces;
0231 lsConfig.binnings = {
0232 {Acts::DirectedProtoAxis(Acts::AxisDirection::AxisZ,
0233 Acts::AxisBoundaryType::Bound, -480., 480., 14u),
0234 1u},
0235 {Acts::DirectedProtoAxis(Acts::AxisDirection::AxisPhi,
0236 Acts::AxisBoundaryType::Closed,
0237 -std::numbers::pi, std::numbers::pi, 32u),
0238 1u}};
0239
0240 auto barrelBuilder =
0241 std::make_shared<Acts::Experimental::LayerStructureBuilder>(
0242 lsConfig, Acts::getDefaultLogger("BarrelInternalsBuilder",
0243 Acts::Logging::VERBOSE));
0244
0245 Acts::Experimental::VolumeStructureBuilder::Config shapeConfig;
0246 shapeConfig.boundValues = {60., 80., 800., std::numbers::pi, 0.};
0247 shapeConfig.boundsType = Acts::VolumeBounds::BoundsType::eCylinder;
0248
0249 auto shapeBuilder =
0250 std::make_shared<Acts::Experimental::VolumeStructureBuilder>(
0251 shapeConfig,
0252 Acts::getDefaultLogger("BarrelShapeBuilder", Acts::Logging::VERBOSE));
0253
0254 Acts::Experimental::DetectorVolumeBuilder::Config dvCfg;
0255 dvCfg.auxiliary = "*** Test 1 - Cylinder with internal Surface ***";
0256 dvCfg.name = "BarrelWithSurfaces";
0257 dvCfg.externalsBuilder = shapeBuilder;
0258 dvCfg.internalsBuilder = barrelBuilder;
0259
0260 auto dvBuilder = std::make_shared<Acts::Experimental::DetectorVolumeBuilder>(
0261 dvCfg, Acts::getDefaultLogger("EndcapBuilder", Acts::Logging::VERBOSE));
0262
0263 auto [volumes, portals, roots] = dvBuilder->construct(tContext);
0264
0265 auto volume = volumes.front();
0266
0267 auto jVolume = Acts::DetectorVolumeJsonConverter::toJson(tContext, *volume,
0268 {volume.get()});
0269
0270 std::ofstream out;
0271 out.open("barrel-volume-with-surfaces.json");
0272 out << jVolume.dump(4);
0273 out.close();
0274
0275 auto in = std::ifstream("barrel-volume-with-surfaces.json",
0276 std::ifstream::in | std::ifstream::binary);
0277
0278 BOOST_CHECK(in.good());
0279 nlohmann::json jVolumeIn;
0280 in >> jVolumeIn;
0281 in.close();
0282
0283 auto volumeIn =
0284 Acts::DetectorVolumeJsonConverter::fromJson(tContext, jVolumeIn);
0285
0286 BOOST_CHECK_EQUAL(volumeIn->name(), volume->name());
0287 BOOST_CHECK(
0288 volumeIn->transform(tContext).isApprox(volume->transform(tContext)));
0289 BOOST_CHECK_EQUAL(volumeIn->surfaces().size(), volume->surfaces().size());
0290 BOOST_CHECK_EQUAL(volumeIn->volumes().size(), volume->volumes().size());
0291
0292
0293 jVolume = Acts::DetectorVolumeJsonConverter::toJson(tContext, *volumeIn,
0294 {volumeIn.get()});
0295 out.open("barrel-volume-with-surfaces-closure.json");
0296 out << jVolume.dump(4);
0297 out.close();
0298 }
0299
0300 BOOST_AUTO_TEST_SUITE_END()