Files
aare/docs/src/Interpolation.rst
T
lunin_landGitHub 8f8173feb6
Build on RHEL8 / build (push) Successful in 2m48s
Build on RHEL9 / build (push) Successful in 3m8s
Run tests using data on local RHEL8 / build (push) Successful in 3m34s
Build on local RHEL8 / build (push) Successful in 2m24s
CI/CD: Integrate pre-commit hooks and GitHub Actions workflow (#303)
To improve codebase quality and reduce human error, this PR introduces
the pre-commit framework. This ensures that all code adheres to project
standards before it is even committed, maintaining a consistent style
and catching common mistakes early.

Key Changes:

- Code Formatting: Automated C++ formatting using clang-format (based on
the project's .clang-format file).
- Syntax Validation: Basic checks for file integrity and syntax.
- Spell Check: Automated scanning for typos in source code and comments.
- CMake Formatting: Standardization of CMakeLists.txt and .cmake
configuration files.
- GitHub Workflow: Added a CI action that validates every Pull Request
against the pre-commit configuration to ensure compliance.

The configuration includes a [ci] block to handle automated fixes within
the PR. Currently, this is disabled. If we want the CI to automatically
commit formatting fixes back to the PR branch, this can be toggled to
true in .pre-commit-config.yaml.

```yaml
ci:
  autofix_commit_msg: [pre-commit] auto fixes from pre-commit hooks
  autofix_prs: false
  autoupdate_schedule: monthly
```

The last large commit with the fit functions, for example, was not
formatted according to the clang-format rules. This PR would allow to
avoid similar mistakes in the future.

Python fomat with `ruff` for tests and sanitiser for `.ipynb` notebooks
can be added as well.
2026-04-14 11:52:23 +02:00

7.1 KiB
Raw Blame History

Interpolation

The Interpolation class implements the η-interpolation method. This interpolation technique is based on charge sharing: for detected photon hits (e.g. clusters), it refines the estimated photon hit using information from neighboring pixels.

The method relies on the so-called η-functions, which describe the relationship between the energy measured in the central cluster pixel (the initially estimated photon hit) and the energies measured in its neighboring pixels. Depending on how much energy each neighboring pixel receives relative to the central pixel, the estimated photon hit is shifted toward that neighbor by a certain offset to the actual photon hit position in the pixel (x,y).

The mapping between the η values and the corresponding spatial photon position (x,y) can be viewed as an optimal transport problem.

One can readily compute the probability distribution Pη of the η values by forming a 2D histogram. However, the probability distribution Px,y of the true photon positions is generally unknown unless the detector is illuminated uniformly (i.e. under flat-field conditions). In a flat-field, the photon positions are uniformly distributed.

With this assumption, the problem reduces to determining a transport map T:(ηx,ηy) → (x,y), that pushes forward the distribution of (ηx,ηy) to the known uniform distribution of photon positions of a flatfield.

The map T is given by:

$$\begin{aligned} \begin{align*} T_1: & F_{x}^{-1} F_{\eta_x|\eta_y} \\ T_2: & F_{y}^{-1} F_{\eta_y|\eta_x}, \end{align*} \end{aligned}$$

where Fηx|ηy and Fηy|ηx are the conditional cumulative distribution functions e.g. Fηx|ηy(ηx,ηy)=Pηx,ηy(ηx ≤ ηx|ηy=ηy). And Fx and Fy are the cumulative distribution functions of x and y. Note as x and y are uniformly distributed Fx and Fy are the identity functions. The map T thus simplifies to

$$\begin{aligned} \begin{align*} T_1: & F_{\eta_x|\eta_y} \\ T_2: & F_{\eta_y|\eta_x}. \end{align*} \end{aligned}$$

Note that for the implementation Pη is not only a distribution of ηx, ηy but also of the estimated photon energy e. The energy level correlates slightly with the z-depth. Higher z-depth leads to more charge sharing and a different η distribution. Thus we create a mapping T for each energy level.

η-Functions:

aare::Eta2

Note

The corner value c is only relevant when one uses calculate_eta_2 or calculate_full_eta2. Otherwise its default value is cTopLeft.

Supported are the following η-functions:

η-Function on 2x2 Clusters:

Eta2x2

$$\begin{equation*} {\color{blue}{\eta_x}} = \frac{Q_{1,1}}{Q_{1,0} + Q_{1,1}} \quad \quad {\color{green}{\eta_y}} = \frac{Q_{1,1}}{Q_{0,1} + Q_{1,1}} \end{equation*}$$

The η values can range between 0,1. Note they only range between 0,1 because the position of the center pixel (red) can change. If the center pixel is in the bottom left pixel ηx will be close to zero. If the center pixel is in the bottom right pixel ηy will be close to 1.

One can apply this η not only on 2x2 clusters but on clusters with any size. Then the 2x2 subcluster with maximum energy is chosen and the η function applied on the subcluster.

aare::calculate_eta2(const ClusterVector<ClusterType>&)

aare::calculate_eta2(const Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>&)

Full η-Function on 2x2 Clusters:

Eta2x2 Full

$$\begin{equation*} {\color{blue}{\eta_x}} = \frac{Q_{0,1} + Q_{1,1}}{\sum_i^{1}\sum_j^{1}Q_{i,j}} \quad \quad {\textcolor{green}{\eta_y}} = \frac{Q_{1,0} + Q_{1,1}}{\sum_i^{1}\sum_j^{1}Q_{i,j}} \end{equation*}$$

The η values can range between 0,1. Note they only range between 0,1 because the position of the center pixel (red) can change. If the center pixel is in the bottom left pixel ηx will be close to zero. If the center pixel is in the bottom right pixel ηy will be close to 1.

aare::calculate_full_eta2(const ClusterVector<ClusterType>&)

aare::calculate_full_eta2(const Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>&)

Full η-Function on 3x3 Clusters:

Eta3x3

$$\begin{equation*} {\color{blue}{\eta_x}} = \frac{\sum_{i=0}^{2} Q_{i,2} - \sum_{i=0}^{2} Q_{i,0}}{\sum_{i=0}^{2}\sum_{j=0}^{2} Q_{i,j}} \quad \quad {\color{green}{\eta_y}} = \frac{\sum_{j=0}^{2} Q_{2,j} - \sum_{j=0}^{2} Q_{0,j}}{\sum_{i=0}^{2}\sum_{j=0}^{2} Q_{i,j}} \end{equation*}$$

The η values can range between -0.5,0.5.

aare::calculate_eta3(const ClusterVector<ClusterType>&)

aare::calculate_eta3(const Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>&)

Cross η-Function on 3x3 Clusters:

Cross Eta3x3

$$\begin{equation*} {\color{blue}{\eta_x}} = \frac{Q_{1,2} - Q_{1,0}}{Q_{1,0} + Q_{1,1} + Q_{1,2}} \quad \quad {\color{green}{\eta_y}} = \frac{Q_{0,2} - Q_{0,1}}{Q_{0,1} + Q_{1,1} + Q_{2,1}} \end{equation*}$$

The η values can range between -0.5,0.5.

aare::calculate_cross_eta3(const ClusterVector<ClusterType>&)

aare::calculate_cross_eta3(const Cluster<T, ClusterSizeX, ClusterSizeY, CoordType>&)

Interpolation class:

Warning

The interpolation might lead to erroneous photon positions for clusters at the borders of a frame. Make sure to filter out such cases.

Warning

Make sure to use the same η-function during interpolation as given by the joint η-distribution passed to the constructor.

Note

Make sure to use reasonable energy bins, when constructing the joint distribution. If data is too sparse for a given energy the interpolation will lead to erroneous results.

aare::Interpolator