|
7 | 7 |
|
8 | 8 | from functools import partial
|
9 | 9 |
|
10 |
| -import dask.array as da |
11 | 10 | import numpy as np
|
12 | 11 | from cfdm.data.dask_utils import cfdm_asanyarray
|
13 |
| -from dask.core import flatten |
14 | 12 | from scipy.ndimage import convolve1d
|
15 | 13 |
|
16 | 14 | from ..cfdatetime import dt, dt2rt, rt2dt
|
17 |
| -from ..functions import atol as cf_atol |
18 |
| -from ..functions import rtol as cf_rtol |
19 | 15 | from ..units import Units
|
20 | 16 |
|
21 | 17 |
|
22 |
| -def _da_ma_allclose(x, y, masked_equal=True, rtol=None, atol=None): |
23 |
| - """An effective dask.array.ma.allclose method. |
24 |
| -
|
25 |
| - True if two dask arrays are element-wise equal within a tolerance. |
26 |
| -
|
27 |
| - Equivalent to allclose except that masked values are treated as |
28 |
| - equal (default) or unequal, depending on the masked_equal |
29 |
| - argument. |
30 |
| -
|
31 |
| - Define an effective da.ma.allclose method here because one is |
32 |
| - currently missing in the Dask codebase. |
33 |
| -
|
34 |
| - Note that all default arguments are the same as those provided to |
35 |
| - the corresponding NumPy method (see the `numpy.ma.allclose` API |
36 |
| - reference). |
37 |
| -
|
38 |
| - .. versionadded:: 3.14.0 |
39 |
| -
|
40 |
| - :Parameters: |
41 |
| -
|
42 |
| - x: a dask array to compare with y |
43 |
| -
|
44 |
| - y: a dask array to compare with x |
45 |
| -
|
46 |
| - masked_equal: `bool`, optional |
47 |
| - Whether masked values in a and b are considered equal |
48 |
| - (True) or not (False). They are considered equal by |
49 |
| - default. |
50 |
| -
|
51 |
| - {{rtol: number, optional}} |
52 |
| -
|
53 |
| - {{atol: number, optional}} |
54 |
| -
|
55 |
| - :Returns: |
56 |
| -
|
57 |
| - `bool` |
58 |
| - A Boolean value indicating whether or not the two dask |
59 |
| - arrays are element-wise equal to the given *rtol* and |
60 |
| - *atol* tolerance. |
61 |
| -
|
62 |
| - """ |
63 |
| - # TODODASK: put in a PR to Dask to request to add as genuine method. |
64 |
| - |
65 |
| - if rtol is None: |
66 |
| - rtol = cf_rtol() |
67 |
| - if atol is None: |
68 |
| - atol = cf_atol() |
69 |
| - |
70 |
| - # Must pass rtol=rtol, atol=atol in as kwargs to allclose, rather than it |
71 |
| - # using those in local scope from the outer function arguments, because |
72 |
| - # Dask's internal algorithms require these to be set as parameters. |
73 |
| - def allclose(a_blocks, b_blocks, rtol=rtol, atol=atol): |
74 |
| - """Run `ma.allclose` across multiple blocks over two arrays.""" |
75 |
| - result = True |
76 |
| - # Handle scalars, including 0-d arrays, for which a_blocks and |
77 |
| - # b_blocks will have the corresponding type and hence not be iterable. |
78 |
| - # With this approach, we avoid inspecting sizes or lengths, and for |
79 |
| - # the 0-d array blocks the following iteration can be used unchanged |
80 |
| - # and will only execute once with block sizes as desired of: |
81 |
| - # (np.array(<int size>),)[0] = array(<int size>). Note |
82 |
| - # can't check against more general case of collections.abc.Iterable |
83 |
| - # because a 0-d array is also iterable, but in practice always a list. |
84 |
| - if not isinstance(a_blocks, list): |
85 |
| - a_blocks = (a_blocks,) |
86 |
| - if not isinstance(b_blocks, list): |
87 |
| - b_blocks = (b_blocks,) |
88 |
| - |
89 |
| - # Note: If a_blocks or b_blocks has more than one chunk in |
90 |
| - # more than one dimension they will comprise a nested |
91 |
| - # sequence of sequences, that needs to be flattened so |
92 |
| - # that we can safely iterate through the actual numpy |
93 |
| - # array elements. |
94 |
| - |
95 |
| - for a, b in zip(flatten(a_blocks), flatten(b_blocks)): |
96 |
| - result &= np.ma.allclose( |
97 |
| - a, b, masked_equal=masked_equal, rtol=rtol, atol=atol |
98 |
| - ) |
99 |
| - |
100 |
| - return result |
101 |
| - |
102 |
| - axes = tuple(range(x.ndim)) |
103 |
| - return da.blockwise( |
104 |
| - allclose, "", x, axes, y, axes, dtype=bool, rtol=rtol, atol=atol |
105 |
| - ) |
106 |
| - |
107 |
| - |
108 | 18 | def cf_contains(a, value):
|
109 | 19 | """Whether or not an array contains a value.
|
110 | 20 |
|
|
0 commit comments