obsarray 1.0.2__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,373 @@
1
+ """test_flag_accessor - tests for obsarray.flag_accessor"""
2
+
3
+ from copy import deepcopy
4
+ import xarray as xr
5
+ import pandas as pd
6
+ import numpy as np
7
+ import unittest
8
+ from unittest.mock import patch
9
+ from obsarray.templater.template_util import create_var
10
+ import obsarray
11
+
12
+
13
+ __author__ = "Sam Hunt <sam.hunt@npl.co.uk>"
14
+ __all__ = []
15
+
16
+
17
+ def create_ds():
18
+ np.random.seed(0)
19
+ temperature = 15 + 8 * np.random.randn(2, 2, 3)
20
+ lon = [[-99.83, -99.32], [-99.79, -99.23]]
21
+ lat = [[42.25, 42.21], [42.63, 42.59]]
22
+ time = pd.date_range("2014-09-06", periods=3)
23
+ reference_time = pd.Timestamp("2014-09-05")
24
+
25
+ ds = xr.Dataset(
26
+ data_vars=dict(
27
+ temperature=(["x", "y", "time"], temperature, {"units": "K"}),
28
+ precipitation=(["x", "y", "time"], temperature, {"units": "K"}),
29
+ ),
30
+ coords=dict(
31
+ lon=(["x", "y"], lon),
32
+ lat=(["x", "y"], lat),
33
+ time=time,
34
+ reference_time=reference_time,
35
+ ),
36
+ attrs=dict(description="Weather related data."),
37
+ )
38
+
39
+ ds["temperature_flags"] = create_var(
40
+ "temperature_flags",
41
+ {
42
+ "dtype": "flag",
43
+ "dim": ["x", "y", "time"],
44
+ "attributes": {
45
+ "flag_meanings": ["bad_data", "dubious_data"],
46
+ "applicable_vars": ["temperature"],
47
+ },
48
+ },
49
+ {"x": 2, "y": 2, "time": 3},
50
+ )
51
+
52
+ ds["general_flags"] = create_var(
53
+ "general_flags",
54
+ {
55
+ "dtype": "flag",
56
+ "dim": ["x", "y", "time"],
57
+ "attributes": {"flag_meanings": []},
58
+ },
59
+ {"x": 2, "y": 2, "time": 3},
60
+ )
61
+
62
+ ds["time_flags"] = create_var(
63
+ "time_flags",
64
+ {
65
+ "dtype": "flag",
66
+ "dim": ["time"],
67
+ "attributes": {"flag_meanings": ["dubious", "invalid"]},
68
+ },
69
+ {"time": 3},
70
+ )
71
+
72
+ return ds
73
+
74
+
75
+ class TestFlagAccessor(unittest.TestCase):
76
+ def setUp(self):
77
+ self.ds = create_ds()
78
+
79
+ def test___getitem__(self):
80
+ self.assertIsInstance(
81
+ self.ds.flag["general_flag"], obsarray.flag_accessor.FlagVariable
82
+ )
83
+ self.assertEqual(self.ds.flag["general_flag"]._flag_var_name, "general_flag")
84
+
85
+ def test___len__(self):
86
+ self.assertEqual(len(self.ds.flag), 3)
87
+
88
+ def test___iter__(self):
89
+
90
+ var_names = []
91
+ for flag in self.ds.flag:
92
+ self.assertIsInstance(flag, obsarray.flag_accessor.FlagVariable)
93
+ var_names.append(flag._flag_var_name)
94
+
95
+ self.assertCountEqual(
96
+ var_names, ["temperature_flags", "general_flags", "time_flags"]
97
+ )
98
+
99
+ def test_keys(self):
100
+ self.assertCountEqual(
101
+ self.ds.flag.keys(), ["temperature_flags", "general_flags", "time_flags"]
102
+ )
103
+
104
+ def test__is_data_var_true(self):
105
+ self.assertTrue(self.ds.flag._is_data_var("temperature"))
106
+
107
+ def test__is_data_var_false(self):
108
+ self.assertFalse(self.ds.flag._is_data_var("temperature_flags"))
109
+
110
+ def test_data_vars(self):
111
+ data_vars = self.ds.flag.data_vars
112
+ self.assertEqual(type(data_vars), xr.core.dataset.DataVariables)
113
+ self.assertCountEqual(
114
+ list(data_vars.variables), ["temperature", "precipitation"]
115
+ )
116
+
117
+ def test_flag_vars(self):
118
+ flag_vars = self.ds.flag.flag_vars
119
+ self.assertEqual(type(flag_vars), xr.core.dataset.DataVariables)
120
+ self.assertCountEqual(
121
+ list(flag_vars.variables),
122
+ ["temperature_flags", "general_flags", "time_flags"],
123
+ )
124
+
125
+ def test__is_flag_var_true(self):
126
+ self.assertTrue(self.ds.flag._is_flag_var("temperature_flags"))
127
+
128
+ def test__is_flag_var_false(self):
129
+ self.assertFalse(self.ds.flag._is_flag_var("temperature"))
130
+
131
+ def test___setitem___DataArray(self):
132
+ new_flag = xr.DataArray(
133
+ np.zeros(self.ds.precipitation.shape),
134
+ dims=["x", "y", "time"],
135
+ attrs={"flag_meanings": "test"},
136
+ )
137
+
138
+ self.ds.flag["new_flag"] = new_flag
139
+
140
+ self.assertEqual(self.ds.new_flag.attrs["flag_meanings"], "test")
141
+ self.assertEqual(self.ds.new_flag.attrs["flag_masks"], "1")
142
+
143
+ np.testing.assert_array_equal(new_flag.values, self.ds.new_flag.values)
144
+
145
+ def test___setitem___DataArray_nomeanings(self):
146
+ new_flag = xr.DataArray(
147
+ np.zeros(self.ds.precipitation.shape), dims=["x", "y", "time"], attrs={}
148
+ )
149
+
150
+ self.ds.flag["new_flag"] = new_flag
151
+
152
+ self.assertEqual(self.ds.new_flag.attrs["flag_meanings"], "")
153
+ self.assertEqual(self.ds.new_flag.attrs["flag_masks"], "")
154
+
155
+ np.testing.assert_array_equal(new_flag.values, self.ds.new_flag.values)
156
+
157
+ @patch("obsarray.flag_accessor.create_var")
158
+ def test___setitem___tuple(self, mock):
159
+
160
+ flag_def = (
161
+ ["x", "y", "time"],
162
+ {"flag_meanings": ["flag1", "flag2", "flag3"]},
163
+ )
164
+ self.ds.flag["new_flag"] = flag_def
165
+
166
+ mock.assert_called_once_with(
167
+ "new_flag",
168
+ {
169
+ "dtype": "flag",
170
+ "dim": ["x", "y", "time"],
171
+ "attributes": {"flag_meanings": ["flag1", "flag2", "flag3"]},
172
+ },
173
+ {"x": 2, "y": 2, "time": 3},
174
+ )
175
+
176
+ self.assertTrue(("new_flag" in self.ds))
177
+
178
+
179
+ class TestFlagVariable(unittest.TestCase):
180
+ def setUp(self):
181
+ self.ds = create_ds()
182
+
183
+ def test___getitem__(self):
184
+ self.assertIsInstance(
185
+ self.ds.flag["temperature_flags"]["bad_data"],
186
+ obsarray.flag_accessor.Flag,
187
+ )
188
+ self.assertEqual(
189
+ self.ds.flag["temperature_flags"]["bad_data"]._flag_var_name,
190
+ "temperature_flags",
191
+ )
192
+ self.assertEqual(
193
+ self.ds.flag["temperature_flags"]["bad_data"]._flag_meaning,
194
+ "bad_data",
195
+ )
196
+
197
+ @patch("obsarray.flag_accessor.Flag.__setitem__")
198
+ @patch("obsarray.flag_accessor.DatasetUtil.add_flag_meaning_to_attrs")
199
+ def test___setitem___existing_mask(self, mdu, mf):
200
+ self.ds.flag["temperature_flags"]["bad_data"] = True
201
+ mdu.assert_not_called()
202
+ mf.assert_called_with(slice(None, None, None), True)
203
+
204
+ @patch("obsarray.flag_accessor.Flag.__setitem__")
205
+ @patch("obsarray.flag_accessor.DatasetUtil.add_flag_meaning_to_attrs")
206
+ def test___setitem___new_mask_1d(self, mdu, mf):
207
+ original_attrs = deepcopy(self.ds["time_flags"].attrs)
208
+
209
+ self.ds.flag["time_flags"]["test_flag"] = True
210
+
211
+ mdu.assert_called_once_with(
212
+ original_attrs, "test_flag", self.ds["time_flags"].dtype
213
+ )
214
+
215
+ self.assertDictEqual(self.ds["time_flags"].attrs, {})
216
+
217
+ mf.assert_called_with(slice(None, None, None), True)
218
+
219
+ @patch("obsarray.flag_accessor.Flag.__setitem__")
220
+ @patch("obsarray.flag_accessor.DatasetUtil.add_flag_meaning_to_attrs")
221
+ def test___setitem___new_mask(self, mdu, mf):
222
+ original_attrs = deepcopy(self.ds["temperature_flags"].attrs)
223
+
224
+ self.ds.flag["temperature_flags"]["test_flag"] = True
225
+
226
+ mdu.assert_called_once_with(
227
+ original_attrs, "test_flag", self.ds["temperature_flags"].dtype
228
+ )
229
+
230
+ self.assertDictEqual(self.ds["temperature_flags"].attrs, {})
231
+
232
+ mf.assert_called_with(slice(None, None, None), True)
233
+
234
+ @patch("obsarray.flag_accessor.Flag.__setitem__")
235
+ @patch("obsarray.flag_accessor.DatasetUtil.add_flag_meaning_to_attrs")
236
+ def test___setitem___new_mask(self, mdu, mf):
237
+
238
+ original_attrs = deepcopy(self.ds["temperature_flags"].attrs)
239
+
240
+ self.ds.flag["temperature_flags"]["test_flag"] = True
241
+
242
+ mdu.assert_called_once_with(
243
+ original_attrs, "test_flag", self.ds["temperature_flags"].dtype
244
+ )
245
+
246
+ self.assertDictEqual(self.ds["temperature_flags"].attrs, {})
247
+
248
+ mf.assert_called_with(slice(None, None, None), True)
249
+
250
+ @patch("obsarray.flag_accessor.Flag.__setitem__")
251
+ @patch("obsarray.flag_accessor.DatasetUtil.rm_flag_meaning_from_attrs")
252
+ def test___delitem__(self, mdu, mf):
253
+ original_attrs = deepcopy(self.ds["temperature_flags"].attrs)
254
+
255
+ del self.ds.flag["temperature_flags"]["dubious_data"]
256
+
257
+ mdu.assert_called_once_with(original_attrs, "dubious_data")
258
+
259
+ self.assertDictEqual(self.ds["temperature_flags"].attrs, {})
260
+
261
+ mf.assert_called_with(slice(None, None, None), False)
262
+
263
+ def test___len__(self):
264
+ self.assertEqual(len(self.ds.flag["temperature_flags"]), 2)
265
+
266
+ def test___iter__(self):
267
+
268
+ var_names = []
269
+ for flag in self.ds.flag["temperature_flags"]:
270
+ self.assertIsInstance(flag, obsarray.flag_accessor.Flag)
271
+ var_names.append(flag._flag_meaning)
272
+
273
+ self.assertCountEqual(var_names, ["bad_data", "dubious_data"])
274
+
275
+ def test_keys(self):
276
+ self.assertCountEqual(
277
+ self.ds.flag["temperature_flags"].keys(),
278
+ ["bad_data", "dubious_data"],
279
+ )
280
+
281
+
282
+ class TestFlag(unittest.TestCase):
283
+ def setUp(self):
284
+ self.ds = create_ds()
285
+
286
+ @patch("obsarray.flag_accessor.Flag._expand_sli", return_value="slice")
287
+ def test___getitem__(self, m):
288
+ self.assertEqual(
289
+ self.ds.flag["temperature_flags"]["bad_data"]["in_slice"]._sli, "slice"
290
+ )
291
+
292
+ m.assert_called_with("in_slice")
293
+
294
+ def test_expand_slice_1d_full(self):
295
+ sli = self.ds.flag["time_flags"]["dubious"]._expand_sli((1))
296
+ self.assertEqual((1,), sli)
297
+
298
+ def test_expand_slice_1d_None(self):
299
+ sli = self.ds.flag["time_flags"]["dubious"]._expand_sli()
300
+ self.assertEqual((slice(None),), sli)
301
+
302
+ def test_expand_slice_full(self):
303
+ sli = self.ds.flag["temperature_flags"]["bad_data"]._expand_sli((1, 1, 1))
304
+ self.assertEqual((1, 1, 1), sli)
305
+
306
+ def test_expand_slice_None(self):
307
+ sli = self.ds.flag["temperature_flags"]["bad_data"]._expand_sli()
308
+ self.assertEqual((slice(None), slice(None), slice(None)), sli)
309
+
310
+ def test_expand_slice_first(self):
311
+ sli = self.ds.flag["temperature_flags"]["bad_data"]._expand_sli((0,))
312
+ self.assertEqual((0, slice(None), slice(None)), sli)
313
+
314
+ def test__setitem___1element_False2True(self):
315
+ self.ds["temperature_flags"].values[:] = 0
316
+
317
+ self.ds.flag["temperature_flags"]["bad_data"][0, 0, 0] = True
318
+
319
+ exp_flags = np.array([[[1, 0, 0], [0, 0, 0]], [[0, 0, 0], [0, 0, 0]]])
320
+
321
+ np.testing.assert_array_equal(self.ds["temperature_flags"].values, exp_flags)
322
+
323
+ def test__setitem___False2True(self):
324
+ self.ds.flag["temperature_flags"]["bad_data"][:, 0, :] = True
325
+
326
+ exp_flags = np.array([[[1, 1, 1], [0, 0, 0]], [[1, 1, 1], [0, 0, 0]]])
327
+
328
+ np.testing.assert_array_equal(self.ds["temperature_flags"].values, exp_flags)
329
+
330
+ def test__setitem___True2False(self):
331
+
332
+ self.ds["temperature_flags"].values[:] = 1
333
+
334
+ self.ds.flag["temperature_flags"]["bad_data"][:, 1, :] = False
335
+
336
+ exp_flags = np.array([[[1, 1, 1], [0, 0, 0]], [[1, 1, 1], [0, 0, 0]]])
337
+
338
+ np.testing.assert_array_equal(self.ds["temperature_flags"].values, exp_flags)
339
+
340
+ def test__setitem___array(self):
341
+ self.ds["temperature_flags"].values[:] = np.array(
342
+ [[[1, 1, 1], [0, 0, 0]], [[1, 1, 1], [0, 0, 0]]]
343
+ )
344
+
345
+ self.ds.flag["temperature_flags"]["bad_data"][:, :, 0] = np.array(
346
+ [[False, True], [False, True]]
347
+ )
348
+
349
+ exp_flags = np.array([[[0, 1, 1], [1, 0, 0]], [[0, 1, 1], [1, 0, 0]]])
350
+
351
+ np.testing.assert_array_equal(self.ds["temperature_flags"].values, exp_flags)
352
+
353
+ def test__setitem___array_not_bool(self):
354
+ self.assertRaises(
355
+ TypeError,
356
+ self.ds.flag["temperature_flags"]["bad_data"],
357
+ slice(None, None, 0),
358
+ np.array([[0.0, 1.0], [0.0, 1.0]]),
359
+ )
360
+
361
+ def test_value(self):
362
+ self.ds["temperature_flags"].values[:] = np.array(
363
+ [[[1, 1, 1], [0, 0, 0]], [[1, 1, 1], [0, 0, 0]]]
364
+ )
365
+
366
+ mask = self.ds.flag["temperature_flags"]["bad_data"][:, :, 0].value
367
+ exp_mask = np.array([[True, False], [True, False]])
368
+
369
+ np.testing.assert_array_equal(mask, exp_mask)
370
+
371
+
372
+ if __name__ == "__main__":
373
+ unittest.main()