File indexing completed on 2025-01-30 09:15:18
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Plugins/Json/MaterialMapJsonConverter.hpp"
0010
0011 #include "Acts/Definitions/Tolerance.hpp"
0012 #include "Acts/Geometry/ApproachDescriptor.hpp"
0013 #include "Acts/Geometry/BoundarySurfaceT.hpp"
0014 #include "Acts/Geometry/CuboidVolumeBounds.hpp"
0015 #include "Acts/Geometry/CutoutCylinderVolumeBounds.hpp"
0016 #include "Acts/Geometry/CylinderVolumeBounds.hpp"
0017 #include "Acts/Geometry/GeometryHierarchyMap.hpp"
0018 #include "Acts/Geometry/GeometryIdentifier.hpp"
0019 #include "Acts/Geometry/Layer.hpp"
0020 #include "Acts/Geometry/TrackingGeometry.hpp"
0021 #include "Acts/Geometry/TrackingVolume.hpp"
0022 #include "Acts/Geometry/VolumeBounds.hpp"
0023 #include "Acts/Material/ISurfaceMaterial.hpp"
0024 #include "Acts/Material/IVolumeMaterial.hpp"
0025 #include "Acts/Material/ProtoSurfaceMaterial.hpp"
0026 #include "Acts/Material/ProtoVolumeMaterial.hpp"
0027 #include "Acts/Plugins/Json/ITrackingGeometryJsonDecorator.hpp"
0028 #include "Acts/Plugins/Json/IVolumeMaterialJsonDecorator.hpp"
0029 #include "Acts/Plugins/Json/MaterialJsonConverter.hpp"
0030 #include "Acts/Plugins/Json/SurfaceJsonConverter.hpp"
0031 #include "Acts/Plugins/Json/VolumeJsonConverter.hpp"
0032 #include "Acts/Surfaces/RectangleBounds.hpp"
0033 #include "Acts/Surfaces/Surface.hpp"
0034 #include "Acts/Surfaces/SurfaceArray.hpp"
0035 #include "Acts/Utilities/BinUtility.hpp"
0036 #include "Acts/Utilities/BinnedArray.hpp"
0037 #include "Acts/Utilities/BinningType.hpp"
0038 #include <Acts/Surfaces/AnnulusBounds.hpp>
0039 #include <Acts/Surfaces/CylinderBounds.hpp>
0040 #include <Acts/Surfaces/RadialBounds.hpp>
0041 #include <Acts/Surfaces/SurfaceBounds.hpp>
0042 #include <Acts/Surfaces/TrapezoidBounds.hpp>
0043
0044 #include <algorithm>
0045 #include <cmath>
0046 #include <cstddef>
0047 #include <map>
0048 #include <numbers>
0049 #include <stdexcept>
0050
0051 namespace Acts {
0052
0053
0054 template <>
0055 inline void decorateJson<Acts::SurfaceAndMaterialWithContext>(
0056 const ITrackingGeometryJsonDecorator* decorator,
0057 const Acts::SurfaceAndMaterialWithContext& src, nlohmann::json& dest) {
0058 if (decorator != nullptr && std::get<0>(src) != nullptr) {
0059 decorator->decorate(*std::get<0>(src), dest);
0060 }
0061 }
0062 template <>
0063 inline void decorateJson<Acts::TrackingVolumeAndMaterial>(
0064 const ITrackingGeometryJsonDecorator* decorator,
0065 const Acts::TrackingVolumeAndMaterial& src, nlohmann::json& dest) {
0066 if (decorator != nullptr && src.first != nullptr) {
0067 decorator->decorate(*src.first, dest);
0068 }
0069 }
0070
0071 template <>
0072 inline void decorateJson<Acts::IVolumeMaterial>(
0073 const IVolumeMaterialJsonDecorator* decorator,
0074 const Acts::IVolumeMaterial* src, nlohmann::json& dest) {
0075 if (decorator != nullptr && src != nullptr) {
0076 decorator->decorate(*src, dest);
0077 }
0078 }
0079 template <>
0080 inline void decorateJson<Acts::ISurfaceMaterial>(
0081 const IVolumeMaterialJsonDecorator* decorator,
0082 const Acts::ISurfaceMaterial* src, nlohmann::json& dest) {
0083 if (decorator != nullptr && src != nullptr) {
0084 decorator->decorate(*src, dest);
0085 }
0086 }
0087 }
0088
0089 namespace {
0090
0091 Acts::SurfaceAndMaterialWithContext defaultSurfaceMaterial(
0092 const std::shared_ptr<const Acts::Surface>& surface,
0093 const Acts::GeometryContext& context) {
0094 if (surface->surfaceMaterialSharedPtr() != nullptr) {
0095 return {surface, surface->surfaceMaterialSharedPtr(), context};
0096 }
0097 Acts::BinUtility bUtility;
0098
0099 const Acts::SurfaceBounds& surfaceBounds = surface->bounds();
0100 const Acts::RadialBounds* radialBounds =
0101 dynamic_cast<const Acts::RadialBounds*>(&surfaceBounds);
0102 const Acts::CylinderBounds* cylinderBounds =
0103 dynamic_cast<const Acts::CylinderBounds*>(&surfaceBounds);
0104 const Acts::AnnulusBounds* annulusBounds =
0105 dynamic_cast<const Acts::AnnulusBounds*>(&surfaceBounds);
0106 const Acts::RectangleBounds* rectangleBounds =
0107 dynamic_cast<const Acts::RectangleBounds*>(&surfaceBounds);
0108 const Acts::TrapezoidBounds* trapezoidBounds =
0109 dynamic_cast<const Acts::TrapezoidBounds*>(&surfaceBounds);
0110
0111 if (radialBounds != nullptr) {
0112 bUtility += Acts::BinUtility(
0113 1,
0114 radialBounds->get(Acts::RadialBounds::eAveragePhi) -
0115 radialBounds->get(Acts::RadialBounds::eHalfPhiSector),
0116 radialBounds->get(Acts::RadialBounds::eAveragePhi) +
0117 radialBounds->get(Acts::RadialBounds::eHalfPhiSector),
0118 (radialBounds->get(Acts::RadialBounds::eHalfPhiSector) -
0119 std::numbers::pi) < Acts::s_epsilon
0120 ? Acts::closed
0121 : Acts::open,
0122 Acts::AxisDirection::AxisPhi);
0123 bUtility += Acts::BinUtility(1, radialBounds->rMin(), radialBounds->rMax(),
0124 Acts::open, Acts::AxisDirection::AxisR);
0125 }
0126 if (cylinderBounds != nullptr) {
0127 bUtility += Acts::BinUtility(
0128 1,
0129 cylinderBounds->get(Acts::CylinderBounds::eAveragePhi) -
0130 cylinderBounds->get(Acts::CylinderBounds::eHalfPhiSector),
0131 cylinderBounds->get(Acts::CylinderBounds::eAveragePhi) +
0132 cylinderBounds->get(Acts::CylinderBounds::eHalfPhiSector),
0133 (cylinderBounds->get(Acts::CylinderBounds::eHalfPhiSector) -
0134 std::numbers::pi) < Acts::s_epsilon
0135 ? Acts::closed
0136 : Acts::open,
0137 Acts::AxisDirection::AxisPhi);
0138 bUtility += Acts::BinUtility(
0139 1, -1 * cylinderBounds->get(Acts::CylinderBounds::eHalfLengthZ),
0140 cylinderBounds->get(Acts::CylinderBounds::eHalfLengthZ), Acts::open,
0141 Acts::AxisDirection::AxisZ);
0142 }
0143 if (annulusBounds != nullptr) {
0144 bUtility +=
0145 Acts::BinUtility(1, annulusBounds->get(Acts::AnnulusBounds::eMinPhiRel),
0146 annulusBounds->get(Acts::AnnulusBounds::eMaxPhiRel),
0147 Acts::open, Acts::AxisDirection::AxisPhi);
0148 bUtility += Acts::BinUtility(1, static_cast<float>(annulusBounds->rMin()),
0149 static_cast<float>(annulusBounds->rMax()),
0150 Acts::open, Acts::AxisDirection::AxisR);
0151 }
0152 if (rectangleBounds != nullptr) {
0153 bUtility +=
0154 Acts::BinUtility(1, rectangleBounds->get(Acts::RectangleBounds::eMinX),
0155 rectangleBounds->get(Acts::RectangleBounds::eMaxX),
0156 Acts::open, Acts::AxisDirection::AxisX);
0157 bUtility +=
0158 Acts::BinUtility(1, rectangleBounds->get(Acts::RectangleBounds::eMinY),
0159 rectangleBounds->get(Acts::RectangleBounds::eMaxY),
0160 Acts::open, Acts::AxisDirection::AxisY);
0161 }
0162 if (trapezoidBounds != nullptr) {
0163 double halfLengthX =
0164 std::max(trapezoidBounds->get(Acts::TrapezoidBounds::eHalfLengthXnegY),
0165 trapezoidBounds->get(Acts::TrapezoidBounds::eHalfLengthXposY));
0166 bUtility += Acts::BinUtility(1, -1 * halfLengthX, halfLengthX, Acts::open,
0167 Acts::AxisDirection::AxisX);
0168 bUtility += Acts::BinUtility(
0169 1, -1 * trapezoidBounds->get(Acts::TrapezoidBounds::eHalfLengthY),
0170 trapezoidBounds->get(Acts::TrapezoidBounds::eHalfLengthY), Acts::open,
0171 Acts::AxisDirection::AxisY);
0172 }
0173 return {surface, std::make_shared<Acts::ProtoSurfaceMaterial>(bUtility),
0174 context};
0175 }
0176
0177 Acts::TrackingVolumeAndMaterial defaultVolumeMaterial(
0178 const Acts::TrackingVolume* volume) {
0179 Acts::BinUtility bUtility;
0180 if (volume->volumeMaterialPtr() != nullptr) {
0181 return {volume, volume->volumeMaterialPtr()};
0182 }
0183
0184 auto cyBounds = dynamic_cast<const Acts::CylinderVolumeBounds*>(
0185 &(volume->volumeBounds()));
0186 auto cutcylBounds = dynamic_cast<const Acts::CutoutCylinderVolumeBounds*>(
0187 &(volume->volumeBounds()));
0188 auto cuBounds =
0189 dynamic_cast<const Acts::CuboidVolumeBounds*>(&(volume->volumeBounds()));
0190
0191 if (cyBounds != nullptr) {
0192 bUtility +=
0193 Acts::BinUtility(1, cyBounds->get(Acts::CylinderVolumeBounds::eMinR),
0194 cyBounds->get(Acts::CylinderVolumeBounds::eMaxR),
0195 Acts::open, Acts::AxisDirection::AxisR);
0196 bUtility += Acts::BinUtility(
0197 1, -cyBounds->get(Acts::CylinderVolumeBounds::eHalfPhiSector),
0198 cyBounds->get(Acts::CylinderVolumeBounds::eHalfPhiSector),
0199 (cyBounds->get(Acts::CylinderVolumeBounds::eHalfPhiSector) -
0200 std::numbers::pi) < Acts::s_epsilon
0201 ? Acts::closed
0202 : Acts::open,
0203 Acts::AxisDirection::AxisPhi);
0204 bUtility += Acts::BinUtility(
0205 1, -cyBounds->get(Acts::CylinderVolumeBounds::eHalfLengthZ),
0206 cyBounds->get(Acts::CylinderVolumeBounds::eHalfLengthZ), Acts::open,
0207 Acts::AxisDirection::AxisZ);
0208 }
0209 if (cutcylBounds != nullptr) {
0210 bUtility += Acts::BinUtility(
0211 1, cutcylBounds->get(Acts::CutoutCylinderVolumeBounds::eMinR),
0212 cutcylBounds->get(Acts::CutoutCylinderVolumeBounds::eMaxR), Acts::open,
0213 Acts::AxisDirection::AxisR);
0214 bUtility += Acts::BinUtility(1, -std::numbers::pi_v<float>,
0215 std::numbers::pi_v<float>, Acts::closed,
0216 Acts::AxisDirection::AxisPhi);
0217 bUtility += Acts::BinUtility(
0218 1, -cutcylBounds->get(Acts::CutoutCylinderVolumeBounds::eHalfLengthZ),
0219 cutcylBounds->get(Acts::CutoutCylinderVolumeBounds::eHalfLengthZ),
0220 Acts::open, Acts::AxisDirection::AxisZ);
0221 } else if (cuBounds != nullptr) {
0222 bUtility += Acts::BinUtility(
0223 1, -cuBounds->get(Acts::CuboidVolumeBounds::eHalfLengthX),
0224 cuBounds->get(Acts::CuboidVolumeBounds::eHalfLengthX), Acts::open,
0225 Acts::AxisDirection::AxisX);
0226 bUtility += Acts::BinUtility(
0227 1, -cuBounds->get(Acts::CuboidVolumeBounds::eHalfLengthY),
0228 cuBounds->get(Acts::CuboidVolumeBounds::eHalfLengthY), Acts::open,
0229 Acts::AxisDirection::AxisY);
0230 bUtility += Acts::BinUtility(
0231 1, -cuBounds->get(Acts::CuboidVolumeBounds::eHalfLengthZ),
0232 cuBounds->get(Acts::CuboidVolumeBounds::eHalfLengthZ), Acts::open,
0233 Acts::AxisDirection::AxisZ);
0234 }
0235 return {volume, std::make_shared<Acts::ProtoVolumeMaterial>(bUtility)};
0236 }
0237 }
0238
0239 Acts::MaterialMapJsonConverter::MaterialMapJsonConverter(
0240 const Acts::MaterialMapJsonConverter::Config& config,
0241 Acts::Logging::Level level)
0242 : m_cfg(config),
0243 m_logger{getDefaultLogger("MaterialMapJsonConverter", level)},
0244 m_volumeMaterialConverter(m_volumeName),
0245 m_volumeConverter(m_volumeName),
0246 m_surfaceMaterialConverter(m_surfaceName),
0247 m_surfaceConverter(m_surfaceName) {}
0248
0249
0250
0251 nlohmann::json Acts::MaterialMapJsonConverter::materialMapsToJson(
0252 const DetectorMaterialMaps& maps,
0253 const IVolumeMaterialJsonDecorator* decorator) {
0254 VolumeMaterialMap volumeMap = maps.second;
0255 std::vector<std::pair<GeometryIdentifier, const IVolumeMaterial*>>
0256 mapVolumeInit;
0257 for (const auto& [key, value] : volumeMap) {
0258 mapVolumeInit.push_back({key, value.get()});
0259 }
0260 GeometryHierarchyMap<const IVolumeMaterial*> hierarchyVolumeMap(
0261 mapVolumeInit);
0262 nlohmann::json materialVolume =
0263 m_volumeMaterialConverter.toJson(hierarchyVolumeMap, decorator);
0264 SurfaceMaterialMap surfaceMap = maps.first;
0265 std::vector<std::pair<GeometryIdentifier, const ISurfaceMaterial*>>
0266 mapSurfaceInit;
0267 for (const auto& [key, value] : surfaceMap) {
0268 mapSurfaceInit.push_back({key, value.get()});
0269 }
0270 GeometryHierarchyMap<const ISurfaceMaterial*> hierarchySurfaceMap(
0271 mapSurfaceInit);
0272 nlohmann::json materialSurface =
0273 m_surfaceMaterialConverter.toJson(hierarchySurfaceMap, decorator);
0274 nlohmann::json materialMap;
0275 materialMap["Volumes"] = materialVolume;
0276 materialMap["Surfaces"] = materialSurface;
0277 return materialMap;
0278 }
0279
0280 Acts::MaterialMapJsonConverter::DetectorMaterialMaps
0281 Acts::MaterialMapJsonConverter::jsonToMaterialMaps(
0282 const nlohmann::json& materialmap) {
0283 nlohmann::json materialVolume = materialmap["Volumes"];
0284 GeometryHierarchyMap<const IVolumeMaterial*> hierarchyVolumeMap =
0285 m_volumeMaterialConverter.fromJson(materialVolume);
0286 VolumeMaterialMap volumeMap;
0287 for (std::size_t i = 0; i < hierarchyVolumeMap.size(); i++) {
0288 std::shared_ptr<const IVolumeMaterial> volumePointer(
0289 hierarchyVolumeMap.valueAt(i));
0290 volumeMap.insert({hierarchyVolumeMap.idAt(i), std::move(volumePointer)});
0291 }
0292 nlohmann::json materialSurface = materialmap["Surfaces"];
0293 GeometryHierarchyMap<const ISurfaceMaterial*> hierarchySurfaceMap =
0294 m_surfaceMaterialConverter.fromJson(materialSurface);
0295 SurfaceMaterialMap surfaceMap;
0296 for (std::size_t i = 0; i < hierarchySurfaceMap.size(); i++) {
0297 std::shared_ptr<const ISurfaceMaterial> surfacePointer(
0298 hierarchySurfaceMap.valueAt(i));
0299 surfaceMap.insert({hierarchySurfaceMap.idAt(i), std::move(surfacePointer)});
0300 }
0301
0302 Acts::MaterialMapJsonConverter::DetectorMaterialMaps maps = {surfaceMap,
0303 volumeMap};
0304
0305
0306 return maps;
0307 }
0308
0309 nlohmann::json Acts::MaterialMapJsonConverter::trackingGeometryToJson(
0310 const Acts::TrackingGeometry& tGeometry,
0311 const ITrackingGeometryJsonDecorator* decorator) {
0312 std::vector<std::pair<GeometryIdentifier, Acts::TrackingVolumeAndMaterial>>
0313 volumeHierarchy;
0314 std::vector<
0315 std::pair<GeometryIdentifier, Acts::SurfaceAndMaterialWithContext>>
0316 surfaceHierarchy;
0317 convertToHierarchy(volumeHierarchy, surfaceHierarchy,
0318 tGeometry.highestTrackingVolume());
0319 GeometryHierarchyMap<Acts::TrackingVolumeAndMaterial> hierarchyVolumeMap(
0320 volumeHierarchy);
0321 nlohmann::json jsonVolumes =
0322 m_volumeConverter.toJson(hierarchyVolumeMap, decorator);
0323 GeometryHierarchyMap<Acts::SurfaceAndMaterialWithContext> hierarchySurfaceMap(
0324 surfaceHierarchy);
0325 nlohmann::json jsonSurfaces =
0326 m_surfaceConverter.toJson(hierarchySurfaceMap, decorator);
0327 nlohmann::json hierarchyMap;
0328 hierarchyMap["Volumes"] = jsonVolumes;
0329 hierarchyMap["Surfaces"] = jsonSurfaces;
0330 return hierarchyMap;
0331 }
0332
0333 void Acts::MaterialMapJsonConverter::convertToHierarchy(
0334 std::vector<std::pair<GeometryIdentifier, Acts::TrackingVolumeAndMaterial>>&
0335 volumeHierarchy,
0336 std::vector<
0337 std::pair<GeometryIdentifier, Acts::SurfaceAndMaterialWithContext>>&
0338 surfaceHierarchy,
0339 const Acts::TrackingVolume* tVolume) {
0340 auto sameId = [tVolume](const auto& pair) {
0341 return (tVolume->geometryId() == pair.first);
0342 };
0343 if (std::ranges::any_of(volumeHierarchy, sameId)) {
0344
0345 return;
0346 }
0347 if ((tVolume->volumeMaterial() != nullptr ||
0348 m_cfg.processNonMaterial == true) &&
0349 m_cfg.processVolumes == true) {
0350 volumeHierarchy.push_back(
0351 {tVolume->geometryId(), defaultVolumeMaterial(tVolume)});
0352 }
0353
0354 if (tVolume->confinedVolumes() != nullptr) {
0355
0356 auto& volumes = tVolume->confinedVolumes()->arrayObjects();
0357
0358 for (auto& vol : volumes) {
0359
0360 convertToHierarchy(volumeHierarchy, surfaceHierarchy, vol.get());
0361 }
0362 }
0363
0364 if (m_cfg.processDenseVolumes && !tVolume->denseVolumes().empty()) {
0365
0366 for (auto& vol : tVolume->denseVolumes()) {
0367
0368 convertToHierarchy(volumeHierarchy, surfaceHierarchy, vol.get());
0369 }
0370 }
0371 if (tVolume->confinedLayers() != nullptr) {
0372
0373 auto& layers = tVolume->confinedLayers()->arrayObjects();
0374
0375 for (auto& lay : layers) {
0376 if (m_cfg.processRepresenting == true) {
0377 auto& layRep = lay->surfaceRepresentation();
0378 if ((layRep.surfaceMaterial() != nullptr ||
0379 m_cfg.processNonMaterial == true) &&
0380 layRep.geometryId() != GeometryIdentifier()) {
0381 surfaceHierarchy.push_back(
0382 {layRep.geometryId(),
0383 defaultSurfaceMaterial(layRep.getSharedPtr(), m_cfg.context)});
0384 }
0385 }
0386 if (lay->approachDescriptor() != nullptr &&
0387 m_cfg.processApproaches == true) {
0388 for (auto& asf : lay->approachDescriptor()->containedSurfaces()) {
0389 if (asf->surfaceMaterial() != nullptr ||
0390 m_cfg.processNonMaterial == true) {
0391 surfaceHierarchy.push_back(
0392 {asf->geometryId(),
0393 defaultSurfaceMaterial(asf->getSharedPtr(), m_cfg.context)});
0394 }
0395 }
0396 }
0397 if (lay->surfaceArray() != nullptr && m_cfg.processSensitives == true) {
0398 for (auto& ssf : lay->surfaceArray()->surfaces()) {
0399 if (ssf->surfaceMaterial() != nullptr ||
0400 m_cfg.processNonMaterial == true) {
0401 auto sp = ssf->getSharedPtr();
0402 auto sm = defaultSurfaceMaterial(sp, m_cfg.context);
0403 auto id = ssf->geometryId();
0404
0405 std::pair p{id, sm};
0406 surfaceHierarchy.push_back(p);
0407 }
0408 }
0409 }
0410 }
0411 }
0412
0413 for (auto& bsurf : tVolume->boundarySurfaces()) {
0414
0415 auto& bssfRep = bsurf->surfaceRepresentation();
0416 if (bssfRep.geometryId().volume() == tVolume->geometryId().volume() &&
0417 m_cfg.processBoundaries == true) {
0418 if (bssfRep.surfaceMaterial() != nullptr ||
0419 m_cfg.processNonMaterial == true) {
0420 surfaceHierarchy.push_back(
0421 {bssfRep.geometryId(),
0422 defaultSurfaceMaterial(bssfRep.getSharedPtr(), m_cfg.context)});
0423 }
0424 }
0425 }
0426 }