Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:11:18

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