2222 dense_lucaskanade
2323"""
2424
25+ import time
26+
2527import numpy as np
28+ import xarray as xr
2629from numpy .ma .core import MaskedArray
2730
31+ from pysteps import feature , utils
2832from pysteps .decorators import check_input_frames
29-
30- from pysteps import utils , feature
3133from pysteps .tracking .lucaskanade import track_features
3234from pysteps .utils .cleansing import decluster , detect_outliers
3335from pysteps .utils .images import morph_opening
3436
35- import time
36-
3737
3838@check_input_frames (2 )
3939def dense_lucaskanade (
40- input_images ,
40+ dataset : xr . Dataset ,
4141 lk_kwargs = None ,
4242 fd_method = "shitomasi" ,
4343 fd_kwargs = None ,
@@ -73,18 +73,14 @@ def dense_lucaskanade(
7373
7474 Parameters
7575 ----------
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.
8884
8985 lk_kwargs: dict, optional
9086 Optional dictionary containing keyword arguments for the `Lucas-Kanade`_
@@ -151,14 +147,10 @@ def dense_lucaskanade(
151147
152148 Returns
153149 -------
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.
162154
163155 If **dense=False**, it returns a tuple containing the 2-dimensional
164156 arrays **xy** and **uv**, where x, y define the vector locations,
@@ -179,7 +171,9 @@ def dense_lucaskanade(
179171 Understanding Workshop, pp. 121–130, 1981.
180172 """
181173
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
183177
184178 if verbose :
185179 print ("Computing the motion field with the Lucas-Kanade method." )
@@ -244,7 +238,10 @@ def dense_lucaskanade(
244238 # return zero motion field is no sparse vectors are found
245239 if xy .shape [0 ] == 0 :
246240 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
248245 else :
249246 return xy , uv
250247
@@ -266,14 +263,20 @@ def dense_lucaskanade(
266263
267264 # return zero motion field if no sparse vectors are left for interpolation
268265 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
270270
271271 # interpolation
272272 xgrid = np .arange (domain_size [1 ])
273273 ygrid = np .arange (domain_size [0 ])
274274 uvgrid = interpolation_method (xy , uv , xgrid , ygrid , ** interp_kwargs )
275275
276+ dataset ["velocity_x" ] = (["y" , "x" ], uvgrid [0 ])
277+ dataset ["velocity_y" ] = (["y" , "x" ], uvgrid [1 ])
278+
276279 if verbose :
277280 print ("--- total time: %.2f seconds ---" % (time .time () - t0 ))
278281
279- return uvgrid
282+ return dataset
0 commit comments