Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:10:16

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2017-2018 CERN for the benefit of the Acts project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
0008 
0009 #include "Acts/Plugins/DD4hep/ConvertDD4hepDetector.hpp"
0010 
0011 #include "Acts/Geometry/CylinderVolumeBuilder.hpp"
0012 #include "Acts/Geometry/CylinderVolumeHelper.hpp"
0013 #include "Acts/Geometry/GeometryContext.hpp"
0014 #include "Acts/Geometry/ITrackingVolumeArrayCreator.hpp"
0015 #include "Acts/Geometry/ITrackingVolumeBuilder.hpp"
0016 #include "Acts/Geometry/LayerArrayCreator.hpp"
0017 #include "Acts/Geometry/LayerCreator.hpp"
0018 #include "Acts/Geometry/PassiveLayerBuilder.hpp"
0019 #include "Acts/Geometry/SurfaceArrayCreator.hpp"
0020 #include "Acts/Geometry/TrackingGeometryBuilder.hpp"
0021 #include "Acts/Geometry/TrackingVolumeArrayCreator.hpp"
0022 #include "Acts/Geometry/Volume.hpp"
0023 #include "Acts/Material/ISurfaceMaterial.hpp"
0024 #include "Acts/Material/ProtoSurfaceMaterial.hpp"
0025 #include "Acts/Plugins/DD4hep/DD4hepConversionHelpers.hpp"
0026 #include "Acts/Plugins/DD4hep/DD4hepLayerBuilder.hpp"
0027 #include "Acts/Plugins/DD4hep/DD4hepMaterialHelpers.hpp"
0028 #include "Acts/Plugins/DD4hep/DD4hepVolumeBuilder.hpp"
0029 #include "Acts/Utilities/Logger.hpp"
0030 
0031 #include <array>
0032 #include <cmath>
0033 #include <list>
0034 #include <map>
0035 #include <regex>
0036 #include <sstream>
0037 #include <stdexcept>
0038 #include <string>
0039 #include <utility>
0040 
0041 #include "DD4hep/DetType.h"
0042 #include "DDRec/DetectorData.h"
0043 #include "TGeoManager.h"
0044 
0045 namespace Acts {
0046 class IMaterialDecorator;
0047 class ISurfaceMaterial;
0048 class TrackingGeometry;
0049 class TrackingVolume;
0050 
0051 namespace {
0052 struct DebugVisitor {
0053   std::string operator()(int value) { return std::to_string(value); }
0054 
0055   std::string operator()(double value) { return std::to_string(value); }
0056 
0057   std::string operator()(std::string value) { return value; }
0058 };
0059 }  // namespace
0060 
0061 std::unique_ptr<const TrackingGeometry> convertDD4hepDetector(
0062     dd4hep::DetElement worldDetElement, const Logger& logger,
0063     BinningType bTypePhi, BinningType bTypeR, BinningType bTypeZ,
0064     double layerEnvelopeR, double layerEnvelopeZ, double defaultLayerThickness,
0065     const std::function<void(std::vector<dd4hep::DetElement>& detectors)>&
0066         sortSubDetectors,
0067     const Acts::GeometryContext& gctx,
0068     std::shared_ptr<const IMaterialDecorator> matDecorator,
0069     std::shared_ptr<const GeometryIdentifierHook> geometryIdentifierHook) {
0070   // create local logger for conversion
0071   ACTS_INFO("Translating DD4hep geometry into Acts geometry");
0072   // get the sub detectors of the world detector e.g. beampipe, pixel detector,
0073   // strip detector
0074   std::vector<dd4hep::DetElement> subDetectors;
0075   // go through the detector hierarchies
0076   collectSubDetectors_dd4hep(worldDetElement, subDetectors, logger);
0077   ACTS_VERBOSE("Collected " << subDetectors.size() << " sub detectors");
0078   // sort to build detector from bottom to top
0079   sortSubDetectors(subDetectors);
0080   // the volume builders of the subdetectors
0081   std::list<std::shared_ptr<const ITrackingVolumeBuilder>> volumeBuilders;
0082   // the beam pipe volume builder needs special treatment and needs to be added
0083   // in the end (beampipe exceeds length of all other subdetectors)
0084   std::shared_ptr<const CylinderVolumeBuilder> beamPipeVolumeBuilder;
0085   // loop over the sub detectors
0086   for (auto& subDetector : subDetectors) {
0087     ACTS_INFO("Translating DD4hep sub detector: " << subDetector.name());
0088 
0089     const dd4hep::rec::VariantParameters* params =
0090         subDetector.extension<dd4hep::rec::VariantParameters>(false);
0091 
0092     if (params != nullptr) {
0093       ACTS_VERBOSE("VariantParameters from DD4hep:");
0094       for (const auto& [k, v] : params->variantParameters) {
0095         ACTS_VERBOSE("- " << k << ": "
0096                           << boost::apply_visitor(DebugVisitor{}, v));
0097       }
0098     }
0099 
0100     // create volume builder
0101     auto volBuilder = volumeBuilder_dd4hep(
0102         subDetector, logger, bTypePhi, bTypeR, bTypeZ, layerEnvelopeR,
0103         layerEnvelopeZ, defaultLayerThickness);
0104     if (volBuilder != nullptr) {
0105       // distinguish beam pipe
0106       if (volBuilder->getConfiguration().buildToRadiusZero) {
0107         // check if beam pipe is already present
0108         if (beamPipeVolumeBuilder) {
0109           throw std::logic_error(
0110               std::string("Beampipe has already been set! There can only "
0111                           "exist one beam pipe. Please check your "
0112                           "detector construction. Current volume name: ") +
0113               volBuilder->getConfiguration().volumeName +
0114               std::string(", name of volume, already set as beam pipe: ") +
0115               beamPipeVolumeBuilder->getConfiguration().volumeName);
0116         }
0117         // set the beam pipe
0118         beamPipeVolumeBuilder = volBuilder;
0119       } else {
0120         volumeBuilders.push_back(volBuilder);
0121       }
0122     }
0123   }
0124   // Finally add the beam pipe
0125   if (beamPipeVolumeBuilder != nullptr) {
0126     volumeBuilders.push_back(beamPipeVolumeBuilder);
0127   }
0128 
0129   std::vector<std::function<std::shared_ptr<TrackingVolume>(
0130       const GeometryContext&, const TrackingVolumePtr&,
0131       const std::shared_ptr<const VolumeBounds>&)>>
0132       volumeFactories;
0133 
0134   for (const auto& vb : volumeBuilders) {
0135     volumeFactories.push_back(
0136         [vb](const GeometryContext& vgctx,
0137              const std::shared_ptr<const TrackingVolume>& inner,
0138              const std::shared_ptr<const VolumeBounds>&) {
0139           return vb->trackingVolume(vgctx, inner);
0140         });
0141   }
0142 
0143   // create cylinder volume helper
0144   auto volumeHelper = cylinderVolumeHelper_dd4hep(logger);
0145   // hand over the collected volume builders
0146   Acts::TrackingGeometryBuilder::Config tgbConfig;
0147   tgbConfig.trackingVolumeHelper = volumeHelper;
0148   tgbConfig.materialDecorator = std::move(matDecorator);
0149   tgbConfig.trackingVolumeBuilders = std::move(volumeFactories);
0150   tgbConfig.geometryIdentifierHook = std::move(geometryIdentifierHook);
0151   auto trackingGeometryBuilder =
0152       std::make_shared<const Acts::TrackingGeometryBuilder>(tgbConfig);
0153   return (trackingGeometryBuilder->trackingGeometry(gctx));
0154 }
0155 
0156 std::shared_ptr<const CylinderVolumeBuilder> volumeBuilder_dd4hep(
0157     dd4hep::DetElement subDetector, const Logger& logger, BinningType bTypePhi,
0158     BinningType bTypeR, BinningType bTypeZ, double layerEnvelopeR,
0159     double layerEnvelopeZ, double defaultLayerThickness) {
0160   // create cylinder volume helper
0161   auto volumeHelper = cylinderVolumeHelper_dd4hep(logger);
0162   // create local logger for conversion
0163   ACTS_VERBOSE("Processing detector element:  " << subDetector.name());
0164   dd4hep::DetType subDetType{subDetector.typeFlag()};
0165   ACTS_VERBOSE("SubDetector type is: ["
0166                << subDetType << "], compound: "
0167                << (subDetector.type() == "compound" ? "yes" : "no"));
0168 
0169   if (subDetector.type() == "compound") {
0170     ACTS_VERBOSE("Subdetector: '" << subDetector.name()
0171                                   << "' has type compound ");
0172     ACTS_VERBOSE(
0173         "handling as a compound volume (a hierarchy of a "
0174         "barrel-endcap structure) and resolving the "
0175         "subvolumes...");
0176     // Now create the Layerbuilders and Volumebuilder
0177     // the layers
0178     /// the dd4hep::DetElements of the layers of the negative volume
0179     std::vector<dd4hep::DetElement> negativeLayers;
0180     /// the dd4hep::DetElements of the layers of the central volume
0181     std::vector<dd4hep::DetElement> centralLayers;
0182     /// the dd4hep::DetElements of the layers of the positive volume
0183     std::vector<dd4hep::DetElement> positiveLayers;
0184 
0185     // the configuration object of the volume builder
0186     Acts::CylinderVolumeBuilder::Config cvbConfig;
0187 
0188     // go through sub volumes
0189     std::vector<dd4hep::DetElement> compounds;
0190     collectCompounds_dd4hep(subDetector, compounds);
0191 
0192     // get z position to distinguish positive & negative endcap
0193     double zPos = 0.;
0194     // flags to catch if sub volumes have been set already
0195     bool nEndCap = false;
0196     bool pEndCap = false;
0197     bool barrel = false;
0198     for (auto& volumeDetElement : compounds) {
0199       ACTS_VERBOSE("Volume: '"
0200                    << subDetector.name()
0201                    << "' is a compound volume -> resolve the sub volumes");
0202 
0203       // get the dimensions of the volume
0204       TGeoShape* geoShape =
0205           volumeDetElement.placement().ptr()->GetVolume()->GetShape();
0206       // check if it has a shape (the other case should not happen)
0207       if (geoShape != nullptr) {
0208         zPos = volumeDetElement.placement()
0209                    .ptr()
0210                    ->GetMatrix()
0211                    ->GetTranslation()[2] *
0212                UnitConstants::cm;
0213       } else {
0214         throw std::logic_error(std::string("Volume of DetElement: ") +
0215                                volumeDetElement.name() +
0216                                std::string(" has no shape!"));
0217       }
0218 
0219       dd4hep::DetType type{volumeDetElement.typeFlag()};
0220 
0221       if (type.is(dd4hep::DetType::ENDCAP)) {
0222         ACTS_VERBOSE("Subvolume: '" << volumeDetElement.name()
0223                                     << "' is marked ENDCAP");
0224         if (zPos < 0.) {
0225           if (nEndCap) {
0226             throw std::logic_error(
0227                 "Negative Endcap was already given for this "
0228                 "hierarchy! Please create a new "
0229                 "DD4hep_SubDetectorAssembly for the next "
0230                 "hierarchy.");
0231           }
0232           nEndCap = true;
0233           ACTS_VERBOSE("-> is negative endcap");
0234           ACTS_VERBOSE("-> collecting layers");
0235           collectLayers_dd4hep(volumeDetElement, negativeLayers, logger);
0236           // Fill the volume material for barrel case
0237           if (getParamOr<bool>("boundary_material", volumeDetElement, false)) {
0238             ACTS_VERBOSE(
0239                 "-> boundary_material flag detected, creating proto "
0240                 "material.");
0241             auto& params = getParams(volumeDetElement);
0242             if (hasParam("boundary_material_negative", volumeDetElement)) {
0243               ACTS_VERBOSE("--> negative");
0244               cvbConfig.boundaryMaterial[2] = Acts::createProtoMaterial(
0245                   params, "boundary_material_negative",
0246                   {{"binPhi", Acts::closed}, {"binR", Acts::open}}, logger);
0247             }
0248             if (hasParam("boundary_material_positive", volumeDetElement)) {
0249               ACTS_VERBOSE("--> positive");
0250               cvbConfig.boundaryMaterial[3] = Acts::createProtoMaterial(
0251                   params, "boundary_material_positive",
0252                   {{"binPhi", Acts::closed}, {"binR", Acts::open}}, logger);
0253             }
0254           }
0255         } else {
0256           if (pEndCap) {
0257             throw std::logic_error(
0258                 "Positive Endcap was already given for this "
0259                 "hierarchy! Please create a new "
0260                 "DD4hep_SubDetectorAssembly for the next "
0261                 "hierarchy.");
0262           }
0263           pEndCap = true;
0264           ACTS_VERBOSE("-> is positive endcap");
0265           ACTS_VERBOSE("-> collecting layers");
0266           collectLayers_dd4hep(volumeDetElement, positiveLayers, logger);
0267           // Fill the volume material for barrel case
0268           if (getParamOr<bool>("boundary_material", volumeDetElement, false)) {
0269             ACTS_VERBOSE(
0270                 "-> boundary_material flag detected, creating proto "
0271                 "material.");
0272             auto& params = getParams(volumeDetElement);
0273             if (params.contains("boundary_material_negative")) {
0274               ACTS_VERBOSE("--> negative");
0275               cvbConfig.boundaryMaterial[4] = Acts::createProtoMaterial(
0276                   params, "boundary_material_negative",
0277                   {{"binPhi", Acts::closed}, {"binR", Acts::open}}, logger);
0278             }
0279             if (params.contains("boundary_material_positive")) {
0280               ACTS_VERBOSE("--> positive");
0281               cvbConfig.boundaryMaterial[5] = Acts::createProtoMaterial(
0282                   params, "boundary_material_positive",
0283                   {{"binPhi", Acts::closed}, {"binR", Acts::open}}, logger);
0284             }
0285           }
0286         }
0287       } else if (type.is(dd4hep::DetType::BARREL)) {
0288         if (barrel) {
0289           throw std::logic_error(
0290               "Barrel was already given for this "
0291               "hierarchy! Please create a new "
0292               "DD4hep_SubDetectorAssembly for the next "
0293               "hierarchy.");
0294         }
0295         barrel = true;
0296         ACTS_VERBOSE("Subvolume: " << volumeDetElement.name()
0297                                    << " is marked as BARREL");
0298         ACTS_VERBOSE("-> collecting layers");
0299         collectLayers_dd4hep(volumeDetElement, centralLayers, logger);
0300         // Fill the volume material for barrel case
0301         if (getParamOr<bool>("boundary_material", volumeDetElement, false)) {
0302           ACTS_VERBOSE(
0303               "-> boundary_material flag detected, creating proto "
0304               "material.");
0305           auto& params = getParams(volumeDetElement);
0306           if (params.contains("boundary_material_negative")) {
0307             ACTS_VERBOSE("--> negative");
0308             cvbConfig.boundaryMaterial[3] = Acts::createProtoMaterial(
0309                 params, "boundary_material_negative",
0310                 {{"binPhi", Acts::closed}, {"binR", Acts::open}}, logger);
0311           }
0312           if (params.contains("boundary_material_positive")) {
0313             ACTS_VERBOSE("--> positive");
0314             cvbConfig.boundaryMaterial[4] = Acts::createProtoMaterial(
0315                 params, "boundary_material_positive",
0316                 {{"binPhi", Acts::closed}, {"binR", Acts::open}}, logger);
0317           }
0318         }
0319       } else {
0320         throw std::logic_error(
0321             std::string("Current DetElement: ") + volumeDetElement.name() +
0322             std::string(" has inconsistent settings. It's a compound,"
0323                         " but its DetectorType is neither BARREL nor ENDCAP"
0324                         " Please check your detector construction."));
0325       }
0326 
0327       // Fill the volume material for the inner / outer cover
0328       if (getParamOr<bool>("boundary_material", volumeDetElement, false)) {
0329         ACTS_VERBOSE(
0330             "-> boundary_material flag detected, creating proto "
0331             "material.");
0332         auto& params = getParams(volumeDetElement);
0333         if (params.contains("boundary_material_inner")) {
0334           ACTS_VERBOSE("--> inner");
0335           cvbConfig.boundaryMaterial[0] = Acts::createProtoMaterial(
0336               params, "boundary_material_inner",
0337               {{"binPhi", Acts::closed}, {"binZ", Acts::open}}, logger);
0338         }
0339         if (params.contains("boundary_material_outer")) {
0340           ACTS_VERBOSE("--> outer");
0341           cvbConfig.boundaryMaterial[1] = Acts::createProtoMaterial(
0342               params, "boundary_material_outer",
0343               {{"binPhi", Acts::closed}, {"binZ", Acts::open}}, logger);
0344         }
0345       }
0346     }
0347 
0348     if ((pEndCap && !nEndCap) || (!pEndCap && nEndCap)) {
0349       throw std::logic_error(
0350           "Only one Endcap is given for the current "
0351           "hierarchy! Endcaps should always occur in "
0352           "pairs. Please check your detector "
0353           "construction.");
0354     }
0355 
0356     // configure SurfaceArrayCreator
0357     auto surfaceArrayCreator =
0358         std::make_shared<const Acts::SurfaceArrayCreator>(
0359             logger.clone("D2A_SAC"));
0360     // configure LayerCreator
0361     Acts::LayerCreator::Config lcConfig;
0362     lcConfig.surfaceArrayCreator = surfaceArrayCreator;
0363     auto layerCreator = std::make_shared<const Acts::LayerCreator>(
0364         lcConfig, logger.clone("D2A_LAC"));
0365     // configure DD4hepLayerBuilder
0366     Acts::DD4hepLayerBuilder::Config lbConfig;
0367     lbConfig.configurationName = subDetector.name();
0368     lbConfig.layerCreator = layerCreator;
0369     lbConfig.negativeLayers = negativeLayers;
0370     lbConfig.centralLayers = centralLayers;
0371     lbConfig.positiveLayers = positiveLayers;
0372     lbConfig.bTypePhi = bTypePhi;
0373     lbConfig.bTypeR = bTypeR;
0374     lbConfig.bTypeZ = bTypeZ;
0375     lbConfig.defaultThickness = defaultLayerThickness;
0376     auto dd4hepLayerBuilder = std::make_shared<const Acts::DD4hepLayerBuilder>(
0377         lbConfig, logger.clone(std::string("D2A_L:") + subDetector.name()));
0378 
0379     // Create the sub volume
0380     // Dimensions are created automatically by adding a tolerance to the
0381     // layer setup
0382     cvbConfig.layerEnvelopeR = std::make_pair(layerEnvelopeR, layerEnvelopeR);
0383     cvbConfig.layerEnvelopeZ = layerEnvelopeZ;
0384     cvbConfig.trackingVolumeHelper = volumeHelper;
0385     cvbConfig.volumeName = subDetector.name();
0386     cvbConfig.layerBuilder = dd4hepLayerBuilder;
0387     auto cylinderVolumeBuilder =
0388         std::make_shared<const Acts::CylinderVolumeBuilder>(
0389             cvbConfig,
0390             logger.clone(std::string("D2A_V:") + subDetector.name()));
0391     return cylinderVolumeBuilder;
0392   } else if (subDetType.is(dd4hep::DetType::BEAMPIPE) ||
0393              getParamOr<bool>("passive_layer", subDetector, false)) {
0394     ACTS_VERBOSE("Subdetector: " << subDetector.name()
0395                                  << " - building a passive cylinder.");
0396 
0397     if (subDetType.is(dd4hep::DetType::BEAMPIPE)) {
0398       ACTS_VERBOSE("This is the beam pipe - will be built to r -> 0.");
0399     }
0400 
0401     // get the dimensions of the volume
0402     TGeoShape* geoShape =
0403         subDetector.placement().ptr()->GetVolume()->GetShape();
0404     TGeoTubeSeg* tube = dynamic_cast<TGeoTubeSeg*>(geoShape);
0405     if (tube == nullptr) {
0406       throw std::logic_error(
0407           "Cylinder has wrong shape - needs to be TGeoTubeSeg!");
0408     }
0409     // get the dimension of TGeo and convert lengths
0410     double rMin = tube->GetRmin() * UnitConstants::cm - layerEnvelopeR;
0411     double rMax = tube->GetRmax() * UnitConstants::cm + layerEnvelopeR;
0412     double halfZ = tube->GetDz() * UnitConstants::cm + layerEnvelopeZ;
0413     ACTS_VERBOSE(
0414         "Extracting cylindrical volume bounds ( rmin / rmax / "
0415         "halfZ )=  ( "
0416         << rMin << " / " << rMax << " / " << halfZ << " )");
0417 
0418     std::shared_ptr<Acts::ISurfaceMaterial> plMaterial = nullptr;
0419     if (getParamOr<bool>("layer_material", subDetector, false)) {
0420       // get the possible material of the surrounding volume
0421       ACTS_VERBOSE("--> adding layer material at 'representing'");
0422       plMaterial = Acts::createProtoMaterial(
0423           getParams(subDetector), "layer_material_representing",
0424           {{"binPhi", Acts::closed}, {"binZ", Acts::open}}, logger);
0425     }
0426 
0427     // configure the passive layer builder
0428     Acts::PassiveLayerBuilder::Config plbConfig;
0429     plbConfig.layerIdentification = subDetector.name();
0430     plbConfig.centralLayerRadii = std::vector<double>(1, 0.5 * (rMax + rMin));
0431     plbConfig.centralLayerHalflengthZ = std::vector<double>(1, halfZ);
0432     plbConfig.centralLayerThickness = std::vector<double>(1, fabs(rMax - rMin));
0433     plbConfig.centralLayerMaterial = {plMaterial};
0434     auto pcLayerBuilder = std::make_shared<const Acts::PassiveLayerBuilder>(
0435         plbConfig, logger.clone(std::string("D2A_PL:") + subDetector.name()));
0436 
0437     // the configuration object of the volume builder
0438     Acts::CylinderVolumeBuilder::Config cvbConfig;
0439     cvbConfig.trackingVolumeHelper = volumeHelper;
0440     cvbConfig.volumeName = subDetector.name();
0441     cvbConfig.layerBuilder = pcLayerBuilder;
0442     cvbConfig.layerEnvelopeR = {layerEnvelopeR, layerEnvelopeR};
0443     cvbConfig.layerEnvelopeZ = layerEnvelopeZ;
0444     cvbConfig.buildToRadiusZero = subDetType.is(dd4hep::DetType::BEAMPIPE);
0445 
0446     // Fill the volume material for the inner / outer cover
0447     if (getParamOr<bool>("boundary_material", subDetector, false)) {
0448       ACTS_VERBOSE(
0449           "-> boundary_material flag detected, creating proto "
0450           "material.");
0451       auto& params = getParams(subDetector);
0452       if (hasParam("boundary_material_inner", subDetector)) {
0453         ACTS_VERBOSE("--> inner");
0454         cvbConfig.boundaryMaterial[0] = Acts::createProtoMaterial(
0455             params, "boundary_material_inner",
0456             {{"binPhi", Acts::closed}, {"binZ", Acts::open}}, logger);
0457       }
0458       if (hasParam("boundary_material_outer", subDetector)) {
0459         ACTS_VERBOSE("--> outer");
0460         cvbConfig.boundaryMaterial[1] = Acts::createProtoMaterial(
0461             params, "boundary_material_outer",
0462             {{"binPhi", Acts::closed}, {"binZ", Acts::open}}, logger);
0463       }
0464     }
0465 
0466     // beam pipe / passive cylinder volume builder
0467     auto pcVolumeBuilder = std::make_shared<const Acts::CylinderVolumeBuilder>(
0468         cvbConfig, logger.clone(std::string("D2A_V:") + subDetector.name()));
0469     return pcVolumeBuilder;
0470   } else if (subDetType.is(dd4hep::DetType::BARREL)) {
0471     ACTS_VERBOSE("Subdetector: "
0472                  << subDetector.name()
0473                  << " is a (sensitive) Barrel volume - building barrel.");
0474     /// the dd4hep::DetElements of the layers of the central volume
0475     std::vector<dd4hep::DetElement> centralLayers, centralVolumes;
0476     ACTS_VERBOSE("-> collecting layers");
0477     collectLayers_dd4hep(subDetector, centralLayers, logger);
0478 
0479     // configure SurfaceArrayCreator
0480     auto surfaceArrayCreator =
0481         std::make_shared<const Acts::SurfaceArrayCreator>(
0482             logger.clone("D2A_SAC"));
0483     // configure LayerCreator
0484     Acts::LayerCreator::Config lcConfig;
0485     lcConfig.surfaceArrayCreator = surfaceArrayCreator;
0486     auto layerCreator = std::make_shared<const Acts::LayerCreator>(
0487         lcConfig, logger.clone("D2A_LAC"));
0488     // configure DD4hepLayerBuilder
0489     Acts::DD4hepLayerBuilder::Config lbConfig;
0490     lbConfig.configurationName = subDetector.name();
0491     lbConfig.layerCreator = layerCreator;
0492     lbConfig.centralLayers = centralLayers;
0493     lbConfig.bTypePhi = bTypePhi;
0494     lbConfig.bTypeZ = bTypeZ;
0495     lbConfig.defaultThickness = defaultLayerThickness;
0496     auto dd4hepLayerBuilder = std::make_shared<const Acts::DD4hepLayerBuilder>(
0497         lbConfig, logger.clone(std::string("D2A_LB_") + subDetector.name()));
0498 
0499     // Configure DD4hepVolumeBuilder
0500     Acts::DD4hepVolumeBuilder::Config vbConfig;
0501     vbConfig.configurationName = subDetector.name();
0502     vbConfig.centralVolumes = centralVolumes;
0503     auto dd4hepVolumeBuilder =
0504         std::make_shared<const Acts::DD4hepVolumeBuilder>(
0505             vbConfig,
0506             logger.clone(std::string("D2A_VB_") + subDetector.name()));
0507 
0508     // the configuration object of the volume builder
0509     Acts::CylinderVolumeBuilder::Config cvbConfig;
0510     // get the dimensions of the volume
0511     TGeoShape* geoShape =
0512         subDetector.placement().ptr()->GetVolume()->GetShape();
0513     // this should not happen
0514     if (geoShape == nullptr) {
0515       throw std::logic_error(std::string("Volume of DetElement: ") +
0516                              subDetector.name() +
0517                              std::string(" has no a shape!"));
0518     }
0519 
0520     cvbConfig.layerEnvelopeR = std::make_pair(layerEnvelopeR, layerEnvelopeR);
0521     cvbConfig.layerEnvelopeZ = layerEnvelopeZ;
0522     cvbConfig.trackingVolumeHelper = volumeHelper;
0523     cvbConfig.volumeName = subDetector.name();
0524     cvbConfig.layerBuilder = dd4hepLayerBuilder;
0525     cvbConfig.ctVolumeBuilder = dd4hepVolumeBuilder;
0526     auto cylinderVolumeBuilder =
0527         std::make_shared<const Acts::CylinderVolumeBuilder>(
0528             cvbConfig,
0529             logger.clone(std::string("D2A_V:") + subDetector.name()));
0530     return cylinderVolumeBuilder;
0531   } else {
0532     ACTS_WARNING(
0533         "Subdetector with name: '"
0534         << subDetector.name()
0535         << "' has inconsistent information for translation and is not of type "
0536            "'compound'. If you want to have this DetElement be translated "
0537            "into the tracking geometry you need add the right DetectorType "
0538            "or VariantParameters (at this stage the subvolume needs to be "
0539            "declared as BEAMPIPE or BARREl, or have a VariantParameter "
0540            "passive_layer=true) or if it is a compound DetElement (containing "
0541            "a barrel-endcap hierarchy), the type needs to be set to "
0542            "'compound'.");
0543     return nullptr;
0544   }
0545 }
0546 
0547 std::shared_ptr<const Acts::CylinderVolumeHelper> cylinderVolumeHelper_dd4hep(
0548     const Logger& logger) {
0549   // create cylindervolumehelper which can be used by all instances
0550   // hand over LayerArrayCreator
0551   Acts::LayerArrayCreator::Config lacConfig;
0552   auto layerArrayCreator = std::make_shared<const Acts::LayerArrayCreator>(
0553       lacConfig, logger.clone("D2A_LAC"));
0554   // tracking volume array creator
0555   Acts::TrackingVolumeArrayCreator::Config tvacConfig;
0556   auto trackingVolumeArrayCreator =
0557       std::make_shared<const Acts::TrackingVolumeArrayCreator>(
0558           tvacConfig, logger.clone("D2A_TVAC"));
0559   // configure the cylinder volume helper
0560   Acts::CylinderVolumeHelper::Config cvhConfig;
0561   cvhConfig.layerArrayCreator = layerArrayCreator;
0562   cvhConfig.trackingVolumeArrayCreator = trackingVolumeArrayCreator;
0563   auto cylinderVolumeHelper =
0564       std::make_shared<const Acts::CylinderVolumeHelper>(
0565           cvhConfig, logger.clone("D2A_CVH"));
0566 
0567   return cylinderVolumeHelper;
0568 }
0569 
0570 void collectCompounds_dd4hep(dd4hep::DetElement& detElement,
0571                              std::vector<dd4hep::DetElement>& compounds) {
0572   const dd4hep::DetElement::Children& children = detElement.children();
0573   for (auto& child : children) {
0574     dd4hep::DetElement childDetElement = child.second;
0575     dd4hep::DetType type{childDetElement.typeFlag()};
0576     if (type.is(dd4hep::DetType::BARREL) || type.is(dd4hep::DetType::ENDCAP)) {
0577       compounds.push_back(childDetElement);
0578     }
0579     collectCompounds_dd4hep(childDetElement, compounds);
0580   }
0581 }
0582 
0583 void collectSubDetectors_dd4hep(dd4hep::DetElement& detElement,
0584                                 std::vector<dd4hep::DetElement>& subdetectors,
0585                                 const Logger& logger) {
0586   const dd4hep::DetElement::Children& children = detElement.children();
0587   for (auto& child : children) {
0588     dd4hep::DetElement childDetElement = child.second;
0589     dd4hep::DetType type{childDetElement.typeFlag()};
0590     if (childDetElement.type() == "compound") {
0591       // Check if the compound is excluded from assembly
0592       // This is needed to eventually exclude compounds of pixel, strip, etc.
0593       // from barrel / endcap parsing
0594       if (getParamOr<bool>("acts_legacy_assembly", childDetElement, true)) {
0595         subdetectors.push_back(childDetElement);
0596         continue;
0597       }
0598     }
0599 
0600     if (type.is(dd4hep::DetType::TRACKER)) {
0601       subdetectors.push_back(childDetElement);
0602     }
0603     collectSubDetectors_dd4hep(childDetElement, subdetectors, logger);
0604   }
0605 }
0606 
0607 void collectLayers_dd4hep(dd4hep::DetElement& detElement,
0608                           std::vector<dd4hep::DetElement>& layers,
0609                           const Logger& logger) {
0610   const dd4hep::DetElement::Children& children = detElement.children();
0611   for (auto& child : children) {
0612     std::string _expr{"$^"};  // nothing
0613 
0614     dd4hep::rec::VariantParameters* params =
0615         detElement.extension<dd4hep::rec::VariantParameters>(false);
0616 
0617     if (params != nullptr) {
0618       _expr = params->value_or<std::string>("layer_pattern", _expr);
0619       ACTS_VERBOSE("--> Layer pattern for elt " << detElement.name() << ": "
0620                                                 << _expr);
0621     }
0622     std::regex expr{_expr};
0623 
0624     dd4hep::DetElement childDetElement = child.second;
0625 
0626     if (std::regex_search(childDetElement.name(), expr)) {
0627       ACTS_VERBOSE("--> Layer candidate match: " << _expr << " -> "
0628                                                  << childDetElement.name());
0629       layers.push_back(childDetElement);
0630       continue;
0631     }
0632 
0633     collectLayers_dd4hep(childDetElement, layers, logger);
0634   }
0635 }
0636 
0637 }  // namespace Acts