Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-30 09:15:17

0001 // This file is part of the ACTS project.
0002 //
0003 // Copyright (C) 2016 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 https://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/MaterialJsonConverter.hpp"
0020 #include "Acts/Plugins/Json/PortalJsonConverter.hpp"
0021 #include "Acts/Plugins/Json/VolumeBoundsJsonConverter.hpp"
0022 #include "Acts/Utilities/Enumerate.hpp"
0023 #include "Acts/Utilities/Helpers.hpp"
0024 
0025 #include <algorithm>
0026 #include <ctime>
0027 #include <map>
0028 #include <memory>
0029 #include <set>
0030 #include <string>
0031 
0032 nlohmann::json Acts::DetectorJsonConverter::toJson(
0033     const GeometryContext& gctx, const Experimental::Detector& detector,
0034     const Options& options) {
0035   // Get the time stamp
0036   std::time_t tt = 0;
0037   std::time(&tt);
0038   auto ti = std::localtime(&tt);
0039 
0040   nlohmann::json jDetector;
0041 
0042   std::size_t nSurfaces = 0;
0043   std::vector<const Experimental::Portal*> portals;
0044 
0045   for (const auto* volume : detector.volumes()) {
0046     nSurfaces += volume->surfaces().size();
0047     for (const auto& portal : volume->portals()) {
0048       if (!rangeContainsValue(portals, portal)) {
0049         portals.push_back(portal);
0050       }
0051     }
0052   }
0053 
0054   // Write the actual data objects
0055   nlohmann::json jData;
0056   jData["name"] = detector.name();
0057 
0058   // The portals are written first
0059   auto volumes = detector.volumes();
0060   nlohmann::json jPortals;
0061 
0062   for (const auto& portal : portals) {
0063     auto jPortal = PortalJsonConverter::toJson(
0064         gctx, *portal, volumes, options.volumeOptions.portalOptions);
0065     jPortals.push_back(jPortal);
0066   }
0067   jData["portals"] = jPortals;
0068 
0069   // The volumes are written next, with portals already defined, the volumes
0070   // will only index those
0071   nlohmann::json jVolumes;
0072   for (const auto& volume : volumes) {
0073     auto jVolume = DetectorVolumeJsonConverter::toJson(
0074         gctx, *volume, volumes, portals, options.volumeOptions);
0075     jVolumes.push_back(jVolume);
0076   }
0077   jData["volumes"] = jVolumes;
0078   jData["volume_finder"] = DetectorVolumeFinderJsonConverter::toJson(
0079       detector.detectorVolumeFinder());
0080 
0081   // Write the header
0082   nlohmann::json jHeader;
0083   jHeader["detector"] = detector.name();
0084   jHeader["type"] = "acts";
0085   char buffer[100];
0086   strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", ti);
0087   jHeader["date"] = std::string(buffer);
0088   jHeader["surface_count"] = nSurfaces;
0089   jHeader["portal_count"] = portals.size();
0090   jHeader["volume_count"] = detector.volumes().size();
0091   jDetector["header"] = jHeader;
0092   jDetector["data"] = jData;
0093   return jDetector;
0094 }
0095 
0096 nlohmann::json Acts::DetectorJsonConverter::toJsonDetray(
0097     const GeometryContext& gctx, const Experimental::Detector& detector,
0098     const Options& options) {
0099   // Get the time stamp
0100   std::time_t tt = 0;
0101   std::time(&tt);
0102   auto ti = std::localtime(&tt);
0103 
0104   nlohmann::json jFile;
0105 
0106   nlohmann::json jCommonHeader;
0107   jCommonHeader["detector"] = detector.name();
0108   char buffer[100];
0109   strftime(buffer, sizeof(buffer), "%Y-%m-%d %H:%M:%S", ti);
0110   jCommonHeader["date"] = std::string(buffer);
0111   jCommonHeader["version"] = "detray - 0.44.0";
0112   jCommonHeader["tag"] = "geometry";
0113 
0114   // Three sub sections are created
0115   // (1) Geometry
0116   nlohmann::json jGeometry;
0117   nlohmann::json jGeometryData;
0118   nlohmann::json jGeometryHeader;
0119   nlohmann::json jGeometryVolumes;
0120   // (2) Surface grids
0121   nlohmann::json jSurfaceGrids;
0122   nlohmann::json jSurfaceGridsData;
0123   nlohmann::json jSurfaceGridsInfoCollection;
0124   nlohmann::json jSurfaceGridsHeader;
0125   // (3) Material
0126   nlohmann::json jMaterial;
0127   nlohmann::json jMaterialData;
0128   nlohmann::json jMaterialHeader;
0129   nlohmann::json jMaterialGrids;
0130 
0131   // Counters:
0132   std::size_t nSurfaces = 0;
0133   std::size_t nGrids = 0;
0134 
0135   // Main loop over volumes
0136   for (auto [iv, volume] : enumerate(detector.volumes())) {
0137     // Write the volume information
0138     nlohmann::json jVolume;
0139     jVolume["name"] = volume->name();
0140 
0141     // Write the transform and bounds information
0142     jVolume["transform"] = Transform3JsonConverter::toJson(
0143         volume->transform(gctx), options.volumeOptions.transformOptions);
0144     jVolume["bounds"] =
0145         VolumeBoundsJsonConverter::toJson(volume->volumeBounds());
0146     auto volumeBoundsType = volume->volumeBounds().type();
0147     if (volumeBoundsType == VolumeBounds::BoundsType::eCylinder) {
0148       jVolume["type"] = 0u;
0149     } else if (volumeBoundsType == VolumeBounds::BoundsType::eCuboid) {
0150       jVolume["type"] = 4u;
0151     } else {
0152       throw std::runtime_error("Unsupported volume bounds type");
0153     }
0154     // Link to itself
0155     jVolume["index"] = iv;
0156 
0157     // Acceleration link if there
0158     nlohmann::json jSurfacesDelegate = IndexedSurfacesJsonConverter::toJson(
0159         volume->internalNavigation(), true);
0160     if (!jSurfacesDelegate.is_null()) {
0161       // Colplete the grid json for detray usage
0162       jSurfacesDelegate["owner_link"] = iv;
0163       // jSurfacesDelegate["acc_link"] =
0164       nlohmann::json jSurfaceGridsCollection;
0165       jSurfaceGridsCollection.push_back(jSurfacesDelegate);
0166 
0167       nlohmann::json jSurfaceGridsInfo;
0168       jSurfaceGridsInfo["volume_link"] = iv;
0169       jSurfaceGridsInfo["grid_data"] = jSurfaceGridsCollection;
0170       jSurfaceGridsInfoCollection.push_back(jSurfaceGridsInfo);
0171     }
0172 
0173     // Grids per volume
0174     nlohmann::json jMaterialVolumeGrids;
0175     nlohmann::json jMaterialVolumeGridsData;
0176     jMaterialVolumeGrids["volume_link"] = iv;
0177     std::map<std::size_t, std::size_t> gridLinks;
0178 
0179     // Write the surfaces - patch bounds & augment with self links
0180     std::size_t sIndex = 0;
0181     nlohmann::json jSurfaces;
0182     for (const auto& s : volume->surfaces()) {
0183       auto jSurface = SurfaceJsonConverter::toJsonDetray(
0184           gctx, *s, options.volumeOptions.surfaceOptions);
0185       DetrayJsonHelper::addVolumeLink(jSurface["mask"], iv);
0186       jSurface["index_in_coll"] = sIndex;
0187       jSurfaces.push_back(jSurface);
0188 
0189       // Check for material
0190       if (s->surfaceMaterial() != nullptr) {
0191         nlohmann::json jSurfaceMaterial = MaterialJsonConverter::toJsonDetray(
0192             *s->surfaceMaterial(), *s, sIndex, gridLinks);
0193         if (!jSurfaceMaterial.empty()) {
0194           ++nGrids;
0195           jMaterialVolumeGridsData.push_back(jSurfaceMaterial);
0196         }
0197       }
0198       ++sIndex;
0199     }
0200 
0201     // Write the portals - we need oriented surfaces for this
0202     auto orientedSurfaces =
0203         volume->volumeBounds().orientedSurfaces(volume->transform(gctx));
0204     // Write the portals - they will end up in the surface container
0205     for (const auto& [ip, p] : enumerate(volume->portals())) {
0206       auto [jPortalSurfaces, portalSubSplits] = (toJsonDetray(
0207           gctx, *p, ip, *volume, orientedSurfaces, detector.volumes(),
0208           options.volumeOptions.portalOptions));
0209       std::size_t splitSurfaceIdx = 0;
0210       for (auto& jSurface : jPortalSurfaces) {
0211         jSurface["index_in_coll"] = sIndex;
0212         jSurfaces.push_back(jSurface);
0213         const Surface* pSurface =
0214             portalSubSplits.empty() ? (&p->surface())
0215                                     : portalSubSplits[splitSurfaceIdx++].get();
0216         // Check for material
0217         if (p->surface().surfaceMaterial() != nullptr) {
0218           nlohmann::json jSurfaceMaterial = MaterialJsonConverter::toJsonDetray(
0219               *p->surface().surfaceMaterial(), *pSurface, sIndex, gridLinks);
0220           if (!jSurfaceMaterial.empty()) {
0221             ++nGrids;
0222             jMaterialVolumeGridsData.push_back(jSurfaceMaterial);
0223           }
0224         }
0225         ++sIndex;
0226       }
0227     }
0228     // If material was found, keep it
0229     if (!jMaterialVolumeGridsData.empty()) {
0230       jMaterialVolumeGrids["grid_data"] = {jMaterialVolumeGridsData};
0231       jMaterialGrids.push_back(jMaterialVolumeGrids);
0232     }
0233 
0234     // Surfaces go into the volume
0235     jVolume["surfaces"] = jSurfaces;
0236     nSurfaces += jSurfaces.size();
0237     jGeometryVolumes.push_back(jVolume);
0238   }
0239 
0240   jGeometryData["volumes"] = jGeometryVolumes;
0241   jGeometryData["volume_grid"] = DetectorVolumeFinderJsonConverter::toJson(
0242       detector.detectorVolumeFinder(), true);
0243 
0244   // Collect it (1) - Geometry
0245   jGeometryHeader["type"] = "detray";
0246   jGeometryHeader["common"] = jCommonHeader;
0247   jGeometryHeader["surface_count"] = nSurfaces;
0248   jGeometryHeader["volume_count"] = detector.volumes().size();
0249   jGeometry["header"] = jGeometryHeader;
0250   jGeometry["data"] = jGeometryData;
0251   jFile["geometry"] = jGeometry;
0252 
0253   // Collect it (2) - Grid
0254   jCommonHeader["tag"] = "surface_grids";
0255   jSurfaceGridsHeader["common"] = jCommonHeader;
0256   jSurfaceGridsData["grids"] = jSurfaceGridsInfoCollection;
0257   jSurfaceGridsHeader["grid_count"] = jSurfaceGridsInfoCollection.size();
0258   jSurfaceGrids["header"] = jSurfaceGridsHeader;
0259   jSurfaceGrids["data"] = jSurfaceGridsData;
0260   jFile["surface_grids"] = jSurfaceGrids;
0261 
0262   // Collect it (3) - Material
0263   jCommonHeader["tag"] = "material_maps";
0264   jMaterialHeader["common"] = jCommonHeader;
0265   jMaterialData["grids"] = jMaterialGrids;
0266   jMaterialHeader["grid_count"] = nGrids;
0267   jMaterial["header"] = jMaterialHeader;
0268   jMaterial["data"] = jMaterialData;
0269   jFile["material"] = jMaterial;
0270 
0271   return jFile;
0272 }
0273 
0274 std::shared_ptr<Acts::Experimental::Detector>
0275 Acts::DetectorJsonConverter::fromJson(const GeometryContext& gctx,
0276                                       const nlohmann::json& jDetector) {
0277   // Read back all the data
0278   auto jData = jDetector["data"];
0279   auto jVolumes = jData["volumes"];
0280   auto jPortals = jData["portals"];
0281   const std::string name = jData["name"];
0282 
0283   std::vector<std::shared_ptr<Experimental::DetectorVolume>> volumes;
0284   std::vector<std::shared_ptr<Experimental::Portal>> portals;
0285 
0286   for (const auto& jVolume : jVolumes) {
0287     auto volume = DetectorVolumeJsonConverter::fromJson(gctx, jVolume);
0288     volumes.push_back(volume);
0289   }
0290 
0291   for (const auto& jPortal : jPortals) {
0292     auto portal = PortalJsonConverter::fromJson(gctx, jPortal, volumes);
0293     portals.push_back(portal);
0294   }
0295 
0296   // Patch all the portals of the volumes
0297   for (auto [iv, v] : enumerate(volumes)) {
0298     // Get the Volumes and update the portals with the loaded ones
0299     auto jVolume = jVolumes[iv];
0300     std::vector<std::size_t> portalLinks = jVolume["portal_links"];
0301     for (auto [ip, ipl] : enumerate(portalLinks)) {
0302       auto portal = portals[ipl];
0303       v->updatePortal(portal, ip);
0304     }
0305   }
0306   return Experimental::Detector::makeShared(name, volumes,
0307                                             Experimental::tryRootVolumes());
0308 }