Skip to content

Commit

Permalink
feat: volume bounds to/from Json (#1660)
Browse files Browse the repository at this point in the history
Adds functionality for reading/writing volume bounds from/to json file, excluding Polyhedron and GenericCuboidVolumeBounds, as well as corresponding unit tests. Pinging @asalzburger
  • Loading branch information
Matthewharri committed Nov 10, 2022
1 parent 599dd86 commit 06d342a
Show file tree
Hide file tree
Showing 5 changed files with 289 additions and 1 deletion.
1 change: 1 addition & 0 deletions Plugins/Json/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ add_library(
src/SurfaceBoundsJsonConverter.cpp
src/SurfaceJsonConverter.cpp
src/UtilitiesJsonConverter.cpp
src/VolumeBoundsJsonConverter.cpp
src/VolumeJsonConverter.cpp)
target_include_directories(
ActsPluginJson
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
// 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/GenericCuboidVolumeBounds.hpp"
#include "Acts/Geometry/VolumeBounds.hpp"
#include "Acts/Plugins/Json/ActsJson.hpp"

#include <array>
#include <vector>

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

const static std::vector<std::string> volumeBoundTypes = {
"Cone", "Cuboid", "CutoutCylinder",
"Cylinder", "GenericCuboid", "Trapezoid"};

void to_json(nlohmann::json& j, const VolumeBounds& bounds);

void to_json(nlohmann::json& j, const GenericCuboidVolumeBounds& bounds);

/// Conversion to surfaceBounds from json
///
/// The type is given as a template argument in order to be able
/// to construct the correct fitting types for surfaces.
///
/// @param j the read-in json object
///
/// @return a shared_ptr to a surface object for type polymorphism
template <typename bounds_t>
std::unique_ptr<bounds_t> volumeBoundsFromJson(const nlohmann::json& j) {
const size_t kValues = bounds_t::BoundValues::eSize;
std::array<ActsScalar, kValues> bValues;
std::vector<ActsScalar> bVector = j["values"];
std::copy_n(bVector.begin(), kValues, bValues.begin());
return std::make_unique<bounds_t>(bValues);
}

inline std::unique_ptr<GenericCuboidVolumeBounds> genericVolumeBoundsFromJson(
const nlohmann::json& j) {
auto json_vertices = j["values"];
std::array<Vector3, 8> vertices;
for (size_t i = 0; i < 8; i++) {
vertices[i] << json_vertices[i][0], json_vertices[i][1],
json_vertices[i][2];
}
return std::make_unique<GenericCuboidVolumeBounds>(vertices);
}

/// Conversion to surfaceBounds from json
/// @param j the read-in json object
///
/// @return a shared_ptr to a surface object for type polymorphism
std::unique_ptr<VolumeBounds> unqiueVolumeBoundsFromJson(
const nlohmann::json& j);

} // namespace Acts
54 changes: 54 additions & 0 deletions Plugins/Json/src/VolumeBoundsJsonConverter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// 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/VolumeBoundsJsonConverter.hpp"

#include "Acts/Geometry/ConeVolumeBounds.hpp"
#include "Acts/Geometry/CuboidVolumeBounds.hpp"
#include "Acts/Geometry/CutoutCylinderVolumeBounds.hpp"
#include "Acts/Geometry/CylinderVolumeBounds.hpp"
#include "Acts/Geometry/GenericCuboidVolumeBounds.hpp"
#include "Acts/Geometry/TrapezoidVolumeBounds.hpp"

void Acts::to_json(nlohmann::json& j, const Acts::VolumeBounds& bounds) {
j["type"] = volumeBoundTypes[bounds.type()];
j["values"] = bounds.values();
}

void Acts::to_json(nlohmann::json& j,
const Acts::GenericCuboidVolumeBounds& bounds) {
j["type"] = volumeBoundTypes[bounds.type()];
std::vector<std::vector<double>> vertices;
for (size_t i = 0; i < bounds.values().size(); i += 3) {
vertices.push_back(
{bounds.values()[i], bounds.values()[i + 1], bounds.values()[i + 2]});
}
j["values"] = vertices;
}

std::unique_ptr<Acts::VolumeBounds> Acts::unqiueVolumeBoundsFromJson(
const nlohmann::json& j) {
const std::string type = j["type"];

if (type == "Cone") {
return volumeBoundsFromJson<ConeVolumeBounds>(j);
} else if (type == "Cuboid") {
return volumeBoundsFromJson<CuboidVolumeBounds>(j);
} else if (type == "CutoutCylinder") {
return volumeBoundsFromJson<CutoutCylinderVolumeBounds>(j);
} else if (type == "Cylinder") {
return volumeBoundsFromJson<CylinderVolumeBounds>(j);
} else if (type == "Trapezoid") {
return volumeBoundsFromJson<TrapezoidVolumeBounds>(j);
} else if (type == "GenericCuboid") {
return genericVolumeBoundsFromJson(j);
} else {
throw std::invalid_argument("Unknown volume bounds type: " + type);
}
return nullptr;
} // namespace Acts
3 changes: 2 additions & 1 deletion Tests/UnitTests/Plugins/Json/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,5 @@ add_unittest(MaterialMapJsonConverter MaterialMapJsonConverterTests.cpp)
add_unittest(AlgebraJsonConverter AlgebraJsonConverterTests.cpp)
add_unittest(UtilitiesJsonConverter UtilitiesJsonConverterTests.cpp)
add_unittest(SurfaceBoundsJsonConverter SurfaceBoundsJsonConverterTests.cpp)
add_unittest(SurfaceJsonConverter SurfaceJsonConverterTests.cpp)
add_unittest(SurfaceJsonConverter SurfaceJsonConverterTests.cpp)
add_unittest(VolumeBoundsJsonConverter VolumeBoundsJsonConverterTests.cpp)
167 changes: 167 additions & 0 deletions Tests/UnitTests/Plugins/Json/VolumeBoundsJsonConverterTests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
// 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/Definitions/Units.hpp"
#include "Acts/Geometry/ConeVolumeBounds.hpp"
#include "Acts/Geometry/CuboidVolumeBounds.hpp"
#include "Acts/Geometry/CutoutCylinderVolumeBounds.hpp"
#include "Acts/Geometry/CylinderVolumeBounds.hpp"
#include "Acts/Geometry/GenericCuboidVolumeBounds.hpp"
#include "Acts/Geometry/TrapezoidVolumeBounds.hpp"
#include "Acts/Plugins/Json/ActsJson.hpp"
#include "Acts/Plugins/Json/VolumeBoundsJsonConverter.hpp"

#include <fstream>
#include <iostream>

using namespace Acts;

BOOST_AUTO_TEST_SUITE(VolumeBoundsJsonConverter)
BOOST_AUTO_TEST_CASE(Cuboid) {
std::ofstream out("CuboidVolumeBounds.json");

auto cuboidRef = std::make_shared<const CuboidVolumeBounds>(2., 4., 6.);
nlohmann::json cuboidOut;
to_json(cuboidOut, *cuboidRef);
out << cuboidOut.dump(2);
out.close();

// Read in json file
auto in = std::ifstream("CuboidVolumeBounds.json",
std::ifstream::in | std::ifstream::binary);
BOOST_CHECK(in.good());
nlohmann::json cuboidIn;
in >> cuboidIn;
in.close();

auto cuboidTest = volumeBoundsFromJson<CuboidVolumeBounds>(cuboidIn);
BOOST_CHECK(cuboidRef->values() == cuboidTest->values());
}

BOOST_AUTO_TEST_CASE(Cylinder) {
std::ofstream out("CylinderVolumeBounds.json");

auto cylinderRef =
std::make_shared<const CylinderVolumeBounds>(10., 20., 30., M_PI / 4, 0);
nlohmann::json cylinderOut;
to_json(cylinderOut, *cylinderRef);
out << cylinderOut.dump(2);
out.close();

// Read in json file
auto in = std::ifstream("CylinderVolumeBounds.json",
std::ifstream::in | std::ifstream::binary);
BOOST_CHECK(in.good());
nlohmann::json cylinderIn;
in >> cylinderIn;
in.close();

auto cylinderTest = volumeBoundsFromJson<CylinderVolumeBounds>(cylinderIn);
BOOST_CHECK(cylinderRef->values() == cylinderTest->values());
}

BOOST_AUTO_TEST_CASE(Cone) {
std::ofstream out("ConeVolumeBounds.json");

auto coneRef = std::make_shared<const ConeVolumeBounds>(0., 0., 0.45, 0.050,
0.050, 0., M_PI);
nlohmann::json coneOut;
to_json(coneOut, *coneRef);
out << coneOut.dump(2);
out.close();

// Read in json file
auto in = std::ifstream("ConeVolumeBounds.json",
std::ifstream::in | std::ifstream::binary);
BOOST_CHECK(in.good());
nlohmann::json coneIn;
in >> coneIn;
in.close();

auto coneTest = volumeBoundsFromJson<ConeVolumeBounds>(coneIn);
BOOST_CHECK(coneRef->values() == coneTest->values());
}

BOOST_AUTO_TEST_CASE(CutoutCylinder) {
std::ofstream out("CutoutCylinderVolumeBounds.json");

auto cutoutCylinderRef =
std::make_shared<const CutoutCylinderVolumeBounds>(5, 10, 15, 30, 25);
nlohmann::json cutoutCylinderOut;
to_json(cutoutCylinderOut, *cutoutCylinderRef);
out << cutoutCylinderOut.dump(2);
out.close();

// Read in json file
auto in = std::ifstream("CutoutCylinderVolumeBounds.json",
std::ifstream::in | std::ifstream::binary);
BOOST_CHECK(in.good());
nlohmann::json cutoutCylinderIn;
in >> cutoutCylinderIn;
in.close();

auto cutoutCylinderTest =
volumeBoundsFromJson<CutoutCylinderVolumeBounds>(cutoutCylinderIn);
BOOST_CHECK(cutoutCylinderRef->values() == cutoutCylinderTest->values());
}

BOOST_AUTO_TEST_CASE(GenericCuboid) {
std::ofstream out("GenericCuboidVolumeBounds.json");
std::array<Vector3, 8> vertices;
vertices = {{{0, 0, 0},
{2, 0, 0},
{2, 1, 0},
{0, 1, 0},
{0, 0, 1},
{2, 0, 1},
{2, 1, 1},
{0, 1, 1}}};

nlohmann::json genericCuboidOut;
auto genericCuboidRef =
std::make_shared<const GenericCuboidVolumeBounds>(vertices);
to_json(genericCuboidOut, *genericCuboidRef);
out << genericCuboidOut.dump(2);
out.close();

// Read in json file
auto in = std::ifstream("GenericCuboidVolumeBounds.json",
std::ifstream::in | std::ifstream::binary);
BOOST_CHECK(in.good());
nlohmann::json genericCuboidIn;
in >> genericCuboidIn;
in.close();

auto genericCuboidTest = genericVolumeBoundsFromJson(genericCuboidIn);
BOOST_CHECK(genericCuboidRef->values() == genericCuboidTest->values());
}

BOOST_AUTO_TEST_CASE(Trapezoid) {
std::ofstream out("TrapezoidVolumeBounds.json");

auto trapezoidRef =
std::make_shared<const TrapezoidVolumeBounds>(2., 4., 6., 8.);
nlohmann::json trapezoidOut;
to_json(trapezoidOut, *trapezoidRef);
out << trapezoidOut.dump(2);
out.close();

// Read in json file
auto in = std::ifstream("TrapezoidVolumeBounds.json",
std::ifstream::in | std::ifstream::binary);
BOOST_CHECK(in.good());
nlohmann::json trapezoidIn;
in >> trapezoidIn;
in.close();

auto trapezoidTest = volumeBoundsFromJson<TrapezoidVolumeBounds>(trapezoidIn);
BOOST_CHECK(trapezoidRef->values() == trapezoidTest->values());
}
BOOST_AUTO_TEST_SUITE_END()

0 comments on commit 06d342a

Please sign in to comment.