Back to home page

sPhenix code displayed by LXR

 
 

    


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

0001 // This file is part of the Acts project.
0002 //
0003 // Copyright (C) 2023 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/Json/DetectorJsonConverter.hpp"
0010 
0011 #include "Acts/Detector/Detector.hpp"
0012 #include "Acts/Detector/DetectorVolume.hpp"
0013 #include "Acts/Detector/Portal.hpp"
0014 #include "Acts/Navigation/DetectorVolumeFinders.hpp"
0015 #include "Acts/Plugins/Json/DetectorVolumeFinderJsonConverter.hpp"
0016 #include "Acts/Plugins/Json/DetectorVolumeJsonConverter.hpp"
0017 #include "Acts/Plugins/Json/DetrayJsonHelper.hpp"
0018 #include "Acts/Plugins/Json/IndexedSurfacesJsonConverter.hpp"
0019 #include "Acts/Plugins/Json/PortalJsonConverter.hpp"
0020 #include "Acts/Utilities/Enumerate.hpp"
0021 #include "Acts/Utilities/Helpers.hpp"
0022 
0023 #include <algorithm>
0024 #include <ctime>
0025 #include <set>
0026 
0027 nlohmann::json Acts::DetectorJsonConverter::toJson(
0028     const GeometryContext& gctx, const Experimental::Detector& detector,
0029     const Options& options) {
0030   // Get the time stamp
0031   std::time_t tt = 0;
0032   std::time(&tt);
0033   auto ti = std::localtime(&tt);
0034 
0035   nlohmann::json jDetector;
0036 
0037   std::size_t nSurfaces = 0;
0038   std::vector<const Experimental::Portal*> portals;
0039 
0040   for (const auto* volume : detector.volumes()) {
0041     nSurfaces += volume->surfaces().size();
0042     for (const auto& portal : volume->portals()) {
0043       if (std::find(portals.begin(), portals.end(), portal) == portals.end()) {
0044         portals.push_back(portal);
0045       }
0046     }
0047   }
0048 
0049   // Write the actual data objects
0050   nlohmann::json jData;
0051   jData["name"] = detector.name();
0052 
0053   // The portals are written first
0054   auto volumes = detector.volumes();
0055   nlohmann::json jPortals;
0056 
0057   for (const auto& portal : portals) {
0058     auto jPortal = PortalJsonConverter::toJson(
0059         gctx, *portal, volumes, options.volumeOptions.portalOptions);
0060     jPortals.push_back(jPortal);
0061   }
0062   jData["portals"] = jPortals;
0063 
0064   // The volumes are written next, with portals already defined, the volumes
0065   // will only index those
0066   nlohmann::json jVolumes;
0067   for (const auto& volume : volumes) {
0068     auto jVolume = DetectorVolumeJsonConverter::toJson(
0069         gctx, *volume, volumes, portals, options.volumeOptions);
0070     jVolumes.push_back(jVolume);
0071   }
0072   jData["volumes"] = jVolumes;
0073 
0074   jData["volume_finder"] = DetectorVolumeFinderJsonConverter::toJson(
0075       detector.detectorVolumeFinder());
0076 
0077   // Write the header
0078   nlohmann::json jHeader;
0079   jHeader["detector"] = detector.name();
0080   jHeader["type"] = "acts";
0081   jHeader["date"] = std::asctime(ti);
0082   jHeader["surface_count"] = nSurfaces;
0083   jHeader["portal_count"] = portals.size();
0084   jHeader["volume_count"] = detector.volumes().size();
0085   jDetector["header"] = jHeader;
0086   jDetector["data"] = jData;
0087   return jDetector;
0088 }
0089 
0090 nlohmann::json Acts::DetectorJsonConverter::toJsonDetray(
0091     const GeometryContext& gctx, const Experimental::Detector& detector,
0092     const Options& options) {
0093   // Get the time stamp
0094   std::time_t tt = 0;
0095   std::time(&tt);
0096   auto ti = std::localtime(&tt);
0097 
0098   nlohmann::json jFile;
0099 
0100   // (1) Detector section
0101   nlohmann::json jGeometry;
0102   nlohmann::json jGeometryData;
0103   nlohmann::json jGeometryHeader;
0104   std::size_t nSurfaces = 0;
0105 
0106   nlohmann::json jCommonHeader;
0107   jCommonHeader["detector"] = detector.name();
0108   jCommonHeader["date"] = std::asctime(ti);
0109   jCommonHeader["version"] = "detray - 0.44.0";
0110   jCommonHeader["tag"] = "geometry";
0111 
0112   auto volumes = detector.volumes();
0113 
0114   // Convert the volumes
0115   nlohmann::json jVolumes;
0116   for (const auto& volume : volumes) {
0117     auto jVolume = DetectorVolumeJsonConverter::toJsonDetray(
0118         gctx, *volume, volumes, options.volumeOptions);
0119     jVolumes.push_back(jVolume);
0120     if (jVolume.find("surfaces") != jVolume.end() &&
0121         jVolume["surfaces"].is_array()) {
0122       nSurfaces += jVolume["surfaces"].size();
0123     }
0124   }
0125   jGeometryData["volumes"] = jVolumes;
0126   jGeometryData["volume_grid"] = DetectorVolumeFinderJsonConverter::toJson(
0127       detector.detectorVolumeFinder(), true);
0128 
0129   // (1) Geometry
0130   // For detray, the number of surfaces and portals are collected
0131   // from the translated volumes
0132   jGeometryHeader["type"] = "detray";
0133   jGeometryHeader["common"] = jCommonHeader;
0134   jGeometryHeader["surface_count"] = nSurfaces;
0135   jGeometryHeader["volume_count"] = detector.volumes().size();
0136   jGeometry["header"] = jGeometryHeader;
0137   jGeometry["data"] = jGeometryData;
0138   jFile["geometry"] = jGeometry;
0139 
0140   // (2) surface grid section
0141   nlohmann::json jSurfaceGrids;
0142   nlohmann::json jSurfaceGridsData;
0143   nlohmann::json jSurfaceGridsCollection;
0144   nlohmann::json jSurfaceGridsHeader;
0145   for (const auto [iv, volume] : enumerate(volumes)) {
0146     // And its surface navigation delegates
0147     nlohmann::json jSurfacesDelegate = IndexedSurfacesJsonConverter::toJson(
0148         volume->surfaceCandidatesUpdater(), true);
0149     if (jSurfacesDelegate.is_null()) {
0150       continue;
0151     }
0152     // Patch axes for cylindrical grid surfaces, axes are swapped
0153     // at this point
0154     auto jAccLink = jSurfacesDelegate["acc_link"];
0155     std::size_t accLinkType = jAccLink["type"];
0156     if (accLinkType == 4u) {
0157       // Radial value to transfer phi to rphi
0158       std::vector<ActsScalar> bValues = volume->volumeBounds().values();
0159       ActsScalar rRef = 0.5 * (bValues[1] + bValues[0]);
0160       // Get the axes
0161       auto& jAxes = jSurfacesDelegate["axes"];
0162       // r*phi axis is the first one
0163       std::vector<ActsScalar> jAxesEdges = jAxes[0u]["edges"];
0164       std::for_each(jAxesEdges.begin(), jAxesEdges.end(),
0165                     [rRef](ActsScalar& phi) { phi *= rRef; });
0166       // Write back the patches axis edges
0167       jSurfacesDelegate["axes"][0u]["edges"] = jAxesEdges;
0168     }
0169     // Colplete the grid json for detray usage
0170     jSurfacesDelegate["volume_link"] = iv;
0171     // jSurfacesDelegate["acc_link"] =
0172     jSurfaceGridsCollection.push_back(jSurfacesDelegate);
0173   }
0174   jSurfaceGridsData["grids"] = jSurfaceGridsCollection;
0175 
0176   jCommonHeader["tag"] = "surface_grids";
0177   jSurfaceGridsHeader["common"] = jCommonHeader;
0178   jSurfaceGridsHeader["grid_count"] = jSurfaceGridsCollection.size();
0179 
0180   jSurfaceGrids["header"] = jSurfaceGridsHeader;
0181   jSurfaceGrids["data"] = jSurfaceGridsData;
0182 
0183   jFile["surface_grids"] = jSurfaceGrids;
0184 
0185   // (3) material section
0186   nlohmann::json jMaterial;
0187 
0188   jFile["material"] = jMaterial;
0189 
0190   return jFile;
0191 }
0192 
0193 std::shared_ptr<Acts::Experimental::Detector>
0194 Acts::DetectorJsonConverter::fromJson(const GeometryContext& gctx,
0195                                       const nlohmann::json& jDetector) {
0196   // Read back all the data
0197   auto jData = jDetector["data"];
0198   auto jVolumes = jData["volumes"];
0199   auto jPortals = jData["portals"];
0200   const std::string name = jData["name"];
0201 
0202   std::vector<std::shared_ptr<Experimental::DetectorVolume>> volumes;
0203   std::vector<std::shared_ptr<Experimental::Portal>> portals;
0204 
0205   for (const auto& jVolume : jVolumes) {
0206     auto volume = DetectorVolumeJsonConverter::fromJson(gctx, jVolume);
0207     volumes.push_back(volume);
0208   }
0209 
0210   for (const auto& jPortal : jPortals) {
0211     auto portal = PortalJsonConverter::fromJson(gctx, jPortal, volumes);
0212     portals.push_back(portal);
0213   }
0214 
0215   // Patch all the portals of the volumes
0216   for (auto [iv, v] : enumerate(volumes)) {
0217     // Get the Volumes and update the portals with the loaded ones
0218     auto jVolume = jVolumes[iv];
0219     std::vector<std::size_t> portalLinks = jVolume["portal_links"];
0220     for (auto [ip, ipl] : enumerate(portalLinks)) {
0221       auto portal = portals[ipl];
0222       v->updatePortal(portal, ip);
0223     }
0224   }
0225   return Experimental::Detector::makeShared(name, volumes,
0226                                             Experimental::tryRootVolumes());
0227 }