Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-09 07:51:05

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
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 // Test both const and non-const versions
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   // Create a proto layer with 4 surfaces on the x/y grid
0046   auto recBounds = std::make_shared<RectangleBounds>(3., 6.);
0047 
0048   // Planar definitions to help construct the boundary surfaces
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   // Test 0 - check constructor with surfaces and shared surfaces
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   // CHECK That you have 4 surfaces
0103   BOOST_CHECK_EQUAL(pLayerSf.surfaces().size(), 4);
0104   // Add one surface from a detector element (to test thickness)
0105   auto rB = std::make_shared<RectangleBounds>(30., 60.);
0106 
0107   // Create the detector element
0108   auto addSurface =
0109       Surface::makeShared<PlaneSurface>(Transform3::Identity(), rB);
0110 
0111   pLayerSf.add(tgContext, *addSurface);
0112   // CHECK That if you now have 5 surfaces
0113   BOOST_CHECK_EQUAL(pLayerSf.surfaces().size(), 5);
0114 
0115   // That should invalidate the ranges
0116   BOOST_CHECK(!(pLayerSf.extent.range() == pLayerSfShared.extent.range()));
0117 
0118   // Test 1 - identity transform
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   // Test 2 - rotate around Z-Axis, should leave R, Z untouched,
0137   // only preserves medium values
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>();  // Test const version
0170 }
0171 
0172 BOOST_AUTO_TEST_CASE(ProtoLayerTestsNonConst) {
0173   testProtoLayer<false>();  // Test non-const version
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       // Create a fan of sensors
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   // Do NOT provide rotation matrix: sizing will be affected
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 }  // namespace Acts::Test::Layers