Back to home page

sPhenix code displayed by LXR

 
 

    


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

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/VolumeStructureBuilder.hpp"
0010 
0011 #include "Acts/Detector/PortalGenerators.hpp"
0012 #include "Acts/Geometry/ConeVolumeBounds.hpp"
0013 #include "Acts/Geometry/CuboidVolumeBounds.hpp"
0014 #include "Acts/Geometry/CutoutCylinderVolumeBounds.hpp"
0015 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0016 #include "Acts/Geometry/GenericCuboidVolumeBounds.hpp"
0017 #include "Acts/Geometry/TrapezoidVolumeBounds.hpp"
0018 #include "Acts/Utilities/Enumerate.hpp"
0019 #include "Acts/Utilities/Helpers.hpp"
0020 #include "Acts/Utilities/StringHelpers.hpp"
0021 
0022 Acts::Experimental::VolumeStructureBuilder::VolumeStructureBuilder(
0023     const Acts::Experimental::VolumeStructureBuilder::Config& cfg,
0024     std::unique_ptr<const Acts::Logger> mlogger)
0025     : IExternalStructureBuilder(), m_cfg(cfg), m_logger(std::move(mlogger)) {
0026   // Sanity cross-checks
0027   if (m_cfg.boundValues.empty() && !m_cfg.extent.has_value()) {
0028     throw std::invalid_argument(
0029         "VolumeStructureBuilder: no extent nor boundary values given");
0030   }
0031   // Check for the bounds type
0032   if (m_cfg.boundsType == VolumeBounds::BoundsType::eOther) {
0033     throw std::invalid_argument(
0034         "VolumeStructureBuilder: no known volume bounds type provided.");
0035   }
0036 }
0037 
0038 Acts::Experimental::ExternalStructure
0039 Acts::Experimental::VolumeStructureBuilder::construct(
0040     [[maybe_unused]] const Acts::GeometryContext& gctx) const {
0041   // Print out the auxiliary information
0042   if (!m_cfg.auxiliary.empty()) {
0043     ACTS_DEBUG(m_cfg.auxiliary);
0044   }
0045 
0046   // The volume bounds to be constructed
0047   std::unique_ptr<VolumeBounds> volumeBounds = nullptr;
0048 
0049   // The transform from the extent
0050   auto eTransform = Transform3::Identity();
0051   std::vector<ActsScalar> boundValues = m_cfg.boundValues;
0052 
0053   // This code dispatches into the dedicated volume types
0054   switch (m_cfg.boundsType) {
0055     case VolumeBounds::BoundsType::eCone: {
0056       ACTS_VERBOSE("Building conical volume bounds.");
0057       // Cone translation - only pre-defined values
0058       if (boundValues.size() < 5u) {
0059         throw std::runtime_error(
0060             "VolumeStructureBuilder: parameters for cone volume bounds need to "
0061             "be fully provided, they can not be estimated from an Extent "
0062             "object. It needs at least 5 parameters, while " +
0063             std::to_string(boundValues.size()) + " where given");
0064       }
0065       auto bArray = to_array<ConeVolumeBounds::BoundValues::eSize, ActsScalar>(
0066           boundValues);
0067       volumeBounds = std::make_unique<ConeVolumeBounds>(bArray);
0068     } break;
0069     case VolumeBounds::BoundsType::eCuboid: {
0070       ACTS_VERBOSE("Building cuboid volume bounds.");
0071       // Cuboid translation - either parameters / or extent
0072       if (boundValues.empty() && m_cfg.extent.has_value()) {
0073         ACTS_VERBOSE("Cuboid: estimate parameters from Extent.");
0074         const auto& vExtent = m_cfg.extent.value();
0075         if (vExtent.constrains(binX) && vExtent.constrains(binY) &&
0076             vExtent.constrains(binZ)) {
0077           eTransform.pretranslate(Vector3(vExtent.medium(binX),
0078                                           vExtent.medium(binY),
0079                                           vExtent.medium(binZ)));
0080           boundValues = {0.5 * vExtent.interval(binX),
0081                          0.5 * vExtent.interval(binY),
0082                          0.5 * vExtent.interval(binZ)};
0083 
0084         } else {
0085           throw std::runtime_error(
0086               "VolumeStructureBuilder: translation to cuboid does not work as "
0087               "the extent does not constrain all necessary value.");
0088         }
0089       } else if (boundValues.size() < 3u) {
0090         throw std::runtime_error(
0091             "VolumeStructureBuilder: parameters for cuboid volume bounds need "
0092             "to be fully provided, it needs exactly 3 parameters, while " +
0093             std::to_string(boundValues.size()) + " where given");
0094       }
0095       auto bArray =
0096           to_array<CuboidVolumeBounds::BoundValues::eSize>(boundValues);
0097       volumeBounds = std::make_unique<CuboidVolumeBounds>(bArray);
0098     } break;
0099     case VolumeBounds::BoundsType::eCutoutCylinder: {
0100       ACTS_VERBOSE("Building cutout cylindrical volume bounds.");
0101       // Cutout cylinder translation - only parameters
0102       if (boundValues.size() < 5u) {
0103         throw std::runtime_error(
0104             "VolumeStructureBuilder: parameters for cutout cylinder volume "
0105             "bounds need to be fully provided, they can not be estimated from "
0106             "an Extent object. It needs exactly 3 parameters, while " +
0107             std::to_string(boundValues.size()) + " where given");
0108       }
0109       auto bArray =
0110           to_array<CutoutCylinderVolumeBounds::BoundValues::eSize>(boundValues);
0111       volumeBounds = std::make_unique<CutoutCylinderVolumeBounds>(bArray);
0112     } break;
0113     case VolumeBounds::BoundsType::eCylinder: {
0114       ACTS_VERBOSE("Building cylindrical volume bounds.");
0115       // Cylinder translation - either parameters / or extent
0116       if (boundValues.empty() && m_cfg.extent.has_value()) {
0117         ACTS_VERBOSE("Cylinder: estimate parameters from Extent.");
0118         const auto& vExtent = m_cfg.extent.value();
0119         if (vExtent.constrains(binR) && vExtent.constrains(binZ)) {
0120           eTransform.pretranslate(Vector3(0., 0., vExtent.medium(binZ)));
0121           boundValues = {vExtent.min(binR), vExtent.max(binR),
0122                          0.5 * vExtent.interval(binZ)};
0123           if (vExtent.constrains(binPhi)) {
0124             boundValues.push_back(0.5 * vExtent.interval(binPhi));
0125             boundValues.push_back(vExtent.medium(binPhi));
0126           }
0127         } else {
0128           throw std::runtime_error(
0129               "VolumeStructureBuilder: translation to cuboid does not work as "
0130               "the extent does not constrain all necessary values.");
0131         }
0132       } else if (boundValues.size() < 3u) {
0133         throw std::runtime_error(
0134             "VolumeStructureBuilder: parameters for cylinder volume "
0135             "bounds need to be fully provided, it needs at least 3 parameters, "
0136             "while " +
0137             std::to_string(boundValues.size()) + " where given");
0138       }
0139       // Check if phi has been constraint, otherwise fill it with full coverage
0140       if (boundValues.size() == 3u) {
0141         boundValues.push_back(M_PI);
0142         boundValues.push_back(0.);
0143       }
0144       ACTS_VERBOSE(" - cylindrical shape with [iR, oR, hZ, sPhi, mPhi] = "
0145                    << boundValues[0] << ", " << boundValues[1] << ", "
0146                    << boundValues[2] << ", " << boundValues[3] << ", "
0147                    << boundValues[4]);
0148       auto bArray =
0149           to_array<CylinderVolumeBounds::BoundValues::eSize>(boundValues);
0150       volumeBounds = std::make_unique<CylinderVolumeBounds>(bArray);
0151     } break;
0152     case VolumeBounds::BoundsType::eGenericCuboid: {
0153       ACTS_VERBOSE("Building generic cuboid volume bounds.");
0154       // Generic cuboid translation - parameters only
0155       if (boundValues.size() < GenericCuboidVolumeBounds::BoundValues::eSize) {
0156         throw std::runtime_error(
0157             "VolumeStructureBuilder: parameters for generic cuboid volume "
0158             "bounds need to be provided, they can not be estimated from an "
0159             "Extent object. It needs exactly 24 parameters, while " +
0160             std::to_string(boundValues.size()) + " where given");
0161       }
0162       auto bArray =
0163           to_array<GenericCuboidVolumeBounds::BoundValues::eSize>(boundValues);
0164       volumeBounds = std::make_unique<GenericCuboidVolumeBounds>(bArray);
0165     } break;
0166     case VolumeBounds::BoundsType::eTrapezoid: {
0167       ACTS_VERBOSE("Building trapezoid volume bounds.");
0168       // Trapezoid translation - parameters only
0169       if (boundValues.size() < 4u) {
0170         throw std::runtime_error(
0171             "VolumeStructureBuilder: parameters for trapezoid volume bounds "
0172             "need to be provided, they can not be estimated from an Extent "
0173             "object. It needs at least 4 parameters, while " +
0174             std::to_string(boundValues.size()) + " where given");
0175       }
0176       auto bArray =
0177           to_array<TrapezoidVolumeBounds::BoundValues::eSize>(boundValues);
0178       volumeBounds = std::make_unique<TrapezoidVolumeBounds>(bArray);
0179     } break;
0180     default:
0181       break;
0182   }
0183 
0184   Transform3 fTransform = m_cfg.transform * eTransform;
0185   ACTS_VERBOSE(" - translation: " << Acts::toString(fTransform.translation()));
0186   if (!fTransform.rotation().isApprox(
0187           Acts::Transform3::Identity().rotation())) {
0188     ACTS_VERBOSE(" - rotation: " << Acts::toString(fTransform.rotation()));
0189   }
0190   // Return the transform, the volume bounds, and some default portal
0191   // generators
0192   return {fTransform, std::move(volumeBounds), defaultPortalGenerator()};
0193 }