Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Geant4 detector plugin, part 2 #1759

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
4 changes: 3 additions & 1 deletion Plugins/Json/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ include(ActsTargetLinkLibrariesSystem)

add_library(
ActsPluginJson SHARED
src/MaterialMapJsonConverter.cpp
src/AlgebraJsonConverter.cpp
src/ExtentJsonConverter.cpp
src/MaterialMapJsonConverter.cpp
src/MaterialJsonConverter.cpp
src/ProtoDetectorJsonConverter.cpp
src/SurfaceBoundsJsonConverter.cpp
src/SurfaceJsonConverter.cpp
src/UtilitiesJsonConverter.cpp
Expand Down
22 changes: 22 additions & 0 deletions Plugins/Json/include/Acts/Plugins/Json/ExtentJsonConverter.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// This file is part of the Acts project.
//
// Copyright (C) 2022 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 "Acts/Geometry/Extent.hpp"
#include "Acts/Plugins/Json/ActsJson.hpp"

// Custom Json encoder/decoders. Naming is mandated by nlohmann::json and thus
// can not match our naming guidelines.
namespace Acts {

void to_json(nlohmann::json& j, const Extent& e);

void from_json(const nlohmann::json& j, Extent& e);

} // namespace Acts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// This file is part of the Acts project.
//
// Copyright (C) 2022 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 "Acts/Geometry/ProtoDetector.hpp"
#include "Acts/Plugins/Json/UtilitiesJsonConverter.hpp"

// Custom Json encoder/decoders. Naming is mandated by nlohmann::json and thus
// can not match our naming guidelines.

namespace Acts {

void to_json(nlohmann::json& j, const ProtoVolume& pv);

void from_json(const nlohmann::json& j, ProtoVolume& pv);

void to_json(nlohmann::json& j, const ProtoDetector& pd);

void from_json(const nlohmann::json& j, ProtoDetector& pd);

} // namespace Acts
13 changes: 13 additions & 0 deletions Plugins/Json/include/Acts/Plugins/Json/UtilitiesJsonConverter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "Acts/Plugins/Json/ActsJson.hpp"
#include "Acts/Utilities/BinUtility.hpp"
#include "Acts/Utilities/BinningData.hpp"
#include "Acts/Utilities/Range1D.hpp"

// Custom Json encoder/decoders. Naming is mandated by nlohmann::json and thus
// can not match our naming guidelines.
Expand All @@ -25,4 +26,16 @@ void to_json(nlohmann::json& j, const BinUtility& bu);

void from_json(const nlohmann::json& j, BinUtility& bu);

template <typename Type>
void to_json(nlohmann::json& j, const Range1D<Type>& r) {
j["min"] = r.min();
j["max"] = r.max();
}

template <typename Type>
void from_json(const nlohmann::json& j, Range1D<Type>& r) {
r.setMin(static_cast<Type>(j["min"]));
r.setMax(static_cast<Type>(j["max"]));
}

} // namespace Acts
33 changes: 33 additions & 0 deletions Plugins/Json/src/ExtentJsonConverter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
// This file is part of the Acts project.
//
// Copyright (C) 2022 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/ExtentJsonConverter.hpp"

#include "Acts/Plugins/Json/UtilitiesJsonConverter.hpp"
#include "Acts/Utilities/BinningData.hpp"
#include "Acts/Utilities/Enumerate.hpp"

void Acts::to_json(nlohmann::json& j, const Acts::Extent& e) {
const auto bValueNames = binningValueNames();
const auto& xrange = e.range();
for (auto [ib, ibv] : enumerate(s_binningValues)) {
if (e.constrains(ibv)) {
const auto& r = xrange[ib];
j[bValueNames[ib]] = r;
}
}
}

void Acts::from_json(const nlohmann::json& j, Acts::Extent& e) {
const auto bValueNames = binningValueNames();
for (auto [ib, bvn] : enumerate(bValueNames)) {
if (j.find(bvn) != j.end()) {
e.set(static_cast<BinningValue>(ib), j[bvn]["min"], j[bvn]["max"]);
asalzburger marked this conversation as resolved.
Show resolved Hide resolved
}
}
}
119 changes: 119 additions & 0 deletions Plugins/Json/src/ProtoDetectorJsonConverter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
// This file is part of the Acts project.
//
// Copyright (C) 2022 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/ProtoDetectorJsonConverter.hpp"

