Skip to content

Commit

Permalink
feat: CSV volume layer writer (#815)
Browse files Browse the repository at this point in the history
This PR adds a new output file for Geometry in the CSV writing:
- layer/volume objects are written to CSV
  • Loading branch information
asalzburger committed May 27, 2021
1 parent d00ea63 commit e20c66e
Show file tree
Hide file tree
Showing 4 changed files with 198 additions and 15 deletions.
1 change: 1 addition & 0 deletions Core/src/Geometry/Layer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ void Acts::Layer::closeGeometry(const IMaterialDecorator* materialDecorator,
if (materialDecorator != nullptr) {
materialDecorator->decorate(*rSurface);
}
rSurface->assignGeometryId(layerID);

// also find out how the sub structure is defined
if (surfaceRepresentation().surfaceMaterial() != nullptr) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class CsvTrackingGeometryWriter : public IWriter {
bool writeBoundary = false;
/// Write the surface grid information
bool writeSurfaceGrid = true;
/// Write the layer volume representation
bool writeLayerVolume = true;
/// Whether to write the per-event file.
bool writePerEvent = false;
};
Expand Down
18 changes: 18 additions & 0 deletions Examples/Io/Csv/src/CsvOutputData.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,24 @@ struct SurfaceData {
bound_param5, bound_param6);
};

struct LayerVolumeData {
/// Surface identifier. Not available in the TrackML datasets.
uint64_t geometry_id;
/// Partially decoded surface identifier components.
uint32_t volume_id, layer_id;
/// The type of the surface bpounds object, determines the parameters filled
int volume_type;
float min_v0 = -1.f;
float max_v0 = -1.f;
float min_v1 = -1.f;
float max_v1 = -1.f;
float min_v2 = -1.f;
float max_v2 = -1.f;

DFE_NAMEDTUPLE(LayerVolumeData, geometry_id, volume_id, layer_id, min_v0,
max_v0, min_v1, max_v1, min_v2, max_v2);
};

struct SurfaceGridData {
/// Surface identifier. Not available in the TrackML datasets.
uint64_t geometry_id;
Expand Down
192 changes: 177 additions & 15 deletions Examples/Io/Csv/src/CsvTrackingGeometryWriter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "Acts/Definitions/Units.hpp"
#include "Acts/Geometry/BoundarySurfaceT.hpp"
#include "Acts/Geometry/TrackingVolume.hpp"
#include "Acts/Geometry/VolumeBounds.hpp"
#include "Acts/Plugins/Digitization/CartesianSegmentation.hpp"
#include "Acts/Plugins/Digitization/DigitizationModule.hpp"
#include "Acts/Plugins/Identification/IdentifiedDetectorElement.hpp"
Expand Down Expand Up @@ -51,6 +52,7 @@ namespace {

using SurfaceWriter = dfe::NamedTupleCsvWriter<SurfaceData>;
using SurfaceGridWriter = dfe::NamedTupleCsvWriter<SurfaceGridData>;
using LayerVolumeWriter = dfe::NamedTupleCsvWriter<LayerVolumeData>;
using BoundarySurface = Acts::BoundarySurfaceT<Acts::TrackingVolume>;

/// Write a single surface.
Expand Down Expand Up @@ -117,20 +119,148 @@ void writeBoundarySurface(SurfaceWriter& writer,

/// Write all child surfaces and descend into confined volumes.
void writeVolume(SurfaceWriter& sfWriter, SurfaceGridWriter& sfGridWriter,
LayerVolumeWriter& lvWriter,
const Acts::TrackingVolume& volume, bool writeSensitive,
bool writeBoundary, bool writeSurfaceGrid,
const Acts::GeometryContext& geoCtx) {
bool writeLayerVolume, const Acts::GeometryContext& geoCtx) {
// process all layers that are directly stored within this volume
if (volume.confinedLayers()) {
for (auto layer : volume.confinedLayers()->arrayObjects()) {
// We jump navigation layers
const auto& vTransform = volume.transform();

// Get the values of the volume boundaries
std::vector<Acts::ActsScalar> volumeBoundValues =
volume.volumeBounds().values();
std::vector<Acts::ActsScalar> lastBoundValues;
if (volume.volumeBounds().type() == Acts::VolumeBounds::eCylinder) {
auto vTranslation = vTransform.translation();
// change volume Bound values to r min , r max , z min, z max, phi min ,
// phi max
volumeBoundValues = {
volumeBoundValues[0],
volumeBoundValues[1],
vTranslation.z() - volumeBoundValues[2],
vTranslation.z() + volumeBoundValues[2],
volumeBoundValues[4] - volumeBoundValues[3],
volumeBoundValues[4] + volumeBoundValues[3],
};
lastBoundValues = volumeBoundValues;
}

/// Helper method for layer volume writing
///
/// @param lv the layer volume to be written
/// @param transform the layer transform
/// @param representingBoundValues [in,out] the bound values
/// @param last is the last layer
auto writeCylinderLayerVolume =
[&](const Acts::Layer& lv, const Acts::Transform3& transform,
std::vector<Acts::ActsScalar>& representingBoundValues,
bool last) -> void {
// The layer volume to be written
LayerVolumeData lvDims;
lvDims.geometry_id = lv.geometryId().value();
lvDims.volume_id = lv.geometryId().volume();
lvDims.layer_id = lv.geometryId().layer();
bool isCylinderLayer = (lv.surfaceRepresentation().bounds().type() ==
Acts::SurfaceBounds::eCylinder);

auto lTranslation = transform.translation();
// Change volume Bound values to r min , r max , z min, z max, phi min ,
// phi max
representingBoundValues = {
representingBoundValues[0],
representingBoundValues[1],
lTranslation.z() - representingBoundValues[2],
lTranslation.z() + representingBoundValues[2],
representingBoundValues[4] - representingBoundValues[3],
representingBoundValues[4] + representingBoundValues[3]};

// Synchronize
lvDims.min_v0 =
isCylinderLayer ? representingBoundValues[0] : volumeBoundValues[0];
lvDims.max_v0 =
isCylinderLayer ? representingBoundValues[1] : volumeBoundValues[1];
lvDims.min_v1 =
isCylinderLayer ? volumeBoundValues[2] : representingBoundValues[2];
lvDims.max_v1 =
isCylinderLayer ? volumeBoundValues[3] : representingBoundValues[3];
lvDims.min_v2 = representingBoundValues[4];
lvDims.max_v2 = representingBoundValues[5];

// Write the prior navigation layer
LayerVolumeData nlvDims;
nlvDims.geometry_id = lv.geometryId().value();
nlvDims.volume_id = lv.geometryId().volume();
nlvDims.layer_id = lv.geometryId().layer() - 1;
if (isCylinderLayer) {
nlvDims.min_v0 = lastBoundValues[0];
nlvDims.max_v0 = representingBoundValues[0];
nlvDims.min_v1 = lastBoundValues[2];
nlvDims.max_v1 = lastBoundValues[3];
// Reset the r min boundary
lastBoundValues[0] = representingBoundValues[1];
} else {
nlvDims.min_v0 = lastBoundValues[0];
nlvDims.max_v0 = lastBoundValues[1];
nlvDims.min_v1 = lastBoundValues[2];
nlvDims.max_v1 = representingBoundValues[2];
// Reset the r min boundary
lastBoundValues[2] = representingBoundValues[3];
}
nlvDims.min_v2 = representingBoundValues[4];
nlvDims.max_v2 = representingBoundValues[5];
lvWriter.append(nlvDims);
// Write the volume dimensions for the sensitive layer
lvWriter.append(lvDims);

// Write last if needed
if (last) {
// Write the last navigation layer volume
LayerVolumeData llvDims;
llvDims.geometry_id = lv.geometryId().value();
llvDims.volume_id = lv.geometryId().volume();
llvDims.layer_id = lv.geometryId().layer() + 1;
llvDims.min_v0 = lastBoundValues[0];
llvDims.max_v0 = lastBoundValues[1];
llvDims.min_v1 = lastBoundValues[2];
llvDims.max_v1 = lastBoundValues[3];
llvDims.min_v2 = representingBoundValues[4];
llvDims.max_v2 = representingBoundValues[5];
// Close up volume
lvWriter.append(llvDims);
}
};

unsigned int layerIdx = 0;
const auto& layers = volume.confinedLayers()->arrayObjects();
for (auto layer : layers) {
// We jump navigation layers - they will be written last
if (layer->layerType() == Acts::navigation) {
++layerIdx;
// For a correct layer volume setup, we need the navigation layers
if (writeLayerVolume) {
writeSurface(sfWriter, layer->surfaceRepresentation(), geoCtx);
}
continue;
}
// check for sensitive surfaces
if (layer->surfaceArray()) {
auto sfArray = layer->surfaceArray();

} else if (layer->surfaceArray()) {
// Get the representing volume
const auto* rVolume = layer->representingVolume();
// Write the layer volume
if (rVolume != nullptr and writeLayerVolume) {
// Get the values of the representing volume
std::vector<Acts::ActsScalar> representingBoundValues =
rVolume->volumeBounds().values();
if (rVolume->volumeBounds().type() == Acts::VolumeBounds::eCylinder) {
bool last = (layerIdx + 2 ==
volume.confinedLayers()->arrayObjects().size());
writeCylinderLayerVolume(*layer, rVolume->transform(),
representingBoundValues, last);
}
}

auto sfArray = layer->surfaceArray();
// Write the surface grid
if (writeSurfaceGrid) {
SurfaceGridData sfGrid;
sfGrid.geometry_id = layer->geometryId().value();
Expand Down Expand Up @@ -162,8 +292,29 @@ void writeVolume(SurfaceWriter& sfWriter, SurfaceGridWriter& sfGridWriter,
}
}
}
} else {
writeSurface(sfWriter, layer->surfaceRepresentation(), geoCtx);
// Layer volume definition of passive layers
if (writeLayerVolume) {
if (volume.volumeBounds().type() == Acts::VolumeBounds::eCylinder) {
// Only one passive layer present - write volume directly
if (layers.size() == 3) {
LayerVolumeData plvDims;
plvDims.geometry_id = layer->geometryId().value();
plvDims.volume_id = layer->geometryId().volume();
plvDims.layer_id = layer->geometryId().layer();
plvDims.min_v0 = volumeBoundValues[0];
plvDims.max_v0 = volumeBoundValues[1];
plvDims.min_v1 = volumeBoundValues[2];
plvDims.max_v1 = volumeBoundValues[3];
lvWriter.append(plvDims);
}
}
}
}
}
++layerIdx;
} // enf of layer loop

// This is a navigation volume, write the boundaries
if (writeBoundary) {
for (auto bsurface : volume.boundarySurfaces()) {
Expand All @@ -174,8 +325,9 @@ void writeVolume(SurfaceWriter& sfWriter, SurfaceGridWriter& sfGridWriter,
// step down into hierarchy to process all child volumnes
if (volume.confinedVolumes()) {
for (auto confined : volume.confinedVolumes()->arrayObjects()) {
writeVolume(sfWriter, sfGridWriter, *confined.get(), writeSensitive,
writeBoundary, writeSurfaceGrid, geoCtx);
writeVolume(sfWriter, sfGridWriter, lvWriter, *confined.get(),
writeSensitive, writeBoundary, writeSurfaceGrid,
writeLayerVolume, geoCtx);
}
}
}
Expand All @@ -185,15 +337,22 @@ ProcessCode CsvTrackingGeometryWriter::write(const AlgorithmContext& ctx) {
if (not m_cfg.writePerEvent) {
return ProcessCode::SUCCESS;
}

SurfaceWriter sfWriter(
perEventFilepath(m_cfg.outputDir, "detectors.csv", ctx.eventNumber),
m_cfg.outputPrecision);

SurfaceGridWriter sfGridWriter(
perEventFilepath(m_cfg.outputDir, "surface-grids.csv", ctx.eventNumber),
m_cfg.outputPrecision);

writeVolume(sfWriter, sfGridWriter, *m_world, m_cfg.writeSensitive,
m_cfg.writeSensitive, m_cfg.writeSurfaceGrid, ctx.geoContext);
LayerVolumeWriter lvWriter(
perEventFilepath(m_cfg.outputDir, "layer-volumes.csv", ctx.eventNumber),
m_cfg.outputPrecision);

writeVolume(sfWriter, sfGridWriter, lvWriter, *m_world, m_cfg.writeSensitive,
m_cfg.writeBoundary, m_cfg.writeSurfaceGrid,
m_cfg.writeLayerVolume, ctx.geoContext);
return ProcessCode::SUCCESS;
}

Expand All @@ -203,8 +362,11 @@ ProcessCode CsvTrackingGeometryWriter::endRun() {
SurfaceGridWriter sfGridWriter(
joinPaths(m_cfg.outputDir, "surface-grids.csv"), m_cfg.outputPrecision);

writeVolume(sfWriter, sfGridWriter, *m_world, m_cfg.writeSensitive,
m_cfg.writeSensitive, m_cfg.writeSurfaceGrid,
Acts::GeometryContext());
LayerVolumeWriter lvWriter(joinPaths(m_cfg.outputDir, "layer-volumes.csv"),
m_cfg.outputPrecision);

writeVolume(sfWriter, sfGridWriter, lvWriter, *m_world, m_cfg.writeSensitive,
m_cfg.writeBoundary, m_cfg.writeSurfaceGrid,
m_cfg.writeLayerVolume, Acts::GeometryContext());
return ProcessCode::SUCCESS;
}

0 comments on commit e20c66e

Please sign in to comment.