File indexing completed on 2025-01-18 09:11:46
0001
0002
0003
0004
0005
0006
0007
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
0049
0050
0051
0052
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
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
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
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
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
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
0152
0153
0154
0155
0156
0157
0158
0159
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
0167 Acts::SurfaceArrayCreator::Config sacConfig;
0168 auto surfaceArrayCreator = std::make_shared<const Acts::SurfaceArrayCreator>(
0169 sacConfig, logger.clone("SurfaceArrayCreator", config.surfaceLogLevel));
0170
0171 Acts::ProtoLayerHelper::Config plhConfig;
0172 auto protoLayerHelper = std::make_shared<const Acts::ProtoLayerHelper>(
0173 plhConfig, logger.clone("ProtoLayerHelper", config.layerLogLevel));
0174
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
0180 Acts::LayerArrayCreator::Config lacConfig;
0181 auto layerArrayCreator = std::make_shared<const Acts::LayerArrayCreator>(
0182 lacConfig, logger.clone("LayerArrayCreator", config.layerLogLevel));
0183
0184 Acts::TrackingVolumeArrayCreator::Config tvacConfig;
0185 auto tVolumeArrayCreator =
0186 std::make_shared<const Acts::TrackingVolumeArrayCreator>(
0187 tvacConfig,
0188 logger.clone("TrackingVolumeArrayCreator", config.volumeLogLevel));
0189
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
0200 std::list<std::shared_ptr<const Acts::ITrackingVolumeBuilder>> volumeBuilders;
0201
0202
0203 if (config.buildBeamPipe) {
0204
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
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
0225 volumeBuilders.push_back(beamPipeVolumeBuilder);
0226 }
0227
0228
0229 TGeoManager::Import(config.fileName.c_str());
0230
0231 auto layerBuilderConfigs = makeLayerBuilderConfigs(config, logger);
0232
0233
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
0241
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
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
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
0273 tgLayerBuilders.push_back(layerBuilder);
0274
0275
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
0302 volumeBuilders.push_back(volumeBuilder);
0303 }
0304
0305
0306
0307 Acts::TrackingGeometryBuilder::Config tgConfig;
0308
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
0319 tgConfig.trackingVolumeHelper = cylinderVolumeHelper;
0320 auto cylinderGeometryBuilder =
0321 std::make_shared<const Acts::TrackingGeometryBuilder>(
0322 tgConfig,
0323 logger.clone("TrackerGeometryBuilder", config.volumeLogLevel));
0324
0325 auto trackingGeometry = cylinderGeometryBuilder->trackingGeometry(context);
0326
0327 for (auto& lBuilder : tgLayerBuilders) {
0328 auto detElements = lBuilder->detectorElements();
0329 detElementStore.insert(detElementStore.begin(), detElements.begin(),
0330 detElements.end());
0331 }
0332
0333
0334 return trackingGeometry;
0335 }
0336
0337 }
0338
0339
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
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 }