Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
MaterialJsonConverter.cpp
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file MaterialJsonConverter.cpp
1 // This file is part of the Acts project.
2 //
3 // Copyright (C) 2021 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 
25 
26 #include <algorithm>
27 #include <cstddef>
28 #include <functional>
29 #include <iosfwd>
30 #include <memory>
31 #include <stdexcept>
32 #include <string>
33 #include <tuple>
34 #include <utility>
35 #include <vector>
36 
37 void Acts::to_json(nlohmann::json& j, const Material& t) {
38  if (!t) {
39  return;
40  }
41  for (unsigned i = 0; i < t.parameters().size(); ++i) {
42  j.push_back(t.parameters()[i]);
43  }
44 }
45 
46 void Acts::from_json(const nlohmann::json& j, Material& t) {
47  if (j.is_null()) {
48  return;
49  }
51  Acts::Material::ParametersVector::Zero();
52  for (auto i = params.size(); 0 < i--;) {
53  // .at(...) ensures bound checks
54  params[i] = j.at(i);
55  }
56  t = Acts::Material(params);
57  return;
58 }
59 
60 void Acts::to_json(nlohmann::json& j, const MaterialSlab& t) {
61  nlohmann::json jmat(t.material());
62  j["material"] = jmat;
63  j["thickness"] = t.thickness();
64 }
65 
66 void Acts::from_json(const nlohmann::json& j, MaterialSlab& t) {
67  Material mat(j["material"].get<Material>());
68  t = Acts::MaterialSlab(mat, j.at("thickness").get<float>());
69 }
70 
71 void Acts::from_json(const nlohmann::json& j, MaterialSlabMatrix& t) {
72  // the input data must be array[array[object]]
73  for (auto& outer : j) {
74  Acts::MaterialSlabVector mpVector;
75  for (auto& inner : outer) {
76  MaterialSlab mat = inner.get<MaterialSlab>();
77  mpVector.emplace_back(mat);
78  }
79  t.push_back(std::move(mpVector));
80  }
81 }
82 
83 void Acts::to_json(nlohmann::json& j, const surfaceMaterialPointer& material) {
84  nlohmann::json jMaterial;
85  // A bin utility needs to be written
86  const Acts::BinUtility* bUtility = nullptr;
87  // Check if we have a proto material
88  auto psMaterial = dynamic_cast<const Acts::ProtoSurfaceMaterial*>(material);
89  if (psMaterial != nullptr) {
90  // Type is proto material
91  jMaterial[Acts::jsonKey().typekey] = "proto";
92  // Set mapping type
93  nlohmann::json mapType(material->mappingType());
94  jMaterial[Acts::jsonKey().maptype] = mapType;
95  // by default the protoMaterial is not used for mapping
96  jMaterial[Acts::jsonKey().mapkey] = false;
97  // write the bin utility
98  bUtility = &(psMaterial->binUtility());
99  // Check in the number of bin is different from 1
100  auto& binningData = bUtility->binningData();
101  for (size_t ibin = 0; ibin < binningData.size(); ++ibin) {
102  if (binningData[ibin].bins() > 1) {
103  jMaterial[Acts::jsonKey().mapkey] = true;
104  break;
105  }
106  }
107  nlohmann::json jBin(*bUtility);
108  jMaterial[Acts::jsonKey().binkey] = jBin;
109  j[Acts::jsonKey().materialkey] = jMaterial;
110  return;
111  }
112  // Now check if we have a homogeneous material
113  auto hsMaterial =
114  dynamic_cast<const Acts::HomogeneousSurfaceMaterial*>(material);
115  if (hsMaterial != nullptr) {
116  // type is homogeneous
117  jMaterial[Acts::jsonKey().typekey] = "homogeneous";
118  // Set mapping type
119  nlohmann::json mapType(material->mappingType());
120  jMaterial[Acts::jsonKey().maptype] = mapType;
121  // Material has been mapped
122  jMaterial[Acts::jsonKey().mapkey] = true;
123  nlohmann::json jmat(hsMaterial->materialSlab(0, 0));
126  jmat,
127  }),
128  });
129  j[Acts::jsonKey().materialkey] = jMaterial;
130  return;
131  }
132  // Only option remaining: BinnedSurface material
133  auto bsMaterial = dynamic_cast<const Acts::BinnedSurfaceMaterial*>(material);
134  if (bsMaterial != nullptr) {
135  // type is binned
136  jMaterial[Acts::jsonKey().typekey] = "binned";
137  // Set mapping type
138  nlohmann::json mapType(material->mappingType());
139  jMaterial[Acts::jsonKey().maptype] = mapType;
140  // Material has been mapped
141  jMaterial[Acts::jsonKey().mapkey] = true;
142  bUtility = &(bsMaterial->binUtility());
143  // convert the data
144  // get the material matrix
145  nlohmann::json mmat = nlohmann::json::array();
146  for (const auto& mpVector : bsMaterial->fullMaterial()) {
147  nlohmann::json mvec = nlohmann::json::array();
148  for (const auto& mp : mpVector) {
149  nlohmann::json jmat(mp);
150  mvec.push_back(jmat);
151  }
152  mmat.push_back(std::move(mvec));
153  }
154  jMaterial[Acts::jsonKey().datakey] = std::move(mmat);
155  // write the bin utility
156  nlohmann::json jBin(*bUtility);
157  jMaterial[Acts::jsonKey().binkey] = jBin;
158  j[Acts::jsonKey().materialkey] = jMaterial;
159  return;
160  }
161  // No material the json object is left empty.
162  return;
163 }
164 
165 void Acts::from_json(const nlohmann::json& j,
166  surfaceMaterialPointer& material) {
167  if (j.find(Acts::jsonKey().materialkey) == j.end()) {
168  return;
169  }
170  nlohmann::json jMaterial = j[Acts::jsonKey().materialkey];
171  // By default no material is return.
172  material = nullptr;
173  if (jMaterial[Acts::jsonKey().mapkey] == false) {
174  return;
175  }
176 
177  // The bin utility and material
178  Acts::BinUtility bUtility;
179  Acts::MaterialSlabMatrix mpMatrix;
181  for (auto& [key, value] : jMaterial.items()) {
182  if (key == Acts::jsonKey().binkey and not value.empty()) {
183  from_json(value, bUtility);
184  }
185  if (key == Acts::jsonKey().datakey and not value.empty()) {
186  from_json(value, mpMatrix);
187  }
188  if (key == Acts::jsonKey().maptype and not value.empty()) {
189  from_json(value, mapType);
190  }
191  }
192  // Return the appropriate typr of material
193  if (mpMatrix.empty()) {
194  material = new Acts::ProtoSurfaceMaterial(bUtility, mapType);
195  } else if (bUtility.bins() == 1) {
196  material = new Acts::HomogeneousSurfaceMaterial(mpMatrix[0][0], mapType);
197  } else {
198  material = new Acts::BinnedSurfaceMaterial(bUtility, mpMatrix, mapType);
199  }
200 }
201 
202 void Acts::to_json(nlohmann::json& j, const volumeMaterialPointer& material) {
203  nlohmann::json jMaterial;
204  // A bin utility needs to be written
205  const Acts::BinUtility* bUtility = nullptr;
206  // Check if we have a proto material
207  auto pvMaterial = dynamic_cast<const Acts::ProtoVolumeMaterial*>(material);
208  if (pvMaterial != nullptr) {
209  // Type is proto material
210  jMaterial[Acts::jsonKey().typekey] = "proto";
211  // By default the protoMaterial is not used for mapping
212  jMaterial[Acts::jsonKey().mapkey] = false;
213  bUtility = &(pvMaterial->binUtility());
214  // Check in the number of bin is different from 1
215  auto& binningData = bUtility->binningData();
216  for (size_t ibin = 0; ibin < binningData.size(); ++ibin) {
217  if (binningData[ibin].bins() > 1) {
218  jMaterial[Acts::jsonKey().mapkey] = true;
219  break;
220  }
221  }
222  // Write the bin utility
223  nlohmann::json jBin(*bUtility);
224  jMaterial[Acts::jsonKey().binkey] = jBin;
225  j[Acts::jsonKey().materialkey] = jMaterial;
226  return;
227  }
228  // Now check if we have a homogeneous material
229  auto hvMaterial =
230  dynamic_cast<const Acts::HomogeneousVolumeMaterial*>(material);
231  if (hvMaterial != nullptr) {
232  // type is homogeneous
233  jMaterial[Acts::jsonKey().typekey] = "homogeneous";
234  jMaterial[Acts::jsonKey().mapkey] = true;
235  // array of encoded materials w/ one entry
236  nlohmann::json jmat(hvMaterial->material({0, 0, 0}));
238  jmat,
239  });
240  j[Acts::jsonKey().materialkey] = jMaterial;
241  return;
242  }
243  // Only option remaining: material map
244  auto bvMaterial2D = dynamic_cast<const Acts::InterpolatedMaterialMap<
246  // Now check if we have a 2D map
247  if (bvMaterial2D != nullptr) {
248  // type is binned
249  jMaterial[Acts::jsonKey().typekey] = "interpolated2D";
250  jMaterial[Acts::jsonKey().mapkey] = true;
251  bUtility = &(bvMaterial2D->binUtility());
252  // convert the data
253  nlohmann::json mmat = nlohmann::json::array();
254  Acts::MaterialGrid2D grid = bvMaterial2D->getMapper().getGrid();
255  for (size_t bin = 0; bin < grid.size(); bin++) {
256  nlohmann::json jmat(Material(grid.at(bin)));
257  mmat.push_back(jmat);
258  }
259  jMaterial[Acts::jsonKey().datakey] = std::move(mmat);
260  // Write the bin utility
261  nlohmann::json jBin(*bUtility);
262  jMaterial[Acts::jsonKey().binkey] = jBin;
263  j[Acts::jsonKey().materialkey] = jMaterial;
264  return;
265  }
266  // Only option remaining: material map
267  auto bvMaterial3D = dynamic_cast<const Acts::InterpolatedMaterialMap<
269  // Now check if we have a 3D map
270  if (bvMaterial3D != nullptr) {
271  // type is binned
272  jMaterial[Acts::jsonKey().typekey] = "interpolated3D";
273  jMaterial[Acts::jsonKey().mapkey] = true;
274  bUtility = &(bvMaterial3D->binUtility());
275  // convert the data
276  nlohmann::json mmat = nlohmann::json::array();
277  Acts::MaterialGrid3D grid = bvMaterial3D->getMapper().getGrid();
278  for (size_t bin = 0; bin < grid.size(); bin++) {
279  nlohmann::json jmat(Material(grid.at(bin)));
280  mmat.push_back(jmat);
281  }
282  jMaterial[Acts::jsonKey().datakey] = std::move(mmat);
283  // Write the bin utility
284  nlohmann::json jBin(*bUtility);
285  jMaterial[Acts::jsonKey().binkey] = jBin;
286  j[Acts::jsonKey().materialkey] = jMaterial;
287  return;
288  }
289 }
290 
291 void Acts::from_json(const nlohmann::json& j, volumeMaterialPointer& material) {
292  if (j.find(Acts::jsonKey().materialkey) == j.end()) {
293  return;
294  }
295  nlohmann::json jMaterial = j[Acts::jsonKey().materialkey];
296  // By default no material is return.
297  material = nullptr;
298  if (jMaterial[Acts::jsonKey().mapkey] == false) {
299  return;
300  }
301  // The bin utility and material
302  Acts::BinUtility bUtility;
303  std::vector<Acts::Material> mmat;
304  for (auto& [key, value] : jMaterial.items()) {
305  if (key == Acts::jsonKey().binkey and not value.empty()) {
306  from_json(value, bUtility);
307  }
308  if (key == Acts::jsonKey().datakey and not value.empty()) {
309  for (const auto& bin : value) {
310  Acts::Material mat(bin.get<Acts::Material>());
311  mmat.push_back(mat);
312  }
313  }
314  }
315  // We have protoMaterial
316  if (mmat.empty()) {
317  material = new Acts::ProtoVolumeMaterial(bUtility);
318  return;
319  }
320  if (mmat.size() == 1) {
321  material = new Acts::HomogeneousVolumeMaterial(mmat[0]);
322  return;
323  }
324  if (bUtility.dimensions() == 2) {
325  std::function<Acts::Vector2(Acts::Vector3)> transfoGlobalToLocal;
326  Acts::Grid2D grid = createGrid2D(bUtility, transfoGlobalToLocal);
327 
329  Acts::Grid2D::point_t max = grid.maxPosition();
330  Acts::Grid2D::index_t nBins = grid.numLocalBins();
331 
332  Acts::EAxis axis1(min[0], max[0], nBins[0]);
333  Acts::EAxis axis2(min[1], max[1], nBins[1]);
334 
335  // Build the grid and fill it with data
336  Acts::MaterialGrid2D mGrid(std::make_tuple(axis1, axis2));
337 
338  for (size_t bin = 0; bin < mmat.size(); bin++) {
339  mGrid.at(bin) = mmat[bin].parameters();
340  }
341  Acts::MaterialMapper<Acts::MaterialGrid2D> matMap(transfoGlobalToLocal,
342  mGrid);
343  material = new Acts::InterpolatedMaterialMap<
345  bUtility);
346  return;
347  }
348  if (bUtility.dimensions() == 3) {
349  std::function<Acts::Vector3(Acts::Vector3)> transfoGlobalToLocal;
350  Acts::Grid3D grid = createGrid3D(bUtility, transfoGlobalToLocal);
351 
353  Acts::Grid3D::point_t max = grid.maxPosition();
354  Acts::Grid3D::index_t nBins = grid.numLocalBins();
355 
356  Acts::EAxis axis1(min[0], max[0], nBins[0]);
357  Acts::EAxis axis2(min[1], max[1], nBins[1]);
358  Acts::EAxis axis3(min[2], max[2], nBins[2]);
359 
360  // Build the grid and fill it with data
361  Acts::MaterialGrid3D mGrid(std::make_tuple(axis1, axis2, axis3));
362 
363  for (size_t bin = 0; bin < mmat.size(); bin++) {
364  mGrid.at(bin) = mmat[bin].parameters();
365  }
366  Acts::MaterialMapper<Acts::MaterialGrid3D> matMap(transfoGlobalToLocal,
367  mGrid);
368  material = new Acts::InterpolatedMaterialMap<
370  bUtility);
371  return;
372  }
373 }