eb
compression_safeguards.safeguards.stencil.qoi.eb
Stencil quantity of interest (QoI) error bound safeguard.
Classes:
-
StencilQuantityOfInterestErrorBoundSafeguard–The
StencilQuantityOfInterestErrorBoundSafeguardguarantees that the
StencilQuantityOfInterestErrorBoundSafeguard
StencilQuantityOfInterestErrorBoundSafeguard(
qoi: StencilQuantityOfInterestExpression,
neighbourhood: Sequence[
dict[str, JSON] | NeighbourhoodBoundaryAxis
],
type: str | ErrorBound,
eb: int | float | str | Parameter,
qoi_dtype: str | ToFloatMode = lossless,
)
Bases: StencilSafeguard
The StencilQuantityOfInterestErrorBoundSafeguard guarantees that the
pointwise error type on a derived quantity of interest (QoI) over a
neighbourhood of data points is less than or equal to the provided bound
eb.
The quantity of interest is specified as a non-constant expression, in
string form, over the neighbourhood tensor X that is centred on the
pointwise value x. For example, to bound the error on the four-neighbour
box mean in a 3x3 neighbourhood (where x = X[I]), set
qoi="(X[I[0]-1, I[1]] + X[I[0]+1, I[1]] + X[I[0], I[1]-1] + X[I[0], I[1]+1]) / 4".
Note that X can be indexed absolute or relative to the centred data point
x using the index array I.
Tip: Finite Differences
The stencil QoI safeguard can also be used to bound the pointwise error of
the finite-difference-approximated derivative (of arbitrary order,
accuracy, and grid spacing) over the data by using the finite_difference
function in the qoi expression.
Tip: Monotonic Sequences
The stencil QoI safeguard can also be used to preserve the monotonicity of
a sequence of values, i.e. to guarantee that a sequence that was originally
strictly/weakly monotonically increasing/decreasing/constant still is. The
sequence can be arbitrary within the stencil neighbourhood, e.g. along a
single axis, in a zigzag, etc. Preserving the monotonicity of multiple
sequences, e.g. along several axes, requires multiple stencil QoI
safeguards. For instance, to guarantee that strictly increasing/decreasing
sequences along a single axis stay strictly increasing/decreasing, use the
following qoi expression with an absolute error bound of zero (more
monotonicity QoIs, including strict vs weak monotonicity and constant
sequences, can be found in test_monotonicity.py):
all([
# strictly decreasing sequences stay strictly decreasing
all(X[1:] < X[:-1]) == all(C["$X"][1:] < C["$X"][:-1]),
# strictly increasing sequences stay strictly increasing
all(X[1:] > X[:-1]) == all(C["$X"][1:] > C["$X"][:-1]),
])
The shape of the data neighbourhood is specified as an ordered list of unique data axes and boundary conditions that are applied to these axes. If the safeguard is applied to data with an insufficient number of dimensions, it raises an exception. If the safeguard is applied to data with additional dimensions, it is indendently applied along these extra axes. For instance, a 2d QoI is applied to independently to all 2d slices in a 3d data cube.
If the data neighbourhood uses the valid
boundary condition along an axis, the safeguard is only applied to data
neighbourhoods centred on data points that have sufficient points before
and after to satisfy the neighbourhood shape, i.e. it is not applied to
all data points. If the axis is smaller than required by the neighbourhood
along this axis, the safeguard is not applied. Using a different
BoundaryCondition ensures that the safeguard is
always applied to all data points.
If the derived quantity of interest for a data neighbourhood evaluates to an infinite value, this safeguard guarantees that the quantity of interest on the corrected data neighbourhood produces the exact same infinite value. For a NaN quantity of interest, this safeguard guarantees that the quantity of interest on the corrected data neighbourhood is also NaN, but does not guarantee that it has the same bit pattern.
The error bound can be verified by evaluating the QoI in the floating-point
data type selected by qoi_dtype parameter using the
evaluate_qoi method.
Please refer to the
StencilQuantityOfInterestExpression
for the EBNF grammar that specifies the language in which the quantities of
interest are written.
The implementation was originally inspired by:
Pu Jiao, Sheng Di, Hanqi Guo, Kai Zhao, Jiannan Tian, Dingwen Tao, Xin Liang, and Franck Cappello. (2022). Toward Quantity-of-Interest Preserving Lossy Compression for Scientific Data. Proceedings of the VLDB Endowment. 16, 4 (December 2022), 697-710. Available from: doi:10.14778/3574245.3574255.
| Parameters: |
|
|---|
| Raises: |
|
|---|
Methods:
-
compute_check_neighbourhood_for_data_shape–Compute the shape of the data neighbourhood for data of a given shape.
-
evaluate_qoi–Evaluate the derived quantity of interest on the
datain the -
check_pointwise–Check which elements in the
approximationarray satisfy the error bound -
compute_safe_intervals–Compute the intervals in which the error bound is upheld with respect
-
compute_footprint–Compute the footprint of the
footarray, e.g. for expanding data -
compute_inverse_footprint–Compute the inverse footprint of the
footarray, e.g. for expanding -
truncate_data_to_qoi_shape–Truncate the
dataarray to the shape of theqoiarray that would be evaluated from it. -
expand_qoi_to_data_shape–Expand the
qoiarray to the shape of the data it was evaluated from. -
get_config–Returns the configuration of the safeguard.
late_bound
property
The set of late-bound parameters that this safeguard has.
Late-bound parameters are only bound when checking and applying the safeguard, in contrast to the normal early-bound parameters that are configured during safeguard initialisation.
Late-bound parameters can be used for parameters that depend on the specific data that is to be safeguarded.
compute_check_neighbourhood_for_data_shape
compute_check_neighbourhood_for_data_shape(
data_shape: tuple[int, ...],
) -> tuple[dict[BoundaryCondition, NeighbourhoodAxis], ...]
Compute the shape of the data neighbourhood for data of a given shape. Boundary conditions of the same kind are combined, but separate kinds are tracked separately.
An empty dict is returned along dimensions for which the
stencil QoI safeguard does not need to look at adjacent data points.
This method also checks that the data shape is compatible with the stencil QoI safeguard.
| Parameters: |
|---|
| Returns: |
|
|---|
| Raises: |
|
|---|
evaluate_qoi
evaluate_qoi(
data: ndarray[S, dtype[T]], late_bound: Bindings
) -> ndarray[tuple[int, ...], dtype[F]]
Evaluate the derived quantity of interest on the data in the
floating-point data type selected by the qoi_dtype parameter.
The quantity of interest may have a different shape if the valid boundary condition is used along any axis.
| Parameters: |
|---|
| Returns: |
|---|
| Raises: |
|
|---|
check_pointwise
check_pointwise(
data: ndarray[S, dtype[T]],
approximation: ndarray[S, dtype[T]],
*,
late_bound: Bindings,
where: Literal[True] | ndarray[S, dtype[bool]] = True,
) -> ndarray[S, dtype[bool]]
Check which elements in the approximation array satisfy the error bound
for the quantity of interest over a neighbourhood on the data.
| Parameters: |
|
|---|
| Returns: |
|---|
| Raises: |
|
|---|
compute_safe_intervals
compute_safe_intervals(
data: ndarray[S, dtype[T]],
*,
late_bound: Bindings,
where: Literal[True] | ndarray[S, dtype[bool]] = True,
) -> IntervalUnion[T, int, int]
Compute the intervals in which the error bound is upheld with respect
to the quantity of interest over a neighbourhood on the data.
| Parameters: |
|
|---|
| Returns: |
|
|---|
| Raises: |
|
|---|
compute_footprint
compute_footprint(
foot: ndarray[S, dtype[bool]],
*,
late_bound: Bindings,
where: Literal[True] | ndarray[S, dtype[bool]] = True,
) -> ndarray[S, dtype[bool]]
Compute the footprint of the foot array, e.g. for expanding data
points into the pointwise checks that they contribute to.
The footprint usually extends beyond foot & where.
| Parameters: |
|
|---|
| Returns: |
|---|
compute_inverse_footprint
compute_inverse_footprint(
foot: ndarray[S, dtype[bool]],
*,
late_bound: Bindings,
where: Literal[True] | ndarray[S, dtype[bool]] = True,
) -> ndarray[S, dtype[bool]]
Compute the inverse footprint of the foot array, e.g. for expanding
pointwise check fails into the points that could have contributed to
the failures.
The inverse footprint usually extends beyond foot & where.
| Parameters: |
|
|---|
| Returns: |
|---|
truncate_data_to_qoi_shape
truncate_data_to_qoi_shape(
data: ndarray[tuple[int, ...], dtype[T]],
) -> ndarray[tuple[int, ...], dtype[T]]
Truncate the data array to the shape of the qoi array that would be evaluated from it.
For neighbourhoods without any valid
boundaries, this method simply copies the data array. Along axes with
a valid boundary, the data is
truncated before and after by as many elements as the boundary cuts off.
This method is the lossy inverse of
expand_qoi_to_data_shape.
| Parameters: |
|---|
| Returns: |
|---|
| Raises: |
|
|---|
expand_qoi_to_data_shape
expand_qoi_to_data_shape(
qoi: ndarray[tuple[int, ...], dtype[T]],
) -> ndarray[tuple[int, ...], dtype[T]]
Expand the qoi array to the shape of the data it was evaluated from.
The qoi array is assumed to have been produced by the
evaluate_qoi method.
For neighbourhoods without any valid
boundaries, this method simply copies the qoi array. Along axes with
a valid boundary, the qoi is expanded
before and after by as many elements as the boundary cut off. These new
elements are filled with zeros.
This method can be used to produce the array for the late-bound eb
parameter by first deriving the error bound from an evaluated QoI array
(shape) and then expanding it to the data shape.
This method is the lossy inverse of
truncate_data_to_qoi_shape.
| Parameters: |
|---|
| Returns: |
|---|
| Raises: |
|
|---|