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