Warning, /acts/docs/core/misc/grid_axis.md is written in an unsupported language. File is not indexed.
0001 # Grid and axis
0002
0003 The `Grid` template class provides a generic binned `Grid` implementation in $N$ dimensions. `Grid` accepts a variadic list of `Axis` types, where the number of axes equals the number of desired dimensions of the `Grid`.
0004
0005 ## Axis
0006 `Axis` accepts two template parameters:
0007
0008 ```cpp
0009 template <AxisType type,
0010 AxisBoundaryType bdt = AxisBoundaryType::Open>
0011 class Axis;
0012 ```
0013
0014 where
0015 ```cpp
0016 enum class AxisBoundaryType { Open, Bound, Closed };
0017 enum class AxisType { Equidistant, Variable };
0018 ```
0019
0020 ### AxisType
0021
0022 `AxisType` defines whether an axis is fully determined by $x_\text{min}$, $x_\text{max}$ and $N_\text{bins}$, or if there are variable bin boundaries $x_i = \{x_1, \ldots x_N\}$.
0023 The axis boundaries and, if necessary, the bin boundaries are provided in the constructor.
0024
0025
0026 If at all possible, `Equidistant` is preferable, since bin $b$ can then be calculated in constant time for given $x$ as
0027
0028 $$b = \frac{\mathrm{floor}(x - x_\text{min})}{w} + 1$$
0029
0030 where $b \in \{0, 1, \ldots N_\text{bins}\}$. If the type is `Variable`, a search for the correct bin is performed over the bin boundaries.
0031
0032 ### AxisBoundaryType
0033
0034 `AxisBoundaryType` steers how out-of-bounds lookups are handled.
0035 There are three options:
0036
0037 ![The three different axis boundary types](figures/AxisBoundaryTypes.svg)
0038
0039 - **Bound**: out-of-bounds lookups resolve to the closest valid bin.
0040 - **Open**: out-of-bounds lookups resolve to dedicated underflow and overflow bins.
0041 - **Closed**: out-of-bounds lookups wrap-around to the other side of the axis.
0042
0043 ## Grid creation
0044
0045 The types of the axes have to be known at compile-time, since they are provided to the `Grid` as template parameters.
0046 Thus, the number of dimensions $N$ of the `Grid` is also fixed at compile-time.
0047 The axes can be any combination of the aforementioned variations.
0048
0049 ```cpp
0050 template <typename T, class... Axes> class Grid;
0051 ```
0052
0053 where `T` is the value type that is stored in each bin. Instances of each axis are then given to the `Grid` constructor as a tuple. This Axis instances hold the number of bins and the boundary values, which are **runtime values**.
0054
0055 The `Grid` performs a lookup by recursively visiting each axis and having it perform a lookup in the corresponding component of the input vector. The lookup methods are templated on the input vector type, which only has to support component access. Transforming in and out of the local `Grid` reference frame is not handled by the `Grid`.
0056
0057 ## Local vs global bin indices
0058
0059 The underlying data structure of the `Grid` is a one-dimensional `std::vector<T>`, where `T` is the template parameter determining the stored value type. The index of this vector is referred to as the **global bin index**.
0060 The logical index structure, where each global bin is addressed by an $N$-dimensional vector of integers is called **local bin indices**. The two can be converted into one another using
0061
0062 ```cpp
0063 using index_t = std::array<size_t, N>;
0064 index_t getLocalBinIndices(size_t bin) const;
0065 size_t getGlobalBinIndex(const index_t& localBins) const;
0066 ```
0067
0068 The local bin indices are always defined from 1 to $N_\text{bins}$ for the respective axis. Bins 0 and $N_\text{bins} + 1$ address the underflow and overflow bins, **which are always present, even if `AxisBoundaryType != Open`**.
0069
0070 ## Finding neighbors
0071
0072 The `Grid` can determine the number of neighbors around a given bin. This done by first converting the global bin index to local bin indices, and then varying the local bin indices in each dimension. At this stage, each Axis gets to decide, which indices are considered neighbors, which differs depending on `AxisBinningType`. `Open` considers the underflow and overflow bins, while `Bound` does not. `Closed` considers bins on the other side of the axis.
0073 The resulting neighbor combination around bin *B* might look like
0074
0075 | b x b | 1 | 2 | 3 |
0076 |-------|-------|------|-------|
0077 | 1 | x | 0,+1 | x |
0078 | 2 | -1, 0 | B | +1, 0 |
0079 | 3 | x | 0,-1 | x |
0080
0081 Here, the corner combinations are still missing (also true for $N>2$). This is then turned into a hypercube which in $N=2$ results in:
0082
0083 | b x b | 1 | 2 | 3 |
0084 |-------|-------|------|-------|
0085 | 1 | -1,+1 | 0,+1 | +1,+1 |
0086 | 2 | -1, 0 | B | +1, 0 |
0087 | 3 | -1,-1 | 0,-1 | +1,-1 |
0088
0089 These local bin indices are then converted into global bin indices before being returned.