Back to home page

EIC code displayed by LXR

 
 

    


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