41 #include "DD4hep/DetType.h"
42 #include "DDRec/DetectorData.h"
43 #include "TGeoManager.h"
46 class IMaterialDecorator;
47 class ISurfaceMaterial;
62 dd4hep::DetElement worldDetElement,
const Logger&
logger,
64 double layerEnvelopeR,
double layerEnvelopeZ,
double defaultLayerThickness,
65 const std::function<
void(std::vector<dd4hep::DetElement>&
detectors)>&
68 std::shared_ptr<const IMaterialDecorator> matDecorator,
69 std::shared_ptr<const GeometryIdentifierHook> geometryIdentifierHook) {
71 ACTS_INFO(
"Translating DD4hep geometry into Acts geometry");
74 std::vector<dd4hep::DetElement> subDetectors;
77 ACTS_VERBOSE(
"Collected " << subDetectors.size() <<
" sub detectors");
79 sortSubDetectors(subDetectors);
81 std::list<std::shared_ptr<const ITrackingVolumeBuilder>> volumeBuilders;
84 std::shared_ptr<const CylinderVolumeBuilder> beamPipeVolumeBuilder;
86 for (
auto& subDetector : subDetectors) {
87 ACTS_INFO(
"Translating DD4hep sub detector: " << subDetector.name());
89 const dd4hep::rec::VariantParameters* params =
90 subDetector.extension<dd4hep::rec::VariantParameters>(
false);
92 if (params !=
nullptr) {
94 for (
const auto& [
k,
v] : params->variantParameters) {
96 << boost::apply_visitor(DebugVisitor{},
v));
102 subDetector, logger, bTypePhi, bTypeR, bTypeZ, layerEnvelopeR,
103 layerEnvelopeZ, defaultLayerThickness);
106 if (volBuilder->getConfiguration().buildToRadiusZero) {
108 if (beamPipeVolumeBuilder) {
109 throw std::logic_error(
110 std::string(
"Beampipe has already been set! There can only "
111 "exist one beam pipe. Please check your "
112 "detector construction. Current volume name: ") +
113 volBuilder->getConfiguration().volumeName +
114 std::string(
", name of volume, already set as beam pipe: ") +
115 beamPipeVolumeBuilder->getConfiguration().volumeName);
118 beamPipeVolumeBuilder = volBuilder;
120 volumeBuilders.push_back(volBuilder);
125 if (beamPipeVolumeBuilder) {
126 volumeBuilders.push_back(beamPipeVolumeBuilder);
129 std::vector<std::function<std::shared_ptr<TrackingVolume>(
134 for (
const auto& vb : volumeBuilders) {
135 volumeFactories.push_back(
136 [vb](
const GeometryContext& vgctx,
137 const std::shared_ptr<const TrackingVolume>& inner,
139 return vb->trackingVolume(vgctx, inner);
151 auto trackingGeometryBuilder =
152 std::make_shared<const Acts::TrackingGeometryBuilder>(tgbConfig);
153 return (trackingGeometryBuilder->trackingGeometry(gctx));
159 double layerEnvelopeZ,
double defaultLayerThickness) {
163 ACTS_VERBOSE(
"Processing detector element: " << subDetector.name());
165 dd4hep::DetType subDetType{subDetector.typeFlag()};
167 << subDetType <<
"], compound: "
168 << (subDetector.type() ==
"compound" ?
"yes" :
"no"));
169 if (subDetector.type() ==
"compound") {
171 <<
"' has type compound ");
173 "handling as a compound volume (a hierarchy of a "
174 "barrel-endcap structure) and resolving the "
179 std::vector<dd4hep::DetElement> negativeLayers;
181 std::vector<dd4hep::DetElement> centralLayers;
183 std::vector<dd4hep::DetElement> positiveLayers;
189 std::vector<dd4hep::DetElement> compounds;
195 bool nEndCap =
false;
196 bool pEndCap =
false;
198 for (
auto& volumeDetElement : compounds) {
200 << subDetector.name()
201 <<
"' is a compound volume -> resolve the sub volumes");
204 TGeoShape* geoShape =
205 volumeDetElement.placement().ptr()->GetVolume()->GetShape();
207 if (geoShape !=
nullptr) {
208 zPos = volumeDetElement.placement()
211 ->GetTranslation()[2] *
214 throw std::logic_error(
std::string(
"Volume of DetElement: ") +
215 volumeDetElement.name() +
219 dd4hep::DetType
type{volumeDetElement.typeFlag()};
221 if (
type.is(dd4hep::DetType::ENDCAP)) {
226 throw std::logic_error(
227 "Negative Endcap was already given for this "
228 "hierarchy! Please create a new "
229 "DD4hep_SubDetectorAssembly for the next "
237 if (getParamOr<bool>(
"boundary_material", volumeDetElement,
false)) {
239 "-> boundary_material flag detected, creating proto "
241 auto& params =
getParams(volumeDetElement);
242 if (
hasParam(
"boundary_material_negative", volumeDetElement)) {
245 params,
"boundary_material_negative",
248 if (
hasParam(
"boundary_material_positive", volumeDetElement)) {
251 params,
"boundary_material_positive",
257 throw std::logic_error(
258 "Positive Endcap was already given for this "
259 "hierarchy! Please create a new "
260 "DD4hep_SubDetectorAssembly for the next "
268 if (getParamOr<bool>(
"boundary_material", volumeDetElement,
false)) {
270 "-> boundary_material flag detected, creating proto "
272 auto& params =
getParams(volumeDetElement);
273 if (params.contains(
"boundary_material_negative")) {
276 params,
"boundary_material_negative",
279 if (params.contains(
"boundary_material_positive")) {
282 params,
"boundary_material_positive",
287 }
else if (
type.is(dd4hep::DetType::BARREL)) {
289 throw std::logic_error(
290 "Barrel was already given for this "
291 "hierarchy! Please create a new "
292 "DD4hep_SubDetectorAssembly for the next "
297 <<
" is marked as BARREL");
301 if (getParamOr<bool>(
"boundary_material", volumeDetElement,
false)) {
303 "-> boundary_material flag detected, creating proto "
305 auto& params =
getParams(volumeDetElement);
306 if (params.contains(
"boundary_material_negative")) {
309 params,
"boundary_material_negative",
312 if (params.contains(
"boundary_material_positive")) {
315 params,
"boundary_material_positive",
320 throw std::logic_error(
321 std::string(
"Current DetElement: ") + volumeDetElement.name() +
322 std::string(
" has inconsistent settings. It's a compound,"
323 " but its DetectorType is neither BARREL nor ENDCAP"
324 " Please check your detector construction."));
328 if (getParamOr<bool>(
"boundary_material", volumeDetElement,
false)) {
330 "-> boundary_material flag detected, creating proto "
332 auto& params =
getParams(volumeDetElement);
333 if (params.contains(
"boundary_material_inner")) {
336 params,
"boundary_material_inner",
339 if (params.contains(
"boundary_material_outer")) {
342 params,
"boundary_material_outer",
348 if ((pEndCap && !nEndCap) || (!pEndCap && nEndCap)) {
349 throw std::logic_error(
350 "Only one Endcap is given for the current "
351 "hierarchy! Endcaps should always occur in "
352 "pairs. Please check your detector "
357 auto surfaceArrayCreator =
358 std::make_shared<const Acts::SurfaceArrayCreator>(
359 logger.
clone(
"D2A_SAC"));
363 auto layerCreator = std::make_shared<const Acts::LayerCreator>(
364 lcConfig, logger.
clone(
"D2A_LAC"));
368 lbConfig.layerCreator = layerCreator;
369 lbConfig.negativeLayers = negativeLayers;
370 lbConfig.centralLayers = centralLayers;
371 lbConfig.positiveLayers = positiveLayers;
372 lbConfig.bTypePhi = bTypePhi;
373 lbConfig.bTypeR = bTypeR;
374 lbConfig.bTypeZ = bTypeZ;
375 lbConfig.defaultThickness = defaultLayerThickness;
376 auto dd4hepLayerBuilder = std::make_shared<const Acts::DD4hepLayerBuilder>(
382 cvbConfig.
layerEnvelopeR = std::make_pair(layerEnvelopeR, layerEnvelopeR);
388 auto cylinderVolumeBuilder =
389 std::make_shared<const Acts::CylinderVolumeBuilder>(
392 return cylinderVolumeBuilder;
393 }
else if (subDetType.is(dd4hep::DetType::BEAMPIPE) ||
394 getParamOr<bool>(
"passive_layer", subDetector,
false)) {
396 <<
" - building a passive cylinder.");
398 if (subDetType.is(dd4hep::DetType::BEAMPIPE)) {
399 ACTS_VERBOSE(
"This is the beam pipe - will be built to r -> 0.");
403 TGeoShape* geoShape =
404 subDetector.placement().ptr()->GetVolume()->GetShape();
405 TGeoTubeSeg* tube =
dynamic_cast<TGeoTubeSeg*
>(geoShape);
406 if (tube ==
nullptr) {
407 throw std::logic_error(
408 "Cylinder has wrong shape - needs to be TGeoTubeSeg!");
415 "Extracting cylindrical volume bounds ( rmin / rmax / "
417 << rMin <<
" / " << rMax <<
" / " << halfZ <<
" )");
419 std::shared_ptr<Acts::ISurfaceMaterial> plMaterial =
nullptr;
420 if (getParamOr<bool>(
"layer_material", subDetector,
false)) {
422 ACTS_VERBOSE(
"--> adding layer material at 'representing'");
424 getParams(subDetector),
"layer_material_representing",
435 auto pcLayerBuilder = std::make_shared<const Acts::PassiveLayerBuilder>(
449 if (getParamOr<bool>(
"boundary_material", subDetector,
false)) {
451 "-> boundary_material flag detected, creating proto "
454 if (
hasParam(
"boundary_material_inner", subDetector)) {
457 params,
"boundary_material_inner",
460 if (
hasParam(
"boundary_material_outer", subDetector)) {
463 params,
"boundary_material_outer",
469 auto pcVolumeBuilder = std::make_shared<const Acts::CylinderVolumeBuilder>(
471 return pcVolumeBuilder;
472 }
else if (subDetType.is(dd4hep::DetType::BARREL)) {
474 << subDetector.name()
475 <<
" is a (sensitive) Barrel volume - building barrel.");
477 std::vector<dd4hep::DetElement> centralLayers, centralVolumes;
482 auto surfaceArrayCreator =
483 std::make_shared<const Acts::SurfaceArrayCreator>(
484 logger.
clone(
"D2A_SAC"));
488 auto layerCreator = std::make_shared<const Acts::LayerCreator>(
489 lcConfig, logger.
clone(
"D2A_LAC"));
493 lbConfig.layerCreator = layerCreator;
494 lbConfig.centralLayers = centralLayers;
495 lbConfig.bTypePhi = bTypePhi;
496 lbConfig.bTypeZ = bTypeZ;
497 lbConfig.defaultThickness = defaultLayerThickness;
498 auto dd4hepLayerBuilder = std::make_shared<const Acts::DD4hepLayerBuilder>(
505 auto dd4hepVolumeBuilder =
506 std::make_shared<const Acts::DD4hepVolumeBuilder>(
513 TGeoShape* geoShape =
514 subDetector.placement().ptr()->GetVolume()->GetShape();
516 if (geoShape ==
nullptr) {
517 throw std::logic_error(
std::string(
"Volume of DetElement: ") +
522 cvbConfig.
layerEnvelopeR = std::make_pair(layerEnvelopeR, layerEnvelopeR);
529 auto cylinderVolumeBuilder =
530 std::make_shared<const Acts::CylinderVolumeBuilder>(
533 return cylinderVolumeBuilder;
536 "Subdetector with name : '"
537 << subDetector.name()
538 <<
"' has inconsistent information for translation and is not of type "
539 "'compound'. If you want to have this DetElement be translated "
540 "into the tracking geometry you need add the right DetectorType "
541 "or VariantParameters (at this stage the subvolume needs to be "
542 "declared as BEAMPIPE or BARREl, or have a VariantParameter "
543 "passive_layer=true) or if it is a compound DetElement (containing "
544 "a barrel-endcap hierarchy), the type needs to be set to "
555 auto layerArrayCreator = std::make_shared<const Acts::LayerArrayCreator>(
556 lacConfig, logger.
clone(
"D2A_LAC"));
559 auto trackingVolumeArrayCreator =
560 std::make_shared<const Acts::TrackingVolumeArrayCreator>(
561 tvacConfig, logger.
clone(
"D2A_TVAC"));
565 cvhConfig.trackingVolumeArrayCreator = trackingVolumeArrayCreator;
566 auto cylinderVolumeHelper =
567 std::make_shared<const Acts::CylinderVolumeHelper>(
568 cvhConfig, logger.
clone(
"D2A_CVH"));
570 return cylinderVolumeHelper;
574 std::vector<dd4hep::DetElement>& compounds) {
575 const dd4hep::DetElement::Children& children = detElement.children();
576 for (
auto&
child : children) {
577 dd4hep::DetElement childDetElement =
child.second;
578 dd4hep::DetType
type{childDetElement.typeFlag()};
579 if (
type.is(dd4hep::DetType::BARREL) ||
type.is(dd4hep::DetType::ENDCAP)) {
580 compounds.push_back(childDetElement);
587 std::vector<dd4hep::DetElement>& subdetectors,
589 const dd4hep::DetElement::Children& children = detElement.children();
590 for (
auto&
child : children) {
591 dd4hep::DetElement childDetElement =
child.second;
592 dd4hep::DetType
type{childDetElement.typeFlag()};
593 if (childDetElement.type() ==
"compound") {
594 subdetectors.push_back(childDetElement);
598 if (
type.is(dd4hep::DetType::TRACKER)) {
599 subdetectors.push_back(childDetElement);
606 std::vector<dd4hep::DetElement>& layers,
608 const dd4hep::DetElement::Children& children = detElement.children();
609 for (
auto&
child : children) {
612 dd4hep::rec::VariantParameters* params =
613 detElement.extension<dd4hep::rec::VariantParameters>(
false);
615 if (params !=
nullptr) {
616 _expr = params->value_or<
std::string>(
"layer_pattern", _expr);
617 ACTS_VERBOSE(
"--> Layer pattern for elt " << detElement.name() <<
": "
620 std::regex expr{_expr};
622 dd4hep::DetElement childDetElement =
child.second;
624 if (std::regex_search(childDetElement.name(), expr)) {
625 ACTS_VERBOSE(
"--> Layer candidate match: " << _expr <<
" -> "
626 << childDetElement.name());
627 layers.push_back(childDetElement);