tobac 1.6.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.
- tobac/__init__.py +112 -0
- tobac/analysis/__init__.py +31 -0
- tobac/analysis/cell_analysis.py +628 -0
- tobac/analysis/feature_analysis.py +212 -0
- tobac/analysis/spatial.py +619 -0
- tobac/centerofgravity.py +226 -0
- tobac/feature_detection.py +1758 -0
- tobac/merge_split.py +324 -0
- tobac/plotting.py +2321 -0
- tobac/segmentation/__init__.py +10 -0
- tobac/segmentation/watershed_segmentation.py +1316 -0
- tobac/testing.py +1179 -0
- tobac/tests/segmentation_tests/test_iris_xarray_segmentation.py +0 -0
- tobac/tests/segmentation_tests/test_segmentation.py +1183 -0
- tobac/tests/segmentation_tests/test_segmentation_time_pad.py +104 -0
- tobac/tests/test_analysis_spatial.py +1109 -0
- tobac/tests/test_convert.py +265 -0
- tobac/tests/test_datetime.py +216 -0
- tobac/tests/test_decorators.py +148 -0
- tobac/tests/test_feature_detection.py +1321 -0
- tobac/tests/test_generators.py +273 -0
- tobac/tests/test_import.py +24 -0
- tobac/tests/test_iris_xarray_match_utils.py +244 -0
- tobac/tests/test_merge_split.py +351 -0
- tobac/tests/test_pbc_utils.py +497 -0
- tobac/tests/test_sample_data.py +197 -0
- tobac/tests/test_testing.py +747 -0
- tobac/tests/test_tracking.py +714 -0
- tobac/tests/test_utils.py +650 -0
- tobac/tests/test_utils_bulk_statistics.py +789 -0
- tobac/tests/test_utils_coordinates.py +328 -0
- tobac/tests/test_utils_internal.py +97 -0
- tobac/tests/test_xarray_utils.py +232 -0
- tobac/tracking.py +613 -0
- tobac/utils/__init__.py +27 -0
- tobac/utils/bulk_statistics.py +360 -0
- tobac/utils/datetime.py +184 -0
- tobac/utils/decorators.py +540 -0
- tobac/utils/general.py +753 -0
- tobac/utils/generators.py +87 -0
- tobac/utils/internal/__init__.py +2 -0
- tobac/utils/internal/coordinates.py +430 -0
- tobac/utils/internal/iris_utils.py +462 -0
- tobac/utils/internal/label_props.py +82 -0
- tobac/utils/internal/xarray_utils.py +439 -0
- tobac/utils/mask.py +364 -0
- tobac/utils/periodic_boundaries.py +419 -0
- tobac/wrapper.py +244 -0
- tobac-1.6.2.dist-info/METADATA +154 -0
- tobac-1.6.2.dist-info/RECORD +53 -0
- tobac-1.6.2.dist-info/WHEEL +5 -0
- tobac-1.6.2.dist-info/licenses/LICENSE +29 -0
- tobac-1.6.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,540 @@
|
|
|
1
|
+
"""Decorators for use with other tobac functions"""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
import functools
|
|
5
|
+
import warnings
|
|
6
|
+
|
|
7
|
+
import numpy as np
|
|
8
|
+
from numpy import ma
|
|
9
|
+
import pandas as pd
|
|
10
|
+
import xarray as xr
|
|
11
|
+
import iris.cube
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def convert_cube_to_dataarray(
|
|
15
|
+
cube: iris.cube.Cube, preserve_iris_datetime_types: bool = True
|
|
16
|
+
) -> xr.DataArray:
|
|
17
|
+
"""
|
|
18
|
+
Convert an iris cube to an xarray dataarray, averting error for integer dtype cubes in xarray<v2023.06
|
|
19
|
+
|
|
20
|
+
Parameters
|
|
21
|
+
----------
|
|
22
|
+
cube : iris.cube.Cube
|
|
23
|
+
Iris data cube
|
|
24
|
+
|
|
25
|
+
preserve_iris_datetime_types : bool, optional (default: True)
|
|
26
|
+
If True, ensure that the time coordinate of the output (if present) uses the same cftime type as the
|
|
27
|
+
input cube.
|
|
28
|
+
|
|
29
|
+
Returns
|
|
30
|
+
-------
|
|
31
|
+
dataarray : xr.DataArray
|
|
32
|
+
dataarray converted from cube. If the cube's core data is a masked array and has integer dtype,
|
|
33
|
+
the returned datarray will have a numpy array with masked values filled with the minimum value for
|
|
34
|
+
that integer dtype. Otherwise the data will be identical to that produced using xr.DataArray.from_iris
|
|
35
|
+
"""
|
|
36
|
+
if isinstance(cube.core_data(), ma.core.MaskedArray) and np.issubdtype(
|
|
37
|
+
cube.core_data().dtype, np.integer
|
|
38
|
+
):
|
|
39
|
+
da = xr.DataArray.from_iris(
|
|
40
|
+
cube.copy(cube.core_data().filled(np.iinfo(cube.core_data().dtype).min))
|
|
41
|
+
)
|
|
42
|
+
else:
|
|
43
|
+
da = xr.DataArray.from_iris(cube)
|
|
44
|
+
|
|
45
|
+
if preserve_iris_datetime_types & ("time" in da.coords):
|
|
46
|
+
da = da.convert_calendar(cube.coord("time").units.calendar, use_cftime=True)
|
|
47
|
+
|
|
48
|
+
return da
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def _conv_kwargs_iris_to_xarray(
|
|
52
|
+
conv_kwargs: dict, preserve_iris_datetime_types: bool = True
|
|
53
|
+
) -> dict:
|
|
54
|
+
"""
|
|
55
|
+
Internal function to convert iris cube kwargs to xarray dataarrays
|
|
56
|
+
|
|
57
|
+
Parameters
|
|
58
|
+
----------
|
|
59
|
+
conv_kwargs : dict
|
|
60
|
+
Input kwargs to convert
|
|
61
|
+
|
|
62
|
+
Returns
|
|
63
|
+
-------
|
|
64
|
+
dict
|
|
65
|
+
Output keyword arguments without any Iris Cubes
|
|
66
|
+
"""
|
|
67
|
+
return {
|
|
68
|
+
key: (
|
|
69
|
+
convert_cube_to_dataarray(
|
|
70
|
+
arg, preserve_iris_datetime_types=preserve_iris_datetime_types
|
|
71
|
+
)
|
|
72
|
+
if isinstance(arg, iris.cube.Cube)
|
|
73
|
+
else arg
|
|
74
|
+
)
|
|
75
|
+
for key, arg in zip(conv_kwargs.keys(), conv_kwargs.values())
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
def _conv_kwargs_irispandas_to_xarray(
|
|
80
|
+
conv_kwargs: dict, preserve_iris_datetime_types: bool = True
|
|
81
|
+
) -> dict:
|
|
82
|
+
"""
|
|
83
|
+
Internal function to convert iris cube and pandas dataframe kwargs to xarray dataarrays
|
|
84
|
+
|
|
85
|
+
Parameters
|
|
86
|
+
----------
|
|
87
|
+
conv_kwargs : dict
|
|
88
|
+
Input kwargs to convert
|
|
89
|
+
|
|
90
|
+
Returns
|
|
91
|
+
-------
|
|
92
|
+
dict
|
|
93
|
+
Output keyword arguments without any Iris Cubes or pandas dataframes
|
|
94
|
+
|
|
95
|
+
"""
|
|
96
|
+
return {
|
|
97
|
+
key: (
|
|
98
|
+
convert_cube_to_dataarray(
|
|
99
|
+
arg, preserve_iris_datetime_types=preserve_iris_datetime_types
|
|
100
|
+
)
|
|
101
|
+
if isinstance(arg, iris.cube.Cube)
|
|
102
|
+
else arg.to_xarray() if isinstance(arg, pd.DataFrame) else arg
|
|
103
|
+
)
|
|
104
|
+
for key, arg in zip(conv_kwargs.keys(), conv_kwargs.values())
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def _conv_kwargs_xarray_to_iris(conv_kwargs: dict):
|
|
109
|
+
"""
|
|
110
|
+
Internal function to convert xarray dataarray kwargs back to iris cubes
|
|
111
|
+
|
|
112
|
+
Parameters
|
|
113
|
+
----------
|
|
114
|
+
conv_kwargs : dict
|
|
115
|
+
Input kwargs to convert
|
|
116
|
+
|
|
117
|
+
Returns
|
|
118
|
+
-------
|
|
119
|
+
dict
|
|
120
|
+
Output keyword arguments with all xarray dataarrays converted back to
|
|
121
|
+
iris cubes
|
|
122
|
+
"""
|
|
123
|
+
return {
|
|
124
|
+
key: (
|
|
125
|
+
xr.DataArray.to_iris(arg).copy(arg.data)
|
|
126
|
+
if isinstance(arg, xr.DataArray)
|
|
127
|
+
else arg
|
|
128
|
+
)
|
|
129
|
+
for key, arg in zip(conv_kwargs.keys(), conv_kwargs.values())
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def _conv_kwargs_xarray_to_irispandas(conv_kwargs: dict):
|
|
134
|
+
"""
|
|
135
|
+
Internal function to convert xarray dataarrays back to iris cubes/pandas dataframes
|
|
136
|
+
|
|
137
|
+
Parameters
|
|
138
|
+
----------
|
|
139
|
+
conv_kwargs : dict
|
|
140
|
+
Input kwargs to convert
|
|
141
|
+
|
|
142
|
+
Returns
|
|
143
|
+
-------
|
|
144
|
+
dict
|
|
145
|
+
Output keyword arguments with all xarray dataarrays converted back to
|
|
146
|
+
iris cubes
|
|
147
|
+
"""
|
|
148
|
+
return {
|
|
149
|
+
key: (
|
|
150
|
+
xr.DataArray.to_iris(arg).copy(arg.data)
|
|
151
|
+
if isinstance(arg, xr.DataArray)
|
|
152
|
+
else arg.to_dataframe() if isinstance(arg, xr.Dataset) else arg
|
|
153
|
+
)
|
|
154
|
+
for key, arg in zip(conv_kwargs.keys(), conv_kwargs.values())
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
def iris_to_xarray(save_iris_info: bool = False):
|
|
159
|
+
def iris_to_xarray_i(func):
|
|
160
|
+
"""Decorator that converts all input of a function that is in the form of
|
|
161
|
+
Iris cubes into xarray DataArrays and converts all outputs with type
|
|
162
|
+
xarray DataArrays back into Iris cubes.
|
|
163
|
+
|
|
164
|
+
Parameters
|
|
165
|
+
----------
|
|
166
|
+
func : function
|
|
167
|
+
Function to be decorated
|
|
168
|
+
|
|
169
|
+
Returns
|
|
170
|
+
-------
|
|
171
|
+
wrapper : function
|
|
172
|
+
Function including decorator
|
|
173
|
+
"""
|
|
174
|
+
|
|
175
|
+
import iris
|
|
176
|
+
import iris.cube
|
|
177
|
+
import xarray
|
|
178
|
+
|
|
179
|
+
@functools.wraps(func)
|
|
180
|
+
def wrapper(*args, preserve_iris_datetime_types: bool = True, **kwargs):
|
|
181
|
+
# print(kwargs)
|
|
182
|
+
|
|
183
|
+
if save_iris_info:
|
|
184
|
+
if any([(type(arg) == iris.cube.Cube) for arg in args]) or any(
|
|
185
|
+
[(type(arg) == iris.cube.Cube) for arg in kwargs.values()]
|
|
186
|
+
):
|
|
187
|
+
kwargs["converted_from_iris"] = True
|
|
188
|
+
else:
|
|
189
|
+
kwargs["converted_from_iris"] = False
|
|
190
|
+
|
|
191
|
+
if any([type(arg) == iris.cube.Cube for arg in args]) or any(
|
|
192
|
+
[type(arg) == iris.cube.Cube for arg in kwargs.values()]
|
|
193
|
+
):
|
|
194
|
+
# print("converting iris to xarray and back")
|
|
195
|
+
args = tuple(
|
|
196
|
+
[
|
|
197
|
+
(
|
|
198
|
+
convert_cube_to_dataarray(
|
|
199
|
+
arg,
|
|
200
|
+
preserve_iris_datetime_types=preserve_iris_datetime_types,
|
|
201
|
+
)
|
|
202
|
+
if type(arg) == iris.cube.Cube
|
|
203
|
+
else arg
|
|
204
|
+
)
|
|
205
|
+
for arg in args
|
|
206
|
+
]
|
|
207
|
+
)
|
|
208
|
+
kwargs_new = _conv_kwargs_iris_to_xarray(
|
|
209
|
+
kwargs, preserve_iris_datetime_types=preserve_iris_datetime_types
|
|
210
|
+
)
|
|
211
|
+
# print(args)
|
|
212
|
+
# print(kwargs)
|
|
213
|
+
output = func(*args, **kwargs_new)
|
|
214
|
+
if type(output) == tuple:
|
|
215
|
+
output = tuple(
|
|
216
|
+
[
|
|
217
|
+
(
|
|
218
|
+
output_item.to_iris().copy(output_item.data)
|
|
219
|
+
if type(output_item) == xarray.DataArray
|
|
220
|
+
else output_item
|
|
221
|
+
)
|
|
222
|
+
for output_item in output
|
|
223
|
+
]
|
|
224
|
+
)
|
|
225
|
+
elif type(output) == xarray.DataArray:
|
|
226
|
+
output = output.to_iris().copy(output.data)
|
|
227
|
+
# if output is neither tuple nor an xr.DataArray
|
|
228
|
+
|
|
229
|
+
else:
|
|
230
|
+
output = func(*args, **kwargs)
|
|
231
|
+
return output
|
|
232
|
+
|
|
233
|
+
return wrapper
|
|
234
|
+
|
|
235
|
+
return iris_to_xarray_i
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def xarray_to_iris():
|
|
239
|
+
def xarray_to_iris_i(func):
|
|
240
|
+
"""Decorator that converts all input of a function that is in the form of
|
|
241
|
+
xarray DataArrays into Iris cubes and converts all outputs with type
|
|
242
|
+
Iris cubes back into xarray DataArrays.
|
|
243
|
+
|
|
244
|
+
Parameters
|
|
245
|
+
----------
|
|
246
|
+
func : function
|
|
247
|
+
Function to be decorated.
|
|
248
|
+
|
|
249
|
+
Returns
|
|
250
|
+
-------
|
|
251
|
+
wrapper : function
|
|
252
|
+
Function including decorator.
|
|
253
|
+
|
|
254
|
+
Examples
|
|
255
|
+
--------
|
|
256
|
+
>>> segmentation_xarray_conv = xarray_to_iris()
|
|
257
|
+
>>> segmentation_xarray = segmentation_xarray_conv(segmentation)
|
|
258
|
+
|
|
259
|
+
This line creates a new function that can process xarray fields and
|
|
260
|
+
also outputs fields in xarray format, but otherwise works just like
|
|
261
|
+
the original function:
|
|
262
|
+
|
|
263
|
+
>>> mask_xarray, features = segmentation_xarray(
|
|
264
|
+
features, data_xarray, dxy, threshold
|
|
265
|
+
)
|
|
266
|
+
"""
|
|
267
|
+
|
|
268
|
+
import iris
|
|
269
|
+
import xarray
|
|
270
|
+
|
|
271
|
+
@functools.wraps(func)
|
|
272
|
+
def wrapper(*args, **kwargs):
|
|
273
|
+
# print(args)
|
|
274
|
+
# print(kwargs)
|
|
275
|
+
if any([type(arg) == xarray.DataArray for arg in args]) or any(
|
|
276
|
+
[type(arg) == xarray.DataArray for arg in kwargs.values()]
|
|
277
|
+
):
|
|
278
|
+
# print("converting xarray to iris and back")
|
|
279
|
+
args = tuple(
|
|
280
|
+
[
|
|
281
|
+
(
|
|
282
|
+
arg.to_iris().copy(arg.data)
|
|
283
|
+
if type(arg) == xarray.DataArray
|
|
284
|
+
else arg
|
|
285
|
+
)
|
|
286
|
+
for arg in args
|
|
287
|
+
]
|
|
288
|
+
)
|
|
289
|
+
if kwargs:
|
|
290
|
+
kwargs_new = _conv_kwargs_xarray_to_iris(kwargs)
|
|
291
|
+
else:
|
|
292
|
+
kwargs_new = kwargs
|
|
293
|
+
# print(args)
|
|
294
|
+
# print(kwargs)
|
|
295
|
+
output = func(*args, **kwargs_new)
|
|
296
|
+
if type(output) == tuple:
|
|
297
|
+
output = tuple(
|
|
298
|
+
[
|
|
299
|
+
(
|
|
300
|
+
xarray.DataArray.from_iris(output_item)
|
|
301
|
+
if type(output_item) == iris.cube.Cube
|
|
302
|
+
else output_item
|
|
303
|
+
)
|
|
304
|
+
for output_item in output
|
|
305
|
+
]
|
|
306
|
+
)
|
|
307
|
+
else:
|
|
308
|
+
if type(output) == iris.cube.Cube:
|
|
309
|
+
output = xarray.DataArray.from_iris(output)
|
|
310
|
+
|
|
311
|
+
else:
|
|
312
|
+
output = func(*args, **kwargs)
|
|
313
|
+
# print(output)
|
|
314
|
+
return output
|
|
315
|
+
|
|
316
|
+
return wrapper
|
|
317
|
+
|
|
318
|
+
return xarray_to_iris_i
|
|
319
|
+
|
|
320
|
+
|
|
321
|
+
def irispandas_to_xarray(save_iris_info: bool = False):
|
|
322
|
+
def irispandas_to_xarray_i(func):
|
|
323
|
+
"""Decorator that converts all input of a function that is in the form of
|
|
324
|
+
Iris cubes/pandas Dataframes into xarray DataArrays/xarray Datasets and
|
|
325
|
+
converts all outputs with the type xarray DataArray/xarray Dataset
|
|
326
|
+
back into Iris cubes/pandas Dataframes.
|
|
327
|
+
|
|
328
|
+
Parameters
|
|
329
|
+
----------
|
|
330
|
+
func : function
|
|
331
|
+
Function to be decorated.
|
|
332
|
+
|
|
333
|
+
Returns
|
|
334
|
+
-------
|
|
335
|
+
wrapper : function
|
|
336
|
+
Function including decorator.
|
|
337
|
+
"""
|
|
338
|
+
import iris
|
|
339
|
+
import iris.cube
|
|
340
|
+
import xarray
|
|
341
|
+
import pandas as pd
|
|
342
|
+
|
|
343
|
+
@functools.wraps(func)
|
|
344
|
+
def wrapper(*args, preserve_iris_datetime_types: bool = True, **kwargs):
|
|
345
|
+
# pass if we did an iris conversion.
|
|
346
|
+
if save_iris_info:
|
|
347
|
+
if any([(type(arg) == iris.cube.Cube) for arg in args]) or any(
|
|
348
|
+
[(type(arg) == iris.cube.Cube) for arg in kwargs.values()]
|
|
349
|
+
):
|
|
350
|
+
kwargs["converted_from_iris"] = True
|
|
351
|
+
else:
|
|
352
|
+
kwargs["converted_from_iris"] = False
|
|
353
|
+
|
|
354
|
+
# print(kwargs)
|
|
355
|
+
if any(
|
|
356
|
+
[
|
|
357
|
+
(type(arg) == iris.cube.Cube or type(arg) == pd.DataFrame)
|
|
358
|
+
for arg in args
|
|
359
|
+
]
|
|
360
|
+
) or any(
|
|
361
|
+
[
|
|
362
|
+
(type(arg) == iris.cube.Cube or type(arg) == pd.DataFrame)
|
|
363
|
+
for arg in kwargs.values()
|
|
364
|
+
]
|
|
365
|
+
):
|
|
366
|
+
# print("converting iris to xarray and back")
|
|
367
|
+
args = tuple(
|
|
368
|
+
[
|
|
369
|
+
(
|
|
370
|
+
convert_cube_to_dataarray(
|
|
371
|
+
arg,
|
|
372
|
+
preserve_iris_datetime_types=preserve_iris_datetime_types,
|
|
373
|
+
)
|
|
374
|
+
if type(arg) == iris.cube.Cube
|
|
375
|
+
else arg.to_xarray() if type(arg) == pd.DataFrame else arg
|
|
376
|
+
)
|
|
377
|
+
for arg in args
|
|
378
|
+
]
|
|
379
|
+
)
|
|
380
|
+
kwargs = _conv_kwargs_irispandas_to_xarray(
|
|
381
|
+
kwargs, preserve_iris_datetime_types=preserve_iris_datetime_types
|
|
382
|
+
)
|
|
383
|
+
|
|
384
|
+
output = func(*args, **kwargs)
|
|
385
|
+
if type(output) == tuple:
|
|
386
|
+
output = tuple(
|
|
387
|
+
[
|
|
388
|
+
(
|
|
389
|
+
output_item.to_iris().copy(output_item.data)
|
|
390
|
+
if type(output_item) == xarray.DataArray
|
|
391
|
+
else (
|
|
392
|
+
output_item.to_dataframe()
|
|
393
|
+
if type(output_item) == xarray.Dataset
|
|
394
|
+
else output_item
|
|
395
|
+
)
|
|
396
|
+
)
|
|
397
|
+
for output_item in output
|
|
398
|
+
]
|
|
399
|
+
)
|
|
400
|
+
else:
|
|
401
|
+
if type(output) == xarray.DataArray:
|
|
402
|
+
output = output.to_iris().copy(output.data)
|
|
403
|
+
elif type(output) == xarray.Dataset:
|
|
404
|
+
output = output.to_dataframe()
|
|
405
|
+
|
|
406
|
+
else:
|
|
407
|
+
output = func(*args, **kwargs)
|
|
408
|
+
return output
|
|
409
|
+
|
|
410
|
+
return wrapper
|
|
411
|
+
|
|
412
|
+
return irispandas_to_xarray_i
|
|
413
|
+
|
|
414
|
+
|
|
415
|
+
def xarray_to_irispandas():
|
|
416
|
+
def xarray_to_irispandas_i(func):
|
|
417
|
+
"""Decorator that converts all input of a function that is in the form of
|
|
418
|
+
DataArrays/xarray Datasets into xarray Iris cubes/pandas Dataframes and
|
|
419
|
+
converts all outputs with the type Iris cubes/pandas Dataframes back into
|
|
420
|
+
xarray DataArray/xarray Dataset.
|
|
421
|
+
|
|
422
|
+
Parameters
|
|
423
|
+
----------
|
|
424
|
+
func : function
|
|
425
|
+
Function to be decorated.
|
|
426
|
+
|
|
427
|
+
Returns
|
|
428
|
+
-------
|
|
429
|
+
wrapper : function
|
|
430
|
+
Function including decorator.
|
|
431
|
+
|
|
432
|
+
Examples
|
|
433
|
+
--------
|
|
434
|
+
>>> linking_trackpy_xarray = xarray_to_irispandas(
|
|
435
|
+
linking_trackpy
|
|
436
|
+
)
|
|
437
|
+
|
|
438
|
+
This line creates a new function that can process xarray inputs and
|
|
439
|
+
also outputs in xarray formats, but otherwise works just like the
|
|
440
|
+
original function:
|
|
441
|
+
|
|
442
|
+
>>> track_xarray = linking_trackpy_xarray(
|
|
443
|
+
features_xarray, field_xarray, dt, dx
|
|
444
|
+
)
|
|
445
|
+
"""
|
|
446
|
+
import iris
|
|
447
|
+
import xarray
|
|
448
|
+
import pandas as pd
|
|
449
|
+
|
|
450
|
+
@functools.wraps(func)
|
|
451
|
+
def wrapper(*args, **kwargs):
|
|
452
|
+
# print(args)
|
|
453
|
+
# print(kwargs)
|
|
454
|
+
if any(
|
|
455
|
+
[
|
|
456
|
+
(type(arg) == xarray.DataArray or type(arg) == xarray.Dataset)
|
|
457
|
+
for arg in args
|
|
458
|
+
]
|
|
459
|
+
) or any(
|
|
460
|
+
[
|
|
461
|
+
(type(arg) == xarray.DataArray or type(arg) == xarray.Dataset)
|
|
462
|
+
for arg in kwargs.values()
|
|
463
|
+
]
|
|
464
|
+
):
|
|
465
|
+
# print("converting xarray to iris and back")
|
|
466
|
+
args = tuple(
|
|
467
|
+
[
|
|
468
|
+
(
|
|
469
|
+
xarray.DataArray.to_iris(arg).copy(arg.data)
|
|
470
|
+
if type(arg) == xarray.DataArray
|
|
471
|
+
else (
|
|
472
|
+
arg.to_dataframe()
|
|
473
|
+
if type(arg) == xarray.Dataset
|
|
474
|
+
else arg
|
|
475
|
+
)
|
|
476
|
+
)
|
|
477
|
+
for arg in args
|
|
478
|
+
]
|
|
479
|
+
)
|
|
480
|
+
if kwargs:
|
|
481
|
+
kwargs_new = _conv_kwargs_xarray_to_irispandas(kwargs)
|
|
482
|
+
else:
|
|
483
|
+
kwargs_new = kwargs
|
|
484
|
+
# print(args)
|
|
485
|
+
# print(kwargs)
|
|
486
|
+
output = func(*args, **kwargs_new)
|
|
487
|
+
if type(output) == tuple:
|
|
488
|
+
output = tuple(
|
|
489
|
+
[
|
|
490
|
+
(
|
|
491
|
+
xarray.DataArray.from_iris(output_item)
|
|
492
|
+
if type(output_item) == iris.cube.Cube
|
|
493
|
+
else (
|
|
494
|
+
output_item.to_xarray()
|
|
495
|
+
if type(output_item) == pd.DataFrame
|
|
496
|
+
else output_item
|
|
497
|
+
)
|
|
498
|
+
)
|
|
499
|
+
for output_item in output
|
|
500
|
+
]
|
|
501
|
+
)
|
|
502
|
+
else:
|
|
503
|
+
if type(output) == iris.cube.Cube:
|
|
504
|
+
output = xarray.DataArray.from_iris(output)
|
|
505
|
+
elif type(output) == pd.DataFrame:
|
|
506
|
+
output = output.to_xarray()
|
|
507
|
+
|
|
508
|
+
else:
|
|
509
|
+
output = func(*args, **kwargs)
|
|
510
|
+
# print(output)
|
|
511
|
+
return output
|
|
512
|
+
|
|
513
|
+
return wrapper
|
|
514
|
+
|
|
515
|
+
return xarray_to_irispandas_i
|
|
516
|
+
|
|
517
|
+
|
|
518
|
+
def njit_if_available(func, **kwargs):
|
|
519
|
+
"""Decorator to wrap a function with numba.njit if available.
|
|
520
|
+
If numba isn't available, it just returns the function.
|
|
521
|
+
|
|
522
|
+
Parameters
|
|
523
|
+
----------
|
|
524
|
+
func: function object
|
|
525
|
+
Function to wrap with njit
|
|
526
|
+
kwargs:
|
|
527
|
+
Keyword arguments to pass to numba njit
|
|
528
|
+
"""
|
|
529
|
+
try:
|
|
530
|
+
from numba import njit
|
|
531
|
+
|
|
532
|
+
return njit(func, kwargs)
|
|
533
|
+
except KeyboardInterrupt as kie:
|
|
534
|
+
raise
|
|
535
|
+
except Exception as exc:
|
|
536
|
+
warnings.warn(
|
|
537
|
+
"Numba not able to be imported; periodic boundary calculations will be slower."
|
|
538
|
+
"Exception raised: " + repr(exc)
|
|
539
|
+
)
|
|
540
|
+
return func
|