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