Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-29 07:55:50

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