File indexing completed on 2026-03-30 07:47:07
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/Geometry/GeometryContext.hpp"
0013 #include "Acts/Surfaces/Surface.hpp"
0014 #include "ActsPlugins/DD4hep/DD4hepDetectorElement.hpp"
0015 #include "ActsPlugins/Root/TGeoAxes.hpp"
0016 #include "ActsTests/CommonHelpers/FloatComparisons.hpp"
0017
0018 #include <fstream>
0019 #include <iostream>
0020
0021 #include <DD4hep/DetElement.h>
0022 #include <DD4hep/Detector.h>
0023
0024 #include "DD4hep/DetFactoryHelper.h"
0025 #include "XML/Utilities.h"
0026 #include "XMLFragments.hpp"
0027
0028 using namespace Acts;
0029 using namespace ActsPlugins;
0030
0031 auto tContext = GeometryContext::dangerouslyDefaultConstruct();
0032
0033 const char* cylinder_xml =
0034 R""""(
0035 <detectors>
0036 <detector id="1" name="Cylinder" type="Cylinder">
0037 <type_flags type="DetType_TRACKER"/>
0038 <tubs name="Cylinder" rmin="10*cm" rmax="11*cm" dz="100*cm" material="Vacuum" sensitive="true"/>
0039 </detector>
0040 </detectors>
0041 )"""";
0042
0043 const char* sectoral_cylinder_xml =
0044 R""""(
0045 <detectors>
0046 <detector id="1" name="SectoralCylinder" type="Cylinder">
0047 <type_flags type="DetType_TRACKER"/>
0048 <tubs name="Cylinder" rmin="10*cm" rmax="11*cm" dz="100*cm" phimin="0.1*rad" phimax="0.8*rad" material="Vacuum" sensitive="true"/>
0049 </detector>
0050 </detectors>
0051 )"""";
0052
0053 const char* disc_xml =
0054 R""""(
0055 <detectors>
0056 <detector id="1" name="Disc" type="Disc">
0057 <type_flags type="DetType_TRACKER"/>
0058 <tubs name="Disc" rmin="10*cm" rmax="90*cm" dz="1*cm" material="Vacuum" sensitive="true"/>
0059 </detector>
0060 </detectors>
0061 )"""";
0062
0063 const char* sectoral_disc_xml =
0064 R""""(
0065 <detectors>
0066 <detector id="1" name="SectoralDisc" type="Disc">
0067 <type_flags type="DetType_TRACKER"/>
0068 <tubs name="Disc" rmin="10*cm" rmax="90*cm" dz="1*cm" phimin="0.*rad" phimax="1.5*rad" material="Vacuum" sensitive="true"/>
0069 </detector>
0070 </detectors>
0071 )"""";
0072
0073 const char* rectangle_xml =
0074 R""""(
0075 <detectors>
0076 <detector id="1" name="Rectangle" type="Rectangle">
0077 <type_flags type="DetType_TRACKER"/>
0078 <box name="Rectangle" dx="10*cm" dy="90*cm" dz="0.1*cm" cx="1.*cm" cy="2.*cm" cz="3.*cm" material="Vacuum" sensitive="true"/>
0079 </detector>
0080 </detectors>
0081 )"""";
0082
0083 const char* trapezoid_xml =
0084 R""""(
0085 <detectors>
0086 <detector id="1" name="Trapezoid" type="Trapezoid">
0087 <type_flags type="DetType_TRACKER"/>
0088 <trap name="Trapezoid" x1="10*cm" x2="20*cm" dy="30*cm" dz="0.1*cm" cx="2.*cm" cy="3.*cm" cz="4.*cm" material="Vacuum" sensitive="true"/>
0089 </detector>
0090 </detectors>
0091 )"""";
0092
0093 namespace ActsTests {
0094
0095 BOOST_AUTO_TEST_SUITE(DD4hepSuite)
0096
0097 BOOST_AUTO_TEST_CASE(DD4hepPluginDetectorElementCylinder) {
0098 std::ofstream cxml;
0099 cxml.open("Cylinder.xml");
0100 cxml << head_xml;
0101 cxml << cylinder_xml;
0102 cxml << end_xml;
0103 cxml.close();
0104
0105 auto lcdd = &(dd4hep::Detector::getInstance());
0106 lcdd->fromCompact("Cylinder.xml");
0107 lcdd->volumeManager();
0108 lcdd->apply("DD4hepVolumeManager", 0, nullptr);
0109
0110 auto world = lcdd->world();
0111
0112 std::shared_ptr<ActsPlugins::DD4hepDetectorElement> cylindricalElement =
0113 nullptr;
0114 for (const auto& [chn, child] : world.children()) {
0115 cylindricalElement = std::make_shared<ActsPlugins::DD4hepDetectorElement>(
0116 child, TGeoAxes{"XYZ"}, 10.);
0117 }
0118
0119 BOOST_REQUIRE_NE(cylindricalElement, nullptr);
0120
0121 const auto& surface = cylindricalElement->surface();
0122 BOOST_CHECK_EQUAL(surface.type(), Surface::SurfaceType::Cylinder);
0123 BOOST_CHECK(surface.localToGlobalTransform(tContext).isApprox(
0124 Transform3::Identity()));
0125 auto boundValues = surface.bounds().values();
0126 CHECK_CLOSE_ABS(boundValues[0u], 105., 1e-10);
0127 CHECK_CLOSE_ABS(boundValues[1u], 1000., 1e-10);
0128 lcdd->destroyInstance();
0129 }
0130
0131 BOOST_AUTO_TEST_CASE(DD4hepPluginDetectorElementSectoralCylinder) {
0132 std::ofstream cxml;
0133 cxml.open("SectoralCylinder.xml");
0134 cxml << head_xml;
0135 cxml << sectoral_cylinder_xml;
0136 cxml << end_xml;
0137 cxml.close();
0138
0139 auto lcdd = &(dd4hep::Detector::getInstance());
0140 lcdd->fromCompact("SectoralCylinder.xml");
0141 lcdd->volumeManager();
0142 lcdd->apply("DD4hepVolumeManager", 0, nullptr);
0143
0144 auto world = lcdd->world();
0145
0146 std::shared_ptr<ActsPlugins::DD4hepDetectorElement> cylindricalElement =
0147 nullptr;
0148 for (const auto& [chn, child] : world.children()) {
0149 cylindricalElement = std::make_shared<ActsPlugins::DD4hepDetectorElement>(
0150 child, TGeoAxes{"XYZ"}, 10.);
0151 }
0152
0153 BOOST_REQUIRE_NE(cylindricalElement, nullptr);
0154
0155 const auto& surface = cylindricalElement->surface();
0156 BOOST_CHECK_EQUAL(surface.type(), Surface::SurfaceType::Cylinder);
0157 BOOST_CHECK(surface.localToGlobalTransform(tContext).isApprox(
0158 Transform3::Identity()));
0159 auto boundValues = surface.bounds().values();
0160 CHECK_CLOSE_ABS(boundValues[0u], 105., 1e-10);
0161 CHECK_CLOSE_ABS(boundValues[1u], 1000., 1e-10);
0162 CHECK_CLOSE_ABS(boundValues[2u], 0.35, 1e-10);
0163 CHECK_CLOSE_ABS(boundValues[3u], 0.45, 1e-10);
0164 lcdd->destroyInstance();
0165 }
0166
0167 BOOST_AUTO_TEST_CASE(DD4hepPluginDetectorElementDisc) {
0168 std::ofstream cxml;
0169 cxml.open("Disc.xml");
0170 cxml << head_xml;
0171 cxml << disc_xml;
0172 cxml << end_xml;
0173 cxml.close();
0174
0175 auto lcdd = &(dd4hep::Detector::getInstance());
0176 lcdd->fromCompact("Disc.xml");
0177 lcdd->volumeManager();
0178 lcdd->apply("DD4hepVolumeManager", 0, nullptr);
0179
0180 auto world = lcdd->world();
0181
0182 std::shared_ptr<ActsPlugins::DD4hepDetectorElement> discElement = nullptr;
0183 for (const auto& [chn, child] : world.children()) {
0184 discElement = std::make_shared<ActsPlugins::DD4hepDetectorElement>(
0185 child, TGeoAxes{"XYZ"}, 10.);
0186 }
0187
0188 BOOST_REQUIRE_NE(discElement, nullptr);
0189
0190 const auto& surface = discElement->surface();
0191 BOOST_CHECK_EQUAL(surface.type(), Surface::SurfaceType::Disc);
0192 BOOST_CHECK(surface.localToGlobalTransform(tContext).isApprox(
0193 Transform3::Identity()));
0194 auto boundValues = surface.bounds().values();
0195 CHECK_CLOSE_ABS(boundValues[0u], 100., 1e-10);
0196 CHECK_CLOSE_ABS(boundValues[1u], 900., 1e-10);
0197 lcdd->destroyInstance();
0198 }
0199
0200 BOOST_AUTO_TEST_CASE(DD4hepPluginDetectorElementSectoralDisc) {
0201 std::ofstream cxml;
0202 cxml.open("SectoralDisc.xml");
0203 cxml << head_xml;
0204 cxml << sectoral_disc_xml;
0205 cxml << end_xml;
0206 cxml.close();
0207
0208 auto lcdd = &(dd4hep::Detector::getInstance());
0209 lcdd->fromCompact("SectoralDisc.xml");
0210 lcdd->volumeManager();
0211 lcdd->apply("DD4hepVolumeManager", 0, nullptr);
0212
0213 auto world = lcdd->world();
0214
0215 std::shared_ptr<ActsPlugins::DD4hepDetectorElement> discElement = nullptr;
0216 for (const auto& [chn, child] : world.children()) {
0217 discElement = std::make_shared<ActsPlugins::DD4hepDetectorElement>(
0218 child, TGeoAxes{"XYZ"}, 10.);
0219 }
0220
0221 BOOST_REQUIRE_NE(discElement, nullptr);
0222
0223 const auto& surface = discElement->surface();
0224 BOOST_CHECK_EQUAL(surface.type(), Surface::SurfaceType::Disc);
0225 BOOST_CHECK(surface.localToGlobalTransform(tContext).isApprox(
0226 Transform3::Identity()));
0227 auto boundValues = surface.bounds().values();
0228
0229 CHECK_CLOSE_ABS(boundValues[0u], 100., 1e-10);
0230 CHECK_CLOSE_ABS(boundValues[1u], 900., 1e-10);
0231 CHECK_CLOSE_ABS(boundValues[2u], 0.75, 1e-10);
0232 CHECK_CLOSE_ABS(boundValues[3u], 0.75, 1e-10);
0233 lcdd->destroyInstance();
0234 }
0235
0236 BOOST_AUTO_TEST_CASE(DD4hepPluginDetectorElementRectangle) {
0237 std::ofstream cxml;
0238 cxml.open("Rectangle.xml");
0239 cxml << head_xml;
0240 cxml << rectangle_xml;
0241 cxml << end_xml;
0242 cxml.close();
0243
0244 auto lcdd = &(dd4hep::Detector::getInstance());
0245 lcdd->fromCompact("Rectangle.xml");
0246 lcdd->volumeManager();
0247 lcdd->apply("DD4hepVolumeManager", 0, nullptr);
0248
0249 auto world = lcdd->world();
0250
0251 std::shared_ptr<ActsPlugins::DD4hepDetectorElement> rectangleElement =
0252 nullptr;
0253 for (const auto& [chn, child] : world.children()) {
0254 rectangleElement = std::make_shared<ActsPlugins::DD4hepDetectorElement>(
0255 child, TGeoAxes{"XYZ"}, 10.);
0256 }
0257
0258 BOOST_REQUIRE_NE(rectangleElement, nullptr);
0259
0260 Surface& surface = rectangleElement->surface();
0261 surface.assignGeometryId(GeometryIdentifier().withVolume(1).withLayer(2));
0262 BOOST_CHECK_EQUAL(surface.type(), Surface::SurfaceType::Plane);
0263
0264 auto sTransform = surface.localToGlobalTransform(tContext);
0265 BOOST_CHECK(sTransform.translation().isApprox(Vector3(10., 20., 30.)));
0266
0267 const auto& sBounds = surface.bounds();
0268 BOOST_CHECK_EQUAL(sBounds.type(), SurfaceBounds::BoundsType::eRectangle);
0269
0270 auto boundValues = sBounds.values();
0271
0272 CHECK_CLOSE_ABS(boundValues[0u], -50., 1e-10);
0273 CHECK_CLOSE_ABS(boundValues[1u], -450., 1e-10);
0274 CHECK_CLOSE_ABS(boundValues[2u], 50, 1e-10);
0275 CHECK_CLOSE_ABS(boundValues[3u], 450, 1e-10);
0276
0277
0278 lcdd->destroyInstance();
0279 }
0280
0281 BOOST_AUTO_TEST_CASE(DD4hepPluginDetectorElementTrapezoid) {
0282 std::ofstream cxml;
0283 cxml.open("Trapezoid.xml");
0284 cxml << head_xml;
0285 cxml << trapezoid_xml;
0286 cxml << end_xml;
0287 cxml.close();
0288
0289 auto lcdd = &(dd4hep::Detector::getInstance());
0290 lcdd->fromCompact("Trapezoid.xml");
0291 lcdd->volumeManager();
0292 lcdd->apply("DD4hepVolumeManager", 0, nullptr);
0293
0294 auto world = lcdd->world();
0295
0296 std::shared_ptr<ActsPlugins::DD4hepDetectorElement> trapezoidElement =
0297 nullptr;
0298 for (const auto& [chn, child] : world.children()) {
0299 trapezoidElement = std::make_shared<ActsPlugins::DD4hepDetectorElement>(
0300 child, TGeoAxes("xZy"), 10.);
0301 }
0302
0303 BOOST_REQUIRE_NE(trapezoidElement, nullptr);
0304
0305 const auto& surface = trapezoidElement->surface();
0306 BOOST_CHECK_EQUAL(surface.type(), Surface::SurfaceType::Plane);
0307
0308 auto sTransform = surface.localToGlobalTransform(tContext);
0309 BOOST_CHECK(sTransform.translation().isApprox(Vector3(20., 30., 40.)));
0310
0311 const auto& sBounds = surface.bounds();
0312 BOOST_CHECK_EQUAL(sBounds.type(), SurfaceBounds::BoundsType::eTrapezoid);
0313
0314 auto boundValues = sBounds.values();
0315 CHECK_CLOSE_ABS(boundValues[0u], 100., 1e-10);
0316 CHECK_CLOSE_ABS(boundValues[1u], 200., 1e-10);
0317 CHECK_CLOSE_ABS(boundValues[2u], 150, 1e-10);
0318
0319 lcdd->destroyInstance();
0320 }
0321
0322 BOOST_AUTO_TEST_SUITE_END()
0323
0324 }