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