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
tobac/utils/mask.py
ADDED
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
"""Provide essential methods for masking"""
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def column_mask_from2D(mask_2D, cube, z_coord="model_level_number"):
|
|
5
|
+
"""Turn 2D watershedding mask into a 3D mask of selected columns.
|
|
6
|
+
|
|
7
|
+
Parameters
|
|
8
|
+
----------
|
|
9
|
+
cube : iris.cube.Cube
|
|
10
|
+
Data cube.
|
|
11
|
+
|
|
12
|
+
mask_2D : iris.cube.Cube
|
|
13
|
+
2D cube containing mask (int id for tacked volumes 0
|
|
14
|
+
everywhere else).
|
|
15
|
+
|
|
16
|
+
z_coord : str
|
|
17
|
+
Name of the vertical coordinate in the cube.
|
|
18
|
+
|
|
19
|
+
Returns
|
|
20
|
+
-------
|
|
21
|
+
mask_2D : iris.cube.Cube
|
|
22
|
+
3D cube containing columns of 2D mask (int id for tracked
|
|
23
|
+
volumes, 0 everywhere else).
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
from copy import deepcopy
|
|
27
|
+
|
|
28
|
+
mask_3D = deepcopy(cube)
|
|
29
|
+
mask_3D.rename("segmentation_mask")
|
|
30
|
+
dim = mask_3D.coord_dims(z_coord)[0]
|
|
31
|
+
for i in range(len(mask_3D.coord(z_coord).points)):
|
|
32
|
+
slc = [slice(None)] * len(mask_3D.shape)
|
|
33
|
+
slc[dim] = slice(i, i + 1)
|
|
34
|
+
mask_out = mask_3D[slc]
|
|
35
|
+
mask_3D.data[slc] = mask_2D.core_data()
|
|
36
|
+
return mask_3D
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def mask_cube_cell(variable_cube, mask, cell, track):
|
|
40
|
+
"""Mask cube for tracked volume of an individual cell.
|
|
41
|
+
|
|
42
|
+
Parameters
|
|
43
|
+
----------
|
|
44
|
+
variable_cube : iris.cube.Cube
|
|
45
|
+
Unmasked data cube.
|
|
46
|
+
|
|
47
|
+
mask : iris.cube.Cube
|
|
48
|
+
Cube containing mask (int id for tracked volumes, 0 everywhere
|
|
49
|
+
else).
|
|
50
|
+
|
|
51
|
+
cell : int
|
|
52
|
+
Integer id of cell to create masked cube for.
|
|
53
|
+
|
|
54
|
+
track : pandas.DataFrame
|
|
55
|
+
Output of the linking.
|
|
56
|
+
|
|
57
|
+
Returns
|
|
58
|
+
-------
|
|
59
|
+
variable_cube_out : iris.cube.Cube
|
|
60
|
+
Masked cube with data for respective cell.
|
|
61
|
+
"""
|
|
62
|
+
|
|
63
|
+
from copy import deepcopy
|
|
64
|
+
|
|
65
|
+
variable_cube_out = deepcopy(variable_cube)
|
|
66
|
+
feature_ids = track.loc[track["cell"] == cell, "feature"].values
|
|
67
|
+
variable_cube_out = mask_cube_features(variable_cube, mask, feature_ids)
|
|
68
|
+
return variable_cube_out
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def mask_cube_all(variable_cube, mask):
|
|
72
|
+
"""Mask cube (iris.cube) for tracked volume.
|
|
73
|
+
|
|
74
|
+
Parameters
|
|
75
|
+
----------
|
|
76
|
+
variable_cube : iris.cube.Cube
|
|
77
|
+
Unmasked data cube.
|
|
78
|
+
|
|
79
|
+
mask : iris.cube.Cube
|
|
80
|
+
Cube containing mask (int id for tacked volumes 0 everywhere
|
|
81
|
+
else).
|
|
82
|
+
|
|
83
|
+
Returns
|
|
84
|
+
-------
|
|
85
|
+
variable_cube_out : iris.cube.Cube
|
|
86
|
+
Masked cube for untracked volume.
|
|
87
|
+
"""
|
|
88
|
+
|
|
89
|
+
from dask.array import ma
|
|
90
|
+
from copy import deepcopy
|
|
91
|
+
|
|
92
|
+
variable_cube_out = deepcopy(variable_cube)
|
|
93
|
+
variable_cube_out.data = ma.masked_where(
|
|
94
|
+
mask.core_data() == 0, variable_cube_out.core_data()
|
|
95
|
+
)
|
|
96
|
+
return variable_cube_out
|
|
97
|
+
|
|
98
|
+
|
|
99
|
+
def mask_cube_untracked(variable_cube, mask):
|
|
100
|
+
"""Mask cube (iris.cube) for untracked volume.
|
|
101
|
+
|
|
102
|
+
Parameters
|
|
103
|
+
----------
|
|
104
|
+
variable_cube : iris.cube.Cube
|
|
105
|
+
Unmasked data cube.
|
|
106
|
+
|
|
107
|
+
mask : iris.cube.Cube
|
|
108
|
+
Cube containing mask (int id for tacked volumes 0 everywhere
|
|
109
|
+
else).
|
|
110
|
+
|
|
111
|
+
Returns
|
|
112
|
+
-------
|
|
113
|
+
variable_cube_out : iris.cube.Cube
|
|
114
|
+
Masked cube for untracked volume.
|
|
115
|
+
"""
|
|
116
|
+
|
|
117
|
+
from dask.array import ma
|
|
118
|
+
from copy import deepcopy
|
|
119
|
+
|
|
120
|
+
variable_cube_out = deepcopy(variable_cube)
|
|
121
|
+
variable_cube_out.data = ma.masked_where(
|
|
122
|
+
mask.core_data() > 0, variable_cube_out.core_data()
|
|
123
|
+
)
|
|
124
|
+
return variable_cube_out
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def mask_cube(cube_in, mask):
|
|
128
|
+
"""Mask cube where mask is not zero.
|
|
129
|
+
|
|
130
|
+
Parameters
|
|
131
|
+
----------
|
|
132
|
+
cube_in : iris.cube.Cube
|
|
133
|
+
Unmasked data cube.
|
|
134
|
+
|
|
135
|
+
mask : iris.cube.Cube
|
|
136
|
+
Mask to use for masking, >0 where cube is supposed to be masked.
|
|
137
|
+
|
|
138
|
+
Returns
|
|
139
|
+
-------
|
|
140
|
+
variable_cube_out : iris.cube.Cube
|
|
141
|
+
Masked cube.
|
|
142
|
+
"""
|
|
143
|
+
|
|
144
|
+
from dask.array import ma
|
|
145
|
+
from copy import deepcopy
|
|
146
|
+
|
|
147
|
+
cube_out = deepcopy(cube_in)
|
|
148
|
+
cube_out.data = ma.masked_where(mask.core_data() != 0, cube_in.core_data())
|
|
149
|
+
return cube_out
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def mask_cell(mask, cell, track, masked=False):
|
|
153
|
+
"""Create mask for specific cell.
|
|
154
|
+
|
|
155
|
+
Parameters
|
|
156
|
+
----------
|
|
157
|
+
mask : iris.cube.Cube
|
|
158
|
+
Cube containing mask (int id for tracked volumes 0 everywhere
|
|
159
|
+
else).
|
|
160
|
+
|
|
161
|
+
cell : int
|
|
162
|
+
Integer id of cell to create masked cube for.
|
|
163
|
+
|
|
164
|
+
track : pandas.DataFrame
|
|
165
|
+
Output of the linking.
|
|
166
|
+
|
|
167
|
+
masked : bool, optional
|
|
168
|
+
Bool determining whether to mask the mask for the cell where
|
|
169
|
+
it is 0. Default is False.
|
|
170
|
+
|
|
171
|
+
Returns
|
|
172
|
+
-------
|
|
173
|
+
mask_i : numpy.ndarray
|
|
174
|
+
Mask for a specific cell.
|
|
175
|
+
"""
|
|
176
|
+
|
|
177
|
+
feature_ids = track.loc[track["cell"] == cell, "feature"].values
|
|
178
|
+
mask_i = mask_features(mask, feature_ids, masked=masked)
|
|
179
|
+
return mask_i
|
|
180
|
+
|
|
181
|
+
|
|
182
|
+
def mask_cell_surface(mask, cell, track, masked=False, z_coord="model_level_number"):
|
|
183
|
+
"""Create surface projection of 3d-mask for individual cell by
|
|
184
|
+
collapsing one coordinate.
|
|
185
|
+
|
|
186
|
+
Parameters
|
|
187
|
+
----------
|
|
188
|
+
mask : iris.cube.Cube
|
|
189
|
+
Cube containing mask (int id for tacked volumes, 0 everywhere
|
|
190
|
+
else).
|
|
191
|
+
|
|
192
|
+
cell : int
|
|
193
|
+
Integer id of cell to create masked cube for.
|
|
194
|
+
|
|
195
|
+
track : pandas.DataFrame
|
|
196
|
+
Output of the linking.
|
|
197
|
+
|
|
198
|
+
masked : bool, optional
|
|
199
|
+
Bool determining whether to mask the mask for the cell where
|
|
200
|
+
it is 0. Default is False.
|
|
201
|
+
|
|
202
|
+
z_coord : str, optional
|
|
203
|
+
Name of the coordinate to collapse. Default is 'model_level_number'.
|
|
204
|
+
|
|
205
|
+
Returns
|
|
206
|
+
-------
|
|
207
|
+
mask_i_surface : iris.cube.Cube
|
|
208
|
+
Collapsed Masked cube for the cell with the maximum value
|
|
209
|
+
along the collapsed coordinate.
|
|
210
|
+
|
|
211
|
+
"""
|
|
212
|
+
|
|
213
|
+
feature_ids = track.loc[track["cell"] == cell, "feature"].values
|
|
214
|
+
mask_i_surface = mask_features_surface(
|
|
215
|
+
mask, feature_ids, masked=masked, z_coord=z_coord
|
|
216
|
+
)
|
|
217
|
+
return mask_i_surface
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def mask_cube_features(variable_cube, mask, feature_ids):
|
|
221
|
+
"""Mask cube for tracked volume of one or more specific
|
|
222
|
+
features.
|
|
223
|
+
|
|
224
|
+
Parameters
|
|
225
|
+
----------
|
|
226
|
+
variable_cube : iris.cube.Cube
|
|
227
|
+
Unmasked data cube.
|
|
228
|
+
|
|
229
|
+
mask : iris.cube.Cube
|
|
230
|
+
Cube containing mask (int id for tacked volumes, 0 everywhere
|
|
231
|
+
else).
|
|
232
|
+
|
|
233
|
+
feature_ids : int or list of ints
|
|
234
|
+
Integer ids of features to create masked cube for.
|
|
235
|
+
|
|
236
|
+
Returns
|
|
237
|
+
-------
|
|
238
|
+
variable_cube_out : iris.cube.Cube
|
|
239
|
+
Masked cube with data for respective features.
|
|
240
|
+
"""
|
|
241
|
+
|
|
242
|
+
from dask.array import ma, isin
|
|
243
|
+
from copy import deepcopy
|
|
244
|
+
|
|
245
|
+
variable_cube_out = deepcopy(variable_cube)
|
|
246
|
+
variable_cube_out.data = ma.masked_where(
|
|
247
|
+
~isin(mask.core_data(), feature_ids), variable_cube_out.core_data()
|
|
248
|
+
)
|
|
249
|
+
return variable_cube_out
|
|
250
|
+
|
|
251
|
+
|
|
252
|
+
def mask_features(mask, feature_ids, masked=False):
|
|
253
|
+
"""Create mask for specific features.
|
|
254
|
+
|
|
255
|
+
Parameters
|
|
256
|
+
----------
|
|
257
|
+
mask : iris.cube.Cube
|
|
258
|
+
Cube containing mask (int id for tacked volumes 0 everywhere
|
|
259
|
+
else).
|
|
260
|
+
|
|
261
|
+
feature_ids : int or list of ints
|
|
262
|
+
Integer ids of the features to create the masked cube for.
|
|
263
|
+
|
|
264
|
+
masked : bool, optional
|
|
265
|
+
Bool determining whether to mask the mask for the cell where
|
|
266
|
+
it is 0. Default is False.
|
|
267
|
+
|
|
268
|
+
Returns
|
|
269
|
+
-------
|
|
270
|
+
mask_i : numpy.ndarray
|
|
271
|
+
Masked cube for specific features.
|
|
272
|
+
"""
|
|
273
|
+
|
|
274
|
+
from dask.array import ma, isin
|
|
275
|
+
from copy import deepcopy
|
|
276
|
+
|
|
277
|
+
mask_i = deepcopy(mask)
|
|
278
|
+
mask_i_data = mask_i.core_data()
|
|
279
|
+
mask_i_data[~isin(mask_i.core_data(), feature_ids)] = 0
|
|
280
|
+
if masked:
|
|
281
|
+
mask_i.data = ma.masked_equal(mask_i.core_data(), 0)
|
|
282
|
+
return mask_i
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
def mask_features_surface(
|
|
286
|
+
mask, feature_ids, masked=False, z_coord="model_level_number"
|
|
287
|
+
):
|
|
288
|
+
"""Create surface projection of 3d-mask for specific features
|
|
289
|
+
by collapsing one coordinate.
|
|
290
|
+
|
|
291
|
+
Parameters
|
|
292
|
+
----------
|
|
293
|
+
mask : iris.cube.Cube
|
|
294
|
+
Cube containing mask (int id for tacked volumes 0 everywhere
|
|
295
|
+
else).
|
|
296
|
+
|
|
297
|
+
feature_ids : int or list of ints
|
|
298
|
+
Integer ids of the features to create the masked cube for.
|
|
299
|
+
|
|
300
|
+
masked : bool, optional
|
|
301
|
+
Bool determining whether to mask the mask for the cell where
|
|
302
|
+
it is 0. Default is False
|
|
303
|
+
|
|
304
|
+
z_coord : str, optional
|
|
305
|
+
Name of the coordinate to collapse. Default is
|
|
306
|
+
'model_level_number'.
|
|
307
|
+
|
|
308
|
+
Returns
|
|
309
|
+
-------
|
|
310
|
+
mask_i_surface : iris.cube.Cube
|
|
311
|
+
Collapsed Masked cube for the features with the maximum value
|
|
312
|
+
along the collapsed coordinate.
|
|
313
|
+
"""
|
|
314
|
+
|
|
315
|
+
from iris.analysis import MAX
|
|
316
|
+
from dask.array import ma, isin
|
|
317
|
+
from copy import deepcopy
|
|
318
|
+
|
|
319
|
+
mask_i = deepcopy(mask)
|
|
320
|
+
# mask_i.data=[~isin(mask_i.data,feature_ids)]=0
|
|
321
|
+
mask_i_data = mask_i.core_data()
|
|
322
|
+
mask_i_data[~isin(mask_i.core_data(), feature_ids)] = 0
|
|
323
|
+
mask_i_surface = mask_i.collapsed(z_coord, MAX)
|
|
324
|
+
if masked:
|
|
325
|
+
mask_i_surface.data = ma.masked_equal(mask_i_surface.core_data(), 0)
|
|
326
|
+
return mask_i_surface
|
|
327
|
+
|
|
328
|
+
|
|
329
|
+
def mask_all_surface(mask, masked=False, z_coord="model_level_number"):
|
|
330
|
+
"""Create surface projection of 3d-mask for all features
|
|
331
|
+
by collapsing one coordinate.
|
|
332
|
+
|
|
333
|
+
Parameters
|
|
334
|
+
----------
|
|
335
|
+
mask : iris.cube.Cube
|
|
336
|
+
Cube containing mask (int id for tacked volumes 0 everywhere
|
|
337
|
+
else).
|
|
338
|
+
|
|
339
|
+
masked : bool, optional
|
|
340
|
+
Bool determining whether to mask the mask for the cell where
|
|
341
|
+
it is 0. Default is False
|
|
342
|
+
|
|
343
|
+
z_coord : str, optional
|
|
344
|
+
Name of the coordinate to collapse. Default is
|
|
345
|
+
'model_level_number'.
|
|
346
|
+
|
|
347
|
+
Returns
|
|
348
|
+
-------
|
|
349
|
+
mask_i_surface : iris.cube.Cube (2D)
|
|
350
|
+
Collapsed Masked cube for the features with the maximum value
|
|
351
|
+
along the collapsed coordinate.
|
|
352
|
+
"""
|
|
353
|
+
|
|
354
|
+
from iris.analysis import MAX
|
|
355
|
+
from dask.array import ma, isin
|
|
356
|
+
from copy import deepcopy
|
|
357
|
+
|
|
358
|
+
mask_i = deepcopy(mask)
|
|
359
|
+
mask_i_surface = mask_i.collapsed(z_coord, MAX)
|
|
360
|
+
mask_i_surface_data = mask_i_surface.core_data()
|
|
361
|
+
mask_i_surface.data[mask_i_surface_data > 0] = 1
|
|
362
|
+
if masked:
|
|
363
|
+
mask_i_surface.data = ma.masked_equal(mask_i_surface.core_data(), 0)
|
|
364
|
+
return mask_i_surface
|