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: Add JSON detector element #3851

Merged
merged 12 commits into from
Nov 27, 2024
1 change: 0 additions & 1 deletion Examples/Io/Json/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ add_library(
src/JsonGeometryList.cpp
src/JsonMaterialWriter.cpp
src/JsonSurfacesWriter.cpp
src/JsonSurfacesReader.cpp
src/JsonDigitizationConfig.cpp
)
target_include_directories(
Expand Down
6 changes: 6 additions & 0 deletions Examples/Python/src/Detector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -222,6 +222,12 @@ void addDetector(Context& ctx) {

patchKwargsConstructor(c);
}

{
py::class_<Acts::DetectorElementBase,
std::shared_ptr<Acts::DetectorElementBase>>(
mex, "DetectorElementBase");
}
benjaminhuth marked this conversation as resolved.
Show resolved Hide resolved
}

} // namespace Acts::Python
28 changes: 18 additions & 10 deletions Examples/Python/src/Json.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,13 @@
#include "Acts/Detector/ProtoDetector.hpp"
#include "Acts/Plugins/Json/DetectorJsonConverter.hpp"
#include "Acts/Plugins/Json/JsonMaterialDecorator.hpp"
#include "Acts/Plugins/Json/JsonSurfacesReader.hpp"
#include "Acts/Plugins/Json/MaterialMapJsonConverter.hpp"
#include "Acts/Plugins/Json/ProtoDetectorJsonConverter.hpp"
#include "Acts/Plugins/Python/Utilities.hpp"
#include "Acts/Utilities/Logger.hpp"
#include "ActsExamples/Framework/ProcessCode.hpp"
#include "ActsExamples/Io/Json/JsonMaterialWriter.hpp"
#include "ActsExamples/Io/Json/JsonSurfacesReader.hpp"
#include "ActsExamples/Io/Json/JsonSurfacesWriter.hpp"

#include <fstream>
Expand Down Expand Up @@ -153,21 +153,29 @@ void addJson(Context& ctx) {
}

{
auto sjOptions = py::class_<ActsExamples::JsonSurfacesReader::Options>(
mex, "SurfaceJsonOptions")
.def(py::init<>());
auto sjOptions =
py::class_<Acts::JsonSurfacesReader::Options>(m, "SurfaceJsonOptions")
.def(py::init<>());

ACTS_PYTHON_STRUCT_BEGIN(sjOptions,
ActsExamples::JsonSurfacesReader::Options);
ACTS_PYTHON_STRUCT_BEGIN(sjOptions, Acts::JsonSurfacesReader::Options);
ACTS_PYTHON_MEMBER(inputFile);
ACTS_PYTHON_MEMBER(jsonEntryPath);
ACTS_PYTHON_STRUCT_END();

mex.def("readSurfaceHierarchyMapFromJson",
ActsExamples::JsonSurfacesReader::readHierarchyMap);
m.def("readSurfaceHierarchyMapFromJson",
Acts::JsonSurfacesReader::readHierarchyMap);

mex.def("readSurfaceVectorFromJson",
ActsExamples::JsonSurfacesReader::readVector);
m.def("readSurfaceVectorFromJson", Acts::JsonSurfacesReader::readVector);

py::class_<Acts::JsonDetectorElement, Acts::DetectorElementBase,
std::shared_ptr<Acts::JsonDetectorElement>>(
m, "JsonDetectorElement")
.def("surface", [](Acts::JsonDetectorElement& self) {
benjaminhuth marked this conversation as resolved.
Show resolved Hide resolved
return self.surface().getSharedPtr();
});

m.def("readDetectorElementsFromJson",
Acts::JsonSurfacesReader::readDetectorElements);
}

