File indexing completed on 2025-07-09 07:51:05
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/Definitions/Units.hpp"
0013 #include "Acts/Geometry/DetectorElementBase.hpp"
0014 #include "Acts/Geometry/Extent.hpp"
0015 #include "Acts/Geometry/GeometryContext.hpp"
0016 #include "Acts/Geometry/ProtoLayer.hpp"
0017 #include "Acts/Surfaces/PlaneSurface.hpp"
0018 #include "Acts/Surfaces/RectangleBounds.hpp"
0019 #include "Acts/Surfaces/Surface.hpp"
0020 #include "Acts/Tests/CommonHelpers/DetectorElementStub.hpp"
0021 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0022 #include "Acts/Utilities/BinningType.hpp"
0023 #include "Acts/Utilities/RangeXD.hpp"
0024
0025 #include <cmath>
0026 #include <memory>
0027 #include <numbers>
0028 #include <sstream>
0029 #include <string>
0030 #include <vector>
0031
0032 namespace Acts::Test::Layers {
0033
0034 GeometryContext tgContext = GeometryContext();
0035
0036 BOOST_AUTO_TEST_SUITE(Geometry)
0037
0038
0039 template <bool IsConst>
0040 void testProtoLayer() {
0041 using enum AxisDirection;
0042 using TestProtoLayer = detail::ProtoLayerT<IsConst>;
0043 using SurfacePtr = typename TestProtoLayer::SurfacePtr;
0044
0045
0046 auto recBounds = std::make_shared<RectangleBounds>(3., 6.);
0047
0048
0049 static const Transform3 planeYZ =
0050 AngleAxis3(std::numbers::pi / 2., Vector3::UnitY()) *
0051 AngleAxis3(std::numbers::pi / 2., Vector3::UnitZ()) *
0052 Transform3::Identity();
0053 static const Transform3 planeZX =
0054 AngleAxis3(-std::numbers::pi / 2., Vector3::UnitX()) *
0055 AngleAxis3(-std::numbers::pi / 2., Vector3::UnitZ()) *
0056 Transform3::Identity();
0057
0058 std::vector<
0059 std::shared_ptr<std::conditional_t<IsConst, const Surface, Surface>>>
0060 surfaceStore;
0061 surfaceStore.reserve(100);
0062
0063 auto createProtoLayer = [&](const Transform3& trf,
0064 bool shared = false) -> TestProtoLayer {
0065 auto atNegX = Surface::makeShared<PlaneSurface>(
0066 Transform3(trf * Translation3(Vector3(-3., 0., 0.)) * planeYZ),
0067 recBounds);
0068
0069 auto atPosX = Surface::makeShared<PlaneSurface>(
0070 Transform3(trf * Translation3(Vector3(3., 0., 0.)) * planeYZ),
0071 recBounds);
0072
0073 auto atNegY = Surface::makeShared<PlaneSurface>(
0074 Transform3(trf * Translation3(Vector3(0., -3, 0.)) * planeZX),
0075 recBounds);
0076
0077 auto atPosY = Surface::makeShared<PlaneSurface>(
0078 Transform3(trf * Translation3(Vector3(0., 3., 0.)) * planeZX),
0079 recBounds);
0080
0081 std::vector<
0082 std::shared_ptr<std::conditional_t<IsConst, const Surface, Surface>>>
0083 sharedSurfaces = {atNegX, atNegY, atPosX, atPosY};
0084 surfaceStore.insert(surfaceStore.begin(), sharedSurfaces.begin(),
0085 sharedSurfaces.end());
0086 if (!shared) {
0087 std::vector<SurfacePtr> surfaces = {atNegX.get(), atNegY.get(),
0088 atPosX.get(), atPosY.get()};
0089
0090 return TestProtoLayer(tgContext, surfaces);
0091 }
0092 return TestProtoLayer(tgContext, sharedSurfaces);
0093 };
0094
0095
0096 auto pLayerSf = createProtoLayer(Transform3::Identity());
0097 auto pLayerSfShared = createProtoLayer(Transform3::Identity());
0098
0099 BOOST_CHECK(pLayerSf.extent.range() == pLayerSfShared.extent.range());
0100 BOOST_CHECK(pLayerSf.envelope == pLayerSfShared.envelope);
0101
0102
0103 BOOST_CHECK_EQUAL(pLayerSf.surfaces().size(), 4);
0104
0105 auto rB = std::make_shared<RectangleBounds>(30., 60.);
0106
0107
0108 auto addSurface =
0109 Surface::makeShared<PlaneSurface>(Transform3::Identity(), rB);
0110
0111 pLayerSf.add(tgContext, *addSurface);
0112
0113 BOOST_CHECK_EQUAL(pLayerSf.surfaces().size(), 5);
0114
0115
0116 BOOST_CHECK(!(pLayerSf.extent.range() == pLayerSfShared.extent.range()));
0117
0118
0119 auto protoLayer = createProtoLayer(Transform3::Identity());
0120
0121 CHECK_CLOSE_ABS(protoLayer.range(AxisX), 12., 1e-8);
0122 CHECK_CLOSE_ABS(protoLayer.medium(AxisX), 0., 1e-8);
0123 CHECK_CLOSE_ABS(protoLayer.min(AxisX), -6., 1e-8);
0124 CHECK_CLOSE_ABS(protoLayer.max(AxisX), 6., 1e-8);
0125 CHECK_CLOSE_ABS(protoLayer.range(AxisY), 6., 1e-8);
0126 CHECK_CLOSE_ABS(protoLayer.medium(AxisY), 0., 1e-8);
0127 CHECK_CLOSE_ABS(protoLayer.min(AxisY), -3., 1e-8);
0128 CHECK_CLOSE_ABS(protoLayer.max(AxisY), 3., 1e-8);
0129 CHECK_CLOSE_ABS(protoLayer.range(AxisZ), 12., 1e-8);
0130 CHECK_CLOSE_ABS(protoLayer.medium(AxisZ), 0., 1e-8);
0131 CHECK_CLOSE_ABS(protoLayer.min(AxisZ), -6., 1e-8);
0132 CHECK_CLOSE_ABS(protoLayer.max(AxisZ), 6., 1e-8);
0133 CHECK_CLOSE_ABS(protoLayer.max(AxisR), std::hypot(3, 6), 1e-8);
0134 CHECK_CLOSE_ABS(protoLayer.min(AxisR), 3., 1e-8);
0135
0136
0137
0138 auto protoLayerRot = createProtoLayer(AngleAxis3(-0.345, Vector3::UnitZ()) *
0139 Transform3::Identity());
0140
0141 BOOST_CHECK_NE(protoLayer.min(AxisX), -6.);
0142 CHECK_CLOSE_ABS(protoLayerRot.medium(AxisX), 0., 1e-8);
0143 CHECK_CLOSE_ABS(protoLayerRot.medium(AxisY), 0., 1e-8);
0144 CHECK_CLOSE_ABS(protoLayerRot.range(AxisZ), 12., 1e-8);
0145 CHECK_CLOSE_ABS(protoLayerRot.medium(AxisZ), 0., 1e-8);
0146 CHECK_CLOSE_ABS(protoLayerRot.min(AxisZ), -6., 1e-8);
0147 CHECK_CLOSE_ABS(protoLayerRot.max(AxisZ), 6., 1e-8);
0148 CHECK_CLOSE_ABS(protoLayerRot.min(AxisR), 3., 1e-8);
0149 CHECK_CLOSE_ABS(protoLayerRot.max(AxisR), std::hypot(3, 6), 1e-8);
0150
0151 std::stringstream sstream;
0152 protoLayerRot.toStream(sstream);
0153 std::string oString = R"(ProtoLayer with dimensions (min/max)
0154 Extent in space :
0155 - value : AxisX | range = [-6.66104, 6.66104]
0156 - value : AxisY | range = [-4.85241, 4.85241]
0157 - value : AxisZ | range = [-6, 6]
0158 - value : AxisR | range = [3, 6.7082]
0159 - value : AxisPhi | range = [-3.02295, 2.33295]
0160 - value : AxisRPhi | range = [-20.2785, 15.6499]
0161 - value : AxisTheta | range = [0.61548, 2.52611]
0162 - value : AxisEta | range = [-1.14622, 1.14622]
0163 - value : AxisMag | range = [7.34847, 7.34847]
0164 )";
0165 BOOST_CHECK_EQUAL(sstream.str(), oString);
0166 }
0167
0168 BOOST_AUTO_TEST_CASE(ProtoLayerTests) {
0169 testProtoLayer<true>();
0170 }
0171
0172 BOOST_AUTO_TEST_CASE(ProtoLayerTestsNonConst) {
0173 testProtoLayer<false>();
0174 }
0175
0176 BOOST_AUTO_TEST_CASE(OrientedLayer) {
0177 using enum AxisDirection;
0178 using namespace Acts::UnitLiterals;
0179
0180 Transform3 base = Transform3::Identity();
0181
0182 auto recBounds = std::make_shared<RectangleBounds>(3_mm, 6_mm);
0183
0184 std::vector<std::unique_ptr<DetectorElementBase>> detectorElements;
0185
0186 auto makeFan = [&](double yrot, double thickness = 0) {
0187 detectorElements.clear();
0188
0189 std::size_t nSensors = 8;
0190 double deltaPhi = 2 * std::numbers::pi / nSensors;
0191 double r = 20_mm;
0192 std::vector<std::shared_ptr<const Surface>> surfaces;
0193 for (std::size_t i = 0; i < nSensors; i++) {
0194
0195
0196 Transform3 trf = base * AngleAxis3{yrot, Vector3::UnitY()} *
0197 AngleAxis3{deltaPhi * i, Vector3::UnitZ()} *
0198 Translation3(Vector3::UnitX() * r);
0199
0200 auto& element = detectorElements.emplace_back(
0201 std::make_unique<DetectorElementStub>(trf, recBounds, thickness));
0202
0203 surfaces.push_back(element->surface().getSharedPtr());
0204 }
0205 return surfaces;
0206 };
0207
0208 std::vector<std::shared_ptr<const Surface>> surfaces = makeFan(0_degree);
0209
0210 ProtoLayer protoLayer(tgContext, surfaces);
0211
0212 BOOST_CHECK_EQUAL(protoLayer.surfaces().size(), 8);
0213 BOOST_CHECK_CLOSE(protoLayer.min(AxisX), -23_mm, 1e-8);
0214 BOOST_CHECK_CLOSE(protoLayer.max(AxisX), 23_mm, 1e-8);
0215 BOOST_CHECK_CLOSE(protoLayer.min(AxisY), -23_mm, 1e-8);
0216 BOOST_CHECK_CLOSE(protoLayer.max(AxisY), 23_mm, 1e-8);
0217 BOOST_CHECK_CLOSE(protoLayer.min(AxisZ), 0_mm, 1e-8);
0218 BOOST_CHECK_CLOSE(protoLayer.max(AxisZ), 0_mm, 1e-8);
0219 BOOST_CHECK_CLOSE(protoLayer.min(AxisR), 17_mm, 1e-8);
0220 BOOST_CHECK_CLOSE(protoLayer.max(AxisR), 23.769728648_mm, 1e-8);
0221
0222 surfaces = makeFan(45_degree);
0223
0224
0225 protoLayer = {tgContext, surfaces};
0226
0227 BOOST_CHECK_EQUAL(protoLayer.surfaces().size(), 8);
0228 BOOST_CHECK_CLOSE(protoLayer.min(AxisX), -16.26345596_mm, 1e-4);
0229 BOOST_CHECK_CLOSE(protoLayer.max(AxisX), 16.26345596_mm, 1e-4);
0230 BOOST_CHECK_CLOSE(protoLayer.min(AxisY), -23_mm, 1e-8);
0231 BOOST_CHECK_CLOSE(protoLayer.max(AxisY), 23_mm, 1e-8);
0232 BOOST_CHECK_CLOSE(protoLayer.min(AxisZ), -16.26345596_mm, 1e-4);
0233 BOOST_CHECK_CLOSE(protoLayer.max(AxisZ), 16.26345596_mm, 1e-4);
0234
0235 protoLayer = {tgContext, surfaces,
0236 Transform3{AngleAxis3{45_degree, Vector3::UnitY()}}.inverse()};
0237
0238 BOOST_CHECK_EQUAL(protoLayer.surfaces().size(), 8);
0239 BOOST_CHECK_CLOSE(protoLayer.range(AxisX), 46_mm, 1e-8);
0240 BOOST_CHECK_CLOSE(protoLayer.min(AxisX), -23_mm, 1e-8);
0241 BOOST_CHECK_CLOSE(protoLayer.max(AxisX), 23_mm, 1e-8);
0242 BOOST_CHECK_CLOSE(protoLayer.range(AxisY), 46_mm, 1e-8);
0243 BOOST_CHECK_CLOSE(protoLayer.min(AxisY), -23_mm, 1e-8);
0244 BOOST_CHECK_CLOSE(protoLayer.max(AxisY), 23_mm, 1e-8);
0245 CHECK_SMALL(protoLayer.range(AxisZ), 1e-14);
0246 CHECK_SMALL(protoLayer.min(AxisZ), 1e-14);
0247 CHECK_SMALL(protoLayer.max(AxisZ), 1e-14);
0248
0249 surfaces = makeFan(0_degree, 10_mm);
0250
0251 protoLayer = {tgContext, surfaces};
0252
0253 BOOST_CHECK_EQUAL(protoLayer.surfaces().size(), 8);
0254 BOOST_CHECK_CLOSE(protoLayer.range(AxisX), 46_mm, 1e-8);
0255 BOOST_CHECK_CLOSE(protoLayer.min(AxisX), -23_mm, 1e-8);
0256 BOOST_CHECK_CLOSE(protoLayer.max(AxisX), 23_mm, 1e-8);
0257 BOOST_CHECK_CLOSE(protoLayer.range(AxisY), 46_mm, 1e-8);
0258 BOOST_CHECK_CLOSE(protoLayer.min(AxisY), -23_mm, 1e-8);
0259 BOOST_CHECK_CLOSE(protoLayer.max(AxisY), 23_mm, 1e-8);
0260 BOOST_CHECK_CLOSE(protoLayer.range(AxisZ), 10_mm, 1e-8);
0261 BOOST_CHECK_CLOSE(protoLayer.min(AxisZ), -5_mm, 1e-8);
0262 BOOST_CHECK_CLOSE(protoLayer.max(AxisZ), 5_mm, 1e-8);
0263
0264 surfaces = makeFan(45_degree, 10_mm);
0265
0266 protoLayer = {tgContext, surfaces,
0267 Transform3{AngleAxis3{45_degree, Vector3::UnitY()}}.inverse()};
0268
0269 BOOST_CHECK_EQUAL(protoLayer.surfaces().size(), 8);
0270 BOOST_CHECK_CLOSE(protoLayer.range(AxisX), 46_mm, 1e-8);
0271 BOOST_CHECK_CLOSE(protoLayer.min(AxisX), -23_mm, 1e-8);
0272 BOOST_CHECK_CLOSE(protoLayer.max(AxisX), 23_mm, 1e-8);
0273 BOOST_CHECK_CLOSE(protoLayer.range(AxisY), 46_mm, 1e-8);
0274 BOOST_CHECK_CLOSE(protoLayer.min(AxisY), -23_mm, 1e-8);
0275 BOOST_CHECK_CLOSE(protoLayer.max(AxisY), 23_mm, 1e-8);
0276 BOOST_CHECK_CLOSE(protoLayer.range(AxisZ), 10_mm, 1e-8);
0277 BOOST_CHECK_CLOSE(protoLayer.min(AxisZ), -5_mm, 1e-8);
0278 BOOST_CHECK_CLOSE(protoLayer.max(AxisZ), 5_mm, 1e-8);
0279 }
0280
0281 BOOST_AUTO_TEST_SUITE_END()
0282
0283 }