Skip to content

Commit

Permalink
feat: add export to json geometry using hierarchy map (#679)
Browse files Browse the repository at this point in the history
Adding Surface writing capability to the framework.
  • Loading branch information
asalzburger committed Jan 29, 2021
1 parent 9efc8fc commit c97d2af
Show file tree
Hide file tree
Showing 11 changed files with 259 additions and 16 deletions.
3 changes: 2 additions & 1 deletion Examples/Io/Json/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
add_library(
ActsExamplesIoJson SHARED
src/JsonMaterialWriter.cpp)
src/JsonMaterialWriter.cpp
src/JsonSurfacesWriter.cpp)
target_include_directories(
ActsExamplesIoJson
PUBLIC $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +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/.

///////////////////////////////////////////////////////////////////
// JsonMaterialWriter.h
///////////////////////////////////////////////////////////////////

#pragma once

#include "Acts/Definitions/Algebra.hpp"
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// 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 "ActsExamples/Framework/IWriter.hpp"
#include <Acts/Geometry/TrackingGeometry.hpp>
#include <Acts/Utilities/Logger.hpp>

#include <limits>

namespace Acts {
class TrackingVolume;
}

namespace ActsExamples {

/// Write out the geometry for detector surfaces.
///
/// This writes a `detectors.json` file at the end of the run using the
/// default context to determine the geometry. If configured, it also writes
/// an additional file for each event using the following schema
///
/// event000000001-detectors.json
/// event000000002-detectors.json
/// ...
///
/// that uses the per-event context to determine the geometry.
class JsonSurfacesWriter : public IWriter {
public:
struct Config {
/// The tracking geometry that should be written.
std::shared_ptr<const Acts::TrackingGeometry> trackingGeometry;
/// Where to place output files.
std::string outputDir;
/// Number of decimal digits for floating point precision in output.
std::size_t outputPrecision = std::numeric_limits<float>::max_digits10;
/// Write layer surfaces
bool writeLayer = false;
/// Write layer approach
bool writeApproach = false;
/// Write sensitive surfaces
bool writeSensitive = true;
/// Write boundary surfaces
bool writeBoundary = false;
/// Whether to write the per-event file.
bool writePerEvent = false;
};

/// Construct the geometry writer.
///
/// @param cfg is the configuration object
/// @param lvl is the logging level
JsonSurfacesWriter(const Config& cfg, Acts::Logging::Level lvl);

std::string name() const final override;

/// Write geometry using the per-event context (optional).
ProcessCode write(const AlgorithmContext& context) final override;

/// Write geometry using the default context.
ProcessCode endRun() final override;

private:
Config m_cfg;
const Acts::TrackingVolume* m_world;
std::unique_ptr<const Acts::Logger> m_logger;

const Acts::Logger& logger() const { return *m_logger; }
};

} // namespace ActsExamples
2 changes: 1 addition & 1 deletion Examples/Io/Json/src/JsonMaterialWriter.cpp
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 http://mozilla.org/MPL/2.0/.

#include "ActsExamples/Plugins/Json/JsonMaterialWriter.hpp"
#include "ActsExamples/Io/Json/JsonMaterialWriter.hpp"

#include "Acts/Geometry/GeometryIdentifier.hpp"
#include "Acts/Material/BinnedSurfaceMaterial.hpp"
Expand Down
133 changes: 133 additions & 0 deletions Examples/Io/Json/src/JsonSurfacesWriter.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// 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 "ActsExamples/Io/Json/JsonSurfacesWriter.hpp"

#include "Acts/Geometry/GeometryHierarchyMap.hpp"
#include "Acts/Geometry/TrackingVolume.hpp"
#include "Acts/Plugins/Json/GeometryHierarchyMapJsonConverter.hpp"
#include "Acts/Plugins/Json/SurfaceJsonConverter.hpp"
#include "Acts/Surfaces/Surface.hpp"
#include "ActsExamples/Utilities/Paths.hpp"

using namespace ActsExamples;

JsonSurfacesWriter::JsonSurfacesWriter(const JsonSurfacesWriter::Config& cfg,
Acts::Logging::Level lvl)
: m_cfg(cfg),
m_world(nullptr),
m_logger(Acts::getDefaultLogger("JsonSurfacesWriter", lvl)) {
if (not m_cfg.trackingGeometry) {
throw std::invalid_argument("Missing tracking geometry");
}
m_world = m_cfg.trackingGeometry->highestTrackingVolume();
if (not m_world) {
throw std::invalid_argument("Could not identify the world volume");
}
}

std::string JsonSurfacesWriter::name() const {
return "JsonSurfacesWriter";
}

namespace {

using SurfaceContainer =
Acts::GeometryHierarchyMap<std::shared_ptr<const Acts::Surface>>;
using SurfaceConverter = Acts::GeometryHierarchyMapJsonConverter<
std::shared_ptr<const Acts::Surface>>;

/// Write all child surfaces and descend into confined volumes.
void collectSurfaces(std::vector<SurfaceContainer::InputElement>& cSurfaces,
const Acts::TrackingVolume& volume, bool writeLayer,
bool writeApproach, bool writeSensitive,
bool writeBoundary) {
// Process all layers that are directly stored within this volume
if (volume.confinedLayers()) {
for (auto layer : volume.confinedLayers()->arrayObjects()) {
// We jump navigation layers
if (layer->layerType() == Acts::navigation) {
continue;
}
// Layer surface
if (writeLayer) {
auto layerSurfacePtr = layer->surfaceRepresentation().getSharedPtr();
cSurfaces.push_back(SurfaceContainer::InputElement{
layer->surfaceRepresentation().geometryId(), layerSurfacePtr});
}
// Approach surfaces
if (writeApproach and layer->approachDescriptor()) {
for (auto sf : layer->approachDescriptor()->containedSurfaces()) {
cSurfaces.push_back(SurfaceContainer::InputElement{
sf->geometryId(), sf->getSharedPtr()});
}
}
// Check for sensitive surfaces
if (layer->surfaceArray() and writeSensitive) {
for (auto surface : layer->surfaceArray()->surfaces()) {
if (surface) {
cSurfaces.push_back(
SurfaceContainer::InputElement{surface->geometryId(), surface});
}
}
}
}
// This is a navigation volume, write the boundaries
if (writeBoundary) {
for (auto bsurface : volume.boundarySurfaces()) {
const auto& bsRep = bsurface->surfaceRepresentation();
cSurfaces.push_back(SurfaceContainer::InputElement{
bsRep.geometryId(), bsRep.getSharedPtr()});
}
}
}
// Step down into hierarchy to process all child volumnes
if (volume.confinedVolumes()) {
for (auto confined : volume.confinedVolumes()->arrayObjects()) {
collectSurfaces(cSurfaces, *confined.get(), writeLayer, writeApproach,
writeSensitive, writeBoundary);
}
}
}
} // namespace

ProcessCode JsonSurfacesWriter::write(const AlgorithmContext& ctx) {
if (not m_cfg.writePerEvent) {
return ProcessCode::SUCCESS;
}

std::ofstream out;
out.open(perEventFilepath(m_cfg.outputDir, "detector.json", ctx.eventNumber));

std::vector<SurfaceContainer::InputElement> cSurfaces;
collectSurfaces(cSurfaces, *m_world, m_cfg.writeLayer, m_cfg.writeApproach,
m_cfg.writeSensitive, m_cfg.writeBoundary);
SurfaceContainer sContainer(cSurfaces);

auto j = SurfaceConverter("surfaces").toJson(sContainer);
out << std::setprecision(m_cfg.outputPrecision) << j.dump(2);
out.close();

return ProcessCode::SUCCESS;
}

ProcessCode JsonSurfacesWriter::endRun() {
std::ofstream out;
out.open(joinPaths(m_cfg.outputDir, "detector.csv"));

std::vector<SurfaceContainer::InputElement> cSurfaces;
collectSurfaces(cSurfaces, *m_world, m_cfg.writeLayer, m_cfg.writeApproach,
m_cfg.writeSensitive, m_cfg.writeBoundary);
SurfaceContainer sContainer(cSurfaces);

auto j = SurfaceConverter("surfaces").toJson(sContainer);
out << std::setprecision(m_cfg.outputPrecision) << j.dump(2);
out.close();

return ProcessCode::SUCCESS;
}
13 changes: 5 additions & 8 deletions Examples/Run/Common/src/CommonOptions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,16 +93,13 @@ void ActsExamples::Options::addOutputOptions(
// Add specific options for this example
opt.add_options()("output-dir", value<std::string>()->default_value(""),
"Output directory location.")(
"output-root", value<bool>()->default_value(false),
"output-root", bool_switch(),
"Switch on to write '.root' output file(s).")(
"output-csv", value<bool>()->default_value(false),
"Switch on to write '.csv' output file(s).")(
"output-obj", value<bool>()->default_value(false),
"Switch on to write '.obj' ouput file(s).")(
"output-json", value<bool>()->default_value(false),
"output-csv", bool_switch(), "Switch on to write '.csv' output file(s).")(
"output-obj", bool_switch(), "Switch on to write '.obj' ouput file(s).")(
"output-json", bool_switch(),
"Switch on to write '.json' ouput file(s).")(
"output-txt", value<bool>()->default_value(false),
"Switch on to write '.txt' ouput file(s).");
"output-txt", bool_switch(), "Switch on to write '.txt' ouput file(s).");
}

