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