Skip to content

Commit 602bdd8

Browse files
authored
Fix warnings shown during tests (#152)
* pysteps.motion.vet: Fix bug in `vet` keywords handling. Previously, the argument passed to the minimizer was ignored. * pysteps.io.importers: Add a function to safely get the rain/no rain threshold that handles NaN correctly. * Fix collections imports. Remove DeprecationWarning for using the ABCs from 'collections' instead of from 'collections.abc'. * pysteps.timeseries.autoregression: Make some docstrings raw literals, avoiding the interpretation of math equations as invalid escape sequences.
1 parent 69e4cec commit 602bdd8

File tree

8 files changed

+65
-58
lines changed

8 files changed

+65
-58
lines changed

pysteps/io/importers.py

Lines changed: 35 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,31 @@ def _get_grib_projection(grib_msg):
201201
return projparams
202202

203203

204+
def _get_threshold_value(precip):
205+
"""
206+
Get the the rain/no rain threshold with the same unit, transformation and
207+
accutime of the data.
208+
If all the values are NaNs, the returned value is `np.nan`.
209+
Otherwise, np.min(precip[precip > precip.min()]) is returned.
210+
211+
Returns
212+
-------
213+
214+
threshold : float
215+
"""
216+
valid_mask = np.isfinite(precip)
217+
if valid_mask.any():
218+
_precip = precip[valid_mask]
219+
min_precip = _precip.min()
220+
above_min_mask = _precip > min_precip
221+
if above_min_mask.any():
222+
return np.min(_precip[above_min_mask])
223+
else:
224+
return min_precip
225+
else:
226+
return np.nan
227+
228+
204229
@postprocess_import(dtype='float32')
205230
def import_mrms(filename, extent=None, window_size=4, **kwargs):
206231
"""
@@ -371,6 +396,7 @@ def import_mrms(filename, extent=None, window_size=4, **kwargs):
371396
zerovalue=0,
372397
projection=proj_params,
373398
yorigin="upper",
399+
threshold=_get_threshold_value(precip),
374400
x1=x1,
375401
x2=x2,
376402
y1=y1,
@@ -414,10 +440,7 @@ def import_bom_rf3(filename, **kwargs):
414440

415441
metadata["transform"] = None
416442
metadata["zerovalue"] = np.nanmin(precip)
417-
if np.any(np.isfinite(precip)):
418-
metadata["threshold"] = np.nanmin(precip[precip > np.nanmin(precip)])
419-
else:
420-
metadata["threshold"] = np.nan
443+
metadata["threshold"] = _get_threshold_value(precip)
421444

422445
return precip, None, metadata
423446

@@ -584,9 +607,8 @@ def import_fmi_geotiff(filename, **kwargs):
584607
metadata["unit"] = rb.GetUnitType()
585608
metadata["transform"] = None
586609
metadata["accutime"] = 5.0
587-
precip_min = np.nanmin(precip)
588-
metadata["threshold"] = np.nanmin(precip[precip > precip_min])
589-
metadata["zerovalue"] = precip_min
610+
metadata["threshold"] = _get_threshold_value(precip)
611+
metadata["zerovalue"] = np.nanmin(precip)
590612

591613
return precip, None, metadata
592614

@@ -640,10 +662,7 @@ def import_fmi_pgm(filename, gzipped=False, **kwargs):
640662
metadata["unit"] = "dBZ"
641663
metadata["transform"] = "dB"
642664
metadata["zerovalue"] = np.nanmin(precip)
643-
if np.any(np.isfinite(precip)):
644-
metadata["threshold"] = np.nanmin(precip[precip > np.nanmin(precip)])
645-
else:
646-
metadata["threshold"] = np.nan
665+
metadata["threshold"] = _get_threshold_value(precip)
647666
metadata["zr_a"] = 223.0
648667
metadata["zr_b"] = 1.53
649668

@@ -861,7 +880,7 @@ def import_knmi_hdf5(filename, qty="ACRR", accutime=5.0, pixelsize=1.0, **kwargs
861880
metadata["unit"] = unit
862881
metadata["transform"] = transform
863882
metadata["zerovalue"] = 0.0
864-
metadata["threshold"] = np.nanmin(precip[precip > np.nanmin(precip)])
883+
metadata["threshold"] = _get_threshold_value(precip)
865884
metadata["zr_a"] = 200.0
866885
metadata["zr_b"] = 1.6
867886

@@ -985,10 +1004,7 @@ def import_mch_gif(filename, product, unit, accutime, **kwargs):
9851004
metadata["unit"] = unit
9861005
metadata["transform"] = None
9871006
metadata["zerovalue"] = np.nanmin(precip)
988-
if np.any(precip > np.nanmin(precip)):
989-
metadata["threshold"] = np.nanmin(precip[precip > np.nanmin(precip)])
990-
else:
991-
metadata["threshold"] = np.nan
1007+
metadata["threshold"] = _get_threshold_value(precip)
9921008
metadata["institution"] = "MeteoSwiss"
9931009
metadata["product"] = product
9941010
metadata["zr_a"] = 316.0
@@ -1201,10 +1217,7 @@ def import_mch_metranet(filename, product, unit, accutime):
12011217
metadata["unit"] = unit
12021218
metadata["transform"] = None
12031219
metadata["zerovalue"] = np.nanmin(precip)
1204-
if np.isnan(metadata["zerovalue"]):
1205-
metadata["threshold"] = np.nan
1206-
else:
1207-
metadata["threshold"] = np.nanmin(precip[precip > metadata["zerovalue"]])
1220+
metadata["threshold"] = _get_threshold_value(precip)
12081221
metadata["zr_a"] = 316.0
12091222
metadata["zr_b"] = 1.5
12101223

@@ -1389,11 +1402,6 @@ def import_opera_hdf5(filename, qty="RATE", **kwargs):
13891402
unit = "mm/h"
13901403
transform = None
13911404

1392-
if np.any(np.isfinite(precip)):
1393-
thr = np.nanmin(precip[precip > np.nanmin(precip)])
1394-
else:
1395-
thr = np.nan
1396-
13971405
metadata = {
13981406
"projection": proj4str,
13991407
"ll_lon": ll_lon,
@@ -1412,7 +1420,7 @@ def import_opera_hdf5(filename, qty="RATE", **kwargs):
14121420
"unit": unit,
14131421
"transform": transform,
14141422
"zerovalue": np.nanmin(precip),
1415-
"threshold": thr,
1423+
"threshold": _get_threshold_value(precip),
14161424
}
14171425

14181426
f.close()
@@ -1493,10 +1501,7 @@ def import_saf_crri(filename, extent=None, **kwargs):
14931501

14941502
metadata["transform"] = None
14951503
metadata["zerovalue"] = np.nanmin(precip)
1496-
if np.any(np.isfinite(precip)):
1497-
metadata["threshold"] = np.nanmin(precip[precip > np.nanmin(precip)])
1498-
else:
1499-
metadata["threshold"] = np.nan
1504+
metadata["threshold"] = _get_threshold_value(precip)
15001505

15011506
return precip, quality, metadata
15021507

pysteps/motion/vet.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -481,6 +481,7 @@ def debug_print(*args, **kwargs):
481481
options.setdefault('gtol', 0.1)
482482
options.setdefault('maxiter', 100)
483483
options.setdefault('disp', False)
484+
optimization_method = options.pop("method", "CG")
484485

485486
# Set to None to suppress pylint warning.
486487
pad_i = None
@@ -613,7 +614,7 @@ def debug_print(*args, **kwargs):
613614
(sectors_in_i, sectors_in_j),
614615
_mask,
615616
smooth_gain),
616-
method='CG',
617+
method=optimization_method,
617618
options=options)
618619

619620
first_guess = result.x.reshape(*first_guess.shape)

pysteps/tests/test_motion.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ def test_optflow_method_convergence(input_precip, optflow_method_name,
209209
# To increase the stability of the tests to we increase this value to
210210
# maxiter=150.
211211
retrieved_motion = oflow_method(precip_obs, verbose=False,
212-
options=dict(maxiter=150, method='BFGS'))
212+
options=dict(maxiter=150))
213213
elif optflow_method_name == 'proesmans':
214214
retrieved_motion = oflow_method(precip_obs)
215215
else:

pysteps/timeseries/autoregression.py

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ def ar_acf(gamma, n=None):
116116

117117
def estimate_ar_params_ols(x, p, d=0, check_stationarity=True,
118118
include_constant_term=False, h=0, lam=0.0):
119-
"""Estimate the parameters of an autoregressive AR(p) model
119+
r"""Estimate the parameters of an autoregressive AR(p) model
120120
121121
:math:`x_{k+1}=c+\phi_1 x_k+\phi_2 x_{k-1}+\dots+\phi_p x_{k-p}+\phi_{p+1}\epsilon`
122122
@@ -222,7 +222,7 @@ def estimate_ar_params_ols(x, p, d=0, check_stationarity=True,
222222
def estimate_ar_params_ols_localized(x, p, window_radius, d=0,
223223
include_constant_term=False, h=0, lam=0.0,
224224
window="gaussian"):
225-
"""Estimate the parameters of a localized AR(p) model
225+
r"""Estimate the parameters of a localized AR(p) model
226226
227227
:math:`x_{k+1,i}=c_i+\phi_{1,i}x_{k,i}+\phi_{2,i}x_{k-1,i}+\dots+\phi_{p,i}x_{k-p,i}+\phi_{p+1,i}\epsilon`
228228
@@ -365,7 +365,7 @@ def estimate_ar_params_ols_localized(x, p, window_radius, d=0,
365365

366366

367367
def estimate_ar_params_yw(gamma, d=0, check_stationarity=True):
368-
"""Estimate the parameters of an AR(p) model
368+
r"""Estimate the parameters of an AR(p) model
369369
370370
:math:`x_{k+1}=\phi_1 x_k+\phi_2 x_{k-1}+\dots+\phi_p x_{k-p}+\phi_{p+1}\epsilon`
371371
@@ -441,7 +441,7 @@ def estimate_ar_params_yw(gamma, d=0, check_stationarity=True):
441441

442442

443443
def estimate_ar_params_yw_localized(gamma, d=0):
444-
"""Estimate the parameters of a localized AR(p) model
444+
r"""Estimate the parameters of a localized AR(p) model
445445
446446
:math:`x_{k+1,i}=\phi_{1,i}x_{k,i}+\phi_{2,i}x_{k-1,i}+\dots+\phi_{p,i}x_{k-p,i}+\phi_{p+1}\epsilon`
447447
@@ -518,7 +518,7 @@ def estimate_ar_params_yw_localized(gamma, d=0):
518518

519519
def estimate_var_params_ols(x, p, d=0, check_stationarity=True,
520520
include_constant_term=False, h=0, lam=0.0):
521-
"""Estimate the parameters of a vector autoregressive VAR(p) model
521+
r"""Estimate the parameters of a vector autoregressive VAR(p) model
522522
523523
:math:`\mathbf{x}_{k+1}=\mathbf{c}+\mathbf{\Phi}_1\mathbf{x}_k+
524524
\mathbf{\Phi}_2\mathbf{x}_{k-1}+\dots+\mathbf{\Phi}_p\mathbf{x}_{k-p}+
@@ -634,7 +634,7 @@ def estimate_var_params_ols(x, p, d=0, check_stationarity=True,
634634
def estimate_var_params_ols_localized(x, p, window_radius, d=0,
635635
include_constant_term=False,
636636
h=0, lam=0.0, window="gaussian"):
637-
"""Estimate the parameters of a vector autoregressive VAR(p) model
637+
r"""Estimate the parameters of a vector autoregressive VAR(p) model
638638
639639
:math:`\mathbf{x}_{k+1,i}=\mathbf{c}_i+\mathbf{\Phi}_{1,i}\mathbf{x}_{k,i}+
640640
\mathbf{\Phi}_{2,i}\mathbf{x}_{k-1,i}+\dots+\mathbf{\Phi}_{p,i}
@@ -787,7 +787,7 @@ def estimate_var_params_ols_localized(x, p, window_radius, d=0,
787787

788788

789789
def estimate_var_params_yw(gamma, d=0, check_stationarity=True):
790-
"""Estimate the parameters of a VAR(p) model
790+
r"""Estimate the parameters of a VAR(p) model
791791
792792
:math:`\mathbf{x}_{k+1}=\mathbf{\Phi}_1\mathbf{x}_k+
793793
\mathbf{\Phi}_2\mathbf{x}_{k-1}+\dots+\mathbf{\Phi}_p\mathbf{x}_{k-p}+
@@ -870,7 +870,7 @@ def estimate_var_params_yw(gamma, d=0, check_stationarity=True):
870870

871871

872872
def estimate_var_params_yw_localized(gamma, d=0):
873-
"""Estimate the parameters of a vector autoregressive VAR(p) model
873+
r"""Estimate the parameters of a vector autoregressive VAR(p) model
874874
875875
:math:`\mathbf{x}_{k+1,i}=\mathbf{\Phi}_{1,i}\mathbf{x}_{k,i}+
876876
\mathbf{\Phi}_{2,i}\mathbf{x}_{k-1,i}+\dots+\mathbf{\Phi}_{p,i}
@@ -949,7 +949,7 @@ def estimate_var_params_yw_localized(gamma, d=0):
949949

950950

951951
def iterate_ar_model(x, phi, eps=None):
952-
"""Apply an AR(p) model
952+
r"""Apply an AR(p) model
953953
954954
:math:`x_{k+1}=\phi_1 x_k+\phi_2 x_{k-1}+\dots+\phi_p x_{k-p}+\phi_{p+1}\epsilon`
955955
@@ -1000,7 +1000,7 @@ def iterate_ar_model(x, phi, eps=None):
10001000

10011001

10021002
def iterate_var_model(x, phi, eps=None):
1003-
"""Apply a VAR(p) model
1003+
r"""Apply a VAR(p) model
10041004
10051005
:math:`\mathbf{x}_{k+1}=\mathbf{\Phi}_1\mathbf{x}_k+\mathbf{\Phi}_2
10061006
\mathbf{x}_{k-1}+\dots+\mathbf{\Phi}_p\mathbf{x}_{k-p}+
@@ -1057,7 +1057,7 @@ def iterate_var_model(x, phi, eps=None):
10571057

10581058

10591059
def test_ar_stationarity(phi):
1060-
"""Test stationarity of an AR(p) process. That is, test that the roots of
1060+
r"""Test stationarity of an AR(p) process. That is, test that the roots of
10611061
the equation :math:`x^p-\phi_1*x^{p-1}-\dots-\phi_p` lie inside the unit
10621062
circle.
10631063
@@ -1079,7 +1079,7 @@ def test_ar_stationarity(phi):
10791079

10801080

10811081
def test_var_stationarity(phi):
1082-
"""Test stationarity of an AR(p) process. That is, test that the moduli of
1082+
r"""Test stationarity of an AR(p) process. That is, test that the moduli of
10831083
the eigenvalues of the companion matrix lie inside the unit circle.
10841084
10851085
Parameters

pysteps/utils/transformation.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ def NQ_transform(R, metadata=None, inverse=False, **kwargs):
278278
279279
References
280280
----------
281-
Bogner, K., Pappenberger, field., and Cloke, H. L.: Technical Note: The normal
281+
Bogner, K., Pappenberger, F., and Cloke, H. L.: Technical Note: The normal
282282
quantile transformation and its application in a flood forecasting system,
283283
Hydrol. Earth Syst. Sci., 16, 1085-1094,
284284
https://doi.org/10.5194/hess-16-1085-2012, 2012.

pysteps/verification/detcatscores.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ def det_cat_fct_init(thr, axis=None):
130130
# catch case of axis passed as integer
131131
def get_iterable(x):
132132
if x is None or (
133-
isinstance(x, collections.Iterable) and not isinstance(x, int)
133+
isinstance(x, collections.abc.Iterable) and not isinstance(x, int)
134134
):
135135
return x
136136
else:
@@ -332,7 +332,7 @@ def det_cat_fct_compute(contab, scores=""):
332332

333333
# catch case of single score passed as string
334334
def get_iterable(x):
335-
if isinstance(x, collections.Iterable) and not isinstance(x, str):
335+
if isinstance(x, collections.abc.Iterable) and not isinstance(x, str):
336336
return x
337337
else:
338338
return (x,)

pysteps/verification/detcontscores.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,7 @@ def det_cont_fct(pred, obs, scores="", axis=None, conditioning=None, thr=0.0):
139139

140140
# catch case of single score passed as string
141141
def get_iterable(x):
142-
if isinstance(x, collections.Iterable) and not isinstance(x, str):
142+
if isinstance(x, collections.abc.Iterable) and not isinstance(x, str):
143143
return x
144144
else:
145145
return (x,)
@@ -257,7 +257,7 @@ def det_cont_fct_init(axis=None, conditioning=None, thr=0.0):
257257
# catch case of axis passed as integer
258258
def get_iterable(x):
259259
if x is None or (
260-
isinstance(x, collections.Iterable) and not isinstance(x, int)
260+
isinstance(x, collections.abc.Iterable) and not isinstance(x, int)
261261
):
262262
return x
263263
else:
@@ -299,7 +299,7 @@ def det_cont_fct_accum(err, pred, obs):
299299
References
300300
----------
301301
302-
Chan, Tony field.; Golub, Gene H.; LeVeque, Randall J. (1979), "Updating
302+
Chan, Tony F.; Golub, Gene H.; LeVeque, Randall J. (1979), "Updating
303303
Formulae and a Pairwise Algorithm for Computing Sample Variances.",
304304
Technical Report STAN-CS-79-773, Department of Computer Science,
305305
Stanford University.
@@ -561,7 +561,7 @@ def det_cont_fct_compute(err, scores=""):
561561

562562
# catch case of single score passed as string
563563
def get_iterable(x):
564-
if isinstance(x, collections.Iterable) and not isinstance(x, str):
564+
if isinstance(x, collections.abc.Iterable) and not isinstance(x, str):
565565
return x
566566
else:
567567
return (x,)
@@ -694,7 +694,7 @@ def _scatter(pred, obs, axis=None):
694694
# catch case of axis passed as integer
695695
def get_iterable(x):
696696
if x is None or (
697-
isinstance(x, collections.Iterable) and not isinstance(x, int)
697+
isinstance(x, collections.abc.Iterable) and not isinstance(x, int)
698698
):
699699
return x
700700
else:
@@ -748,7 +748,7 @@ def _spearmanr(pred, obs, axis=None):
748748
# catch case of axis passed as integer
749749
def get_iterable(x):
750750
if x is None or (
751-
isinstance(x, collections.Iterable) and not isinstance(x, int)
751+
isinstance(x, collections.abc.Iterable) and not isinstance(x, int)
752752
):
753753
return x
754754
else:

pysteps/verification/spatialscores.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ def intensity_scale_init(name, thrs, scales=None, wavelet="Haar"):
151151

152152
# catch scalars when passed as arguments
153153
def get_iterable(x):
154-
if isinstance(x, collections.Iterable):
154+
if isinstance(x, collections.abc.Iterable):
155155
return np.copy(x)
156156
else:
157157
return np.copy((x,))
@@ -453,11 +453,12 @@ def binary_mse_accum(bmse, X_f, X_o):
453453
mse = np.mean(E_decomp[j] ** 2)
454454
if np.isfinite(mse):
455455
bmse["mse"][j] = (bmse["mse"][j] * bmse["n"] + mse) / (
456-
bmse["n"] + 1
456+
bmse["n"] + 1
457457
)
458458

459459
bmse["n"] += 1
460460

461+
461462
def binary_mse_merge(bmse_1, bmse_2):
462463
"""Merge two BMSE objects.
463464
@@ -503,12 +504,12 @@ def binary_mse_merge(bmse_1, bmse_2):
503504
# merge the BMSE objects
504505
bmse = bmse_1.copy()
505506
bmse["eps"] = (bmse["eps"] * bmse["n"] + bmse_2["eps"] * bmse_2["n"]) / (
506-
bmse["n"] + bmse_2["n"]
507+
bmse["n"] + bmse_2["n"]
507508
)
508509
for j, scale in enumerate(bmse["scales"]):
509510
bmse["mse"][j] = (
510-
bmse["mse"][j] * bmse["n"] + bmse_2["mse"][j] * bmse_2["n"]
511-
) / (bmse["n"] + bmse_2["n"])
511+
bmse["mse"][j] * bmse["n"] + bmse_2["mse"][j] * bmse_2["n"]
512+
) / (bmse["n"] + bmse_2["n"])
512513
bmse["n"] += bmse_2["n"]
513514

514515
return bmse

0 commit comments

Comments
 (0)