Skip to content

Commit

Permalink
feat: add digitisation configuration example (#762)
Browse files Browse the repository at this point in the history
This PR allows to create a geometric digitisation file.
  • Loading branch information
asalzburger committed Apr 8, 2021
1 parent d424ca1 commit ed25abc
Show file tree
Hide file tree
Showing 9 changed files with 375 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ ActsExamples::DigitizationAlgorithm::DigitizationAlgorithm(
throw std::invalid_argument("Missing digitization configuration");
}

// create the smearers from the configuration
// Create the digitizers from the configuration
std::vector<std::pair<Acts::GeometryIdentifier, Digitizer>> digitizerInput;

for (size_t i = 0; i < m_cfg.digitizationConfigs.size(); ++i) {
Expand Down
2 changes: 1 addition & 1 deletion Examples/Detectors/TGeoDetector/src/TGeoDetector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ auto TGeoDetector::finalize(
mdecorator);

ContextDecorators tgeoContextDeocrators = {};
// return the pair of geometry and empty decorators
// Return the pair of geometry and empty decorators
return std::make_pair<TrackingGeometryPtr, ContextDecorators>(
std::move(tgeoTrackingGeometry), std::move(tgeoContextDeocrators));
}
3 changes: 2 additions & 1 deletion Examples/Io/Json/src/JsonDigitizationConfig.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,5 +169,6 @@ void ActsExamples::writeDigiConfigToJson(
std::ofstream outfile(path, std::ofstream::out | std::ofstream::binary);
// rely on exception for error handling
outfile.exceptions(std::ofstream::failbit | std::ofstream::badbit);
outfile << DigiConfigConverter("digitization-configuration").toJson(cfg);
outfile
<< DigiConfigConverter("digitization-configuration").toJson(cfg).dump(2);
}
15 changes: 15 additions & 0 deletions Examples/Run/Digitization/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,21 @@ install(
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

# Digitization for TGeo detector
add_executable(
ActsExampleDigitizationConfigTGeo
TGeoDigitizationConfigExample.cpp)
target_link_libraries(
ActsExampleDigitizationConfigTGeo
PRIVATE
ActsExamplesDigitizationCommon
ActsExamplesDetectorTGeo
)

install(
TARGETS
ActsExampleDigitizationConfigTGeo
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

add_executable(
ActsExampleDigitizationTGeo
TGeoDigitizationExample.cpp)
Expand Down
1 change: 1 addition & 0 deletions Examples/Run/Digitization/Common/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
add_library(
ActsExamplesDigitizationCommon SHARED
DigitizationConfigExample.cpp
DigitizationExample.cpp
DigitizationInput.cpp)
target_include_directories(
Expand Down
70 changes: 70 additions & 0 deletions Examples/Run/Digitization/Common/DigitizationConfigExample.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// This file is part of the Acts project.
//
// Copyright (C) 2020-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/Geometry/GeometryHierarchyMap.hpp"
#include "Acts/Geometry/TrackingGeometry.hpp"
#include "ActsExamples/Detector/IBaseDetector.hpp"
#include "ActsExamples/Geometry/CommonGeometry.hpp"
#include "ActsExamples/Io/Json/JsonDigitizationConfig.hpp"
#include "ActsExamples/Options/CommonOptions.hpp"
#include "ActsExamples/Utilities/Options.hpp"
#include "ActsExamples/Utilities/Paths.hpp"

#include <fstream>
#include <memory>

#include <boost/program_options.hpp>

#include "DigitizationInput.hpp"
#include "detail/DigitizationConfigurator.hpp"

using namespace ActsExamples;

int runDigitizationConfigExample(
int argc, char* argv[],
std::shared_ptr<ActsExamples::IBaseDetector> detector) {
// Setup and parse options
auto desc = Options::makeDefaultOptions();
Options::addSequencerOptions(desc);
Options::addGeometryOptions(desc);
Options::addMaterialOptions(desc);
Options::addDigitizationOptions(desc);

// Add specific options for this geometry
detector->addOptions(desc);
auto vm = Options::parse(desc, argc, argv);
if (vm.empty()) {
return EXIT_FAILURE;
}

// Get the input configuration
auto inputConfig =
readDigiConfigFromJson(vm["digi-config-file"].as<std::string>());

// The geometry, material and decoration
auto geometry = Geometry::build(vm, *detector);

// Build a parser and visit the geometry
ActsExamples::detail::DigitizationConfigurator digiConfigurator;
digiConfigurator.inputDigiComponents = inputConfig;
digiConfigurator.outputDigiComponents =
std::make_shared<ActsExamples::detail::DigitizationConfigurator::
CollectedOutputComponents>();

geometry.first->visitSurfaces(digiConfigurator);

Acts::GeometryHierarchyMap<DigiComponentsConfig> outputConfig(
*digiConfigurator.outputDigiComponents);

if (not vm["dump-digi-config"].as<std::string>().empty()) {
writeDigiConfigToJson(outputConfig,
vm["dump-digi-config"].as<std::string>());
}

return 0;
}
22 changes: 22 additions & 0 deletions Examples/Run/Digitization/Common/DigitizationConfigExample.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// 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

namespace ActsExamples {
class IBaseDetector;
}

/// The Digitization example
///
/// @param argc the number of argumetns of the call
/// @param argv the argument list
/// @param detector The detector descriptor instance
int runDigitizationConfigExample(
int argc, char* argv[],
std::shared_ptr<ActsExamples::IBaseDetector> detector);
247 changes: 247 additions & 0 deletions Examples/Run/Digitization/Common/detail/DigitizationConfigurator.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,247 @@
// This file is part of the Acts project.
//
// Copyright (C) 2020-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/Geometry/GeometryHierarchyMap.hpp"
#include "Acts/Geometry/GeometryIdentifier.hpp"
#include "Acts/Geometry/TrackingGeometry.hpp"
#include "Acts/Surfaces/AnnulusBounds.hpp"
#include "Acts/Surfaces/DiscTrapezoidBounds.hpp"
#include "Acts/Surfaces/RadialBounds.hpp"
#include "Acts/Surfaces/RectangleBounds.hpp"
#include "Acts/Surfaces/SurfaceBounds.hpp"
#include "Acts/Surfaces/TrapezoidBounds.hpp"
#include "Acts/Utilities/BinUtility.hpp"
#include "Acts/Utilities/BinningData.hpp"
#include "ActsExamples/Digitization/DigitizationAlgorithm.hpp"
#include "ActsExamples/Digitization/DigitizationConfig.hpp"
#include "ActsExamples/Digitization/DigitizationOptions.hpp"
#include "ActsExamples/Digitization/SmearingAlgorithm.hpp"

#include <memory>

namespace ActsExamples {
namespace detail {

/// Helper configurator that takes a simplified (per volume, per layer)
/// Input digitization file and creates a full fletched per module
/// digitization configuration file.
///
/// It acts as a visitor and then builds a fully developed digitization file
/// for the geometric digitization, filling in the correct dimensions and
/// numer of bins.
///
/// The simplified file is assumed to have just one bin for the geometric
/// digitization, which is then used to calculate the number of bins with
/// respect to the bounds range.
struct DigitizationConfigurator {
/// Simplified input components for digitization
Acts::GeometryHierarchyMap<DigiComponentsConfig> inputDigiComponents;

using CollectedOutputComponents =
std::vector<std::pair<Acts::GeometryIdentifier, DigiComponentsConfig>>;

/// Full output components for digitization
std::shared_ptr<CollectedOutputComponents> outputDigiComponents = nullptr;

/// The visitor call for the geometry
void operator()(const Acts::Surface* surface) {
if (surface->associatedDetectorElement() != nullptr) {
Acts::GeometryIdentifier geoId = surface->geometryId();
auto dInputConfig = inputDigiComponents.find((geoId));
if (dInputConfig != inputDigiComponents.end()) {
// The output config, copy over the smearing part
DigiComponentsConfig dOutputConfig;
dOutputConfig.smearingDigiConfig = dInputConfig->smearingDigiConfig;

if (not dInputConfig->geometricDigiConfig.indices.empty()) {
// Copy over what can be done
dOutputConfig.geometricDigiConfig.indices =
dInputConfig->geometricDigiConfig.indices;
dOutputConfig.geometricDigiConfig.drift =
dInputConfig->geometricDigiConfig.drift;
dOutputConfig.geometricDigiConfig.thickness =
dInputConfig->geometricDigiConfig.thickness;
dOutputConfig.geometricDigiConfig.charge =
dInputConfig->geometricDigiConfig.charge;
dOutputConfig.geometricDigiConfig.digital =
dInputConfig->geometricDigiConfig.digital;
dOutputConfig.geometricDigiConfig.variances =
dInputConfig->geometricDigiConfig.variances;

const Acts::SurfaceBounds& sBounds = surface->bounds();
auto boundValues = sBounds.values();

const auto& inputSegmentation =
dInputConfig->geometricDigiConfig.segmentation;
Acts::BinUtility outputSegmentation;

switch (sBounds.type()) {
// The module is a rectangle module
case Acts::SurfaceBounds::eRectangle: {
if (inputSegmentation.binningData()[0].binvalue == Acts::binX) {
Acts::ActsScalar minX =
boundValues[Acts::RectangleBounds::eMinX];
Acts::ActsScalar maxX =
boundValues[Acts::RectangleBounds::eMaxX];
unsigned int nBins =
(maxX - minX) / inputSegmentation.binningData()[0].step;
outputSegmentation +=
Acts::BinUtility(nBins, minX, maxX, Acts::open, Acts::binX);
}
if (inputSegmentation.binningData()[0].binvalue == Acts::binY or
inputSegmentation.dimensions() == 2) {
unsigned int accessBin =
inputSegmentation.dimensions() == 2 ? 1 : 0;
Acts::ActsScalar minY =
boundValues[Acts::RectangleBounds::eMinY];
Acts::ActsScalar maxY =
boundValues[Acts::RectangleBounds::eMaxY];
unsigned int nBins =
(maxY - minY) /
inputSegmentation.binningData()[accessBin].step;
outputSegmentation +=
Acts::BinUtility(nBins, minY, maxY, Acts::open, Acts::binY);
}
} break;

// The module is a trapezoid module
case Acts::SurfaceBounds::eTrapezoid: {
if (inputSegmentation.binningData()[0].binvalue == Acts::binX) {
Acts::ActsScalar maxX = std::max(
boundValues[Acts::TrapezoidBounds::eHalfLengthXnegY],
boundValues[Acts::TrapezoidBounds::eHalfLengthXposY]);
unsigned int nBins =
2 * maxX / inputSegmentation.binningData()[0].step;
outputSegmentation += Acts::BinUtility(nBins, -maxX, maxX,
Acts::open, Acts::binX);
}
if (inputSegmentation.binningData()[0].binvalue == Acts::binY or
inputSegmentation.dimensions() == 2) {
unsigned int accessBin =
inputSegmentation.dimensions() == 2 ? 1 : 0;
Acts::ActsScalar maxY =
boundValues[Acts::TrapezoidBounds::eHalfLengthY];
unsigned int nBins =
(2 * maxY) /
inputSegmentation.binningData()[accessBin].step;
outputSegmentation += Acts::BinUtility(nBins, -maxY, maxY,
Acts::open, Acts::binY);
}
} break;

// The module is an annulus module
case Acts::SurfaceBounds::eAnnulus: {
if (inputSegmentation.binningData()[0].binvalue == Acts::binR) {
Acts::ActsScalar minR = boundValues[Acts::AnnulusBounds::eMinR];
Acts::ActsScalar maxR = boundValues[Acts::AnnulusBounds::eMaxR];
unsigned int nBins =
(maxR - minR) / inputSegmentation.binningData()[0].step;
outputSegmentation +=
Acts::BinUtility(nBins, minR, maxR, Acts::open, Acts::binR);
}
if (inputSegmentation.binningData()[0].binvalue == Acts::binPhi or
inputSegmentation.dimensions() == 2) {
unsigned int accessBin =
inputSegmentation.dimensions() == 2 ? 1 : 0;
Acts::ActsScalar averagePhi =
boundValues[Acts::AnnulusBounds::eAveragePhi];
Acts::ActsScalar minPhi =
averagePhi - boundValues[Acts::AnnulusBounds::eMinPhiRel];
Acts::ActsScalar maxPhi =
averagePhi + boundValues[Acts::AnnulusBounds::eMaxPhiRel];
unsigned int nBins =
(maxPhi - minPhi) /
inputSegmentation.binningData()[accessBin].step;
outputSegmentation += Acts::BinUtility(
nBins, minPhi, maxPhi, Acts::open, Acts::binPhi);
}

} break;

// The module is a Disc Trapezoid
case Acts::SurfaceBounds::eDiscTrapezoid: {
Acts::ActsScalar minR =
boundValues[Acts::DiscTrapezoidBounds::eMinR];
Acts::ActsScalar maxR =
boundValues[Acts::DiscTrapezoidBounds::eMaxR];

if (inputSegmentation.binningData()[0].binvalue == Acts::binR) {
unsigned int nBins =
(maxR - minR) / inputSegmentation.binningData()[0].step;
outputSegmentation +=
Acts::BinUtility(nBins, minR, maxR, Acts::open, Acts::binR);
}
if (inputSegmentation.binningData()[0].binvalue == Acts::binPhi or
inputSegmentation.dimensions() == 2) {
unsigned int accessBin =
inputSegmentation.dimensions() == 2 ? 1 : 0;
Acts::ActsScalar hxMinR =
boundValues[Acts::DiscTrapezoidBounds::eHalfLengthXminR];
Acts::ActsScalar hxMaxR =
boundValues[Acts::DiscTrapezoidBounds::eHalfLengthXmaxR];

Acts::ActsScalar averagePhi =
boundValues[Acts::DiscTrapezoidBounds::eAveragePhi];
Acts::ActsScalar alphaMinR = std::atan2(minR, hxMinR);
Acts::ActsScalar alphaMaxR = std::atan2(maxR, hxMaxR);
Acts::ActsScalar alpha = std::max(alphaMinR, alphaMaxR);
unsigned int nBins =
2 * alpha / inputSegmentation.binningData()[accessBin].step;
outputSegmentation += Acts::BinUtility(
nBins, averagePhi - alpha, averagePhi + alpha, Acts::open,
Acts::binPhi);
}

} break;

case Acts::SurfaceBounds::eDisc: {
if (inputSegmentation.binningData()[0].binvalue == Acts::binR) {
Acts::ActsScalar minR = boundValues[Acts::RadialBounds::eMinR];
Acts::ActsScalar maxR = boundValues[Acts::RadialBounds::eMaxR];
unsigned int nBins =
(maxR - minR) / inputSegmentation.binningData()[0].step;
outputSegmentation +=
Acts::BinUtility(nBins, minR, maxR, Acts::open, Acts::binR);
}
if (inputSegmentation.binningData()[0].binvalue == Acts::binPhi or
inputSegmentation.dimensions() == 2) {
unsigned int accessBin =
inputSegmentation.dimensions() == 2 ? 1 : 0;

Acts::ActsScalar averagePhi =
boundValues[Acts::RadialBounds::eAveragePhi];
Acts::ActsScalar halfPhiSector =
boundValues[Acts::RadialBounds::eHalfPhiSector];
Acts::ActsScalar minPhi = averagePhi - halfPhiSector;
Acts::ActsScalar maxPhi = averagePhi + halfPhiSector;

unsigned int nBins =
(maxPhi - minPhi) /
inputSegmentation.binningData()[accessBin].step;
outputSegmentation += Acts::BinUtility(
nBins, minPhi, maxPhi, Acts::open, Acts::binPhi);
}

} break;

default:
break;
}
// Set the adapted segmentation class
dOutputConfig.geometricDigiConfig.segmentation = outputSegmentation;
}
// Insert into the output list
outputDigiComponents->push_back({geoId, dOutputConfig});
}
}
}
};
} // namespace detail
} // namespace ActsExamples

0 comments on commit ed25abc

Please sign in to comment.