Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-06-30 07:53:38

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/Geometry/GeometryContext.hpp"
0012 #include "Acts/Plugins/DD4hep/DD4hepDetectorSurfaceFactory.hpp"
0013 #include "Acts/Plugins/DD4hep/DD4hepLayerStructure.hpp"
0014 #include "Acts/Surfaces/SurfaceBounds.hpp"
0015 #include "Acts/Tests/CommonHelpers/CylindricalTrackingGeometry.hpp"
0016 #include "Acts/Utilities/Logger.hpp"
0017 
0018 #include <fstream>
0019 #include <string>
0020 
0021 #include <DD4hep/DetElement.h>
0022 #include <DD4hep/DetFactoryHelper.h>
0023 #include <DD4hep/Detector.h>
0024 #include <XML/Utilities.h>
0025 #include <XMLFragments.hpp>
0026 
0027 #include "DD4hepTestsHelper.hpp"
0028 
0029 Acts::GeometryContext tContext;
0030 Acts::Test::CylindricalTrackingGeometry cGeometry =
0031     Acts::Test::CylindricalTrackingGeometry(tContext);
0032 
0033 const char* beampipe_head_xml =
0034     R""""(
0035     <detectors>
0036         <detector id="0" name="BeamPipe" type="BarrelDetector">
0037             <type_flags type="DetType_TRACKER + DetType_BEAMPIPE"/>
0038             <layers>
0039                 <layer name="BP" id="0">
0040 )"""";
0041 
0042 const char* cylinder_layer_head_xml =
0043     R""""(
0044     <detectors>
0045         <detector id="1" name="BarrelLayer" type="BarrelDetector" readout="PixelReadout">
0046             <type_flags type="DetType_TRACKER + DetType_BARREL"/>
0047             <layers>
0048                 <layer name="B0" id="0">
0049 )"""";
0050 
0051 const char* tail_xml =
0052     R""""(
0053                 </layer>
0054             </layers>
0055         </detector>
0056     </detectors>
0057 )"""";
0058 
0059 const std::string indent_12_xml(12, ' ');
0060 
0061 BOOST_AUTO_TEST_SUITE(DD4hepPlugin)
0062 
0063 // This tests creates a beampipe as a passive cylinder surface
0064 BOOST_AUTO_TEST_CASE(DD4hepPluginBeampipeStructure) {
0065   // Create an XML from it
0066   std::ofstream cxml;
0067 
0068   std::string fNameBase = "BeamPipe";
0069 
0070   cxml.open(fNameBase + ".xml");
0071   cxml << head_xml;
0072   cxml << beampipe_head_xml;
0073   cxml << indent_12_xml << "  <acts_passive_surface>" << '\n';
0074   cxml << indent_12_xml
0075        << "    <tubs rmin=\"25*mm\" rmax=\"25.8*mm\" dz=\"1800*mm\" "
0076           "material=\"Air\"/>"
0077        << '\n';
0078   cxml << indent_12_xml << "  </acts_passive_surface>" << '\n';
0079 
0080   cxml << tail_xml;
0081   cxml << end_xml;
0082   cxml.close();
0083 
0084   auto lcdd = &(dd4hep::Detector::getInstance());
0085   lcdd->fromCompact(fNameBase + ".xml");
0086   lcdd->volumeManager();
0087   lcdd->apply("DD4hepVolumeManager", 0, nullptr);
0088 
0089   auto world = lcdd->world();
0090 
0091   // Now the test starts ...
0092   Acts::DD4hepDetectorSurfaceFactory::Config sFactoryConfig;
0093   auto sFactory = std::make_shared<Acts::DD4hepDetectorSurfaceFactory>(
0094       sFactoryConfig, Acts::getDefaultLogger("DD4hepDetectorSurfaceFactory",
0095                                              Acts::Logging::DEBUG));
0096 
0097   Acts::Experimental::DD4hepLayerStructure beamPipeStructure(
0098       std::move(sFactory), Acts::getDefaultLogger("DD4hepBeamPipeStructure",
0099                                                   Acts::Logging::VERBOSE));
0100 
0101   Acts::DD4hepDetectorElement::Store dd4hepStore;
0102 
0103   Acts::Experimental::DD4hepLayerStructure::Options lsOptions;
0104   lsOptions.name = "BeamPipe";
0105   lsOptions.logLevel = Acts::Logging::VERBOSE;
0106 
0107   auto [beamPipeInternalsBuilder, beamPipeExt] =
0108       beamPipeStructure.builder(dd4hepStore, tContext, world, lsOptions);
0109 
0110   // Not configured to have the beam pipe Extent measured
0111   BOOST_CHECK(beamPipeExt == std::nullopt);
0112 
0113   // Build the internal volume structure
0114   auto [surfaces, volumes, surfacesUpdater, volumeUpdater] =
0115       beamPipeInternalsBuilder->construct(tContext);
0116 
0117   // All surfaces are filled
0118   BOOST_CHECK_EQUAL(surfaces.size(), 1u);
0119   // No volumes are added
0120   BOOST_CHECK(volumes.empty());
0121   // The surface updator is connected
0122   BOOST_CHECK(surfacesUpdater.connected());
0123   // The volume updator is connected
0124   BOOST_CHECK(volumeUpdater.connected());
0125 
0126   // Kill that instance before going into the next test
0127   lcdd->destroyInstance();
0128 }
0129 
0130 // This test creates DD4hep xml compact files for cylindrical
0131 // layer structures and then converts them into IndexedSurfacesUpdater
0132 // and other additional components needed for Internal DetectorVolume
0133 // structure.
0134 //
0135 // It tests without explicit binning first
0136 //
0137 // It tests also with Bin expansion, i.e. the filling of additional
0138 // bins with the found surface object.
0139 //
0140 BOOST_AUTO_TEST_CASE(DD4hepPluginCylinderLayerStructure) {
0141   // First create some test surfaces
0142   Acts::Test::CylindricalTrackingGeometry::DetectorStore dStore;
0143   auto cSurfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.145,
0144                                               116., 3., 2., {52, 14});
0145 
0146   // Running three tests with
0147   // - no binning / no support
0148   // - 14 x 52 bins and expansion / support
0149   // - 28 x 104 bins without expansion /  support with proto material
0150   std::vector<std::array<unsigned int, 4u> > zphiBinning = {
0151       {1u, 1u, 0u, 0u}, {14u, 52u, 1u, 1u}, {28u, 104u, 0u, 0u}};
0152 
0153   std::size_t itest = 0;
0154   for (auto [nz, nphi, ez, ephi] : zphiBinning) {
0155     // Create an XML from it
0156     std::ofstream cxml;
0157 
0158     std::string fNameBase = "CylinderLayer_nz";
0159     fNameBase += std::to_string(nz);
0160     fNameBase += "_nphi";
0161     fNameBase += std::to_string(nphi);
0162 
0163     cxml.open(fNameBase + ".xml");
0164     cxml << head_xml;
0165     cxml << segmentation_xml;
0166     cxml << cylinder_layer_head_xml;
0167 
0168     // Test binning
0169     if (nz * nphi > 1u) {
0170       cxml << indent_12_xml << "<acts_surface_binning";
0171       cxml << " ztype=\"equidistant\"";
0172       cxml << " phitype=\"equidistant\"";
0173       cxml << " nz=\"" << nz << "\" zmin=\"-500*mm\" zmax=\"500*mm\"";
0174       cxml << " zexpansion= \"" << ez << "\"";
0175       cxml << " nphi=\"" << nphi << "\"  phimin=\"-3.1415\" phimax=\"3.1415\"";
0176       cxml << " phiexpansion= \"" << ephi << "\"/>";
0177     }
0178     cxml << "<modules>" << '\n';
0179 
0180     for (const auto& s : cSurfaces) {
0181       cxml << indent_12_xml
0182            << DD4hepTestsHelper::surfaceToXML(tContext, *s,
0183                                               Acts::Transform3::Identity())
0184            << "\n";
0185     }
0186 
0187     cxml << "</modules>" << '\n';
0188 
0189     // test the support structure definition
0190     unsigned int passiveAddon = 0u;
0191     if (itest == 1u) {
0192       cxml << indent_12_xml << "  <acts_passive_surface>" << '\n';
0193       cxml << indent_12_xml
0194            << "    <tubs rmin=\"122*mm\" rmax=\"124*mm\" dz=\"500*mm\" "
0195               "material=\"Air\"/>"
0196            << '\n';
0197       cxml << indent_12_xml << "  </acts_passive_surface>" << '\n';
0198       passiveAddon = 1u;
0199     }
0200     ++itest;
0201 
0202     cxml << tail_xml;
0203     cxml << end_xml;
0204     cxml.close();
0205 
0206     auto lcdd = &(dd4hep::Detector::getInstance());
0207     lcdd->fromCompact(fNameBase + ".xml");
0208     lcdd->volumeManager();
0209     lcdd->apply("DD4hepVolumeManager", 0, nullptr);
0210 
0211     auto world = lcdd->world();
0212 
0213     // Now the test starts ...
0214     Acts::DD4hepDetectorSurfaceFactory::Config sFactoryConfig;
0215     auto sFactory = std::make_shared<Acts::DD4hepDetectorSurfaceFactory>(
0216         sFactoryConfig, Acts::getDefaultLogger("DD4hepDetectorSurfaceFactory",
0217                                                Acts::Logging::VERBOSE));
0218 
0219     Acts::Experimental::DD4hepLayerStructure barrelStructure(
0220         std::move(sFactory),
0221         Acts::getDefaultLogger("DD4hepLayerStructure", Acts::Logging::VERBOSE));
0222 
0223     Acts::DD4hepDetectorElement::Store dd4hepStore;
0224 
0225     Acts::Experimental::DD4hepLayerStructure::Options lsOptions;
0226     lsOptions.name = "BarrelLayer";
0227     lsOptions.logLevel = Acts::Logging::VERBOSE;
0228 
0229     auto [barrelInternalsBuilder, barrelExt] =
0230         barrelStructure.builder(dd4hepStore, tContext, world, lsOptions);
0231 
0232     // Build the internal volume structure
0233     auto [surfaces, volumes, surfacesUpdater, volumeUpdater] =
0234         barrelInternalsBuilder->construct(tContext);
0235 
0236     // All surfaces are filled
0237     BOOST_CHECK_EQUAL(surfaces.size(), 14u * 52u + passiveAddon);
0238     // No volumes are added
0239     BOOST_CHECK(volumes.empty());
0240     // The surface updator is connected
0241     BOOST_CHECK(surfacesUpdater.connected());
0242     // The volume updator is connected
0243     BOOST_CHECK(volumeUpdater.connected());
0244 
0245     // Kill that instance before going into the next test
0246     lcdd->destroyInstance();
0247   }
0248 }
0249 
0250 // Test the auto-range determination
0251 BOOST_AUTO_TEST_CASE(DD4hepPluginCylinderLayerStructureAutoRange) {
0252   // First create some test surfaces
0253   Acts::Test::CylindricalTrackingGeometry::DetectorStore dStore;
0254   auto cSurfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.145,
0255                                               116., 3., 2., {52, 14});
0256 
0257   // Create an XML from it
0258   std::ofstream cxml;
0259   std::string fName = "CylinderLayer_auto_range.xml";
0260 
0261   cxml.open(fName);
0262   cxml << head_xml;
0263   cxml << segmentation_xml;
0264   cxml << cylinder_layer_head_xml;
0265 
0266   cxml << "<modules>" << '\n';
0267   for (const auto& s : cSurfaces) {
0268     cxml << indent_12_xml
0269          << DD4hepTestsHelper::surfaceToXML(tContext, *s,
0270                                             Acts::Transform3::Identity())
0271          << "\n";
0272   }
0273   cxml << "</modules>" << '\n';
0274   cxml << tail_xml;
0275   cxml << end_xml;
0276   cxml.close();
0277 
0278   auto lcdd = &(dd4hep::Detector::getInstance());
0279   lcdd->fromCompact(fName);
0280   lcdd->volumeManager();
0281   lcdd->apply("DD4hepVolumeManager", 0, nullptr);
0282 
0283   auto world = lcdd->world();
0284 
0285   // Now the test starts ...
0286   Acts::DD4hepDetectorSurfaceFactory::Config sFactoryConfig;
0287   auto sFactory = std::make_shared<Acts::DD4hepDetectorSurfaceFactory>(
0288       sFactoryConfig, Acts::getDefaultLogger("DD4hepDetectorSurfaceFactory",
0289                                              Acts::Logging::VERBOSE));
0290 
0291   Acts::Experimental::DD4hepLayerStructure barrelStructure(
0292       std::move(sFactory),
0293       Acts::getDefaultLogger("DD4hepLayerStructure", Acts::Logging::VERBOSE));
0294 
0295   Acts::DD4hepDetectorElement::Store dd4hepStore;
0296 
0297   Acts::Experimental::DD4hepLayerStructure::Options lsOptions;
0298   lsOptions.name = "AutoRangeLayer";
0299   auto extent = Acts::Extent();
0300   lsOptions.extent = extent;
0301   lsOptions.extentConstraints = {Acts::AxisDirection::AxisZ,
0302                                  Acts::AxisDirection::AxisR};
0303   lsOptions.logLevel = Acts::Logging::VERBOSE;
0304 
0305   auto [barrelInternalsBuilder, barrelExt] =
0306       barrelStructure.builder(dd4hepStore, tContext, world, lsOptions);
0307 
0308   BOOST_CHECK(barrelExt != std::nullopt);
0309   BOOST_CHECK(barrelExt.value().constrains(Acts::AxisDirection::AxisZ));
0310   BOOST_CHECK(barrelExt.value().constrains(Acts::AxisDirection::AxisR));
0311 }
0312 
0313 BOOST_AUTO_TEST_SUITE_END()