Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-06-21 08:10:31

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/Plugins/DD4hep/DD4hepDetectorElement.hpp"
0014 #include "Acts/Plugins/DD4hep/DD4hepDetectorSurfaceFactory.hpp"
0015 #include "Acts/Surfaces/Surface.hpp"
0016 #include "Acts/Tests/CommonHelpers/CylindricalTrackingGeometry.hpp"
0017 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0018 
0019 #include <fstream>
0020 #include <iostream>
0021 
0022 #include <DD4hep/DetElement.h>
0023 #include <DD4hep/Detector.h>
0024 
0025 #include "DD4hep/DetFactoryHelper.h"
0026 #include "DD4hepTestsHelper.hpp"
0027 #include "XML/Utilities.h"
0028 #include "XMLFragments.hpp"
0029 
0030 namespace {
0031 Acts::GeometryContext tContext;
0032 Acts::Test::CylindricalTrackingGeometry cGeometry =
0033     Acts::Test::CylindricalTrackingGeometry(tContext);
0034 }  // namespace
0035 
0036 const char* beampipe_head_xml =
0037     R""""(
0038     <detectors>
0039         <detector id="0" name="BeamPipe" type="BarrelDetector">
0040             <type_flags type="DetType_TRACKER + DetType_BEAMPIPE"/>
0041             <layers>
0042                 <layer id="0"  name="BeamPipeLayer">
0043 )"""";
0044 
0045 const char* nec_head_xml =
0046     R""""(
0047         <detector id="1" name="PixelNegativeEndcap" type="EndcapDetector" readout="PixelReadout">
0048             <type_flags type="DetType_TRACKER + DetType_BARREL"/>
0049 )"""";
0050 
0051 const char* barrel_head_xml =
0052     R""""(
0053         <detector id="2" name="PixelBarrel" type="BarrelDetector" readout="PixelReadout">
0054             <type_flags type="DetType_TRACKER + DetType_BARREL"/>
0055 )"""";
0056 
0057 const char* pec_head_xml =
0058     R""""(
0059         <detector id="3" name="PixelPositiveEndcap" type="EndcapDetector" readout="PixelReadout">
0060             <type_flags type="DetType_TRACKER + DetType_BARREL"/>
0061 )"""";
0062 
0063 const char* plugin_xml =
0064     R"""(<plugins>
0065     <plugin name="DD4hep_ParametersPlugin">
0066       <argument value="world"/>
0067       <argument value="acts_world: bool = true"/>
0068       <argument value="acts_world_type: int = 3"/>
0069       <argument value="acts_world_bvalues_n: int = 3"/>
0070       <argument value="acts_world_bvalues_0: double = 0"/>
0071       <argument value="acts_world_bvalues_1: double = 150*mm"/>
0072       <argument value="acts_world_bvalues_2: double = 1000*mm"/>
0073       <argument value="acts_world_binning: str = r"/>
0074       <argument value="acts_world_geo_id: str = incremental"/>
0075       <argument value="acts_world_root_volume_finder: str = indexed"/>
0076     </plugin>
0077     <plugin name="DD4hep_ParametersPlugin">
0078       <argument value="BeamPipe"/>
0079       <argument value="acts_volume: bool = true"/>
0080       <argument value="acts_volume_type: int = 3"/>
0081       <argument value="acts_volume_bvalues_n: int = 3"/>
0082       <argument value="acts_volume_bvalues_0: double = 0"/>
0083       <argument value="acts_volume_bvalues_1: double = 20*mm"/>
0084       <argument value="acts_volume_bvalues_2: double = 1000*mm"/>
0085       <argument value="acts_volume_internals: bool = true"/>
0086       <argument value="acts_volume_internals_type: str = layer"/>
0087     </plugin>
0088     <plugin name="DD4hep_ParametersPlugin">
0089       <argument value="Pixel"/>
0090       <argument value="acts_container: bool = true"/>
0091       <argument value="acts_container_type: int = 3"/>
0092       <argument value="acts_container_bvalues_n: int = 3"/>
0093       <argument value="acts_container_bvalues_0: double = 20*mm"/>
0094       <argument value="acts_container_bvalues_1: double = 150*mm"/>
0095       <argument value="acts_container_bvalues_2: double = 1000*mm"/>
0096       <argument value="acts_container_binning: str = z"/>
0097     </plugin>
0098     <plugin name="DD4hep_ParametersPlugin">
0099       <argument value="PixelNegativeEndcap"/>
0100       <argument value="acts_container: bool = true"/>
0101       <argument value="acts_container_type: int = 3"/>
0102       <argument value="acts_container_bvalues_n: int = 3"/>
0103       <argument value="acts_container_bvalues_0: double = 20*mm"/>
0104       <argument value="acts_container_bvalues_1: double = 150*mm"/>
0105       <argument value="acts_container_bvalues_2: double = 200*mm"/>
0106       <argument value="acts_container_binning: str = z"/>
0107       <argument value="acts_container_z: double = -800*mm"/>
0108     </plugin>
0109     <plugin name="DD4hep_ParametersPlugin">
0110       <argument value="PixelBarrel"/>
0111       <argument value="acts_container: bool = true"/>
0112       <argument value="acts_container_type: int = 3"/>
0113       <argument value="acts_container_bvalues_n: int = 3"/>
0114       <argument value="acts_container_bvalues_0: double = 20*mm"/>
0115       <argument value="acts_container_bvalues_1: double = 150*mm"/>
0116       <argument value="acts_container_bvalues_2: double = 600*mm"/>
0117       <argument value="acts_container_binning: str = r"/>
0118     </plugin>
0119     <plugin name="DD4hep_ParametersPlugin">
0120       <argument value="PixelPositiveEndcap"/>
0121       <argument value="acts_container: bool = true"/>
0122       <argument value="acts_container_type: int = 3"/>
0123       <argument value="acts_container_bvalues_n: int = 3"/>
0124       <argument value="acts_container_bvalues_0: double = 20*mm"/>
0125       <argument value="acts_container_bvalues_1: double = 150*mm"/>
0126       <argument value="acts_container_bvalues_2: double = 200*mm"/>
0127       <argument value="acts_container_binning: str = z"/>
0128       <argument value="acts_container_z: double = 800*mm"/>
0129     </plugin>
0130   </plugins>
0131   )""";
0132 
0133 const std::string indent_4_xml(4, ' ');
0134 const std::string indent_8_xml(8, ' ');
0135 const std::string indent_12_xml(12, ' ');
0136 
0137 namespace {
0138 
0139 Acts::Test::CylindricalTrackingGeometry::DetectorStore generateXML() {
0140   Acts::Test::CylindricalTrackingGeometry::DetectorStore dStore;
0141 
0142   // Nec surfaces
0143   double necZ = -800.;
0144   auto necR0Surfaces = cGeometry.surfacesRing(dStore, 6.4, 12.4, 18., 0.125, 0.,
0145                                               42., necZ, 2., 22u);
0146 
0147   auto necR1Surfaces = cGeometry.surfacesRing(dStore, 12.4, 20.4, 30., 0.125,
0148                                               0., 80., necZ, 2., 22u);
0149 
0150   std::vector<std::vector<const Acts::Surface*>> necSurfaces = {necR0Surfaces,
0151                                                                 necR1Surfaces};
0152 
0153   // Barrel surfaces
0154   std::vector<std::array<double, 2u>> innerOuter = {
0155       {25., 35.}, {65., 75.}, {110., 120.}};
0156   auto b0Surfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.14,
0157                                                31., 3., 2., {16, 14});
0158 
0159   auto b1Surfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.14,
0160                                                71., 3., 2., {32, 14});
0161 
0162   auto b2Surfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.14,
0163                                                116., 3., 2., {52, 14});
0164 
0165   std::vector<std::vector<const Acts::Surface*>> barrelSurfaces = {
0166       b0Surfaces, b1Surfaces, b2Surfaces};
0167 
0168   // Nec surfaces
0169   double pecZ = 800.;
0170   auto pecR0Surfaces = cGeometry.surfacesRing(dStore, 6.4, 12.4, 18., 0.125, 0.,
0171                                               42., pecZ, 2., 22u);
0172 
0173   auto pecR1Surfaces = cGeometry.surfacesRing(dStore, 12.4, 20.4, 30., 0.125,
0174                                               0., 80., pecZ, 2., 22u);
0175 
0176   std::vector<std::vector<const Acts::Surface*>> pecSurfaces = {pecR0Surfaces,
0177                                                                 pecR1Surfaces};
0178 
0179   // Create an XML from it
0180   std::ofstream cxml;
0181   cxml.open("CylindricalDetectorTestSF.xml");
0182   cxml << head_xml;
0183   cxml << segmentation_xml;
0184 
0185   // Add the beam pipe first
0186   cxml << beampipe_head_xml << '\n';
0187   cxml << indent_12_xml << "<acts_passive_surface>" << '\n';
0188   cxml << indent_12_xml
0189        << "<tubs rmin=\"19*mm\" rmax=\"20*mm\" dz=\"800*mm\" "
0190           "material=\"Air\"/>"
0191        << '\n';
0192   cxml << indent_12_xml << "</acts_passive_surface>" << '\n';
0193   cxml << indent_12_xml << "</layer> " << '\n';
0194   cxml << indent_8_xml << "</layers>" << '\n';
0195   cxml << indent_8_xml << "</detector>" << '\n';
0196 
0197   // Declare the assembly
0198   const char* pixel_assembly_xml =
0199       R"""(<detector id="4" name="Pixel" type="DD4hep_SubdetectorAssembly" vis="invisible">
0200             <shape name="PixelVolume" type="Tube" rmin="20*mm" rmax="150*mm" dz="1000*mm" material="Air"/>
0201             <composite name="PixelNegativeEndcap"/>
0202             <composite name="PixelBarrel"/>
0203             <composite name="PixelPositiveEndcap"/>
0204         </detector>)""";
0205 
0206   cxml << pixel_assembly_xml << '\n';
0207   cxml << "</detectors>" << '\n';
0208 
0209   // The Pixel detector
0210 
0211   // Nec - 1 Layer only
0212   cxml << "<detectors>" << '\n';
0213 
0214   cxml << nec_head_xml << '\n';
0215   cxml << indent_8_xml << "<layers>" << '\n';
0216   cxml << indent_8_xml << "<acts_container/> " << '\n';
0217   cxml << indent_4_xml << "<layer name=\"NegEndcapLayer_0\" id=\"0\">" << '\n';
0218   cxml << indent_4_xml << "<acts_volume dz=\"20*mm\" cz=\"-800.*mm\"/>" << '\n';
0219   cxml << indent_8_xml << "<modules>" << '\n';
0220   for (const auto& ring : necSurfaces) {
0221     for (const auto& s : ring) {
0222       cxml << indent_12_xml
0223            << DD4hepTestsHelper::surfaceToXML(tContext, *s,
0224                                               Acts::Transform3::Identity())
0225            << "\n";
0226     }
0227   }
0228   cxml << indent_8_xml << "</modules>" << '\n';
0229   cxml << indent_8_xml << "</layer> " << '\n';
0230   cxml << indent_8_xml << "</layers>" << '\n';
0231   cxml << indent_8_xml << "</detector>" << '\n';
0232 
0233   // Barrel
0234   cxml << barrel_head_xml << '\n';
0235   cxml << indent_8_xml << "<layers>" << '\n';
0236   cxml << indent_8_xml << "<acts_container/> " << '\n';
0237   for (const auto [ib, bs] : Acts::enumerate(barrelSurfaces)) {
0238     cxml << indent_4_xml << "<layer name=\"PixelBarrel_" << ib << "\" id=\""
0239          << ib << "\">" << '\n';
0240     cxml << indent_4_xml << "<acts_volume rmin=\"" << innerOuter[ib][0u]
0241          << "*mm\" rmax=\"" << innerOuter[ib][1u] << "*mm\"/>";
0242     cxml << indent_8_xml << "<modules>" << '\n';
0243     for (const auto& s : bs) {
0244       cxml << indent_12_xml
0245            << DD4hepTestsHelper::surfaceToXML(tContext, *s,
0246                                               Acts::Transform3::Identity())
0247            << "\n";
0248     }
0249     cxml << indent_8_xml << "</modules>" << '\n';
0250     cxml << indent_8_xml << "</layer>" << '\n';
0251   }
0252   cxml << indent_8_xml << "</layers>" << '\n';
0253   cxml << indent_8_xml << "</detector>" << '\n';
0254 
0255   // Pec - 1 layer only
0256   cxml << pec_head_xml << '\n';
0257   cxml << indent_8_xml << "<layers>" << '\n';
0258   cxml << indent_8_xml << "<acts_container/> " << '\n';
0259   cxml << indent_4_xml << "<layer name=\"PosEndcapLayer_0\" id=\"0\">" << '\n';
0260   cxml << indent_4_xml << "<acts_volume dz=\"20*mm\" cz=\"800.*mm\"/>" << '\n';
0261   cxml << indent_8_xml << "<modules>" << '\n';
0262   for (const auto& ring : pecSurfaces) {
0263     for (const auto& s : ring) {
0264       cxml << indent_12_xml
0265            << DD4hepTestsHelper::surfaceToXML(tContext, *s,
0266                                               Acts::Transform3::Identity())
0267            << "\n";
0268     }
0269   }
0270   cxml << indent_8_xml << "</modules>" << '\n';
0271   cxml << indent_8_xml << "</layer> " << '\n';
0272   cxml << indent_8_xml << "</layers>" << '\n';
0273   cxml << indent_8_xml << "</detector>" << '\n';
0274   cxml << indent_8_xml << "</detectors>" << '\n';
0275 
0276   cxml << plugin_xml << '\n';
0277   cxml << end_xml << '\n';
0278   cxml.close();
0279 
0280   return dStore;
0281 }
0282 
0283 }  // namespace
0284 
0285 auto store = generateXML();
0286 
0287 BOOST_AUTO_TEST_SUITE(DD4hepPlugin)
0288 
0289 BOOST_AUTO_TEST_CASE(ConvertSensitivesDefault) {
0290   auto lcdd = &(dd4hep::Detector::getInstance());
0291   lcdd->fromCompact("CylindricalDetectorTestSF.xml");
0292   lcdd->volumeManager();
0293   lcdd->apply("DD4hepVolumeManager", 0, nullptr);
0294 
0295   auto world = lcdd->world();
0296 
0297   // Test starts here - with nonimal detector construction
0298   Acts::DD4hepDetectorSurfaceFactory::Config sFactoryConfig;
0299   auto surfaceFactory = Acts::DD4hepDetectorSurfaceFactory(
0300       sFactoryConfig, Acts::getDefaultLogger("DD4hepDetectorSurfaceFactory",
0301                                              Acts::Logging::VERBOSE));
0302 
0303   Acts::DD4hepDetectorSurfaceFactory::Cache sFactoryCache;
0304   Acts::DD4hepDetectorSurfaceFactory::Options sFactoryOptions;
0305 
0306   surfaceFactory.construct(sFactoryCache, tContext, world, sFactoryOptions);
0307   // Check the number of surfaces
0308   BOOST_CHECK_EQUAL(sFactoryCache.sensitiveSurfaces.size(), 1488u);
0309 
0310   // Kill that instance before going into the next test
0311   lcdd->destroyInstance();
0312 }
0313 
0314 BOOST_AUTO_TEST_CASE(ConvertSensitivesextended) {
0315   auto lcdd = &(dd4hep::Detector::getInstance());
0316   lcdd->fromCompact("CylindricalDetectorTestSF.xml");
0317   lcdd->volumeManager();
0318   lcdd->apply("DD4hepVolumeManager", 0, nullptr);
0319 
0320   auto world = lcdd->world();
0321 
0322   // A typical extension would be overriding the `tranform(const
0323   // GeometryContext&)` method in order change how the detector element is
0324   // handled in alignment, for simplicity here we show a simple extension that
0325   // overrides the  thickness
0326   class ExtendedDetectorElement : public Acts::DD4hepDetectorElement {
0327    public:
0328     using Acts::DD4hepDetectorElement::DD4hepDetectorElement;
0329 
0330     double thickness() const final {
0331       // Return a fixed thickness for testing purposes
0332       return 42. * Acts::UnitConstants::mm;
0333     }
0334   };
0335 
0336   auto extendedFactory =
0337       [](const dd4hep::DetElement& detElem, const std::string& axes,
0338          double scalor, bool isDisc,
0339          const std::shared_ptr<const Acts::ISurfaceMaterial>& material)
0340       -> std::shared_ptr<Acts::DD4hepDetectorElement> {
0341     return std::make_shared<ExtendedDetectorElement>(detElem, axes, scalor,
0342                                                      isDisc, material);
0343   };
0344 
0345   // Test starts here - with nonimal detector construction
0346   Acts::DD4hepDetectorSurfaceFactory::Config sFactoryConfig;
0347   sFactoryConfig.detectorElementFactory = extendedFactory;
0348   auto surfaceFactory = Acts::DD4hepDetectorSurfaceFactory(
0349       sFactoryConfig, Acts::getDefaultLogger("DD4hepDetectorSurfaceFactory",
0350                                              Acts::Logging::VERBOSE));
0351 
0352   Acts::DD4hepDetectorSurfaceFactory::Cache sFactoryCache;
0353   Acts::DD4hepDetectorSurfaceFactory::Options sFactoryOptions;
0354 
0355   surfaceFactory.construct(sFactoryCache, tContext, world, sFactoryOptions);
0356   // Check the number of surfaces
0357   BOOST_CHECK_EQUAL(sFactoryCache.sensitiveSurfaces.size(), 1488u);
0358   for (const auto& [detElem, surface] : sFactoryCache.sensitiveSurfaces) {
0359     // Check that the extended detector element is used
0360     BOOST_CHECK_NE(dynamic_cast<const ExtendedDetectorElement*>(detElem.get()),
0361                    nullptr);
0362     // Check that the thickness is 42 mm
0363     CHECK_CLOSE_ABS(detElem->thickness(), 42. * Acts::UnitConstants::mm, 1e-10);
0364   }
0365 
0366   // Kill that instance before going into the next test
0367   lcdd->destroyInstance();
0368 }
0369 
0370 BOOST_AUTO_TEST_SUITE_END()