Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-05 08:10:21

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2017-2018 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/Plugins/TGeo/TGeoLayerBuilder.hpp"
0010 
0011 #include "Acts/Geometry/Extent.hpp"
0012 #include "Acts/Geometry/LayerCreator.hpp"
0013 #include "Acts/Geometry/ProtoLayer.hpp"
0014 #include "Acts/Geometry/ProtoLayerHelper.hpp"
0015 #include "Acts/Plugins/TGeo/ITGeoDetectorElementSplitter.hpp"
0016 #include "Acts/Plugins/TGeo/ITGeoIdentifierProvider.hpp"
0017 #include "Acts/Plugins/TGeo/TGeoDetectorElement.hpp"
0018 #include "Acts/Plugins/TGeo/TGeoParser.hpp"
0019 #include "Acts/Plugins/TGeo/TGeoPrimitivesHelper.hpp"
0020 #include "Acts/Utilities/Helpers.hpp"
0021 
0022 #include <ostream>
0023 #include <stdexcept>
0024 
0025 #include "TGeoManager.h"
0026 #include "TGeoMatrix.h"
0027 
0028 namespace Acts {
0029 class ISurfaceMaterial;
0030 }  // namespace Acts
0031 
0032 Acts::TGeoLayerBuilder::TGeoLayerBuilder(
0033     const Acts::TGeoLayerBuilder::Config& config,
0034     std::unique_ptr<const Logger> logger)
0035     : m_cfg(), m_logger(std::move(logger)) {
0036   setConfiguration(config);
0037 }
0038 
0039 Acts::TGeoLayerBuilder::~TGeoLayerBuilder() = default;
0040 
0041 void Acts::TGeoLayerBuilder::setConfiguration(
0042     const Acts::TGeoLayerBuilder::Config& config) {
0043   m_cfg = config;
0044 }
0045 
0046 void Acts::TGeoLayerBuilder::setLogger(
0047     std::unique_ptr<const Logger> newLogger) {
0048   m_logger = std::move(newLogger);
0049 }
0050 
0051 const Acts::LayerVector Acts::TGeoLayerBuilder::negativeLayers(
0052     const GeometryContext& gctx) const {
0053   // @todo Remove this hack once the m_elementStore mess is sorted out
0054   auto mutableThis = const_cast<TGeoLayerBuilder*>(this);
0055   LayerVector nVector;
0056   mutableThis->buildLayers(gctx, nVector, -1);
0057   return nVector;
0058 }
0059 
0060 const Acts::LayerVector Acts::TGeoLayerBuilder::centralLayers(
0061     const GeometryContext& gctx) const {
0062   // @todo Remove this hack once the m_elementStore mess is sorted out
0063   auto mutableThis = const_cast<TGeoLayerBuilder*>(this);
0064   LayerVector cVector;
0065   mutableThis->buildLayers(gctx, cVector, 0);
0066   return cVector;
0067 }
0068 
0069 const Acts::LayerVector Acts::TGeoLayerBuilder::positiveLayers(
0070     const GeometryContext& gctx) const {
0071   // @todo Remove this hack once the m_elementStore mess is sorted out
0072   auto mutableThis = const_cast<TGeoLayerBuilder*>(this);
0073   LayerVector pVector;
0074   mutableThis->buildLayers(gctx, pVector, 1);
0075   return pVector;
0076 }
0077 
0078 void Acts::TGeoLayerBuilder::buildLayers(const GeometryContext& gctx,
0079                                          LayerVector& layers, int type) {
0080   // Bail out if you have no gGeoManager
0081   if (gGeoManager == nullptr) {
0082     ACTS_WARNING("No gGeoManager found - bailing out.");
0083     return;
0084   }
0085 
0086   using LayerSurfaceVector = std::vector<std::shared_ptr<const Surface>>;
0087   LayerSurfaceVector layerSurfaces;
0088 
0089   std::vector<LayerConfig> layerConfigs = m_cfg.layerConfigurations[type + 1];
0090   std::string layerType = m_layerTypes[type + 1];
0091 
0092   // Appropriate screen output
0093   std::string addonOutput = m_cfg.layerSplitToleranceR[type + 1] > 0.
0094                                 ? std::string(", splitting in r")
0095                                 : std::string("");
0096   addonOutput += m_cfg.layerSplitToleranceZ[type + 1] > 0.
0097                      ? std::string(", splitting in z")
0098                      : std::string("");
0099   addonOutput += std::string(".");
0100 
0101   // Screen output of the configuration
0102   ACTS_DEBUG(layerType << " layers : found " << layerConfigs.size()
0103                        << " configuration(s)" + addonOutput);
0104 
0105   // Helper function to fill the layer
0106   auto fillLayer = [&](const LayerSurfaceVector& lSurfaces,
0107                        const LayerConfig& lCfg,
0108                        unsigned int pl_id = 0) -> void {
0109     int nb0 = 0, nt0 = 0;
0110     bool is_autobinning = ((lCfg.binning0.size() == 1) &&
0111                            (std::get<int>(lCfg.binning0.at(0)) <= 0));
0112     if (!is_autobinning && std::get<int>(lCfg.binning0.at(pl_id)) <= 0) {
0113       throw std::invalid_argument(
0114           "Incorrect binning configuration found for loc0 protolayer #" +
0115           std::to_string(pl_id) +
0116           ". Layer is autobinned: No mixed binning (manual and auto) for loc0 "
0117           "possible between layers in a single subvolume. Quitting");
0118     }
0119     if (is_autobinning) {
0120       // Set binning by hand if nb0 > 0 and nb1 > 0
0121       nb0 = std::get<int>(lCfg.binning0.at(0));
0122       // Read the binning type
0123       nt0 = std::get<BinningType>(lCfg.binning0.at(0));
0124     } else if (pl_id < lCfg.binning0.size()) {
0125       // Set binning by hand if nb0 > 0 and nb1 > 0
0126       nb0 = std::get<int>(lCfg.binning0.at(pl_id));
0127     }
0128 
0129     int nb1 = 0, nt1 = 0;
0130     is_autobinning = (lCfg.binning1.size() == 1) &&
0131                      (std::get<int>(lCfg.binning1.at(0)) <= 0);
0132     if (!is_autobinning && std::get<int>(lCfg.binning1.at(pl_id)) <= 0) {
0133       throw std::invalid_argument(
0134           "Incorrect binning configuration found for loc1 protolayer #" +
0135           std::to_string(pl_id) +
0136           ". Layer is autobinned: No mixed binning (manual and auto) for loc1 "
0137           "possible between layers in a single subvolume. Quitting");
0138     }
0139     if (is_autobinning) {
0140       // Set binning by hand if nb0 > 0 and nb1 > 0
0141       nb1 = std::get<int>(lCfg.binning1.at(0));
0142       // For a binning type
0143       nt1 = std::get<BinningType>(lCfg.binning1.at(0));
0144     } else if (pl_id < lCfg.binning1.size()) {
0145       // Set binning by hand if nb0 > 0 and nb1 > 0
0146       nb1 = std::get<int>(lCfg.binning1.at(pl_id));
0147     }
0148 
0149     if (type == 0) {
0150       ProtoLayer pl(gctx, lSurfaces);
0151       ACTS_DEBUG("- creating CylinderLayer with "
0152                  << lSurfaces.size() << " surfaces at r = " << pl.medium(binR));
0153 
0154       pl.envelope[Acts::binR] = {lCfg.envelope.first, lCfg.envelope.second};
0155       pl.envelope[Acts::binZ] = {lCfg.envelope.second, lCfg.envelope.second};
0156       if (nb0 >= 0 && nb1 >= 0) {
0157         layers.push_back(
0158             m_cfg.layerCreator->cylinderLayer(gctx, lSurfaces, nb0, nb1, pl));
0159       } else {
0160         layers.push_back(
0161             m_cfg.layerCreator->cylinderLayer(gctx, lSurfaces, nt0, nt1, pl));
0162       }
0163     } else {
0164       ProtoLayer pl(gctx, lSurfaces);
0165       ACTS_DEBUG("- creating DiscLayer with "
0166                  << lSurfaces.size() << " surfaces at z = " << pl.medium(binZ));
0167 
0168       pl.envelope[Acts::binR] = {lCfg.envelope.first, lCfg.envelope.second};
0169       pl.envelope[Acts::binZ] = {lCfg.envelope.second, lCfg.envelope.second};
0170       if (nb0 >= 0 && nb1 >= 0) {
0171         layers.push_back(
0172             m_cfg.layerCreator->discLayer(gctx, lSurfaces, nb0, nb1, pl));
0173       } else {
0174         layers.push_back(
0175             m_cfg.layerCreator->discLayer(gctx, lSurfaces, nt0, nt1, pl));
0176       }
0177     }
0178   };
0179 
0180   for (auto layerCfg : layerConfigs) {
0181     ACTS_DEBUG("- layer configuration found for layer " << layerCfg.volumeName
0182                                                         << " with sensors ");
0183     for (auto& sensor : layerCfg.sensorNames) {
0184       ACTS_DEBUG("  - sensor: " << sensor);
0185     }
0186     if (!layerCfg.parseRanges.empty()) {
0187       for (const auto& pRange : layerCfg.parseRanges) {
0188         ACTS_DEBUG("- layer parsing restricted in "
0189                    << binningValueNames()[pRange.first] << " to ["
0190                    << pRange.second.first << "/" << pRange.second.second
0191                    << "].");
0192       }
0193     }
0194     if (!layerCfg.splitConfigs.empty()) {
0195       for (const auto& sConfig : layerCfg.splitConfigs) {
0196         ACTS_DEBUG("- layer splitting attempt in "
0197                    << binningValueNames()[sConfig.first] << " with tolerance "
0198                    << sConfig.second << ".");
0199       }
0200     }
0201 
0202     // Either pick the configured volume or take the top level volume
0203     TGeoVolume* tVolume =
0204         gGeoManager->FindVolumeFast(layerCfg.volumeName.c_str());
0205     if (tVolume == nullptr) {
0206       tVolume = gGeoManager->GetTopVolume();
0207       ACTS_DEBUG("- search volume is TGeo top volume");
0208     } else {
0209       ACTS_DEBUG("- setting search volume to " << tVolume->GetName());
0210     }
0211 
0212     if (tVolume != nullptr) {
0213       TGeoParser::Options tgpOptions;
0214       tgpOptions.volumeNames = {layerCfg.volumeName};
0215       tgpOptions.targetNames = layerCfg.sensorNames;
0216       tgpOptions.parseRanges = layerCfg.parseRanges;
0217       tgpOptions.unit = m_cfg.unit;
0218       TGeoParser::State tgpState;
0219       tgpState.volume = tVolume;
0220 
0221       ACTS_DEBUG("- applying  " << layerCfg.parseRanges.size()
0222                                 << " search restrictions.");
0223       for (const auto& prange : layerCfg.parseRanges) {
0224         ACTS_VERBOSE(" - range " << binningValueNames()[prange.first]
0225                                  << " within [ " << prange.second.first << ", "
0226                                  << prange.second.second << "]");
0227       }
0228 
0229       TGeoParser::select(tgpState, tgpOptions);
0230 
0231       ACTS_DEBUG("- number of selected nodes found : "
0232                  << tgpState.selectedNodes.size());
0233 
0234       for (auto& snode : tgpState.selectedNodes) {
0235         auto identifier =
0236             m_cfg.identifierProvider != nullptr
0237                 ? m_cfg.identifierProvider->identify(gctx, *snode.node)
0238                 : Identifier();
0239 
0240         auto tgElement =
0241             m_cfg.elementFactory(identifier, *snode.node, *snode.transform,
0242                                  layerCfg.localAxes, m_cfg.unit, nullptr);
0243 
0244         std::vector<std::shared_ptr<const Acts::TGeoDetectorElement>>
0245             tgElements =
0246                 (m_cfg.detectorElementSplitter == nullptr)
0247                     ? std::vector<std::shared_ptr<
0248                           const Acts::TGeoDetectorElement>>{tgElement}
0249                     : m_cfg.detectorElementSplitter->split(gctx, tgElement);
0250 
0251         for (const auto& tge : tgElements) {
0252           m_elementStore.push_back(tge);
0253           layerSurfaces.push_back(tge->surface().getSharedPtr());
0254         }
0255       }
0256 
0257       ACTS_DEBUG("- created TGeoDetectorElements : " << layerSurfaces.size());
0258 
0259       if (m_cfg.protoLayerHelper != nullptr && !layerCfg.splitConfigs.empty()) {
0260         auto protoLayers = m_cfg.protoLayerHelper->protoLayers(
0261             gctx, unpack_shared_vector(layerSurfaces), layerCfg.splitConfigs);
0262         ACTS_DEBUG("- splitting into " << protoLayers.size() << " layers.");
0263 
0264         // Number of options mismatch and has not been configured for
0265         // auto-binning
0266         const bool is_loc0_n_config =
0267             layerCfg.binning0.size() == protoLayers.size();
0268         const bool is_loc0_autobinning =
0269             (layerCfg.binning0.size() == 1) &&
0270             (std::get<int>(layerCfg.binning0.at(0)) <= 0);
0271         const bool is_loc1_n_config =
0272             layerCfg.binning1.size() == protoLayers.size();
0273         const bool is_loc1_autobinning =
0274             (layerCfg.binning1.size() == 1) &&
0275             (std::get<int>(layerCfg.binning1.at(0)) <= 0);
0276         if ((!is_loc0_n_config && !is_loc0_autobinning) ||
0277             (!is_loc1_n_config && !is_loc1_autobinning)) {
0278           throw std::invalid_argument(
0279               "Incorrect binning configuration found: Number of configurations "
0280               "does not match number of protolayers in subvolume " +
0281               layerCfg.volumeName + ". Quitting.");
0282         }
0283         unsigned int layer_id = 0;
0284         for (auto& pLayer : protoLayers) {
0285           layerSurfaces.clear();
0286 
0287           for (const auto& lsurface : pLayer.surfaces()) {
0288             layerSurfaces.push_back(lsurface->getSharedPtr());
0289           }
0290           fillLayer(layerSurfaces, layerCfg, layer_id);
0291           layer_id++;
0292         }
0293       } else {
0294         fillLayer(layerSurfaces, layerCfg);
0295       }
0296     }
0297   }
0298   return;
0299 }
0300 
0301 std::shared_ptr<Acts::TGeoDetectorElement>
0302 Acts::TGeoLayerBuilder::defaultElementFactory(
0303     const Identifier& identifier, const TGeoNode& tGeoNode,
0304     const TGeoMatrix& tGeoMatrix, const std::string& axes, double scalor,
0305     std::shared_ptr<const Acts::ISurfaceMaterial> material) {
0306   return std::make_shared<TGeoDetectorElement>(
0307       identifier, tGeoNode, tGeoMatrix, axes, scalor, std::move(material));
0308 }