File indexing completed on 2025-06-30 07:53:01
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "Acts/Plugins/Json/MaterialJsonConverter.hpp"
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Geometry/GeometryContext.hpp"
0013 #include "Acts/Material/BinnedSurfaceMaterial.hpp"
0014 #include "Acts/Material/GridSurfaceMaterial.hpp"
0015 #include "Acts/Material/HomogeneousSurfaceMaterial.hpp"
0016 #include "Acts/Material/HomogeneousVolumeMaterial.hpp"
0017 #include "Acts/Material/ISurfaceMaterial.hpp"
0018 #include "Acts/Material/IVolumeMaterial.hpp"
0019 #include "Acts/Material/InterpolatedMaterialMap.hpp"
0020 #include "Acts/Material/MaterialGridHelper.hpp"
0021 #include "Acts/Material/MaterialSlab.hpp"
0022 #include "Acts/Material/ProtoSurfaceMaterial.hpp"
0023 #include "Acts/Material/ProtoVolumeMaterial.hpp"
0024 #include "Acts/Plugins/Json/GeometryJsonKeys.hpp"
0025 #include "Acts/Plugins/Json/GridJsonConverter.hpp"
0026 #include "Acts/Plugins/Json/UtilitiesJsonConverter.hpp"
0027 #include "Acts/Surfaces/Surface.hpp"
0028 #include "Acts/Utilities/BinUtility.hpp"
0029 #include "Acts/Utilities/Grid.hpp"
0030 #include "Acts/Utilities/GridAxisGenerators.hpp"
0031 #include "Acts/Utilities/TypeList.hpp"
0032
0033 #include <algorithm>
0034 #include <cstddef>
0035 #include <functional>
0036 #include <numbers>
0037 #include <stdexcept>
0038 #include <string>
0039 #include <tuple>
0040 #include <utility>
0041 #include <vector>
0042
0043 namespace {
0044
0045
0046 template <typename value_type>
0047 using GridEqBound =
0048 Acts::Grid<value_type, Acts::Axis<Acts::AxisType::Equidistant,
0049 Acts::AxisBoundaryType::Bound>>;
0050
0051 template <typename value_type>
0052 using GridEqClosed =
0053 Acts::Grid<value_type, Acts::Axis<Acts::AxisType::Equidistant,
0054 Acts::AxisBoundaryType::Closed>>;
0055
0056
0057 template <typename value_type>
0058 using GridEqBoundEqBound = Acts::Grid<
0059 value_type,
0060 Acts::Axis<Acts::AxisType::Equidistant, Acts::AxisBoundaryType::Bound>,
0061 Acts::Axis<Acts::AxisType::Equidistant, Acts::AxisBoundaryType::Bound>>;
0062
0063
0064 template <typename value_type>
0065 using GridEqBoundEqClosed = Acts::Grid<
0066 value_type,
0067 Acts::Axis<Acts::AxisType::Equidistant, Acts::AxisBoundaryType::Bound>,
0068 Acts::Axis<Acts::AxisType::Equidistant, Acts::AxisBoundaryType::Closed>>;
0069
0070
0071 template <typename value_type>
0072 using GridEqClosedEqBound = Acts::Grid<
0073 value_type,
0074 Acts::Axis<Acts::AxisType::Equidistant, Acts::AxisBoundaryType::Closed>,
0075 Acts::Axis<Acts::AxisType::Equidistant, Acts::AxisBoundaryType::Bound>>;
0076
0077
0078
0079
0080
0081
0082 template <typename indexed_grid_materital_t>
0083 void convertIndexedGridMaterial(
0084 nlohmann::json& jMaterial,
0085 const Acts::ISurfaceMaterial& indexedMaterialCandidate) {
0086
0087 const indexed_grid_materital_t* indexedMaterial =
0088 dynamic_cast<const indexed_grid_materital_t*>(&indexedMaterialCandidate);
0089
0090 if (indexedMaterial != nullptr) {
0091
0092 jMaterial[Acts::jsonKey().typekey] = "grid";
0093 nlohmann::json jMaterialAccessor;
0094
0095 jMaterialAccessor["type"] = "globally_indexed";
0096
0097
0098
0099 const auto& materialAccessor = indexedMaterial->materialAccessor();
0100
0101 if constexpr (std::is_same_v<decltype(materialAccessor),
0102 const Acts::IndexedMaterialAccessor&>) {
0103
0104 jMaterialAccessor["type"] = "indexed";
0105
0106 nlohmann::json jMaterialData;
0107 for (const auto& msl : materialAccessor.material) {
0108 jMaterialData.push_back(msl);
0109 }
0110 jMaterialAccessor["storage_vector"] = jMaterialData;
0111 }
0112
0113 jMaterialAccessor["grid"] =
0114 Acts::GridJsonConverter::toJson(indexedMaterial->grid());
0115 jMaterial["accessor"] = jMaterialAccessor;
0116
0117
0118 jMaterial["global_to_grid_local"] = Acts::GridAccessJsonConverter::toJson(
0119 *(indexedMaterial->globalToGridLocalDelegate().instance()));
0120
0121 jMaterial["bound_to_grid_local"] = Acts::GridAccessJsonConverter::toJson(
0122 *(indexedMaterial->boundToGridLocalDelegate().instance()));
0123 }
0124 }
0125
0126
0127
0128
0129
0130 template <typename... Args>
0131 void unrollIndexedGridConversion(nlohmann::json& jMaterial,
0132 const Acts::ISurfaceMaterial& indexedMaterial,
0133 Acts::TypeList<Args...> ) {
0134 (convertIndexedGridMaterial<Args>(jMaterial, indexedMaterial), ...);
0135 }
0136
0137 template <typename IndexedAccessorType>
0138 Acts::ISurfaceMaterial* indexedMaterialFromJson(nlohmann::json& jMaterial) {
0139
0140 nlohmann::json jMaterialAccessor = jMaterial["accessor"];
0141
0142
0143 IndexedAccessorType materialAccessor(std::vector<Acts::MaterialSlab>{});
0144
0145
0146 if constexpr (std::is_same_v<IndexedAccessorType,
0147 Acts::IndexedMaterialAccessor>) {
0148
0149 for (const auto& msl : jMaterialAccessor["storage_vector"]) {
0150 Acts::MaterialSlab mat = Acts::MaterialSlab::Nothing();
0151 from_json(msl, mat);
0152 materialAccessor.material.push_back(mat);
0153 }
0154 }
0155
0156
0157 nlohmann::json jGrid = jMaterialAccessor["grid"];
0158 nlohmann::json jGridAxes = jGrid["axes"];
0159
0160 Acts::AxisBoundaryType boundaryType0 = jGridAxes[0]["boundary_type"];
0161
0162
0163 if (jGridAxes.size() == 1u) {
0164
0165 if (boundaryType0 == Acts::AxisBoundaryType::Bound) {
0166 Acts::GridAxisGenerators::EqBound eqBound{jGridAxes[0]["range"],
0167 jGridAxes[0]["bins"]};
0168 auto grid =
0169 Acts::GridJsonConverter::fromJson<decltype(eqBound), std::size_t>(
0170 jGrid, eqBound);
0171
0172 auto boundToGridLocal =
0173 Acts::GridAccessJsonConverter::boundToGridLocal1DimDelegateFromJson(
0174 jMaterial["bound_to_grid_local"]);
0175
0176 auto globalToGridLocal =
0177 Acts::GridAccessJsonConverter::globalToGridLocal1DimDelegateFromJson(
0178 jMaterial["global_to_grid_local"]);
0179
0180 return new Acts::IndexedSurfaceMaterial<decltype(grid)>(
0181 std::move(grid), std::move(materialAccessor),
0182 std::move(boundToGridLocal), std::move(globalToGridLocal));
0183 }
0184
0185 if (boundaryType0 == Acts::AxisBoundaryType::Closed) {
0186 Acts::GridAxisGenerators::EqClosed eqClosed{jGridAxes[0]["range"],
0187 jGridAxes[0]["bins"]};
0188 auto grid =
0189 Acts::GridJsonConverter::fromJson<decltype(eqClosed), std::size_t>(
0190 jGrid, eqClosed);
0191
0192 auto boundToGridLocal =
0193 Acts::GridAccessJsonConverter::boundToGridLocal1DimDelegateFromJson(
0194 jMaterial["bound_to_grid_local"]);
0195
0196 auto globalToGridLocal =
0197 Acts::GridAccessJsonConverter::globalToGridLocal1DimDelegateFromJson(
0198 jMaterial["global_to_grid_local"]);
0199
0200 return new Acts::IndexedSurfaceMaterial<decltype(grid)>(
0201 std::move(grid), std::move(materialAccessor),
0202 std::move(boundToGridLocal), std::move(globalToGridLocal));
0203 }
0204 }
0205
0206
0207 if (jGridAxes.size() == 2u) {
0208
0209 Acts::AxisBoundaryType boundaryType1 = jGridAxes[1]["boundary_type"];
0210
0211
0212 if (boundaryType0 == Acts::AxisBoundaryType::Bound &&
0213 boundaryType1 == Acts::AxisBoundaryType::Bound) {
0214 Acts::GridAxisGenerators::EqBoundEqBound eqBoundEqBound{
0215 jGridAxes[0]["range"], jGridAxes[0]["bins"], jGridAxes[1]["range"],
0216 jGridAxes[1]["bins"]};
0217 auto grid =
0218 Acts::GridJsonConverter::fromJson<decltype(eqBoundEqBound),
0219 std::size_t>(jGrid, eqBoundEqBound);
0220
0221 auto boundToGridLocal =
0222 Acts::GridAccessJsonConverter::boundToGridLocal2DimDelegateFromJson(
0223 jMaterial["bound_to_grid_local"]);
0224
0225 auto globalToGridLocal =
0226 Acts::GridAccessJsonConverter::globalToGridLocal2DimDelegateFromJson(
0227 jMaterial["global_to_grid_local"]);
0228
0229 return new Acts::IndexedSurfaceMaterial<decltype(grid)>(
0230 std::move(grid), std::move(materialAccessor),
0231 std::move(boundToGridLocal), std::move(globalToGridLocal));
0232 }
0233
0234
0235 if (boundaryType0 == Acts::AxisBoundaryType::Bound &&
0236 boundaryType1 == Acts::AxisBoundaryType::Closed) {
0237 Acts::GridAxisGenerators::EqBoundEqClosed eqBoundEqClosed{
0238 jGridAxes[0]["range"], jGridAxes[0]["bins"], jGridAxes[1]["range"],
0239 jGridAxes[1]["bins"]};
0240 auto grid = Acts::GridJsonConverter::fromJson<decltype(eqBoundEqClosed),
0241 std::size_t>(
0242 jGrid, eqBoundEqClosed);
0243
0244 auto boundToGridLocal =
0245 Acts::GridAccessJsonConverter::boundToGridLocal2DimDelegateFromJson(
0246 jMaterial["bound_to_grid_local"]);
0247
0248 auto globalToGridLocal =
0249 Acts::GridAccessJsonConverter::globalToGridLocal2DimDelegateFromJson(
0250 jMaterial["global_to_grid_local"]);
0251
0252 return new Acts::IndexedSurfaceMaterial<decltype(grid)>(
0253 std::move(grid), std::move(materialAccessor),
0254 std::move(boundToGridLocal), std::move(globalToGridLocal));
0255 }
0256
0257
0258 if (boundaryType0 == Acts::AxisBoundaryType::Closed &&
0259 boundaryType1 == Acts::AxisBoundaryType::Bound) {
0260 Acts::GridAxisGenerators::EqClosedEqBound eqClosedEqBound{
0261 jGridAxes[0]["range"], jGridAxes[0]["bins"], jGridAxes[1]["range"],
0262 jGridAxes[1]["bins"]};
0263 auto grid = Acts::GridJsonConverter::fromJson<decltype(eqClosedEqBound),
0264 std::size_t>(
0265 jGrid, eqClosedEqBound);
0266
0267 auto boundToGridLocal =
0268 Acts::GridAccessJsonConverter::boundToGridLocal2DimDelegateFromJson(
0269 jMaterial["bound_to_grid_local"]);
0270
0271 auto globalToGridLocal =
0272 Acts::GridAccessJsonConverter::globalToGridLocal2DimDelegateFromJson(
0273 jMaterial["global_to_grid_local"]);
0274
0275 return new Acts::IndexedSurfaceMaterial<decltype(grid)>(
0276 std::move(grid), std::move(materialAccessor),
0277 std::move(boundToGridLocal), std::move(globalToGridLocal));
0278 }
0279 }
0280
0281 return nullptr;
0282 }
0283
0284 }
0285
0286 void Acts::to_json(nlohmann::json& j, const Material& t) {
0287 if (t.isVacuum()) {
0288 return;
0289 }
0290 for (unsigned i = 0; i < t.parameters().size(); ++i) {
0291 j.push_back(t.parameters()[i]);
0292 }
0293 }
0294
0295 void Acts::from_json(const nlohmann::json& j, Material& t) {
0296 if (j.is_null()) {
0297 return;
0298 }
0299 Acts::Material::ParametersVector params =
0300 Acts::Material::ParametersVector::Zero();
0301 for (auto i = params.size(); 0 < i--;) {
0302
0303 params[i] = j.at(i);
0304 }
0305 t = Acts::Material(params);
0306 return;
0307 }
0308
0309 void Acts::to_json(nlohmann::json& j, const MaterialSlab& t) {
0310 nlohmann::json jmat(t.material());
0311 j["material"] = jmat;
0312 j["thickness"] = t.thickness();
0313 }
0314
0315 void Acts::from_json(const nlohmann::json& j, MaterialSlab& t) {
0316 Material mat = Material::Vacuum();
0317 from_json(j.at("material"), mat);
0318 t = Acts::MaterialSlab(mat, j.at("thickness").get<float>());
0319 }
0320
0321 void Acts::from_json(const nlohmann::json& j, MaterialSlabMatrix& t) {
0322
0323 for (auto& outer : j) {
0324 Acts::MaterialSlabVector mpVector;
0325 for (auto& inner : outer) {
0326 MaterialSlab mat = MaterialSlab::Nothing();
0327 from_json(inner, mat);
0328 mpVector.emplace_back(mat);
0329 }
0330 t.push_back(std::move(mpVector));
0331 }
0332 }
0333
0334 void Acts::to_json(nlohmann::json& j, const surfaceMaterialPointer& material) {
0335 nlohmann::json jMaterial;
0336
0337 const Acts::BinUtility* bUtility = nullptr;
0338
0339
0340 auto psMaterial = dynamic_cast<const Acts::ProtoSurfaceMaterial*>(material);
0341 if (psMaterial != nullptr) {
0342
0343 jMaterial[Acts::jsonKey().typekey] = "proto";
0344
0345 nlohmann::json mapType(material->mappingType());
0346 jMaterial[Acts::jsonKey().maptype] = mapType;
0347
0348 jMaterial[Acts::jsonKey().mapkey] = false;
0349
0350 bUtility = &(psMaterial->binning());
0351
0352 auto& binningData = bUtility->binningData();
0353 for (std::size_t ibin = 0; ibin < binningData.size(); ++ibin) {
0354 if (binningData[ibin].bins() > 1) {
0355 jMaterial[Acts::jsonKey().mapkey] = true;
0356 break;
0357 }
0358 }
0359 nlohmann::json jBin(*bUtility);
0360 jMaterial[Acts::jsonKey().binkey] = jBin;
0361 j[Acts::jsonKey().materialkey] = jMaterial;
0362 return;
0363 }
0364
0365
0366 auto hsMaterial =
0367 dynamic_cast<const Acts::HomogeneousSurfaceMaterial*>(material);
0368 if (hsMaterial != nullptr) {
0369
0370 jMaterial[Acts::jsonKey().typekey] = "homogeneous";
0371
0372 nlohmann::json mapType(material->mappingType());
0373 jMaterial[Acts::jsonKey().maptype] = mapType;
0374
0375 jMaterial[Acts::jsonKey().mapkey] = true;
0376 nlohmann::json jmat(hsMaterial->materialSlab(Acts::Vector3(0., 0., 0.)));
0377 jMaterial[Acts::jsonKey().datakey] = nlohmann::json::array({
0378 nlohmann::json::array({
0379 jmat,
0380 }),
0381 });
0382 j[Acts::jsonKey().materialkey] = jMaterial;
0383 return;
0384 }
0385
0386
0387 auto bsMaterial = dynamic_cast<const Acts::BinnedSurfaceMaterial*>(material);
0388 if (bsMaterial != nullptr) {
0389
0390 jMaterial[Acts::jsonKey().typekey] = "binned";
0391
0392 nlohmann::json mapType(material->mappingType());
0393 jMaterial[Acts::jsonKey().maptype] = mapType;
0394
0395 jMaterial[Acts::jsonKey().mapkey] = true;
0396 bUtility = &(bsMaterial->binUtility());
0397
0398
0399 nlohmann::json mmat = nlohmann::json::array();
0400 for (const auto& mpVector : bsMaterial->fullMaterial()) {
0401 nlohmann::json mvec = nlohmann::json::array();
0402 for (const auto& mp : mpVector) {
0403 nlohmann::json jmat(mp);
0404 mvec.push_back(jmat);
0405 }
0406 mmat.push_back(std::move(mvec));
0407 }
0408 jMaterial[Acts::jsonKey().datakey] = std::move(mmat);
0409
0410 nlohmann::json jBin(*bUtility);
0411 jMaterial[Acts::jsonKey().binkey] = jBin;
0412 j[Acts::jsonKey().materialkey] = jMaterial;
0413 return;
0414 }
0415
0416
0417 using IndexedSurfaceGrids = Acts::TypeList<
0418 Acts::IndexedSurfaceMaterial<GridEqBound<std::size_t>>,
0419 Acts::IndexedSurfaceMaterial<GridEqClosed<std::size_t>>,
0420 Acts::IndexedSurfaceMaterial<GridEqBoundEqBound<std::size_t>>,
0421 Acts::IndexedSurfaceMaterial<GridEqBoundEqClosed<std::size_t>>,
0422 Acts::IndexedSurfaceMaterial<GridEqClosedEqBound<std::size_t>>>;
0423
0424 unrollIndexedGridConversion(jMaterial, *material, IndexedSurfaceGrids{});
0425 if (!jMaterial.empty()) {
0426 j[Acts::jsonKey().materialkey] = jMaterial;
0427 return;
0428 }
0429
0430
0431 using GloballyIndexedSurfaceGrids = Acts::TypeList<
0432 Acts::GloballyIndexedSurfaceMaterial<GridEqBound<std::size_t>>,
0433 Acts::GloballyIndexedSurfaceMaterial<GridEqClosed<std::size_t>>,
0434 Acts::GloballyIndexedSurfaceMaterial<GridEqBoundEqBound<std::size_t>>,
0435 Acts::GloballyIndexedSurfaceMaterial<GridEqBoundEqClosed<std::size_t>>,
0436 Acts::GloballyIndexedSurfaceMaterial<GridEqClosedEqBound<std::size_t>>>;
0437
0438 unrollIndexedGridConversion(jMaterial, *material,
0439 GloballyIndexedSurfaceGrids{});
0440 if (!jMaterial.empty()) {
0441 j[Acts::jsonKey().materialkey] = jMaterial;
0442 return;
0443 }
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454 return;
0455 }
0456
0457 void Acts::from_json(const nlohmann::json& j,
0458 surfaceMaterialPointer& material) {
0459 if (j.find(Acts::jsonKey().materialkey) == j.end()) {
0460 return;
0461 }
0462 nlohmann::json jMaterial = j[Acts::jsonKey().materialkey];
0463
0464 material = nullptr;
0465 if (jMaterial[Acts::jsonKey().mapkey] == false) {
0466 return;
0467 }
0468
0469
0470 if (jMaterial[Acts::jsonKey().typekey] == "grid") {
0471 material =
0472 indexedMaterialFromJson<Acts::IndexedMaterialAccessor>(jMaterial);
0473 return;
0474 }
0475
0476
0477 Acts::BinUtility bUtility;
0478 Acts::MaterialSlabMatrix mpMatrix;
0479 Acts::MappingType mapType = Acts::MappingType::Default;
0480 for (auto& [key, value] : jMaterial.items()) {
0481 if (key == Acts::jsonKey().binkey && !value.empty()) {
0482 from_json(value, bUtility);
0483 }
0484 if (key == Acts::jsonKey().datakey && !value.empty()) {
0485 from_json(value, mpMatrix);
0486 }
0487 if (key == Acts::jsonKey().maptype && !value.empty()) {
0488 from_json(value, mapType);
0489 }
0490 }
0491
0492 if (mpMatrix.empty()) {
0493 material = new Acts::ProtoSurfaceMaterial(bUtility, mapType);
0494 } else if (bUtility.bins() == 1) {
0495 material = new Acts::HomogeneousSurfaceMaterial(mpMatrix[0][0], mapType);
0496 } else {
0497 material = new Acts::BinnedSurfaceMaterial(bUtility, mpMatrix, mapType);
0498 }
0499 }
0500
0501 void Acts::to_json(nlohmann::json& j, const volumeMaterialPointer& material) {
0502 nlohmann::json jMaterial;
0503
0504 const Acts::BinUtility* bUtility = nullptr;
0505
0506 auto pvMaterial = dynamic_cast<const Acts::ProtoVolumeMaterial*>(material);
0507 if (pvMaterial != nullptr) {
0508
0509 jMaterial[Acts::jsonKey().typekey] = "proto";
0510
0511 jMaterial[Acts::jsonKey().mapkey] = false;
0512 bUtility = &(pvMaterial->binUtility());
0513
0514 auto& binningData = bUtility->binningData();
0515 for (std::size_t ibin = 0; ibin < binningData.size(); ++ibin) {
0516 if (binningData[ibin].bins() > 1) {
0517 jMaterial[Acts::jsonKey().mapkey] = true;
0518 break;
0519 }
0520 }
0521
0522 nlohmann::json jBin(*bUtility);
0523 jMaterial[Acts::jsonKey().binkey] = jBin;
0524 j[Acts::jsonKey().materialkey] = jMaterial;
0525 return;
0526 }
0527
0528 auto hvMaterial =
0529 dynamic_cast<const Acts::HomogeneousVolumeMaterial*>(material);
0530 if (hvMaterial != nullptr) {
0531
0532 jMaterial[Acts::jsonKey().typekey] = "homogeneous";
0533 jMaterial[Acts::jsonKey().mapkey] = true;
0534
0535 nlohmann::json jmat(hvMaterial->material({0, 0, 0}));
0536 jMaterial[Acts::jsonKey().datakey] = nlohmann::json::array({
0537 jmat,
0538 });
0539 j[Acts::jsonKey().materialkey] = jMaterial;
0540 return;
0541 }
0542
0543 auto bvMaterial2D = dynamic_cast<const Acts::InterpolatedMaterialMap<
0544 Acts::MaterialMapper<Acts::MaterialGrid2D>>*>(material);
0545
0546 if (bvMaterial2D != nullptr) {
0547
0548 jMaterial[Acts::jsonKey().typekey] = "interpolated2D";
0549 jMaterial[Acts::jsonKey().mapkey] = true;
0550 bUtility = &(bvMaterial2D->binUtility());
0551
0552 nlohmann::json mmat = nlohmann::json::array();
0553 Acts::MaterialGrid2D grid = bvMaterial2D->getMapper().getGrid();
0554 for (std::size_t bin = 0; bin < grid.size(); bin++) {
0555 nlohmann::json jmat(Material(grid.at(bin)));
0556 mmat.push_back(jmat);
0557 }
0558 jMaterial[Acts::jsonKey().datakey] = std::move(mmat);
0559
0560 nlohmann::json jBin(*bUtility);
0561 jMaterial[Acts::jsonKey().binkey] = jBin;
0562 j[Acts::jsonKey().materialkey] = jMaterial;
0563 return;
0564 }
0565
0566 auto bvMaterial3D = dynamic_cast<const Acts::InterpolatedMaterialMap<
0567 Acts::MaterialMapper<Acts::MaterialGrid3D>>*>(material);
0568
0569 if (bvMaterial3D != nullptr) {
0570
0571 jMaterial[Acts::jsonKey().typekey] = "interpolated3D";
0572 jMaterial[Acts::jsonKey().mapkey] = true;
0573 bUtility = &(bvMaterial3D->binUtility());
0574
0575 nlohmann::json mmat = nlohmann::json::array();
0576 Acts::MaterialGrid3D grid = bvMaterial3D->getMapper().getGrid();
0577 for (std::size_t bin = 0; bin < grid.size(); bin++) {
0578 nlohmann::json jmat(Material(grid.at(bin)));
0579 mmat.push_back(jmat);
0580 }
0581 jMaterial[Acts::jsonKey().datakey] = std::move(mmat);
0582
0583 nlohmann::json jBin(*bUtility);
0584 jMaterial[Acts::jsonKey().binkey] = jBin;
0585 j[Acts::jsonKey().materialkey] = jMaterial;
0586 return;
0587 }
0588 }
0589
0590 void Acts::from_json(const nlohmann::json& j, volumeMaterialPointer& material) {
0591 if (j.find(Acts::jsonKey().materialkey) == j.end()) {
0592 return;
0593 }
0594 nlohmann::json jMaterial = j[Acts::jsonKey().materialkey];
0595
0596 material = nullptr;
0597 if (jMaterial[Acts::jsonKey().mapkey] == false) {
0598 return;
0599 }
0600
0601 Acts::BinUtility bUtility;
0602 std::vector<Acts::Material> mmat;
0603 for (auto& [key, value] : jMaterial.items()) {
0604 if (key == Acts::jsonKey().binkey && !value.empty()) {
0605 from_json(value, bUtility);
0606 }
0607 if (key == Acts::jsonKey().datakey && !value.empty()) {
0608 for (const auto& bin : value) {
0609 Acts::Material mat = Material::Vacuum();
0610 from_json(bin, mat);
0611 mmat.push_back(mat);
0612 }
0613 }
0614 }
0615
0616 if (mmat.empty()) {
0617 material = new Acts::ProtoVolumeMaterial(bUtility);
0618 return;
0619 }
0620 if (mmat.size() == 1) {
0621 material = new Acts::HomogeneousVolumeMaterial(mmat[0]);
0622 return;
0623 }
0624 if (bUtility.dimensions() == 2) {
0625 std::function<Acts::Vector2(Acts::Vector3)> transfoGlobalToLocal;
0626 Acts::Grid2D grid = createGrid2D(bUtility, transfoGlobalToLocal);
0627
0628 Acts::Grid2D::point_t min = grid.minPosition();
0629 Acts::Grid2D::point_t max = grid.maxPosition();
0630 Acts::Grid2D::index_t nBins = grid.numLocalBins();
0631
0632 Acts::EAxis axis1(min[0], max[0], nBins[0]);
0633 Acts::EAxis axis2(min[1], max[1], nBins[1]);
0634
0635
0636 Acts::MaterialGrid2D mGrid(std::make_tuple(axis1, axis2));
0637
0638 for (std::size_t bin = 0; bin < mmat.size(); bin++) {
0639 mGrid.at(bin) = mmat[bin].parameters();
0640 }
0641 Acts::MaterialMapper<Acts::MaterialGrid2D> matMap(transfoGlobalToLocal,
0642 mGrid);
0643 material = new Acts::InterpolatedMaterialMap<
0644 Acts::MaterialMapper<Acts::MaterialGrid2D>>(std::move(matMap),
0645 bUtility);
0646 return;
0647 }
0648 if (bUtility.dimensions() == 3) {
0649 std::function<Acts::Vector3(Acts::Vector3)> transfoGlobalToLocal;
0650 Acts::Grid3D grid = createGrid3D(bUtility, transfoGlobalToLocal);
0651
0652 Acts::Grid3D::point_t min = grid.minPosition();
0653 Acts::Grid3D::point_t max = grid.maxPosition();
0654 Acts::Grid3D::index_t nBins = grid.numLocalBins();
0655
0656 Acts::EAxis axis1(min[0], max[0], nBins[0]);
0657 Acts::EAxis axis2(min[1], max[1], nBins[1]);
0658 Acts::EAxis axis3(min[2], max[2], nBins[2]);
0659
0660
0661 Acts::MaterialGrid3D mGrid(std::make_tuple(axis1, axis2, axis3));
0662
0663 for (std::size_t bin = 0; bin < mmat.size(); bin++) {
0664 mGrid.at(bin) = mmat[bin].parameters();
0665 }
0666 Acts::MaterialMapper<Acts::MaterialGrid3D> matMap(transfoGlobalToLocal,
0667 mGrid);
0668 material = new Acts::InterpolatedMaterialMap<
0669 Acts::MaterialMapper<Acts::MaterialGrid3D>>(std::move(matMap),
0670 bUtility);
0671 return;
0672 }
0673 }
0674
0675 nlohmann::json Acts::MaterialJsonConverter::toJsonDetray(
0676 const Acts::ISurfaceMaterial& surfaceMaterial, const Acts::Surface& surface,
0677 std::size_t surfaceIndex, std::map<std::size_t, std::size_t>& gridLink) {
0678 nlohmann::json jSurfaceMaterial;
0679
0680
0681 if (auto binnedMaterial =
0682 dynamic_cast<const BinnedSurfaceMaterial*>(&surfaceMaterial);
0683 binnedMaterial != nullptr) {
0684
0685 bool swapped = false;
0686
0687
0688
0689 BinUtility bUtility = binnedMaterial->binUtility();
0690
0691 if (bUtility.dimensions() == 1u) {
0692 if (bUtility.binningData()[0u].binvalue == AxisDirection::AxisR) {
0693
0694 bUtility += BinUtility(1u, -std::numbers::pi, std::numbers::pi, closed,
0695 AxisDirection::AxisPhi);
0696 } else if (bUtility.binningData()[0u].binvalue == AxisDirection::AxisZ) {
0697
0698 BinUtility nbUtility(1u, -std::numbers::pi, std::numbers::pi, closed,
0699 AxisDirection::AxisPhi);
0700 nbUtility += bUtility;
0701 bUtility = std::move(nbUtility);
0702 swapped = true;
0703 } else {
0704 std::runtime_error("Unsupported binning for Detray");
0705 }
0706 } else if (bUtility.dimensions() == 2u &&
0707 bUtility.binningData()[0u].binvalue == AxisDirection::AxisZ &&
0708 bUtility.binningData()[1u].binvalue == AxisDirection::AxisPhi) {
0709 BinUtility nbUtility(bUtility.binningData()[1u]);
0710 nbUtility += BinUtility{bUtility.binningData()[0u]};
0711 bUtility = std::move(nbUtility);
0712 swapped = true;
0713 }
0714
0715 AxisDirection bVal0 = bUtility.binningData()[0u].binvalue;
0716 AxisDirection bVal1 = bUtility.binningData()[1u].binvalue;
0717
0718
0719 int gridIndexType = 0;
0720 if (bVal0 == AxisDirection::AxisR && bVal1 == AxisDirection::AxisPhi) {
0721 gridIndexType = 0;
0722 } else if (bVal0 == AxisDirection::AxisPhi &&
0723 bVal1 == AxisDirection::AxisZ) {
0724 gridIndexType = 3;
0725 } else if (bVal0 == AxisDirection::AxisX && bVal1 == AxisDirection::AxisY) {
0726 gridIndexType = 2;
0727 } else {
0728 std::runtime_error("Unsupported binning for Detray");
0729 }
0730
0731 nlohmann::json jAxes = toJsonDetray(bUtility, surface);
0732
0733 nlohmann::json jGridLink;
0734 jGridLink["type"] = gridIndexType;
0735 std::size_t gridIndex = 0;
0736 if (gridLink.contains(gridIndexType)) {
0737 std::size_t& fGridIndex = gridLink[gridIndex];
0738 gridIndex = fGridIndex;
0739 fGridIndex++;
0740 } else {
0741 gridLink[gridIndexType] = 1;
0742 }
0743 jGridLink["index"] = gridIndex;
0744
0745
0746 jSurfaceMaterial["axes"] = jAxes;
0747 jSurfaceMaterial["grid_link"] = jGridLink;
0748 jSurfaceMaterial["owner_link"] = surfaceIndex;
0749
0750
0751 nlohmann::json jBins;
0752 auto materialMatrix = binnedMaterial->fullMaterial();
0753 for (std::size_t ib1 = 0; ib1 < materialMatrix.size(); ++ib1) {
0754 for (std::size_t ib0 = 0; ib0 < materialMatrix[0u].size(); ++ib0) {
0755 nlohmann::json jBin;
0756
0757 MaterialSlab slab = materialMatrix[ib1][ib0];
0758
0759 std::size_t lb0 = swapped ? ib1 : ib0;
0760 std::size_t lb1 = swapped ? ib0 : ib1;
0761 jBin["loc_index"] = std::array<std::size_t, 2u>{lb0, lb1};
0762
0763 const Material& material = slab.material();
0764
0765 nlohmann::json jContent;
0766 jContent["thickness"] = slab.thickness();
0767
0768 nlohmann::json jMaterialParams;
0769 if (slab.thickness() > 0.) {
0770 jMaterialParams["params"] =
0771 std::vector<double>{material.X0(),
0772 material.L0(),
0773 material.Ar(),
0774 material.Z(),
0775 material.massDensity(),
0776 material.molarDensity(),
0777 0.};
0778
0779 } else {
0780 jMaterialParams["params"] =
0781 std::vector<double>{0., 0., 0., 0., 0., 0., 0.};
0782 }
0783 jContent["material"] = jMaterialParams;
0784 jContent["type"] = 6;
0785 jContent["surface_idx"] = surfaceIndex;
0786
0787 nlohmann::json jContentVector;
0788 jContentVector.push_back(jContent);
0789 jBin["content"] = jContentVector;
0790 jBins.push_back(jBin);
0791 }
0792 }
0793 jSurfaceMaterial["bins"] = jBins;
0794 }
0795 return jSurfaceMaterial;
0796 }
0797
0798 nlohmann::json Acts::MaterialJsonConverter::toJsonDetray(
0799 const Acts::BinUtility& binUtility, const Surface& surface) {
0800 nlohmann::json jAxes;
0801 for (const auto [ib, bData] : enumerate(binUtility.binningData())) {
0802 nlohmann::json jAxis;
0803 jAxis["bounds"] = bData.option == closed ? 2 : 1;
0804 jAxis["binning"] = 0u;
0805 jAxis["label"] = ib;
0806 jAxis["bins"] = bData.bins();
0807 double offset = 0;
0808 if (bData.binvalue == AxisDirection::AxisZ) {
0809 offset = surface.center(Acts::GeometryContext{}).z();
0810 }
0811 jAxis["edges"] =
0812 std::array<double, 2>{bData.min + offset, bData.max + offset};
0813 jAxes.push_back(jAxis);
0814 }
0815 return jAxes;
0816 }