22
22
dense_lucaskanade
23
23
"""
24
24
25
+ import time
26
+
25
27
import numpy as np
28
+ import xarray as xr
26
29
from numpy .ma .core import MaskedArray
27
30
31
+ from pysteps import feature , utils
28
32
from pysteps .decorators import check_input_frames
29
-
30
- from pysteps import utils , feature
31
33
from pysteps .tracking .lucaskanade import track_features
32
34
from pysteps .utils .cleansing import decluster , detect_outliers
33
35
from pysteps .utils .images import morph_opening
34
36
35
- import time
36
-
37
37
38
38
@check_input_frames (2 )
39
39
def dense_lucaskanade (
40
- input_images ,
40
+ dataset : xr . Dataset ,
41
41
lk_kwargs = None ,
42
42
fd_method = "shitomasi" ,
43
43
fd_kwargs = None ,
@@ -73,18 +73,14 @@ def dense_lucaskanade(
73
73
74
74
Parameters
75
75
----------
76
- input_images: ndarray_ or MaskedArray_
77
- Array of shape (T, m, n) containing a sequence of *T* two-dimensional
78
- input images of shape (m, n). The indexing order in **input_images** is
79
- assumed to be (time, latitude, longitude).
80
-
81
- *T* = 2 is the minimum required number of images.
82
- With *T* > 2, all the resulting sparse vectors are pooled together for
83
- the final interpolation on a regular grid.
84
-
85
- In case of ndarray_, invalid values (Nans or infs) are masked,
86
- otherwise the mask of the MaskedArray_ is used. Such mask defines a
87
- region where features are not detected for the tracking algorithm.
76
+ dataset: xarray.Dataset
77
+ Input dataset as described in the documentation of
78
+ :py:mod:`pysteps.io.importers`. It has to contain a precipitation data variable.
79
+ The dataset has to have a time dimension. The size of the time dimension needs to
80
+ be at least 2. If it is larger than 2, all the resulting sparse vectors are pooled
81
+ together for the final interpolation on a regular grid. Invalid values (Nans or infs)
82
+ are masked. This mask defines a region where features are not detected for the tracking
83
+ algorithm.
88
84
89
85
lk_kwargs: dict, optional
90
86
Optional dictionary containing keyword arguments for the `Lucas-Kanade`_
@@ -151,14 +147,10 @@ def dense_lucaskanade(
151
147
152
148
Returns
153
149
-------
154
- out: ndarray_ or tuple
155
- If **dense=True** (the default), return the advection field having shape
156
- (2, m, n), where out[0, :, :] contains the x-components of the motion
157
- vectors and out[1, :, :] contains the y-components.
158
- The velocities are in units of pixels / timestep, where timestep is the
159
- time difference between the two input images.
160
- Return a zero motion field of shape (2, m, n) when no motion is
161
- detected.
150
+ out: xarray.Dataset or tuple
151
+ If **dense=True** (the default), return the input dataset with the advection
152
+ field added in the ``velocity_x`` and ``velocity_y`` data variables.
153
+ Return a zero motion field when no motion is detected.
162
154
163
155
If **dense=False**, it returns a tuple containing the 2-dimensional
164
156
arrays **xy** and **uv**, where x, y define the vector locations,
@@ -179,7 +171,9 @@ def dense_lucaskanade(
179
171
Understanding Workshop, pp. 121–130, 1981.
180
172
"""
181
173
182
- input_images = input_images .copy ()
174
+ dataset = dataset .copy (deep = True )
175
+ precip_var = dataset .attrs ["precip_var" ]
176
+ input_images = dataset [precip_var ].values
183
177
184
178
if verbose :
185
179
print ("Computing the motion field with the Lucas-Kanade method." )
@@ -244,7 +238,10 @@ def dense_lucaskanade(
244
238
# return zero motion field is no sparse vectors are found
245
239
if xy .shape [0 ] == 0 :
246
240
if dense :
247
- return np .zeros ((2 , domain_size [0 ], domain_size [1 ]))
241
+ uvgrid = np .zeros ((2 , domain_size [0 ], domain_size [1 ]))
242
+ dataset ["velocity_x" ] = (["y" , "x" ], uvgrid [0 ])
243
+ dataset ["velocity_y" ] = (["y" , "x" ], uvgrid [1 ])
244
+ return dataset
248
245
else :
249
246
return xy , uv
250
247
@@ -266,14 +263,20 @@ def dense_lucaskanade(
266
263
267
264
# return zero motion field if no sparse vectors are left for interpolation
268
265
if xy .shape [0 ] == 0 :
269
- return np .zeros ((2 , domain_size [0 ], domain_size [1 ]))
266
+ uvgrid = np .zeros ((2 , domain_size [0 ], domain_size [1 ]))
267
+ dataset ["velocity_x" ] = (["y" , "x" ], uvgrid [0 ])
268
+ dataset ["velocity_y" ] = (["y" , "x" ], uvgrid [1 ])
269
+ return dataset
270
270
271
271
# interpolation
272
272
xgrid = np .arange (domain_size [1 ])
273
273
ygrid = np .arange (domain_size [0 ])
274
274
uvgrid = interpolation_method (xy , uv , xgrid , ygrid , ** interp_kwargs )
275
275
276
+ dataset ["velocity_x" ] = (["y" , "x" ], uvgrid [0 ])
277
+ dataset ["velocity_y" ] = (["y" , "x" ], uvgrid [1 ])
278
+
276
279
if verbose :
277
280
print ("--- total time: %.2f seconds ---" % (time .time () - t0 ))
278
281
279
- return uvgrid
282
+ return dataset
0 commit comments