File indexing completed on 2025-01-30 09:15:17
0001
0002
0003
0004
0005
0006
0007
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
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
0055 nlohmann::json jData;
0056 jData["name"] = detector.name();
0057
0058
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
0070
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
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
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
0115
0116 nlohmann::json jGeometry;
0117 nlohmann::json jGeometryData;
0118 nlohmann::json jGeometryHeader;
0119 nlohmann::json jGeometryVolumes;
0120
0121 nlohmann::json jSurfaceGrids;
0122 nlohmann::json jSurfaceGridsData;
0123 nlohmann::json jSurfaceGridsInfoCollection;
0124 nlohmann::json jSurfaceGridsHeader;
0125
0126 nlohmann::json jMaterial;
0127 nlohmann::json jMaterialData;
0128 nlohmann::json jMaterialHeader;
0129 nlohmann::json jMaterialGrids;
0130
0131
0132 std::size_t nSurfaces = 0;
0133 std::size_t nGrids = 0;
0134
0135
0136 for (auto [iv, volume] : enumerate(detector.volumes())) {
0137
0138 nlohmann::json jVolume;
0139 jVolume["name"] = volume->name();
0140
0141
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
0155 jVolume["index"] = iv;
0156
0157
0158 nlohmann::json jSurfacesDelegate = IndexedSurfacesJsonConverter::toJson(
0159 volume->internalNavigation(), true);
0160 if (!jSurfacesDelegate.is_null()) {
0161
0162 jSurfacesDelegate["owner_link"] = iv;
0163
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
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
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
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
0202 auto orientedSurfaces =
0203 volume->volumeBounds().orientedSurfaces(volume->transform(gctx));
0204
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
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
0229 if (!jMaterialVolumeGridsData.empty()) {
0230 jMaterialVolumeGrids["grid_data"] = {jMaterialVolumeGridsData};
0231 jMaterialGrids.push_back(jMaterialVolumeGrids);
0232 }
0233
0234
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
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
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
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
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
0297 for (auto [iv, v] : enumerate(volumes)) {
0298
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 }