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/DetectorVolumeJsonConverter.hpp"
0010 
0011 #include "Acts/Detector/DetectorVolume.hpp"
0012 #include "Acts/Detector/Portal.hpp"
0013 #include "Acts/Detector/PortalGenerators.hpp"
0014 #include "Acts/Navigation/DetectorVolumeFinders.hpp"
0015 #include "Acts/Navigation/SurfaceCandidatesUpdaters.hpp"
0016 #include "Acts/Plugins/Json/AlgebraJsonConverter.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/Plugins/Json/SurfaceJsonConverter.hpp"
0021 #include "Acts/Plugins/Json/VolumeBoundsJsonConverter.hpp"
0022 #include "Acts/Utilities/Enumerate.hpp"
0023 
0024 #include <ctime>
0025 
0026 namespace {
0027 
0028 /// Find the position of the volume to point to
0029 ///
0030 /// @param volume the volume to find
0031 /// @param the collection of volumes
0032 ///
0033 /// @note return -1 if not found, to be interpreted by the caller
0034 int findVolume(
0035     const Acts::Experimental::DetectorVolume* volume,
0036     const std::vector<const Acts::Experimental::DetectorVolume*>& volumes) {
0037   auto candidate = std::find(volumes.begin(), volumes.end(), volume);
0038   if (candidate != volumes.end()) {
0039     return std::distance(volumes.begin(), candidate);
0040   }
0041   return -1;
0042 }
0043 }  // namespace
0044 
0045 nlohmann::json Acts::DetectorVolumeJsonConverter::toJson(
0046     const GeometryContext& gctx, const Experimental::DetectorVolume& volume,
0047     const std::vector<const Experimental::DetectorVolume*>& detectorVolumes,
0048     const std::vector<const Experimental::Portal*>& portals,
0049     const Options& options) {
0050   nlohmann::json jVolume;
0051   jVolume["name"] = volume.name();
0052   jVolume["geometryId"] = volume.geometryId().volume();
0053   jVolume["transform"] = Transform3JsonConverter::toJson(
0054       volume.transform(gctx), options.transformOptions);
0055   jVolume["bounds"] = VolumeBoundsJsonConverter::toJson(volume.volumeBounds());
0056   // Write the surfaces
0057   nlohmann::json jSurfaces;
0058   std::for_each(
0059       volume.surfaces().begin(), volume.surfaces().end(), [&](const auto& s) {
0060         jSurfaces.push_back(
0061             SurfaceJsonConverter::toJson(gctx, *s, options.surfaceOptions));
0062       });
0063   jVolume["surfaces"] = jSurfaces;
0064   // And its surface navigation delegates
0065   nlohmann::json jSurfacesDelegate =
0066       IndexedSurfacesJsonConverter::toJson(volume.surfaceCandidatesUpdater());
0067   jVolume["surface_navigation"] = jSurfacesDelegate;
0068 
0069   // Write the sub volumes
0070   nlohmann::json jVolumes;
0071   std::for_each(
0072       volume.volumes().begin(), volume.volumes().end(), [&](const auto& v) {
0073         jVolumes.push_back(toJson(gctx, *v, detectorVolumes, portals, options));
0074       });
0075   jVolume["volumes"] = jVolumes;
0076 
0077   // Write the portals if pre-converted as link
0078   nlohmann::json jPortals;
0079   if (!portals.empty()) {
0080     for (const auto* p : volume.portals()) {
0081       auto it = std::find(portals.begin(), portals.end(), p);
0082       if (it != portals.end()) {
0083         jPortals.push_back(std::distance(portals.begin(), it));
0084       } else {
0085         throw std::runtime_error("Portal not found in the list of portals");
0086       }
0087     }
0088     jVolume["portal_links"] = jPortals;
0089   } else {
0090     for (const auto& p : volume.portals()) {
0091       nlohmann::json jPortal = PortalJsonConverter::toJson(
0092           gctx, *p, detectorVolumes, options.portalOptions);
0093       jPortals.push_back(jPortal);
0094     }
0095     jVolume["portals"] = jPortals;
0096   }
0097   return jVolume;
0098 }
0099 
0100 nlohmann::json Acts::DetectorVolumeJsonConverter::toJsonDetray(
0101     const GeometryContext& gctx, const Experimental::DetectorVolume& volume,
0102     const std::vector<const Experimental::DetectorVolume*>& detectorVolumes,
0103     const Options& options) {
0104   nlohmann::json jVolume;
0105   jVolume["name"] = volume.name();
0106 
0107   // Write the transform - path them with defaults
0108   jVolume["transform"] = Transform3JsonConverter::toJson(
0109       volume.transform(gctx), options.transformOptions);
0110   jVolume["bounds"] = VolumeBoundsJsonConverter::toJson(volume.volumeBounds());
0111   auto volumeBoundsType = volume.volumeBounds().type();
0112   if (volumeBoundsType == VolumeBounds::BoundsType::eCylinder) {
0113     jVolume["type"] = 0u;
0114   } else if (volumeBoundsType == VolumeBounds::BoundsType::eCuboid) {
0115     jVolume["type"] = 4u;
0116   } else {
0117     throw std::runtime_error("Unsupported volume bounds type");
0118   }
0119 
0120   // Get the index
0121   int vIndex = findVolume(&volume, detectorVolumes);
0122   jVolume["index"] = vIndex;
0123 
0124   std::size_t sIndex = 0;
0125   // Write the surfaces - patch bounds & augment with self links
0126   nlohmann::json jSurfaces;
0127   for (const auto& s : volume.surfaces()) {
0128     auto jSurface =
0129         SurfaceJsonConverter::toJsonDetray(gctx, *s, options.surfaceOptions);
0130     DetrayJsonHelper::addVolumeLink(jSurface["mask"], vIndex);
0131     jSurface["index_in_coll"] = sIndex++;
0132     jSurfaces.push_back(jSurface);
0133   }
0134 
0135   // Create the oriented surfaces, they could potentially be one-to-one
0136   // translated
0137   auto orientedSurfaces =
0138       volume.volumeBounds().orientedSurfaces(volume.transform(gctx));
0139 
0140   // Write the portals - they will end up in the surface container
0141   for (const auto& [ip, p] : enumerate(volume.portals())) {
0142     auto jPortalSurfaces =
0143         (toJsonDetray(gctx, *p, ip, volume, orientedSurfaces, detectorVolumes,
0144                       options.portalOptions));
0145     std::for_each(jPortalSurfaces.begin(), jPortalSurfaces.end(),
0146                   [&](auto& jSurface) {
0147                     jSurface["index_in_coll"] = sIndex++;
0148                     jSurfaces.push_back(jSurface);
0149                   });
0150   }
0151   jVolume["surfaces"] = jSurfaces;
0152 
0153   return jVolume;
0154 }
0155 
0156 std::shared_ptr<Acts::Experimental::DetectorVolume>
0157 Acts::DetectorVolumeJsonConverter::fromJson(const GeometryContext& gctx,
0158                                             const nlohmann::json& jVolume) {
0159   std::string name = jVolume["name"];
0160   GeometryIdentifier geoId;
0161   geoId.setVolume(jVolume["geometryId"]);
0162   Transform3 transform =
0163       Transform3JsonConverter::fromJson(jVolume["transform"]);
0164   auto bounds = VolumeBoundsJsonConverter::fromJson(jVolume["bounds"]);
0165 
0166   auto jSurfaces = jVolume["surfaces"];
0167   auto jVolumes = jVolume["volumes"];
0168 
0169   // Some tooling
0170   auto portalGenerator = Experimental::defaultPortalGenerator();
0171 
0172   if (jSurfaces.empty() && jVolumes.empty()) {
0173     auto volume = Experimental::DetectorVolumeFactory::construct(
0174         portalGenerator, gctx, name, transform, std::move(bounds),
0175         Experimental::tryAllPortals());
0176     volume->assignGeometryId(geoId);
0177     return volume;
0178   }
0179   // Convert the surfaces
0180   std::vector<std::shared_ptr<Surface>> surfaces;
0181   for (const auto& js : jSurfaces) {
0182     surfaces.push_back(SurfaceJsonConverter::fromJson(js));
0183   }
0184   // Convert the volumes
0185   std::vector<std::shared_ptr<Experimental::DetectorVolume>> volumes;
0186   for (const auto& jv : jVolumes) {
0187     volumes.push_back(DetectorVolumeJsonConverter::fromJson(gctx, jv));
0188   }
0189 
0190   auto jSurfaceNavigation = jVolume["surface_navigation"];
0191 
0192   auto volume = Experimental::DetectorVolumeFactory::construct(
0193       portalGenerator, gctx, name, transform, std::move(bounds), surfaces,
0194       volumes, Experimental::tryRootVolumes(),
0195       IndexedSurfacesJsonConverter::fromJson(jSurfaceNavigation));
0196   volume->assignGeometryId(geoId);
0197   return volume;
0198 }