Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:09:34

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2023 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 http://mozilla.org/MPL/2.0/.
0008 
0009 #include "Acts/Detector/CuboidalContainerBuilder.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/CuboidalDetectorHelper.hpp"
0015 #include "Acts/Detector/interface/IGeometryIdGenerator.hpp"
0016 #include "Acts/Detector/interface/IRootVolumeFinderBuilder.hpp"
0017 #include "Acts/Navigation/DetectorVolumeFinders.hpp"
0018 
0019 #include <algorithm>
0020 #include <ostream>
0021 #include <stdexcept>
0022 #include <utility>
0023 
0024 namespace Acts::Experimental {
0025 class DetectorVolume;
0026 }  // namespace Acts::Experimental
0027 
0028 Acts::Experimental::CuboidalContainerBuilder::CuboidalContainerBuilder(
0029     const Acts::Experimental::CuboidalContainerBuilder::Config& cfg,
0030     std::unique_ptr<const Acts::Logger> logger)
0031     : IDetectorComponentBuilder(), m_cfg(cfg), m_logger(std::move(logger)) {
0032   // Check if builders are present
0033   if (m_cfg.builders.empty()) {
0034     throw std::invalid_argument(
0035         "CuboidalContainerBuilder: no sub builders provided.");
0036   }
0037   // Check if binning value is correctly chosen
0038   if (m_cfg.binning != Acts::binX && m_cfg.binning != Acts::binY &&
0039       m_cfg.binning != Acts::binZ) {
0040     throw std::invalid_argument(
0041         "CuboidalContainerBuilder: Invalid binning value. Only Acts::binX, "
0042         "Acts::binY, Acts::binZ are supported.");
0043   }
0044 }
0045 
0046 Acts::Experimental::CuboidalContainerBuilder::CuboidalContainerBuilder(
0047     const Acts::Experimental::Blueprint::Node& bpNode,
0048     Acts::Logging::Level logLevel)
0049     : IDetectorComponentBuilder(),
0050       m_logger(getDefaultLogger(bpNode.name + "_cont", logLevel)) {
0051   if (bpNode.boundsType != VolumeBounds::BoundsType::eCuboid) {
0052     throw std::invalid_argument(
0053         "CuboidalContainerBuilder: boundary type must be cuboid - for "
0054         "building from a blueprint node.");
0055   }
0056 
0057   std::vector<std::shared_ptr<const IDetectorComponentBuilder>> builders;
0058   for (const auto& child : bpNode.children) {
0059     if (child->isLeaf()) {
0060       // Volume structure
0061       VolumeStructureBuilder::Config vsCfg;
0062       vsCfg.transform = child->transform;
0063       vsCfg.boundsType = child->boundsType;
0064       vsCfg.boundValues = child->boundaryValues;
0065       vsCfg.auxiliary = "*** acts auto-generated shape builder ***";
0066       auto vsBuilder = std::make_shared<VolumeStructureBuilder>(
0067           vsCfg, getDefaultLogger(child->name + "_shape", logLevel));
0068       // Detector volume builder
0069       DetectorVolumeBuilder::Config dvCfg;
0070       dvCfg.name = child->name;
0071       dvCfg.externalsBuilder = vsBuilder;
0072       dvCfg.internalsBuilder = child->internalsBuilder;
0073       dvCfg.auxiliary = "*** acts auto-generated volume builder ***";
0074       // Add the builder
0075       m_cfg.builders.push_back(std::make_shared<DetectorVolumeBuilder>(
0076           dvCfg, getDefaultLogger(child->name, logLevel)));
0077     } else {
0078       // This evokes the recursive stepping down the tree
0079       m_cfg.builders.push_back(
0080           std::make_shared<CuboidalContainerBuilder>(*child, logLevel));
0081     }
0082   }
0083   // Check if builders are present
0084   if (m_cfg.builders.empty()) {
0085     throw std::invalid_argument(
0086         "CuboidalContainerBuilder: no sub builders provided.");
0087   }
0088   if (bpNode.binning.size() != 1) {
0089     throw std::invalid_argument(
0090         "CuboidalContainerBuilder: >1D binning is not supported for cuboid "
0091         "containers.");
0092   }
0093   m_cfg.binning = bpNode.binning.at(0);
0094   // Check if binning value is correctly chosen
0095   if (m_cfg.binning != Acts::binX && m_cfg.binning != Acts::binY &&
0096       m_cfg.binning != Acts::binZ) {
0097     throw std::invalid_argument(
0098         "CuboidalContainerBuilder: Invalid binning value. Only Acts::binX, "
0099         "Acts::binY, Acts::binZ are supported.");
0100   }
0101 
0102   m_cfg.auxiliary = "*** acts auto-generated from proxy ***";
0103   m_cfg.geoIdGenerator = bpNode.geoIdGenerator;
0104   m_cfg.rootVolumeFinderBuilder = bpNode.rootVolumeFinderBuilder;
0105 }
0106 
0107 Acts::Experimental::DetectorComponent
0108 Acts::Experimental::CuboidalContainerBuilder::construct(
0109     const GeometryContext& gctx) const {
0110   // Return container object
0111   DetectorComponent::PortalContainer rContainer;
0112   bool atNavigationLevel = true;
0113 
0114   // Create the indivudal components, collect for both outcomes
0115   std::vector<DetectorComponent> components;
0116   ACTS_DEBUG("Building container from " << m_cfg.builders.size()
0117                                         << " components.");
0118   // Check through the component volumes - if every builder only
0119   // built exactly one volume, you are at pure navigation level
0120   // Collect the volumes
0121   std::vector<std::shared_ptr<DetectorVolume>> volumes;
0122   std::vector<DetectorComponent::PortalContainer> containers;
0123   std::vector<std::shared_ptr<DetectorVolume>> rootVolumes;
0124   // Run through the builders
0125   std::for_each(
0126       m_cfg.builders.begin(), m_cfg.builders.end(), [&](const auto& builder) {
0127         auto [cVolumes, cContainer, cRoots] = builder->construct(gctx);
0128         atNavigationLevel = (atNavigationLevel && cVolumes.size() == 1u);
0129         ACTS_VERBOSE("Number of volumes: " << cVolumes.size());
0130         // Collect individual components, volumes, containers, roots
0131         volumes.insert(volumes.end(), cVolumes.begin(), cVolumes.end());
0132         containers.push_back(cContainer);
0133         rootVolumes.insert(rootVolumes.end(), cRoots.volumes.begin(),
0134                            cRoots.volumes.end());
0135       });
0136   // Navigation level detected, connect volumes (cleaner and faster than
0137   // connect containers)
0138   if (atNavigationLevel) {
0139     ACTS_VERBOSE(
0140         "Component volumes are at navigation level: connecting volumes.");
0141     // Connect volumes
0142     rContainer = Acts::Experimental::detail::CuboidalDetectorHelper::connect(
0143         gctx, volumes, m_cfg.binning, {}, logger().level());
0144 
0145   } else {
0146     ACTS_VERBOSE("Components contain sub containers: connect containers.");
0147     // Connect containers
0148     rContainer = Acts::Experimental::detail::CuboidalDetectorHelper::connect(
0149         gctx, containers, m_cfg.binning, {}, logger().level());
0150   }
0151   ACTS_VERBOSE("Number of root volumes: " << rootVolumes.size());
0152 
0153   // Geometry Id generation
0154   if (m_cfg.geoIdGenerator != nullptr) {
0155     ACTS_DEBUG("Assigning geometry ids to the detector");
0156     auto cache = m_cfg.geoIdGenerator->generateCache();
0157     if (m_cfg.geoIdReverseGen) {
0158       std::for_each(rootVolumes.rbegin(), rootVolumes.rend(), [&](auto& v) {
0159         m_cfg.geoIdGenerator->assignGeometryId(cache, *v);
0160         ACTS_VERBOSE("-> Assigning geometry id to volume " << v->name());
0161       });
0162     } else {
0163       std::for_each(rootVolumes.begin(), rootVolumes.end(), [&](auto& v) {
0164         m_cfg.geoIdGenerator->assignGeometryId(cache, *v);
0165         ACTS_VERBOSE("-> Assigning geometry id to volume " << v->name());
0166       });
0167     }
0168   }
0169 
0170   // Check if a root volume finder is provided
0171   if (m_cfg.rootVolumeFinderBuilder) {
0172     // Return the container
0173     return Acts::Experimental::DetectorComponent{
0174         volumes, rContainer,
0175         RootDetectorVolumes{
0176             rootVolumes,
0177             m_cfg.rootVolumeFinderBuilder->construct(gctx, rootVolumes)}};
0178   }
0179 
0180   // Return the container
0181   return Acts::Experimental::DetectorComponent{
0182       volumes, rContainer, RootDetectorVolumes{rootVolumes, tryRootVolumes()}};
0183 }