|
4 | 4 | # See LICENSE in the root of the repository for full licensing details. |
5 | 5 | """Test function :func:`iris.util.array_equal`.""" |
6 | 6 |
|
| 7 | +import dask.array as da |
7 | 8 | import numpy as np |
8 | 9 | import numpy.ma as ma |
| 10 | +import pytest |
9 | 11 |
|
10 | 12 | from iris.util import array_equal |
11 | 13 |
|
12 | | - |
13 | | -class Test: |
14 | | - def test_0d(self): |
15 | | - array_a = np.array(23) |
16 | | - array_b = np.array(23) |
17 | | - array_c = np.array(7) |
18 | | - assert array_equal(array_a, array_b) |
19 | | - assert not array_equal(array_a, array_c) |
20 | | - |
21 | | - def test_0d_and_scalar(self): |
22 | | - array_a = np.array(23) |
23 | | - assert array_equal(array_a, 23) |
24 | | - assert not array_equal(array_a, 45) |
25 | | - |
26 | | - def test_1d_and_sequences(self): |
27 | | - for sequence_type in (list, tuple): |
28 | | - seq_a = sequence_type([1, 2, 3]) |
29 | | - array_a = np.array(seq_a) |
30 | | - assert array_equal(array_a, seq_a) |
31 | | - assert not array_equal(array_a, seq_a[:-1]) |
32 | | - array_a[1] = 45 |
33 | | - assert not array_equal(array_a, seq_a) |
34 | | - |
35 | | - def test_nd(self): |
36 | | - array_a = np.array(np.arange(24).reshape(2, 3, 4)) |
37 | | - array_b = np.array(np.arange(24).reshape(2, 3, 4)) |
38 | | - array_c = np.array(np.arange(24).reshape(2, 3, 4)) |
39 | | - array_c[0, 1, 2] = 100 |
40 | | - assert array_equal(array_a, array_b) |
41 | | - assert not array_equal(array_a, array_c) |
42 | | - |
43 | | - def test_masked_is_not_ignored(self): |
44 | | - array_a = ma.masked_array([1, 2, 3], mask=[1, 0, 1]) |
45 | | - array_b = ma.masked_array([2, 2, 2], mask=[1, 0, 1]) |
46 | | - assert array_equal(array_a, array_b) |
47 | | - |
48 | | - def test_masked_is_different(self): |
49 | | - array_a = ma.masked_array([1, 2, 3], mask=[1, 0, 1]) |
50 | | - array_b = ma.masked_array([1, 2, 3], mask=[0, 0, 1]) |
51 | | - assert not array_equal(array_a, array_b) |
52 | | - |
53 | | - def test_masked_isnt_unmasked(self): |
54 | | - array_a = np.array([1, 2, 2]) |
55 | | - array_b = ma.masked_array([1, 2, 2], mask=[0, 0, 1]) |
56 | | - assert not array_equal(array_a, array_b) |
57 | | - |
58 | | - def test_masked_unmasked_equivelance(self): |
59 | | - array_a = np.array([1, 2, 2]) |
60 | | - array_b = ma.masked_array([1, 2, 2]) |
61 | | - array_c = ma.masked_array([1, 2, 2], mask=[0, 0, 0]) |
62 | | - assert array_equal(array_a, array_b) |
63 | | - assert array_equal(array_a, array_c) |
64 | | - |
65 | | - def test_fully_masked_arrays(self): |
66 | | - array_a = ma.masked_array(np.arange(24).reshape(2, 3, 4), mask=True) |
67 | | - array_b = ma.masked_array(np.arange(24).reshape(2, 3, 4), mask=True) |
68 | | - assert array_equal(array_a, array_b) |
69 | | - |
70 | | - def test_fully_masked_0d_arrays(self): |
71 | | - array_a = ma.masked_array(3, mask=True) |
72 | | - array_b = ma.masked_array(3, mask=True) |
73 | | - assert array_equal(array_a, array_b) |
74 | | - |
75 | | - def test_fully_masked_string_arrays(self): |
76 | | - array_a = ma.masked_array(["a", "b", "c"], mask=True) |
77 | | - array_b = ma.masked_array(["a", "b", "c"], mask=[1, 1, 1]) |
78 | | - assert array_equal(array_a, array_b) |
79 | | - |
80 | | - def test_partially_masked_string_arrays(self): |
81 | | - array_a = ma.masked_array(["a", "b", "c"], mask=[1, 0, 1]) |
82 | | - array_b = ma.masked_array(["a", "b", "c"], mask=[1, 0, 1]) |
83 | | - assert array_equal(array_a, array_b) |
84 | | - |
85 | | - def test_string_arrays_equal(self): |
86 | | - array_a = np.array(["abc", "def", "efg"]) |
87 | | - array_b = np.array(["abc", "def", "efg"]) |
88 | | - assert array_equal(array_a, array_b) |
89 | | - |
90 | | - def test_string_arrays_different_contents(self): |
91 | | - array_a = np.array(["abc", "def", "efg"]) |
92 | | - array_b = np.array(["abc", "de", "efg"]) |
93 | | - assert not array_equal(array_a, array_b) |
94 | | - |
95 | | - def test_string_arrays_subset(self): |
96 | | - array_a = np.array(["abc", "def", "efg"]) |
97 | | - array_b = np.array(["abc", "def"]) |
98 | | - assert not array_equal(array_a, array_b) |
99 | | - assert not array_equal(array_b, array_a) |
100 | | - |
101 | | - def test_string_arrays_unequal_dimensionality(self): |
102 | | - array_a = np.array("abc") |
103 | | - array_b = np.array(["abc"]) |
104 | | - array_c = np.array([["abc"]]) |
105 | | - assert not array_equal(array_a, array_b) |
106 | | - assert not array_equal(array_b, array_a) |
107 | | - assert not array_equal(array_a, array_c) |
108 | | - assert not array_equal(array_b, array_c) |
109 | | - |
110 | | - def test_string_arrays_0d_and_scalar(self): |
111 | | - array_a = np.array("foobar") |
112 | | - assert array_equal(array_a, "foobar") |
113 | | - assert not array_equal(array_a, "foo") |
114 | | - assert not array_equal(array_a, "foobar.") |
115 | | - |
116 | | - def test_nan_equality_nan_ne_nan(self): |
117 | | - array_a = np.array([1.0, np.nan, 2.0, np.nan, 3.0]) |
118 | | - array_b = array_a.copy() |
119 | | - assert not array_equal(array_a, array_a) |
120 | | - assert not array_equal(array_a, array_b) |
121 | | - |
122 | | - def test_nan_equality_nan_naneq_nan(self): |
123 | | - array_a = np.array([1.0, np.nan, 2.0, np.nan, 3.0]) |
124 | | - array_b = np.array([1.0, np.nan, 2.0, np.nan, 3.0]) |
125 | | - assert array_equal(array_a, array_a, withnans=True) |
126 | | - assert array_equal(array_a, array_b, withnans=True) |
127 | | - |
128 | | - def test_nan_equality_nan_nanne_a(self): |
129 | | - array_a = np.array([1.0, np.nan, 2.0, np.nan, 3.0]) |
130 | | - array_b = np.array([1.0, np.nan, 2.0, 0.0, 3.0]) |
131 | | - assert not array_equal(array_a, array_b, withnans=True) |
132 | | - |
133 | | - def test_nan_equality_a_nanne_b(self): |
134 | | - array_a = np.array([1.0, np.nan, 2.0, np.nan, 3.0]) |
135 | | - array_b = np.array([1.0, np.nan, 2.0, np.nan, 4.0]) |
136 | | - assert not array_equal(array_a, array_b, withnans=True) |
| 14 | +ARRAY1 = np.array(np.arange(24).reshape(2, 3, 4)) |
| 15 | +ARRAY1[0, 1, 2] = 100 |
| 16 | + |
| 17 | +ARRAY2 = np.array([1.0, np.nan, 2.0, np.nan, 3.0]) |
| 18 | + |
| 19 | +TEST_CASES = [ |
| 20 | + # test empty |
| 21 | + (np.array([]), np.array([]), False, True), |
| 22 | + (np.array([]), np.array([], dtype=np.float64), True, True), |
| 23 | + # test 0d |
| 24 | + (np.array(23), np.array(23), False, True), |
| 25 | + (np.array(23), np.array(7), False, False), |
| 26 | + # test 0d and scalar |
| 27 | + (np.array(23), 23, False, True), |
| 28 | + (np.array(23), 45, False, False), |
| 29 | + # test 1d and sequences |
| 30 | + (np.array([1, 2, 3]), [1, 2, 3], False, True), |
| 31 | + (np.array([1, 2, 3]), [1, 2], False, False), |
| 32 | + (np.array([1, 45, 3]), [1, 2, 3], False, False), |
| 33 | + (np.array([1, 2, 3]), (1, 2, 3), False, True), |
| 34 | + (np.array([1, 2, 3]), (1, 2), False, False), |
| 35 | + (np.array([1, 45, 3]), (1, 2, 3), False, False), |
| 36 | + # test 3d |
| 37 | + ( |
| 38 | + np.array(np.arange(24).reshape(2, 3, 4)), |
| 39 | + np.array(np.arange(24).reshape(2, 3, 4)), |
| 40 | + False, |
| 41 | + True, |
| 42 | + ), |
| 43 | + ( |
| 44 | + np.array(np.arange(24).reshape(2, 3, 4)), |
| 45 | + ARRAY1, |
| 46 | + False, |
| 47 | + False, |
| 48 | + ), |
| 49 | + # test masked is not ignored |
| 50 | + ( |
| 51 | + ma.masked_array([1, 2, 3], mask=[1, 0, 1]), |
| 52 | + ma.masked_array([2, 2, 2], mask=[1, 0, 1]), |
| 53 | + False, |
| 54 | + True, |
| 55 | + ), |
| 56 | + # test masked is different |
| 57 | + ( |
| 58 | + ma.masked_array([1, 2, 3], mask=[1, 0, 1]), |
| 59 | + ma.masked_array([1, 2, 3], mask=[0, 0, 1]), |
| 60 | + False, |
| 61 | + False, |
| 62 | + ), |
| 63 | + # test masked isn't unmasked |
| 64 | + ( |
| 65 | + np.array([1, 2, 2]), |
| 66 | + ma.masked_array([1, 2, 2], mask=[0, 0, 1]), |
| 67 | + False, |
| 68 | + False, |
| 69 | + ), |
| 70 | + ( |
| 71 | + np.array([1, 2]), |
| 72 | + ma.masked_array([1, 3], mask=[0, 1]), |
| 73 | + False, |
| 74 | + False, |
| 75 | + ), |
| 76 | + # test masked/unmasked_equivalence |
| 77 | + ( |
| 78 | + np.array([1, 2, 2]), |
| 79 | + ma.masked_array([1, 2, 2]), |
| 80 | + False, |
| 81 | + True, |
| 82 | + ), |
| 83 | + ( |
| 84 | + np.array([1, 2, 2]), |
| 85 | + ma.masked_array([1, 2, 2], mask=[0, 0, 0]), |
| 86 | + False, |
| 87 | + True, |
| 88 | + ), |
| 89 | + # test fully masked arrays |
| 90 | + ( |
| 91 | + ma.masked_array(np.arange(24).reshape(2, 3, 4), mask=True), |
| 92 | + ma.masked_array(np.arange(24).reshape(2, 3, 4), mask=True), |
| 93 | + False, |
| 94 | + True, |
| 95 | + ), |
| 96 | + # test fully masked 0d arrays |
| 97 | + ( |
| 98 | + ma.masked_array(3, mask=True), |
| 99 | + ma.masked_array(3, mask=True), |
| 100 | + False, |
| 101 | + True, |
| 102 | + ), |
| 103 | + # test fully masked string arrays |
| 104 | + ( |
| 105 | + ma.masked_array(["a", "b", "c"], mask=True), |
| 106 | + ma.masked_array(["a", "b", "c"], mask=[1, 1, 1]), |
| 107 | + False, |
| 108 | + True, |
| 109 | + ), |
| 110 | + # test partially masked string arrays |
| 111 | + ( |
| 112 | + ma.masked_array(["a", "b", "c"], mask=[1, 0, 1]), |
| 113 | + ma.masked_array(["a", "b", "c"], mask=[1, 0, 1]), |
| 114 | + False, |
| 115 | + True, |
| 116 | + ), |
| 117 | + # test string arrays equal |
| 118 | + ( |
| 119 | + np.array(["abc", "def", "efg"]), |
| 120 | + np.array(["abc", "def", "efg"]), |
| 121 | + False, |
| 122 | + True, |
| 123 | + ), |
| 124 | + # test string arrays different contents |
| 125 | + ( |
| 126 | + np.array(["abc", "def", "efg"]), |
| 127 | + np.array(["abc", "de", "efg"]), |
| 128 | + False, |
| 129 | + False, |
| 130 | + ), |
| 131 | + # test string arrays subset |
| 132 | + ( |
| 133 | + np.array(["abc", "def", "efg"]), |
| 134 | + np.array(["abc", "def"]), |
| 135 | + False, |
| 136 | + False, |
| 137 | + ), |
| 138 | + ( |
| 139 | + np.array(["abc", "def"]), |
| 140 | + np.array(["abc", "def", "efg"]), |
| 141 | + False, |
| 142 | + False, |
| 143 | + ), |
| 144 | + # test string arrays unequal dimensionality |
| 145 | + (np.array("abc"), np.array(["abc"]), False, False), |
| 146 | + (np.array(["abc"]), np.array("abc"), False, False), |
| 147 | + (np.array("abc"), np.array([["abc"]]), False, False), |
| 148 | + (np.array(["abc"]), np.array([["abc"]]), False, False), |
| 149 | + # test string arrays 0d and scalar |
| 150 | + (np.array("foobar"), "foobar", False, True), |
| 151 | + (np.array("foobar"), "foo", False, False), |
| 152 | + (np.array("foobar"), "foobar.", False, False), |
| 153 | + # test nan equality nan ne nan |
| 154 | + (ARRAY2, ARRAY2, False, False), |
| 155 | + (ARRAY2, ARRAY2.copy(), False, False), |
| 156 | + # test nan equality nan naneq nan |
| 157 | + (ARRAY2, ARRAY2, True, True), |
| 158 | + (ARRAY2, ARRAY2.copy(), True, True), |
| 159 | + # test nan equality nan nanne a |
| 160 | + ( |
| 161 | + np.array([1.0, np.nan, 2.0, np.nan, 3.0]), |
| 162 | + np.array([1.0, np.nan, 2.0, 0.0, 3.0]), |
| 163 | + True, |
| 164 | + False, |
| 165 | + ), |
| 166 | + # test nan equality a nanne b |
| 167 | + ( |
| 168 | + np.array([1.0, np.nan, 2.0, np.nan, 3.0]), |
| 169 | + np.array([1.0, np.nan, 2.0, np.nan, 4.0]), |
| 170 | + True, |
| 171 | + False, |
| 172 | + ), |
| 173 | +] |
| 174 | + |
| 175 | + |
| 176 | +@pytest.mark.parametrize("lazy", [False, True]) |
| 177 | +@pytest.mark.parametrize("array_a,array_b,withnans,eq", TEST_CASES) |
| 178 | +def test_array_equal(array_a, array_b, withnans, eq, lazy): |
| 179 | + if lazy: |
| 180 | + identical = array_a is array_b |
| 181 | + if isinstance(array_a, np.ndarray): |
| 182 | + array_a = da.asarray(array_a, chunks=2) |
| 183 | + if isinstance(array_b, np.ndarray): |
| 184 | + array_b = da.asarray(array_b, chunks=1) |
| 185 | + if identical: |
| 186 | + array_b = array_a |
| 187 | + assert eq == array_equal(array_a, array_b, withnans=withnans) |
0 commit comments