Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-16 08:03:42

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