File indexing completed on 2025-06-21 08:10:31
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Geometry/GeometryContext.hpp"
0013 #include "Acts/Plugins/DD4hep/DD4hepDetectorElement.hpp"
0014 #include "Acts/Plugins/DD4hep/DD4hepDetectorSurfaceFactory.hpp"
0015 #include "Acts/Surfaces/Surface.hpp"
0016 #include "Acts/Tests/CommonHelpers/CylindricalTrackingGeometry.hpp"
0017 #include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
0018
0019 #include <fstream>
0020 #include <iostream>
0021
0022 #include <DD4hep/DetElement.h>
0023 #include <DD4hep/Detector.h>
0024
0025 #include "DD4hep/DetFactoryHelper.h"
0026 #include "DD4hepTestsHelper.hpp"
0027 #include "XML/Utilities.h"
0028 #include "XMLFragments.hpp"
0029
0030 namespace {
0031 Acts::GeometryContext tContext;
0032 Acts::Test::CylindricalTrackingGeometry cGeometry =
0033 Acts::Test::CylindricalTrackingGeometry(tContext);
0034 }
0035
0036 const char* beampipe_head_xml =
0037 R""""(
0038 <detectors>
0039 <detector id="0" name="BeamPipe" type="BarrelDetector">
0040 <type_flags type="DetType_TRACKER + DetType_BEAMPIPE"/>
0041 <layers>
0042 <layer id="0" name="BeamPipeLayer">
0043 )"""";
0044
0045 const char* nec_head_xml =
0046 R""""(
0047 <detector id="1" name="PixelNegativeEndcap" type="EndcapDetector" readout="PixelReadout">
0048 <type_flags type="DetType_TRACKER + DetType_BARREL"/>
0049 )"""";
0050
0051 const char* barrel_head_xml =
0052 R""""(
0053 <detector id="2" name="PixelBarrel" type="BarrelDetector" readout="PixelReadout">
0054 <type_flags type="DetType_TRACKER + DetType_BARREL"/>
0055 )"""";
0056
0057 const char* pec_head_xml =
0058 R""""(
0059 <detector id="3" name="PixelPositiveEndcap" type="EndcapDetector" readout="PixelReadout">
0060 <type_flags type="DetType_TRACKER + DetType_BARREL"/>
0061 )"""";
0062
0063 const char* plugin_xml =
0064 R"""(<plugins>
0065 <plugin name="DD4hep_ParametersPlugin">
0066 <argument value="world"/>
0067 <argument value="acts_world: bool = true"/>
0068 <argument value="acts_world_type: int = 3"/>
0069 <argument value="acts_world_bvalues_n: int = 3"/>
0070 <argument value="acts_world_bvalues_0: double = 0"/>
0071 <argument value="acts_world_bvalues_1: double = 150*mm"/>
0072 <argument value="acts_world_bvalues_2: double = 1000*mm"/>
0073 <argument value="acts_world_binning: str = r"/>
0074 <argument value="acts_world_geo_id: str = incremental"/>
0075 <argument value="acts_world_root_volume_finder: str = indexed"/>
0076 </plugin>
0077 <plugin name="DD4hep_ParametersPlugin">
0078 <argument value="BeamPipe"/>
0079 <argument value="acts_volume: bool = true"/>
0080 <argument value="acts_volume_type: int = 3"/>
0081 <argument value="acts_volume_bvalues_n: int = 3"/>
0082 <argument value="acts_volume_bvalues_0: double = 0"/>
0083 <argument value="acts_volume_bvalues_1: double = 20*mm"/>
0084 <argument value="acts_volume_bvalues_2: double = 1000*mm"/>
0085 <argument value="acts_volume_internals: bool = true"/>
0086 <argument value="acts_volume_internals_type: str = layer"/>
0087 </plugin>
0088 <plugin name="DD4hep_ParametersPlugin">
0089 <argument value="Pixel"/>
0090 <argument value="acts_container: bool = true"/>
0091 <argument value="acts_container_type: int = 3"/>
0092 <argument value="acts_container_bvalues_n: int = 3"/>
0093 <argument value="acts_container_bvalues_0: double = 20*mm"/>
0094 <argument value="acts_container_bvalues_1: double = 150*mm"/>
0095 <argument value="acts_container_bvalues_2: double = 1000*mm"/>
0096 <argument value="acts_container_binning: str = z"/>
0097 </plugin>
0098 <plugin name="DD4hep_ParametersPlugin">
0099 <argument value="PixelNegativeEndcap"/>
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 = 200*mm"/>
0106 <argument value="acts_container_binning: str = z"/>
0107 <argument value="acts_container_z: double = -800*mm"/>
0108 </plugin>
0109 <plugin name="DD4hep_ParametersPlugin">
0110 <argument value="PixelBarrel"/>
0111 <argument value="acts_container: bool = true"/>
0112 <argument value="acts_container_type: int = 3"/>
0113 <argument value="acts_container_bvalues_n: int = 3"/>
0114 <argument value="acts_container_bvalues_0: double = 20*mm"/>
0115 <argument value="acts_container_bvalues_1: double = 150*mm"/>
0116 <argument value="acts_container_bvalues_2: double = 600*mm"/>
0117 <argument value="acts_container_binning: str = r"/>
0118 </plugin>
0119 <plugin name="DD4hep_ParametersPlugin">
0120 <argument value="PixelPositiveEndcap"/>
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 = 200*mm"/>
0127 <argument value="acts_container_binning: str = z"/>
0128 <argument value="acts_container_z: double = 800*mm"/>
0129 </plugin>
0130 </plugins>
0131 )""";
0132
0133 const std::string indent_4_xml(4, ' ');
0134 const std::string indent_8_xml(8, ' ');
0135 const std::string indent_12_xml(12, ' ');
0136
0137 namespace {
0138
0139 Acts::Test::CylindricalTrackingGeometry::DetectorStore generateXML() {
0140 Acts::Test::CylindricalTrackingGeometry::DetectorStore dStore;
0141
0142
0143 double necZ = -800.;
0144 auto necR0Surfaces = cGeometry.surfacesRing(dStore, 6.4, 12.4, 18., 0.125, 0.,
0145 42., necZ, 2., 22u);
0146
0147 auto necR1Surfaces = cGeometry.surfacesRing(dStore, 12.4, 20.4, 30., 0.125,
0148 0., 80., necZ, 2., 22u);
0149
0150 std::vector<std::vector<const Acts::Surface*>> necSurfaces = {necR0Surfaces,
0151 necR1Surfaces};
0152
0153
0154 std::vector<std::array<double, 2u>> innerOuter = {
0155 {25., 35.}, {65., 75.}, {110., 120.}};
0156 auto b0Surfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.14,
0157 31., 3., 2., {16, 14});
0158
0159 auto b1Surfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.14,
0160 71., 3., 2., {32, 14});
0161
0162 auto b2Surfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.14,
0163 116., 3., 2., {52, 14});
0164
0165 std::vector<std::vector<const Acts::Surface*>> barrelSurfaces = {
0166 b0Surfaces, b1Surfaces, b2Surfaces};
0167
0168
0169 double pecZ = 800.;
0170 auto pecR0Surfaces = cGeometry.surfacesRing(dStore, 6.4, 12.4, 18., 0.125, 0.,
0171 42., pecZ, 2., 22u);
0172
0173 auto pecR1Surfaces = cGeometry.surfacesRing(dStore, 12.4, 20.4, 30., 0.125,
0174 0., 80., pecZ, 2., 22u);
0175
0176 std::vector<std::vector<const Acts::Surface*>> pecSurfaces = {pecR0Surfaces,
0177 pecR1Surfaces};
0178
0179
0180 std::ofstream cxml;
0181 cxml.open("CylindricalDetectorTestSF.xml");
0182 cxml << head_xml;
0183 cxml << segmentation_xml;
0184
0185
0186 cxml << beampipe_head_xml << '\n';
0187 cxml << indent_12_xml << "<acts_passive_surface>" << '\n';
0188 cxml << indent_12_xml
0189 << "<tubs rmin=\"19*mm\" rmax=\"20*mm\" dz=\"800*mm\" "
0190 "material=\"Air\"/>"
0191 << '\n';
0192 cxml << indent_12_xml << "</acts_passive_surface>" << '\n';
0193 cxml << indent_12_xml << "</layer> " << '\n';
0194 cxml << indent_8_xml << "</layers>" << '\n';
0195 cxml << indent_8_xml << "</detector>" << '\n';
0196
0197
0198 const char* pixel_assembly_xml =
0199 R"""(<detector id="4" name="Pixel" type="DD4hep_SubdetectorAssembly" vis="invisible">
0200 <shape name="PixelVolume" type="Tube" rmin="20*mm" rmax="150*mm" dz="1000*mm" material="Air"/>
0201 <composite name="PixelNegativeEndcap"/>
0202 <composite name="PixelBarrel"/>
0203 <composite name="PixelPositiveEndcap"/>
0204 </detector>)""";
0205
0206 cxml << pixel_assembly_xml << '\n';
0207 cxml << "</detectors>" << '\n';
0208
0209
0210
0211
0212 cxml << "<detectors>" << '\n';
0213
0214 cxml << nec_head_xml << '\n';
0215 cxml << indent_8_xml << "<layers>" << '\n';
0216 cxml << indent_8_xml << "<acts_container/> " << '\n';
0217 cxml << indent_4_xml << "<layer name=\"NegEndcapLayer_0\" id=\"0\">" << '\n';
0218 cxml << indent_4_xml << "<acts_volume dz=\"20*mm\" cz=\"-800.*mm\"/>" << '\n';
0219 cxml << indent_8_xml << "<modules>" << '\n';
0220 for (const auto& ring : necSurfaces) {
0221 for (const auto& s : ring) {
0222 cxml << indent_12_xml
0223 << DD4hepTestsHelper::surfaceToXML(tContext, *s,
0224 Acts::Transform3::Identity())
0225 << "\n";
0226 }
0227 }
0228 cxml << indent_8_xml << "</modules>" << '\n';
0229 cxml << indent_8_xml << "</layer> " << '\n';
0230 cxml << indent_8_xml << "</layers>" << '\n';
0231 cxml << indent_8_xml << "</detector>" << '\n';
0232
0233
0234 cxml << barrel_head_xml << '\n';
0235 cxml << indent_8_xml << "<layers>" << '\n';
0236 cxml << indent_8_xml << "<acts_container/> " << '\n';
0237 for (const auto [ib, bs] : Acts::enumerate(barrelSurfaces)) {
0238 cxml << indent_4_xml << "<layer name=\"PixelBarrel_" << ib << "\" id=\""
0239 << ib << "\">" << '\n';
0240 cxml << indent_4_xml << "<acts_volume rmin=\"" << innerOuter[ib][0u]
0241 << "*mm\" rmax=\"" << innerOuter[ib][1u] << "*mm\"/>";
0242 cxml << indent_8_xml << "<modules>" << '\n';
0243 for (const auto& s : bs) {
0244 cxml << indent_12_xml
0245 << DD4hepTestsHelper::surfaceToXML(tContext, *s,
0246 Acts::Transform3::Identity())
0247 << "\n";
0248 }
0249 cxml << indent_8_xml << "</modules>" << '\n';
0250 cxml << indent_8_xml << "</layer>" << '\n';
0251 }
0252 cxml << indent_8_xml << "</layers>" << '\n';
0253 cxml << indent_8_xml << "</detector>" << '\n';
0254
0255
0256 cxml << pec_head_xml << '\n';
0257 cxml << indent_8_xml << "<layers>" << '\n';
0258 cxml << indent_8_xml << "<acts_container/> " << '\n';
0259 cxml << indent_4_xml << "<layer name=\"PosEndcapLayer_0\" id=\"0\">" << '\n';
0260 cxml << indent_4_xml << "<acts_volume dz=\"20*mm\" cz=\"800.*mm\"/>" << '\n';
0261 cxml << indent_8_xml << "<modules>" << '\n';
0262 for (const auto& ring : pecSurfaces) {
0263 for (const auto& s : ring) {
0264 cxml << indent_12_xml
0265 << DD4hepTestsHelper::surfaceToXML(tContext, *s,
0266 Acts::Transform3::Identity())
0267 << "\n";
0268 }
0269 }
0270 cxml << indent_8_xml << "</modules>" << '\n';
0271 cxml << indent_8_xml << "</layer> " << '\n';
0272 cxml << indent_8_xml << "</layers>" << '\n';
0273 cxml << indent_8_xml << "</detector>" << '\n';
0274 cxml << indent_8_xml << "</detectors>" << '\n';
0275
0276 cxml << plugin_xml << '\n';
0277 cxml << end_xml << '\n';
0278 cxml.close();
0279
0280 return dStore;
0281 }
0282
0283 }
0284
0285 auto store = generateXML();
0286
0287 BOOST_AUTO_TEST_SUITE(DD4hepPlugin)
0288
0289 BOOST_AUTO_TEST_CASE(ConvertSensitivesDefault) {
0290 auto lcdd = &(dd4hep::Detector::getInstance());
0291 lcdd->fromCompact("CylindricalDetectorTestSF.xml");
0292 lcdd->volumeManager();
0293 lcdd->apply("DD4hepVolumeManager", 0, nullptr);
0294
0295 auto world = lcdd->world();
0296
0297
0298 Acts::DD4hepDetectorSurfaceFactory::Config sFactoryConfig;
0299 auto surfaceFactory = Acts::DD4hepDetectorSurfaceFactory(
0300 sFactoryConfig, Acts::getDefaultLogger("DD4hepDetectorSurfaceFactory",
0301 Acts::Logging::VERBOSE));
0302
0303 Acts::DD4hepDetectorSurfaceFactory::Cache sFactoryCache;
0304 Acts::DD4hepDetectorSurfaceFactory::Options sFactoryOptions;
0305
0306 surfaceFactory.construct(sFactoryCache, tContext, world, sFactoryOptions);
0307
0308 BOOST_CHECK_EQUAL(sFactoryCache.sensitiveSurfaces.size(), 1488u);
0309
0310
0311 lcdd->destroyInstance();
0312 }
0313
0314 BOOST_AUTO_TEST_CASE(ConvertSensitivesextended) {
0315 auto lcdd = &(dd4hep::Detector::getInstance());
0316 lcdd->fromCompact("CylindricalDetectorTestSF.xml");
0317 lcdd->volumeManager();
0318 lcdd->apply("DD4hepVolumeManager", 0, nullptr);
0319
0320 auto world = lcdd->world();
0321
0322
0323
0324
0325
0326 class ExtendedDetectorElement : public Acts::DD4hepDetectorElement {
0327 public:
0328 using Acts::DD4hepDetectorElement::DD4hepDetectorElement;
0329
0330 double thickness() const final {
0331
0332 return 42. * Acts::UnitConstants::mm;
0333 }
0334 };
0335
0336 auto extendedFactory =
0337 [](const dd4hep::DetElement& detElem, const std::string& axes,
0338 double scalor, bool isDisc,
0339 const std::shared_ptr<const Acts::ISurfaceMaterial>& material)
0340 -> std::shared_ptr<Acts::DD4hepDetectorElement> {
0341 return std::make_shared<ExtendedDetectorElement>(detElem, axes, scalor,
0342 isDisc, material);
0343 };
0344
0345
0346 Acts::DD4hepDetectorSurfaceFactory::Config sFactoryConfig;
0347 sFactoryConfig.detectorElementFactory = extendedFactory;
0348 auto surfaceFactory = Acts::DD4hepDetectorSurfaceFactory(
0349 sFactoryConfig, Acts::getDefaultLogger("DD4hepDetectorSurfaceFactory",
0350 Acts::Logging::VERBOSE));
0351
0352 Acts::DD4hepDetectorSurfaceFactory::Cache sFactoryCache;
0353 Acts::DD4hepDetectorSurfaceFactory::Options sFactoryOptions;
0354
0355 surfaceFactory.construct(sFactoryCache, tContext, world, sFactoryOptions);
0356
0357 BOOST_CHECK_EQUAL(sFactoryCache.sensitiveSurfaces.size(), 1488u);
0358 for (const auto& [detElem, surface] : sFactoryCache.sensitiveSurfaces) {
0359
0360 BOOST_CHECK_NE(dynamic_cast<const ExtendedDetectorElement*>(detElem.get()),
0361 nullptr);
0362
0363 CHECK_CLOSE_ABS(detElem->thickness(), 42. * Acts::UnitConstants::mm, 1e-10);
0364 }
0365
0366
0367 lcdd->destroyInstance();
0368 }
0369
0370 BOOST_AUTO_TEST_SUITE_END()