Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-07-02 07:51:52

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/DD4hepBlueprintFactory.hpp"
0010 
0011 #include "Acts/Detector/GeometryIdGenerator.hpp"
0012 #include "Acts/Detector/IndexedRootVolumeFinderBuilder.hpp"
0013 #include "Acts/Plugins/DD4hep/DD4hepBinningHelpers.hpp"
0014 #include "Acts/Plugins/DD4hep/DD4hepConversionHelpers.hpp"
0015 #include "Acts/Utilities/BinningData.hpp"
0016 #include "Acts/Utilities/StringHelpers.hpp"
0017 
0018 #include <sstream>
0019 
0020 Acts::Experimental::DD4hepBlueprintFactory::DD4hepBlueprintFactory(
0021     const Config& cfg, std::unique_ptr<const Logger> mlogger)
0022     : m_cfg(cfg), m_logger(std::move(mlogger)) {
0023   ACTS_DEBUG("UnitLength conversion factor (DD4hep -> Acts): " << unitLength);
0024 }
0025 
0026 std::unique_ptr<Acts::Experimental::Gen2Blueprint::Node>
0027 Acts::Experimental::DD4hepBlueprintFactory::create(
0028     Cache& cache, const GeometryContext& gctx,
0029     const dd4hep::DetElement& dd4hepElement) const {
0030   ACTS_DEBUG("Drawing a blueprint from the DD4hep element '"
0031              << dd4hepElement.name() << "'.");
0032 
0033   // Create the root node
0034   std::vector<double> bValues = {0., 150., 1000.};
0035   std::vector<AxisDirection> binning = {Acts::AxisDirection::AxisR};
0036   auto root = std::make_unique<Acts::Experimental::Gen2Blueprint::Node>(
0037       dd4hepElement.name(), Acts::Transform3::Identity(),
0038       Acts::VolumeBounds::eCylinder, bValues, binning);
0039 
0040   // Recursively parse the tree
0041   recursiveParse(cache, *root, gctx, dd4hepElement);
0042   // Return the top node
0043   return root;
0044 }
0045 
0046 void Acts::Experimental::DD4hepBlueprintFactory::recursiveParse(
0047     Cache& cache, Gen2Blueprint::Node& mother, const GeometryContext& gctx,
0048     const dd4hep::DetElement& dd4hepElement, unsigned int hiearchyLevel) const {
0049   // This will allow to skip empty hierarchy levels
0050   Gen2Blueprint::Node* current = &mother;
0051   unsigned int hierarchyAddOn = 0;
0052 
0053   std::string ofs(hiearchyLevel * 2u, ' ');
0054 
0055   // Node types
0056   std::vector<std::string> nodeTypes = {"acts_world", "acts_container",
0057                                         "acts_volume"};
0058   for (const auto& nType : nodeTypes) {
0059     // Check if it complies with the given definition
0060     bool ntt = getParamOr<bool>(nType, dd4hepElement, false);
0061     if (ntt) {
0062       ACTS_DEBUG(ofs << "ACTS node '" << nType
0063                      << "' attached to dd4hep element '" << dd4hepElement.name()
0064                      << "',");
0065       // Extract potential internal builders and tools
0066       auto [internalsBuilder, rootsFinderBuilder, geoIdGenerator, auxInt,
0067             extOpt] =
0068           extractInternals(cache.dd4hepStore, gctx, dd4hepElement, nType);
0069       // Extract the bounds type, values and binning
0070       auto [transform, bValueType, bValues, binning, auxExt] =
0071           extractExternals(gctx, dd4hepElement, nType, extOpt);
0072       // Screen output of position and shape
0073       ACTS_DEBUG(ofs << " - translation  : "
0074                      << toString(transform.translation()));
0075       ACTS_DEBUG(ofs << " - bounds type  : " << bValueType);
0076       ACTS_DEBUG(ofs << " - bound values : " << toString(bValues));
0077       // If it is not the world node, create a new one
0078       if (nType == "acts_world") {
0079         mother.transform = transform;
0080         mother.boundsType = bValueType;
0081         mother.boundaryValues = bValues;
0082         mother.binning = binning;
0083 
0084       } else if (nType == "acts_container") {
0085         // Creating the branch node
0086         auto branch = std::make_unique<Acts::Experimental::Gen2Blueprint::Node>(
0087             dd4hepElement.name(), transform, bValueType, bValues, binning);
0088         current = branch.get();
0089         mother.add(std::move(branch));
0090 
0091       } else if (nType == "acts_volume") {
0092         // Crreating a leaf node
0093         auto leaf = std::make_unique<Acts::Experimental::Gen2Blueprint::Node>(
0094             dd4hepElement.name(), transform, bValueType, bValues);
0095         current = leaf.get();
0096         mother.add(std::move(leaf));
0097       }
0098       // Current is set now appropriately, adding auxiliary information
0099       if (!auxExt.empty()) {
0100         ACTS_VERBOSE(ofs << " - " << auxExt);
0101         current->auxiliary.push_back(auxExt);
0102       }
0103       // Adding the internals builder - if present
0104       if (internalsBuilder != nullptr) {
0105         ACTS_VERBOSE(ofs << " - " << auxInt[0u]);
0106         current->internalsBuilder = internalsBuilder;
0107       }
0108       // Adding root finder builder - if present
0109       if (rootsFinderBuilder != nullptr) {
0110         ACTS_VERBOSE(ofs << " - " << auxInt[1u]);
0111         current->rootVolumeFinderBuilder = rootsFinderBuilder;
0112       }
0113 
0114       // Check for proto material for the portals, max portal number
0115       // can be changed in configuration
0116       for (unsigned int p = 0u; p < m_cfg.maxPortals; ++p) {
0117         std::string pmName = "acts_portal_proto_material_" + std::to_string(p);
0118         auto protoMaterial = getParamOr<bool>(pmName, dd4hepElement, false);
0119         if (protoMaterial) {
0120           ACTS_VERBOSE(ofs << " - proto material binning for portal " << p
0121                            << " found");
0122           auto pmProtoAxis = DD4hepBinningHelpers::convertBinning(
0123               dd4hepElement, pmName + "_binning");
0124           // Strip out the axis without expansion
0125           std::vector<DirectedProtoAxis> pmAxisBare = {};
0126           for (const auto& [dpAxis, nB] : pmProtoAxis) {
0127             pmAxisBare.emplace_back(dpAxis);
0128           }
0129           current->portalMaterialBinning[p] = pmAxisBare;
0130           ACTS_VERBOSE(ofs << " - binning description is "
0131                            << current->portalMaterialBinning[p]);
0132         }
0133       }
0134 
0135       // Adding geo Id generator - if present
0136       if (geoIdGenerator != nullptr) {
0137         ACTS_VERBOSE(ofs << " - " << auxInt[2u]);
0138         current->geoIdGenerator = geoIdGenerator;
0139       }
0140     }
0141   }
0142 
0143   // Step down to the children - not possible for leaf nodes
0144   const dd4hep::DetElement::Children& children = dd4hepElement.children();
0145   if (!children.empty()) {
0146     ACTS_VERBOSE(ofs << "dd4hep element '" << dd4hepElement.name() << "' has "
0147                      << children.size() << " children.");
0148     for (auto& child : children) {
0149       dd4hep::DetElement dd4hepChild = child.second;
0150       recursiveParse(cache, *current, gctx, dd4hepChild,
0151                      hiearchyLevel + hierarchyAddOn);
0152     }
0153   }
0154 }
0155 
0156 std::tuple<Acts::Transform3, Acts::VolumeBounds::BoundsType,
0157            std::vector<double>, std::vector<Acts::AxisDirection>, std::string>
0158 Acts::Experimental::DD4hepBlueprintFactory::extractExternals(
0159     [[maybe_unused]] const GeometryContext& gctx,
0160     const dd4hep::DetElement& dd4hepElement, const std::string& baseName,
0161     const std::optional<Extent>& extOpt) const {
0162   std::string aux = "";
0163 
0164   /// Get the transform - extract from values first
0165   auto transform = extractTransform(dd4hepElement, baseName, unitLength);
0166 
0167   // Get the bounds type
0168   auto bValueInt =
0169       getParamOr<int>(baseName + "_type", dd4hepElement,
0170                       static_cast<int>(VolumeBounds::BoundsType::eOther));
0171   auto bValueType = static_cast<VolumeBounds::BoundsType>(bValueInt);
0172   std::vector<double> bValues = {};
0173 
0174   // Get the bound values from parsed internals if possible
0175   if (extOpt.has_value() && bValueType == VolumeBounds::BoundsType::eCylinder) {
0176     // Set as defaults
0177     bValues = {0., 0., 0.};
0178     auto parsedExtent = extOpt.value();
0179     if (parsedExtent.constrains(AxisDirection::AxisR)) {
0180       bValues[0u] = std::floor(parsedExtent.min(AxisDirection::AxisR));
0181       bValues[1u] = std::ceil(parsedExtent.max(AxisDirection::AxisR));
0182     }
0183     if (parsedExtent.constrains(AxisDirection::AxisZ)) {
0184       double minZ = parsedExtent.min(AxisDirection::AxisZ) > 0.
0185                         ? std::floor(parsedExtent.min(AxisDirection::AxisZ))
0186                         : std::ceil(parsedExtent.min(AxisDirection::AxisZ));
0187       double maxZ = parsedExtent.max(AxisDirection::AxisZ) > 0.
0188                         ? std::floor(parsedExtent.max(AxisDirection::AxisZ))
0189                         : std::ceil(parsedExtent.max(AxisDirection::AxisZ));
0190       bValues[2u] = 0.5 * (maxZ - minZ);
0191       transform.translation().z() = 0.5 * (maxZ + minZ);
0192     }
0193     ACTS_VERBOSE("   cylindrical bounds determined from internals as "
0194                  << toString(bValues));
0195   }
0196 
0197   // Get the bounds values from the series if not found before
0198   if (bValues.empty()) {
0199     bValues =
0200         extractSeries<double>(dd4hepElement, baseName + "_bvalues", unitLength);
0201     ACTS_VERBOSE(" - cylindrical determined from variant parameters as "
0202                  << toString(bValues));
0203   }
0204 
0205   // Get the binning values
0206   auto binningString =
0207       getParamOr<std::string>(baseName + "_binning", dd4hepElement, "");
0208   std::vector<AxisDirection> bBinning =
0209       Acts::stringToAxisDirections(binningString);
0210   if (!binningString.empty()) {
0211     aux += "vol. binning : " + binningString;
0212   }
0213   // Return the tuple
0214   return {transform, bValueType, bValues, bBinning, aux};
0215 }
0216 
0217 std::tuple<std::shared_ptr<const Acts::Experimental::IInternalStructureBuilder>,
0218            std::shared_ptr<const Acts::Experimental::IRootVolumeFinderBuilder>,
0219            std::shared_ptr<const Acts::Experimental::IGeometryIdGenerator>,
0220            std::array<std::string, 3u>, std::optional<Acts::Extent>>
0221 Acts::Experimental::DD4hepBlueprintFactory::extractInternals(
0222     Acts::DD4hepDetectorElement::Store& dd4hepStore,
0223     const GeometryContext& gctx, const dd4hep::DetElement& dd4hepElement,
0224     const std::string& baseName) const {
0225   // Return objects
0226   std::shared_ptr<const Acts::Experimental::IInternalStructureBuilder>
0227       internalsBuilder = nullptr;
0228   std::shared_ptr<const Acts::Experimental::IRootVolumeFinderBuilder>
0229       rootsFinderBuilder = nullptr;
0230   std::shared_ptr<const Acts::Experimental::IGeometryIdGenerator>
0231       geoIdGenerator = nullptr;
0232   /// The hand-over information for externals
0233   std::optional<Extent> ext = std::nullopt;
0234   /// Auxiliary information
0235   std::array<std::string, 3u> aux = {"", "", ""};
0236 
0237   // Check for internal structure builder
0238   auto internals =
0239       Acts::getParamOr<bool>(baseName + "_internals", dd4hepElement, false);
0240   if (internals) {
0241     auto internalsType = Acts::getParamOr<std::string>(
0242         baseName + "_internals_type", dd4hepElement, "");
0243     if (internalsType == "layer") {
0244       aux[0u] = "int. struct : layer";
0245       // Create a new layer builder
0246       DD4hepLayerStructure::Options lOptions;
0247       lOptions.name = dd4hepElement.name();
0248       // Check whether internal/sensitive surfaces should have directly
0249       // translated material
0250       auto convertMaterial = Acts::getParamOr<bool>(
0251           "acts_surface_material_conversion", dd4hepElement, false);
0252       lOptions.conversionOptions.convertMaterial = convertMaterial;
0253       // Check if the extent should be measured
0254       auto interenalsMeasure = Acts::getParamOr<std::string>(
0255           baseName + "_internals_measure", dd4hepElement, "");
0256       auto internalsClearance =
0257           unitLength *
0258           Acts::getParamOr<double>(baseName + "_internals_clearance",
0259                                    dd4hepElement, 0.);
0260       auto internalAxisDirections = stringToAxisDirections(interenalsMeasure);
0261       if (!internalAxisDirections.empty()) {
0262         ACTS_VERBOSE(" - internals extent measurement requested");
0263         Extent internalsExtent;
0264         ExtentEnvelope clearance = ExtentEnvelope::Zero();
0265         for (const auto& bv : internalAxisDirections) {
0266           ACTS_VERBOSE("   -> measuring extent for " << axisDirectionName(bv));
0267           ACTS_VERBOSE("   -> with clearance :" << internalsClearance);
0268           clearance[bv] = {internalsClearance, internalsClearance};
0269         }
0270         internalsExtent.setEnvelope(clearance);
0271         lOptions.extent = internalsExtent;
0272         lOptions.extentConstraints = internalAxisDirections;
0273       }
0274       // Create the builder from the dd4hep element
0275       auto [ib, extOpt] = m_cfg.layerStructure->builder(
0276           dd4hepStore, gctx, dd4hepElement, lOptions);
0277       internalsBuilder = std::move(ib);
0278       if (extOpt.has_value()) {
0279         ACTS_VERBOSE(" - internals extent measured as "
0280                      << extOpt.value().toString());
0281       }
0282       ext = extOpt;
0283     }
0284   }
0285 
0286   // Check for root volume finder
0287   auto rootFinder = Acts::getParamOr<std::string>(
0288       baseName + "_root_volume_finder", dd4hepElement, "");
0289   if (rootFinder == "indexed") {
0290     aux[1u] = "root finder : indexed";
0291     std::vector<AxisDirection> binning = {AxisDirection::AxisZ,
0292                                           AxisDirection::AxisR};
0293     rootsFinderBuilder =
0294         std::make_shared<Acts::Experimental::IndexedRootVolumeFinderBuilder>(
0295             binning);
0296   }
0297 
0298   // Check for geo Id generator
0299   auto geoIdGen =
0300       Acts::getParamOr<std::string>(baseName + "_geo_id", dd4hepElement, "");
0301   if (geoIdGen == "incremental") {
0302     aux[2u] = "geo_id gen. : incremental";
0303     Acts::Experimental::GeometryIdGenerator::Config geoIdCfg;
0304     geoIdGenerator =
0305         std::make_shared<Acts::Experimental::GeometryIdGenerator>(geoIdCfg);
0306   } else if (geoIdGen == "container") {
0307     aux[2u] = "geo_id gen. : container";
0308     Acts::Experimental::GeometryIdGenerator::Config geoIdCfg;
0309     geoIdCfg.containerMode = true;
0310     geoIdCfg.containerId =
0311         Acts::getParamOr<int>(baseName + "_geo_id_base", dd4hepElement, 1);
0312     geoIdGenerator =
0313         std::make_shared<Acts::Experimental::GeometryIdGenerator>(geoIdCfg);
0314   }
0315 
0316   return {internalsBuilder, rootsFinderBuilder, geoIdGenerator, aux, ext};
0317 }