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.
Files changed (53) hide show
  1. tobac/__init__.py +112 -0
  2. tobac/analysis/__init__.py +31 -0
  3. tobac/analysis/cell_analysis.py +628 -0
  4. tobac/analysis/feature_analysis.py +212 -0
  5. tobac/analysis/spatial.py +619 -0
  6. tobac/centerofgravity.py +226 -0
  7. tobac/feature_detection.py +1758 -0
  8. tobac/merge_split.py +324 -0
  9. tobac/plotting.py +2321 -0
  10. tobac/segmentation/__init__.py +10 -0
  11. tobac/segmentation/watershed_segmentation.py +1316 -0
  12. tobac/testing.py +1179 -0
  13. tobac/tests/segmentation_tests/test_iris_xarray_segmentation.py +0 -0
  14. tobac/tests/segmentation_tests/test_segmentation.py +1183 -0
  15. tobac/tests/segmentation_tests/test_segmentation_time_pad.py +104 -0
  16. tobac/tests/test_analysis_spatial.py +1109 -0
  17. tobac/tests/test_convert.py +265 -0
  18. tobac/tests/test_datetime.py +216 -0
  19. tobac/tests/test_decorators.py +148 -0
  20. tobac/tests/test_feature_detection.py +1321 -0
  21. tobac/tests/test_generators.py +273 -0
  22. tobac/tests/test_import.py +24 -0
  23. tobac/tests/test_iris_xarray_match_utils.py +244 -0
  24. tobac/tests/test_merge_split.py +351 -0
  25. tobac/tests/test_pbc_utils.py +497 -0
  26. tobac/tests/test_sample_data.py +197 -0
  27. tobac/tests/test_testing.py +747 -0
  28. tobac/tests/test_tracking.py +714 -0
  29. tobac/tests/test_utils.py +650 -0
  30. tobac/tests/test_utils_bulk_statistics.py +789 -0
  31. tobac/tests/test_utils_coordinates.py +328 -0
  32. tobac/tests/test_utils_internal.py +97 -0
  33. tobac/tests/test_xarray_utils.py +232 -0
  34. tobac/tracking.py +613 -0
  35. tobac/utils/__init__.py +27 -0
  36. tobac/utils/bulk_statistics.py +360 -0
  37. tobac/utils/datetime.py +184 -0
  38. tobac/utils/decorators.py +540 -0
  39. tobac/utils/general.py +753 -0
  40. tobac/utils/generators.py +87 -0
  41. tobac/utils/internal/__init__.py +2 -0
  42. tobac/utils/internal/coordinates.py +430 -0
  43. tobac/utils/internal/iris_utils.py +462 -0
  44. tobac/utils/internal/label_props.py +82 -0
  45. tobac/utils/internal/xarray_utils.py +439 -0
  46. tobac/utils/mask.py +364 -0
  47. tobac/utils/periodic_boundaries.py +419 -0
  48. tobac/wrapper.py +244 -0
  49. tobac-1.6.2.dist-info/METADATA +154 -0
  50. tobac-1.6.2.dist-info/RECORD +53 -0
  51. tobac-1.6.2.dist-info/WHEEL +5 -0
  52. tobac-1.6.2.dist-info/licenses/LICENSE +29 -0
  53. tobac-1.6.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,226 @@
