Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ codegen/build/
codegen/src/codegen.egg-info/
# the codegen manifest is tracked, despite the blanket *.json rule above
!codegen/manifest.json
# the generated material map example shown in the docs, same exception
!docs/examples/material_map_example.json
# generated code shipped in source archives, never committed
/prebuilt-codegen/

Expand Down
1 change: 1 addition & 0 deletions Plugins/Json/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ acts_add_library(
src/ProtoAxisJsonConverter.cpp
src/SurfaceBoundsJsonConverter.cpp
src/SurfaceJsonConverter.cpp
src/SurfaceMaterialJsonConverter.cpp
src/UtilitiesJsonConverter.cpp
src/VolumeBoundsJsonConverter.cpp
src/VolumeJsonConverter.cpp
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,17 @@
/// Convert surfaceMaterialPointer to JSON
/// @param j Destination JSON object
/// @param material Source surfaceMaterialPointer to convert
/// @deprecated Use SurfaceMaterialJsonConverter::toJson instead
[[deprecated("use SurfaceMaterialJsonConverter")]]
void to_json(nlohmann::json& j, const surfaceMaterialPointer& material);

Check warning on line 74 in Plugins/Json/include/ActsPlugins/Json/MaterialJsonConverter.hpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Do not forget to remove this deprecated code someday.

See more on https://sonarcloud.io/project/issues?id=acts-project_acts&issues=AaBoWyyFNpHOiCCpUIS2&open=AaBoWyyFNpHOiCCpUIS2&pullRequest=6023

/// Convert JSON to surfaceMaterialPointer
/// @param j Source JSON object
/// @param material Destination surfaceMaterialPointer to populate
/// @note the caller takes ownership of the returned raw pointer
/// @deprecated Use SurfaceMaterialJsonConverter::fromJson instead
[[deprecated("use SurfaceMaterialJsonConverter")]]
void from_json(const nlohmann::json& j, surfaceMaterialPointer& material);

Check warning on line 82 in Plugins/Json/include/ActsPlugins/Json/MaterialJsonConverter.hpp

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Do not forget to remove this deprecated code someday.

See more on https://sonarcloud.io/project/issues?id=acts-project_acts&issues=AaBoWyyFNpHOiCCpUIS3&open=AaBoWyyFNpHOiCCpUIS3&pullRequest=6023

/// JSON serialization mapping for MappingType enum
// This macro create a conversion for the mapping type enum
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,9 +153,9 @@ class MaterialMapJsonConverter {

/// Name of the surface hierarchy
std::string m_surfaceName = "Material Surface Map";
/// Geometry hierarchy writer for surface material.
Acts::GeometryHierarchyMapJsonConverter<const ISurfaceMaterial*,
Acts::IVolumeMaterialJsonDecorator>
/// Geometry hierarchy writer for surface material. The material entries
/// are encoded by this converter, so the container only sees ready json.
Acts::GeometryHierarchyMapJsonConverter<nlohmann::json>
m_surfaceMaterialConverter;
/// Geometry hierarchy writer for surface.
Acts::GeometryHierarchyMapJsonConverter<Acts::SurfaceAndMaterialWithContext,
Expand Down
100 changes: 100 additions & 0 deletions Plugins/Json/include/ActsPlugins/Json/SurfaceMaterialJsonConverter.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
// This file is part of the ACTS project.
//
// Copyright (C) 2016 CERN for the benefit of the ACTS project
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

#pragma once

#include "Acts/Material/ISurfaceMaterial.hpp"
#include "Acts/Utilities/TypeDispatcher.hpp"
#include "ActsPlugins/Json/ActsJson.hpp"
#include "ActsPlugins/Json/GeometryJsonKeys.hpp"
#include "ActsPlugins/Json/JsonKindDispatcher.hpp"

#include <memory>

#include <nlohmann/json.hpp>

namespace Acts {

namespace detail {
class MaterialJsonEncodeContext;
class MaterialJsonDecodeContext;
} // namespace detail

/// @addtogroup json_plugin
/// @{

/// Static class performing the JSON conversion of surface material
///
/// The encoding side is a @c TypeDispatcher registered on the concrete
/// (or, for the grid family, the abstract templated) material types, the
/// decoding side a @c JsonKindDispatcher keyed on the payload type tag.
class SurfaceMaterialJsonConverter {
public:
/// Context collecting the slab stores of the document being written
using EncodeContext = detail::MaterialJsonEncodeContext;

/// Context carrying the slab stores of the document being read
using DecodeContext = detail::MaterialJsonDecodeContext;

/// Encoder type for the surface material
using Encoder =
TypeDispatcher<ISurfaceMaterial, nlohmann::json(EncodeContext&)>;

/// Decoder type for the surface material
using Decoder = JsonKindDispatcher<std::unique_ptr<const ISurfaceMaterial>,
const DecodeContext&>;

/// Configuration struct
struct Config {
/// Encoder for the surface material
Encoder encoder{};

/// Decoder for the surface material, keyed on the payload type tag
Decoder decoder{jsonKey().typekey, "surface material"};

/// Access the shared default configuration
///
/// @return the default configuration instance
static const Config& defaultConfig();
};

/// Delete the default constructor as the class is purely static
SurfaceMaterialJsonConverter() = delete;

/// Convert surface material into its json payload
///
/// @param material the material to be converted
/// @param config the converter configuration
/// @param context the document context collecting the slab stores, or a
/// nullptr to inline any slab store and keep the payload
/// self-contained
///
/// @return the json payload of the material, i.e. the value that goes
/// under the @c material key of a surface
static nlohmann::json toJson(const ISurfaceMaterial& material,
const Config& config = Config::defaultConfig(),
EncodeContext* context = nullptr);

/// Convert a json payload back into surface material
///
/// @param jMaterial the json payload of the material
/// @param config the converter configuration
/// @param context the document context holding the slab stores, or a
/// nullptr if the payload is expected to be self-contained
///
/// @return the decoded material, or a nullptr if the payload is flagged
/// as not participating in the material mapping
static std::unique_ptr<const ISurfaceMaterial> fromJson(
const nlohmann::json& jMaterial,
const Config& config = Config::defaultConfig(),
const DecodeContext* context = nullptr);
};

/// @}

} // namespace Acts
130 changes: 130 additions & 0 deletions Plugins/Json/include/ActsPlugins/Json/detail/MaterialJsonContext.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
// This file is part of the ACTS project.
//
// Copyright (C) 2016 CERN for the benefit of the ACTS project
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

#pragma once

#include "Acts/Material/MaterialSlab.hpp"

#include <cstddef>
#include <memory>
#include <stdexcept>
#include <string>
#include <vector>

namespace Acts::detail {

/// A store of material slabs that several index grids can share
using MaterialSlabStore = std::shared_ptr<std::vector<MaterialSlab>>;

/// Context threaded through the material encoders of a single document.
///
/// Material grids that index into a shared slab store register that store
/// here instead of inlining it, so the document holds one copy per store.
/// A default constructed context has no store table, which makes the
/// encoders fall back to inlining and keeps standalone payloads
/// self-contained.
class MaterialJsonEncodeContext {
public:
/// Default construction, the store table is disabled
MaterialJsonEncodeContext() = default;

/// Create a context that collects slab stores in a table
///
/// @return a context with the store table enabled
static MaterialJsonEncodeContext withStoreTable() {
MaterialJsonEncodeContext ctx;
ctx.m_storeTable = true;
return ctx;
}

/// @return whether encoders should reference the store table
bool storeTableEnabled() const { return m_storeTable; }

/// Look up, and if needed assign, the table id of a slab store
///
/// Stores are keyed on pointer identity, never on content, so two stores
/// that happen to hold the same slabs stay distinct.
///
/// @param store the slab store to register
///
/// @return the id of the store in the table
std::size_t storeId(const MaterialSlabStore& store) {
if (!m_storeTable) {
throw std::logic_error(
"MaterialJsonEncodeContext: store table is not enabled");
}
if (store == nullptr) {
throw std::invalid_argument(
"MaterialJsonEncodeContext: cannot register a null slab store");
}
for (std::size_t is = 0; is < m_stores.size(); ++is) {
if (m_stores[is] == store) {
return is;
}
}
m_stores.push_back(store);
return m_stores.size() - 1;
}

/// @return the collected slab stores, in encounter order
const std::vector<MaterialSlabStore>& stores() const { return m_stores; }

private:
bool m_storeTable = false;
std::vector<MaterialSlabStore> m_stores;
};

/// Context threaded through the material decoders of a single document.
///
/// It carries the slab store table read from the document so that all
/// grids referencing the same id end up sharing one allocation.
class MaterialJsonDecodeContext {
public:
/// Default construction, no store table is available
MaterialJsonDecodeContext() = default;

/// Install the slab store table of the document
///
/// @param stores the stores, indexed by their document id
void setStores(std::vector<MaterialSlabStore> stores) {
m_stores = std::move(stores);
m_storeTable = true;
}

/// @return whether a store table is available
bool storeTableEnabled() const { return m_storeTable; }

/// Resolve a slab store by its document id
///
/// @param id the id of the store in the table
///
/// @return the shared slab store
MaterialSlabStore store(std::size_t id) const {
if (!m_storeTable) {
throw std::invalid_argument(
"MaterialJsonDecodeContext: the payload references slab store " +
std::to_string(id) + " but no store table was read");
}
if (id >= m_stores.size()) {
throw std::invalid_argument("MaterialJsonDecodeContext: slab store id " +
std::to_string(id) +
" is out of range, the table holds " +
std::to_string(m_stores.size()) + " stores");
}
return m_stores[id];
}

/// @return the number of stores in the table
std::size_t size() const { return m_stores.size(); }

private:
bool m_storeTable = false;
std::vector<MaterialSlabStore> m_stores;
};

} // namespace Acts::detail
Loading
Loading