Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-17 07:47:15

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 CERN for the benefit of the ACTS project
0004 //
0005 // This Source Code Form is subject to the terms of the Mozilla Public
0006 // License, v. 2.0. If a copy of the MPL was not distributed with this
0007 // file, You can obtain one at https://mozilla.org/MPL/2.0/.
0008 
0009 #include "ActsPlugins/DD4hep/OpenDataDetectorBuilder.hpp"
0010 
0011 #include "Acts/Definitions/Units.hpp"
0012 #include "Acts/Geometry/Blueprint.hpp"
0013 #include "Acts/Geometry/BlueprintOptions.hpp"
0014 #include "Acts/Geometry/ContainerBlueprintNode.hpp"
0015 #include "Acts/Geometry/Extent.hpp"
0016 #include "Acts/Geometry/NavigationPolicyFactory.hpp"
0017 #include "Acts/Geometry/VolumeAttachmentStrategy.hpp"
0018 #include "Acts/Geometry/VolumeResizeStrategy.hpp"
0019 #include "Acts/Navigation/CylinderNavigationPolicy.hpp"
0020 #include "Acts/Navigation/SurfaceArrayNavigationPolicy.hpp"
0021 #include "Acts/Utilities/AxisDefinitions.hpp"
0022 #include "ActsPlugins/DD4hep/BlueprintBuilder.hpp"
0023 
0024 #include <format>
0025 #include <memory>
0026 #include <optional>
0027 #include <regex>
0028 #include <stdexcept>
0029 #include <string>
0030 #include <utility>
0031 
0032 #include <DD4hep/DetElement.h>
0033 #include <DD4hep/Detector.h>
0034 
0035 namespace ActsPlugins::DD4hep {
0036 
0037 namespace {
0038 
0039 auto makeLayerCustomizer(const BlueprintBuilder& builder, std::string det,
0040                          std::regex layerFilter) {
0041   return [&builder, det = std::move(det), layerFilter = std::move(layerFilter)](
0042              const std::optional<dd4hep::DetElement>& elem,
0043              Acts::Experimental::LayerBlueprintNode& layer) {
0044     layer.setEnvelope(detail::kLayerEnvelope);
0045 
0046     const std::string elemName =
0047         elem.has_value() ? std::string{builder.backend().nameOf(*elem)}
0048                          : layer.name();
0049     const int layerIdx = detail::layerIndexFromName(elemName, layerFilter);
0050 
0051     using SrfArrayNavPol = Acts::SurfaceArrayNavigationPolicy;
0052     using enum SrfArrayNavPol::LayerType;
0053 
0054     SrfArrayNavPol::Config navCfg;
0055 
0056     if (layer.layerType() ==
0057         Acts::Experimental::LayerBlueprintNode::LayerType::Cylinder) {
0058       // Barrel layer
0059       navCfg.layerType = Cylinder;
0060       navCfg.bins = {
0061           builder.backend().constant("{}_b{}_sf_b_phi", det, layerIdx),
0062           builder.backend().constant("{}_b_sf_b_z", det)};
0063     } else {
0064       // Endcap layer
0065       navCfg.layerType = Disc;
0066       navCfg.bins = {builder.backend().constant("{}_e_sf_b_r", det),
0067                      builder.backend().constant("{}_e_sf_b_phi", det)};
0068     }
0069 
0070     layer.setNavigationPolicyFactory(Acts::NavigationPolicyFactory{}
0071                                          .add<Acts::CylinderNavigationPolicy>()
0072                                          .add<SrfArrayNavPol>(navCfg)
0073                                          .asUniquePtr());
0074   };
0075 }
0076 
0077 void addDirectLayerSubsystem(const BlueprintBuilder& builder,
0078                              Acts::Experimental::ContainerBlueprintNode& outer,
0079                              std::string assembly, std::string det,
0080                              const std::regex& layerFilter) {
0081   const auto assemblyElement = builder.findDetElementByName(assembly);
0082   if (!assemblyElement.has_value()) {
0083     throw std::runtime_error(
0084         std::format("Could not find assembly '{}'", assembly));
0085   }
0086 
0087   auto barrels = builder.findBarrelElements(*assemblyElement);
0088   auto endcaps = builder.findEndcapElements(*assemblyElement);
0089 
0090   const std::string assemblyName{builder.backend().nameOf(*assemblyElement)};
0091   auto containerNode =
0092       std::make_shared<Acts::Experimental::CylinderContainerBlueprintNode>(
0093           assemblyName, Acts::AxisDirection::AxisZ);
0094 
0095   auto layerCustomizer =
0096       makeLayerCustomizer(builder, std::move(det), layerFilter);
0097 
0098   auto addLayerChildren = [&](const auto& elements, auto makeNode) {
0099     for (const auto& element : elements) {
0100       auto node = makeNode(element);
0101       node->setAttachmentStrategy(Acts::VolumeAttachmentStrategy::Gap);
0102       node->setResizeStrategies(Acts::VolumeResizeStrategy::Gap,
0103                                 Acts::VolumeResizeStrategy::Gap);
0104       containerNode->addChild(std::move(node));
0105     }
0106   };
0107 
0108   addLayerChildren(barrels, [&](const auto& barrel) {
0109     return builder.layers()
0110         .barrel()
0111         .setSensorAxes("XYZ")
0112         .setLayerFilter(layerFilter)
0113         .setContainer(barrel)
0114         .onLayer(layerCustomizer)
0115         .build();
0116   });
0117 
0118   addLayerChildren(endcaps, [&](const auto& endcap) {
0119     return builder.layers()
0120         .endcap()
0121         .setSensorAxes("XZY")
0122         .setLayerFilter(layerFilter)
0123         .setContainer(endcap)
0124         .onLayer(layerCustomizer)
0125         .build();
0126   });
0127 
0128   outer.addChild(std::move(containerNode));
0129 }
0130 
0131 void addBarrelEndcapSubsystem(const BlueprintBuilder& builder,
0132                               Acts::Experimental::ContainerBlueprintNode& outer,
0133                               std::string assembly, std::string det,
0134                               const std::regex& layerFilter) {
0135   const auto assemblyElement = builder.findDetElementByName(assembly);
0136   if (!assemblyElement.has_value()) {
0137     throw std::runtime_error(
0138         std::format("Could not find assembly '{}'", assembly));
0139   }
0140 
0141   builder.barrelEndcap()
0142       .setAssembly(*assemblyElement)
0143       .setSensorAxes("XYZ", "XZY")
0144       .setLayerFilter(layerFilter)
0145       .onLayer(makeLayerCustomizer(builder, std::move(det), layerFilter))
0146       .onContainer(
0147           [](const auto&, Acts::Experimental::ContainerBlueprintNode& node) {
0148             node.setAttachmentStrategy(Acts::VolumeAttachmentStrategy::Gap);
0149             node.setResizeStrategies(Acts::VolumeResizeStrategy::Gap,
0150                                      Acts::VolumeResizeStrategy::Gap);
0151           })
0152       .addTo(outer);
0153 }
0154 
0155 void addDirectLayerGroupedSubsystem(
0156     const BlueprintBuilder& builder,
0157     Acts::Experimental::ContainerBlueprintNode& outer, std::string assembly,
0158     std::string det, const std::regex& layerFilter) {
0159   const auto assemblyElement = builder.findDetElementByName(assembly);
0160   if (!assemblyElement.has_value()) {
0161     throw std::runtime_error(
0162         std::format("Could not find assembly '{}'", assembly));
0163   }
0164 
0165   auto barrels = builder.findBarrelElements(*assemblyElement);
0166   auto endcaps = builder.findEndcapElements(*assemblyElement);
0167 
0168   const std::string assemblyName{builder.backend().nameOf(*assemblyElement)};
0169   auto containerNode =
0170       std::make_shared<Acts::Experimental::CylinderContainerBlueprintNode>(
0171           assemblyName, Acts::AxisDirection::AxisZ);
0172 
0173   auto layerCustomizer =
0174       makeLayerCustomizer(builder, std::move(det), layerFilter);
0175 
0176   auto sensorToLayerKey = [&](const dd4hep::DetElement& elem) {
0177     auto current = elem;
0178     const auto world = builder.backend().world();
0179     while (!(current == world)) {
0180       std::cmatch match;
0181       if (const std::string name{builder.backend().nameOf(current)};
0182           std::regex_search(name.c_str(), match, layerFilter) &&
0183           match.size() > 1) {
0184         return builder.getPathToElementName(current);
0185       }
0186       current = builder.backend().parent(current);
0187     }
0188     return builder.getPathToElementName(elem);
0189   };
0190 
0191   for (const auto& barrel : barrels) {
0192     auto sensors = builder.resolveSensitives(barrel);
0193     auto barrelNode = builder.layersFromSensors()
0194                           .barrel()
0195                           .setSensorAxes("XYZ")
0196                           .setSensors(std::move(sensors))
0197                           .setContainerName(builder.backend().nameOf(barrel))
0198                           .groupBy(sensorToLayerKey)
0199                           .onLayer(layerCustomizer)
0200                           .build();
0201     barrelNode->setAttachmentStrategy(Acts::VolumeAttachmentStrategy::Gap);
0202     barrelNode->setResizeStrategies(Acts::VolumeResizeStrategy::Gap,
0203                                     Acts::VolumeResizeStrategy::Gap);
0204     containerNode->addChild(std::move(barrelNode));
0205   }
0206 
0207   for (const auto& endcap : endcaps) {
0208     auto sensors = builder.resolveSensitives(endcap);
0209     auto endcapNode = builder.layersFromSensors()
0210                           .endcap()
0211                           .setSensorAxes("XZY")
0212                           .setSensors(std::move(sensors))
0213                           .setContainerName(builder.backend().nameOf(endcap))
0214                           .groupBy(sensorToLayerKey)
0215                           .onLayer(layerCustomizer)
0216                           .build();
0217     endcapNode->setAttachmentStrategy(Acts::VolumeAttachmentStrategy::Gap);
0218     endcapNode->setResizeStrategies(Acts::VolumeResizeStrategy::Gap,
0219                                     Acts::VolumeResizeStrategy::Gap);
0220     containerNode->addChild(std::move(endcapNode));
0221   }
0222 
0223   outer.addChild(std::move(containerNode));
0224 }
0225 
0226 }  // namespace
0227 
0228 std::unique_ptr<Acts::TrackingGeometry> buildOpenDataDetectorBarrelEndcap(
0229     const dd4hep::Detector& detector, const Acts::GeometryContext& gctx,
0230     const Acts::Logger& logger) {
0231   using namespace Acts::Experimental;
0232   using namespace Acts;
0233   using enum AxisDirection;
0234 
0235   BlueprintBuilder builder{{
0236                                .dd4hepDetector = &detector,
0237                                .lengthScale = Acts::UnitConstants::cm,
0238                                .gctx = gctx,
0239                            },
0240                            logger.cloneWithSuffix("BlpBld")};
0241 
0242   Blueprint::Config blueprintCfg;
0243   blueprintCfg.envelope = ActsPlugins::DD4hep::detail::kBlueprintEnvelope;
0244   Blueprint root{blueprintCfg};
0245 
0246   auto& outer = root.addCylinderContainer("OpenDataDetector", AxisR);
0247   outer.setAttachmentStrategy(VolumeAttachmentStrategy::Gap);
0248 
0249   outer.addChild(builder.backend().makeBeampipe());
0250 
0251   addBarrelEndcapSubsystem(builder, outer, "Pixels", "pix",
0252                            ActsPlugins::DD4hep::detail::kPixelLayerFilter);
0253   addBarrelEndcapSubsystem(builder, outer, "ShortStrips", "ss",
0254                            ActsPlugins::DD4hep::detail::kShortStripLayerFilter);
0255   addBarrelEndcapSubsystem(builder, outer, "LongStrips", "ls",
0256                            ActsPlugins::DD4hep::detail::kLongStripLayerFilter);
0257 
0258   return root.construct(BlueprintOptions{}, gctx, logger);
0259 }
0260 
0261 std::unique_ptr<Acts::TrackingGeometry> buildOpenDataDetectorDirectLayer(
0262     const dd4hep::Detector& detector, const Acts::GeometryContext& gctx,
0263     const Acts::Logger& logger) {
0264   using namespace Acts::Experimental;
0265   using namespace Acts;
0266   using enum AxisDirection;
0267 
0268   BlueprintBuilder builder{{
0269                                .dd4hepDetector = &detector,
0270                                .lengthScale = Acts::UnitConstants::cm,
0271                                .gctx = gctx,
0272                            },
0273                            logger.cloneWithSuffix("BlpBld")};
0274 
0275   Blueprint::Config blueprintCfg;
0276   blueprintCfg.envelope = ActsPlugins::DD4hep::detail::kBlueprintEnvelope;
0277   Blueprint root{blueprintCfg};
0278 
0279   auto& outer = root.addCylinderContainer("OpenDataDetector", AxisR);
0280   outer.setAttachmentStrategy(VolumeAttachmentStrategy::Gap);
0281 
0282   outer.addChild(builder.backend().makeBeampipe());
0283 
0284   addDirectLayerSubsystem(builder, outer, "Pixels", "pix",
0285                           ActsPlugins::DD4hep::detail::kPixelLayerFilter);
0286   addDirectLayerSubsystem(builder, outer, "ShortStrips", "ss",
0287                           ActsPlugins::DD4hep::detail::kShortStripLayerFilter);
0288   addDirectLayerSubsystem(builder, outer, "LongStrips", "ls",
0289                           ActsPlugins::DD4hep::detail::kLongStripLayerFilter);
0290 
0291   return root.construct(BlueprintOptions{}, gctx, logger);
0292 }
0293 
0294 std::unique_ptr<Acts::TrackingGeometry> buildOpenDataDetectorDirectLayerGrouped(
0295     const dd4hep::Detector& detector, const Acts::GeometryContext& gctx,
0296     const Acts::Logger& logger) {
0297   using namespace Acts::Experimental;
0298   using namespace Acts;
0299   using enum AxisDirection;
0300 
0301   BlueprintBuilder builder{{
0302                                .dd4hepDetector = &detector,
0303                                .lengthScale = Acts::UnitConstants::cm,
0304                                .gctx = gctx,
0305                            },
0306                            logger.cloneWithSuffix("BlpBld")};
0307 
0308   Blueprint::Config blueprintCfg;
0309   blueprintCfg.envelope = ActsPlugins::DD4hep::detail::kBlueprintEnvelope;
0310   Blueprint root{blueprintCfg};
0311 
0312   auto& outer = root.addCylinderContainer("OpenDataDetector", AxisR);
0313   outer.setAttachmentStrategy(VolumeAttachmentStrategy::Gap);
0314 
0315   outer.addChild(builder.backend().makeBeampipe());
0316 
0317   addDirectLayerGroupedSubsystem(
0318       builder, outer, "Pixels", "pix",
0319       ActsPlugins::DD4hep::detail::kPixelLayerFilter);
0320   addDirectLayerGroupedSubsystem(
0321       builder, outer, "ShortStrips", "ss",
0322       ActsPlugins::DD4hep::detail::kShortStripLayerFilter);
0323   addDirectLayerGroupedSubsystem(
0324       builder, outer, "LongStrips", "ls",
0325       ActsPlugins::DD4hep::detail::kLongStripLayerFilter);
0326 
0327   return root.construct(BlueprintOptions{}, gctx, logger);
0328 }
0329 
0330 }  // namespace ActsPlugins::DD4hep