#include "Acts/Plugins/Json/ExtentJsonConverter.hpp"
#include "Acts/Plugins/Json/UtilitiesJsonConverter.hpp"
#include "Acts/Surfaces/Surface.hpp"

void Acts::to_json(nlohmann::json& j, const Acts::ProtoVolume& pv) {
j["name"] = pv.name;
j["extent"] = pv.extent;

/// Helper m ethod to write binnings
///
/// @param root the json root into which this is written
/// @param binning the vector of binning data
/// @param key the key for the root writing
auto writeBinning = [&](nlohmann::json& root,
const std::vector<BinningData>& binning,
const std::string& key) -> void {
nlohmann::json jbinning;
for (const auto& bd : binning) {
jbinning.push_back(bd);
}
root[key] = jbinning;
};

// The internal structure
if (pv.internal.has_value()) {
auto& its = pv.internal.value();
nlohmann::json jinternal;
if (its.layerType != Surface::SurfaceType::Other) {
jinternal["layerType"] = static_cast<int>(its.layerType);
}
if (not its.surfaceBinning.empty()) {
writeBinning(jinternal, its.surfaceBinning, "surfaceBinning");
}
j["internalStructure"] = jinternal;
}

// The container structure
if (pv.container.has_value()) {
auto& cts = pv.container.value();
nlohmann::json jcontainer;
nlohmann::json jconstituents;
for (const auto& pvc : cts.constituentVolumes) {
jconstituents.push_back(pvc);
}
jcontainer["constituents"] = jconstituents;
writeBinning(jcontainer, cts.constituentBinning, "constituentBinning");
jcontainer["layerContainer"] = cts.layerContainer;
j["containerStructure"] = jcontainer;
}
}

void Acts::from_json(const nlohmann::json& j, Acts::ProtoVolume& pv) {
pv.name = j["name"];
pv.extent = j["extent"];

/// Helper method to read binnings
///
/// @param root is the json root
/// @param binning is the vector of binning data to be filled
/// @param key is the lookup key
auto readBinning = [&](const nlohmann::json& root,
std::vector<BinningData>& binning,
const std::string& key) -> void {
// return if no surface binning in json
if (root.find(key) == root.end() or root[key].is_null()) {
return;
}

for (const auto& jbinning : root[key]) {
binning.push_back(jbinning);
}
};

// The internal structure
if (j.find("internalStructure") != j.end() and
not j["internalStructure"].is_null()) {
auto& jinternal = j["internalStructure"];
Surface::SurfaceType layerType =
static_cast<Surface::SurfaceType>(jinternal["layerType"]);
std::vector<BinningData> surfaceBinning;
readBinning(jinternal, surfaceBinning, "surfaceBinning");
pv.internal = ProtoVolume::InternalStructure{layerType, surfaceBinning};
}

// The container structure
if (j.find("containerStructure") != j.end() and
not j["containerStructure"].is_null()) {
std::vector<ProtoVolume> constituentVolumes;
auto& jcontainer = j["containerStructure"];
for (const auto& jc : jcontainer["constituents"]) {
constituentVolumes.push_back(jc);
}
std::vector<BinningData> constituentBinning;
readBinning(jcontainer, constituentBinning, "constituentBinning");
bool layerContainer = jcontainer["layerContainer"];
pv.container = ProtoVolume::ContainerStructure{
constituentVolumes, constituentBinning, layerContainer};
}
}

void Acts::to_json(nlohmann::json& j, const Acts::ProtoDetector& pd) {
j["name"] = pd.name;
j["world"] = pd.worldVolume;
}

