Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
DetectorVolumeJsonConverterTests.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file DetectorVolumeJsonConverterTests.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 
9 #include <boost/test/unit_test.hpp>
10 
26 
27 #include <fstream>
28 #include <memory>
29 #include <vector>
30 
31 #include <nlohmann/json.hpp>
32 
33 namespace {
37 std::vector<std::shared_ptr<Acts::Surface>> unpackSurfaces(
38  const std::vector<const Acts::Surface*>& surfaces) {
39  std::vector<std::shared_ptr<Acts::Surface>> uSurfaces;
40  uSurfaces.reserve(surfaces.size());
41  for (const auto s : surfaces) {
42  auto* ncs = const_cast<Acts::Surface*>(s);
43  uSurfaces.push_back(ncs->getSharedPtr());
44  }
45  return uSurfaces;
46 }
47 
48 } // namespace
49 
52 
54 
55 BOOST_AUTO_TEST_SUITE(DetectorVolumeJsonConverter)
56 
57 BOOST_AUTO_TEST_CASE(SingleEmptyVolume) {
58  // Create a single cylindrical volume
59  Acts::Transform3 nominal = Acts::Transform3::Identity();
60  auto bounds = std::make_unique<Acts::CylinderVolumeBounds>(0., 50., 100.);
61 
63  portalGenerator, tContext, "EmptyVolume", nominal, std::move(bounds),
65 
66  std::ofstream out;
67 
68  auto jVolume = Acts::DetectorVolumeJsonConverter::toJson(tContext, *volume,
69  {volume.get()});
70 
71  out.open("single-empty-volume.json");
72  out << jVolume.dump(4);
73  out.close();
74 
75  auto in = std::ifstream("single-empty-volume.json",
76  std::ifstream::in | std::ifstream::binary);
77 
78  BOOST_CHECK(in.good());
79  nlohmann::json jVolumeIn;
80  in >> jVolumeIn;
81  in.close();
82 
83  auto volumeIn =
85 
86  BOOST_CHECK(volumeIn->name() == volume->name());
87  BOOST_CHECK(
88  volumeIn->transform(tContext).isApprox(volume->transform(tContext)));
89  BOOST_CHECK(volumeIn->surfaces().size() == volume->surfaces().size());
90  BOOST_CHECK(volumeIn->volumes().size() == volume->volumes().size());
91 
92  // Detray format test - manipulate for detray
94  detrayOptions.transformOptions.writeIdentity = true;
95  detrayOptions.transformOptions.transpose = true;
96  detrayOptions.surfaceOptions.transformOptions =
97  detrayOptions.transformOptions;
98  detrayOptions.portalOptions.surfaceOptions = detrayOptions.surfaceOptions;
99 
101  tContext, *volume, {volume.get()}, detrayOptions);
102 
103  out.open("single-empty-volume-detray.json");
104  out << jVolumeDetray.dump(4);
105  out.close();
106 }
107 
108 BOOST_AUTO_TEST_CASE(SingleSurfaceVolume) {
109  // Create a single cylindrical volume
110  Acts::Transform3 nominal = Acts::Transform3::Identity();
111  auto volumeBounds =
112  std::make_unique<Acts::CylinderVolumeBounds>(0., 50., 100.);
113  auto surfaceBounds = std::make_unique<Acts::CylinderBounds>(25., 100.);
114 
115  auto cylinderSurface = Acts::Surface::makeShared<Acts::CylinderSurface>(
116  nominal, std::move(surfaceBounds));
117 
119  portalGenerator, tContext, "CylinderVolume", nominal,
120  std::move(volumeBounds), {cylinderSurface}, {},
123 
124  std::ofstream out;
125 
126  auto jVolume = Acts::DetectorVolumeJsonConverter::toJson(tContext, *volume,
127  {volume.get()});
128 
129  out.open("single-surface-volume.json");
130  out << jVolume.dump(4);
131  out.close();
132 
133  auto in = std::ifstream("single-surface-volume.json",
134  std::ifstream::in | std::ifstream::binary);
135 
136  BOOST_CHECK(in.good());
137  nlohmann::json jVolumeIn;
138  in >> jVolumeIn;
139  in.close();
140 
141  auto volumeIn =
142  Acts::DetectorVolumeJsonConverter::fromJson(tContext, jVolumeIn);
143 
144  BOOST_CHECK(volumeIn->name() == volume->name());
145  BOOST_CHECK(
146  volumeIn->transform(tContext).isApprox(volume->transform(tContext)));
147  BOOST_CHECK(volumeIn->surfaces().size() == volume->surfaces().size());
148  BOOST_CHECK(volumeIn->volumes().size() == volume->volumes().size());
149 }
150 
151 BOOST_AUTO_TEST_CASE(EndcapVolumeWithSurfaces) {
153 
154  auto rSurfaces = cGeometry.surfacesRing(dStore, 6.4, 12.4, 36., 0.125, 0.,
155  55., -800, 2., 22u);
156 
157  auto endcapSurfaces = std::make_shared<
159  unpackSurfaces(rSurfaces));
160  // Configure the layer structure builder
162  lsConfig.auxiliary = "*** Endcap with 22 surfaces ***";
163  lsConfig.surfacesProvider = endcapSurfaces;
164  lsConfig.binnings = {Acts::Experimental::ProtoBinning(
165  Acts::binPhi, Acts::detail::AxisBoundaryType::Closed, -M_PI, M_PI, 22u,
166  1u)};
167 
168  auto layerBuilder =
169  std::make_shared<Acts::Experimental::LayerStructureBuilder>(
170  lsConfig, Acts::getDefaultLogger("EndcapInteralsBuilder",
172 
174  shapeConfig.boundValues = {10, 100, 10., M_PI, 0.};
175  shapeConfig.transform = Acts::Transform3(Acts::Transform3::Identity())
176  .pretranslate(Acts::Vector3(0., 0., -800.));
177  shapeConfig.boundsType = Acts::VolumeBounds::BoundsType::eCylinder;
178 
179  auto shapeBuilder =
180  std::make_shared<Acts::Experimental::VolumeStructureBuilder>(
181  shapeConfig,
182  Acts::getDefaultLogger("EndcapShapeBuilder", Acts::Logging::VERBOSE));
183 
185  dvCfg.auxiliary = "*** Test 1 - Cylinder with internal Surface ***";
186  dvCfg.name = "CylinderWithSurface";
187  dvCfg.externalsBuilder = shapeBuilder;
188  dvCfg.internalsBuilder = layerBuilder;
189 
190  auto dvBuilder = std::make_shared<Acts::Experimental::DetectorVolumeBuilder>(
191  dvCfg, Acts::getDefaultLogger("EndcapBuilder", Acts::Logging::VERBOSE));
192 
193  auto [volumes, portals, roots] = dvBuilder->construct(tContext);
194  auto volume = volumes.front();
195 
196  auto jVolume = Acts::DetectorVolumeJsonConverter::toJson(tContext, *volume,
197  {volume.get()});
198 
199  std::ofstream out;
200  out.open("endcap-volume-with-surfaces.json");
201  out << jVolume.dump(4);
202  out.close();
203 
204  auto in = std::ifstream("endcap-volume-with-surfaces.json",
205  std::ifstream::in | std::ifstream::binary);
206 
207  BOOST_CHECK(in.good());
208  nlohmann::json jVolumeIn;
209  in >> jVolumeIn;
210  in.close();
211 
212  auto volumeIn =
213  Acts::DetectorVolumeJsonConverter::fromJson(tContext, jVolumeIn);
214 
215  BOOST_CHECK(volumeIn->name() == volume->name());
216  BOOST_CHECK(
217  volumeIn->transform(tContext).isApprox(volume->transform(tContext)));
218  BOOST_CHECK(volumeIn->surfaces().size() == volume->surfaces().size());
219  BOOST_CHECK(volumeIn->volumes().size() == volume->volumes().size());
220 
221  // Cross-check writing
222  jVolume = Acts::DetectorVolumeJsonConverter::toJson(tContext, *volumeIn,
223  {volumeIn.get()});
224  out.open("endcap-volume-with-surfaces-closure.json");
225  out << jVolume.dump(4);
226  out.close();
227 }
228 
229 BOOST_AUTO_TEST_CASE(BarrelVolumeWithSurfaces) {
231  auto cSurfaces = cGeometry.surfacesCylinder(dStore, 8.4, 36., 0.15, 0.145, 72,
232  3., 2., {32u, 14u});
233 
234  auto barrelSurfaces = std::make_shared<
236  unpackSurfaces(cSurfaces));
237 
238  // Configure the layer structure builder
240  lsConfig.auxiliary = "*** Barrel with 448 surfaces ***";
241  lsConfig.surfacesProvider = barrelSurfaces;
242  lsConfig.binnings = {Acts::Experimental::ProtoBinning{
243  Acts::binZ, Acts::detail::AxisBoundaryType::Bound,
244  -480., 480., 14u, 1u},
246  Acts::binPhi, Acts::detail::AxisBoundaryType::Closed,
247  -M_PI, M_PI, 32u, 1u)};
248 
249  auto barrelBuilder =
250  std::make_shared<Acts::Experimental::LayerStructureBuilder>(
251  lsConfig, Acts::getDefaultLogger("BarrelInternalsBuilder",
253 
255  shapeConfig.boundValues = {60., 80., 800., M_PI, 0.};
256  shapeConfig.boundsType = Acts::VolumeBounds::BoundsType::eCylinder;
257 
258  auto shapeBuilder =
259  std::make_shared<Acts::Experimental::VolumeStructureBuilder>(
260  shapeConfig,
261  Acts::getDefaultLogger("BarrelShapeBuilder", Acts::Logging::VERBOSE));
262 
264  dvCfg.auxiliary = "*** Test 1 - Cylinder with internal Surface ***";
265  dvCfg.name = "BarrelWithSurfaces";
266  dvCfg.externalsBuilder = shapeBuilder;
267  dvCfg.internalsBuilder = barrelBuilder;
268 
269  auto dvBuilder = std::make_shared<Acts::Experimental::DetectorVolumeBuilder>(
270  dvCfg, Acts::getDefaultLogger("EndcapBuilder", Acts::Logging::VERBOSE));
271 
272  auto [volumes, portals, roots] = dvBuilder->construct(tContext);
273 
274  auto volume = volumes.front();
275 
276  auto jVolume = Acts::DetectorVolumeJsonConverter::toJson(tContext, *volume,
277  {volume.get()});
278 
279  std::ofstream out;
280  out.open("barrel-volume-with-surfaces.json");
281  out << jVolume.dump(4);
282  out.close();
283 
284  auto in = std::ifstream("barrel-volume-with-surfaces.json",
285  std::ifstream::in | std::ifstream::binary);
286 
287  BOOST_CHECK(in.good());
288  nlohmann::json jVolumeIn;
289  in >> jVolumeIn;
290  in.close();
291 
292  auto volumeIn =
293  Acts::DetectorVolumeJsonConverter::fromJson(tContext, jVolumeIn);
294 
295  BOOST_CHECK(volumeIn->name() == volume->name());
296  BOOST_CHECK(
297  volumeIn->transform(tContext).isApprox(volume->transform(tContext)));
298  BOOST_CHECK(volumeIn->surfaces().size() == volume->surfaces().size());
299  BOOST_CHECK(volumeIn->volumes().size() == volume->volumes().size());
300 
301  // Cross-check writing
302  jVolume = Acts::DetectorVolumeJsonConverter::toJson(tContext, *volumeIn,
303  {volumeIn.get()});
304  out.open("barrel-volume-with-surfaces-closure.json");
305  out << jVolume.dump(4);
306  out.close();
307 }
308 
309 BOOST_AUTO_TEST_SUITE_END()