Skip to content

Commit

Permalink
feat: streamline json plugin (#654)
Browse files Browse the repository at this point in the history
This PR introduces the first modules of the updated Json converters that use the nlohmann::json::to_json/from_json interface.
  • Loading branch information
asalzburger committed Jan 20, 2021
1 parent bc366d9 commit f3f5479
Show file tree
Hide file tree
Showing 10 changed files with 475 additions and 7 deletions.
2 changes: 1 addition & 1 deletion Core/include/Acts/Utilities/BinUtility.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ class BinUtility {
/// Virtual Destructor
~BinUtility() = default;

/// return the binning data vector
/// Return the binning data vector
const std::vector<BinningData>& binningData() const { return m_binningData; }

/// Return the total number of bins
Expand Down
7 changes: 2 additions & 5 deletions Core/include/Acts/Utilities/BinningData.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,6 @@
// 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/.

///////////////////////////////////////////////////////////////////
// BinUtility.h, Acts project
///////////////////////////////////////////////////////////////////
#pragma once
#include "Acts/Definitions/Algebra.hpp"
#include "Acts/Utilities/BinningType.hpp"
Expand Down Expand Up @@ -114,7 +111,7 @@ class BinningData {
checkSubStructure();
}

/// Constructor for equidistant binning
/// Constructor for non-equidistant binning
///
/// @param bOption is the binning option : open / closed
/// @param bValue is the binning value : binX, binY, etc.
Expand Down Expand Up @@ -213,7 +210,7 @@ class BinningData {
return (*this);
}

/// Destructor
BinningData() = default;
~BinningData() = default;

/// Return the number of bins - including sub bins
Expand Down
4 changes: 3 additions & 1 deletion Plugins/Json/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
add_library(
ActsPluginJson SHARED
src/JsonGeometryConverter.cpp)
src/JsonGeometryConverter.cpp
src/AlgebraJsonConverter.cpp
src/UtilitiesJsonConverter.cpp)
target_include_directories(
ActsPluginJson
PUBLIC
Expand Down
23 changes: 23 additions & 0 deletions Plugins/Json/include/Acts/Plugins/Json/AlgebraJsonConverter.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// This file is part of the Acts project.
//
// Copyright (C) 2021 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/Definitions/Algebra.hpp"

#include <nlohmann/json.hpp>

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

void to_json(nlohmann::json& j, const Transform3& t);

void from_json(const nlohmann::json& j, Transform3& t);

} // namespace Acts
29 changes: 29 additions & 0 deletions Plugins/Json/include/Acts/Plugins/Json/UtilitiesJsonConverter.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// This file is part of the Acts project.
//
// Copyright (C) 2021 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/Utilities/BinUtility.hpp"
#include "Acts/Utilities/BinningData.hpp"

#include <nlohmann/json.hpp>

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

namespace Acts {

void to_json(nlohmann::json& j, const BinningData& bd);

void from_json(const nlohmann::json& j, BinningData& bd);

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

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

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

void Acts::to_json(nlohmann::json& j, const Acts::Transform3& r) {
auto translation = r.translation();
if (translation != Acts::Vector3(0., 0., 0)) {
std::array<Acts::ActsScalar, 3> tdata = {translation.x(), translation.y(),
translation.z()};
j["translation"] = tdata;
} else {
j["translation"] = nlohmann::json();
}

auto rotation = r.rotation();
if (rotation != Acts::RotationMatrix3::Identity()) {
std::array<Acts::ActsScalar, 9> rdata = {
rotation(0, 0), rotation(0, 1), rotation(0, 2),
rotation(1, 0), rotation(1, 1), rotation(1, 2),
rotation(2, 0), rotation(2, 1), rotation(2, 2)};
j["rotation"] = rdata;
} else {
j["rotation"] = nlohmann::json();
}
}

void Acts::from_json(const nlohmann::json& j, Acts::Transform3& t) {
t = Acts::Transform3::Identity();
if (j.find("translation") != j.end() and not j["translation"].empty()) {
std::array<Acts::ActsScalar, 3> tdata = j["translation"];
t.pretranslate(Acts::Vector3(tdata[0], tdata[1], tdata[2]));
}
if (j.find("rotation") != j.end() and not j["rotation"].empty()) {
std::array<Acts::ActsScalar, 9> rdata = j["rotation"];
Acts::RotationMatrix3 rot;
rot << rdata[0], rdata[1], rdata[2], rdata[3], rdata[4], rdata[5], rdata[6],
rdata[7], rdata[8];
t.prerotate(rot);
}
}
104 changes: 104 additions & 0 deletions Plugins/Json/src/UtilitiesJsonConverter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// This file is part of the Acts project.
//
// Copyright (C) 2021 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/UtilitiesJsonConverter.hpp"

#include "Acts/Plugins/Json/AlgebraJsonConverter.hpp"

void Acts::to_json(nlohmann::json& j, const Acts::BinningData& bd) {
// Common to all bin utilities
j["min"] = bd.min;
j["max"] = bd.max;
j["option"] = (bd.option == Acts::open ? "open" : "closed");
j["value"] = Acts::binningValueNames[bd.binvalue];
int bins = bd.bins();
// Write sub bin data if present
if (bd.subBinningData != nullptr) {
nlohmann::json subjson;
to_json(subjson, *bd.subBinningData);
j["subdata"] = subjson;
j["subadditive"] = bd.subBinningAdditive;
// this modifies the bins as bins() returns total number in general
if (bd.subBinningAdditive) {
bins -= static_cast<int>(subjson["bins"]) + 1;
} else {
bins /= static_cast<int>(subjson["bins"]);
}
}
// Now distinguish between equidistant / arbitrary
if (bd.type == Acts::equidistant) {
j["type"] = "equidistant";
} else if (bd.type == Acts::arbitrary) {
j["type"] = "arbitrary";
j["boundaries"] = bd.boundaries();
}
j["bins"] = bins;
}

void Acts::from_json(const nlohmann::json& j, Acts::BinningData& bd) {
// Common to all bin utilities
float min = j["min"];
float max = j["max"];
int bins = j["bins"];
std::string valueName = j["value"];
auto valueIter = std::find(Acts::binningValueNames.begin(),
Acts::binningValueNames.end(), valueName);
Acts::BinningValue bValue = static_cast<Acts::BinningValue>(
valueIter - Acts::binningValueNames.begin());
if (bins == 1) {
bd = Acts::BinningData(bValue, min, max);
return;
}
Acts::BinningOption bOption =
(j["option"] == "open") ? Acts::open : Acts::closed;
Acts::BinningType bType =
(j["type"] == "equidistant") ? Acts::equidistant : Acts::arbitrary;

std::unique_ptr<Acts::BinningData> subBinning = nullptr;
bool subBinningAdditive = false;
if (j.find("subdata") != j.end()) {
subBinningAdditive = j["subadditive"];
}

if (bType == Acts::equidistant) {
bd = Acts::BinningData(bOption, bValue, bins, min, max,
std::move(subBinning), subBinningAdditive);
} else {
std::vector<float> boundaries = j["boundaries"];
bd = Acts::BinningData(bOption, bValue, boundaries, std::move(subBinning));
}
}

void Acts::to_json(nlohmann::json& j, const Acts::BinUtility& bu) {
nlohmann::json jbindata;
for (const auto& bdata : bu.binningData()) {
nlohmann::json jdata;
to_json(jdata, bdata);
jbindata.push_back(jdata);
}
j["binningdata"] = jbindata;
if (not bu.transform().isApprox(Acts::Transform3::Identity())) {
nlohmann::json jtrf;
to_json(jtrf, bu.transform());
j["transform"] = jtrf;
}
}

void Acts::from_json(const nlohmann::json& j, Acts::BinUtility& bu) {
bu = Acts::BinUtility();
if (j.find("transform") != j.end() and not j["transform"].empty()) {
Acts::Transform3 trf;
from_json(j["transform"], trf);
bu = Acts::BinUtility(trf);
}
for (const auto& jdata : j["binningdata"]) {
Acts::BinningData bd;
from_json(jdata, bd);
bu += Acts::BinUtility(bd);
}
}
92 changes: 92 additions & 0 deletions Tests/UnitTests/Plugins/Json/AlgebraJsonConverterTests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// This file is part of the Acts project.
//
// Copyright (C) 2021 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/Definitions/Algebra.hpp"
#include "Acts/Plugins/Json/AlgebraJsonConverter.hpp"
#include "Acts/Tests/CommonHelpers/DataDirectory.hpp"

#include <fstream>
#include <iostream>

#include <nlohmann/json.hpp>

using namespace Acts;

BOOST_AUTO_TEST_SUITE(AlgebraJsonConverter)

BOOST_AUTO_TEST_CASE(TransformRoundTripTests) {
Transform3 reference = Transform3::Identity();

std::ofstream out;

// Test the identity transform
nlohmann::json identityOut;
to_json(identityOut, reference);
out.open("Transform3_Identity.json");
out << identityOut.dump(2);
out.close();

auto in = std::ifstream("Transform3_Identity.json",
std::ifstream::in | std::ifstream::binary);
BOOST_CHECK(in.good());
nlohmann::json identityIn;
in >> identityIn;
in.close();

Transform3 test;
from_json(identityIn, test);

BOOST_CHECK(test.isApprox(reference));

// Test a pure translation transform
reference.pretranslate(Vector3(1., 2., 3.));

nlohmann::json translationOut;
to_json(translationOut, reference);
out.open("Transform3_Translation.json");
out << translationOut.dump(2);
out.close();

in = std::ifstream("Transform3_Translation.json",
std::ifstream::in | std::ifstream::binary);
BOOST_CHECK(in.good());
nlohmann::json translationIn;
in >> translationIn;
in.close();

test = Transform3::Identity();
from_json(translationIn, test);

BOOST_CHECK(test.isApprox(reference));

// Test a full transform
reference = Eigen::AngleAxis(0.12334, Vector3(1., 2., 3).normalized());
reference.pretranslate(Vector3(1., 2., 3.));

nlohmann::json fullOut;
to_json(fullOut, reference);
out.open("Transform3_Full.json");
out << fullOut.dump(2);
out.close();

in = std::ifstream("Transform3_Full.json",
std::ifstream::in | std::ifstream::binary);
BOOST_CHECK(in.good());
nlohmann::json fullIn;
in >> fullIn;
in.close();

test = Transform3::Identity();
from_json(fullIn, test);

BOOST_CHECK(test.isApprox(reference));
}

BOOST_AUTO_TEST_SUITE_END()
2 changes: 2 additions & 0 deletions Tests/UnitTests/Plugins/Json/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,5 @@ set(unittest_extra_libraries ActsPluginJson)

add_unittest(GeometryHierarchyMapJsonConverter GeometryHierarchyMapJsonConverterTests.cpp)
add_unittest(MaterialMapJsonConverter MaterialMapJsonConverterTests.cpp)
add_unittest(AlgebraJsonConverter AlgebraJsonConverterTests.cpp)
add_unittest(UtilitiesJsonConverter UtilitiesJsonConverterTests.cpp)

0 comments on commit f3f5479

Please sign in to comment.