Skip to content
Snippets Groups Projects
Commit b094fdc8 authored by Paul Gessinger's avatar Paul Gessinger
Browse files

Merge branch 'Move-JsonPlugin-to-core' into 'master'

Move json plugin to core

See merge request !708
parents f5d4998a 57e5c359
Branches
Tags
1 merge request!708Move json plugin to core
Pipeline #1283955 passed
......@@ -301,7 +301,7 @@ clang_tidy:
# contain LCG to only where needed
- /bin/sh -c "set +e && source ../CI/setup_lcg96.sh; set -e && cmake .. -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ${COMMON_BUILD_OPTIONS} -DACTS_BUILD_DD4HEP_PLUGIN=on -DACTS_BUILD_TGEO_PLUGIN=on"
- cd ..
- run-clang-tidy.py -p build -header-filter=.* -export-fixes report/clang-tidy-fixes.yml -j$(nproc) 1> report/clang-tidy.log || true
- run-clang-tidy.py -p build -header-filter=.*pp -export-fixes report/clang-tidy-fixes.yml -j$(nproc) 1> report/clang-tidy.log || true
- virtualenv civenv
- source civenv/bin/activate
- pip install -r CI/requirements.txt
......
......@@ -3,19 +3,31 @@
set(_json_dep_header_sha256_ref d2eeb25d2e95bffeb08ebb7704cdffd2e8fca7113eba9a0b38d60a5c391ea09a)
# Check if hash of file on disk matches the stated hash of the release
file(READ "include/Acts/Plugins/Json/lib/json.hpp" _json_dep_header)
file(READ "include/Acts/Plugins/Json/lib/json.h" _json_dep_header)
file(GLOB_RECURSE src_files "src/*.cpp" "include/*.hpp")
string(SHA256 _json_dep_header_sha256 "${_json_dep_header}")
if(NOT ${_json_dep_header_sha256} STREQUAL ${_json_dep_header_sha256_ref})
message(FATAL_ERROR "json.hpp hash does not match reference!")
message(FATAL_ERROR "json.h hash does not match reference!")
endif()
add_library(
ActsJsonPlugin INTERFACE)
ActsJsonPlugin SHARED ${src_files})
target_include_directories(
ActsJsonPlugin
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
SYSTEM INTERFACE
${Boost_INCLUDE_DIRS}
${EIGEN_INCLUDE_DIRS})
target_include_directories(
ActsJsonPlugin
PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include/>
$<INSTALL_INTERFACE:include>)
target_link_libraries(
ActsJsonPlugin PUBLIC ActsCore)
install(
TARGETS ActsJsonPlugin
......
// This file is part of the Acts project.
//
// Copyright (C) 2017-2019 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 http://mozilla.org/MPL/2.0/.
#pragma once
#include <map>
#include "Acts/Geometry/TrackingGeometry.hpp"
#include "Acts/Material/ISurfaceMaterial.hpp"
#include "Acts/Material/IVolumeMaterial.hpp"
#include "Acts/Material/MaterialProperties.hpp"
#include "Acts/Plugins/Json/lib/json.h"
#include "Acts/Utilities/BinUtility.hpp"
#include "Acts/Utilities/Definitions.hpp"
#include "Acts/Utilities/Logger.hpp"
// Convenience shorthand
using json = nlohmann::json;
namespace Acts {
/// @class JsonGeometryConverter
///
/// @brief read the material from Json
class JsonGeometryConverter {
public:
using SurfaceMaterialMap =
std::map<GeometryID, std::shared_ptr<const ISurfaceMaterial>>;
using VolumeMaterialMap =
std::map<GeometryID, std::shared_ptr<const IVolumeMaterial>>;
using DetectorMaterialMaps = std::pair<SurfaceMaterialMap, VolumeMaterialMap>;
using geo_id_value = uint64_t;
using SurfaceMaterialRep = std::map<geo_id_value, const ISurfaceMaterial*>;
using VolumeMaterialRep = std::map<geo_id_value, const IVolumeMaterial*>;
/// @brief Layer representation for Json writing
struct LayerRep {
// the layer id
GeometryID layerID;
SurfaceMaterialRep sensitives;
SurfaceMaterialRep approaches;
const ISurfaceMaterial* representing = nullptr;
/// The LayerRep is actually worth it to write out
operator bool() const {
return (sensitives.empty() or approaches.empty() or
representing != nullptr);
}
};
/// @brief Volume representation for Json writing
struct VolumeRep {
// The geometry id
GeometryID volumeID;
/// The namne
std::string volumeName;
std::map<geo_id_value, LayerRep> layers;
SurfaceMaterialRep boundaries;
const IVolumeMaterial* material = nullptr;
/// The VolumeRep is actually worth it to write out
operator bool() const {
return (layers.empty() or boundaries.empty() or material != nullptr);
}
};
/// @brief Detector representation for Json writing
struct DetectorRep {
std::map<geo_id_value, VolumeRep> volumes;
};
/// @class Config
/// Configuration of the Reader
class Config {
public:
/// The geometry version
std::string geoversion = "undefined";
/// The detector tag
std::string detkey = "detector";
/// The volume identification string
std::string volkey = "volumes";
/// The name identification
std::string namekey = "name";
/// The boundary surface string
std::string boukey = "boundaries";
/// The layer identification string
std::string laykey = "layers";
/// The volume material string
std::string matkey = "material";
/// The approach identification string
std::string appkey = "approach";
/// The sensitive identification string
std::string senkey = "sensitive";
/// The representing idntification string
std::string repkey = "representing";
/// The bin keys
std::string bin0key = "bin0";
/// The bin1 key
std::string bin1key = "bin1";
/// The type key -> proto, else
std::string typekey = "type";
/// The data key
std::string datakey = "data";
/// The geoid key
std::string geoidkey = "geoid";
/// The default logger
std::shared_ptr<const Logger> logger;
/// The name of the writer
std::string name = "";
/// Steering to handle sensitive data
bool processSensitives = true;
/// Steering to handle approach data
bool processApproaches = true;
/// Steering to handle representing data
bool processRepresenting = true;
/// Steering to handle boundary data
bool processBoundaries = true;
/// Steering to handle volume data
bool processVolumes = true;
/// Write out data
bool writeData = true;
/// Constructor
///
/// @param lname Name of the writer tool
/// @param lvl The output logging level
Config(const std::string& lname = "JsonGeometryConverter",
Logging::Level lvl = Logging::INFO)
: logger(getDefaultLogger(lname, lvl)), name(lname) {}
};
/// Constructor
///
/// @param cfg configuration struct for the reader
JsonGeometryConverter(const Config& cfg);
/// Destructor
~JsonGeometryConverter() = default;
/// Convert method
///
/// @param surfaceMaterialMap The indexed material map collection
std::pair<std::map<GeometryID, std::shared_ptr<const ISurfaceMaterial>>,
std::map<GeometryID, std::shared_ptr<const IVolumeMaterial>>>
jsonToMaterialMaps(const json& materialmaps);
/// Convert method
///
/// @param surfaceMaterialMap The indexed material map collection
json materialMapsToJson(const DetectorMaterialMaps& maps);
/// Write method
///
/// @param tGeometry is the tracking geometry which contains the material
json trackingGeometryToJson(const TrackingGeometry& tGeometry);
private:
/// Convert to internal representation method, recursive call
///
/// @param tGeometry is the tracking geometry which contains the material
void convertToRep(DetectorRep& detRep, const TrackingVolume& tVolume);
/// Convert to internal representation method
///
/// @param tGeometry is the tracking geometry which contains the material
LayerRep convertToRep(const Layer& tLayer);
/// Create the Surface Material from Json
/// - factory method, ownership given
/// @param material is the json part representing a material object
const ISurfaceMaterial* jsonToSurfaceMaterial(const json& material);
/// Create the Material Matrix from Json
///
/// @param data is the json part representing a material data array
MaterialPropertiesMatrix jsonToMaterialMatrix(const json& data);
/// Create the BinUtility for from Json
BinUtility jsonToBinUtility(const json& bin);
/// Create Json from a detector represenation
json detectorRepToJson(const DetectorRep& detRep);
/// SurfaceMaterial to Json
///
/// @param the SurfaceMaterial
json surfaceMaterialToJson(const ISurfaceMaterial& sMaterial);
/// The config class
Config m_cfg;
/// Private access to the logging instance
const Logger& logger() const { return *m_cfg.logger; }
};
} // namespace Acts
// This file is part of the Acts project.
//
// Copyright (C) 2017-2019 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 http://mozilla.org/MPL/2.0/.
#pragma once
#include <fstream>
#include <map>
#include <mutex>
#include "Acts/Geometry/TrackingVolume.hpp"
#include "Acts/Material/IMaterialDecorator.hpp"
#include "Acts/Material/ISurfaceMaterial.hpp"
#include "Acts/Material/IVolumeMaterial.hpp"
#include "Acts/Plugins/Json/JsonGeometryConverter.hpp"
#include "Acts/Surfaces/Surface.hpp"
// Convenience shorthand
using json = nlohmann::json;
namespace Acts {
/// @brief Material decorator from Json format
///
/// This reads in material maps for surfaces and volumes
/// from a json file
class JsonMaterialDecorator : public IMaterialDecorator {
public:
using SurfaceMaterialMap =
std::map<GeometryID, std::shared_ptr<const ISurfaceMaterial>>;
using VolumeMaterialMap =
std::map<GeometryID, std::shared_ptr<const IVolumeMaterial>>;
JsonMaterialDecorator(const JsonGeometryConverter::Config& rConfig,
const std::string& jFileName,
bool clearSurfaceMaterial = true,
bool clearVolumeMaterial = true)
: m_readerConfig(rConfig),
m_clearSurfaceMaterial(clearSurfaceMaterial),
m_clearVolumeMaterial(clearVolumeMaterial) {
// the material reader
Acts::JsonGeometryConverter::Config jmConverterCfg("JsonGeometryConverter",
Logging::VERBOSE);
Acts::JsonGeometryConverter jmConverter(jmConverterCfg);
std::ifstream ifj(jFileName.c_str());
json jin;
ifj >> jin;
auto maps = jmConverter.jsonToMaterialMaps(jin);
m_surfaceMaterialMap = maps.first;
m_volumeMaterialMap = maps.second;
}
/// Decorate a surface
///
/// @param surface the non-cost surface that is decorated
void decorate(Surface& surface) const final {
// Clear the material if registered to do so
if (m_clearSurfaceMaterial) {
surface.assignSurfaceMaterial(nullptr);
}
// Try to find the surface in the map
auto sMaterial = m_surfaceMaterialMap.find(surface.geoID());
if (sMaterial != m_surfaceMaterialMap.end()) {
surface.assignSurfaceMaterial(sMaterial->second);
}
}
/// Decorate a TrackingVolume
///
/// @param volume the non-cost volume that is decorated
void decorate(TrackingVolume& volume) const final {
// Clear the material if registered to do so
if (m_clearVolumeMaterial) {
volume.assignVolumeMaterial(nullptr);
}
}
private:
JsonGeometryConverter::Config m_readerConfig;
SurfaceMaterialMap m_surfaceMaterialMap;
VolumeMaterialMap m_volumeMaterialMap;
bool m_clearSurfaceMaterial{true};
bool m_clearVolumeMaterial{true};
};
} // namespace Acts
// This file is part of the Acts project.
//
// Copyright (C) 2017-2019 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 http://mozilla.org/MPL/2.0/.
#include "Acts/Plugins/Json/JsonGeometryConverter.hpp"
#include <boost/algorithm/string.hpp>
#include <boost/algorithm/string/finder.hpp>
#include <boost/algorithm/string/iter_find.hpp>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <map>
#include <sstream>
#include <stdexcept>
#include <string>
#include "Acts/Geometry/ApproachDescriptor.hpp"
#include "Acts/Geometry/GeometryID.hpp"
#include "Acts/Geometry/TrackingVolume.hpp"
#include "Acts/Material/BinnedSurfaceMaterial.hpp"
#include "Acts/Material/HomogeneousSurfaceMaterial.hpp"
#include "Acts/Material/ProtoSurfaceMaterial.hpp"
#include "Acts/Surfaces/SurfaceArray.hpp"
#include "Acts/Utilities/BinUtility.hpp"
#include "Acts/Utilities/BinningType.hpp"
Acts::JsonGeometryConverter::JsonGeometryConverter(
const Acts::JsonGeometryConverter::Config& cfg)
: m_cfg(std::move(cfg)) {
// Validate the configuration
if (!m_cfg.logger) {
throw std::invalid_argument("Missing logger");
}
}
std::pair<
std::map<Acts::GeometryID, std::shared_ptr<const Acts::ISurfaceMaterial>>,
std::map<Acts::GeometryID, std::shared_ptr<const Acts::IVolumeMaterial>>>
Acts::JsonGeometryConverter::jsonToMaterialMaps(const json& materialmaps) {
auto& j = materialmaps;
// The return maps
std::pair<SurfaceMaterialMap, VolumeMaterialMap> maps;
ACTS_VERBOSE("j2a: Reading material maps from json file.");
ACTS_VERBOSE("j2a: Found entries for " << j.count(m_cfg.volkey)
<< " volume(s).");
// Structured binding
for (auto& [key, value] : j.items()) {
// Check if this the volume key
if (key == m_cfg.volkey) {
// Get the volume json
auto volj = value;
for (auto& [vkey, vvalue] : volj.items()) {
// Create the volume id
int vid = std::stoi(vkey);
Acts::GeometryID volumeID;
volumeID.setVolume(vid);
ACTS_VERBOSE("j2a: -> Found Volume " << vid);
// Loop through the information in the volume
for (auto& [vckey, vcvalue] : vvalue.items()) {
if (vckey == m_cfg.boukey and m_cfg.processBoundaries and
not vcvalue.empty()) {
ACTS_VERBOSE("j2a: --> BoundarySurface(s) to be parsed");
for (auto& [bkey, bvalue] : vcvalue.items()) {
// Create the boundary id
int bid = std::stoi(bkey);
Acts::GeometryID boundaryID(volumeID);
boundaryID.setBoundary(bid);
ACTS_VERBOSE("j2a: ---> Found boundary surface " << bid);
auto boumat = jsonToSurfaceMaterial(bvalue);
maps.first[boundaryID] =
std::shared_ptr<const ISurfaceMaterial>(boumat);
}
} else if (vckey == m_cfg.laykey) {
ACTS_VERBOSE("j2a: --> Layer(s) to be parsed");
// Loop over layers and repeat
auto layj = vcvalue;
for (auto& [lkey, lvalue] : layj.items()) {
// Create the layer id
int lid = std::stoi(lkey);
Acts::GeometryID layerID(volumeID);
layerID.setLayer(lid);
ACTS_VERBOSE("j2a: ---> Found Layer " << lid);
// Finally loop over layer components
for (auto& [lckey, lcvalue] : lvalue.items()) {
if (lckey == m_cfg.repkey and m_cfg.processRepresenting and
not lcvalue.empty()) {
ACTS_VERBOSE("j2a: ----> Found representing surface");
auto repmat = jsonToSurfaceMaterial(lcvalue);
maps.first[layerID] =
std::shared_ptr<const Acts::ISurfaceMaterial>(repmat);
} else if (lckey == m_cfg.appkey and m_cfg.processApproaches and
not lcvalue.empty()) {
ACTS_VERBOSE("j2a: ----> Found approach surface(s)");
// Loop over approach surfaces
for (auto& [askey, asvalue] : lcvalue.items()) {
// Create the layer id, todo set to max value
int aid = (askey == "*") ? 0 : std::stoi(askey);
Acts::GeometryID approachID(layerID);
approachID.setApproach(aid);
ACTS_VERBOSE("j2a: -----> Approach surface " << askey);
auto appmat = jsonToSurfaceMaterial(asvalue);
maps.first[approachID] =
std::shared_ptr<const Acts::ISurfaceMaterial>(appmat);
}
} else if (lckey == m_cfg.senkey and m_cfg.processSensitives and
not lcvalue.empty()) {
ACTS_VERBOSE("j2a: ----> Found sensitive surface(s)");
// Loop over sensitive surfaces
for (auto& [sskey, ssvalue] : lcvalue.items()) {
// Create the layer id, todo set to max value
int sid = (sskey == "*") ? 0 : std::stoi(sskey);
Acts::GeometryID senisitiveID(layerID);
senisitiveID.setSensitive(sid);
ACTS_VERBOSE("j2a: -----> Sensitive surface " << sskey);
auto senmat = jsonToSurfaceMaterial(ssvalue);
maps.first[senisitiveID] =
std::shared_ptr<const Acts::ISurfaceMaterial>(senmat);
}
}
}
}
} else if (vckey == m_cfg.matkey and not vcvalue.empty()) {
ACTS_VERBOSE("--> VolumeMaterial to be parsed");
}
}
}
} else if (key == m_cfg.geoversion) {
ACTS_VERBOSE("Detector version: " << m_cfg.geoversion);
}
}
// Return the filled maps
return maps;
}
/// Convert method
///
json Acts::JsonGeometryConverter::materialMapsToJson(
const DetectorMaterialMaps& maps) {
DetectorRep detRep;
// Collect all GeometryIDs per VolumeID for the formatted output
for (auto& [key, value] : maps.first) {
geo_id_value vid = key.volume();
auto volRep = detRep.volumes.find(vid);
if (volRep == detRep.volumes.end()) {
detRep.volumes.insert({vid, VolumeRep()});
volRep = detRep.volumes.find(vid);
volRep->second.volumeID = key;
}
geo_id_value lid = key.layer();
if (lid != 0) {
// we are on a layer, get the layer rep
auto layRep = volRep->second.layers.find(lid);
if (layRep == volRep->second.layers.end()) {
volRep->second.layers.insert({lid, LayerRep()});
layRep = volRep->second.layers.find(lid);
layRep->second.layerID = key;
}
// now insert appropriately
geo_id_value sid = key.sensitive();
geo_id_value aid = key.approach();
if (sid != 0) {
layRep->second.sensitives.insert({sid, value.get()});
} else if (aid != 0) {
layRep->second.approaches.insert({aid, value.get()});
} else {
layRep->second.representing = value.get();
}
} else {
// not on a layer can only be a boundary surface
geo_id_value bid = key.boundary();
volRep->second.boundaries.insert({bid, value.get()});
}
}
for (auto& [key, value] : maps.second) {
// find the volume representation
geo_id_value vid = key.volume();
auto volRep = detRep.volumes.find(vid);
if (volRep == detRep.volumes.end()) {
detRep.volumes.insert({vid, VolumeRep()});
volRep = detRep.volumes.find(vid);
volRep->second.volumeID = key;
}
volRep->second.material = value.get();
}
// convert the detector representation to json format
return detectorRepToJson(detRep);
}
/// Create Json from a detector represenation
json Acts::JsonGeometryConverter::detectorRepToJson(const DetectorRep& detRep) {
json detectorj;
ACTS_VERBOSE("a2j: Writing json from detector representation");
ACTS_VERBOSE("a2j: Found entries for " << detRep.volumes.size()
<< " volume(s).");
json volumesj;
for (auto& [key, value] : detRep.volumes) {
json volj;
ACTS_VERBOSE("a2j: -> Writing Volume: " << key);
volj[m_cfg.namekey] = value.volumeName;
std::ostringstream svolumeID;
svolumeID << value.volumeID;
volj[m_cfg.geoidkey] = svolumeID.str();
// Write the layers
if (not value.layers.empty()) {
ACTS_VERBOSE("a2j: ---> Found " << value.layers.size() << " layer(s) ");
json layersj;
for (auto& [lkey, lvalue] : value.layers) {
ACTS_VERBOSE("a2j: ----> Convert layer " << lkey);
json layj;
std::ostringstream slayerID;
slayerID << lvalue.layerID;
layj[m_cfg.geoidkey] = slayerID.str();
// First check for approaches
if (not lvalue.approaches.empty() and m_cfg.processApproaches) {
ACTS_VERBOSE("a2j: -----> Found " << lvalue.approaches.size()
<< " approach surface(s)");
json approachesj;
for (auto& [akey, avalue] : lvalue.approaches) {
ACTS_VERBOSE("a2j: ------> Convert approach surface " << akey);
approachesj[std::to_string(akey)] = surfaceMaterialToJson(*avalue);
}
// Add to the layer json
layj[m_cfg.appkey] = approachesj;
}
// Then check for sensitive
if (not lvalue.sensitives.empty() and m_cfg.processSensitives) {
ACTS_VERBOSE("a2j: -----> Found " << lvalue.sensitives.size()
<< " sensitive surface(s)");
json sensitivesj;
for (auto& [skey, svalue] : lvalue.sensitives) {
ACTS_VERBOSE("a2j: ------> Convert sensitive surface " << skey);
sensitivesj[std::to_string(skey)] = surfaceMaterialToJson(*svalue);
}
// Add to the layer json
layj[m_cfg.senkey] = sensitivesj;
}
// Finally check for representing
if (lvalue.representing != nullptr and m_cfg.processRepresenting) {
ACTS_VERBOSE("a2j: ------> Convert representing surface ");
layj[m_cfg.repkey] = surfaceMaterialToJson(*lvalue.representing);
}
layersj[std::to_string(lkey)] = layj;
}
volj[m_cfg.laykey] = layersj;
}
// Write the boundary surfaces
if (not value.boundaries.empty()) {
ACTS_VERBOSE("a2j: ---> Found " << value.boundaries.size()
<< " boundary/ies ");
json boundariesj;
for (auto& [bkey, bvalue] : value.boundaries) {
ACTS_VERBOSE("a2j: ----> Convert boundary " << bkey);
boundariesj[std::to_string(bkey)] = surfaceMaterialToJson(*bvalue);
}
volj[m_cfg.boukey] = boundariesj;
}
volumesj[std::to_string(key)] = volj;
}
// Assign the volume json to the detector json
detectorj[m_cfg.volkey] = volumesj;
return detectorj;
}
/// Create the Surface Material
const Acts::ISurfaceMaterial*
Acts::JsonGeometryConverter::jsonToSurfaceMaterial(const json& material) {
Acts::ISurfaceMaterial* sMaterial = nullptr;
// The bin utility for deescribing the data
Acts::BinUtility bUtility;
// Convert the material
Acts::MaterialPropertiesMatrix mpMatrix;
// Structured binding
for (auto& [key, value] : material.items()) {
// Check json keys
if (key == m_cfg.bin0key and not value.empty()) {
bUtility += jsonToBinUtility(value);
} else if (key == m_cfg.bin1key and not value.empty()) {
bUtility += jsonToBinUtility(value);
}
if (key == m_cfg.datakey and not value.empty()) {
mpMatrix = jsonToMaterialMatrix(value);
}
}
// We have protoMaterial
if (mpMatrix.empty()) {
sMaterial = new Acts::ProtoSurfaceMaterial(bUtility);
} else if (bUtility.bins() == 1) {
sMaterial = new Acts::HomogeneousSurfaceMaterial(mpMatrix[0][0]);
} else {
sMaterial = new Acts::BinnedSurfaceMaterial(bUtility, mpMatrix);
}
// return what you have
return sMaterial;
}
json Acts::JsonGeometryConverter::trackingGeometryToJson(
const Acts::TrackingGeometry& tGeometry) {
DetectorRep detRep;
convertToRep(detRep, *tGeometry.highestTrackingVolume());
return detectorRepToJson(detRep);
}
void Acts::JsonGeometryConverter::convertToRep(
DetectorRep& detRep, const Acts::TrackingVolume& tVolume) {
// The writer reader volume representation
VolumeRep volRep;
volRep.volumeName = tVolume.volumeName();
// there are confined volumes
if (tVolume.confinedVolumes() != nullptr) {
// get through the volumes
auto& volumes = tVolume.confinedVolumes()->arrayObjects();
// loop over the volumes
for (auto& vol : volumes) {
// recursive call
convertToRep(detRep, *vol);
}
}
// Get the volume Id
Acts::GeometryID volumeID = tVolume.geoID();
geo_id_value vid = volumeID.volume();
// Write the material if there's one
if (tVolume.volumeMaterial() != nullptr) {
volRep.material = tVolume.volumeMaterial();
}
// there are confied layers
if (tVolume.confinedLayers() != nullptr) {
// get the layers
auto& layers = tVolume.confinedLayers()->arrayObjects();
// loop of the volumes
for (auto& lay : layers) {
auto layRep = convertToRep(*lay);
if (layRep) {
// it's a valid representation so let's go with it
Acts::GeometryID layerID = lay->geoID();
geo_id_value lid = layerID.layer();
volRep.layers.insert({lid, std::move(layRep)});
}
}
}
// Let's finally check the boundaries
for (auto& bsurf : tVolume.boundarySurfaces()) {
// the surface representation
auto& bssfRep = bsurf->surfaceRepresentation();
if (bssfRep.surfaceMaterial() != nullptr) {
Acts::GeometryID boundaryID = bssfRep.geoID();
geo_id_value bid = boundaryID.boundary();
// Ignore if the volumeID is not correct (i.e. shared boundary)
// if (boundaryID.value(Acts::GeometryID::volume_mask) == vid){
volRep.boundaries[bid] = bssfRep.surfaceMaterial();
//}
}
}
// Write if it's good
if (volRep) {
volRep.volumeName = tVolume.volumeName();
volRep.volumeID = volumeID;
detRep.volumes.insert({vid, std::move(volRep)});
}
return;
}
Acts::JsonGeometryConverter::LayerRep Acts::JsonGeometryConverter::convertToRep(
const Acts::Layer& tLayer) {
LayerRep layRep;
// fill layer ID information
layRep.layerID = tLayer.geoID();
if (m_cfg.processSensitives and tLayer.surfaceArray() != nullptr) {
for (auto& ssf : tLayer.surfaceArray()->surfaces()) {
if (ssf != nullptr && ssf->surfaceMaterial() != nullptr) {
Acts::GeometryID sensitiveID = ssf->geoID();
geo_id_value sid = sensitiveID.sensitive();
layRep.sensitives.insert({sid, ssf->surfaceMaterial()});
}
}
}
// the representing
if (tLayer.surfaceRepresentation().surfaceMaterial() != nullptr) {
layRep.representing = tLayer.surfaceRepresentation().surfaceMaterial();
}
// the approach
if (tLayer.approachDescriptor() != nullptr) {
for (auto& asf : tLayer.approachDescriptor()->containedSurfaces()) {
// get the surface and check for material
if (asf->surfaceMaterial() != nullptr) {
Acts::GeometryID approachID = asf->geoID();
geo_id_value aid = approachID.approach();
layRep.approaches.insert({aid, asf->surfaceMaterial()});
}
}
}
// return the layer representation
return layRep;
}
json Acts::JsonGeometryConverter::surfaceMaterialToJson(
const Acts::ISurfaceMaterial& sMaterial) {
json smj;
// lemma 0 : accept the surface
auto convertMaterialProperties =
[](const Acts::MaterialProperties& mp) -> std::vector<float> {
// convert when ready
if (mp) {
/// Return the thickness in mm
return {
mp.material().X0(), mp.material().L0(), mp.material().Ar(),
mp.material().Z(), mp.material().massDensity(), mp.thickness(),
};
}
return {};
};
// A bin utility needs to be written
const Acts::BinUtility* bUtility = nullptr;
// Check if we have a proto material
auto psMaterial = dynamic_cast<const Acts::ProtoSurfaceMaterial*>(&sMaterial);
if (psMaterial != nullptr) {
// Type is proto material
smj[m_cfg.typekey] = "proto";
bUtility = &(psMaterial->binUtility());
} else {
// Now check if we have a homogeneous material
auto hsMaterial =
dynamic_cast<const Acts::HomogeneousSurfaceMaterial*>(&sMaterial);
if (hsMaterial != nullptr) {
// type is homogeneous
smj[m_cfg.typekey] = "homogeneous";
if (m_cfg.writeData) {
// write out the data, it's a [[[X0,L0,Z,A,rho,thickness]]]
auto& mp = hsMaterial->materialProperties(0, 0);
std::vector<std::vector<std::vector<float>>> mmat = {
{convertMaterialProperties(mp)}};
smj[m_cfg.datakey] = mmat;
}
} else {
// Only option remaining: BinnedSurface material
auto bsMaterial =
dynamic_cast<const Acts::BinnedSurfaceMaterial*>(&sMaterial);
if (bsMaterial != nullptr) {
// type is binned
smj[m_cfg.typekey] = "binned";
bUtility = &(bsMaterial->binUtility());
// convert the data
// get the material matrix
if (m_cfg.writeData) {
auto& mpMatrix = bsMaterial->fullMaterial();
std::vector<std::vector<std::vector<float>>> mmat;
mmat.reserve(mpMatrix.size());
for (auto& mpVector : mpMatrix) {
std::vector<std::vector<float>> mvec;
mvec.reserve(mpVector.size());
for (auto& mp : mpVector) {
mvec.push_back(convertMaterialProperties(mp));
}
mmat.push_back(std::move(mvec));
}
smj[m_cfg.datakey] = mmat;
}
}
}
}
// add the bin utility
if (bUtility != nullptr) {
std::vector<std::string> binkeys = {m_cfg.bin0key, m_cfg.bin1key};
// loop over dimensions and write
auto& binningData = bUtility->binningData();
// loop over the dimensions
for (size_t ibin = 0; ibin < binningData.size(); ++ibin) {
json binj;
auto cbData = binningData[ibin];
binj.push_back(Acts::binningValueNames[cbData.binvalue]);
if (cbData.option == Acts::closed) {
binj.push_back("closed");
} else {
binj.push_back("open");
}
binj.push_back(cbData.bins());
// If it's not a proto map, write min / max
if (smj[m_cfg.typekey] != "proto") {
std::pair<double, double> minMax = {cbData.min, cbData.max};
binj.push_back(minMax);
}
smj[binkeys[ibin]] = binj;
}
}
return smj;
}
/// Create the Material Matrix
Acts::MaterialPropertiesMatrix
Acts::JsonGeometryConverter::jsonToMaterialMatrix(const json& data) {
Acts::MaterialPropertiesMatrix mpMatrix;
/// This is assumed to be an array or array of array[6]
for (auto& outer : data) {
Acts::MaterialPropertiesVector mpVector;
for (auto& inner : outer) {
if (inner.size() > 5) {
mpVector.push_back(Acts::MaterialProperties(
inner[0], inner[1], inner[2], inner[3], inner[4], inner[5]));
} else {
mpVector.push_back(Acts::MaterialProperties());
}
}
mpMatrix.push_back(std::move(mpVector));
}
return mpMatrix;
}
/// Create the BinUtility for this
Acts::BinUtility Acts::JsonGeometryConverter::jsonToBinUtility(
const json& bin) {
// finding the iterator position to determine the binning value
auto bit = std::find(Acts::binningValueNames.begin(),
Acts::binningValueNames.end(), bin[0]);
size_t indx = std::distance(Acts::binningValueNames.begin(), bit);
Acts::BinningValue bval = Acts::BinningValue(indx);
Acts::BinningOption bopt = bin[1] == "open" ? Acts::open : Acts::closed;
unsigned int bins = bin[2];
float min = 0;
float max = 0;
if (bin[3].size() == 2) {
min = bin[3][0];
max = bin[3][1];
}
return Acts::BinUtility(bins, min, max, bopt, bval);
}
add_executable (JsonConversionTest JsonConversionTest.cpp)
target_include_directories (JsonConversionTest PRIVATE ${Boost_INCLUDE_DIRS})
target_link_libraries (JsonConversionTest PRIVATE ActsCore ActsJsonPlugin ActsTestsCommonHelpers ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})
add_test (NAME JsonConversionTest COMMAND JsonConversionTest)
acts_add_test_to_cdash_project (PROJECT ACore TEST JsonConversionTest TARGETS JsonConversionTest)
// This file is part of the Acts project.
//
// Copyright (C) 2019 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 http://mozilla.org/MPL/2.0/.
// clang-format off
#define BOOST_TEST_MODULE CartesianSegmentation Tests
#define BOOST_TEST_DYN_LINK
#include <boost/test/unit_test.hpp>
#include <boost/test/data/test_case.hpp>
// clang-format on
#include "Acts/Plugins/Json/JsonGeometryConverter.hpp"
#include <fstream>
#include <ios>
#include <iostream>
#include <stdexcept>
#include "Acts/Geometry/GeometryID.hpp"
#include "Acts/Material/BinnedSurfaceMaterial.hpp"
namespace Acts {
namespace Test {
BOOST_AUTO_TEST_CASE(Json_conversion) {
std::stringstream ifj;
ifj << "{";
ifj << " \"volumes\": {";
ifj << " \"2\": {";
ifj << " \"geoid\": \"[ 2 | 0 | 2 | 0 | 0 ]\",";
ifj << " \"layers\": {";
ifj << " \"2\": {";
ifj << " \"geoid\": \"[ 2 | 0 | 2 | 0 | 0 ]\",";
ifj << " \"representing\": {";
ifj << " \"bin0\": [";
ifj << " \"binR\",";
ifj << " \"open\",";
ifj << " 2,";
ifj << " [";
ifj << " 28.0,";
ifj << " 186.0";
ifj << " ]";
ifj << " ],";
ifj << " \"data\": [";
ifj << " [";
ifj << " [";
ifj << " 116.40576171875,";
ifj << " 220.39578247070313,";
ifj << " 7.115414142608643,";
ifj << " 1.42858931477799e+22,";
ifj << " 0.003504054620862007,";
ifj << " 1.0";
ifj << " ],";
ifj << " [";
ifj << " 431.8612976074219,";
ifj << " 1103.45947265625,";
ifj << " 11.447914123535156,";
ifj << " 4.5373971722490746e+21,";
ifj << " 0.0007596652721986175,";
ifj << " 1.0";
ifj << " ]";
ifj << " ]";
ifj << " ],";
ifj << " \"type\": \"binned\"";
ifj << " }";
ifj << " },";
ifj << " \"4\": {";
ifj << " \"geoid\": \"[ 2 | 0 | 4 | 0 | 0 ]\",";
ifj << " \"representing\": {";
ifj << " \"bin0\": [";
ifj << " \"binR\",";
ifj << " \"open\",";
ifj << " 2,";
ifj << " [";
ifj << " 28.0,";
ifj << " 186.0";
ifj << " ]";
ifj << " ],";
ifj << " \"data\": [";
ifj << " [";
ifj << " [";
ifj << " 91.93806457519531,";
ifj << " 170.03167724609375,";
ifj << " 4.947852611541748,";
ifj << " 1.8783701146029598e+22,";
ifj << " 0.004517487715929747,";
ifj << " 1.0";
ifj << " ],";
ifj << " [";
ifj << " 566.8548583984375,";
ifj << " 1606.4842529296875,";
ifj << " 10.814791679382324,";
ifj << " 5.322017395554306e+21,";
ifj << " 0.0005397787317633629,";
ifj << " 1.0";
ifj << " ]";
ifj << " ]";
ifj << " ],";
ifj << " \"type\": \"binned\"";
ifj << " }";
ifj << " }";
ifj << " ";
ifj << " },";
ifj << " \"name\": \"\"";
ifj << " }";
ifj << " }";
ifj << "}";
json jin;
ifj >> jin;
Acts::JsonGeometryConverter::Config cfg;
Acts::JsonGeometryConverter jmConverter(cfg);
auto Map = jmConverter.jsonToMaterialMaps(jin);
auto jint = jmConverter.materialMapsToJson(Map);
BOOST_CHECK_EQUAL(jin, jint);
}
} // namespace Test
} // namespace Acts
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment