Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-06-30 07:52:54

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/DD4hepMaterialHelpers.hpp"
0026 #include "Acts/Plugins/DD4hep/DD4hepVolumeBuilder.hpp"
0027 #include "Acts/Utilities/Logger.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 Acts {
0042 class IMaterialDecorator;
0043 class ISurfaceMaterial;
0044 class TrackingGeometry;
0045 class TrackingVolume;
0046 
0047 namespace {
0048 struct DebugVisitor {
0049   std::string operator()(int value) { return std::to_string(value); }
0050 
0051   std::string operator()(double value) { return std::to_string(value); }
0052 
0053   std::string operator()(std::string value) { return value; }
0054 };
0055 }  // namespace
0056 
0057 std::unique_ptr<const TrackingGeometry> convertDD4hepDetector(
0058     dd4hep::DetElement worldDetElement, const Logger& logger,
0059     BinningType bTypePhi, BinningType bTypeR, BinningType bTypeZ,
0060     double layerEnvelopeR, double layerEnvelopeZ, double defaultLayerThickness,
0061     const std::function<void(std::vector<dd4hep::DetElement>& detectors)>&
0062         sortSubDetectors,
0063     const Acts::GeometryContext& gctx,
0064     std::shared_ptr<const IMaterialDecorator> matDecorator,
0065     std::shared_ptr<const GeometryIdentifierHook> geometryIdentifierHook,
0066     const DD4hepLayerBuilder::ElementFactory& detectorElementFactory) {
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, detectorElementFactory);
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     const DD4hepLayerBuilder::ElementFactory& detectorElementFactory) {
0158   // create cylinder volume helper
0159   auto volumeHelper = cylinderVolumeHelper_dd4hep(logger);
0160   // create local logger for conversion
0161   ACTS_VERBOSE("Processing detector element:  " << subDetector.name());
0162   dd4hep::DetType subDetType{subDetector.typeFlag()};
0163   ACTS_VERBOSE("SubDetector type is: ["
0164                << subDetType << "], compound: "
0165                << (subDetector.type() == "compound" ? "yes" : "no"));
0166 
0167   if (subDetector.type() == "compound") {
0168     ACTS_VERBOSE("Subdetector: '" << subDetector.name()
0169                                   << "' has type compound ");
0170     ACTS_VERBOSE(
0171         "handling as a compound volume (a hierarchy of a "
0172         "barrel-endcap structure) and resolving the "
0173         "subvolumes...");
0174     // Now create the Layerbuilders and Volumebuilder
0175     // the layers
0176     /// the dd4hep::DetElements of the layers of the negative volume
0177     std::vector<dd4hep::DetElement> negativeLayers;
0178     /// the dd4hep::DetElements of the layers of the central volume
0179     std::vector<dd4hep::DetElement> centralLayers;
0180     /// the dd4hep::DetElements of the layers of the positive volume
0181     std::vector<dd4hep::DetElement> positiveLayers;
0182 
0183     // the configuration object of the volume builder
0184     Acts::CylinderVolumeBuilder::Config cvbConfig;
0185 
0186     // go through sub volumes
0187     std::vector<dd4hep::DetElement> compounds;
0188     collectCompounds_dd4hep(subDetector, compounds);
0189 
0190     // get z position to distinguish positive & negative endcap
0191     double zPos = 0.;
0192     // flags to catch if sub volumes have been set already
0193     bool nEndCap = false;
0194     bool pEndCap = false;
0195     bool barrel = false;
0196     for (auto& volumeDetElement : compounds) {
0197       ACTS_VERBOSE("Volume: '"
0198                    << subDetector.name()
0199                    << "' is a compound volume -> resolve the sub volumes");
0200 
0201       // get the dimensions of the volume
0202       TGeoShape* geoShape =
0203           volumeDetElement.placement().ptr()->GetVolume()->GetShape();
0204       // check if it has a shape (the other case should not happen)
0205       if (geoShape != nullptr) {
0206         zPos = volumeDetElement.placement()
0207                    .ptr()
0208                    ->GetMatrix()
0209                    ->GetTranslation()[2] *
0210                UnitConstants::cm;
0211       } else {
0212         throw std::logic_error(std::string("Volume of DetElement: ") +
0213                                volumeDetElement.name() +
0214                                std::string(" has no shape!"));
0215       }
0216 
0217       dd4hep::DetType type{volumeDetElement.typeFlag()};
0218 
0219       if (!type.is(dd4hep::DetType::TRACKER)) {
0220         continue;
0221       }
0222 
0223       if (type.is(dd4hep::DetType::ENDCAP)) {
0224         ACTS_VERBOSE("Subvolume: '" << volumeDetElement.name()
0225                                     << "' is marked ENDCAP");
0226         if (zPos < 0.) {
0227           if (nEndCap) {
0228             throw std::logic_error(
0229                 "Negative Endcap was already given for this "
0230                 "hierarchy! Please create a new "
0231                 "DD4hep_SubDetectorAssembly for the next "
0232                 "hierarchy.");
0233           }
0234           nEndCap = true;
0235           ACTS_VERBOSE("-> is negative endcap");
0236           ACTS_VERBOSE("-> collecting layers");
0237           collectLayers_dd4hep(volumeDetElement, negativeLayers, logger);
0238           // Fill the volume material for barrel case
0239           if (getParamOr<bool>("boundary_material", volumeDetElement, false)) {
0240             ACTS_VERBOSE(
0241                 "-> boundary_material flag detected, creating proto "
0242                 "material.");
0243             auto& params = getParams(volumeDetElement);
0244             if (hasParam("boundary_material_negative", volumeDetElement)) {
0245               ACTS_VERBOSE("--> negative");
0246               cvbConfig.boundaryMaterial[2] = Acts::createProtoMaterial(
0247                   params, "boundary_material_negative",
0248                   {{"binPhi", Acts::closed}, {"binR", Acts::open}}, logger);
0249             }
0250             if (hasParam("boundary_material_positive", volumeDetElement)) {
0251               ACTS_VERBOSE("--> positive");
0252               cvbConfig.boundaryMaterial[3] = Acts::createProtoMaterial(
0253                   params, "boundary_material_positive",
0254                   {{"binPhi", Acts::closed}, {"binR", Acts::open}}, logger);
0255             }
0256           }
0257         } else {
0258           if (pEndCap) {
0259             throw std::logic_error(
0260                 "Positive Endcap was already given for this "
0261                 "hierarchy! Please create a new "
0262                 "DD4hep_SubDetectorAssembly for the next "
0263                 "hierarchy.");
0264           }
0265           pEndCap = true;
0266           ACTS_VERBOSE("-> is positive endcap");
0267           ACTS_VERBOSE("-> collecting layers");
0268           collectLayers_dd4hep(volumeDetElement, positiveLayers, logger);
0269           // Fill the volume material for barrel case
0270           if (getParamOr<bool>("boundary_material", volumeDetElement, false)) {
0271             ACTS_VERBOSE(
0272                 "-> boundary_material flag detected, creating proto "
0273                 "material.");
0274             auto& params = getParams(volumeDetElement);
0275             if (params.contains("boundary_material_negative")) {
0276               ACTS_VERBOSE("--> negative");
0277               cvbConfig.boundaryMaterial[4] = Acts::createProtoMaterial(
0278                   params, "boundary_material_negative",
0279                   {{"binPhi", Acts::closed}, {"binR", Acts::open}}, logger);
0280             }
0281             if (params.contains("boundary_material_positive")) {
0282               ACTS_VERBOSE("--> positive");
0283               cvbConfig.boundaryMaterial[5] = Acts::createProtoMaterial(
0284                   params, "boundary_material_positive",
0285                   {{"binPhi", Acts::closed}, {"binR", Acts::open}}, logger);
0286             }
0287           }
0288         }
0289       } else if (type.is(dd4hep::DetType::BARREL)) {
0290         if (barrel) {
0291           throw std::logic_error(
0292               "Barrel was already given for this "
0293               "hierarchy! Please create a new "
0294               "DD4hep_SubDetectorAssembly for the next "
0295               "hierarchy.");
0296         }
0297         barrel = true;
0298         ACTS_VERBOSE("Subvolume: " << volumeDetElement.name()
0299                                    << " is marked as BARREL");
0300         ACTS_VERBOSE("-> collecting layers");
0301         collectLayers_dd4hep(volumeDetElement, centralLayers, logger);
0302         // Fill the volume material for barrel case
0303         if (getParamOr<bool>("boundary_material", volumeDetElement, false)) {
0304           ACTS_VERBOSE(
0305               "-> boundary_material flag detected, creating proto "
0306               "material.");
0307           auto& params = getParams(volumeDetElement);
0308           if (params.contains("boundary_material_negative")) {
0309             ACTS_VERBOSE("--> negative");
0310             cvbConfig.boundaryMaterial[3] = Acts::createProtoMaterial(
0311                 params, "boundary_material_negative",
0312                 {{"binPhi", Acts::closed}, {"binR", Acts::open}}, logger);
0313           }
0314           if (params.contains("boundary_material_positive")) {
0315             ACTS_VERBOSE("--> positive");
0316             cvbConfig.boundaryMaterial[4] = Acts::createProtoMaterial(
0317                 params, "boundary_material_positive",
0318                 {{"binPhi", Acts::closed}, {"binR", Acts::open}}, logger);
0319           }
0320         }
0321       } else {
0322         throw std::logic_error(
0323             std::string("Current DetElement: ") + volumeDetElement.name() +
0324             std::string(" has inconsistent settings. It's a compound,"
0325                         " but its DetectorType is neither BARREL nor ENDCAP"
0326                         " Please check your detector construction."));
0327       }
0328 
0329       // Fill the volume material for the inner / outer cover
0330       if (getParamOr<bool>("boundary_material", volumeDetElement, false)) {
0331         ACTS_VERBOSE(
0332             "-> boundary_material flag detected, creating proto "
0333             "material.");
0334         auto& params = getParams(volumeDetElement);
0335         if (params.contains("boundary_material_inner")) {
0336           ACTS_VERBOSE("--> inner");
0337           cvbConfig.boundaryMaterial[0] = Acts::createProtoMaterial(
0338               params, "boundary_material_inner",
0339               {{"binPhi", Acts::closed}, {"binZ", Acts::open}}, logger);
0340         }
0341         if (params.contains("boundary_material_outer")) {
0342           ACTS_VERBOSE("--> outer");
0343           cvbConfig.boundaryMaterial[1] = Acts::createProtoMaterial(
0344               params, "boundary_material_outer",
0345               {{"binPhi", Acts::closed}, {"binZ", Acts::open}}, logger);
0346         }
0347       }
0348     }
0349 
0350     if ((pEndCap && !nEndCap) || (!pEndCap && nEndCap)) {
0351       throw std::logic_error(
0352           "Only one Endcap is given for the current "
0353           "hierarchy! Endcaps should always occur in "
0354           "pairs. Please check your detector "
0355           "construction.");
0356     }
0357 
0358     // configure SurfaceArrayCreator
0359     auto surfaceArrayCreator =
0360         std::make_shared<const Acts::SurfaceArrayCreator>(
0361             logger.clone("D2A_SAC"));
0362     // configure LayerCreator
0363     Acts::LayerCreator::Config lcConfig;
0364     lcConfig.surfaceArrayCreator = surfaceArrayCreator;
0365     auto layerCreator = std::make_shared<const Acts::LayerCreator>(
0366         lcConfig, logger.clone("D2A_LAC"));
0367     // configure DD4hepLayerBuilder
0368     Acts::DD4hepLayerBuilder::Config lbConfig;
0369     lbConfig.configurationName = subDetector.name();
0370     lbConfig.layerCreator = layerCreator;
0371     lbConfig.negativeLayers = negativeLayers;
0372     lbConfig.centralLayers = centralLayers;
0373     lbConfig.positiveLayers = positiveLayers;
0374     lbConfig.bTypePhi = bTypePhi;
0375     lbConfig.bTypeR = bTypeR;
0376     lbConfig.bTypeZ = bTypeZ;
0377     lbConfig.defaultThickness = defaultLayerThickness;
0378     lbConfig.detectorElementFactory = detectorElementFactory;
0379     auto dd4hepLayerBuilder = std::make_shared<const Acts::DD4hepLayerBuilder>(
0380         lbConfig, logger.clone(std::string("D2A_L:") + subDetector.name()));
0381 
0382     // Create the sub volume
0383     // Dimensions are created automatically by adding a tolerance to the
0384     // layer setup
0385     cvbConfig.layerEnvelopeR = std::make_pair(layerEnvelopeR, layerEnvelopeR);
0386     cvbConfig.layerEnvelopeZ = layerEnvelopeZ;
0387     cvbConfig.trackingVolumeHelper = volumeHelper;
0388     cvbConfig.volumeName = subDetector.name();
0389     cvbConfig.layerBuilder = dd4hepLayerBuilder;
0390     auto cylinderVolumeBuilder =
0391         std::make_shared<const Acts::CylinderVolumeBuilder>(
0392             cvbConfig,
0393             logger.clone(std::string("D2A_V:") + subDetector.name()));
0394     return cylinderVolumeBuilder;
0395   } else if (subDetType.is(dd4hep::DetType::BEAMPIPE) ||
0396              getParamOr<bool>("passive_layer", subDetector, false)) {
0397     ACTS_VERBOSE("Subdetector: " << subDetector.name()
0398                                  << " - building a passive cylinder.");
0399 
0400     if (subDetType.is(dd4hep::DetType::BEAMPIPE)) {
0401       ACTS_VERBOSE("This is the beam pipe - will be built to r -> 0.");
0402     }
0403 
0404     // get the dimensions of the volume
0405     TGeoShape* geoShape =
0406         subDetector.placement().ptr()->GetVolume()->GetShape();
0407     TGeoTubeSeg* tube = dynamic_cast<TGeoTubeSeg*>(geoShape);
0408     if (tube == nullptr) {
0409       throw std::logic_error(
0410           "Cylinder has wrong shape - needs to be TGeoTubeSeg!");
0411     }
0412     // get the dimension of TGeo and convert lengths
0413     double rMin = tube->GetRmin() * UnitConstants::cm - layerEnvelopeR;
0414     double rMax = tube->GetRmax() * UnitConstants::cm + layerEnvelopeR;
0415     double halfZ = tube->GetDz() * UnitConstants::cm + layerEnvelopeZ;
0416     ACTS_VERBOSE(
0417         "Extracting cylindrical volume bounds ( rmin / rmax / "
0418         "halfZ )=  ( "
0419         << rMin << " / " << rMax << " / " << halfZ << " )");
0420 
0421     std::shared_ptr<Acts::ISurfaceMaterial> plMaterial = nullptr;
0422     if (getParamOr<bool>("layer_material", subDetector, false)) {
0423       // get the possible material of the surrounding volume
0424       ACTS_VERBOSE("--> adding layer material at 'representing'");
0425       plMaterial = Acts::createProtoMaterial(
0426           getParams(subDetector), "layer_material_representing",
0427           {{"binPhi", Acts::closed}, {"binZ", Acts::open}}, logger);
0428     }
0429 
0430     // configure the passive layer builder
0431     Acts::PassiveLayerBuilder::Config plbConfig;
0432     plbConfig.layerIdentification = subDetector.name();
0433     plbConfig.centralLayerRadii = std::vector<double>(1, 0.5 * (rMax + rMin));
0434     plbConfig.centralLayerHalflengthZ = std::vector<double>(1, halfZ);
0435     plbConfig.centralLayerThickness =
0436         std::vector<double>(1, std::abs(rMax - rMin));
0437     plbConfig.centralLayerMaterial = {plMaterial};
0438     auto pcLayerBuilder = std::make_shared<const Acts::PassiveLayerBuilder>(
0439         plbConfig, logger.clone(std::string("D2A_PL:") + subDetector.name()));
0440 
0441     // the configuration object of the volume builder
0442     Acts::CylinderVolumeBuilder::Config cvbConfig;
0443     cvbConfig.trackingVolumeHelper = volumeHelper;
0444     cvbConfig.volumeName = subDetector.name();
0445     cvbConfig.layerBuilder = pcLayerBuilder;
0446     cvbConfig.layerEnvelopeR = {layerEnvelopeR, layerEnvelopeR};
0447     cvbConfig.layerEnvelopeZ = layerEnvelopeZ;
0448     cvbConfig.buildToRadiusZero = subDetType.is(dd4hep::DetType::BEAMPIPE);
0449 
0450     // Fill the volume material for the inner / outer cover
0451     if (getParamOr<bool>("boundary_material", subDetector, false)) {
0452       ACTS_VERBOSE(
0453           "-> boundary_material flag detected, creating proto "
0454           "material.");
0455       auto& params = getParams(subDetector);
0456       if (hasParam("boundary_material_inner", subDetector)) {
0457         ACTS_VERBOSE("--> inner");
0458         cvbConfig.boundaryMaterial[0] = Acts::createProtoMaterial(
0459             params, "boundary_material_inner",
0460             {{"binPhi", Acts::closed}, {"binZ", Acts::open}}, logger);
0461       }
0462       if (hasParam("boundary_material_outer", subDetector)) {
0463         ACTS_VERBOSE("--> outer");
0464         cvbConfig.boundaryMaterial[1] = Acts::createProtoMaterial(
0465             params, "boundary_material_outer",
0466             {{"binPhi", Acts::closed}, {"binZ", Acts::open}}, logger);
0467       }
0468     }
0469 
0470     // beam pipe / passive cylinder volume builder
0471     auto pcVolumeBuilder = std::make_shared<const Acts::CylinderVolumeBuilder>(
0472         cvbConfig, logger.clone(std::string("D2A_V:") + subDetector.name()));
0473     return pcVolumeBuilder;
0474   } else if (subDetType.is(dd4hep::DetType::BARREL)) {
0475     ACTS_VERBOSE("Subdetector: "
0476                  << subDetector.name()
0477                  << " is a (sensitive) Barrel volume - building barrel.");
0478     /// the dd4hep::DetElements of the layers of the central volume
0479     std::vector<dd4hep::DetElement> centralLayers, centralVolumes;
0480     ACTS_VERBOSE("-> collecting layers");
0481     collectLayers_dd4hep(subDetector, centralLayers, logger);
0482 
0483     // configure SurfaceArrayCreator
0484     auto surfaceArrayCreator =
0485         std::make_shared<const Acts::SurfaceArrayCreator>(
0486             logger.clone("D2A_SAC"));
0487     // configure LayerCreator
0488     Acts::LayerCreator::Config lcConfig;
0489     lcConfig.surfaceArrayCreator = surfaceArrayCreator;
0490     auto layerCreator = std::make_shared<const Acts::LayerCreator>(
0491         lcConfig, logger.clone("D2A_LAC"));
0492     // configure DD4hepLayerBuilder
0493     Acts::DD4hepLayerBuilder::Config lbConfig;
0494     lbConfig.configurationName = subDetector.name();
0495     lbConfig.layerCreator = layerCreator;
0496     lbConfig.centralLayers = centralLayers;
0497     lbConfig.bTypePhi = bTypePhi;
0498     lbConfig.bTypeZ = bTypeZ;
0499     lbConfig.defaultThickness = defaultLayerThickness;
0500     auto dd4hepLayerBuilder = std::make_shared<const Acts::DD4hepLayerBuilder>(
0501         lbConfig, logger.clone(std::string("D2A_LB_") + subDetector.name()));
0502 
0503     // Configure DD4hepVolumeBuilder
0504     Acts::DD4hepVolumeBuilder::Config vbConfig;
0505     vbConfig.configurationName = subDetector.name();
0506     vbConfig.centralVolumes = centralVolumes;
0507     auto dd4hepVolumeBuilder =
0508         std::make_shared<const Acts::DD4hepVolumeBuilder>(
0509             vbConfig,
0510             logger.clone(std::string("D2A_VB_") + subDetector.name()));
0511 
0512     // the configuration object of the volume builder
0513     Acts::CylinderVolumeBuilder::Config cvbConfig;
0514     // get the dimensions of the volume
0515     TGeoShape* geoShape =
0516         subDetector.placement().ptr()->GetVolume()->GetShape();
0517     // this should not happen
0518     if (geoShape == nullptr) {
0519       throw std::logic_error(std::string("Volume of DetElement: ") +
0520                              subDetector.name() +
0521                              std::string(" has no a shape!"));
0522     }
0523 
0524     cvbConfig.layerEnvelopeR = std::make_pair(layerEnvelopeR, layerEnvelopeR);
0525     cvbConfig.layerEnvelopeZ = layerEnvelopeZ;
0526     cvbConfig.trackingVolumeHelper = volumeHelper;
0527     cvbConfig.volumeName = subDetector.name();
0528     cvbConfig.layerBuilder = dd4hepLayerBuilder;
0529     cvbConfig.ctVolumeBuilder = dd4hepVolumeBuilder;
0530     auto cylinderVolumeBuilder =
0531         std::make_shared<const Acts::CylinderVolumeBuilder>(
0532             cvbConfig,
0533             logger.clone(std::string("D2A_V:") + subDetector.name()));
0534     return cylinderVolumeBuilder;
0535   } else {
0536     ACTS_WARNING(
0537         "Subdetector with name: '"
0538         << subDetector.name()
0539         << "' has inconsistent information for translation and is not of type "
0540            "'compound'. If you want to have this DetElement be translated "
0541            "into the tracking geometry you need add the right DetectorType "
0542            "or VariantParameters (at this stage the subvolume needs to be "
0543            "declared as BEAMPIPE or BARREl, or have a VariantParameter "
0544            "passive_layer=true) or if it is a compound DetElement (containing "
0545            "a barrel-endcap hierarchy), the type needs to be set to "
0546            "'compound'.");
0547     return nullptr;
0548   }
0549 }
0550 
0551 std::shared_ptr<const Acts::CylinderVolumeHelper> cylinderVolumeHelper_dd4hep(
0552     const Logger& logger) {
0553   // create cylindervolumehelper which can be used by all instances
0554   // hand over LayerArrayCreator
0555   Acts::LayerArrayCreator::Config lacConfig;
0556   auto layerArrayCreator = std::make_shared<const Acts::LayerArrayCreator>(
0557       lacConfig, logger.clone("D2A_LAC"));
0558   // tracking volume array creator
0559   Acts::TrackingVolumeArrayCreator::Config tvacConfig;
0560   auto trackingVolumeArrayCreator =
0561       std::make_shared<const Acts::TrackingVolumeArrayCreator>(
0562           tvacConfig, logger.clone("D2A_TVAC"));
0563   // configure the cylinder volume helper
0564   Acts::CylinderVolumeHelper::Config cvhConfig;
0565   cvhConfig.layerArrayCreator = layerArrayCreator;
0566   cvhConfig.trackingVolumeArrayCreator = trackingVolumeArrayCreator;
0567   auto cylinderVolumeHelper =
0568       std::make_shared<const Acts::CylinderVolumeHelper>(
0569           cvhConfig, logger.clone("D2A_CVH"));
0570 
0571   return cylinderVolumeHelper;
0572 }
0573 
0574 void collectCompounds_dd4hep(dd4hep::DetElement& detElement,
0575                              std::vector<dd4hep::DetElement>& compounds) {
0576   const dd4hep::DetElement::Children& children = detElement.children();
0577   for (auto& child : children) {
0578     dd4hep::DetElement childDetElement = child.second;
0579     dd4hep::DetType type{childDetElement.typeFlag()};
0580     if (type.is(dd4hep::DetType::BARREL) || type.is(dd4hep::DetType::ENDCAP)) {
0581       compounds.push_back(childDetElement);
0582     }
0583     collectCompounds_dd4hep(childDetElement, compounds);
0584   }
0585 }
0586 
0587 void collectSubDetectors_dd4hep(dd4hep::DetElement& detElement,
0588                                 std::vector<dd4hep::DetElement>& subdetectors,
0589                                 const Logger& logger) {
0590   const dd4hep::DetElement::Children& children = detElement.children();
0591   for (auto& child : children) {
0592     dd4hep::DetElement childDetElement = child.second;
0593     dd4hep::DetType type{childDetElement.typeFlag()};
0594     if (childDetElement.type() == "compound") {
0595       // Check if the compound is excluded from assembly
0596       // This is needed to eventually exclude compounds of pixel, strip, etc.
0597       // from barrel / endcap parsing
0598       if (getParamOr<bool>("acts_legacy_assembly", childDetElement, true)) {
0599         subdetectors.push_back(childDetElement);
0600         continue;
0601       }
0602     }
0603 
0604     if (type.is(dd4hep::DetType::TRACKER)) {
0605       subdetectors.push_back(childDetElement);
0606     }
0607     collectSubDetectors_dd4hep(childDetElement, subdetectors, logger);
0608   }
0609 }
0610 
0611 void collectLayers_dd4hep(dd4hep::DetElement& detElement,
0612                           std::vector<dd4hep::DetElement>& layers,
0613                           const Logger& logger) {
0614   const dd4hep::DetElement::Children& children = detElement.children();
0615   for (auto& child : children) {
0616     std::string _expr{"$^"};  // nothing
0617 
0618     dd4hep::rec::VariantParameters* params =
0619         detElement.extension<dd4hep::rec::VariantParameters>(false);
0620 
0621     if (params != nullptr) {
0622       _expr = params->value_or<std::string>("layer_pattern", _expr);
0623       ACTS_VERBOSE("--> Layer pattern for elt " << detElement.name() << ": "
0624                                                 << _expr);
0625     }
0626     std::regex expr{_expr};
0627 
0628     dd4hep::DetElement childDetElement = child.second;
0629 
0630     if (std::regex_search(childDetElement.name(), expr)) {
0631       ACTS_VERBOSE("--> Layer candidate match: " << _expr << " -> "
0632                                                  << childDetElement.name());
0633       layers.push_back(childDetElement);
0634       continue;
0635     }
0636 
0637     collectLayers_dd4hep(childDetElement, layers, logger);
0638   }
0639 }
0640 
0641 }  // namespace Acts