Skip to content

Commit b6b305f

Browse files
committed
First working quiver+streamplot.
1 parent 91d69fa commit b6b305f

File tree

1 file changed

+133
-0
lines changed

1 file changed

+133
-0
lines changed

lib/iris/plot.py

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1189,6 +1189,139 @@ def _scatter_args(u, v, data, *args, **kwargs):
11891189
*args, **kwargs)
11901190

11911191

1192+
def _vector_component_args(x_points, y_points, u_data, *args, **kwargs):
1193+
"""
1194+
Callback from _draw_2d_from_points for 'quiver' and 'streamlines'.
1195+
1196+
Returns arguments (x, y, u, v), to be passed to the underlying matplotlib
1197+
call.
1198+
1199+
"u_data" will always be "u_cube.data".
1200+
The matching "v_cube.data" component is stored in kwargs['_v_data'].
1201+
1202+
"""
1203+
v_data = kwargs.pop('_v_data')
1204+
1205+
# Rescale u+v values for plot distortion.
1206+
crs = kwargs.get('transform', None)
1207+
if crs:
1208+
if not isinstance(crs, (ccrs.PlateCarree, ccrs.RotatedPole)):
1209+
msg = ('Can only plot vectors provided in a lat-lon '
1210+
'projection, i.e. "cartopy.crs.PlateCarree" or '
1211+
'"cartopy.crs.RotatedPole". This '
1212+
"cubes coordinate system is {}.")
1213+
raise ValueError(msg.format(crs))
1214+
# Given the above check, the Y points must be latitudes.
1215+
# We therefore **assume** they are in degrees : I'm not sure this
1216+
# is wise, but all the rest of this plot code does that, e.g. in
1217+
# _map_common.
1218+
# TODO: investigate degree units assumptions, here + elsewhere.
1219+
1220+
# Implement a latitude scaling, but preserve the given magnitudes.
1221+
v_data = v_data.copy()
1222+
mags = np.sqrt(u_data * u_data + v_data * v_data)
1223+
v_data *= np.cos(np.deg2rad(y_points))
1224+
scales = mags / np.sqrt(u_data * u_data + v_data * v_data)
1225+
u_data *= scales
1226+
v_data *= scales
1227+
1228+
return ((x_points, y_points, u_data, v_data), kwargs)
1229+
1230+
1231+
def quiver(u_cube, v_cube, *args, **kwargs):
1232+
"""
1233+
Draws an arrow plot from two vector component cubes.
1234+
1235+
Args:
1236+
1237+
* u_cube, v_cube : (:class:`~iris.cube.Cube`)
1238+
u and v vector components. Must have same shape and units.
1239+
If the cubes have geographic coordinates, the values are treated as
1240+
true distance differentials, e.g. windspeeds, and *not* map coordinate
1241+
vectors. The components are aligned with the North and East of the
1242+
cube coordinate system.
1243+
1244+
.. Note:
1245+
1246+
At present, if u_cube and v_cube have geographic coordinates, then they
1247+
must be in a lat-lon coordinate system, though it may be a rotated one.
1248+
To transform wind values between coordinate systems, use
1249+
:func:`iris.analysis.cartography.rotate_vectors`.
1250+
To transform coordinate grid points, you will need to create
1251+
2-dimensional arrays of x and y values. These can be transformed with
1252+
:meth:`cartopy.crs.CRS.transform_points`.
1253+
1254+
Kwargs:
1255+
1256+
* coords: (list of :class:`~iris.coords.Coord` or string)
1257+
Coordinates or coordinate names. Use the given coordinates as the axes
1258+
for the plot. The order of the given coordinates indicates which axis
1259+
to use for each, where the first element is the horizontal
1260+
axis of the plot and the second element is the vertical axis
1261+
of the plot.
1262+
1263+
* axes: the :class:`matplotlib.axes.Axes` to use for drawing.
1264+
Defaults to the current axes if none provided.
1265+
1266+
See :func:`matplotlib.pyplot.quiver` for details of other valid
1267+
keyword arguments.
1268+
1269+
"""
1270+
#
1271+
# TODO: check u + v cubes for compatibility.
1272+
#
1273+
kwargs['_v_data'] = v_cube.data
1274+
return _draw_2d_from_points('quiver', _vector_component_args, u_cube,
1275+
*args, **kwargs)
1276+
1277+
1278+
def streamplot(u_cube, v_cube, *args, **kwargs):
1279+
"""
1280+
Draws a streamline plot from two vector component cubes.
1281+
1282+
Args:
1283+
1284+
* u_cube, v_cube : (:class:`~iris.cube.Cube`)
1285+
u and v vector components. Must have same shape and units.
1286+
If the cubes have geographic coordinates, the values are treated as
1287+
true distance differentials, e.g. windspeeds, and *not* map coordinate
1288+
vectors. The components are aligned with the North and East of the
1289+
cube coordinate system.
1290+
1291+
.. Note:
1292+
1293+
At present, if u_cube and v_cube have geographic coordinates, then they
1294+
must be in a lat-lon coordinate system, though it may be a rotated one.
1295+
To transform wind values between coordinate systems, use
1296+
:func:`iris.analysis.cartography.rotate_vectors`.
1297+
To transform coordinate grid points, you will need to create
1298+
2-dimensional arrays of x and y values. These can be transformed with
1299+
:meth:`cartopy.crs.CRS.transform_points`.
1300+
1301+
Kwargs:
1302+
1303+
* coords: (list of :class:`~iris.coords.Coord` or string)
1304+
Coordinates or coordinate names. Use the given coordinates as the axes
1305+
for the plot. The order of the given coordinates indicates which axis
1306+
to use for each, where the first element is the horizontal
1307+
axis of the plot and the second element is the vertical axis
1308+
of the plot.
1309+
1310+
* axes: the :class:`matplotlib.axes.Axes` to use for drawing.
1311+
Defaults to the current axes if none provided.
1312+
1313+
See :func:`matplotlib.pyplot.quiver` for details of other valid
1314+
keyword arguments.
1315+
1316+
"""
1317+
#
1318+
# TODO: check u + v cubes for compatibility.
1319+
#
1320+
kwargs['_v_data'] = v_cube.data
1321+
return _draw_2d_from_points('streamplot', _vector_component_args, u_cube,
1322+
*args, **kwargs)
1323+
1324+
11921325
def plot(*args, **kwargs):
11931326
"""
11941327
Draws a line plot based on the given cube(s) or coordinate(s).

0 commit comments

Comments
 (0)