Skip to content
73 changes: 0 additions & 73 deletions pysteps/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@
.. autosummary::
:toctree: ../generated/

postprocess_import
check_input_frames
prepare_interpolator
memoize
Expand All @@ -22,8 +21,6 @@

import numpy as np

from pysteps.xarray_helpers import convert_input_to_xarray_dataset


def _add_extra_kwrds_to_docstrings(target_func, extra_kwargs_doc_text):
"""
Expand All @@ -44,76 +41,6 @@ def _add_extra_kwrds_to_docstrings(target_func, extra_kwargs_doc_text):
return target_func


def postprocess_import(fillna=np.nan, dtype="double"):
"""
Postprocess the imported precipitation data.
Operations:
- Allow type casting (dtype keyword)
- Set invalid or missing data to predefined value (fillna keyword)
This decorator replaces the text "{extra_kwargs}" in the function's
docstring with the documentation of the keywords used in the postprocessing.
The additional docstrings are added as "Other Parameters" in the importer function.

Parameters
----------
dtype: str
Default data type for precipitation. Double precision by default.
fillna: float or np.nan
Default value used to represent the missing data ("No Coverage").
By default, np.nan is used.
If the importer returns a MaskedArray, all the masked values are set to the
fillna value. If a numpy array is returned, all the invalid values (nan and inf)
are set to the fillna value.

"""

def _postprocess_import(importer):
@wraps(importer)
def _import_with_postprocessing(*args, **kwargs):
precip, quality, metadata = importer(*args, **kwargs)

_dtype = kwargs.get("dtype", dtype)

accepted_precisions = ["float32", "float64", "single", "double"]
if _dtype not in accepted_precisions:
raise ValueError(
"The selected precision does not correspond to a valid value."
"The accepted values are: " + str(accepted_precisions)
)

if isinstance(precip, np.ma.MaskedArray):
invalid_mask = np.ma.getmaskarray(precip)
precip.data[invalid_mask] = fillna
else:
# If plain numpy arrays are used, the importers should indicate
# the invalid values with np.nan.
_fillna = kwargs.get("fillna", fillna)
if _fillna is not np.nan:
mask = ~np.isfinite(precip)
precip[mask] = _fillna

return convert_input_to_xarray_dataset(
precip.astype(_dtype), quality, metadata
)

extra_kwargs_doc = """
Other Parameters
----------------
dtype: str
Data-type to which the array is cast.
Valid values: "float32", "float64", "single", and "double".
fillna: float or np.nan
Value used to represent the missing data ("No Coverage").
By default, np.nan is used.
"""

_add_extra_kwrds_to_docstrings(_import_with_postprocessing, extra_kwargs_doc)

return _import_with_postprocessing

return _postprocess_import


def check_input_frames(
minimum_input_frames=2, maximum_input_frames=np.inf, just_ndim=False
):
Expand Down
26 changes: 8 additions & 18 deletions pysteps/extrapolation/eulerian_persistence.py
Original file line number Diff line number Diff line change
@@ -1,47 +1,40 @@
import numpy as np
import xarray as xr
from pysteps.xarray_helpers import convert_output_to_xarray_dataset


def extrapolate(precip_dataset: xr.Dataset, timesteps, outval=np.nan, **kwargs):
def extrapolate(precip, velocity, timesteps, outval=np.nan, **kwargs):
"""
A dummy extrapolation method to apply Eulerian persistence to a
two-dimensional precipitation field. The method returns the a sequence
of the same initial field with no extrapolation applied (i.e. Eulerian
persistence).

Parameters
----------
precip_dataset : xarray.Dataset
xarray dataset containing the input precipitation field. All
precip : array-like
Array of shape (m,n) containing the input precipitation field. All
values are required to be finite.
velocity : array-like
Not used by the method.
timesteps : int or list of floats
Number of time steps or a list of time steps.
outval : float, optional
Not used by the method.

Other Parameters
----------------
return_displacement : bool
If True, return the total advection velocity (displacement) between the
initial input field and the advected one integrated along
the trajectory. Default : False

Returns
-------
out : array or tuple
If return_displacement=False, return a sequence of the same initial field
of shape (num_timesteps,m,n). Otherwise, return a tuple containing the
replicated fields and a (2,m,n) array of zeros.

References
----------
:cite:`GZ2002`

"""
del outval # Unused by _eulerian_persistence
precip_var = precip_dataset.attrs["precip_var"]
precip = precip_dataset[precip_var].values[-1]
del velocity, outval # Unused by _eulerian_persistence

if isinstance(timesteps, int):
num_timesteps = timesteps
Expand All @@ -51,11 +44,8 @@ def extrapolate(precip_dataset: xr.Dataset, timesteps, outval=np.nan, **kwargs):
return_displacement = kwargs.get("return_displacement", False)

extrapolated_precip = np.repeat(precip[np.newaxis, :, :], num_timesteps, axis=0)
extrapolated_precip_dataset = convert_output_to_xarray_dataset(
precip_dataset, timesteps, extrapolated_precip
)

if not return_displacement:
return extrapolated_precip_dataset
return extrapolated_precip
else:
return extrapolated_precip_dataset, np.zeros((2,) + extrapolated_precip.shape)
return extrapolated_precip, np.zeros((2,) + extrapolated_precip.shape)
Loading