Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:12:17

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