{
Expand Down
2 changes: 2 additions & 0 deletions Plugins/Json/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ add_library(
src/VolumeJsonConverter.cpp
src/AmbiguityConfigJsonConverter.cpp
src/DetrayJsonHelper.cpp
src/JsonDetectorElement.cpp
src/JsonSurfacesReader.cpp
)
target_include_directories(
ActsPluginJson
Expand Down
38 changes: 38 additions & 0 deletions Plugins/Json/include/Acts/Plugins/Json/JsonDetectorElement.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// 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/Geometry/DetectorElementBase.hpp"

#include <nlohmann/json.hpp>

namespace Acts {

/// A implementation of a detector element, that is constructed from a
/// JSON description of a surface. The idea behind this is that it helps
/// importing whole tracking geometries from JSON files. In some parts of
/// the codebase, the existence of a detector element associated to a surface
/// has a specific meaning (e.g., flags surfaces as sensitive).
class JsonDetectorElement : public DetectorElementBase {
public:
JsonDetectorElement(const nlohmann::json &jSurface, double thickness);

Surface &surface() override;
const Surface &surface() const override;

double thickness() const override;

const Transform3 &transform(const GeometryContext &gctx) const override;

private:
std::shared_ptr<Surface> m_surface;
Transform3 m_transform{};
double m_thickness{};
};

} // namespace Acts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
#pragma once

#include "Acts/Geometry/GeometryHierarchyMap.hpp"
#include "Acts/Plugins/Json/JsonDetectorElement.hpp"

#include <memory>
#include <string>
Expand All @@ -18,9 +19,11 @@ namespace Acts {
class Surface;
}

namespace ActsExamples::JsonSurfacesReader {
namespace Acts::JsonSurfacesReader {

/// @brief Options specification for surface reading
/// The file should contain an array of json surfaces
/// as produced by the SurfaceJsonConverter tools
struct Options {
/// @brief Which input file to read from
std::string inputFile = "";
Expand All @@ -29,6 +32,7 @@ struct Options {
};

/// @brief Read the surfaces from the input file
/// For details on the file format see the options struct
///
/// @param options specifies which file and what to read
///
Expand All @@ -37,10 +41,22 @@ Acts::GeometryHierarchyMap<std::shared_ptr<Acts::Surface>> readHierarchyMap(
const Options& options);

/// @brief Read the flat surfaces from the input file
/// For details on the file format see the options struct
///
/// @param inputFile is the input file to read from
/// @param options options for surface reading
///
/// @return a vector of surfaces
std::vector<std::shared_ptr<Acts::Surface>> readVector(const Options& options);

} // namespace ActsExamples::JsonSurfacesReader
/// @brief Read the surfaces from the input file and create
benjaminhuth marked this conversation as resolved.
Show resolved Hide resolved
/// detector elements
/// For details on the file format see the options struct
///
/// @param options options for surface reading
/// @param thickness the thickness used to construct the detector element
///
/// @return a vector of surfaces
std::vector<std::shared_ptr<Acts::JsonDetectorElement>> readDetectorElements(
const Options& options, double thickness);

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

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

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

namespace Acts {

JsonDetectorElement::JsonDetectorElement(const nlohmann::json &jSurface,
double thickness)
: m_thickness(thickness) {
m_surface = Acts::SurfaceJsonConverter::fromJson(jSurface);
m_transform = Transform3JsonConverter::fromJson(jSurface["transform"]);
m_surface->assignDetectorElement(*this);
}
benjaminhuth marked this conversation as resolved.
Show resolved Hide resolved

const Surface &JsonDetectorElement::surface() const {
return *m_surface;
}

Surface &JsonDetectorElement::surface() {
return *m_surface;
}
benjaminhuth marked this conversation as resolved.
Show resolved Hide resolved

const Transform3 &JsonDetectorElement::transform(
const GeometryContext & /*gctx*/) const {
return m_transform;
}

double JsonDetectorElement::thickness() const {
return m_thickness;
}

} // namespace Acts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
// 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/.

#include "ActsExamples/Io/Json/JsonSurfacesReader.hpp"
#include "Acts/Plugins/Json/JsonSurfacesReader.hpp"

#include "Acts/Geometry/GeometryIdentifier.hpp"
#include "Acts/Plugins/Json/ActsJson.hpp"
Expand All @@ -17,7 +17,7 @@
#include <fstream>
#include <iostream>

namespace ActsExamples {
namespace Acts {

Acts::GeometryHierarchyMap<std::shared_ptr<Acts::Surface>>
JsonSurfacesReader::readHierarchyMap(
Expand Down Expand Up @@ -73,4 +73,27 @@ std::vector<std::shared_ptr<Acts::Surface>> JsonSurfacesReader::readVector(
return surfaces;
}

} // namespace ActsExamples
std::vector<std::shared_ptr<Acts::JsonDetectorElement>>
JsonSurfacesReader::readDetectorElements(const Options& options,
double thickness = 0.0) {
nlohmann::json j;
{
std::ifstream in(options.inputFile);
in >> j;
}
benjaminhuth marked this conversation as resolved.
Show resolved Hide resolved

// Walk down the path to the surface entries
nlohmann::json jSurfaces = j;
for (const auto& jep : options.jsonEntryPath) {
benjaminhuth marked this conversation as resolved.
Show resolved Hide resolved
jSurfaces = jSurfaces[jep];
paulgessinger marked this conversation as resolved.
Show resolved Hide resolved
}

std::vector<std::shared_ptr<Acts::JsonDetectorElement>> elements;
for (const auto& jSurface : jSurfaces) {
elements.emplace_back(
std::make_shared<Acts::JsonDetectorElement>(jSurface, thickness));
}
return elements;
}

} // namespace Acts
1 change: 1 addition & 0 deletions Tests/UnitTests/Plugins/Json/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,4 @@ add_unittest(SurfaceBoundsJsonConverter SurfaceBoundsJsonConverterTests.cpp)
add_unittest(SurfaceJsonConverter SurfaceJsonConverterTests.cpp)
add_unittest(VolumeBoundsJsonConverter VolumeBoundsJsonConverterTests.cpp)
add_unittest(TrackParametersJsonConverter TrackParametersJsonConverterTests.cpp)
add_unittest(JsonSurfacesReader JsonSurfacesReaderTests.cpp)
98 changes: 98 additions & 0 deletions Tests/UnitTests/Plugins/Json/JsonSurfacesReaderTests.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// 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/.

#include <boost/test/unit_test.hpp>
#include <boost/test/unit_test_suite.hpp>

#include "Acts/Definitions/Algebra.hpp"
#include "Acts/Geometry/GeometryContext.hpp"
#include "Acts/Geometry/GeometryIdentifier.hpp"
#include "Acts/Plugins/Json/JsonSurfacesReader.hpp"
#include "Acts/Plugins/Json/SurfaceJsonConverter.hpp"
#include "Acts/Surfaces/PlaneSurface.hpp"
#include "Acts/Surfaces/RectangleBounds.hpp"
#include "Acts/Utilities/Zip.hpp"

#include <filesystem>
#include <fstream>
#include <memory>

#include <Eigen/Geometry>
#include <nlohmann/json.hpp>

const std::vector<std::shared_ptr<Acts::Surface>> surfaces = []() {
std::vector<std::shared_ptr<Acts::Surface>> v;

for (int i = 0; i < 3; ++i) {
auto bounds = std::make_shared<Acts::RectangleBounds>(1.0, 1.0);
Acts::Transform3 transform = Acts::Transform3::Identity();
transform.translate(Acts::Vector3::Random());
Acts::Vector3 randomAngles = Acts::Vector3::Random();
Acts::SquareMatrix3 rotMatrix;
rotMatrix = Eigen::AngleAxis(randomAngles[0], Acts::Vector3::UnitX()) *
Eigen::AngleAxis(randomAngles[1], Acts::Vector3::UnitY()) *
Eigen::AngleAxis(randomAngles[2], Acts::Vector3::UnitZ());
transform.rotate(rotMatrix);
v.push_back(
Acts::Surface::makeShared<Acts::PlaneSurface>(transform, bounds));
}

return v;
}();

const std::string filename = "json_surfaces_reader_tests.json";

struct FileFixture {
FileFixture() {
nlohmann::json js = nlohmann::json::array();

for (const auto &s : surfaces) {
js.push_back(Acts::SurfaceJsonConverter::toJson({}, *s));
}

nlohmann::json j;
j["foo"] = js;

std::ofstream f(filename);
f << j.dump(2);
}
benjaminhuth marked this conversation as resolved.
Show resolved Hide resolved

~FileFixture() {
// std::filesystem::remove(filename);
}
};
benjaminhuth marked this conversation as resolved.
Show resolved Hide resolved

FileFixture fileFixture;

BOOST_AUTO_TEST_CASE(surface_reading_test) {
auto readBackSurfaces =
Acts::JsonSurfacesReader::readVector({filename, {"foo"}});

for (auto [refSurface, surface] : Acts::zip(surfaces, readBackSurfaces)) {
BOOST_CHECK(
refSurface->transform({}).isApprox(surface->transform({}), 1.e-4));
BOOST_CHECK(refSurface->center({}).isApprox(surface->center({}), 1.e-4));
BOOST_CHECK_EQUAL(refSurface->type(), surface->type());
BOOST_CHECK_EQUAL(refSurface->bounds().type(), surface->bounds().type());
}
benjaminhuth marked this conversation as resolved.
Show resolved Hide resolved
}

BOOST_AUTO_TEST_CASE(json_detelement_reading_test) {
auto readBackDetElements =
Acts::JsonSurfacesReader::readDetectorElements({filename, {"foo"}}, 1.0);

for (auto [refSurface, detElement] :
Acts::zip(surfaces, readBackDetElements)) {
auto surface = &detElement->surface();
BOOST_CHECK(
refSurface->transform({}).isApprox(surface->transform({}), 1.e-4));
BOOST_CHECK(refSurface->center({}).isApprox(surface->center({}), 1.e-4));
BOOST_CHECK_EQUAL(refSurface->type(), surface->type());
BOOST_CHECK_EQUAL(refSurface->bounds().type(), surface->bounds().type());
}
}
benjaminhuth marked this conversation as resolved.
Show resolved Hide resolved
Loading