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