Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:13:08

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