Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-03-30 07:47:07

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/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   // memory cleanup
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 }  // namespace ActsTests