Skip to content

Commit dce5054

Browse files
Fix plt motionfields (#166)
* Fix interface to plot_geography * Fix docstrings * Fix plotting functions for motion fields * Remove pixelsize as a required argument * Add missing 'lw' argument * Add FutureWarning and internally rename 'map' to 'plot_map' * Rename map argument - Since map was an argument and not a keyword, it can be renamed safely. - The keywords arguments were explicitly declared in the plot_geography calls. * Remove unused shape argument from plot_geography * Speed up tests Co-authored-by: Andres Perez Hortal <andresperezcba@gmail.com>
1 parent f342966 commit dce5054

File tree

5 files changed

+272
-180
lines changed

5 files changed

+272
-180
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# -*- coding: utf-8 -*-
2+
3+
import matplotlib.pyplot as plt
4+
import numpy as np
5+
import pytest
6+
7+
from pysteps import motion
8+
from pysteps.visualization import plot_precip_field, quiver, streamplot
9+
from pysteps.tests.helpers import get_precipitation_fields
10+
11+
12+
arg_names_quiver = (
13+
"source",
14+
"map",
15+
"drawlonlatlines",
16+
"lw",
17+
"axis",
18+
"step",
19+
"quiver_kwargs",
20+
"upscale",
21+
)
22+
23+
arg_values_quiver = [
24+
(None, None, False, 0.5, "off", 10, None, None),
25+
("bom", None, False, 0.5, "on", 10, None, 4000),
26+
("bom", "cartopy", True, 0.5, "on", 10, None, 4000),
27+
("mch", "cartopy", False, 0.5, "on", 20, None, 2000),
28+
("bom", "basemap", False, 0.5, "off", 10, None, 4000),
29+
]
30+
31+
32+
@pytest.mark.parametrize(arg_names_quiver, arg_values_quiver)
33+
def test_visualization_motionfields_quiver(
34+
source, map, drawlonlatlines, lw, axis, step, quiver_kwargs, upscale,
35+
):
36+
37+
if map == "cartopy":
38+
pytest.importorskip("cartopy")
39+
elif map == "basemap":
40+
pytest.importorskip("basemap")
41+
42+
if source is not None:
43+
fields, geodata = get_precipitation_fields(0, 2, False, True, upscale, source)
44+
ax = plot_precip_field(fields[-1], map=map, geodata=geodata,)
45+
oflow_method = motion.get_method("LK")
46+
UV = oflow_method(fields)
47+
48+
else:
49+
shape = (100, 100)
50+
geodata = None
51+
ax = None
52+
u = np.ones(shape[1]) * shape[0]
53+
v = np.arange(0, shape[0])
54+
U, V = np.meshgrid(u, v)
55+
UV = np.concatenate([U[None, :], V[None, :]])
56+
57+
__ = quiver(UV, ax, map, geodata, drawlonlatlines, lw, axis, step, quiver_kwargs)
58+
59+
60+
arg_names_streamplot = (
61+
"source",
62+
"map",
63+
"drawlonlatlines",
64+
"lw",
65+
"axis",
66+
"streamplot_kwargs",
67+
"upscale",
68+
)
69+
70+
arg_values_streamplot = [
71+
(None, None, False, 0.5, "off", None, None),
72+
("bom", None, False, 0.5, "on", None, 4000),
73+
("bom", "cartopy", True, 0.5, "on", {"density": 0.1}, 4000),
74+
]
75+
76+
77+
@pytest.mark.parametrize(arg_names_streamplot, arg_values_streamplot)
78+
def test_visualization_motionfields_streamplot(
79+
source, map, drawlonlatlines, lw, axis, streamplot_kwargs, upscale,
80+
):
81+
82+
if map == "cartopy":
83+
pytest.importorskip("cartopy")
84+
elif map == "basemap":
85+
pytest.importorskip("basemap")
86+
87+
if source is not None:
88+
fields, geodata = get_precipitation_fields(0, 2, False, True, upscale, source)
89+
ax = plot_precip_field(fields[-1], map=map, geodata=geodata,)
90+
oflow_method = motion.get_method("LK")
91+
UV = oflow_method(fields)
92+
93+
else:
94+
shape = (100, 100)
95+
geodata = None
96+
ax = None
97+
u = np.ones(shape[1]) * shape[0]
98+
v = np.arange(0, shape[0])
99+
U, V = np.meshgrid(u, v)
100+
UV = np.concatenate([U[None, :], V[None, :]])
101+
102+
__ = streamplot(UV, ax, map, geodata, drawlonlatlines, lw, axis, streamplot_kwargs)
103+
104+
105+
if __name__ == "__main__":
106+
107+
for i, args in enumerate(arg_values_quiver):
108+
test_visualization_motionfields_quiver(*args)
109+
plt.show()
110+
111+
for i, args in enumerate(arg_values_streamplot):
112+
test_visualization_motionfields_streamplot(*args)
113+
plt.show()

pysteps/visualization/animations.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,14 @@ def animate(
125125
ax : fig axes
126126
Figure axes. Needed if one wants to add e.g. text inside the plot.
127127
"""
128+
if map is not None:
129+
FutureWarning(
130+
"'map' argument will be renamed to 'plot_map' in 1.4.0. Use 'plot_map' to silence this warning."
131+
)
132+
plot_map = map
133+
else:
134+
plot_map = kwargs.pop("plot_map", None)
135+
128136
if timestamps is not None:
129137
startdate_str = timestamps[-1].strftime("%Y%m%d%H%M")
130138
else:
@@ -172,7 +180,7 @@ def animate(
172180
ax = st.plt.plot_precip_field(
173181
P_obs,
174182
type="prob",
175-
map=map,
183+
plot_map=plot_map,
176184
geodata=geodata,
177185
units=units,
178186
probthr=prob_thr,
@@ -183,7 +191,7 @@ def animate(
183191
title += "Observed Rainfall"
184192
ax = st.plt.plot_precip_field(
185193
R_obs[i, :, :],
186-
map=map,
194+
plot_map=plot_map,
187195
geodata=geodata,
188196
units=units,
189197
colorscale=colorscale,
@@ -234,7 +242,7 @@ def animate(
234242
ax = st.plt.plot_precip_field(
235243
P,
236244
type="prob",
237-
map=map,
245+
plot_map=plot_map,
238246
geodata=geodata,
239247
units=units,
240248
probthr=prob_thr,
@@ -248,7 +256,7 @@ def animate(
248256
)
249257
ax = st.plt.plot_precip_field(
250258
EM,
251-
map=map,
259+
plot_map=plot_map,
252260
geodata=geodata,
253261
units=units,
254262
title=title,
@@ -260,7 +268,7 @@ def animate(
260268
title += "Forecast Rainfall"
261269
ax = st.plt.plot_precip_field(
262270
R_fct[n, i - n_obs, :, :],
263-
map=map,
271+
plot_map=plot_map,
264272
geodata=geodata,
265273
units=units,
266274
title=title,

pysteps/visualization/basemaps.py

Lines changed: 11 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,7 @@
4040
from . import utils
4141

4242

43-
def plot_geography(
44-
map, proj4str, extent, shape=None, lw=0.5, drawlonlatlines=False, **kwargs
45-
):
43+
def plot_geography(plot_map, proj4str, extent, lw=0.5, drawlonlatlines=False, **kwargs):
4644
"""
4745
Plot geographical map using either cartopy_ or basemap_ in a chosen projection.
4846
@@ -54,15 +52,12 @@ def plot_geography(
5452
5553
Parameters
5654
----------
57-
map : {'cartopy', 'basemap'}
55+
plot_map : {'cartopy', 'basemap'}
5856
The type of basemap.
5957
proj4str : str
6058
The PROJ.4-compatible projection string.
6159
extent: scalars (left, right, bottom, top)
6260
The bounding box in proj4str coordinates.
63-
shape: scalars (n_rows, n_cols)
64-
The dimensions of the image.
65-
Only used if needing a fallback projection.
6661
lw: float, optional
6762
Linewidth of the map (administrative boundaries and coastlines).
6863
drawlonlatlines : bool, optional
@@ -94,34 +89,30 @@ def plot_geography(
9489
Whether the projection allows plotting a regular grid.
9590
Returns False in case a fall-back projection is used.
9691
"""
97-
if map is not None and map not in ["basemap", "cartopy"]:
92+
93+
if plot_map not in ["basemap", "cartopy"]:
9894
raise ValueError(
99-
"unknown map method %s: must be" + " 'basemap' or 'cartopy'" % map
95+
"unknown map method %s: must be" + " 'basemap' or 'cartopy'" % plot_map
10096
)
101-
if map == "basemap" and not basemap_imported:
97+
if plot_map == "basemap" and not basemap_imported:
10298
raise MissingOptionalDependency(
10399
"map='basemap' option passed to plot_geography function "
104100
"but the basemap package is not installed"
105101
)
106-
if map == "cartopy" and not cartopy_imported:
102+
if plot_map == "cartopy" and not cartopy_imported:
107103
raise MissingOptionalDependency(
108104
"map='cartopy' option passed to plot_geography function "
109105
"but the cartopy package is not installed"
110106
)
111-
if map is not None and not pyproj_imported:
107+
if plot_map is not None and not pyproj_imported:
112108
raise MissingOptionalDependency(
113109
"map!=None option passed to plot_geography function "
114110
"but the pyproj package is not installed"
115111
)
116112

117-
if map == "basemap":
113+
if plot_map == "basemap":
118114
basemap_resolution = kwargs.get("resolution", "l")
119115
basemap_scale_args = kwargs.get("scale_args", None)
120-
if map == "cartopy":
121-
cartopy_scale = kwargs.get("scale", "50m")
122-
cartopy_subplot = kwargs.get("subplot", (1, 1, 1))
123-
124-
if map == "basemap":
125116
pr = pyproj.Proj(proj4str)
126117
x1, x2, y1, y2 = extent[0], extent[1], extent[2], extent[3]
127118
ll_lon, ll_lat = pr(x1, y1, inverse=True)
@@ -139,6 +130,8 @@ def plot_geography(
139130
if basemap_scale_args is not None:
140131
ax.drawmapscale(*basemap_scale_args, fontsize=6, yoffset=10000)
141132
else:
133+
cartopy_scale = kwargs.get("scale", "50m")
134+
cartopy_subplot = kwargs.get("subplot", (1, 1, 1))
142135
crs = utils.proj4_to_cartopy(proj4str)
143136

144137
ax = plot_map_cartopy(

0 commit comments

Comments
 (0)