Skip to content

Commit

Permalink
refactor: Digitization cleanup in Examples (#3865)
Browse files Browse the repository at this point in the history
Some cleanup of our digitization code in Examples

Pulled out of #3838
  • Loading branch information
andiwand authored Nov 20, 2024
1 parent 90c9e92 commit ea831bf
Show file tree
Hide file tree
Showing 22 changed files with 248 additions and 373 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,14 @@

#pragma once

#include "Acts/Definitions/Algebra.hpp"
#include "Acts/Definitions/TrackParametrization.hpp"
#include "Acts/Geometry/GeometryContext.hpp"
#include "Acts/Geometry/GeometryHierarchyMap.hpp"
#include "Acts/Utilities/Logger.hpp"
#include "ActsExamples/Digitization/DigitizationConfig.hpp"
#include "ActsExamples/Digitization/MeasurementCreation.hpp"
#include "ActsExamples/Digitization/SmearingConfig.hpp"
#include "ActsExamples/EventData/Cluster.hpp"
#include "ActsExamples/EventData/Index.hpp"
#include "ActsExamples/EventData/Measurement.hpp"
#include "ActsExamples/EventData/SimHit.hpp"
#include "ActsExamples/EventData/SimParticle.hpp"
#include "ActsExamples/Framework/DataHandle.hpp"
#include "ActsExamples/Framework/IAlgorithm.hpp"
#include "ActsExamples/Framework/ProcessCode.hpp"
Expand All @@ -29,28 +25,62 @@
#include "ActsFatras/Digitization/UncorrelatedHitSmearer.hpp"

#include <cstddef>
#include <memory>
#include <string>
#include <tuple>
#include <utility>
#include <variant>
#include <vector>

namespace ActsFatras {
class Barcode;
} // namespace ActsFatras

namespace ActsExamples {
struct AlgorithmContext;

/// Algorithm that turns simulated hits into measurements by truth smearing.
class DigitizationAlgorithm final : public IAlgorithm {
public:
class Config {
public:
/// Input collection of simulated hits.
std::string inputSimHits = "simhits";
/// Output measurements collection.
std::string outputMeasurements = "measurements";
/// Output cells map (geoID -> collection of cells).
std::string outputCells = "cells";
/// Output cluster collection.
std::string outputClusters = "clusters";
/// Output collection to map measured hits to contributing particles.
std::string outputMeasurementParticlesMap = "measurement_particles_map";
/// Output collection to map measured hits to simulated hits.
std::string outputMeasurementSimHitsMap = "measurement_simhits_map";

/// Map of surface by identifier to allow local - to global
std::unordered_map<Acts::GeometryIdentifier, const Acts::Surface*>
surfaceByIdentifier;
/// Random numbers tool.
std::shared_ptr<const RandomNumbers> randomNumbers = nullptr;
/// Flag to determine whether cell data should be written to the
/// `outputCells` collection; if true, writes (rather voluminous) cell data.
bool doOutputCells = false;
/// Flag to determine whether or not to run the clusterization; if true,
/// clusters, measurements, and sim-hit-maps are output.
bool doClusterization = true;
/// Do we merge hits or not
bool doMerge = false;
/// How close do parameters have to be to consider merged
double mergeNsigma = 1.0;
/// Consider clusters that share a corner as merged (8-cell connectivity)
bool mergeCommonCorner = false;
/// Energy deposit threshold for accepting a hit
/// For a generic readout frontend we assume 1000 e/h pairs, in Si each
/// e/h-pair requiers on average an energy of 3.65 eV (PDG review 2023,
/// Table 35.10)
/// @NOTE The default is set to 0 because this works only well with Geant4
double minEnergyDeposit = 0.0; // 1000 * 3.65 * Acts::UnitConstants::eV;
/// The digitizers per GeometryIdentifiers
Acts::GeometryHierarchyMap<DigiComponentsConfig> digitizationConfigs;
};

/// Construct the smearing algorithm.
///
/// @param config is the algorithm configuration
/// @param level is the logging level
DigitizationAlgorithm(DigitizationConfig config, Acts::Logging::Level level);
DigitizationAlgorithm(Config config, Acts::Logging::Level level);

/// Build measurement from simulation hits at input.
///
Expand All @@ -59,7 +89,7 @@ class DigitizationAlgorithm final : public IAlgorithm {
ProcessCode execute(const AlgorithmContext& ctx) const override;

/// Get const access to the config
const DigitizationConfig& config() const { return m_cfg; }
const Config& config() const { return m_cfg; }

private:
/// Helper method for creating digitized parameters from clusters
Expand Down Expand Up @@ -89,7 +119,7 @@ class DigitizationAlgorithm final : public IAlgorithm {
CombinedDigitizer<4>>;

/// Configuration of the Algorithm
DigitizationConfig m_cfg;
Config m_cfg;
/// Digitizers within geometry hierarchy
Acts::GeometryHierarchyMap<Digitizer> m_digitizers;
/// Geometric digtizer
Expand All @@ -98,17 +128,17 @@ class DigitizationAlgorithm final : public IAlgorithm {
using CellsMap =
std::map<Acts::GeometryIdentifier, std::vector<Cluster::Cell>>;

ReadDataHandle<SimHitContainer> m_simContainerReadHandle{this,
"SimHitContainer"};

WriteDataHandle<MeasurementContainer> m_measurementWriteHandle{
this, "Measurements"};
WriteDataHandle<CellsMap> m_cellsWriteHandle{this, "Cells"};
WriteDataHandle<ClusterContainer> m_clusterWriteHandle{this, "Clusters"};
WriteDataHandle<IndexMultimap<ActsFatras::Barcode>>
m_measurementParticlesMapWriteHandle{this, "MeasurementParticlesMap"};
WriteDataHandle<IndexMultimap<Index>> m_measurementSimHitsMapWriteHandle{
this, "MeasurementSimHitsMap"};
ReadDataHandle<SimHitContainer> m_inputHits{this, "InputHits"};

WriteDataHandle<MeasurementContainer> m_outputMeasurements{
this, "OutputMeasurements"};
WriteDataHandle<CellsMap> m_outputCells{this, "OutputCells"};
WriteDataHandle<ClusterContainer> m_outputClusters{this, "OutputClusters"};

WriteDataHandle<IndexMultimap<SimBarcode>> m_outputMeasurementParticlesMap{
this, "OutputMeasurementParticlesMap"};
WriteDataHandle<IndexMultimap<Index>> m_outputMeasurementSimHitsMap{
this, "OutputMeasurementSimHitsMap"};

/// Construct a fixed-size smearer from a configuration.
///
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,171 +8,22 @@

#pragma once

#include "Acts/Definitions/Algebra.hpp"
#include "Acts/Definitions/TrackParametrization.hpp"
#include "Acts/Definitions/Units.hpp"
#include "Acts/Geometry/GeometryHierarchyMap.hpp"
#include "Acts/Utilities/BinUtility.hpp"
#include "Acts/Utilities/BinningType.hpp"
#include "Acts/Utilities/Logger.hpp"
#include "Acts/Utilities/Result.hpp"
#include "ActsExamples/Digitization/DigitizationConfig.hpp"
#include "ActsExamples/Digitization/Smearers.hpp"
#include "ActsExamples/Digitization/GeometricConfig.hpp"
#include "ActsExamples/Digitization/SmearingConfig.hpp"
#include "ActsExamples/Framework/RandomNumbers.hpp"
#include "ActsFatras/Digitization/UncorrelatedHitSmearer.hpp"

#include <algorithm>
#include <cstddef>
#include <functional>
#include <map>
#include <memory>
#include <stdexcept>
#include <string>
#include <system_error>
#include <unordered_map>
#include <utility>
#include <vector>

namespace Acts {
class GeometryIdentifier;
} // namespace Acts

namespace ActsExamples {

/// Configuration struct for geometric digitization
///
/// If this is defined, then the geometric digitization
/// will create clusters with cells.
/// The BinUtility defines the segmentation and which parameters
/// are defined by this.
///
struct GeometricConfig {
// The dimensions of the measurement
std::vector<Acts::BoundIndices> indices = {};

// The (multidimensional) binning definition for the segmentation of the
// sensor
Acts::BinUtility segmentation;

// The thickness of the sensor
double thickness = 0.;

/// The charge smearer
ActsFatras::SingleParameterSmearFunction<ActsExamples::RandomEngine>
chargeSmearer = Digitization::Exact(0);

// The threshold below a cell activation is ignored
double threshold = 0.;

// Whether to assume digital readout (activation is either 0 or 1)
bool digital = false;

// Flag as strip
bool strip = false;

/// The variances for this digitization
std::map<Acts::BoundIndices, std::vector<Acts::ActsScalar>> varianceMap = {};

/// Charge generation (configurable via the chargeSmearer)
Acts::ActsScalar charge(Acts::ActsScalar path, RandomEngine &rng) const {
if (!chargeSmearer) {
return path;
}
auto res = chargeSmearer(path, rng);
if (res.ok()) {
return std::max(0.0, res->first);
} else {
throw std::runtime_error(res.error().message());
}
}

/// This generates the variances for a given cluster
///
/// @note either the variances are directly taken from a pre-read
/// variance map, or they are generated from the pitch size
///
/// @param csizes is the cluster size in the different dimensions
/// @param cmins is the cluster minimum in the different dimensions
///
/// @return a vector of variances for the cluster
std::vector<Acts::ActsScalar> variances(
const std::array<std::size_t, 2u> &csizes,
const std::array<std::size_t, 2u> &cmins) const;

/// Drift generation (currently not implemented)
/// Takes as an argument the position, and a random engine
/// @return drift direction in local 3D coordinates
Acts::Vector3 drift(const Acts::Vector3 & /*position*/,
RandomEngine & /*rng*/) const {
return Acts::Vector3(0., 0., 0.);
};
};

/// Configuration struct for the Digitization algorithm
///
/// It contains:
/// - optional GeometricConfig
/// - optional SmearingConfig
struct DigiComponentsConfig {
GeometricConfig geometricDigiConfig;
SmearingConfig smearingDigiConfig = {};
SmearingConfig smearingDigiConfig;
};

class DigitizationConfig {
public:
DigitizationConfig(bool merge, double sigma, bool commonCorner)
: DigitizationConfig(merge, sigma, commonCorner,
Acts::GeometryHierarchyMap<DigiComponentsConfig>()) {
}

DigitizationConfig(
bool doMerge, double mergeNsigma, bool mergeCommonCorner,
Acts::GeometryHierarchyMap<DigiComponentsConfig> &&digiCfgs);

explicit DigitizationConfig(
Acts::GeometryHierarchyMap<DigiComponentsConfig> &&digiCfgs);
using DigiConfigContainer = Acts::GeometryHierarchyMap<DigiComponentsConfig>;

/// Input collection of simulated hits.
std::string inputSimHits = "simhits";
/// Output measurements collection.
std::string outputMeasurements = "measurements";
/// Output cells map (geoID -> collection of cells).
std::string outputCells = "cells";
/// Output cluster collection.
std::string outputClusters = "clusters";
/// Output collection to map measured hits to contributing particles.
std::string outputMeasurementParticlesMap = "measurement_particles_map";
/// Output collection to map measured hits to simulated hits.
std::string outputMeasurementSimHitsMap = "measurement_simhits_map";
/// Map of surface by identifier to allow local - to global
std::unordered_map<Acts::GeometryIdentifier, const Acts::Surface *>
surfaceByIdentifier;
/// Random numbers tool.
std::shared_ptr<const RandomNumbers> randomNumbers = nullptr;
/// Flag to determine whether cell data should be written to the
/// `outputCells` collection; if true, writes (rather voluminous) cell data.
bool doOutputCells = false;
/// Flag to determine whether or not to run the clusterization; if true,
/// clusters, measurements, and sim-hit-maps are output.
bool doClusterization = true;
/// Do we merge hits or not
bool doMerge;
/// How close do parameters have to be to consider merged
const double mergeNsigma;
/// Consider clusters that share a corner as merged (8-cell connectivity)
const bool mergeCommonCorner;
/// Energy deposit threshold for accepting a hit
/// For a generic readout frontend we assume 1000 e/h pairs, in Si each
/// e/h-pair requiers on average an energy of 3.65 eV (PDG review 2023,
/// Table 35.10)
/// @NOTE The default is set to 0 because this works only well with Geant4
double minEnergyDeposit = 0.0; // 1000 * 3.65 * Acts::UnitConstants::eV;
/// The digitizers per GeometryIdentifiers
Acts::GeometryHierarchyMap<DigiComponentsConfig> digitizationConfigs;

std::vector<
std::pair<Acts::GeometryIdentifier, std::vector<Acts::BoundIndices>>>
getBoundIndices() const;
};
} // namespace ActsExamples
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,9 @@
#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 <map>
#include <memory>
#include <utility>
#include <vector>

namespace Acts {
class Surface;
Expand Down Expand Up @@ -66,4 +54,5 @@ struct DigitizationConfigurator {
/// it adds an appropriate entry into the digitisation configuration
void operator()(const Acts::Surface* surface);
};

} // namespace ActsExamples
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

#pragma once

#include "ActsExamples/Digitization/DigitizationAlgorithm.hpp"
#include "ActsExamples/Digitization/DigitizationConfig.hpp"

namespace ActsExamples {
Expand All @@ -18,10 +19,11 @@ class DigitizationCoordinatesConverter final {
/// Construct the converter
///
/// @param config is the configuration
explicit DigitizationCoordinatesConverter(DigitizationConfig config);
explicit DigitizationCoordinatesConverter(
DigitizationAlgorithm::Config config);

/// Get const access to the config
const DigitizationConfig& config() const { return m_cfg; }
const DigitizationAlgorithm::Config& config() const { return m_cfg; }

/// Convert the hit coordinates to the local frame.
std::tuple<double, double> globalToLocal(std::uint64_t moduleId, double x,
Expand All @@ -33,7 +35,7 @@ class DigitizationCoordinatesConverter final {

private:
/// Configuration
DigitizationConfig m_cfg;
DigitizationAlgorithm::Config m_cfg;
};

} // namespace ActsExamples
Loading

0 comments on commit ea831bf

Please sign in to comment.