Coverage for src/scores/probability/checks.py: 100%

1"""

2 This module contains methods which make assertions at runtime about the state of various data

3 structures and values

4"""

5

6 import numpy as np

7 import xarray as xr

8

9

10 def coords_increasing(da: xr.DataArray, dim: str):

11 """Checks if coordinates in a given DataArray are increasing.

12

13 Note: No in-built raise if `dim` is not a dimension of `da`.

14

15 Args:

16 da (xr.DataArray): Input data

17 dim (str): Dimension to check if increasing

18 Returns:

19 (bool): Returns True if coordinates along `dim` dimension of

20 `da` are increasing, False otherwise.

21 """

22 result = (da[dim].diff(dim) > 0).all()

23 return result

24

25

26 def cdf_values_within_bounds(cdf: xr.DataArray) -> bool:

27 """Checks that 0 <= cdf <= 1. Ignores NaNs.

28

29 Args:

30 cdf (xr.DataArray): array of CDF values

31

32 Returns:

33 (bool): `True` if `cdf` values are all between 0 and 1 whenever values are not NaN,

34 or if all values are NaN; and `False` otherwise.

35 """

36 return cdf.count() == 0 or ((cdf.min() >= 0) & (cdf.max() <= 1))

37

38

39 def check_nan_decreasing_inputs(cdf, threshold_dim, tolerance):

40 """Checks inputs to `nan_decreasing_cdfs` and `_decreasing_cdfs`."""

41

42 if threshold_dim not in cdf.dims:

43 raise ValueError(f"'{threshold_dim}' is not a dimension of `cdf`")

44

45 if tolerance < 0:

46 raise ValueError("`tolerance` must be nonnegative.")

47

48 if not coords_increasing(cdf, threshold_dim):

49 raise ValueError(f"Coordinates along '{threshold_dim}' dimension should be increasing.")

50

51 all_nan_or_no_nan = np.isnan(cdf).all(threshold_dim) | (~np.isnan(cdf)).all(threshold_dim)

52 if not all_nan_or_no_nan.all():

53 raise ValueError("CDFs should have no NaNs or be all NaN along `threshold_dim`")