Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-01 07:46:21

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 "ActsExamples/GenericDetector/GenericDetector.hpp"
0010 
0011 #include "Acts/Geometry/Blueprint.hpp"
0012 #include "Acts/Geometry/BlueprintNode.hpp"
0013 #include "Acts/Geometry/ContainerBlueprintNode.hpp"
0014 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0015 #include "Acts/Geometry/CylinderVolumeBuilder.hpp"
0016 #include "Acts/Geometry/CylinderVolumeHelper.hpp"
0017 #include "Acts/Geometry/Extent.hpp"
0018 #include "Acts/Geometry/LayerArrayCreator.hpp"
0019 #include "Acts/Geometry/LayerBlueprintNode.hpp"
0020 #include "Acts/Geometry/LayerCreator.hpp"
0021 #include "Acts/Geometry/MaterialDesignatorBlueprintNode.hpp"
0022 #include "Acts/Geometry/NavigationPolicyFactory.hpp"
0023 #include "Acts/Geometry/PassiveLayerBuilder.hpp"
0024 #include "Acts/Geometry/SurfaceArrayCreator.hpp"
0025 #include "Acts/Geometry/TrackingGeometry.hpp"
0026 #include "Acts/Geometry/TrackingGeometryBuilder.hpp"
0027 #include "Acts/Geometry/TrackingVolume.hpp"
0028 #include "Acts/Geometry/TrackingVolumeArrayCreator.hpp"
0029 #include "Acts/Geometry/VolumeAttachmentStrategy.hpp"
0030 #include "Acts/Material/HomogeneousSurfaceMaterial.hpp"
0031 #include "Acts/Navigation/CylinderNavigationPolicy.hpp"
0032 #include "Acts/Navigation/SurfaceArrayNavigationPolicy.hpp"
0033 #include "Acts/Navigation/TryAllNavigationPolicy.hpp"
0034 #include "Acts/Utilities/AxisDefinitions.hpp"
0035 #include "ActsExamples/GenericDetector/GenericDetectorElement.hpp"
0036 #include "ActsExamples/GenericDetector/LayerBuilder.hpp"
0037 
0038 #include <fstream>
0039 
0040 #include "./GenericDetectorBuilder.hpp"
0041 
0042 namespace ActsExamples {
0043 
0044 namespace Generic {
0045 namespace {
0046 
0047 class Gen1GenericDetectorBuilder : public GenericDetectorBuilder {
0048  public:
0049   using GenericDetectorBuilder::GenericDetectorBuilder;
0050 
0051   std::unique_ptr<const Acts::TrackingGeometry> buildTrackingGeometry(
0052       const Acts::GeometryContext& gctx,
0053       std::shared_ptr<const Acts::IMaterialDecorator> matDecorator,
0054       Acts::Logging::Level surfaceLLevel, Acts::Logging::Level volumeLLevel);
0055 };
0056 
0057 std::unique_ptr<const Acts::TrackingGeometry>
0058 Gen1GenericDetectorBuilder::buildTrackingGeometry(
0059     const Acts::GeometryContext& gctx,
0060     std::shared_ptr<const Acts::IMaterialDecorator> matDecorator,
0061     Acts::Logging::Level surfaceLLevel, Acts::Logging::Level volumeLLevel) {
0062   ACTS_INFO("Building tracking geometry for Generic Detector in Gen1 mode");
0063   using namespace Acts::UnitLiterals;
0064 
0065   // configure surface array creator
0066   Acts::SurfaceArrayCreator::Config sacConfig;
0067   auto surfaceArrayCreator = std::make_shared<const Acts::SurfaceArrayCreator>(
0068       sacConfig, logger().clone("SurfaceArrayCreator", surfaceLLevel));
0069   // configure the layer creator that uses the surface array creator
0070   Acts::LayerCreator::Config lcConfig;
0071   lcConfig.surfaceArrayCreator = surfaceArrayCreator;
0072   auto layerCreator = std::make_shared<const Acts::LayerCreator>(
0073       lcConfig, logger().clone("LayerCreator", m_cfg.layerLogLevel));
0074   // configure the layer array creator
0075   Acts::LayerArrayCreator::Config lacConfig;
0076   auto layerArrayCreator = std::make_shared<const Acts::LayerArrayCreator>(
0077       lacConfig, logger().clone("LayerArrayCreator", m_cfg.layerLogLevel));
0078   // tracking volume array creator
0079   Acts::TrackingVolumeArrayCreator::Config tvacConfig;
0080   auto tVolumeArrayCreator =
0081       std::make_shared<const Acts::TrackingVolumeArrayCreator>(
0082           tvacConfig,
0083           logger().clone("TrackingVolumeArrayCreator", volumeLLevel));
0084   // configure the cylinder volume helper
0085   Acts::CylinderVolumeHelper::Config cvhConfig;
0086   cvhConfig.layerArrayCreator = layerArrayCreator;
0087   cvhConfig.trackingVolumeArrayCreator = tVolumeArrayCreator;
0088   auto cylinderVolumeHelper =
0089       std::make_shared<const Acts::CylinderVolumeHelper>(
0090           cvhConfig, logger().clone("CylinderVolumeHelper", volumeLLevel));
0091   //-------------------------------------------------------------------------------------
0092   // vector of the volume builders
0093   std::vector<std::shared_ptr<const Acts::ITrackingVolumeBuilder>>
0094       volumeBuilders;
0095 
0096   ACTS_DEBUG("Building BeamPipe");
0097   //-------------------------------------------------------------------------------------
0098   // Beam Pipe
0099   //-------------------------------------------------------------------------------------
0100 
0101   // configure the beam pipe layer builder
0102   Acts::PassiveLayerBuilder::Config bplConfig;
0103   bplConfig.layerIdentification = "BeamPipe";
0104   bplConfig.centralLayerRadii = std::vector<double>(1, kBeamPipeRadius);
0105   bplConfig.centralLayerHalflengthZ =
0106       std::vector<double>(1, kBeamPipeHalfLengthZ);
0107   bplConfig.centralLayerThickness = std::vector<double>(1, kBeamPipeThickness);
0108   bplConfig.centralLayerMaterial = {m_beamPipeMaterial};
0109   auto beamPipeBuilder = std::make_shared<const Acts::PassiveLayerBuilder>(
0110       bplConfig, logger().clone("BeamPipeLayerBuilder", m_cfg.layerLogLevel));
0111   // create the volume for the beam pipe
0112   Acts::CylinderVolumeBuilder::Config bpvConfig;
0113   bpvConfig.trackingVolumeHelper = cylinderVolumeHelper;
0114   bpvConfig.volumeName = "BeamPipe";
0115   bpvConfig.layerBuilder = beamPipeBuilder;
0116   bpvConfig.layerEnvelopeR = {1. * Acts::UnitConstants::mm,
0117                               1. * Acts::UnitConstants::mm};
0118   bpvConfig.buildToRadiusZero = true;
0119   auto beamPipeVolumeBuilder =
0120       std::make_shared<const Acts::CylinderVolumeBuilder>(
0121           bpvConfig, logger().clone("BeamPipeVolumeBuilder", volumeLLevel));
0122   // add to the list of builders
0123   volumeBuilders.push_back(beamPipeVolumeBuilder);
0124 
0125   ACTS_DEBUG("Building Pixel");
0126   //-------------------------------------------------------------------------------------
0127   //-------------------------------------------------------------------------------------
0128   // Pixel detector
0129   //-------------------------------------------------------------------------------------
0130   // some prep work
0131 
0132   ProtoLayerCreator pplCreator = createPixelProtoLayerCreator();
0133 
0134   // configure pixel layer builder
0135   LayerBuilder::Config plbConfig;
0136   plbConfig.layerCreator = layerCreator;
0137   plbConfig.layerIdentification = "Pixel";
0138   // material concentration always outside the modules
0139   plbConfig.centralProtoLayers = pplCreator.centralProtoLayers(gctx);
0140   plbConfig.centralLayerMaterialConcentration = {1, 1, 1, 1};
0141   plbConfig.centralLayerMaterial = {
0142       m_pixelCentralMaterial, m_pixelCentralMaterial, m_pixelCentralMaterial,
0143       m_pixelCentralMaterial};
0144   if (m_cfg.buildLevel > 0) {
0145     // material concentration is always behind the layer in the pixels
0146     plbConfig.posnegLayerMaterialConcentration = std::vector<int>(7, 0);
0147     // layer structure surface has pixel material properties
0148     plbConfig.posnegLayerMaterial = {
0149         m_pixelEndcapMaterial, m_pixelEndcapMaterial, m_pixelEndcapMaterial,
0150         m_pixelEndcapMaterial, m_pixelEndcapMaterial, m_pixelEndcapMaterial,
0151         m_pixelEndcapMaterial};
0152     // negative proto layers
0153     plbConfig.negativeProtoLayers = pplCreator.negativeProtoLayers(gctx);
0154     plbConfig.positiveProtoLayers = pplCreator.positiveProtoLayers(gctx);
0155   }
0156   // define the builder
0157   auto pixelLayerBuilder = std::make_shared<const LayerBuilder>(
0158       plbConfig, logger().clone("PixelLayerBuilder", m_cfg.layerLogLevel));
0159   //-------------------------------------------------------------------------------------
0160   // build the pixel volume
0161   Acts::CylinderVolumeBuilder::Config pvbConfig;
0162   pvbConfig.trackingVolumeHelper = cylinderVolumeHelper;
0163   pvbConfig.volumeName = "Pixel";
0164   pvbConfig.buildToRadiusZero = false;
0165   pvbConfig.layerEnvelopeR = {1. * Acts::UnitConstants::mm,
0166                               5. * Acts::UnitConstants::mm};
0167   pvbConfig.layerBuilder = pixelLayerBuilder;
0168   auto pixelVolumeBuilder = std::make_shared<const Acts::CylinderVolumeBuilder>(
0169       pvbConfig, logger().clone("PixelVolumeBuilder", volumeLLevel));
0170   // add to the list of builders
0171   volumeBuilders.push_back(pixelVolumeBuilder);
0172 
0173   if (m_cfg.buildLevel > 1) {
0174     ACTS_DEBUG("Building PST");
0175     //-------------------------------------------------------------------------------------
0176     //-------------------------------------------------------------------------------------
0177     // Pixel Support Tybe (PST)
0178     //-------------------------------------------------------------------------------------
0179 
0180     // Configuration
0181     Acts::PassiveLayerBuilder::Config pstConfig;
0182     pstConfig.layerIdentification = "PST";
0183     pstConfig.centralLayerRadii = std::vector<double>(1, kPstRadius);
0184     pstConfig.centralLayerHalflengthZ = std::vector<double>(1, kPstHalfLengthZ);
0185     pstConfig.centralLayerThickness = std::vector<double>(1, kPstThickness);
0186     pstConfig.centralLayerMaterial = {m_pstMaterial};
0187     auto pstBuilder = std::make_shared<const Acts::PassiveLayerBuilder>(
0188         pstConfig, logger().clone("PSTLayerBuilder", m_cfg.layerLogLevel));
0189     // create the volume for the beam pipe
0190     Acts::CylinderVolumeBuilder::Config pstvolConfig;
0191     pstvolConfig.trackingVolumeHelper = cylinderVolumeHelper;
0192     pstvolConfig.volumeName = "PST";
0193     pstvolConfig.buildToRadiusZero = false;
0194     pstvolConfig.layerBuilder = pstBuilder;
0195     auto pstVolumeBuilder = std::make_shared<const Acts::CylinderVolumeBuilder>(
0196         pstvolConfig, logger().clone("PSTVolumeBuilder", volumeLLevel));
0197     // add to the detector builds
0198     volumeBuilders.push_back(pstVolumeBuilder);
0199 
0200     ACTS_DEBUG("Building SStrip");
0201     //-------------------------------------------------------------------------------------
0202     // SHORT strip detector
0203     //-------------------------------------------------------------------------------------
0204     // first add a Pixel Support Tube
0205     // STRIPS
0206     //
0207     // fill necessary vectors for configuration
0208     //-------------------------------------------------------------------------------------
0209     // some prep work
0210 
0211     ProtoLayerCreator ssplCreator = createShortStripProtoLayerCreator();
0212 
0213     std::size_t nposnegs = ssplCreator.config().posnegLayerPositionsZ.size();
0214 
0215     // configure short strip layer builder
0216     LayerBuilder::Config sslbConfig;
0217     sslbConfig.layerCreator = layerCreator;
0218     sslbConfig.layerIdentification = "SStrip";
0219 
0220     sslbConfig.centralProtoLayers = ssplCreator.centralProtoLayers(gctx);
0221     sslbConfig.centralLayerMaterialConcentration = {-1, -1, -1, -1};
0222     sslbConfig.centralLayerMaterial = {
0223         m_shortStripCentralMaterial, m_shortStripCentralMaterial,
0224         m_shortStripCentralMaterial, m_shortStripCentralMaterial};
0225 
0226     if (m_cfg.buildLevel > 2) {
0227       sslbConfig.negativeProtoLayers = ssplCreator.negativeProtoLayers(gctx);
0228       sslbConfig.positiveProtoLayers = ssplCreator.positiveProtoLayers(gctx);
0229 
0230       sslbConfig.posnegLayerMaterialConcentration =
0231           std::vector<int>(nposnegs, 0);
0232       sslbConfig.posnegLayerMaterial =
0233           std::vector<std::shared_ptr<const Acts::ISurfaceMaterial>>(
0234               nposnegs, m_shortStripEndcapMaterial);
0235     }
0236 
0237     // define the builder
0238     auto sstripLayerBuilder = std::make_shared<const LayerBuilder>(
0239         sslbConfig, logger().clone("SStripLayerBuilder", m_cfg.layerLogLevel));
0240     //-------------------------------------------------------------------------------------
0241     // build the pixel volume
0242     Acts::CylinderVolumeBuilder::Config ssvbConfig;
0243     ssvbConfig.trackingVolumeHelper = cylinderVolumeHelper;
0244     ssvbConfig.volumeName = "SStrip";
0245     ssvbConfig.buildToRadiusZero = false;
0246     ssvbConfig.layerBuilder = sstripLayerBuilder;
0247     auto sstripVolumeBuilder =
0248         std::make_shared<const Acts::CylinderVolumeBuilder>(
0249             ssvbConfig, logger().clone("SStripVolumeBuilder", volumeLLevel));
0250 
0251     //-------------------------------------------------------------------------------------
0252     // add to the list of builders
0253     volumeBuilders.push_back(sstripVolumeBuilder);
0254     //-------------------------------------------------------------------------------------
0255     ACTS_DEBUG("Building LStrip");
0256     //-------------------------------------------------------------------------------------
0257     // LONG strip detector
0258     //-------------------------------------------------------------------------------------
0259     // fill necessary vectors for configuration
0260     //-------------------------------------------------------------------------------------
0261 
0262     // some prep work
0263 
0264     ProtoLayerCreator lsplCreator = createLongStripProtoLayerCreator();
0265 
0266     // configure short strip layer builder
0267     Generic::LayerBuilder::Config lslbConfig;
0268     lslbConfig.layerCreator = layerCreator;
0269     lslbConfig.layerIdentification = "LStrip";
0270     lslbConfig.centralLayerMaterialConcentration = {-1, -1};
0271     lslbConfig.centralLayerMaterial = {m_longStripCentralMaterial,
0272                                        m_longStripCentralMaterial};
0273     lslbConfig.centralProtoLayers = lsplCreator.centralProtoLayers(gctx);
0274 
0275     if (m_cfg.buildLevel > 2) {
0276       lslbConfig.posnegLayerMaterialConcentration =
0277           std::vector<int>(nposnegs, 0);
0278       lslbConfig.posnegLayerMaterial =
0279           std::vector<std::shared_ptr<const Acts::ISurfaceMaterial>>(
0280               nposnegs, m_longStripEndcapMaterial);
0281       lslbConfig.negativeProtoLayers = lsplCreator.negativeProtoLayers(gctx);
0282       lslbConfig.positiveProtoLayers = lsplCreator.positiveProtoLayers(gctx);
0283     }
0284 
0285     // define the builder
0286     auto lstripLayerBuilder = std::make_shared<const LayerBuilder>(
0287         lslbConfig, logger().clone("LStripLayerBuilder", m_cfg.layerLogLevel));
0288     //-------------------------------------------------------------------------------------
0289     // build the pixel volume
0290     Acts::CylinderVolumeBuilder::Config lsvbConfig;
0291     lsvbConfig.trackingVolumeHelper = cylinderVolumeHelper;
0292     lsvbConfig.volumeName = "LStrip";
0293     lsvbConfig.buildToRadiusZero = false;
0294     lsvbConfig.layerBuilder = lstripLayerBuilder;
0295     auto lstripVolumeBuilder =
0296         std::make_shared<const Acts::CylinderVolumeBuilder>(
0297             lsvbConfig, logger().clone("LStripVolumeBuilder", volumeLLevel));
0298     // add to the list of builders
0299     volumeBuilders.push_back(lstripVolumeBuilder);
0300   }
0301 
0302   ACTS_DEBUG("Building TrackingGeometry");
0303   //-------------------------------------------------------------------------------------
0304   // create the tracking geometry
0305   Acts::TrackingGeometryBuilder::Config tgConfig;
0306   // Add the build call functions
0307   for (auto& vb : volumeBuilders) {
0308     tgConfig.trackingVolumeBuilders.emplace_back(
0309         [=](const auto& context, const auto& inner, const auto&) {
0310           return vb->trackingVolume(context, inner);
0311         });
0312   }
0313   tgConfig.trackingVolumeHelper = cylinderVolumeHelper;
0314   tgConfig.materialDecorator = std::move(matDecorator);
0315 
0316   auto cylinderGeometryBuilder =
0317       std::make_shared<const Acts::TrackingGeometryBuilder>(
0318           tgConfig,
0319           logger().clone("CylinderGeometryBuilder", Acts::Logging::INFO));
0320   // get the geometry
0321   auto trackingGeometry = cylinderGeometryBuilder->trackingGeometry(gctx);
0322   // return the tracking geometry
0323   return trackingGeometry;
0324 }
0325 
0326 class Gen3GenericDetectorBuilder : public GenericDetectorBuilder {
0327  public:
0328   using GenericDetectorBuilder::GenericDetectorBuilder;
0329 
0330   std::unique_ptr<const Acts::TrackingGeometry> buildTrackingGeometry(
0331       const Acts::GeometryContext& gctx,
0332       std::optional<std::filesystem::path> graphvizFile);
0333 
0334   void buildPixel(Acts::Experimental::BlueprintNode& parent,
0335                   const Acts::GeometryContext& gctx);
0336 
0337   void buildShortStrip(Acts::Experimental::BlueprintNode& parent,
0338                        const Acts::GeometryContext& gctx);
0339 
0340   void buildLongStrip(Acts::Experimental::BlueprintNode& parent,
0341                       const Acts::GeometryContext& gctx);
0342 
0343   static std::shared_ptr<const Acts::HomogeneousSurfaceMaterial> asHomogeneous(
0344       std::string_view debugLabel,
0345       const std::shared_ptr<const Acts::ISurfaceMaterial>& material) {
0346     auto hm = std::dynamic_pointer_cast<const Acts::HomogeneousSurfaceMaterial>(
0347         material);
0348     if (hm == nullptr) {
0349       throw std::runtime_error(std::string{debugLabel} +
0350                                " material is not homogeneous");
0351     }
0352     return hm;
0353   }
0354 
0355   using LayerType = Acts::SurfaceArrayNavigationPolicy::LayerType;
0356   std::unique_ptr<Acts::NavigationPolicyFactory> createNavigationPolicy(
0357       LayerType layerType,
0358       std::pair<std::size_t, std::size_t> bins = {0, 0}) const {
0359     using SrfArrayNavPol = Acts::SurfaceArrayNavigationPolicy;
0360     return Acts::NavigationPolicyFactory{}
0361         .add<Acts::CylinderNavigationPolicy>()
0362         .add<SrfArrayNavPol>(
0363             SrfArrayNavPol::Config{.layerType = layerType, .bins = bins})
0364         .asUniquePtr();
0365   }
0366 };
0367 
0368 std::unique_ptr<const Acts::TrackingGeometry>
0369 Gen3GenericDetectorBuilder::buildTrackingGeometry(
0370     const Acts::GeometryContext& gctx,
0371     std::optional<std::filesystem::path> graphvizFile) {
0372   using enum Acts::AxisDirection;
0373   using namespace Acts::UnitLiterals;
0374   using namespace Acts::Experimental;
0375   using enum Acts::AxisBoundaryType;
0376   using enum Acts::CylinderVolumeBounds::Face;
0377   ACTS_INFO("GenericDetector construction in  Gen3 mode");
0378 
0379   Blueprint::Config cfg;
0380   cfg.envelope = Acts::ExtentEnvelope{{
0381       .z = {20_mm, 20_mm},
0382       .r = {0_mm, 20_mm},
0383   }};
0384   Blueprint root{cfg};
0385 
0386   root.addCylinderContainer("Detector", AxisR, [&](auto& detector) {
0387     auto beampipeBounds = std::make_unique<Acts::CylinderVolumeBounds>(
0388         0_mm, kBeamPipeRadius, kBeamPipeHalfLengthZ);
0389     auto beampipe = std::make_unique<Acts::TrackingVolume>(
0390         Acts::Transform3::Identity(), std::move(beampipeBounds), "Beampipe");
0391 
0392     detector.addMaterial("BeampipeMaterial", [&](auto& bpMat) {
0393       bpMat.configureFace(OuterCylinder,
0394                           asHomogeneous("Beam pipe", m_beamPipeMaterial));
0395       bpMat.addStaticVolume(std::move(beampipe));
0396     });
0397 
0398     buildPixel(detector, gctx);
0399 
0400     if (m_cfg.buildLevel > 1) {
0401       buildShortStrip(detector, gctx);
0402       buildLongStrip(detector, gctx);
0403     }
0404   });
0405 
0406   if (graphvizFile) {
0407     std::ofstream file(*graphvizFile);
0408     root.graphviz(file);
0409   }
0410 
0411   BlueprintOptions options;
0412   auto trackingGeometry =
0413       root.construct(options, gctx, *logger().clone("Blprnt"));
0414   return trackingGeometry;
0415 }
0416 
0417 void Gen3GenericDetectorBuilder::buildPixel(
0418     Acts::Experimental::BlueprintNode& parent,
0419     const Acts::GeometryContext& gctx) {
0420   using enum Acts::AxisDirection;
0421   using namespace Acts::Experimental;
0422   using namespace Acts::UnitLiterals;
0423   using enum Acts::CylinderVolumeBounds::Face;
0424   using AttachmentStrategy = Acts::VolumeAttachmentStrategy;
0425   using ResizeStrategy = Acts::VolumeResizeStrategy;
0426 
0427   ACTS_DEBUG("Building Pixel");
0428 
0429   ProtoLayerCreator pplCreator = createPixelProtoLayerCreator();
0430 
0431   auto& pixel = parent.addCylinderContainer("Pixel", AxisR);
0432 
0433   if (m_cfg.buildLevel > 1) {
0434     ACTS_DEBUG("Building PST");
0435     auto pstVolume = std::make_unique<Acts::TrackingVolume>(
0436         Acts::Transform3::Identity(),
0437         std::make_unique<Acts::CylinderVolumeBounds>(
0438             kPstRadius - kPstThickness, kPstRadius, kPstHalfLengthZ),
0439         "PST");
0440 
0441     pixel.addMaterial("PSTMaterial", [&](auto& pstMat) {
0442       pstMat.configureFace(OuterCylinder, asHomogeneous("PST", m_pstMaterial));
0443       pstMat.addStaticVolume(std::move(pstVolume));
0444     });
0445   }
0446 
0447   auto& sensitive = pixel.addCylinderContainer("Pixel", AxisZ);
0448   sensitive.addCylinderContainer("Pixel_Barrel", AxisR, [&](auto& barrel) {
0449     barrel.setAttachmentStrategy(AttachmentStrategy::Gap);
0450     barrel.setResizeStrategies(ResizeStrategy::Expand, ResizeStrategy::Gap);
0451 
0452     auto centralProtoLayerSurfaces = pplCreator.centralProtoLayers(gctx);
0453     ACTS_DEBUG("Adding " << centralProtoLayerSurfaces.size()
0454                          << " central proto layers to "
0455                          << "Pixel_Barrel");
0456     for (const auto& [idx, temp] :
0457 
0458          Acts::enumerate(centralProtoLayerSurfaces)) {
0459       auto& pl = temp.protoLayer;
0460       std::string layerName = "Pixel_Barrel_L" + std::to_string(idx);
0461       barrel.addMaterial(layerName + "_Mat", [&](auto& mat) {
0462         mat.configureFace(OuterCylinder,
0463                           asHomogeneous("Pixel", m_pixelCentralMaterial));
0464         mat.addLayer(layerName, [&](auto& layer) {
0465           ACTS_VERBOSE("Adding layer " << layer.name());
0466           layer.setProtoLayer(pl);
0467           layer.setEnvelope(
0468               Acts::ExtentEnvelope{{.z = {5_mm, 5_mm}, .r = {5_mm, 5_mm}}});
0469           layer.setNavigationPolicyFactory(
0470               createNavigationPolicy(LayerType::Cylinder));
0471 
0472           ACTS_VERBOSE("-> Number of surfaces: " << layer.surfaces().size());
0473         });
0474       });
0475     }
0476   });
0477 
0478   sensitive.addCylinderContainer("Pixel_nEC", AxisZ, [&](auto& endcap) {
0479     endcap.setAttachmentStrategy(AttachmentStrategy::Gap);
0480     endcap.setResizeStrategy(ResizeStrategy::Gap);
0481 
0482     auto protoLayerSurfaces = pplCreator.negativeProtoLayers(gctx);
0483     ACTS_DEBUG("Adding " << protoLayerSurfaces.size()
0484                          << " negative proto layers to "
0485                          << "Pixel_nEC");
0486     for (const auto& [idx, temp] :
0487 
0488          Acts::enumerate(protoLayerSurfaces)) {
0489       auto& pl = temp.protoLayer;
0490       std::string layerName = "Pixel_nEC_L" + std::to_string(idx);
0491       endcap.addMaterial(layerName + "_Mat", [&](auto& mat) {
0492         mat.configureFace(NegativeDisc,
0493                           asHomogeneous("Pixel", m_pixelEndcapMaterial));
0494         mat.addLayer(layerName, [&](auto& layer) {
0495           layer.setNavigationPolicyFactory(
0496               createNavigationPolicy(LayerType::Disc));
0497           ACTS_VERBOSE("Adding layer " << layer.name());
0498           layer.setProtoLayer(pl);
0499           layer.setEnvelope(
0500               Acts::ExtentEnvelope{{.z = {5_mm, 5_mm}, .r = {5_mm, 5_mm}}});
0501         });
0502       });
0503     }
0504   });
0505 
0506   sensitive.addCylinderContainer("Pixel_pEC", AxisZ, [&](auto& endcap) {
0507     endcap.setAttachmentStrategy(AttachmentStrategy::Gap);
0508     endcap.setResizeStrategy(ResizeStrategy::Gap);
0509     auto protoLayerSurfaces = pplCreator.positiveProtoLayers(gctx);
0510     ACTS_DEBUG("Adding " << protoLayerSurfaces.size()
0511                          << " positive proto layers to "
0512                          << "Pixel_pEC");
0513     for (const auto& [idx, temp] : Acts::enumerate(protoLayerSurfaces)) {
0514       auto& pl = temp.protoLayer;
0515       std::string layerName = "Pixel_pEC_L" + std::to_string(idx);
0516       endcap.addMaterial(layerName + "_Mat", [&](auto& mat) {
0517         mat.configureFace(PositiveDisc,
0518                           asHomogeneous("Pixel", m_pixelEndcapMaterial));
0519         mat.addLayer(layerName, [&](auto& layer) {
0520           layer.setNavigationPolicyFactory(
0521               createNavigationPolicy(LayerType::Disc));
0522           ACTS_VERBOSE("Adding layer " << layer.name());
0523           layer.setProtoLayer(pl);
0524           layer.setEnvelope(
0525               Acts::ExtentEnvelope{{.z = {5_mm, 5_mm}, .r = {5_mm, 5_mm}}});
0526         });
0527       });
0528     }
0529   });
0530 }
0531 
0532 void Gen3GenericDetectorBuilder::buildShortStrip(
0533     Acts::Experimental::BlueprintNode& parent,
0534     const Acts::GeometryContext& gctx) {
0535   using enum Acts::AxisDirection;
0536   using namespace Acts::Experimental;
0537   using namespace Acts::UnitLiterals;
0538   using enum Acts::CylinderVolumeBounds::Face;
0539   using AttachmentStrategy = Acts::VolumeAttachmentStrategy;
0540   using ResizeStrategy = Acts::VolumeResizeStrategy;
0541 
0542   ACTS_DEBUG("Building Short Strip");
0543 
0544   ProtoLayerCreator ssplCreator = createShortStripProtoLayerCreator();
0545 
0546   auto& sstrip = parent.addCylinderContainer("ShortStrip", AxisZ);
0547   sstrip.setAttachmentStrategy(AttachmentStrategy::Gap);
0548   sstrip.setResizeStrategy(ResizeStrategy::Gap);
0549 
0550   sstrip.addCylinderContainer("ShortStrip_Barrel", AxisR, [&](auto& barrel) {
0551     barrel.setAttachmentStrategy(AttachmentStrategy::Gap);
0552     barrel.setResizeStrategy(ResizeStrategy::Gap);
0553 
0554     auto protoLayerSurfaces = ssplCreator.centralProtoLayers(gctx);
0555     ACTS_DEBUG("Adding " << protoLayerSurfaces.size()
0556                          << " central proto layers to "
0557                          << "ShortStrip");
0558     for (const auto& [idx, temp] : Acts::enumerate(protoLayerSurfaces)) {
0559       auto& pl = temp.protoLayer;
0560       std::string layerName = "ShortStrip_Barrel_L" + std::to_string(idx);
0561       barrel.addMaterial(layerName + "_Mat", [&](auto& mat) {
0562         mat.configureFace(
0563             InnerCylinder,
0564             asHomogeneous("ShortStrip", m_shortStripCentralMaterial));
0565         mat.addLayer(layerName, [&](auto& layer) {
0566           layer.setNavigationPolicyFactory(
0567               createNavigationPolicy(LayerType::Cylinder));
0568           ACTS_VERBOSE("Adding layer " << layer.name());
0569           layer.setProtoLayer(pl);
0570           layer.setEnvelope(
0571               Acts::ExtentEnvelope{{.z = {5_mm, 5_mm}, .r = {5_mm, 5_mm}}});
0572         });
0573       });
0574     }
0575   });
0576 
0577   if (m_cfg.buildLevel > 2) {
0578     sstrip.addCylinderContainer("ShortStrip_nEC", AxisZ, [&](auto& endcap) {
0579       endcap.setAttachmentStrategy(AttachmentStrategy::Gap);
0580       endcap.setResizeStrategy(ResizeStrategy::Gap);
0581 
0582       auto protoLayerSurfaces = ssplCreator.negativeProtoLayers(gctx);
0583 
0584       ACTS_DEBUG("Adding " << protoLayerSurfaces.size()
0585                            << " negative proto layers to "
0586                            << "ShortStrip_nEC");
0587       for (const auto& [idx, temp] : Acts::enumerate(protoLayerSurfaces)) {
0588         auto& pl = temp.protoLayer;
0589         std::string layerName = "ShortStrip_nEC_L" + std::to_string(idx);
0590         endcap.addMaterial(layerName + "_Mat", [&](auto& mat) {
0591           mat.configureFace(
0592               NegativeDisc,
0593               asHomogeneous("ShortStrip", m_shortStripEndcapMaterial));
0594           mat.addLayer(layerName, [&](auto& layer) {
0595             layer.setNavigationPolicyFactory(
0596                 createNavigationPolicy(LayerType::Disc));
0597             ACTS_VERBOSE("Adding layer " << layer.name());
0598             layer.setProtoLayer(pl);
0599             layer.setEnvelope(
0600                 Acts::ExtentEnvelope{{.z = {5_mm, 5_mm}, .r = {0_mm, 0_mm}}});
0601           });
0602         });
0603       }
0604     });
0605 
0606     sstrip.addCylinderContainer("ShortStrip_pEC", AxisZ, [&](auto& endcap) {
0607       endcap.setAttachmentStrategy(AttachmentStrategy::Gap);
0608       endcap.setResizeStrategy(ResizeStrategy::Gap);
0609 
0610       auto protoLayerSurfaces = ssplCreator.positiveProtoLayers(gctx);
0611 
0612       ACTS_DEBUG("Adding " << protoLayerSurfaces.size()
0613                            << " positive proto layers to "
0614                            << "ShortStrip_pEC");
0615       for (const auto& [idx, temp] : Acts::enumerate(protoLayerSurfaces)) {
0616         auto& pl = temp.protoLayer;
0617         std::string layerName = "ShortStrip_pEC_L" + std::to_string(idx);
0618         endcap.addMaterial(layerName + "_Mat", [&](auto& mat) {
0619           mat.configureFace(
0620               PositiveDisc,
0621               asHomogeneous("ShortStrip", m_shortStripEndcapMaterial));
0622           mat.addLayer(layerName, [&](auto& layer) {
0623             layer.setNavigationPolicyFactory(
0624                 createNavigationPolicy(LayerType::Disc));
0625             ACTS_VERBOSE("Adding layer " << layer.name());
0626             layer.setProtoLayer(pl);
0627             layer.setEnvelope(
0628                 Acts::ExtentEnvelope{{.z = {5_mm, 5_mm}, .r = {0_mm, 0_mm}}});
0629           });
0630         });
0631       }
0632     });
0633   }
0634 }
0635 
0636 void Gen3GenericDetectorBuilder::buildLongStrip(
0637     Acts::Experimental::BlueprintNode& parent,
0638     const Acts::GeometryContext& gctx) {
0639   using enum Acts::AxisDirection;
0640   using namespace Acts::Experimental;
0641   using namespace Acts::UnitLiterals;
0642   using enum Acts::CylinderVolumeBounds::Face;
0643   using AttachmentStrategy = Acts::VolumeAttachmentStrategy;
0644   using ResizeStrategy = Acts::VolumeResizeStrategy;
0645 
0646   ACTS_DEBUG("Building Long Strip");
0647 
0648   ProtoLayerCreator lsplCreator = createLongStripProtoLayerCreator();
0649 
0650   auto& lstrip = parent.addCylinderContainer("LongStrip", AxisZ);
0651   lstrip.setAttachmentStrategy(AttachmentStrategy::Gap);
0652   lstrip.setResizeStrategy(ResizeStrategy::Gap);
0653 
0654   lstrip.addCylinderContainer("LongStrip_Barrel", AxisR, [&](auto& barrel) {
0655     barrel.setAttachmentStrategy(AttachmentStrategy::Gap);
0656     barrel.setResizeStrategy(ResizeStrategy::Gap);
0657 
0658     auto protoLayerSurfaces = lsplCreator.centralProtoLayers(gctx);
0659     ACTS_DEBUG("Adding " << protoLayerSurfaces.size()
0660                          << " central proto layers to "
0661                          << "LongStrip_Barrel");
0662     for (const auto& [idx, temp] : Acts::enumerate(protoLayerSurfaces)) {
0663       auto& pl = temp.protoLayer;
0664       std::string layerName = "LongStrip_Barrel_L" + std::to_string(idx);
0665       barrel.addMaterial(layerName + "_Mat", [&](auto& mat) {
0666         mat.configureFace(
0667             InnerCylinder,
0668             asHomogeneous("LongStrip", m_longStripCentralMaterial));
0669         mat.addLayer(layerName, [&](auto& layer) {
0670           layer.setNavigationPolicyFactory(
0671               createNavigationPolicy(LayerType::Cylinder));
0672           ACTS_VERBOSE("Adding layer " << layer.name());
0673           layer.setProtoLayer(pl);
0674           layer.setEnvelope(
0675               Acts::ExtentEnvelope{{.z = {5_mm, 5_mm}, .r = {5_mm, 5_mm}}});
0676         });
0677       });
0678     }
0679   });
0680 
0681   if (m_cfg.buildLevel > 2) {
0682     lstrip.addCylinderContainer("LongStrip_nEC", AxisZ, [&](auto& endcap) {
0683       endcap.setAttachmentStrategy(AttachmentStrategy::Gap);
0684       endcap.setResizeStrategy(ResizeStrategy::Gap);
0685 
0686       auto protoLayerSurfaces = lsplCreator.negativeProtoLayers(gctx);
0687 
0688       ACTS_DEBUG("Adding " << protoLayerSurfaces.size()
0689                            << " negative proto layers to "
0690                            << "LongStrip_nEC");
0691       for (const auto& [idx, temp] : Acts::enumerate(protoLayerSurfaces)) {
0692         auto& pl = temp.protoLayer;
0693         std::string layerName = "LongStrip_nEC_L" + std::to_string(idx);
0694         endcap.addMaterial(layerName + "_Mat", [&](auto& mat) {
0695           mat.configureFace(
0696               NegativeDisc,
0697               asHomogeneous("LongStrip", m_longStripEndcapMaterial));
0698           mat.addLayer(layerName, [&](auto& layer) {
0699             layer.setNavigationPolicyFactory(
0700                 createNavigationPolicy(LayerType::Disc));
0701             ACTS_VERBOSE("Adding layer " << layer.name());
0702             layer.setProtoLayer(pl);
0703             layer.setEnvelope(
0704                 Acts::ExtentEnvelope{{.z = {5_mm, 5_mm}, .r = {0_mm, 0_mm}}});
0705           });
0706         });
0707       }
0708     });
0709 
0710     lstrip.addCylinderContainer("LongStrip_pEC", AxisZ, [&](auto& endcap) {
0711       endcap.setAttachmentStrategy(AttachmentStrategy::Gap);
0712       endcap.setResizeStrategy(ResizeStrategy::Gap);
0713 
0714       auto protoLayerSurfaces = lsplCreator.positiveProtoLayers(gctx);
0715 
0716       ACTS_DEBUG("Adding " << protoLayerSurfaces.size()
0717                            << " positive proto layers to "
0718                            << "LongStrip_pEC");
0719       for (const auto& [idx, temp] : Acts::enumerate(protoLayerSurfaces)) {
0720         auto& pl = temp.protoLayer;
0721         std::string layerName = "LongStrip_pEC_L" + std::to_string(idx);
0722         endcap.addMaterial(layerName + "_Mat", [&](auto& mat) {
0723           mat.configureFace(
0724               PositiveDisc,
0725               asHomogeneous("LongStrip", m_longStripEndcapMaterial));
0726           mat.addLayer(layerName, [&](auto& layer) {
0727             layer.setNavigationPolicyFactory(
0728                 createNavigationPolicy(LayerType::Disc));
0729             ACTS_VERBOSE("Adding layer " << layer.name());
0730             layer.setProtoLayer(pl);
0731             layer.setEnvelope(
0732                 Acts::ExtentEnvelope{{.z = {5_mm, 5_mm}, .r = {0_mm, 0_mm}}});
0733           });
0734         });
0735       }
0736     });
0737   }
0738 }
0739 }  // namespace
0740 }  // namespace Generic
0741 
0742 GenericDetector::GenericDetector(const Config& cfg)
0743     : Detector(Acts::getDefaultLogger("GenericDetector", cfg.logLevel)),
0744       m_cfg(cfg) {
0745   m_nominalGeometryContext =
0746       Acts::GeometryContext::dangerouslyDefaultConstruct();
0747   auto detectorElementFactory =
0748       [this](const Acts::Transform3& transform,
0749              std::shared_ptr<const Acts::PlanarBounds> bounds, double thickness,
0750              std::shared_ptr<const Acts::ISurfaceMaterial> material)
0751       -> std::shared_ptr<GenericDetectorElement> {
0752     auto id =
0753         static_cast<GenericDetectorElement::Identifier>(m_detectorStore.size());
0754     auto detElem = std::make_shared<GenericDetectorElement>(
0755         id, transform, std::move(bounds), thickness, std::move(material));
0756     m_detectorStore.push_back(detElem);
0757     return detElem;
0758   };
0759   buildTrackingGeometry(detectorElementFactory);
0760 }
0761 
0762 GenericDetector::GenericDetector(const Config& cfg, NoBuildTag /*tag*/)
0763     : Detector(Acts::getDefaultLogger("GenericDetector", cfg.logLevel)),
0764       m_cfg(cfg) {}
0765 
0766 void GenericDetector::buildTrackingGeometry(
0767     const Generic::ProtoLayerCreator::DetectorElementFactory&
0768         detectorElementFactory) {
0769   ACTS_INFO("Building tracking geometry");
0770   if (m_trackingGeometry != nullptr) {
0771     throw std::runtime_error("Tracking geometry already built");
0772   }
0773 
0774   Generic::GenericDetectorBuilder::Config cfg;
0775   cfg.detectorElementFactory = detectorElementFactory;
0776   cfg.protoMaterial = m_cfg.buildProto;
0777   cfg.layerLogLevel = m_cfg.layerLogLevel;
0778   cfg.buildLevel = m_cfg.buildLevel;
0779 
0780   if (m_cfg.gen3) {
0781     m_trackingGeometry =
0782         Generic::Gen3GenericDetectorBuilder(cfg, logger().clone())
0783             .buildTrackingGeometry(m_nominalGeometryContext,
0784                                    m_cfg.graphvizFile);
0785   } else {
0786     m_trackingGeometry =
0787         Generic::Gen1GenericDetectorBuilder(cfg, logger().clone())
0788             .buildTrackingGeometry(m_nominalGeometryContext,
0789                                    m_cfg.materialDecorator,
0790                                    m_cfg.surfaceLogLevel, m_cfg.volumeLogLevel);
0791   }
0792 
0793   if (m_trackingGeometry == nullptr) {
0794     throw std::runtime_error("Error building tracking geometry");
0795   }
0796 
0797   ACTS_INFO("Tracking geometry built");
0798 }
0799 
0800 }  // namespace ActsExamples