File indexing completed on 2025-10-25 07:57:19
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include <boost/test/unit_test.hpp>
0010
0011 #include "Acts/Detector/CylindricalContainerBuilder.hpp"
0012 #include "Acts/Detector/Detector.hpp"
0013 #include "Acts/Detector/DetectorBuilder.hpp"
0014 #include "Acts/Detector/detail/BlueprintDrawer.hpp"
0015 #include "Acts/Detector/detail/BlueprintHelper.hpp"
0016 #include "Acts/Geometry/GeometryContext.hpp"
0017 #include "Acts/Surfaces/Surface.hpp"
0018 #include "Acts/Surfaces/SurfaceBounds.hpp"
0019 #include "Acts/Utilities/Enumerate.hpp"
0020 #include "Acts/Utilities/Logger.hpp"
0021 #include "ActsPlugins/DD4hep/DD4hepBlueprintFactory.hpp"
0022 #include "ActsPlugins/DD4hep/DD4hepDetectorStructure.hpp"
0023 #include "ActsPlugins/DD4hep/DD4hepDetectorSurfaceFactory.hpp"
0024 #include "ActsPlugins/DD4hep/DD4hepLayerStructure.hpp"
0025 #include "ActsTests/CommonHelpers/CylindricalTrackingGeometry.hpp"
0026
0027 #include <fstream>
0028 #include <string>
0029
0030 #include <DD4hep/DetElement.h>
0031 #include <DD4hep/DetFactoryHelper.h>
0032 #include <DD4hep/Detector.h>
0033 #include <XML/Utilities.h>
0034 #include <XMLFragments.hpp>
0035
0036 #include "DD4hepTestsHelper.hpp"
0037
0038 using namespace Acts;
0039 using namespace ActsPlugins;
0040
0041 namespace ActsTests {
0042
0043 GeometryContext tContext;
0044 CylindricalTrackingGeometry cGeometry = CylindricalTrackingGeometry(tContext);
0045
0046 const char* beampipe_head_xml =
0047 R""""(
0048 <detectors>
0049 <detector id="0" name="BeamPipe" type="BarrelDetector">
0050 <type_flags type="DetType_TRACKER + DetType_BEAMPIPE"/>
0051 <layers>
0052 <layer id="0" name="BeamPipeLayer">
0053 )"""";
0054
0055 const char* nec_head_xml =
0056 R""""(
0057 <detector id="1" name="PixelNegativeEndcap" type="EndcapDetector" readout="PixelReadout">
0058 <type_flags type="DetType_TRACKER + DetType_BARREL"/>
0059 )"""";
0060
0061 const char* barrel_head_xml =
0062 R""""(
0063 <detector id="2" name="PixelBarrel" type="BarrelDetector" readout="PixelReadout">
0064 <type_flags type="DetType_TRACKER + DetType_BARREL"/>
0065 )"""";
0066
0067 const char* pec_head_xml =
0068 R""""(
0069 <detector id="3" name="PixelPositiveEndcap" type="EndcapDetector" readout="PixelReadout">
0070 <type_flags type="DetType_TRACKER + DetType_BARREL"/>
0071 )"""";
0072
0073 const char* plugin_xml =
0074 R"""(<plugins>
0075 <plugin name="DD4hep_ParametersPlugin">
0076 <argument value="world"/>
0077 <argument value="acts_world: bool = true"/>
0078 <argument value="acts_world_type: int = 3"/>
0079 <argument value="acts_world_bvalues_n: int = 3"/>
0080 <argument value="acts_world_bvalues_0: double = 0"/>
0081 <argument value="acts_world_bvalues_1: double = 150*mm"/>
0082 <argument value="acts_world_bvalues_2: double = 1000*mm"/>
0083 <argument value="acts_world_binning: str = r"/>
0084 <argument value="acts_world_geo_id: str = incremental"/>
0085 <argument value="acts_world_root_volume_finder: str = indexed"/>
0086 </plugin>
0087 <plugin name="DD4hep_ParametersPlugin">
0088 <argument value="BeamPipe"/>
0089 <argument value="acts_volume: bool = true"/>
0090 <argument value="acts_volume_type: int = 3"/>
0091 <argument value="acts_volume_bvalues_n: int = 3"/>
0092 <argument value="acts_volume_bvalues_0: double = 0"/>
0093 <argument value="acts_volume_bvalues_1: double = 20*mm"/>
0094 <argument value="acts_volume_bvalues_2: double = 1000*mm"/>
0095 <argument value="acts_volume_internals: bool = true"/>
0096 <argument value="acts_volume_internals_type: str = layer"/>
0097 </plugin>
0098 <plugin name="DD4hep_ParametersPlugin">
0099 <argument value="Pixel"/>
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 = 1000*mm"/>
0106 <argument value="acts_container_binning: str = z"/>
0107 </plugin>
0108 <plugin name="DD4hep_ParametersPlugin">
0109 <argument value="PixelNegativeEndcap"/>
0110 <argument value="acts_container: bool = true"/>
0111 <argument value="acts_container_type: int = 3"/>
0112 <argument value="acts_container_bvalues_n: int = 3"/>
0113 <argument value="acts_container_bvalues_0: double = 20*mm"/>
0114 <argument value="acts_container_bvalues_1: double = 150*mm"/>
0115 <argument value="acts_container_bvalues_2: double = 200*mm"/>
0116 <argument value="acts_container_binning: str = z"/>
0117 <argument value="acts_container_z: double = -800*mm"/>
0118 </plugin>
0119 <plugin name="DD4hep_ParametersPlugin">
0120 <argument value="PixelBarrel"/>
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 = 600*mm"/>
0127 <argument value="acts_container_binning: str = r"/>
0128 </plugin>
0129 <plugin name="DD4hep_ParametersPlugin">
0130 <argument value="PixelPositiveEndcap"/>
0131 <argument value="acts_container: bool = true"/>
0132 <argument value="acts_container_type: int = 3"/>
0133 <argument value="acts_container_bvalues_n: int = 3"/>
0134 <argument value="acts_container_bvalues_0: double = 20*mm"/>
0135 <argument value="acts_container_bvalues_1: double = 150*mm"/>
0136 <argument value="acts_container_bvalues_2: double = 200*mm"/>
0137 <argument value="acts_container_binning: str = z"/>
0138 <argument value="acts_container_z: double = 800*mm"/>
0139 </plugin>
0140 </plugins>
0141 )""";
0142
0143 const std::string indent_4_xml(4, ' ');
0144 const std::string indent_8_xml(8, ' ');
0145 const std::string indent_12_xml(12, ' ');
0146
0147 CylindricalTrackingGeometry::DetectorStore generateXML() {
0148 CylindricalTrackingGeometry::DetectorStore dStore;
0149
0150
0151 double necZ = -800.;
0152 auto necR0Surfaces = cGeometry.surfacesRing(dStore, 6.4, 12.4, 18., 0.125, 0.,
0153 42., necZ, 2., 22u);
0154
0155 auto necR1Surfaces = cGeometry.surfacesRing(dStore, 12.4, 20.4, 30., 0.125,
0156 0., 80., necZ, 2., 22u);
0157
0158 std::vector<std::vector<Surface*>> necSurfaces = {necR0Surfaces,
0159 necR1Surfaces};
0160
0161
0162 std::vector<std::array<double, 2u>> innerOuter = {
0163 {25., 35.}, {65., 75.}, {110., 120.}};
0164 auto b0Surfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.14,
0165 31., 3., 2., {16, 14});
0166
0167 auto b1Surfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.14,
0168 71., 3., 2., {32, 14});
0169
0170 auto b2Surfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.14,
0171 116., 3., 2., {52, 14});
0172
0173 std::vector<std::vector<Surface*>> barrelSurfaces = {b0Surfaces, b1Surfaces,
0174 b2Surfaces};
0175
0176
0177 double pecZ = 800.;
0178 auto pecR0Surfaces = cGeometry.surfacesRing(dStore, 6.4, 12.4, 18., 0.125, 0.,
0179 42., pecZ, 2., 22u);
0180
0181 auto pecR1Surfaces = cGeometry.surfacesRing(dStore, 12.4, 20.4, 30., 0.125,
0182 0., 80., pecZ, 2., 22u);
0183
0184 std::vector<std::vector<Surface*>> pecSurfaces = {pecR0Surfaces,
0185 pecR1Surfaces};
0186
0187
0188 std::ofstream cxml;
0189 cxml.open("CylindricalDetector.xml");
0190 cxml << head_xml;
0191 cxml << segmentation_xml;
0192
0193
0194 cxml << beampipe_head_xml << '\n';
0195 cxml << indent_12_xml << "<acts_passive_surface>" << '\n';
0196 cxml << indent_12_xml
0197 << "<tubs rmin=\"19*mm\" rmax=\"20*mm\" dz=\"800*mm\" "
0198 "material=\"Air\"/>"
0199 << '\n';
0200 cxml << indent_12_xml << "</acts_passive_surface>" << '\n';
0201 cxml << indent_12_xml << "</layer> " << '\n';
0202 cxml << indent_8_xml << "</layers>" << '\n';
0203 cxml << indent_8_xml << "</detector>" << '\n';
0204
0205
0206 const char* pixel_assembly_xml =
0207 R"""(<detector id="4" name="Pixel" type="DD4hep_SubdetectorAssembly" vis="invisible">
0208 <shape name="PixelVolume" type="Tube" rmin="20*mm" rmax="150*mm" dz="1000*mm" material="Air"/>
0209 <composite name="PixelNegativeEndcap"/>
0210 <composite name="PixelBarrel"/>
0211 <composite name="PixelPositiveEndcap"/>
0212 </detector>)""";
0213
0214 cxml << pixel_assembly_xml << '\n';
0215 cxml << "</detectors>" << '\n';
0216
0217
0218
0219
0220 cxml << "<detectors>" << '\n';
0221
0222 cxml << nec_head_xml << '\n';
0223 cxml << indent_8_xml << "<layers>" << '\n';
0224 cxml << indent_8_xml << "<acts_container/> " << '\n';
0225 cxml << indent_4_xml << "<layer name=\"NegEndcapLayer_0\" id=\"0\">" << '\n';
0226 cxml << indent_4_xml << "<acts_volume dz=\"20*mm\" cz=\"-800.*mm\"/>" << '\n';
0227 cxml << indent_8_xml << "<modules>" << '\n';
0228 for (const auto& ring : necSurfaces) {
0229 for (const auto& s : ring) {
0230 cxml << indent_12_xml
0231 << DD4hepTestsHelper::surfaceToXML(tContext, *s,
0232 Transform3::Identity())
0233 << "\n";
0234 }
0235 }
0236 cxml << indent_8_xml << "</modules>" << '\n';
0237 cxml << indent_8_xml << "</layer> " << '\n';
0238 cxml << indent_8_xml << "</layers>" << '\n';
0239 cxml << indent_8_xml << "</detector>" << '\n';
0240
0241
0242 cxml << barrel_head_xml << '\n';
0243 cxml << indent_8_xml << "<layers>" << '\n';
0244 cxml << indent_8_xml << "<acts_container/> " << '\n';
0245 for (const auto [ib, bs] : enumerate(barrelSurfaces)) {
0246 cxml << indent_4_xml << "<layer name=\"PixelBarrel_" << ib << "\" id=\""
0247 << ib << "\">" << '\n';
0248 cxml << indent_4_xml << "<acts_volume rmin=\"" << innerOuter[ib][0u]
0249 << "*mm\" rmax=\"" << innerOuter[ib][1u] << "*mm\"/>";
0250 cxml << indent_8_xml << "<modules>" << '\n';
0251 for (const auto& s : bs) {
0252 cxml << indent_12_xml
0253 << DD4hepTestsHelper::surfaceToXML(tContext, *s,
0254 Transform3::Identity())
0255 << "\n";
0256 }
0257 cxml << indent_8_xml << "</modules>" << '\n';
0258 cxml << indent_8_xml << "</layer>" << '\n';
0259 }
0260 cxml << indent_8_xml << "</layers>" << '\n';
0261 cxml << indent_8_xml << "</detector>" << '\n';
0262
0263
0264 cxml << pec_head_xml << '\n';
0265 cxml << indent_8_xml << "<layers>" << '\n';
0266 cxml << indent_8_xml << "<acts_container/> " << '\n';
0267 cxml << indent_4_xml << "<layer name=\"PosEndcapLayer_0\" id=\"0\">" << '\n';
0268 cxml << indent_4_xml << "<acts_volume dz=\"20*mm\" cz=\"800.*mm\"/>" << '\n';
0269 cxml << indent_8_xml << "<modules>" << '\n';
0270 for (const auto& ring : pecSurfaces) {
0271 for (const auto& s : ring) {
0272 cxml << indent_12_xml
0273 << DD4hepTestsHelper::surfaceToXML(tContext, *s,
0274 Transform3::Identity())
0275 << "\n";
0276 }
0277 }
0278 cxml << indent_8_xml << "</modules>" << '\n';
0279 cxml << indent_8_xml << "</layer> " << '\n';
0280 cxml << indent_8_xml << "</layers>" << '\n';
0281 cxml << indent_8_xml << "</detector>" << '\n';
0282 cxml << indent_8_xml << "</detectors>" << '\n';
0283
0284 cxml << plugin_xml << '\n';
0285 cxml << end_xml << '\n';
0286 cxml.close();
0287
0288 return dStore;
0289 }
0290
0291 auto store = generateXML();
0292
0293 BOOST_AUTO_TEST_SUITE(DD4hepSuite)
0294
0295 BOOST_AUTO_TEST_CASE(DD4hepCylidricalDetectorExplicit) {
0296 auto lcdd = &(dd4hep::Detector::getInstance());
0297 lcdd->fromCompact("CylindricalDetector.xml");
0298 lcdd->volumeManager();
0299 lcdd->apply("DD4hepVolumeManager", 0, nullptr);
0300
0301 auto world = lcdd->world();
0302
0303
0304 DD4hepDetectorSurfaceFactory::Config sFactoryConfig;
0305 auto surfaceFactory = std::make_shared<DD4hepDetectorSurfaceFactory>(
0306 sFactoryConfig,
0307 getDefaultLogger("DD4hepDetectorSurfaceFactory", Logging::VERBOSE));
0308
0309 auto layerStructure = std::make_shared<DD4hepLayerStructure>(
0310 std::move(surfaceFactory),
0311 getDefaultLogger("DD4hepLayerStructure", Logging::VERBOSE));
0312
0313 DD4hepBlueprintFactory::Config bpCfg{layerStructure};
0314 DD4hepBlueprintFactory::Cache bpCache;
0315
0316 DD4hepBlueprintFactory bp(
0317 bpCfg, getDefaultLogger("DD4hepBlueprintFactory", Logging::VERBOSE));
0318 auto dd4hepBlueprint = bp.create(bpCache, tContext, world);
0319
0320
0321
0322
0323
0324
0325 BOOST_CHECK_EQUAL(bpCache.dd4hepStore.size(), 6u);
0326
0327
0328 Experimental::detail::BlueprintHelper::fillGaps(*dd4hepBlueprint);
0329
0330
0331 std::ofstream cbp("cylindrical_detector_dd4hep.dot");
0332 Experimental::detail::BlueprintDrawer::dotStream(cbp, *dd4hepBlueprint);
0333 cbp.close();
0334
0335
0336 auto detectorBuilder =
0337 std::make_shared<Experimental::CylindricalContainerBuilder>(
0338 *dd4hepBlueprint, Logging::VERBOSE);
0339
0340
0341 Experimental::DetectorBuilder::Config dCfg;
0342 dCfg.auxiliary =
0343 "*** Test : auto generated cylindrical detector builder ***";
0344 dCfg.name = "Cylindrical detector from blueprint";
0345 dCfg.builder = detectorBuilder;
0346 dCfg.geoIdGenerator = dd4hepBlueprint->geoIdGenerator;
0347
0348 auto detector = Experimental::DetectorBuilder(dCfg).construct(tContext);
0349
0350
0351 BOOST_REQUIRE_NE(detector, nullptr);
0352
0353
0354
0355
0356
0357 BOOST_CHECK_EQUAL(detector->volumes().size(), 14u);
0358
0359
0360 lcdd->destroyInstance();
0361 }
0362
0363 BOOST_AUTO_TEST_CASE(DD4hepCylidricalDetectorStructure) {
0364 auto lcdd = &(dd4hep::Detector::getInstance());
0365 lcdd->fromCompact("CylindricalDetector.xml");
0366 lcdd->volumeManager();
0367 lcdd->apply("DD4hepVolumeManager", 0, nullptr);
0368
0369 auto world = lcdd->world();
0370
0371 DD4hepDetectorStructure::Options dsOptions;
0372 dsOptions.logLevel = Logging::VERBOSE;
0373 dsOptions.emulateToGraph = "cylindrical_detector_structure";
0374
0375 auto [detectorEm, detectorStoreEm] =
0376 DD4hepDetectorStructure(
0377 getDefaultLogger("DD4hepDetectorStructure", Logging::VERBOSE))
0378 .construct(tContext, world, dsOptions);
0379
0380
0381
0382 BOOST_CHECK_EQUAL(detectorEm, nullptr);
0383
0384
0385 dsOptions.emulateToGraph = "";
0386 auto [detector, detectorStore] =
0387 DD4hepDetectorStructure(
0388 getDefaultLogger("DD4hepDetectorStructure", Logging::VERBOSE))
0389 .construct(tContext, world, dsOptions);
0390
0391 BOOST_REQUIRE_NE(detector, nullptr);
0392
0393
0394
0395
0396
0397
0398 BOOST_CHECK_EQUAL(detector->volumes().size(), 14u);
0399
0400
0401
0402
0403
0404
0405 BOOST_CHECK_EQUAL(detectorStore.size(), 6u);
0406
0407 int elements = 0;
0408 for (const auto& [key, value] : detectorStore) {
0409 elements += value.size();
0410 }
0411
0412
0413
0414
0415
0416
0417
0418 BOOST_CHECK_EQUAL(elements, 1488);
0419
0420
0421 int surfaces = 0;
0422 for (const auto& v : detector->volumes()) {
0423 surfaces += v->surfaces().size();
0424 }
0425
0426 BOOST_CHECK_EQUAL(surfaces, 1489);
0427
0428
0429 lcdd->destroyInstance();
0430 }
0431
0432 BOOST_AUTO_TEST_SUITE_END()
0433
0434 }