ECCE @ EIC Software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
ConvertDD4hepDetector.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file ConvertDD4hepDetector.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2017-2018 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
10 
11 #include <list>
12 #include <stdexcept>
13 
31 #include "TGeoManager.h"
32 
33 namespace Acts {
34 std::unique_ptr<const TrackingGeometry> convertDD4hepDetector(
35  dd4hep::DetElement worldDetElement, Logging::Level loggingLevel,
36  BinningType bTypePhi, BinningType bTypeR, BinningType bTypeZ,
37  double layerEnvelopeR, double layerEnvelopeZ, double defaultLayerThickness,
38  const std::function<void(std::vector<dd4hep::DetElement>& detectors)>&
39  sortSubDetectors,
41  std::shared_ptr<const IMaterialDecorator> matDecorator) {
42  // create local logger for conversion
43  ACTS_LOCAL_LOGGER(Acts::getDefaultLogger("DD4hepConversion", loggingLevel));
44  ACTS_INFO("Translating DD4hep geometry into Acts geometry");
45  // get the sub detectors of the world detector e.g. beampipe, pixel detector,
46  // strip detector
47  std::vector<dd4hep::DetElement> subDetectors;
48  // go through the detector hierarchies
49  collectSubDetectors_dd4hep(worldDetElement, subDetectors);
50  // sort to build detector from bottom to top
51  sortSubDetectors(subDetectors);
52  // the volume builders of the subdetectors
53  std::list<std::shared_ptr<const ITrackingVolumeBuilder>> volumeBuilders;
54  // the beam pipe volume builder needs special treatment and needs to be added
55  // in the end (beampipe exceeds length of all other subdetectors)
56  std::shared_ptr<const CylinderVolumeBuilder> beamPipeVolumeBuilder;
57  // loop over the sub detectors
58  for (auto& subDetector : subDetectors) {
59  ACTS_INFO("Translating DD4hep sub detector: " << subDetector.name());
60  // create volume builder
61  auto volBuilder = volumeBuilder_dd4hep(
62  subDetector, loggingLevel, bTypePhi, bTypeR, bTypeZ, layerEnvelopeR,
63  layerEnvelopeZ, defaultLayerThickness);
64  if (volBuilder) {
65  // distinguish beam pipe
66  if (volBuilder->getConfiguration().buildToRadiusZero) {
67  // check if beam pipe is already present
68  if (beamPipeVolumeBuilder) {
69  throw std::logic_error(
70  std::string("Beampipe has already been set! There can only "
71  "exist one beam pipe. Please check your "
72  "detector construction. Current volume name: ") +
73  volBuilder->getConfiguration().volumeName +
74  std::string(", name of volume, already set as beam pipe: ") +
75  beamPipeVolumeBuilder->getConfiguration().volumeName);
76  }
77  // set the beam pipe
78  beamPipeVolumeBuilder = volBuilder;
79  } else {
80  volumeBuilders.push_back(volBuilder);
81  }
82  }
83  }
84  // Finally add the beam pipe
85  if (beamPipeVolumeBuilder) {
86  volumeBuilders.push_back(beamPipeVolumeBuilder);
87  }
88 
89  std::vector<std::function<std::shared_ptr<TrackingVolume>(
90  const GeometryContext&, const TrackingVolumePtr&,
91  const VolumeBoundsPtr&)>>
92  volumeFactories;
93 
94  for (const auto& vb : volumeBuilders) {
95  volumeFactories.push_back(
96  [vb](const GeometryContext& vgctx,
97  const std::shared_ptr<const TrackingVolume>& inner,
98  const VolumeBoundsPtr&) {
99  return vb->trackingVolume(vgctx, inner);
100  });
101  }
102 
103  // create cylinder volume helper
104  auto volumeHelper = cylinderVolumeHelper_dd4hep();
105  // hand over the collected volume builders
107  tgbConfig.trackingVolumeHelper = volumeHelper;
108  tgbConfig.materialDecorator = std::move(matDecorator);
109  tgbConfig.trackingVolumeBuilders = std::move(volumeFactories);
110  auto trackingGeometryBuilder =
111  std::make_shared<const Acts::TrackingGeometryBuilder>(tgbConfig);
112  return (trackingGeometryBuilder->trackingGeometry(gctx));
113 }
114 
115 std::shared_ptr<const CylinderVolumeBuilder> volumeBuilder_dd4hep(
116  dd4hep::DetElement subDetector, Logging::Level loggingLevel,
117  BinningType bTypePhi, BinningType bTypeR, BinningType bTypeZ,
118  double layerEnvelopeR, double layerEnvelopeZ,
119  double defaultLayerThickness) {
120  // create cylinder volume helper
121  auto volumeHelper = cylinderVolumeHelper_dd4hep(loggingLevel);
122  // create local logger for conversion
123  ACTS_LOCAL_LOGGER(Acts::getDefaultLogger("D2A_Logger", loggingLevel));
124  ACTS_VERBOSE("Processing detector element: " << subDetector.name());
125 
126  Acts::ActsExtension* subDetExtension = nullptr;
127  // at this stage not every DetElement needs to have an Extension attached
128  try {
129  subDetExtension = subDetector.extension<Acts::ActsExtension>();
130  } catch (std::runtime_error& e) {
131  }
132  if (subDetector.type() == "compound") {
133  ACTS_VERBOSE("Subdetector : '"
134  << subDetector.name()
135  << "' has no ActsExtension and has type compound ");
136  ACTS_VERBOSE(
137  "handling as a compound volume (a hierachy of a "
138  "barrel-endcap structure) and resolving the "
139  "subvolumes...");
140  // Now create the Layerbuilders and Volumebuilder
141  // the layers
143  std::vector<dd4hep::DetElement> negativeLayers;
145  std::vector<dd4hep::DetElement> centralLayers;
147  std::vector<dd4hep::DetElement> positiveLayers;
148 
149  // the configuration object of the volume builder
151 
152  // go through sub volumes
153  std::vector<dd4hep::DetElement> compounds;
154  collectCompounds_dd4hep(subDetector, compounds);
155 
156  // get z position to distinguish positive & negative endcap
157  double zPos = 0.;
158  // flags to catch if sub volumes have been set already
159  bool nEndCap = false;
160  bool pEndCap = false;
161  bool barrel = false;
162  for (auto& volumeDetElement : compounds) {
163  ACTS_VERBOSE("Volume : '"
164  << subDetector.name()
165  << "'is a compound volume -> resolve now the sub volumes");
166 
167  // get the dimensions of the volume
168  TGeoShape* geoShape =
169  volumeDetElement.placement().ptr()->GetVolume()->GetShape();
170  // check if it has a shape (the other case should not happen)
171  if (geoShape != nullptr) {
172  zPos = volumeDetElement.placement()
173  .ptr()
174  ->GetMatrix()
175  ->GetTranslation()[2] *
177  } else {
178  throw std::logic_error(std::string("Volume of DetElement: ") +
179  volumeDetElement.name() +
180  std::string(" has no shape!"));
181  }
182  // check if it has a volume extension telling if it is a barrel or an
183  // endcap
184  ActsExtension* volumeExtension = nullptr;
185  try {
186  volumeExtension = volumeDetElement.extension<ActsExtension>();
187  } catch (std::runtime_error& e) {
188  throw std::logic_error(
189  std::string("Current DetElement: ") + volumeDetElement.name() +
190  std::string(" has no ActsExtension! At this stage it should be a "
191  "detector volume declared as Barrel or Endcap. Please"
192  "check your detector construction."));
193  }
194 
195  if (volumeExtension->hasType("endcap", "detector")) {
196  ACTS_VERBOSE(
197  std::string("Subvolume : '") + volumeDetElement.name() +
198  std::string("' is a disc volume -> handling as an endcap"));
199  if (zPos < 0.) {
200  if (nEndCap) {
201  throw std::logic_error(
202  "Negative Endcap was already given for this "
203  "hierachy! Please create a new "
204  "DD4hep_SubDetectorAssembly for the next "
205  "hierarchy.");
206  }
207  nEndCap = true;
208  ACTS_VERBOSE(" ->is negative endcap");
209  collectLayers_dd4hep(volumeDetElement, negativeLayers);
210  // Fill the volume material for barrel case
211  if (volumeExtension->hasType("boundary_material")) {
212  if (volumeExtension->hasValue("boundary_material_negative")) {
214  *volumeExtension, "boundary_material_negative",
215  {{"binPhi", Acts::closed}, {"binR", Acts::open}});
216  }
217  if (volumeExtension->hasValue("boundary_material_positive")) {
219  *volumeExtension, "boundary_material_positive",
220  {{"binPhi", Acts::closed}, {"binR", Acts::open}});
221  }
222  }
223  } else {
224  if (pEndCap) {
225  throw std::logic_error(
226  "Positive Endcap was already given for this "
227  "hierachy! Please create a new "
228  "DD4hep_SubDetectorAssembly for the next "
229  "hierarchy.");
230  }
231  pEndCap = true;
232  ACTS_VERBOSE(" ->is positive endcap");
233  collectLayers_dd4hep(volumeDetElement, positiveLayers);
234  // Fill the volume material for barrel case
235  if (volumeExtension->hasType("boundary_material")) {
236  if (volumeExtension->hasValue("boundary_material_negative")) {
238  *volumeExtension, "boundary_material_negative",
239  {{"binPhi", Acts::closed}, {"binR", Acts::open}});
240  }
241  if (volumeExtension->hasValue("boundary_material_positive")) {
243  *volumeExtension, "boundary_material_positive",
244  {{"binPhi", Acts::closed}, {"binR", Acts::open}});
245  }
246  }
247  }
248  } else if (volumeExtension->hasType("barrel", "detector")) {
249  if (barrel) {
250  throw std::logic_error(
251  "Barrel was already given for this "
252  "hierachy! Please create a new "
253  "DD4hep_SubDetectorAssembly for the next "
254  "hierarchy.");
255  }
256  barrel = true;
257  ACTS_VERBOSE("Subvolume : "
258  << volumeDetElement.name()
259  << " is a cylinder volume -> handling as a barrel");
260  collectLayers_dd4hep(volumeDetElement, centralLayers);
261  // Fill the volume material for barrel case
262  if (volumeExtension->hasType("boundary_material")) {
263  if (volumeExtension->hasValue("boundary_material_negative")) {
265  *volumeExtension, "boundary_material_negative",
266  {{"binPhi", Acts::closed}, {"binR", Acts::open}});
267  }
268  if (volumeExtension->hasValue("boundary_material_positive")) {
270  *volumeExtension, "boundary_material_positive",
271  {{"binPhi", Acts::closed}, {"binR", Acts::open}});
272  }
273  }
274  } else {
275  throw std::logic_error(
276  std::string("Current DetElement: ") + volumeDetElement.name() +
277  std::string(
278  " has wrong ActsExtension! At this stage it should be a "
279  "detector volume declared as Barrel or Endcap. Please "
280  "check your detector construction."));
281  }
282 
283  // Fill the volume material for the inner / outer cover
284  if (volumeExtension->hasType("boundary_material")) {
285  if (volumeExtension->hasValue("boundary_material_inner")) {
287  *volumeExtension, "boundary_material_inner",
288  {{"binPhi", Acts::closed}, {"binZ", Acts::open}});
289  }
290  if (volumeExtension->hasValue("boundary_material_outer")) {
292  *volumeExtension, "boundary_material_outer",
293  {{"binPhi", Acts::closed}, {"binZ", Acts::open}});
294  }
295  }
296  }
297 
298  if ((pEndCap && !nEndCap) || (!pEndCap && nEndCap)) {
299  throw std::logic_error(
300  "Only one Endcap is given for the current "
301  "hierarchy! Endcaps should always occur in "
302  "pairs. Please check your detector "
303  "construction.");
304  }
305 
306  // configure SurfaceArrayCreator
307  auto surfaceArrayCreator =
308  std::make_shared<const Acts::SurfaceArrayCreator>(
309  Acts::getDefaultLogger("D2A_SAC", loggingLevel));
310  // configure LayerCreator
312  lcConfig.surfaceArrayCreator = surfaceArrayCreator;
313  auto layerCreator = std::make_shared<const Acts::LayerCreator>(
314  lcConfig, Acts::getDefaultLogger("D2A_LAC", loggingLevel));
315  // configure DD4hepLayerBuilder
317  lbConfig.configurationName = subDetector.name();
318  lbConfig.layerCreator = layerCreator;
319  lbConfig.negativeLayers = negativeLayers;
320  lbConfig.centralLayers = centralLayers;
321  lbConfig.positiveLayers = positiveLayers;
322  lbConfig.bTypePhi = bTypePhi;
323  lbConfig.bTypeR = bTypeR;
324  lbConfig.bTypeZ = bTypeZ;
325  lbConfig.defaultThickness = defaultLayerThickness;
326  auto dd4hepLayerBuilder = std::make_shared<const Acts::DD4hepLayerBuilder>(
327  lbConfig,
328  Acts::getDefaultLogger(std::string("D2A_L:") + subDetector.name(),
329  loggingLevel));
330 
331  // get the possible material of the surounding volume
332  dd4hep::Material ddmaterial = subDetector.volume().material();
333  auto volumeMaterial =
334  std::make_shared<const Acts::HomogeneousVolumeMaterial>(Acts::Material(
335  ddmaterial.radLength(), ddmaterial.intLength(), ddmaterial.A(),
336  ddmaterial.Z(), ddmaterial.density()));
337 
338  // Create the sub volume
339  // Dimensions are created automatically by adding a tolerance to the
340  // layer setup
341  cvbConfig.layerEnvelopeR = std::make_pair(layerEnvelopeR, layerEnvelopeR);
342  cvbConfig.layerEnvelopeZ = layerEnvelopeZ;
343  cvbConfig.trackingVolumeHelper = volumeHelper;
344  cvbConfig.volumeSignature = 0;
345  cvbConfig.volumeName = subDetector.name();
346  cvbConfig.volumeMaterial = volumeMaterial;
347  cvbConfig.layerBuilder = dd4hepLayerBuilder;
348  auto cylinderVolumeBuilder =
349  std::make_shared<const Acts::CylinderVolumeBuilder>(
350  cvbConfig,
351  Acts::getDefaultLogger(std::string("D2A_V:") + subDetector.name(),
352  loggingLevel));
353  return cylinderVolumeBuilder;
354 
355  } else if ((subDetExtension != nullptr) &&
356  (subDetExtension->hasType("passive cylinder", "layer") ||
357  subDetExtension->hasType("beampipe", "layer"))) {
358  ACTS_VERBOSE("Subdetector : " << subDetector.name()
359  << " - building a passive cylinder.");
360  if (subDetExtension->hasType("beampipe", "layer")) {
361  ACTS_VERBOSE("This is the beam pipe - will be built to r -> 0.");
362  }
363 
364  // get the dimensions of the volume
365  TGeoShape* geoShape =
366  subDetector.placement().ptr()->GetVolume()->GetShape();
367  TGeoTubeSeg* tube = dynamic_cast<TGeoTubeSeg*>(geoShape);
368  if (tube == nullptr) {
369  throw std::logic_error(
370  "Cylinder has wrong shape - needs to be TGeoTubeSeg!");
371  }
372  // get the dimension of TGeo and convert lengths
373  double rMin = tube->GetRmin() * UnitConstants::cm - layerEnvelopeR;
374  double rMax = tube->GetRmax() * UnitConstants::cm + layerEnvelopeR;
375  double halfZ = tube->GetDz() * UnitConstants::cm + layerEnvelopeZ;
376  ACTS_VERBOSE(
377  "Extracting cylindrical volume bounds ( rmin / rmax / "
378  "halfZ )= ( "
379  << rMin << " / " << rMax << " / " << halfZ << " )");
380 
381  std::shared_ptr<Acts::ISurfaceMaterial> plMaterial = nullptr;
382  if (subDetExtension->hasType("layer_material")) {
383  // get the possible material of the surounding volume
384  plMaterial = Acts::createProtoMaterial(
385  *subDetExtension, "layer_material_representing",
386  {{"binPhi", Acts::closed}, {"binZ", Acts::open}});
387  }
388 
389  // configure the passive layer builder
391  plbConfig.layerIdentification = subDetector.name();
392  plbConfig.centralLayerRadii = std::vector<double>(1, 0.5 * (rMax + rMin));
393  plbConfig.centralLayerHalflengthZ = std::vector<double>(1, halfZ);
394  plbConfig.centralLayerThickness = std::vector<double>(1, fabs(rMax - rMin));
395  plbConfig.centralLayerMaterial = {plMaterial};
396  auto pcLayerBuilder = std::make_shared<const Acts::PassiveLayerBuilder>(
397  plbConfig,
398  Acts::getDefaultLogger(std::string("D2A_PL:") + subDetector.name(),
399  loggingLevel));
400 
401  // the configuration object of the volume builder
403  cvbConfig.trackingVolumeHelper = volumeHelper;
404  cvbConfig.volumeSignature = 0;
405  cvbConfig.volumeName = subDetector.name();
406  cvbConfig.layerBuilder = pcLayerBuilder;
407  cvbConfig.layerEnvelopeR = {layerEnvelopeR, layerEnvelopeR};
408  cvbConfig.layerEnvelopeZ = layerEnvelopeZ;
409  cvbConfig.buildToRadiusZero = subDetExtension->hasType("beampipe", "layer");
410 
411  // beam pipe / passive cylinder volume builder
412  auto pcVolumeBuilder = std::make_shared<const Acts::CylinderVolumeBuilder>(
413  cvbConfig,
414  Acts::getDefaultLogger(std::string("D2A_V:") + subDetector.name(),
415  loggingLevel));
416  return pcVolumeBuilder;
417 
418  } else if ((subDetExtension != nullptr) &&
419  subDetExtension->hasType("barrel", "detector")) {
420  ACTS_VERBOSE("Subdetector: "
421  << subDetector.name()
422  << " is a (sensitive) Barrel volume - building barrel.");
424  std::vector<dd4hep::DetElement> centralLayers, centralVolumes;
425  collectLayers_dd4hep(subDetector, centralLayers);
426  collectVolumes_dd4hep(subDetector, centralVolumes);
427 
428  // configure SurfaceArrayCreator
429  auto surfaceArrayCreator =
430  std::make_shared<const Acts::SurfaceArrayCreator>(
431  Acts::getDefaultLogger("D2A_SAC", loggingLevel));
432  // configure LayerCreator
434  lcConfig.surfaceArrayCreator = surfaceArrayCreator;
435  auto layerCreator = std::make_shared<const Acts::LayerCreator>(
436  lcConfig, Acts::getDefaultLogger("D2A_LAC", loggingLevel));
437  // configure DD4hepLayerBuilder
439  lbConfig.configurationName = subDetector.name();
440  lbConfig.layerCreator = layerCreator;
441  lbConfig.centralLayers = centralLayers;
442  lbConfig.bTypePhi = bTypePhi;
443  lbConfig.bTypeZ = bTypeZ;
444  lbConfig.defaultThickness = defaultLayerThickness;
445  auto dd4hepLayerBuilder = std::make_shared<const Acts::DD4hepLayerBuilder>(
446  lbConfig,
447  Acts::getDefaultLogger(std::string("D2A_LB_") + subDetector.name(),
448  loggingLevel));
449 
450  // Configure DD4hepVolumeBuilder
452  vbConfig.configurationName = subDetector.name();
453  vbConfig.centralVolumes = centralVolumes;
454  auto dd4hepVolumeBuilder =
455  std::make_shared<const Acts::DD4hepVolumeBuilder>(
456  vbConfig,
457  Acts::getDefaultLogger(std::string("D2A_VB_") + subDetector.name(),
458  loggingLevel));
459 
460  // the configuration object of the volume builder
462  // get the dimensions of the volume
463  TGeoShape* geoShape =
464  subDetector.placement().ptr()->GetVolume()->GetShape();
465  // this should not happen
466  if (geoShape == nullptr) {
467  throw std::logic_error(std::string("Volume of DetElement: ") +
468  subDetector.name() +
469  std::string(" has no a shape!"));
470  }
471 
472  // get the possible material
474  dd4hep::Material ddmaterial = subDetector.volume().material();
475  auto volumeMaterial =
476  std::make_shared<const Acts::HomogeneousVolumeMaterial>(Acts::Material(
477  ddmaterial.radLength(), ddmaterial.intLength(), ddmaterial.A(),
478  ddmaterial.Z(), ddmaterial.density()));
479  cvbConfig.layerEnvelopeR = std::make_pair(layerEnvelopeR, layerEnvelopeR);
480  cvbConfig.layerEnvelopeZ = layerEnvelopeZ;
481  cvbConfig.trackingVolumeHelper = volumeHelper;
482  cvbConfig.volumeSignature = 0;
483  cvbConfig.volumeName = subDetector.name();
484  cvbConfig.volumeMaterial = volumeMaterial;
485  cvbConfig.layerBuilder = dd4hepLayerBuilder;
486  cvbConfig.ctVolumeBuilder = dd4hepVolumeBuilder;
487  auto cylinderVolumeBuilder =
488  std::make_shared<const Acts::CylinderVolumeBuilder>(
489  cvbConfig,
490  Acts::getDefaultLogger(std::string("D2A_V:") + subDetector.name(),
491  loggingLevel));
492  return cylinderVolumeBuilder;
493 
494  } else {
495  ACTS_INFO(
496  "Subdetector with name : '"
497  << subDetector.name()
498  << "' has wrong ActsExtension for translation and is not of type "
499  "'compound'. If you want to have this DetElement be translated "
500  "into the tracking geometry you need add the right "
501  "ActsExtension (at this stage the subvolume needs to be "
502  "declared as beampipe or barrel) or if it is a compound "
503  "DetElement (containing a barrel-endcap hierarchy), the type "
504  "needs to be set to 'compound'.");
505  return nullptr;
506  }
507 }
508 
509 std::shared_ptr<const Acts::CylinderVolumeHelper> cylinderVolumeHelper_dd4hep(
510  Logging::Level loggingLevel) {
511  // create cylindervolumehelper which can be used by all instances
512  // hand over LayerArrayCreator
514  auto layerArrayCreator = std::make_shared<const Acts::LayerArrayCreator>(
515  lacConfig, Acts::getDefaultLogger(std::string("D2A_LAC"), loggingLevel));
516  // tracking volume array creator
518  auto trackingVolumeArrayCreator =
519  std::make_shared<const Acts::TrackingVolumeArrayCreator>(
520  tvacConfig,
521  Acts::getDefaultLogger(std::string("D2A_TVAC"), loggingLevel));
522  // configure the cylinder volume helper
524  cvhConfig.layerArrayCreator = layerArrayCreator;
525  cvhConfig.trackingVolumeArrayCreator = trackingVolumeArrayCreator;
526  auto cylinderVolumeHelper =
527  std::make_shared<const Acts::CylinderVolumeHelper>(
528  cvhConfig,
529  Acts::getDefaultLogger(std::string("D2A_CVH"), loggingLevel));
530 
531  return cylinderVolumeHelper;
532 }
533 
534 void collectCompounds_dd4hep(dd4hep::DetElement& detElement,
535  std::vector<dd4hep::DetElement>& compounds) {
536  const dd4hep::DetElement::Children& children = detElement.children();
537  for (auto& child : children) {
538  dd4hep::DetElement childDetElement = child.second;
539  Acts::ActsExtension* detExtension = nullptr;
540  try {
541  detExtension = childDetElement.extension<Acts::ActsExtension>();
542  } catch (std::runtime_error& e) {
543  }
544  if ((detExtension != nullptr) &&
545  (detExtension->hasType("barrel", "detector") ||
546  detExtension->hasType("endcap", "detector"))) {
547  compounds.push_back(childDetElement);
548  continue;
549  }
550  collectCompounds_dd4hep(childDetElement, compounds);
551  }
552 }
553 
554 void collectSubDetectors_dd4hep(dd4hep::DetElement& detElement,
555  std::vector<dd4hep::DetElement>& subdetectors) {
556  const dd4hep::DetElement::Children& children = detElement.children();
557  for (auto& child : children) {
558  dd4hep::DetElement childDetElement = child.second;
559  Acts::ActsExtension* detExtension = nullptr;
560  try {
561  detExtension = childDetElement.extension<Acts::ActsExtension>();
562  } catch (std::runtime_error& e) {
563  if (childDetElement.type() == "compound") {
564  subdetectors.push_back(childDetElement);
565  continue;
566  }
567  }
568  if ((detExtension != nullptr) &&
569  (detExtension->hasType("barrel", "detector") ||
570  detExtension->hasType("beampipe", "layer"))) {
571  subdetectors.push_back(childDetElement);
572  continue;
573  }
574  collectSubDetectors_dd4hep(childDetElement, subdetectors);
575  }
576 }
577 
578 void collectLayers_dd4hep(dd4hep::DetElement& detElement,
579  std::vector<dd4hep::DetElement>& layers) {
580  const dd4hep::DetElement::Children& children = detElement.children();
581  for (auto& child : children) {
582  dd4hep::DetElement childDetElement = child.second;
583  Acts::ActsExtension* detExtension = nullptr;
584  try {
585  detExtension = childDetElement.extension<Acts::ActsExtension>();
586  } catch (std::runtime_error& e) {
587  }
588  if ((detExtension != nullptr) && detExtension->hasType("layer")) {
589  layers.push_back(childDetElement);
590  continue;
591  }
592  collectLayers_dd4hep(childDetElement, layers);
593  }
594 }
595 
596 void collectVolumes_dd4hep(dd4hep::DetElement& detElement,
597  std::vector<dd4hep::DetElement>& volumes) {
598  const dd4hep::DetElement::Children& children = detElement.children();
599  for (auto& child : children) {
600  dd4hep::DetElement childDetElement = child.second;
601  Acts::ActsExtension* detExtension = nullptr;
602  try {
603  detExtension = childDetElement.extension<Acts::ActsExtension>();
604  } catch (std::runtime_error& e) {
605  }
606  if ((detExtension != nullptr) && detExtension->hasType("volume")) {
607  volumes.push_back(childDetElement);
608  continue;
609  }
610  collectVolumes_dd4hep(childDetElement, volumes);
611  }
612 }
613 } // End of namespace Acts