Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DetectorVolumeJsonConverter.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file DetectorVolumeJsonConverter.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2023 CERN for the benefit of the Acts project
4 //
5 // This Source Code Form is subject to the terms of the Mozilla Public
6 // License, v. 2.0. If a copy of the MPL was not distributed with this
7 // file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 
10 
12 #include "Acts/Detector/Portal.hpp"
23 
24 #include <ctime>
25 
26 namespace {
27 
34 int findVolume(
36  const std::vector<const Acts::Experimental::DetectorVolume*>& volumes) {
37  auto candidate = std::find(volumes.begin(), volumes.end(), volume);
38  if (candidate != volumes.end()) {
39  return std::distance(volumes.begin(), candidate);
40  }
41  return -1;
42 }
43 } // namespace
44 
47  const std::vector<const Experimental::DetectorVolume*>& detectorVolumes,
48  const std::vector<const Experimental::Portal*>& portals,
49  const Options& options) {
50  nlohmann::json jVolume;
51  jVolume["name"] = volume.name();
52  jVolume["transform"] = Transform3JsonConverter::toJson(
53  volume.transform(gctx), options.transformOptions);
54  jVolume["bounds"] = VolumeBoundsJsonConverter::toJson(volume.volumeBounds());
55  // Write the surfaces
56  nlohmann::json jSurfaces;
57  std::for_each(
58  volume.surfaces().begin(), volume.surfaces().end(), [&](const auto& s) {
59  jSurfaces.push_back(
61  });
62  jVolume["surfaces"] = jSurfaces;
63  // And its surface navigation delegates
64  nlohmann::json jSurfacesDelegate =
66  jVolume["surface_navigation"] = jSurfacesDelegate;
67 
68  // Write the sub volumes
69  nlohmann::json jVolumes;
70  std::for_each(
71  volume.volumes().begin(), volume.volumes().end(), [&](const auto& v) {
72  jVolumes.push_back(toJson(gctx, *v, detectorVolumes, portals, options));
73  });
74  jVolume["volumes"] = jVolumes;
75 
76  // Write the portals if pre-converted as link
77  nlohmann::json jPortals;
78  if (not portals.empty()) {
79  for (const auto* p : volume.portals()) {
80  auto it = std::find(portals.begin(), portals.end(), p);
81  if (it != portals.end()) {
82  jPortals.push_back(std::distance(portals.begin(), it));
83  } else {
84  throw std::runtime_error("Portal not found in the list of portals");
85  }
86  }
87  jVolume["portal_links"] = jPortals;
88  } else {
89  for (const auto& p : volume.portals()) {
90  nlohmann::json jPortal = PortalJsonConverter::toJson(
91  gctx, *p, detectorVolumes, options.portalOptions);
92  jPortals.push_back(jPortal);
93  }
94  jVolume["portals"] = jPortals;
95  }
96  return jVolume;
97 }
98 
100  const GeometryContext& gctx, const Experimental::DetectorVolume& volume,
101  const std::vector<const Experimental::DetectorVolume*>& detectorVolumes,
102  const Options& options) {
103  nlohmann::json jVolume;
104  jVolume["name"] = volume.name();
105 
106  // Write the transform - path them with defaults
107  jVolume["transform"] = Transform3JsonConverter::toJson(
108  volume.transform(gctx), options.transformOptions);
109  jVolume["bounds"] = VolumeBoundsJsonConverter::toJson(volume.volumeBounds());
110  auto volumeBoundsType = volume.volumeBounds().type();
111  if (volumeBoundsType == VolumeBounds::BoundsType::eCylinder) {
112  jVolume["type"] = 0u;
113  } else if (volumeBoundsType == VolumeBounds::BoundsType::eCuboid) {
114  jVolume["type"] = 4u;
115  } else {
116  throw std::runtime_error("Unsupported volume bounds type");
117  }
118 
119  // Get the index
120  int vIndex = findVolume(&volume, detectorVolumes);
121  jVolume["index"] = vIndex;
122 
123  // Write the surfaces - patch bounds & augment with self links
124  nlohmann::json jSurfaces;
125  for (const auto& s : volume.surfaces()) {
126  auto jSurface =
128  DetrayJsonHelper::addVolumeLink(jSurface["mask"], vIndex);
129  jSurfaces.push_back(jSurface);
130  }
131 
132  // Create the oriented surfaces, they could potentially be one-to-one
133  // translated
134  auto orientedSurfaces =
135  volume.volumeBounds().orientedSurfaces(volume.transform(gctx));
136 
137  // Write the portals - they will end up in the surface container
138  for (const auto& [ip, p] : enumerate(volume.portals())) {
139  auto jPortalSurfaces =
140  (toJsonDetray(gctx, *p, ip, volume, orientedSurfaces, detectorVolumes,
141  options.portalOptions));
142  std::for_each(jPortalSurfaces.begin(), jPortalSurfaces.end(),
143  [&](auto& jSurface) { jSurfaces.push_back(jSurface); });
144  }
145  jVolume["surfaces"] = jSurfaces;
146 
147  return jVolume;
148 }
149 
150 std::shared_ptr<Acts::Experimental::DetectorVolume>
152  const nlohmann::json& jVolume) {
153  std::string name = jVolume["name"];
155  Transform3JsonConverter::fromJson(jVolume["transform"]);
156  auto bounds = VolumeBoundsJsonConverter::fromJson(jVolume["bounds"]);
157 
158  auto jSurfaces = jVolume["surfaces"];
159  auto jVolumes = jVolume["volumes"];
160 
161  // Some tooling
163 
164  if (jSurfaces.empty() and jVolumes.empty()) {
165  return Experimental::DetectorVolumeFactory::construct(
166  portalGenerator, gctx, name, transform, std::move(bounds),
168  }
169  // Convert the surfaces
170  std::vector<std::shared_ptr<Surface>> surfaces;
171  for (const auto& js : jSurfaces) {
172  surfaces.push_back(SurfaceJsonConverter::fromJson(js));
173  }
174  // Convert the volumes
175  std::vector<std::shared_ptr<Experimental::DetectorVolume>> volumes;
176  for (const auto& jv : jVolumes) {
177  volumes.push_back(DetectorVolumeJsonConverter::fromJson(gctx, jv));
178  }
179 
180  auto jSurfaceNavigation = jVolume["surface_navigation"];
181 
182  return Experimental::DetectorVolumeFactory::construct(
183  portalGenerator, gctx, name, transform, std::move(bounds), surfaces,
184  volumes, Experimental::tryRootVolumes(),
185  IndexedSurfacesJsonConverter::fromJson(jSurfaceNavigation));
186 }