void ActsExamples::Options::addInputOptions(
Expand Down
16 changes: 15 additions & 1 deletion Examples/Run/Common/src/GeometryExampleBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,10 @@
#include "ActsExamples/Geometry/CommonGeometry.hpp"
#include "ActsExamples/Io/Csv/CsvOptionsWriter.hpp"
#include "ActsExamples/Io/Csv/CsvTrackingGeometryWriter.hpp"
#include "ActsExamples/Io/Json/JsonMaterialWriter.hpp"
#include "ActsExamples/Io/Json/JsonSurfacesWriter.hpp"
#include "ActsExamples/Io/Root/RootMaterialWriter.hpp"
#include "ActsExamples/Options/CommonOptions.hpp"
#include "ActsExamples/Plugins/Json/JsonMaterialWriter.hpp"
#include "ActsExamples/Plugins/Obj/ObjTrackingGeometryWriter.hpp"
#include "ActsExamples/Plugins/Obj/ObjWriterOptions.hpp"
#include "ActsExamples/Utilities/Options.hpp"
Expand Down Expand Up @@ -114,6 +115,19 @@ int processGeometry(int argc, char* argv[],
tgCsvWriter->write(context);
}

// JSON output
if (vm["output-json"].as<bool>()) {
ActsExamples::JsonSurfacesWriter::Config sJsonWriterConfig;
sJsonWriterConfig.trackingGeometry = tGeometry;
sJsonWriterConfig.outputDir = outputDir;
sJsonWriterConfig.writePerEvent = true;
auto sJsonWriter = std::make_shared<ActsExamples::JsonSurfacesWriter>(
sJsonWriterConfig, logLevel);

// Write the tracking geometry object
sJsonWriter->write(context);
}

// Get the file name from the options
std::string materialFileName = vm["mat-output-file"].as<std::string>();

Expand Down
2 changes: 1 addition & 1 deletion Examples/Run/Common/src/MaterialMappingBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,13 @@
#include "ActsExamples/Detector/IBaseDetector.hpp"
#include "ActsExamples/Framework/Sequencer.hpp"
#include "ActsExamples/Geometry/CommonGeometry.hpp"
#include "ActsExamples/Io/Json/JsonMaterialWriter.hpp"
#include "ActsExamples/Io/Root/RootMaterialTrackReader.hpp"
#include "ActsExamples/Io/Root/RootMaterialTrackWriter.hpp"
#include "ActsExamples/Io/Root/RootMaterialWriter.hpp"
#include "ActsExamples/MaterialMapping/MaterialMapping.hpp"
#include "ActsExamples/MaterialMapping/MaterialMappingOptions.hpp"
#include "ActsExamples/Options/CommonOptions.hpp"
#include "ActsExamples/Plugins/Json/JsonMaterialWriter.hpp"
#include "ActsExamples/Propagation/PropagationOptions.hpp"
#include "ActsExamples/Utilities/Paths.hpp"
#include <Acts/Geometry/GeometryContext.hpp>
Expand Down
13 changes: 13 additions & 0 deletions Plugins/Json/include/Acts/Plugins/Json/SurfaceJsonConverter.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,19 @@ void to_json(nlohmann::json& j, const Surface& surface);
void toJson(nlohmann::json& j, const Surface& surface,
const Acts::GeometryContext& gctx);

/// Non-contextual conversion of a surface
///
/// @note it will take the default context
void to_json(nlohmann::json& j, std::shared_ptr<const Surface> surface);

/// Contextual conversion of a surface
///
/// @param j the json to be filled
/// @param surface the surface to be converted
/// @param gctx the geometry context for this
void toJson(nlohmann::json& j, std::shared_ptr<const Surface> surface,
const Acts::GeometryContext& gctx);

/// Converstion to Surface from jsonn
///
/// @param j the read-in json object
Expand Down
12 changes: 12 additions & 0 deletions Plugins/Json/src/SurfaceJsonConverter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,18 @@ void Acts::to_json(nlohmann::json& j, const Acts::Surface& surface) {
toJson(j, surface, gctx);
}

void Acts::to_json(nlohmann::json& j,
std::shared_ptr<const Acts::Surface> surface) {
Acts::GeometryContext gctx;
toJson(j, *(surface.get()), gctx);
}

void Acts::toJson(nlohmann::json& j,
std::shared_ptr<const Acts::Surface> surface,
const Acts::GeometryContext& gctx) {
toJson(j, *(surface.get()), gctx);
}

void Acts::toJson(nlohmann::json& j, const Acts::Surface& surface,
const Acts::GeometryContext& gctx) {
const auto& sBounds = surface.bounds();
Expand Down

0 comments on commit c97d2af

Please sign in to comment.