1
+ """Identify center of gravity and mass for analysis."""
2
+
3
+ import logging
4
+ import warnings
5
+
6
+
7
+ def calculate_cog(tracks, mass, mask):
8
+ """Calculate center of gravity and mass for each tracked cell.
9
+
10
+ Parameters
11
+ ----------
12
+ tracks : pandas.DataFrame
13
+ DataFrame containing trajectories of cell centers.
14
+
15
+ mass : iris.cube.Cube
16
+ Cube of quantity (need coordinates 'time',
17
+ 'geopotential_height','projection_x_coordinate' and
18
+ 'projection_y_coordinate').
19
+
20
+ mask : iris.cube.Cube
21
+ Cube containing mask (int > where belonging to area/volume
22
+ of feature, 0 else).
23
+
24
+ Returns
25
+ -------
26
+ tracks_out : pandas.DataFrame
27
+ Dataframe containing t, x, y, z positions of center of gravity
28
+ and total mass of each tracked cell at each timestep.
29
+ """
30
+
31
+ from .utils import mask_cube_cell
32
+ from iris import Constraint
33
+
34
+ warnings.warn(
35
+ "calculate_cog is depreciated and will be removed or significantly changed in v2.0.",
36
+ DeprecationWarning,
37
+ )
38
+
39
+ logging.info("start calculating centre of gravity for tracked cells")
40
+
41
+ tracks_out = tracks[["time", "frame", "cell", "time_cell"]]
42
+
43
+ for i_row, row in tracks_out.iterrows():
44
+ cell = row["cell"]
45
+ constraint_time = Constraint(time=row["time"])
46
+ mass_i = mass.extract(constraint_time)
47
+ mask_i = mask.extract(constraint_time)
48
+ mass_masked_i = mask_cube_cell(mass_i, mask_i, cell)
49
+ x_M, y_M, z_M, mass_M = center_of_gravity(mass_masked_i)
50
+ tracks_out.loc[i_row, "x_M"] = float(x_M)
51
+ tracks_out.loc[i_row, "y_M"] = float(y_M)
52
+ tracks_out.loc[i_row, "z_M"] = float(z_M)
53
+ tracks_out.loc[i_row, "mass"] = float(mass_M)
54
+
55
+ logging.info("Finished calculating centre of gravity for tracked cells")
56
+
57
+ return tracks_out
58
+
59
+
60
+ def calculate_cog_untracked(mass, mask):
61
+ """Calculate center of gravity and mass for untracked domain parts.
62
+
63
+ Parameters
64
+ ----------
65
+ mass : iris.cube.Cube
66
+ Cube of quantity (need coordinates 'time',
67
+ 'geopotential_height','projection_x_coordinate' and
68
+ 'projection_y_coordinate').
69
+
70
+ mask : iris.cube.Cube
71
+ Cube containing mask (int > where belonging to area/volume
72
+ of feature, 0 else).
73
+
74
+ Returns
75
+ -------
76
+ tracks_out : pandas.DataFrame
77
+ Dataframe containing t, x, y, z positions of center of gravity
78
+ and total mass for untracked part of the domain.
79
+ """
80
+
81
+ from pandas import DataFrame
82
+ from .utils import mask_cube_untracked
83
+ from iris import Constraint
84
+
85
+ warnings.warn(
86
+ "calculate_cog_untracked is depreciated and will be removed or significantly changed in v2.0.",
87
+ DeprecationWarning,
88
+ )
89
+
90
+ logging.info(
91
+ "start calculating centre of gravity for untracked parts of the domain"
92
+ )
93
+ tracks_out = DataFrame()
94
+ time_coord = mass.coord("time")
95
+ tracks_out["frame"] = range(len(time_coord.points))
96
+ for i_row, row in tracks_out.iterrows():
97
+ time_i = time_coord.units.num2date(time_coord[int(row["frame"])].points[0])
98
+ constraint_time = Constraint(time=time_i)
99
+ mass_i = mass.extract(constraint_time)
100
+ mask_i = mask.extract(constraint_time)
101
+ mass_untracked_i = mask_cube_untracked(mass_i, mask_i)
102
+ x_M, y_M, z_M, mass_M = center_of_gravity(mass_untracked_i)
103
+ tracks_out.loc[i_row, "time"] = time_i
104
+ tracks_out.loc[i_row, "x_M"] = float(x_M)
105
+ tracks_out.loc[i_row, "y_M"] = float(y_M)
106
+ tracks_out.loc[i_row, "z_M"] = float(z_M)
107
+ tracks_out.loc[i_row, "mass"] = float(mass_M)
108
+
109
+ logging.info(
110
+ "Finished calculating centre of gravity for untracked parts of the domain"
111
+ )
112
+
113
+ return tracks_out
114
+
115
+
116
+ def calculate_cog_domain(mass):
117
+ """Calculate center of gravity and mass for entire domain.
118
+
119
+ Parameters
120
+ ----------
121
+ mass : iris.cube.Cube
122
+ Cube of quantity (need coordinates 'time',
123
+ 'geopotential_height','projection_x_coordinate' and
124
+ 'projection_y_coordinate').
125
+
126
+ Returns
127
+ -------
128
+ tracks_out : pandas.DataFrame
129
+ Dataframe containing t, x, y, z positions of center of gravity
130
+ and total mass of the entire domain.
131
+ """
132
+
133
+ from pandas import DataFrame
134
+ from iris import Constraint
135
+
136
+ warnings.warn(
137
+ "calculate_cog_domain is depreciated and will be removed or significantly changed in v2.0.",
138
+ DeprecationWarning,
139
+ )
140
+
141
+ logging.info("start calculating centre of gravity for entire domain")
142
+
143
+ time_coord = mass.coord("time")
144
+
145
+ tracks_out = DataFrame()
146
+ tracks_out["frame"] = range(len(time_coord.points))
147
+ for i_row, row in tracks_out.iterrows():
148
+ time_i = time_coord.units.num2date(time_coord[int(row["frame"])].points[0])
149
+ constraint_time = Constraint(time=time_i)
150
+ mass_i = mass.extract(constraint_time)
151
+ x_M, y_M, z_M, mass_M = center_of_gravity(mass_i)
152
+ tracks_out.loc[i_row, "time"] = time_i
153
+ tracks_out.loc[i_row, "x_M"] = float(x_M)
154
+ tracks_out.loc[i_row, "y_M"] = float(y_M)
155
+ tracks_out.loc[i_row, "z_M"] = float(z_M)
156
+ tracks_out.loc[i_row, "mass"] = float(mass_M)
157
+
158
+ logging.info("Finished calculating centre of gravity for entire domain")
159
+
160
+ return tracks_out
161
+
162
+
163
+ def center_of_gravity(cube_in):
164
+ """Calculate center of gravity and sum of quantity.
165
+
166
+ Parameters
167
+ ----------
168
+ cube_in : iris.cube.Cube
169
+ Cube (potentially masked) of quantity (need coordinates
170
+ 'geopotential_height','projection_x_coordinate' and
171
+ 'projection_y_coordinate').
172
+
173
+ Returns
174
+ -------
175
+ x : float
176
+ X position of center of gravity.
177
+
178
+ y : float
179
+ Y position of center of gravity.
180
+
181
+ z : float
182
+ Z position of center of gravity.
183
+
184
+ variable_sum : float
185
+ Sum of quantity of over unmasked part of the cube.
186
+ """
187
+
188
+ from iris.analysis import SUM
189
+ import numpy as np
190
+
191
+ warnings.warn(
192
+ "center_of_gravity is depreciated and will be removed or significantly changed in v2.0.",
193
+ DeprecationWarning,
194
+ )
195
+
196
+ cube_sum = cube_in.collapsed(["bottom_top", "south_north", "west_east"], SUM)
197
+ z = cube_in.coord("geopotential_height")
198
+ x = cube_in.coord("projection_x_coordinate")
199
+ y = cube_in.coord("projection_y_coordinate")
200
+ dimensions_collapse = ["model_level_number", "x", "y"]
201
+ for coord in cube_in.coords():
202
+ if coord.ndim > 1 and (
203
+ cube_in.coord_dims(dimensions_collapse[0])[0] in cube_in.coord_dims(coord)
204
+ or cube_in.coord_dims(dimensions_collapse[1])[0]
205
+ in cube_in.coord_dims(coord)
206
+ or cube_in.coord_dims(dimensions_collapse[2])[0]
207
+ in cube_in.coord_dims(coord)
208
+ ):
209
+ cube_in.remove_coord(coord.name())
210
+ if cube_sum.data > 0:
211
+ x = (
212
+ (cube_in * x).collapsed(["model_level_number", "x", "y"], SUM) / cube_sum
213
+ ).data
214
+ y = (
215
+ (cube_in * y).collapsed(["model_level_number", "x", "y"], SUM) / cube_sum
216
+ ).data
217
+ z = (
218
+ (cube_in * z.points).collapsed(["model_level_number", "x", "y"], SUM)
219
+ / cube_sum
220
+ ).data
221
+ else:
222
+ x = np.nan
223
+ y = np.nan
224
+ z = np.nan
225
+ variable_sum = cube_sum.data
226
+ return (x, y, z, variable_sum)