File indexing completed on 2025-10-13 08:19:51
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/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
0039
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 }
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
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
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
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
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
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
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 }