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/BlueprintBuilder.hpp"
0010 
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Geometry/TrackingVolume.hpp"
0013 // Needed for explicit instantiation of template methods.
0014 #include "Acts/Geometry/detail/BlueprintBuilder_impl.hpp"
0015 #include "Acts/Surfaces/CylinderBounds.hpp"
0016 #include "Acts/Surfaces/Surface.hpp"
0017 #include "ActsPlugins/DD4hep/DD4hepDetectorElement.hpp"
0018 #include "ActsPlugins/Root/TGeoSurfaceConverter.hpp"
0019 
0020 #include <functional>
0021 #include <optional>
0022 #include <stdexcept>
0023 #include <string>
0024 #include <vector>
0025 
0026 #include <DD4hep/DetElement.h>
0027 #include <DD4hep/DetType.h>
0028 #include <DD4hep/Detector.h>
0029 #include <DDRec/DetectorData.h>
0030 
0031 namespace ActsPlugins::DD4hep {
0032 
0033 using ActsPlugins::TGeoAxes;
0034 
0035 DD4hepBackend::DetectorElementPtr DD4hepBackend::defaultElementFactory(
0036     const Element& detElement, AxisDefinition axes, double lengthScale) {
0037   return std::make_shared<DD4hepDetectorElement>(detElement, axes, lengthScale);
0038 }
0039 
0040 DD4hepBackend::DD4hepBackend(const Config& cfg, const Acts::Logger& logger)
0041     : m_cfg(cfg), m_logger(&logger) {
0042   if (m_cfg.dd4hepDetector == nullptr) {
0043     throw std::invalid_argument("DD4hepBackend: dd4hepDetector is null");
0044   }
0045 }
0046 
0047 DD4hepBackend::DetectorElementPtr DD4hepBackend::createDetectorElement(
0048     const Element& detElement, AxisDefinition axes) const {
0049   auto elem = m_cfg.elementFactory(detElement, axes, m_cfg.lengthScale);
0050 
0051   detElement.addExtension<DD4hepDetectorElementExtension>(
0052       new dd4hep::rec::StructExtension(DD4hepDetectorElementExtension(elem)));
0053 
0054   return elem;
0055 }
0056 
0057 namespace {
0058 void visitSubtree(
0059     const dd4hep::DetElement& detElement,
0060     const std::function<void(const dd4hep::DetElement&)>& visitor) {
0061   visitor(detElement);
0062 
0063   for (const auto& [name, child] : detElement.children()) {
0064     (void)name;
0065     visitSubtree(child, visitor);
0066   }
0067 }
0068 }  // namespace
0069 
0070 DD4hepBackend::Element DD4hepBackend::world() const {
0071   return m_cfg.dd4hepDetector->world();
0072 }
0073 
0074 std::string DD4hepBackend::nameOf(const Element& element) const {
0075   return element.name();
0076 }
0077 
0078 std::vector<DD4hepBackend::Element> DD4hepBackend::children(
0079     const Element& parent) const {
0080   std::vector<Element> result;
0081   result.reserve(parent.children().size());
0082   for (const auto& [name, child] : parent.children()) {
0083     (void)name;
0084     result.push_back(child);
0085   }
0086   return result;
0087 }
0088 
0089 DD4hepBackend::Element DD4hepBackend::parent(const Element& element) const {
0090   return element.parent();
0091 }
0092 
0093 bool DD4hepBackend::isSensitive(const Element& element) const {
0094   return element.volume().isSensitive();
0095 }
0096 
0097 bool DD4hepBackend::isBarrel(const Element& element) const {
0098   return dd4hep::DetType{element.typeFlag()}.is(dd4hep::DetType::BARREL);
0099 }
0100 
0101 bool DD4hepBackend::isEndcap(const Element& element) const {
0102   return dd4hep::DetType{element.typeFlag()}.is(dd4hep::DetType::ENDCAP);
0103 }
0104 
0105 bool DD4hepBackend::isTracker(const Element& element) const {
0106   return dd4hep::DetType{element.typeFlag()}.is(dd4hep::DetType::TRACKER);
0107 }
0108 
0109 std::vector<std::shared_ptr<Acts::Surface>> DD4hepBackend::makeSurfaces(
0110     std::span<const dd4hep::DetElement> sensitives,
0111     const LayerSpec& layerSpec) const {
0112   if (!layerSpec.axes.has_value()) {
0113     throw std::runtime_error("DD4hepBackend::makeSurfaces: axes not set");
0114   }
0115 
0116   ACTS_DEBUG("Using " << sensitives.size() << " sensitive elements.");
0117 
0118   std::vector<std::shared_ptr<Acts::Surface>> surfaces;
0119   surfaces.reserve(sensitives.size());
0120 
0121   for (const auto& sensitive : sensitives) {
0122     auto elem = createDetectorElement(sensitive, layerSpec.axes.value());
0123     surfaces.push_back(elem->surface().getSharedPtr());
0124   }
0125 
0126   return surfaces;
0127 }
0128 
0129 std::optional<Acts::Transform3> DD4hepBackend::lookupLayerTransform(
0130     const dd4hep::DetElement& element, const LayerSpec& layerSpec) const {
0131   if (layerSpec.layerAxes.has_value()) {
0132     ACTS_DEBUG("Finding layer transform automatically using layer axes: "
0133                << layerSpec.layerAxes.value());
0134     Acts::Transform3 layerTransform = TGeoSurfaceConverter::transformFromShape(
0135         *element.placement().ptr()->GetVolume()->GetShape(),
0136         element.nominal().worldTransformation(), layerSpec.layerAxes.value(),
0137         m_cfg.lengthScale);
0138 
0139     ACTS_VERBOSE(" -> Layer transform:\n" << layerTransform.matrix());
0140     return layerTransform;
0141   }
0142 
0143   return std::nullopt;
0144 }
0145 
0146 std::shared_ptr<Acts::Experimental::StaticBlueprintNode>
0147 DD4hepBackend::makeBeampipe() const {
0148   std::optional<dd4hep::DetElement> beampipeElement = std::nullopt;
0149 
0150   visitSubtree(world(), [this,
0151                          &beampipeElement](const dd4hep::DetElement& elem) {
0152     if (!dd4hep::DetType{elem.typeFlag()}.is(dd4hep::DetType::BEAMPIPE)) {
0153       return;
0154     }
0155     if (beampipeElement.has_value()) {
0156       ACTS_WARNING("Multiple beampipe elements found, using first: "
0157                    << beampipeElement->name() << ", ignoring: " << elem.name());
0158       return;
0159     }
0160     beampipeElement = elem;
0161   });
0162 
0163   if (!beampipeElement.has_value()) {
0164     ACTS_ERROR("No beampipe element found in DD4hep detector.");
0165     throw std::runtime_error("No beampipe element found in DD4hep detector.");
0166   }
0167 
0168   ACTS_INFO("Beampipe element found: " << beampipeElement->name());
0169 
0170   const auto tgTransform = beampipeElement->nominal().worldTransformation();
0171   auto [bounds, transform, thickness] =
0172       ActsPlugins::TGeoSurfaceConverter::cylinderComponents(
0173           *beampipeElement->placement().ptr()->GetVolume()->GetShape(),
0174           tgTransform.GetRotationMatrix(), tgTransform.GetTranslation(), "XYZ",
0175           m_cfg.lengthScale);
0176   (void)thickness;
0177 
0178   if (bounds == nullptr) {
0179     ACTS_ERROR("Beampipe element shape could not be converted to cylinder.");
0180     throw std::runtime_error(
0181         "Beampipe element shape could not be converted to cylinder.");
0182   }
0183 
0184   auto volumeBounds = std::make_shared<Acts::CylinderVolumeBounds>(
0185       0, bounds->get(Acts::CylinderBounds::eR),
0186       bounds->get(Acts::CylinderBounds::eHalfLengthZ));
0187   auto volume = std::make_unique<Acts::TrackingVolume>(transform, volumeBounds,
0188                                                        beampipeElement->name());
0189   return std::make_shared<Acts::Experimental::StaticBlueprintNode>(
0190       std::move(volume));
0191 }
0192 
0193 }  // namespace ActsPlugins::DD4hep
0194 
0195 // Explicit template instantiation for DD4hepBackend. Ensures all template
0196 // code is compiled in this TU; other TUs use extern template and link here.
0197 // Must be in ::Acts::Experimental (at global scope) to match the template defs.
0198 namespace Acts::Experimental {
0199 template class BlueprintBuilder<ActsPlugins::DD4hep::DD4hepBackend>;
0200 template class ElementLayerAssembler<ActsPlugins::DD4hep::DD4hepBackend>;
0201 template class SensorLayerAssembler<ActsPlugins::DD4hep::DD4hepBackend>;
0202 template class SensorLayer<ActsPlugins::DD4hep::DD4hepBackend>;
0203 template class BarrelEndcapAssembler<ActsPlugins::DD4hep::DD4hepBackend>;
0204 }  // namespace Acts::Experimental