Coverage for install/scipp/utils/comparison.py: 87%
15 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-11-17 01:51 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2024-11-17 01:51 +0000
1# SPDX-License-Identifier: BSD-3-Clause
2# Copyright (c) 2023 Scipp contributors (https://github.com/scipp)
3# @author Owen Arnold
4"""
5Advanced comparisons.
6"""
8from ..core import CoordError, DataArray, DType, Variable, all, isclose
11def isnear(
12 x: DataArray,
13 y: DataArray,
14 rtol: Variable | None = None,
15 atol: Variable | None = None,
16 include_attrs: bool = True,
17 include_data: bool = True,
18 equal_nan: bool = True,
19) -> bool:
20 """
21 Similar to scipp.isclose, but intended to compare whole DataArrays.
22 Coordinates compared element by element with
24 .. code-block:: python
26 abs(x - y) <= atol + rtol * abs(y)
28 Compared coord and attr pairs are only considered equal if all
29 element-wise comparisons are True.
31 See scipp.isclose for more details on how the comparisons on each
32 item will be conducted.
34 Parameters
35 ----------
36 x:
37 lhs input
38 y:
39 rhs input
40 rtol:
41 relative tolerance (to y)
42 atol:
43 absolute tolerance
44 include_data:
45 Compare data element-wise between x, and y
46 include_attrs:
47 Compare all meta (coords and attrs) between x and y,
48 otherwise only compare coordinates from meta
49 equal_nan:
50 If ``True``, consider NaNs or infs to be equal
51 providing that they match in location and, for infs,
52 have the same sign
54 Returns
55 -------
56 :
57 ``True`` if near
59 Raises
60 ------
61 Exception:
62 If `x`, `y` are not going to be logically comparable
63 for reasons relating to shape, item naming or non-finite elements.
64 """
65 same_data: bool = (
66 all(isclose(x.data, y.data, rtol=rtol, atol=atol, equal_nan=equal_nan)).value
67 if include_data
68 else True
69 )
70 same_len = (
71 len(x.deprecated_meta) == len(y.deprecated_meta)
72 if include_attrs
73 else len(x.coords) == len(y.coords)
74 )
75 if not same_len:
76 return False
77 for key, val in x.deprecated_meta.items() if include_attrs else x.coords.items():
78 a = x.deprecated_meta[key] if include_attrs else x.coords[key]
79 b = y.deprecated_meta[key] if include_attrs else y.coords[key]
80 if a.shape != b.shape:
81 raise CoordError(
82 f'Coord (or attr) with key {key} have different'
83 f' shapes. For x, shape is {a.shape}. For y, shape = {b.shape}'
84 )
85 if val.dtype in [DType.float64, DType.float32]:
86 if not all(isclose(a, b, rtol=rtol, atol=atol, equal_nan=equal_nan)).value:
87 return False
88 return same_data