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