@@ -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+
11921325def plot (* args , ** kwargs ):
11931326 """
11941327 Draws a line plot based on the given cube(s) or coordinate(s).
0 commit comments