Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-22 07:53:41

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/Detector/DetectorVolume.hpp"
0013 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0014 #include "Acts/Geometry/GeometryContext.hpp"
0015 #include "Acts/Surfaces/CylinderBounds.hpp"
0016 #include "Acts/Surfaces/CylinderSurface.hpp"
0017 #include "Acts/Surfaces/Surface.hpp"
0018 #include "Acts/Utilities/BinningType.hpp"
0019 #include "Acts/Utilities/Enumerate.hpp"
0020 #include "Acts/Utilities/Logger.hpp"
0021 #include "ActsPlugins/Detray/DetrayGeometryConverter.hpp"
0022 #include "ActsTests/CommonHelpers/CylindricalDetector.hpp"
0023 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0024 
0025 #include <memory>
0026 #include <numbers>
0027 #include <vector>
0028 
0029 #include <detray/io/frontend/payloads.hpp>
0030 
0031 using namespace Acts;
0032 using namespace Acts::Experimental;
0033 using namespace ActsPlugins;
0034 
0035 GeometryContext tContext;
0036 
0037 auto logger = getDefaultLogger("DetrayGeometryConverterTests", Logging::INFO);
0038 
0039 namespace ActsTests {
0040 
0041 BOOST_AUTO_TEST_SUITE(DetraySuite)
0042 
0043 BOOST_AUTO_TEST_CASE(DetrayTransformConversion) {
0044   auto transform = Transform3::Identity();
0045   transform.pretranslate(Vector3(1., 2., 3.));
0046   transform.rotate(Eigen::AngleAxisd(std::numbers::pi / 2., Vector3::UnitZ()));
0047 
0048   detray::io::transform_payload payload =
0049       DetrayGeometryConverter::convertTransform(transform);
0050   // Transform is correctly translated
0051   CHECK_CLOSE_ABS(payload.tr[0u], 1., std::numeric_limits<double>::epsilon());
0052   CHECK_CLOSE_ABS(payload.tr[1u], 2., std::numeric_limits<double>::epsilon());
0053   CHECK_CLOSE_ABS(payload.tr[2u], 3., std::numeric_limits<double>::epsilon());
0054   // Rotation is correctly translated
0055   RotationMatrix3 rotation = transform.rotation().transpose();
0056   CHECK_CLOSE_ABS(payload.rot[0u], rotation(0, 0),
0057                   std::numeric_limits<double>::epsilon());
0058   CHECK_CLOSE_ABS(payload.rot[1u], rotation(0, 1),
0059                   std::numeric_limits<double>::epsilon());
0060   CHECK_CLOSE_ABS(payload.rot[2u], rotation(0, 2),
0061                   std::numeric_limits<double>::epsilon());
0062   CHECK_CLOSE_ABS(payload.rot[3u], rotation(1, 0),
0063                   std::numeric_limits<double>::epsilon());
0064   CHECK_CLOSE_ABS(payload.rot[4u], rotation(1, 1),
0065                   std::numeric_limits<double>::epsilon());
0066   CHECK_CLOSE_ABS(payload.rot[5u], rotation(1, 2),
0067                   std::numeric_limits<double>::epsilon());
0068   CHECK_CLOSE_ABS(payload.rot[6u], rotation(2, 0),
0069                   std::numeric_limits<double>::epsilon());
0070   CHECK_CLOSE_ABS(payload.rot[7u], rotation(2, 1),
0071                   std::numeric_limits<double>::epsilon());
0072   CHECK_CLOSE_ABS(payload.rot[8u], rotation(2, 2),
0073                   std::numeric_limits<double>::epsilon());
0074 }
0075 
0076 BOOST_AUTO_TEST_CASE(DetrayMaskConversion) {
0077   // Placeholder, masks are tested for the moment through the DetrayJsonHelper,
0078   // this code will move over here when the "toJsonDetray" will become
0079   // deprecated
0080 }
0081 
0082 BOOST_AUTO_TEST_CASE(DetraySurfaceConversion) {
0083   // Translate a cylinder
0084   auto cylinderSurface = Surface::makeShared<CylinderSurface>(
0085       Transform3::Identity(), std::make_shared<CylinderBounds>(20., 100.));
0086 
0087   auto sgID = GeometryIdentifier().withSensitive(1);
0088   cylinderSurface->assignGeometryId(sgID);
0089 
0090   detray::io::surface_payload payload = DetrayGeometryConverter::convertSurface(
0091       tContext, *cylinderSurface, false);
0092 
0093   // Check the payload
0094   BOOST_CHECK(!payload.index_in_coll.has_value());
0095   BOOST_CHECK(payload.masks.at(0).shape == detray::io::shape_id::cylinder2);
0096   BOOST_CHECK_EQUAL(payload.source, sgID.value());
0097   BOOST_CHECK(payload.type == detray::surface_id::e_sensitive);
0098 }
0099 
0100 BOOST_AUTO_TEST_CASE(DetrayVolumeConversion) {
0101   auto beampipe = std::make_shared<
0102       CylindricalVolumeBuilder<CylinderSurface, CylinderBounds>>(
0103       Transform3::Identity(), CylinderVolumeBounds(0., 50., 400.),
0104       CylinderBounds(25., 380.), "BeamPipe");
0105 
0106   auto [volumes, portals, rootVolumes] = beampipe->construct(tContext);
0107   auto volume = volumes.front();
0108 
0109   std::vector<const Experimental::DetectorVolume*> dVolumes = {volume.get()};
0110   DetrayConversionUtils::Cache cCache(dVolumes);
0111 
0112   detray::io::volume_payload payload = DetrayGeometryConverter::convertVolume(
0113       cCache, tContext, *volume, *logger);
0114 
0115   // Check the volume payload
0116   BOOST_CHECK(payload.name == "BeamPipe");
0117   BOOST_CHECK(payload.type == detray::volume_id::e_cylinder);
0118   // 3 portals and 1 surface contained
0119   BOOST_CHECK_EQUAL(payload.surfaces.size(), 4u);
0120   // Let's count
0121   std::size_t nPortals = 0;
0122   for (auto& s : payload.surfaces) {
0123     if (s.type == detray::surface_id::e_portal) {
0124       nPortals++;
0125     }
0126   }
0127   BOOST_CHECK_EQUAL(nPortals, 3u);
0128   // No acceleration structure for the moment
0129   BOOST_CHECK(!payload.acc_links.has_value());
0130 }
0131 
0132 BOOST_AUTO_TEST_CASE(CylindricalDetector) {
0133   // Load the detector from the Test utilities
0134   auto detector = buildCylindricalDetector(tContext);
0135 
0136   // Convert the detector
0137   DetrayConversionUtils::Cache cCache(detector->volumes());
0138 
0139   detray::io::detector_payload payload =
0140       DetrayGeometryConverter::convertDetector(cCache, tContext, *detector,
0141                                                *logger);
0142 
0143   // Test the payload - we have six volumes
0144   BOOST_CHECK_EQUAL(payload.volumes.size(), 6u);
0145 
0146   // The first volume is the beam pipe volume
0147   BOOST_CHECK_EQUAL(payload.volumes[0].name, "BeamPipe");
0148   // The beam pipe should have 1 surface and 5 portals
0149   // the original cylinder cover is split into 3 portals
0150   BOOST_CHECK_EQUAL(payload.volumes[0].surfaces.size(), 6u);
0151   // The second volume should be the negative endcap
0152   BOOST_CHECK_EQUAL(payload.volumes[1].name, "NegativeEndcap");
0153   // The negative endcap should have 1 surface and 6 portals
0154   BOOST_CHECK_EQUAL(payload.volumes[1].surfaces.size(), 7u);
0155   // Barrel 0,1,2 follow
0156   BOOST_CHECK_EQUAL(payload.volumes[2].name, "Barrel0");
0157   BOOST_CHECK_EQUAL(payload.volumes[3].name, "Barrel1");
0158   BOOST_CHECK_EQUAL(payload.volumes[4].name, "Barrel2");
0159   // No portal splitting for those, hence we remain at 5 surfaces
0160   // i.e. 4 portals and one surface
0161   BOOST_CHECK_EQUAL(payload.volumes[2].surfaces.size(), 5u);
0162   BOOST_CHECK_EQUAL(payload.volumes[3].surfaces.size(), 5u);
0163   BOOST_CHECK_EQUAL(payload.volumes[4].surfaces.size(), 5u);
0164   // Finally the positive endcap
0165   BOOST_CHECK_EQUAL(payload.volumes[5].name, "PositiveEndcap");
0166   // The positive endcap should have again 1 surface and 6 portals
0167   BOOST_CHECK_EQUAL(payload.volumes[5].surfaces.size(), 7u);
0168 }
0169 
0170 BOOST_AUTO_TEST_SUITE_END()
0171 
0172 }  // namespace ActsTests