void Acts::from_json(const nlohmann::json& j, Acts::ProtoDetector& pd) {
pd.name = j["name"];
pd.worldVolume = j["world"];
}
2 changes: 1 addition & 1 deletion Plugins/Json/src/UtilitiesJsonConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ void Acts::from_json(const nlohmann::json& j, Acts::BinningData& bd) {
Acts::binningValueNames().end(), valueName);
Acts::BinningValue bValue = static_cast<Acts::BinningValue>(
valueIter - Acts::binningValueNames().begin());
if (bins == 1) {
if (bins == 1 and not(j["type"] == "arbitrary")) {
bd = Acts::BinningData(bValue, min, max);
return;
}
Expand Down
4 changes: 3 additions & 1 deletion Tests/UnitTests/Plugins/Json/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
set(unittest_extra_libraries ActsPluginJson)

add_unittest(AlgebraJsonConverter AlgebraJsonConverterTests.cpp)
add_unittest(ExtentJsonConverter ExtentJsonConverterTests.cpp)
add_unittest(GeometryHierarchyMapJsonConverter GeometryHierarchyMapJsonConverterTests.cpp)
add_unittest(MaterialMapJsonConverter MaterialMapJsonConverterTests.cpp)
add_unittest(AlgebraJsonConverter AlgebraJsonConverterTests.cpp)
add_unittest(ProtoDetectorJsonConverter ProtoDetectorJsonConverterTests.cpp)
add_unittest(UtilitiesJsonConverter UtilitiesJsonConverterTests.cpp)
add_unittest(SurfaceBoundsJsonConverter SurfaceBoundsJsonConverterTests.cpp)
add_unittest(SurfaceJsonConverter SurfaceJsonConverterTests.cpp)
Expand Down
109 changes: 109 additions & 0 deletions Tests/UnitTests/Plugins/Json/EqualityHelpers.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
// This file is part of the Acts project.
//
// Copyright (C) 2022 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 <boost/test/unit_test.hpp>

#include "Acts/Geometry/Extent.hpp"
#include "Acts/Tests/CommonHelpers/FloatComparisons.hpp"
#include "Acts/Utilities/BinUtility.hpp"
#include "Acts/Utilities/BinningData.hpp"

#include <iostream>

namespace Acts {

/// Check whether the BinningData objects are equal
///
/// @param ba The first BinningData object
/// @param bb The second BinningData object
/// @param tolerance a tolerance parameter
///
/// @return a boolean
inline static bool isEqual(const BinningData& ba, const BinningData& bb,
float tolerance) {
bool equalBool = (ba.type == bb.type) and (ba.option == bb.option) and
(ba.binvalue == bb.binvalue) and (ba.zdim == bb.zdim) and
(ba.subBinningAdditive == bb.subBinningAdditive);

BOOST_CHECK(equalBool);
bool equalRange = (std::abs(ba.min - bb.min) < tolerance) and
(std::abs(ba.max - bb.max) < tolerance) and
(std::abs(ba.step - bb.step) < tolerance);

BOOST_CHECK(equalRange);
bool euqalStructure =
(ba.subBinningData != nullptr)
? isEqual(*ba.subBinningData, *bb.subBinningData, tolerance)
: (bb.subBinningData == nullptr);

BOOST_CHECK(euqalStructure);

bool equalBoundaries = (ba.boundaries().size() == bb.boundaries().size());
if (equalBoundaries) {
for (size_t ib = 0; ib < ba.boundaries().size(); ++ib) {
equalBoundaries =
(std::abs(ba.boundaries()[ib] - bb.boundaries()[ib]) < tolerance);
if (not equalBoundaries) {
break;
}
}
}
BOOST_CHECK(equalBoundaries);

return equalBool and equalRange and euqalStructure;
}

/// Check whether the BinUtility objects are equal
///
/// @param ba The first BinUtility object
/// @param bb the second BinUtility object
/// @param tolerance a tolerance parameter
///
/// @return a bollean if equal
inline static bool isEqual(const BinUtility& ba, const BinUtility& bb,
float tolerance) {
bool equal = (ba.binningData().size() == bb.binningData().size());
BOOST_CHECK(equal);
if (equal) {
for (size_t ib = 0; ib < ba.binningData().size(); ++ib) {
equal = isEqual(ba.binningData()[ib], bb.binningData()[ib], tolerance);
BOOST_CHECK(equal);
}
}
return equal;
}

/// check whether Extnet objects are equal - with tolerance
///
/// @param ea the first extent object
/// @param eb the second extent object
/// @param tolerance the tolerance parameter
///
/// @return bool for euqal
inline static bool isEqual(const Acts::Extent& ea, const Acts::Extent& eb,
Acts::ActsScalar tolerance = 0.) {
bool equalConstrains = true;
bool equalRange = true;
for (auto& bVal : s_binningValues) {
equalConstrains =
equalConstrains and (ea.constrains(bVal) == eb.constrains(bVal));
BOOST_CHECK(equalConstrains);
if (ea.constrains(bVal) and eb.constrains(bVal)) {
equalRange =
equalRange and std::abs(ea.min(bVal) - eb.min(bVal)) < tolerance;
equalRange =
equalRange and std::abs(ea.max(bVal) - eb.max(bVal)) < tolerance;
BOOST_CHECK(equalRange);
}
}
BOOST_CHECK(equalConstrains);
BOOST_CHECK(equalRange);
return equalRange and equalConstrains;
}

} // namespace Acts
Loading