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

refactor: Digitization cleanup in Examples #3865

Merged
merged 15 commits into from
Nov 20, 2024
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,66 @@
#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;

Config();

explicit Config(Acts::GeometryHierarchyMap<DigiComponentsConfig> digiCfgs);
andiwand marked this conversation as resolved.
Show resolved Hide resolved
};

/// 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 +93,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 +123,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 +132,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,19 @@

#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);

/// 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
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
Loading