Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-25 07:57:19

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/Detector/CylindricalContainerBuilder.hpp"
0012 #include "Acts/Detector/Detector.hpp"
0013 #include "Acts/Detector/DetectorBuilder.hpp"
0014 #include "Acts/Detector/detail/BlueprintDrawer.hpp"
0015 #include "Acts/Detector/detail/BlueprintHelper.hpp"
0016 #include "Acts/Geometry/GeometryContext.hpp"
0017 #include "Acts/Surfaces/Surface.hpp"
0018 #include "Acts/Surfaces/SurfaceBounds.hpp"
0019 #include "Acts/Utilities/Enumerate.hpp"
0020 #include "Acts/Utilities/Logger.hpp"
0021 #include "ActsPlugins/DD4hep/DD4hepBlueprintFactory.hpp"
0022 #include "ActsPlugins/DD4hep/DD4hepDetectorStructure.hpp"
0023 #include "ActsPlugins/DD4hep/DD4hepDetectorSurfaceFactory.hpp"
0024 #include "ActsPlugins/DD4hep/DD4hepLayerStructure.hpp"
0025 #include "ActsTests/CommonHelpers/CylindricalTrackingGeometry.hpp"
0026 
0027 #include <fstream>
0028 #include <string>
0029 
0030 #include <DD4hep/DetElement.h>
0031 #include <DD4hep/DetFactoryHelper.h>
0032 #include <DD4hep/Detector.h>
0033 #include <XML/Utilities.h>
0034 #include <XMLFragments.hpp>
0035 
0036 #include "DD4hepTestsHelper.hpp"
0037 
0038 using namespace Acts;
0039 using namespace ActsPlugins;
0040 
0041 namespace ActsTests {
0042 
0043 GeometryContext tContext;
0044 CylindricalTrackingGeometry cGeometry = CylindricalTrackingGeometry(tContext);
0045 
0046 const char* beampipe_head_xml =
0047     R""""(
0048     <detectors>
0049         <detector id="0" name="BeamPipe" type="BarrelDetector">
0050             <type_flags type="DetType_TRACKER + DetType_BEAMPIPE"/>
0051             <layers>
0052                 <layer id="0"  name="BeamPipeLayer">
0053 )"""";
0054 
0055 const char* nec_head_xml =
0056     R""""(
0057         <detector id="1" name="PixelNegativeEndcap" type="EndcapDetector" readout="PixelReadout">
0058             <type_flags type="DetType_TRACKER + DetType_BARREL"/>
0059 )"""";
0060 
0061 const char* barrel_head_xml =
0062     R""""(
0063         <detector id="2" name="PixelBarrel" type="BarrelDetector" readout="PixelReadout">
0064             <type_flags type="DetType_TRACKER + DetType_BARREL"/>
0065 )"""";
0066 
0067 const char* pec_head_xml =
0068     R""""(
0069         <detector id="3" name="PixelPositiveEndcap" type="EndcapDetector" readout="PixelReadout">
0070             <type_flags type="DetType_TRACKER + DetType_BARREL"/>
0071 )"""";
0072 
0073 const char* plugin_xml =
0074     R"""(<plugins>
0075     <plugin name="DD4hep_ParametersPlugin">
0076       <argument value="world"/>
0077       <argument value="acts_world: bool = true"/>
0078       <argument value="acts_world_type: int = 3"/>
0079       <argument value="acts_world_bvalues_n: int = 3"/>
0080       <argument value="acts_world_bvalues_0: double = 0"/>
0081       <argument value="acts_world_bvalues_1: double = 150*mm"/>
0082       <argument value="acts_world_bvalues_2: double = 1000*mm"/>
0083       <argument value="acts_world_binning: str = r"/>
0084       <argument value="acts_world_geo_id: str = incremental"/>
0085       <argument value="acts_world_root_volume_finder: str = indexed"/>
0086     </plugin>
0087     <plugin name="DD4hep_ParametersPlugin">
0088       <argument value="BeamPipe"/>
0089       <argument value="acts_volume: bool = true"/>
0090       <argument value="acts_volume_type: int = 3"/>
0091       <argument value="acts_volume_bvalues_n: int = 3"/>
0092       <argument value="acts_volume_bvalues_0: double = 0"/>
0093       <argument value="acts_volume_bvalues_1: double = 20*mm"/>
0094       <argument value="acts_volume_bvalues_2: double = 1000*mm"/>
0095       <argument value="acts_volume_internals: bool = true"/>
0096       <argument value="acts_volume_internals_type: str = layer"/>
0097     </plugin>
0098     <plugin name="DD4hep_ParametersPlugin">
0099       <argument value="Pixel"/>
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 = 1000*mm"/>
0106       <argument value="acts_container_binning: str = z"/>
0107     </plugin>
0108     <plugin name="DD4hep_ParametersPlugin">
0109       <argument value="PixelNegativeEndcap"/>
0110       <argument value="acts_container: bool = true"/>
0111       <argument value="acts_container_type: int = 3"/>
0112       <argument value="acts_container_bvalues_n: int = 3"/>
0113       <argument value="acts_container_bvalues_0: double = 20*mm"/>
0114       <argument value="acts_container_bvalues_1: double = 150*mm"/>
0115       <argument value="acts_container_bvalues_2: double = 200*mm"/>
0116       <argument value="acts_container_binning: str = z"/>
0117       <argument value="acts_container_z: double = -800*mm"/>
0118     </plugin>
0119     <plugin name="DD4hep_ParametersPlugin">
0120       <argument value="PixelBarrel"/>
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 = 600*mm"/>
0127       <argument value="acts_container_binning: str = r"/>
0128     </plugin>
0129     <plugin name="DD4hep_ParametersPlugin">
0130       <argument value="PixelPositiveEndcap"/>
0131       <argument value="acts_container: bool = true"/>
0132       <argument value="acts_container_type: int = 3"/>
0133       <argument value="acts_container_bvalues_n: int = 3"/>
0134       <argument value="acts_container_bvalues_0: double = 20*mm"/>
0135       <argument value="acts_container_bvalues_1: double = 150*mm"/>
0136       <argument value="acts_container_bvalues_2: double = 200*mm"/>
0137       <argument value="acts_container_binning: str = z"/>
0138       <argument value="acts_container_z: double = 800*mm"/>
0139     </plugin>
0140   </plugins>
0141   )""";
0142 
0143 const std::string indent_4_xml(4, ' ');
0144 const std::string indent_8_xml(8, ' ');
0145 const std::string indent_12_xml(12, ' ');
0146 
0147 CylindricalTrackingGeometry::DetectorStore generateXML() {
0148   CylindricalTrackingGeometry::DetectorStore dStore;
0149 
0150   // Nec surfaces
0151   double necZ = -800.;
0152   auto necR0Surfaces = cGeometry.surfacesRing(dStore, 6.4, 12.4, 18., 0.125, 0.,
0153                                               42., necZ, 2., 22u);
0154 
0155   auto necR1Surfaces = cGeometry.surfacesRing(dStore, 12.4, 20.4, 30., 0.125,
0156                                               0., 80., necZ, 2., 22u);
0157 
0158   std::vector<std::vector<Surface*>> necSurfaces = {necR0Surfaces,
0159                                                     necR1Surfaces};
0160 
0161   // Barrel surfaces
0162   std::vector<std::array<double, 2u>> innerOuter = {
0163       {25., 35.}, {65., 75.}, {110., 120.}};
0164   auto b0Surfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.14,
0165                                                31., 3., 2., {16, 14});
0166 
0167   auto b1Surfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.14,
0168                                                71., 3., 2., {32, 14});
0169 
0170   auto b2Surfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.14,
0171                                                116., 3., 2., {52, 14});
0172 
0173   std::vector<std::vector<Surface*>> barrelSurfaces = {b0Surfaces, b1Surfaces,
0174                                                        b2Surfaces};
0175 
0176   // Nec surfaces
0177   double pecZ = 800.;
0178   auto pecR0Surfaces = cGeometry.surfacesRing(dStore, 6.4, 12.4, 18., 0.125, 0.,
0179                                               42., pecZ, 2., 22u);
0180 
0181   auto pecR1Surfaces = cGeometry.surfacesRing(dStore, 12.4, 20.4, 30., 0.125,
0182                                               0., 80., pecZ, 2., 22u);
0183 
0184   std::vector<std::vector<Surface*>> pecSurfaces = {pecR0Surfaces,
0185                                                     pecR1Surfaces};
0186 
0187   // Create an XML from it
0188   std::ofstream cxml;
0189   cxml.open("CylindricalDetector.xml");
0190   cxml << head_xml;
0191   cxml << segmentation_xml;
0192 
0193   // Add the beam pipe first
0194   cxml << beampipe_head_xml << '\n';
0195   cxml << indent_12_xml << "<acts_passive_surface>" << '\n';
0196   cxml << indent_12_xml
0197        << "<tubs rmin=\"19*mm\" rmax=\"20*mm\" dz=\"800*mm\" "
0198           "material=\"Air\"/>"
0199        << '\n';
0200   cxml << indent_12_xml << "</acts_passive_surface>" << '\n';
0201   cxml << indent_12_xml << "</layer> " << '\n';
0202   cxml << indent_8_xml << "</layers>" << '\n';
0203   cxml << indent_8_xml << "</detector>" << '\n';
0204 
0205   // Declare the assembly
0206   const char* pixel_assembly_xml =
0207       R"""(<detector id="4" name="Pixel" type="DD4hep_SubdetectorAssembly" vis="invisible">
0208             <shape name="PixelVolume" type="Tube" rmin="20*mm" rmax="150*mm" dz="1000*mm" material="Air"/>
0209             <composite name="PixelNegativeEndcap"/>
0210             <composite name="PixelBarrel"/>
0211             <composite name="PixelPositiveEndcap"/>
0212         </detector>)""";
0213 
0214   cxml << pixel_assembly_xml << '\n';
0215   cxml << "</detectors>" << '\n';
0216 
0217   // The Pixel detector
0218 
0219   // Nec - 1 Layer only
0220   cxml << "<detectors>" << '\n';
0221 
0222   cxml << nec_head_xml << '\n';
0223   cxml << indent_8_xml << "<layers>" << '\n';
0224   cxml << indent_8_xml << "<acts_container/> " << '\n';
0225   cxml << indent_4_xml << "<layer name=\"NegEndcapLayer_0\" id=\"0\">" << '\n';
0226   cxml << indent_4_xml << "<acts_volume dz=\"20*mm\" cz=\"-800.*mm\"/>" << '\n';
0227   cxml << indent_8_xml << "<modules>" << '\n';
0228   for (const auto& ring : necSurfaces) {
0229     for (const auto& s : ring) {
0230       cxml << indent_12_xml
0231            << DD4hepTestsHelper::surfaceToXML(tContext, *s,
0232                                               Transform3::Identity())
0233            << "\n";
0234     }
0235   }
0236   cxml << indent_8_xml << "</modules>" << '\n';
0237   cxml << indent_8_xml << "</layer> " << '\n';
0238   cxml << indent_8_xml << "</layers>" << '\n';
0239   cxml << indent_8_xml << "</detector>" << '\n';
0240 
0241   // Barrel
0242   cxml << barrel_head_xml << '\n';
0243   cxml << indent_8_xml << "<layers>" << '\n';
0244   cxml << indent_8_xml << "<acts_container/> " << '\n';
0245   for (const auto [ib, bs] : enumerate(barrelSurfaces)) {
0246     cxml << indent_4_xml << "<layer name=\"PixelBarrel_" << ib << "\" id=\""
0247          << ib << "\">" << '\n';
0248     cxml << indent_4_xml << "<acts_volume rmin=\"" << innerOuter[ib][0u]
0249          << "*mm\" rmax=\"" << innerOuter[ib][1u] << "*mm\"/>";
0250     cxml << indent_8_xml << "<modules>" << '\n';
0251     for (const auto& s : bs) {
0252       cxml << indent_12_xml
0253            << DD4hepTestsHelper::surfaceToXML(tContext, *s,
0254                                               Transform3::Identity())
0255            << "\n";
0256     }
0257     cxml << indent_8_xml << "</modules>" << '\n';
0258     cxml << indent_8_xml << "</layer>" << '\n';
0259   }
0260   cxml << indent_8_xml << "</layers>" << '\n';
0261   cxml << indent_8_xml << "</detector>" << '\n';
0262 
0263   // Pec - 1 layer only
0264   cxml << pec_head_xml << '\n';
0265   cxml << indent_8_xml << "<layers>" << '\n';
0266   cxml << indent_8_xml << "<acts_container/> " << '\n';
0267   cxml << indent_4_xml << "<layer name=\"PosEndcapLayer_0\" id=\"0\">" << '\n';
0268   cxml << indent_4_xml << "<acts_volume dz=\"20*mm\" cz=\"800.*mm\"/>" << '\n';
0269   cxml << indent_8_xml << "<modules>" << '\n';
0270   for (const auto& ring : pecSurfaces) {
0271     for (const auto& s : ring) {
0272       cxml << indent_12_xml
0273            << DD4hepTestsHelper::surfaceToXML(tContext, *s,
0274                                               Transform3::Identity())
0275            << "\n";
0276     }
0277   }
0278   cxml << indent_8_xml << "</modules>" << '\n';
0279   cxml << indent_8_xml << "</layer> " << '\n';
0280   cxml << indent_8_xml << "</layers>" << '\n';
0281   cxml << indent_8_xml << "</detector>" << '\n';
0282   cxml << indent_8_xml << "</detectors>" << '\n';
0283 
0284   cxml << plugin_xml << '\n';
0285   cxml << end_xml << '\n';
0286   cxml.close();
0287 
0288   return dStore;
0289 }
0290 
0291 auto store = generateXML();
0292 
0293 BOOST_AUTO_TEST_SUITE(DD4hepSuite)
0294 
0295 BOOST_AUTO_TEST_CASE(DD4hepCylidricalDetectorExplicit) {
0296   auto lcdd = &(dd4hep::Detector::getInstance());
0297   lcdd->fromCompact("CylindricalDetector.xml");
0298   lcdd->volumeManager();
0299   lcdd->apply("DD4hepVolumeManager", 0, nullptr);
0300 
0301   auto world = lcdd->world();
0302 
0303   // Test starts here
0304   DD4hepDetectorSurfaceFactory::Config sFactoryConfig;
0305   auto surfaceFactory = std::make_shared<DD4hepDetectorSurfaceFactory>(
0306       sFactoryConfig,
0307       getDefaultLogger("DD4hepDetectorSurfaceFactory", Logging::VERBOSE));
0308 
0309   auto layerStructure = std::make_shared<DD4hepLayerStructure>(
0310       std::move(surfaceFactory),
0311       getDefaultLogger("DD4hepLayerStructure", Logging::VERBOSE));
0312 
0313   DD4hepBlueprintFactory::Config bpCfg{layerStructure};
0314   DD4hepBlueprintFactory::Cache bpCache;
0315 
0316   DD4hepBlueprintFactory bp(
0317       bpCfg, getDefaultLogger("DD4hepBlueprintFactory", Logging::VERBOSE));
0318   auto dd4hepBlueprint = bp.create(bpCache, tContext, world);
0319 
0320   // We should have 6 store entries now
0321   // 1 : beam pipe (empty)
0322   // 1 : endcap
0323   // 2 : barrel
0324   // 1 : endcap
0325   BOOST_CHECK_EQUAL(bpCache.dd4hepStore.size(), 6u);
0326 
0327   // Now fill the gaps
0328   Experimental::detail::BlueprintHelper::fillGaps(*dd4hepBlueprint);
0329 
0330   // dot -P -Tsvg -o plugins.svg
0331   std::ofstream cbp("cylindrical_detector_dd4hep.dot");
0332   Experimental::detail::BlueprintDrawer::dotStream(cbp, *dd4hepBlueprint);
0333   cbp.close();
0334 
0335   // Create a Cylindrical detector builder from this blueprint
0336   auto detectorBuilder =
0337       std::make_shared<Experimental::CylindricalContainerBuilder>(
0338           *dd4hepBlueprint, Logging::VERBOSE);
0339 
0340   // Detector builder
0341   Experimental::DetectorBuilder::Config dCfg;
0342   dCfg.auxiliary =
0343       "*** Test : auto generated cylindrical detector builder  ***";
0344   dCfg.name = "Cylindrical detector from blueprint";
0345   dCfg.builder = detectorBuilder;
0346   dCfg.geoIdGenerator = dd4hepBlueprint->geoIdGenerator;
0347 
0348   auto detector = Experimental::DetectorBuilder(dCfg).construct(tContext);
0349 
0350   // Detector construction check
0351   BOOST_REQUIRE_NE(detector, nullptr);
0352   // We should have 14 volumes
0353   // 1 : beampipe
0354   // 3 : negative encap
0355   // 7 : barrel
0356   // 3 : positive encap
0357   BOOST_CHECK_EQUAL(detector->volumes().size(), 14u);
0358 
0359   // Kill that instance before going into the next test
0360   lcdd->destroyInstance();
0361 }
0362 
0363 BOOST_AUTO_TEST_CASE(DD4hepCylidricalDetectorStructure) {
0364   auto lcdd = &(dd4hep::Detector::getInstance());
0365   lcdd->fromCompact("CylindricalDetector.xml");
0366   lcdd->volumeManager();
0367   lcdd->apply("DD4hepVolumeManager", 0, nullptr);
0368 
0369   auto world = lcdd->world();
0370 
0371   DD4hepDetectorStructure::Options dsOptions;
0372   dsOptions.logLevel = Logging::VERBOSE;
0373   dsOptions.emulateToGraph = "cylindrical_detector_structure";
0374 
0375   auto [detectorEm, detectorStoreEm] =
0376       DD4hepDetectorStructure(
0377           getDefaultLogger("DD4hepDetectorStructure", Logging::VERBOSE))
0378           .construct(tContext, world, dsOptions);
0379 
0380   // Detector construction : no detector constructed, as we have only
0381   // emulated the grapth writing
0382   BOOST_CHECK_EQUAL(detectorEm, nullptr);
0383 
0384   // Now build in non-emulation mode
0385   dsOptions.emulateToGraph = "";
0386   auto [detector, detectorStore] =
0387       DD4hepDetectorStructure(
0388           getDefaultLogger("DD4hepDetectorStructure", Logging::VERBOSE))
0389           .construct(tContext, world, dsOptions);
0390 
0391   BOOST_REQUIRE_NE(detector, nullptr);
0392 
0393   // We should have 14 volumes
0394   // 1 : beampipe
0395   // 3 : negative endcap
0396   // 7 : barrel
0397   // 3 : positive endcap
0398   BOOST_CHECK_EQUAL(detector->volumes().size(), 14u);
0399 
0400   // We should have 6 store entries now
0401   // 1 : beam pipe (empty)
0402   // 1 : endcap
0403   // 3 : barrel
0404   // 1 : endcap
0405   BOOST_CHECK_EQUAL(detectorStore.size(), 6u);
0406 
0407   int elements = 0;
0408   for (const auto& [key, value] : detectorStore) {
0409     elements += value.size();
0410   }
0411 
0412   // There should be 1488 elements
0413   // NegEndcapLayer_0 has : 44 detector elements.
0414   // PixelBarrel_0 has : 224 detector elements.
0415   // PixelBarrel_1 has : 448 detector elements.
0416   // PixelBarrel_2 has : 728 detector elements.
0417   // PosEndcapLayer_0 has : 44 detector elements.
0418   BOOST_CHECK_EQUAL(elements, 1488);
0419 
0420   // Cross-check with the surfaces
0421   int surfaces = 0;
0422   for (const auto& v : detector->volumes()) {
0423     surfaces += v->surfaces().size();
0424   }
0425   // Sensitives + 1 (beampipe)
0426   BOOST_CHECK_EQUAL(surfaces, 1489);
0427 
0428   // Kill that instance before going into the next test
0429   lcdd->destroyInstance();
0430 }
0431 
0432 BOOST_AUTO_TEST_SUITE_END()
0433 
0434 }  // namespace ActsTests