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