Back to home page

EIC code displayed by LXR

 
 

    


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

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 "ActsExamples/TGeoDetector/TGeoDetector.hpp"
0010 
0011 #include "Acts/Geometry/CylinderVolumeBuilder.hpp"
0012 #include "Acts/Geometry/CylinderVolumeHelper.hpp"
0013 #include "Acts/Geometry/DetectorElementBase.hpp"
0014 #include "Acts/Geometry/GeometryContext.hpp"
0015 #include "Acts/Geometry/ITrackingVolumeBuilder.hpp"
0016 #include "Acts/Geometry/LayerArrayCreator.hpp"
0017 #include "Acts/Geometry/LayerCreator.hpp"
0018 #include "Acts/Geometry/PassiveLayerBuilder.hpp"
0019 #include "Acts/Geometry/ProtoLayerHelper.hpp"
0020 #include "Acts/Geometry/SurfaceArrayCreator.hpp"
0021 #include "Acts/Geometry/SurfaceBinningMatcher.hpp"
0022 #include "Acts/Geometry/TrackingGeometry.hpp"
0023 #include "Acts/Geometry/TrackingGeometryBuilder.hpp"
0024 #include "Acts/Geometry/TrackingVolumeArrayCreator.hpp"
0025 #include "Acts/Plugins/TGeo/TGeoCylinderDiscSplitter.hpp"
0026 #include "Acts/Plugins/TGeo/TGeoLayerBuilder.hpp"
0027 #include "Acts/Utilities/Logger.hpp"
0028 #include "ActsExamples/TGeoDetector/JsonTGeoDetectorConfig.hpp"
0029 #include "ActsExamples/TGeoDetector/TGeoITkModuleSplitter.hpp"
0030 
0031 #include <algorithm>
0032 #include <array>
0033 #include <fstream>
0034 #include <limits>
0035 #include <list>
0036 #include <optional>
0037 #include <utility>
0038 
0039 #include <boost/program_options.hpp>
0040 #include <nlohmann/json.hpp>
0041 
0042 #include "TGeoManager.h"
0043 
0044 namespace ActsExamples {
0045 
0046 namespace {
0047 
0048 /// @brief Function that constructs a set of layer builder
0049 ///        configs from a central @c TGeoDetector config.
0050 ///
0051 /// @param config The input config
0052 /// @return Vector of layer builder configs
0053 std::vector<Acts::TGeoLayerBuilder::Config> makeLayerBuilderConfigs(
0054     const TGeoDetector::Config& config, const Acts::Logger& logger) {
0055   std::vector<Acts::TGeoLayerBuilder::Config> detLayerConfigs;
0056 
0057   // iterate over all configured detector volumes
0058   for (const auto& volume : config.volumes) {
0059     Acts::TGeoLayerBuilder::Config layerBuilderConfig;
0060     layerBuilderConfig.configurationName = volume.name;
0061     layerBuilderConfig.unit = config.unitScalor;
0062     layerBuilderConfig.elementFactory = config.elementFactory;
0063 
0064     // configure surface autobinning
0065     std::vector<std::pair<double, double>> binTolerances(
0066         Acts::numAxisDirections(), {0., 0.});
0067     binTolerances[toUnderlying(Acts::AxisDirection::AxisR)] = {
0068         volume.binToleranceR.lower.value_or(0.),
0069         volume.binToleranceR.upper.value_or(0.)};
0070     binTolerances[toUnderlying(Acts::AxisDirection::AxisZ)] = {
0071         volume.binToleranceZ.lower.value_or(0.),
0072         volume.binToleranceZ.upper.value_or(0.)};
0073     binTolerances[toUnderlying(Acts::AxisDirection::AxisPhi)] = {
0074         volume.binTolerancePhi.lower.value_or(0.),
0075         volume.binTolerancePhi.upper.value_or(0.)};
0076 
0077     layerBuilderConfig.autoSurfaceBinning = true;
0078     layerBuilderConfig.surfaceBinMatcher =
0079         Acts::SurfaceBinningMatcher(binTolerances);
0080 
0081     // loop over the negative/central/positive layer configurations
0082     for (auto ncp : {
0083              TGeoDetector::Config::Negative,
0084              TGeoDetector::Config::Central,
0085              TGeoDetector::Config::Positive,
0086          }) {
0087       if (!volume.layers.at(ncp)) {
0088         continue;
0089       }
0090 
0091       Acts::TGeoLayerBuilder::LayerConfig lConfig;
0092       lConfig.volumeName = volume.subVolumeName.at(ncp);
0093       lConfig.sensorNames = volume.sensitiveNames.at(ncp);
0094       lConfig.localAxes = volume.sensitiveAxes.at(ncp);
0095       lConfig.envelope = {config.layerEnvelopeR, config.layerEnvelopeR};
0096 
0097       auto rR = volume.rRange.at(ncp);
0098       auto rMin = rR.lower.value_or(0.);
0099       auto rMax = rR.upper.value_or(std::numeric_limits<double>::max());
0100       auto zR = volume.zRange.at(ncp);
0101       auto zMin = zR.lower.value_or(-std::numeric_limits<double>::max());
0102       auto zMax = zR.upper.value_or(std::numeric_limits<double>::max());
0103       lConfig.parseRanges = {
0104           {Acts::AxisDirection::AxisR, {rMin, rMax}},
0105           {Acts::AxisDirection::AxisZ, {zMin, zMax}},
0106       };
0107 
0108       // Fill the layer splitting parameters in r/z
0109       auto str = volume.splitTolR.at(ncp);
0110       auto stz = volume.splitTolZ.at(ncp);
0111       if (0 < str) {
0112         lConfig.splitConfigs.emplace_back(Acts::AxisDirection::AxisR, str);
0113       }
0114       if (0 < stz) {
0115         lConfig.splitConfigs.emplace_back(Acts::AxisDirection::AxisZ, stz);
0116       }
0117       lConfig.binning0 = volume.binning0.at(ncp);
0118       lConfig.binning1 = volume.binning1.at(ncp);
0119 
0120       layerBuilderConfig.layerConfigurations[ncp].push_back(lConfig);
0121     }
0122 
0123     // Perform splitting of cylinders and discs
0124     if (volume.cylinderDiscSplit) {
0125       Acts::TGeoCylinderDiscSplitter::Config cdsConfig;
0126       cdsConfig.cylinderPhiSegments = volume.cylinderNPhiSegments;
0127       cdsConfig.cylinderLongitudinalSegments = volume.cylinderNZSegments;
0128       cdsConfig.discPhiSegments = volume.discNPhiSegments;
0129       cdsConfig.discRadialSegments = volume.discNRSegments;
0130       layerBuilderConfig.detectorElementSplitter =
0131           std::make_shared<const Acts::TGeoCylinderDiscSplitter>(
0132               cdsConfig,
0133               logger.clone("TGeoCylinderDiscSplitter", config.layerLogLevel));
0134     } else if (volume.itkModuleSplit) {
0135       TGeoITkModuleSplitter::Config itkConfig;
0136       itkConfig.barrelMap = volume.barrelMap;
0137       itkConfig.discMap = volume.discMap;
0138       itkConfig.splitPatterns = volume.splitPatterns;
0139       layerBuilderConfig.detectorElementSplitter =
0140           std::make_shared<TGeoITkModuleSplitter>(
0141               itkConfig,
0142               logger.clone("TGeoITkModuleSplitter", config.layerLogLevel));
0143     }
0144 
0145     detLayerConfigs.push_back(layerBuilderConfig);
0146   }
0147 
0148   return detLayerConfigs;
0149 }
0150 
0151 /// @brief Function to build the generic tracking geometry
0152 // from a TGeo object.
0153 ///
0154 /// It does *currently* not translate the material, this has
0155 /// to be done with a material mapping stage
0156 ///
0157 /// @tparam variable_map_t is the variable map
0158 ///
0159 /// @param vm is the variable map from the options
0160 std::shared_ptr<const Acts::TrackingGeometry> buildTGeoDetector(
0161     const TGeoDetector::Config& config, const Acts::GeometryContext& context,
0162     std::vector<std::shared_ptr<const Acts::DetectorElementBase>>&
0163         detElementStore,
0164     std::shared_ptr<const Acts::IMaterialDecorator> mdecorator,
0165     const Acts::Logger& logger) {
0166   // configure surface array creator
0167   Acts::SurfaceArrayCreator::Config sacConfig;
0168   auto surfaceArrayCreator = std::make_shared<const Acts::SurfaceArrayCreator>(
0169       sacConfig, logger.clone("SurfaceArrayCreator", config.surfaceLogLevel));
0170   // configure the proto layer helper
0171   Acts::ProtoLayerHelper::Config plhConfig;
0172   auto protoLayerHelper = std::make_shared<const Acts::ProtoLayerHelper>(
0173       plhConfig, logger.clone("ProtoLayerHelper", config.layerLogLevel));
0174   // configure the layer creator that uses the surface array creator
0175   Acts::LayerCreator::Config lcConfig;
0176   lcConfig.surfaceArrayCreator = surfaceArrayCreator;
0177   auto layerCreator = std::make_shared<const Acts::LayerCreator>(
0178       lcConfig, logger.clone("LayerCreator", config.layerLogLevel));
0179   // configure the layer array creator
0180   Acts::LayerArrayCreator::Config lacConfig;
0181   auto layerArrayCreator = std::make_shared<const Acts::LayerArrayCreator>(
0182       lacConfig, logger.clone("LayerArrayCreator", config.layerLogLevel));
0183   // tracking volume array creator
0184   Acts::TrackingVolumeArrayCreator::Config tvacConfig;
0185   auto tVolumeArrayCreator =
0186       std::make_shared<const Acts::TrackingVolumeArrayCreator>(
0187           tvacConfig,
0188           logger.clone("TrackingVolumeArrayCreator", config.volumeLogLevel));
0189   // configure the cylinder volume helper
0190   Acts::CylinderVolumeHelper::Config cvhConfig;
0191   cvhConfig.layerArrayCreator = layerArrayCreator;
0192   cvhConfig.trackingVolumeArrayCreator = tVolumeArrayCreator;
0193   auto cylinderVolumeHelper =
0194       std::make_shared<const Acts::CylinderVolumeHelper>(
0195           cvhConfig,
0196           logger.clone("CylinderVolumeHelper", config.volumeLogLevel));
0197 
0198   //-------------------------------------------------------------------------------------
0199   // list the volume builders
0200   std::list<std::shared_ptr<const Acts::ITrackingVolumeBuilder>> volumeBuilders;
0201 
0202   // Create a beam pipe if configured to do so
0203   if (config.buildBeamPipe) {
0204     /// configure the beam pipe layer builder
0205     Acts::PassiveLayerBuilder::Config bplConfig;
0206     bplConfig.layerIdentification = "BeamPipe";
0207     bplConfig.centralLayerRadii = {config.beamPipeRadius};
0208     bplConfig.centralLayerHalflengthZ = {config.beamPipeHalflengthZ};
0209     bplConfig.centralLayerThickness = {config.beamPipeLayerThickness};
0210     auto beamPipeBuilder = std::make_shared<const Acts::PassiveLayerBuilder>(
0211         bplConfig, logger.clone("BeamPipeLayerBuilder", config.layerLogLevel));
0212     // create the volume for the beam pipe
0213     Acts::CylinderVolumeBuilder::Config bpvConfig;
0214     bpvConfig.trackingVolumeHelper = cylinderVolumeHelper;
0215     bpvConfig.volumeName = "BeamPipe";
0216     bpvConfig.layerBuilder = beamPipeBuilder;
0217     bpvConfig.layerEnvelopeR = {config.beamPipeEnvelopeR,
0218                                 config.beamPipeEnvelopeR};
0219     bpvConfig.buildToRadiusZero = true;
0220     auto beamPipeVolumeBuilder =
0221         std::make_shared<const Acts::CylinderVolumeBuilder>(
0222             bpvConfig,
0223             logger.clone("BeamPipeVolumeBuilder", config.volumeLogLevel));
0224     // add to the list of builders
0225     volumeBuilders.push_back(beamPipeVolumeBuilder);
0226   }
0227 
0228   // Import the file from
0229   TGeoManager::Import(config.fileName.c_str());
0230 
0231   auto layerBuilderConfigs = makeLayerBuilderConfigs(config, logger);
0232 
0233   // Remember the layer builders to collect the detector elements
0234   std::vector<std::shared_ptr<const Acts::TGeoLayerBuilder>> tgLayerBuilders;
0235 
0236   for (auto& lbc : layerBuilderConfigs) {
0237     std::shared_ptr<const Acts::LayerCreator> layerCreatorLB = nullptr;
0238 
0239     if (lbc.autoSurfaceBinning) {
0240       // Configure surface array creator (optionally) per layer builder
0241       // (in order to configure them to work appropriately)
0242       Acts::SurfaceArrayCreator::Config sacConfigLB;
0243       sacConfigLB.surfaceMatcher = lbc.surfaceBinMatcher;
0244       auto surfaceArrayCreatorLB =
0245           std::make_shared<const Acts::SurfaceArrayCreator>(
0246               sacConfigLB,
0247               logger.clone(lbc.configurationName + "SurfaceArrayCreator",
0248                            config.surfaceLogLevel));
0249       // configure the layer creator that uses the surface array creator
0250       Acts::LayerCreator::Config lcConfigLB;
0251       lcConfigLB.surfaceArrayCreator = surfaceArrayCreatorLB;
0252       layerCreatorLB = std::make_shared<const Acts::LayerCreator>(
0253           lcConfigLB, logger.clone(lbc.configurationName + "LayerCreator",
0254                                    config.layerLogLevel));
0255     }
0256 
0257     // Configure the proto layer helper
0258     Acts::ProtoLayerHelper::Config plhConfigLB;
0259     auto protoLayerHelperLB = std::make_shared<const Acts::ProtoLayerHelper>(
0260         plhConfigLB, logger.clone(lbc.configurationName + "ProtoLayerHelper",
0261                                   config.layerLogLevel));
0262 
0263     //-------------------------------------------------------------------------------------
0264     lbc.layerCreator =
0265         (layerCreatorLB != nullptr) ? layerCreatorLB : layerCreator;
0266     lbc.protoLayerHelper =
0267         (protoLayerHelperLB != nullptr) ? protoLayerHelperLB : protoLayerHelper;
0268 
0269     auto layerBuilder = std::make_shared<const Acts::TGeoLayerBuilder>(
0270         lbc, logger.clone(lbc.configurationName + "LayerBuilder",
0271                           config.layerLogLevel));
0272     // remember the layer builder
0273     tgLayerBuilders.push_back(layerBuilder);
0274 
0275     // build the pixel volume
0276     Acts::CylinderVolumeBuilder::Config volumeConfig;
0277     volumeConfig.trackingVolumeHelper = cylinderVolumeHelper;
0278     volumeConfig.volumeName = lbc.configurationName;
0279     volumeConfig.buildToRadiusZero = volumeBuilders.empty();
0280     volumeConfig.layerEnvelopeR = {config.layerEnvelopeR,
0281                                    config.layerEnvelopeR};
0282     auto ringLayoutConfiguration =
0283         [&](const std::vector<Acts::TGeoLayerBuilder::LayerConfig>& lConfigs)
0284         -> void {
0285       for (const auto& lcfg : lConfigs) {
0286         for (const auto& scfg : lcfg.splitConfigs) {
0287           if (scfg.first == Acts::AxisDirection::AxisR && scfg.second > 0.) {
0288             volumeConfig.ringTolerance =
0289                 std::max(volumeConfig.ringTolerance, scfg.second);
0290             volumeConfig.checkRingLayout = true;
0291           }
0292         }
0293       }
0294     };
0295     ringLayoutConfiguration(lbc.layerConfigurations[0]);
0296     ringLayoutConfiguration(lbc.layerConfigurations[2]);
0297     volumeConfig.layerBuilder = layerBuilder;
0298     auto volumeBuilder = std::make_shared<const Acts::CylinderVolumeBuilder>(
0299         volumeConfig, logger.clone(lbc.configurationName + "VolumeBuilder",
0300                                    config.volumeLogLevel));
0301     // add to the list of builders
0302     volumeBuilders.push_back(volumeBuilder);
0303   }
0304 
0305   //-------------------------------------------------------------------------------------
0306   // create the tracking geometry
0307   Acts::TrackingGeometryBuilder::Config tgConfig;
0308   // Add the builders
0309   tgConfig.materialDecorator = std::move(mdecorator);
0310   tgConfig.geometryIdentifierHook = config.geometryIdentifierHook;
0311 
0312   for (auto& vb : volumeBuilders) {
0313     tgConfig.trackingVolumeBuilders.push_back(
0314         [=](const auto& gcontext, const auto& inner, const auto&) {
0315           return vb->trackingVolume(gcontext, inner);
0316         });
0317   }
0318   // Add the helper
0319   tgConfig.trackingVolumeHelper = cylinderVolumeHelper;
0320   auto cylinderGeometryBuilder =
0321       std::make_shared<const Acts::TrackingGeometryBuilder>(
0322           tgConfig,
0323           logger.clone("TrackerGeometryBuilder", config.volumeLogLevel));
0324   // get the geometry
0325   auto trackingGeometry = cylinderGeometryBuilder->trackingGeometry(context);
0326   // collect the detector element store
0327   for (auto& lBuilder : tgLayerBuilders) {
0328     auto detElements = lBuilder->detectorElements();
0329     detElementStore.insert(detElementStore.begin(), detElements.begin(),
0330                            detElements.end());
0331   }
0332 
0333   /// return the tracking geometry
0334   return trackingGeometry;
0335 }
0336 
0337 }  // namespace
0338 
0339 /// Read the TGeo layer builder configurations from the user configuration.
0340 void TGeoDetector::readTGeoLayerBuilderConfigsFile(const std::string& path,
0341                                                    Config& config) {
0342   if (path.empty()) {
0343     return;
0344   }
0345   nlohmann::json djson;
0346   std::ifstream infile(path, std::ifstream::in | std::ifstream::binary);
0347   infile >> djson;
0348 
0349   config.unitScalor = djson["geo-tgeo-unit-scalor"];
0350 
0351   config.buildBeamPipe = djson["geo-tgeo-build-beampipe"];
0352   if (config.buildBeamPipe) {
0353     const auto beamPipeParameters =
0354         djson["geo-tgeo-beampipe-parameters"].get<std::array<double, 3>>();
0355     config.beamPipeRadius = beamPipeParameters[0];
0356     config.beamPipeHalflengthZ = beamPipeParameters[1];
0357     config.beamPipeLayerThickness = beamPipeParameters[2];
0358   }
0359 
0360   // Fill nested volume configs
0361   for (const auto& volume : djson["Volumes"]) {
0362     auto& vol = config.volumes.emplace_back();
0363     vol = volume;
0364   }
0365 }
0366 
0367 TGeoDetector::TGeoDetector(const Config& cfg)
0368     : Detector(Acts::getDefaultLogger("TGeoDetector", cfg.logLevel)),
0369       m_cfg(cfg) {
0370   m_nominalGeometryContext = Acts::GeometryContext();
0371 
0372   m_trackingGeometry =
0373       buildTGeoDetector(m_cfg, m_nominalGeometryContext, m_detectorStore,
0374                         m_cfg.materialDecorator, logger());
0375 }
0376 
0377 void TGeoDetector::Config::readJson(const std::string& jsonFile) {
0378   readTGeoLayerBuilderConfigsFile(jsonFile, *this);
0379 }
0380 
0381 }  // namespace ActsExamples