File indexing completed on 2025-09-14 08:15:53
0001
0002
0003
0004 #include <Acts/Geometry/DetectorElementBase.hpp>
0005 #include <Acts/Geometry/GeometryIdentifier.hpp>
0006 #include <Acts/Geometry/TrackingGeometry.hpp>
0007 #include <Acts/Geometry/TrackingVolume.hpp>
0008 #include <Acts/MagneticField/MagneticFieldContext.hpp>
0009 #include <Acts/Material/IMaterialDecorator.hpp>
0010 #include <Acts/Plugins/DD4hep/ConvertDD4hepDetector.hpp>
0011 #include <Acts/Plugins/DD4hep/DD4hepDetectorElement.hpp>
0012 #include <Acts/Plugins/Json/JsonMaterialDecorator.hpp>
0013 #include <Acts/Plugins/Json/MaterialMapJsonConverter.hpp>
0014 #include <Acts/Surfaces/Surface.hpp>
0015 #include <Acts/Utilities/BinningType.hpp>
0016 #include <Acts/Utilities/Result.hpp>
0017 #include <Acts/Visualization/GeometryView3D.hpp>
0018 #include <Acts/Visualization/ObjVisualization3D.hpp>
0019 #include <Acts/Visualization/PlyVisualization3D.hpp>
0020 #include <DD4hep/DetElement.h>
0021 #include <DD4hep/VolumeManager.h>
0022 #include <JANA/JException.h>
0023 #include <TGeoManager.h>
0024 #include <fmt/core.h>
0025 #include <fmt/format.h>
0026 #include <fmt/ostream.h>
0027 #include <spdlog/common.h>
0028 #include <exception>
0029 #include <filesystem>
0030 #include <functional>
0031 #include <initializer_list>
0032 #include <type_traits>
0033
0034 #include "ActsGeometryProvider.h"
0035 #include "DD4hepBField.h"
0036 #include "extensions/spdlog/SpdlogToActs.h"
0037
0038
0039 #if FMT_VERSION >= 90000
0040 #include <Eigen/Core>
0041
0042 template <typename T>
0043 struct fmt::formatter<T, std::enable_if_t<std::is_base_of_v<Eigen::MatrixBase<T>, T>, char>>
0044 : fmt::ostream_formatter {};
0045 #endif
0046
0047 void ActsGeometryProvider::initialize(const dd4hep::Detector* dd4hep_geo, std::string material_file,
0048 std::shared_ptr<spdlog::logger> log,
0049 std::shared_ptr<spdlog::logger> init_log) {
0050
0051 m_log = log;
0052 m_init_log = init_log;
0053
0054 m_init_log->debug("ActsGeometryProvider initializing...");
0055
0056 m_init_log->debug("Set TGeoManager and acts_init_log_level log levels");
0057
0058 if (m_log->level() >= (int)spdlog::level::info) {
0059 TGeoManager::SetVerboseLevel(0);
0060 }
0061
0062
0063 auto acts_init_log_level = eicrecon::SpdlogToActsLevel(m_init_log->level());
0064
0065 m_dd4hepDetector = dd4hep_geo;
0066
0067
0068 std::shared_ptr<const Acts::IMaterialDecorator> materialDeco{nullptr};
0069 if (!material_file.empty()) {
0070 m_init_log->info("loading materials map from file: '{}'", material_file);
0071
0072 Acts::MaterialMapJsonConverter::Config jsonGeoConvConfig;
0073
0074 materialDeco = std::make_shared<const Acts::JsonMaterialDecorator>(
0075 jsonGeoConvConfig, material_file, acts_init_log_level);
0076 }
0077
0078
0079 class ConvertDD4hepDetectorGeometryIdentifierHook : public Acts::GeometryIdentifierHook {
0080 Acts::GeometryIdentifier decorateIdentifier(Acts::GeometryIdentifier identifier,
0081 const Acts::Surface& surface) const override {
0082 const auto* dd4hep_det_element =
0083 dynamic_cast<const Acts::DD4hepDetectorElement*>(surface.associatedDetectorElement());
0084 if (dd4hep_det_element == nullptr) {
0085 return identifier;
0086 }
0087
0088 #if Acts_VERSION_MAJOR >= 40
0089 return identifier.withExtra(0xff & dd4hep_det_element->identifier());
0090 #else
0091 return identifier.setExtra(0xff & dd4hep_det_element->identifier());
0092 #endif
0093 };
0094 };
0095 auto geometryIdHook = std::make_shared<ConvertDD4hepDetectorGeometryIdentifierHook>();
0096
0097
0098 m_init_log->info("Converting DD4Hep geometry to ACTS...");
0099 auto logger = eicrecon::getSpdlogLogger("CONV", m_log);
0100 Acts::BinningType bTypePhi = Acts::equidistant;
0101 Acts::BinningType bTypeR = Acts::equidistant;
0102 Acts::BinningType bTypeZ = Acts::equidistant;
0103 double layerEnvelopeR = Acts::UnitConstants::mm;
0104 double layerEnvelopeZ = Acts::UnitConstants::mm;
0105 double defaultLayerThickness = Acts::UnitConstants::fm;
0106 using Acts::sortDetElementsByID;
0107
0108 try {
0109 m_trackingGeo = Acts::convertDD4hepDetector(m_dd4hepDetector->world(), *logger, bTypePhi,
0110 bTypeR, bTypeZ, layerEnvelopeR, layerEnvelopeZ,
0111 defaultLayerThickness, sortDetElementsByID,
0112 m_trackingGeoCtx, materialDeco, geometryIdHook);
0113 } catch (std::exception& ex) {
0114 m_init_log->error("Error during DD4Hep -> ACTS geometry conversion: {}", ex.what());
0115 m_init_log->info("Set parameter acts::InitLogLevel=trace to see conversion info and possibly "
0116 "identify failing geometry");
0117 throw JException(ex.what());
0118 }
0119
0120 m_init_log->info("DD4Hep geometry converted!");
0121
0122
0123 m_init_log->info("Checking surfaces...");
0124 if (m_trackingGeo) {
0125
0126 const Acts::TrackingVolume* world = m_trackingGeo->highestTrackingVolume();
0127 if (m_objWriteIt) {
0128 m_init_log->info("Writing obj files to {}...", m_outputDir);
0129 Acts::ObjVisualization3D objVis;
0130 Acts::GeometryView3D::drawTrackingVolume(objVis, *world, m_trackingGeoCtx, m_containerView,
0131 m_volumeView, m_passiveView, m_sensitiveView,
0132 m_gridView, m_objWriteIt, m_outputTag, m_outputDir);
0133 }
0134 if (m_plyWriteIt) {
0135 m_init_log->info("Writing ply files to {}...", m_outputDir);
0136 Acts::PlyVisualization3D plyVis;
0137 Acts::GeometryView3D::drawTrackingVolume(plyVis, *world, m_trackingGeoCtx, m_containerView,
0138 m_volumeView, m_passiveView, m_sensitiveView,
0139 m_gridView, m_plyWriteIt, m_outputTag, m_outputDir);
0140 }
0141
0142 m_init_log->debug("visiting all the surfaces ");
0143 m_trackingGeo->visitSurfaces([this](const Acts::Surface* surface) {
0144
0145 if (surface == nullptr) {
0146 m_init_log->info("no surface??? ");
0147 return;
0148 }
0149 const auto* det_element =
0150 dynamic_cast<const Acts::DD4hepDetectorElement*>(surface->associatedDetectorElement());
0151
0152 if (det_element == nullptr) {
0153 m_init_log->error("invalid det_element!!! det_element == nullptr ");
0154 return;
0155 }
0156
0157
0158 m_init_log->debug(" det_element->identifier() = {} ", det_element->identifier());
0159 auto volman = m_dd4hepDetector->volumeManager();
0160 auto* vol_ctx = volman.lookupContext(det_element->identifier());
0161 auto vol_id = vol_ctx->identifier;
0162
0163 if (m_init_log->level() <= spdlog::level::debug) {
0164 auto de = vol_ctx->element;
0165 m_init_log->debug(" de.path = {}", de.path());
0166 m_init_log->debug(" de.placementPath = {}", de.placementPath());
0167 }
0168
0169 this->m_surfaces.insert_or_assign(vol_id, surface);
0170 });
0171 } else {
0172 m_init_log->error("m_trackingGeo==null why am I still alive???");
0173 }
0174
0175
0176 m_init_log->info("Loading magnetic field...");
0177 m_magneticField = std::make_shared<const eicrecon::BField::DD4hepBField>(m_dd4hepDetector);
0178 Acts::MagneticFieldContext m_fieldctx{eicrecon::BField::BFieldVariant(m_magneticField)};
0179 auto bCache = m_magneticField->makeCache(m_fieldctx);
0180 for (int z : {0, 500, 1000, 1500, 2000, 3000, 4000}) {
0181 auto b = m_magneticField->getField({0.0, 0.0, double(z)}, bCache).value();
0182 m_init_log->debug("B(z = {:>5} [mm]) = {} T", z, b.transpose() / Acts::UnitConstants::T);
0183 }
0184
0185 m_init_log->info("ActsGeometryProvider initialization complete");
0186 }
0187
0188 std::shared_ptr<const Acts::MagneticFieldProvider> ActsGeometryProvider::getFieldProvider() const {
0189 return m_magneticField;
0190 }