File indexing completed on 2025-01-18 09:11:18
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Detector/CylindricalContainerBuilder.hpp"
0010
0011 #include "Acts/Detector/DetectorComponents.hpp"
0012 #include "Acts/Detector/DetectorVolumeBuilder.hpp"
0013 #include "Acts/Detector/VolumeStructureBuilder.hpp"
0014 #include "Acts/Detector/detail/CylindricalDetectorHelper.hpp"
0015 #include "Acts/Detector/detail/ProtoMaterialHelper.hpp"
0016 #include "Acts/Detector/interface/IGeometryIdGenerator.hpp"
0017 #include "Acts/Detector/interface/IRootVolumeFinderBuilder.hpp"
0018 #include "Acts/Material/ProtoSurfaceMaterial.hpp"
0019 #include "Acts/Navigation/DetectorVolumeFinders.hpp"
0020
0021 #include <algorithm>
0022 #include <ostream>
0023 #include <stdexcept>
0024 #include <utility>
0025
0026 namespace Acts::Experimental {
0027 class DetectorVolume;
0028 }
0029
0030 namespace {
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 template <typename object_collection>
0045 Acts::Experimental::DetectorComponent::PortalContainer connect(
0046 const Acts::GeometryContext& gctx, object_collection& objects,
0047 const std::vector<Acts::AxisDirection>& binning,
0048 Acts::Logging::Level logLevel) {
0049
0050 Acts::Experimental::DetectorComponent::PortalContainer portalContainer;
0051 if (binning.size() == 1u) {
0052 Acts::AxisDirection bv = binning.front();
0053
0054 switch (bv) {
0055 case Acts::AxisDirection::AxisR: {
0056 portalContainer =
0057 Acts::Experimental::detail::CylindricalDetectorHelper::connectInR(
0058 gctx, objects, {}, logLevel);
0059 } break;
0060 case Acts::AxisDirection::AxisZ: {
0061 portalContainer =
0062 Acts::Experimental::detail::CylindricalDetectorHelper::connectInZ(
0063 gctx, objects, {}, logLevel);
0064 } break;
0065 case Acts::AxisDirection::AxisPhi: {
0066 portalContainer =
0067 Acts::Experimental::detail::CylindricalDetectorHelper::connectInPhi(
0068 gctx, objects, {}, logLevel);
0069 } break;
0070 default:
0071 break;
0072 }
0073 } else if (binning ==
0074 std::vector<Acts::AxisDirection>{Acts::AxisDirection::AxisZ,
0075 Acts::AxisDirection::AxisR} &&
0076 objects.size() == 2u) {
0077 portalContainer =
0078 Acts::Experimental::detail::CylindricalDetectorHelper::wrapInZR(
0079 gctx, objects, logLevel);
0080 }
0081 return portalContainer;
0082 }
0083 }
0084
0085 Acts::Experimental::CylindricalContainerBuilder::CylindricalContainerBuilder(
0086 const Acts::Experimental::CylindricalContainerBuilder::Config& cfg,
0087 std::unique_ptr<const Acts::Logger> logger)
0088 : IDetectorComponentBuilder(), m_cfg(cfg), m_logger(std::move(logger)) {
0089
0090 if (m_cfg.builders.empty()) {
0091 throw std::invalid_argument(
0092 "CylindricalContainerBuilder: no sub builders provided.");
0093 }
0094
0095 if (m_cfg.binning.size() == 1u) {
0096
0097 auto b = m_cfg.binning.front();
0098 if (b != Acts::AxisDirection::AxisR && b != Acts::AxisDirection::AxisZ &&
0099 b != Acts::AxisDirection::AxisPhi) {
0100 throw std::invalid_argument(
0101 "CylindricalContainerBuilder: 1D binning only supported in z, r, or "
0102 "phi");
0103 }
0104 } else if (m_cfg.binning.size() == 2u) {
0105
0106 if (m_cfg.binning !=
0107 std::vector<Acts::AxisDirection>{Acts::AxisDirection::AxisZ,
0108 Acts::AxisDirection::AxisR}) {
0109 throw std::invalid_argument(
0110 "CylindricalContainerBuilder: 2D binning only supports wrapping in "
0111 "z-r.");
0112 } else if (m_cfg.builders.size() != 2u) {
0113
0114
0115 throw std::invalid_argument(
0116 "CylindricalContainerBuilder: 2D wrapping in z-r requires exactly "
0117 "two builders.");
0118 }
0119 }
0120 }
0121
0122 Acts::Experimental::CylindricalContainerBuilder::CylindricalContainerBuilder(
0123 const Acts::Experimental::Blueprint::Node& bpNode,
0124 Acts::Logging::Level logLevel)
0125 : IDetectorComponentBuilder(),
0126 m_logger(getDefaultLogger(bpNode.name + "_cont", logLevel)) {
0127 if (bpNode.boundsType != VolumeBounds::BoundsType::eCylinder) {
0128 throw std::invalid_argument(
0129 "CylindricalContainerBuilder: boundary type must be cylinder - for "
0130 "building from a blueprint node.");
0131 }
0132
0133 std::vector<std::shared_ptr<const IDetectorComponentBuilder>> builders;
0134 for (const auto& child : bpNode.children) {
0135 if (child->isLeaf()) {
0136
0137 VolumeStructureBuilder::Config vsCfg;
0138 vsCfg.transform = child->transform;
0139 vsCfg.boundsType = child->boundsType;
0140 vsCfg.boundValues = child->boundaryValues;
0141 vsCfg.auxiliary = "*** acts auto-generated shape builder ***";
0142 auto vsBuilder = std::make_shared<VolumeStructureBuilder>(
0143 vsCfg, getDefaultLogger(child->name + "_shape", logLevel));
0144
0145 DetectorVolumeBuilder::Config dvCfg;
0146 dvCfg.name = child->name;
0147 dvCfg.externalsBuilder = vsBuilder;
0148 dvCfg.internalsBuilder = child->internalsBuilder;
0149 dvCfg.geoIdGenerator = child->geoIdGenerator;
0150 dvCfg.portalMaterialBinning = child->portalMaterialBinning;
0151 dvCfg.auxiliary = "*** acts auto-generated volume builder ***";
0152
0153 m_cfg.builders.push_back(std::make_shared<DetectorVolumeBuilder>(
0154 dvCfg, getDefaultLogger(child->name, logLevel)));
0155 } else {
0156
0157 m_cfg.builders.push_back(
0158 std::make_shared<CylindricalContainerBuilder>(*child, logLevel));
0159 }
0160 }
0161
0162 if (m_cfg.builders.empty()) {
0163 throw std::invalid_argument(
0164 "CylindricalContainerBuilder: no sub builders provided.");
0165 }
0166 m_cfg.binning = bpNode.binning;
0167
0168 if (m_cfg.binning.size() == 1u) {
0169
0170 auto b = m_cfg.binning.front();
0171 if (b != Acts::AxisDirection::AxisR && b != Acts::AxisDirection::AxisZ &&
0172 b != Acts::AxisDirection::AxisPhi) {
0173 throw std::invalid_argument(
0174 "CylindricalContainerBuilder: 1D binning only supported in z, r, or "
0175 "phi");
0176 }
0177 } else if (m_cfg.binning.size() == 2u) {
0178
0179 if (m_cfg.binning !=
0180 std::vector<Acts::AxisDirection>{Acts::AxisDirection::AxisZ,
0181 Acts::AxisDirection::AxisR}) {
0182 throw std::invalid_argument(
0183 "CylindricalContainerBuilder: 2D binning only supports wrapping in "
0184 "z-r.");
0185 } else if (m_cfg.builders.size() != 2u) {
0186
0187
0188 throw std::invalid_argument(
0189 "CylindricalContainerBuilder: 2D wrapping in z-r requires exactly "
0190 "two builders.");
0191 }
0192 }
0193
0194 m_cfg.auxiliary = "*** acts auto-generated from proxy ***";
0195 m_cfg.geoIdGenerator = bpNode.geoIdGenerator;
0196 m_cfg.rootVolumeFinderBuilder = bpNode.rootVolumeFinderBuilder;
0197 m_cfg.portalMaterialBinning = bpNode.portalMaterialBinning;
0198 }
0199
0200 Acts::Experimental::DetectorComponent
0201 Acts::Experimental::CylindricalContainerBuilder::construct(
0202 const GeometryContext& gctx) const {
0203
0204 DetectorComponent::PortalContainer portalContainer;
0205 bool atNavigationLevel = true;
0206
0207
0208 std::vector<DetectorComponent> components;
0209 ACTS_DEBUG("Building container from " << m_cfg.builders.size()
0210 << " components.");
0211
0212
0213
0214 std::vector<std::shared_ptr<DetectorVolume>> volumes;
0215 std::vector<DetectorComponent::PortalContainer> containers;
0216 std::vector<std::shared_ptr<DetectorVolume>> rootVolumes;
0217
0218 std::for_each(
0219 m_cfg.builders.begin(), m_cfg.builders.end(), [&](const auto& builder) {
0220 auto [cVolumes, cContainer, cRoots] = builder->construct(gctx);
0221 atNavigationLevel = (atNavigationLevel && cVolumes.size() == 1u);
0222
0223 volumes.insert(volumes.end(), cVolumes.begin(), cVolumes.end());
0224 containers.push_back(cContainer);
0225 rootVolumes.insert(rootVolumes.end(), cRoots.volumes.begin(),
0226 cRoots.volumes.end());
0227 });
0228
0229
0230 if (atNavigationLevel) {
0231 ACTS_VERBOSE(
0232 "Component volumes are at navigation level: connecting volumes.");
0233
0234 portalContainer = connect(gctx, volumes, m_cfg.binning, logger().level());
0235 } else {
0236 ACTS_VERBOSE("Components contain sub containers: connect containers.");
0237
0238 portalContainer =
0239 connect(gctx, containers, m_cfg.binning, logger().level());
0240 }
0241 ACTS_VERBOSE("Number of root volumes: " << rootVolumes.size());
0242
0243
0244 if (m_cfg.geoIdGenerator != nullptr) {
0245 ACTS_DEBUG("Assigning geometry ids to the detector");
0246 auto cache = m_cfg.geoIdGenerator->generateCache();
0247 if (m_cfg.geoIdReverseGen) {
0248 std::for_each(rootVolumes.rbegin(), rootVolumes.rend(), [&](auto& v) {
0249 m_cfg.geoIdGenerator->assignGeometryId(cache, *v);
0250 ACTS_VERBOSE("-> Assigning geometry id to volume " << v->name());
0251 });
0252 } else {
0253 std::for_each(rootVolumes.begin(), rootVolumes.end(), [&](auto& v) {
0254 m_cfg.geoIdGenerator->assignGeometryId(cache, *v);
0255 ACTS_VERBOSE("-> Assigning geometry id to volume " << v->name());
0256 });
0257 }
0258 }
0259
0260
0261
0262 for (const auto& [ip, bDescription] : m_cfg.portalMaterialBinning) {
0263 if (portalContainer.contains(ip)) {
0264 auto bd = detail::ProtoMaterialHelper::attachProtoMaterial(
0265 gctx, portalContainer[ip]->surface(), bDescription);
0266 ACTS_VERBOSE("-> Assigning proto material to portal " << ip << " with "
0267 << bd.toString());
0268 }
0269 }
0270
0271
0272 if (m_cfg.rootVolumeFinderBuilder) {
0273
0274 return Acts::Experimental::DetectorComponent{
0275 volumes, portalContainer,
0276 RootDetectorVolumes{
0277 rootVolumes,
0278 m_cfg.rootVolumeFinderBuilder->construct(gctx, rootVolumes)}};
0279 }
0280
0281
0282 return Acts::Experimental::DetectorComponent{
0283 volumes, portalContainer,
0284 RootDetectorVolumes{rootVolumes, tryRootVolumes()}};
0285 }