- Iris v2.1
+ Iris v2.2
A powerful, format-agnostic, community-driven Python library for analysing and
diff --git a/docs/iris/src/whatsnew/2.2.rst b/docs/iris/src/whatsnew/2.2.rst
index 4165ebf43d..97eba3dee6 100644
--- a/docs/iris/src/whatsnew/2.2.rst
+++ b/docs/iris/src/whatsnew/2.2.rst
@@ -6,7 +6,7 @@ What's New in Iris 2.2.0
This document explains the new/changed features of Iris in the alpha release
- of version 2.2.0
+of version 2.2.0
(:doc:`View all changes `).
From 297becf2ddb6b74128f700cffd65876cdeac002b Mon Sep 17 00:00:00 2001
From: Corinne Bosley
Date: Tue, 31 Jul 2018 14:22:55 +0100
Subject: [PATCH 18/62] re-added bounds definition for contiguity check,
removed unnecessary test
---
lib/iris/plot.py | 2 +
lib/iris/tests/unit/plot/test_2d_coords.py | 72 +++++++++++-----------
2 files changed, 38 insertions(+), 36 deletions(-)
diff --git a/lib/iris/plot.py b/lib/iris/plot.py
index ac8da822cc..8f11c8d116 100644
--- a/lib/iris/plot.py
+++ b/lib/iris/plot.py
@@ -290,6 +290,8 @@ def _check_contiguity_and_bounds(coord, data, abs_tol=1e-4, transpose=False):
if transpose:
data = data.T
+ bounds = coord.bounds
+
both_dirs_contiguous, diffs_along_x, diffs_along_y = \
iris.coords._discontiguity_in_2d_bounds(bounds, abs_tol=abs_tol)
diff --git a/lib/iris/tests/unit/plot/test_2d_coords.py b/lib/iris/tests/unit/plot/test_2d_coords.py
index ce96157bf4..bb27341baa 100644
--- a/lib/iris/tests/unit/plot/test_2d_coords.py
+++ b/lib/iris/tests/unit/plot/test_2d_coords.py
@@ -46,23 +46,23 @@ def setUp(self):
self.latlon_2d = testdata.full2d_global()
testdata.make_bounds_discontiguous_at_point(self.latlon_2d, 2, 2)
- # Take a latlon cube with 1D coords, broadcast the coords into 2D
- # ones, then add ONE of them back into the cube in place of original:
- single_dims = lat_lon_cube()
- lon = single_dims.coord('longitude')
- lat = single_dims.coord('latitude')
- big_lon, big_lat = testdata.grid_coords_2d_from_1d(lon, lat)
- mixed_dims = single_dims.copy()
- mixed_dims.remove_coord(lon)
- # TODO Fix this coord addition:
- # When adding an aux_coord, the function '_check_multidim_metadata'
- # throws an error as it requires coord.shape to be (1, ) instead of
- # (3, 4) or whatever.
- mixed_dims.add_aux_coord(big_lon)
-
- # mixed_dims is now a cube with 2 1D dim coords and an additional
- # 2D aux coord.
- self.mixed_dims = mixed_dims
+ # # Take a latlon cube with 1D coords, broadcast the coords into 2D
+ # # ones, then add ONE of them back into the cube in place of original:
+ # single_dims = lat_lon_cube()
+ # lon = single_dims.coord('longitude')
+ # lat = single_dims.coord('latitude')
+ # big_lon, big_lat = testdata.grid_coords_2d_from_1d(lon, lat)
+ # mixed_dims = single_dims.copy()
+ # mixed_dims.remove_coord(lon)
+ # # TODO Fix this coord addition:
+ # # When adding an aux_coord, the function '_check_multidim_metadata'
+ # # throws an error as it requires coord.shape to be (1, ) instead of
+ # # (3, 4) or whatever.
+ # mixed_dims.add_aux_coord(big_lon)
+ #
+ # # mixed_dims is now a cube with 2 1D dim coords and an additional
+ # # 2D aux coord.
+ # self.mixed_dims = mixed_dims
self.mode = coords.BOUND_MODE
@@ -100,15 +100,15 @@ def test_total_span_check(self):
iplt._get_plot_defn_custom_coords_picked(cube, ('wibble', 'foo'),
self.mode)
- def test_2dcoord_with_1dcoord(self):
- # TODO Generate a cube with one 2d coord and one 1d coord
- # TODO Try and plot them against each other
- # TODO Find out where I can put a catch for this (if necessary)
- cube = self.mixed_dims
- with self.assertRaises(ValueError):
- iplt._get_plot_defn_custom_coords_picked(cube,
- ('latitude', 'longitude'),
- self.mode)
+ # def test_2dcoord_with_1dcoord(self):
+ # # TODO Generate a cube with one 2d coord and one 1d coord
+ # # TODO Try and plot them against each other
+ # # TODO Find out where I can put a catch for this (if necessary)
+ # cube = self.mixed_dims
+ # with self.assertRaises(ValueError):
+ # iplt._get_plot_defn_custom_coords_picked(cube,
+ # ('latitude', 'longitude'),
+ # self.mode)
def test_map_common_not_enough_bounds(self):
# Test that a lat-lon cube with 2d coords and 2 bounds per point
@@ -129,16 +129,16 @@ def test_map_common_2d(self):
result = iplt._map_common('pcolor', None, self.mode, cube, plot_defn)
self.assertTrue(result)
- def test_discontiguous_masked(self):
- # Test that a contiguity check will raise a warning (not an error) for
- # discontiguous bounds but appropriately masked data.
- cube = self.latlon_2d
- coord = cube.coord('longitude')
- msg = 'The bounds of the longitude coordinate are not contiguous. ' \
- 'However, data is masked where the discontiguity occurs so ' \
- 'plotting anyway.'
- with self.assertWarnsRegexp(msg):
- iplt._check_contiguity_and_bounds(coord, cube.data)
+ # def test_discontiguous_masked(self):
+ # # Test that a contiguity check will raise a warning (not an error) for
+ # # discontiguous bounds but appropriately masked data.
+ # cube = self.latlon_2d
+ # coord = cube.coord('longitude')
+ # msg = 'The bounds of the longitude coordinate are not contiguous. ' \
+ # 'However, data is masked where the discontiguity occurs so ' \
+ # 'plotting anyway.'
+ # with self.assertWarnsRegexp(msg):
+ # iplt._check_contiguity_and_bounds(coord, cube.data)
def test_discontiguous_unmasked(self):
# Check that an error occurs when the contiguity check finds
From a281805785e212f2f23cdb8a1ecc372978feca39 Mon Sep 17 00:00:00 2001
From: Patrick Peglar
Date: Thu, 2 Aug 2018 12:32:50 +0100
Subject: [PATCH 19/62] Ensure Sphinx autodocs for grid_angles routines.
---
lib/iris/analysis/cartography.py | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/lib/iris/analysis/cartography.py b/lib/iris/analysis/cartography.py
index 16c99c83a8..0c19b84815 100644
--- a/lib/iris/analysis/cartography.py
+++ b/lib/iris/analysis/cartography.py
@@ -42,6 +42,23 @@
true_vectors_from_grid_vectors as rotate_grid_vectors)
+# List of contents to control Sphinx autodocs.
+# Unfortunately essential to get docs for the grid_angles functions.
+__all__ = [
+ 'area_weights',
+ 'cosine_latitude_weights',
+ 'get_xy_contiguous_bounded_grids',
+ 'get_xy_grids',
+ 'gridcell_angles',
+ 'project',
+ 'rotate_grid_vectors',
+ 'rotate_pole',
+ 'rotate_winds',
+ 'unrotate_pole',
+ 'wrap_lons',
+ 'DistanceDifferential',
+ 'PartialDifferential']
+
# This value is used as a fall-back if the cube does not define the earth
DEFAULT_SPHERICAL_EARTH_RADIUS = 6367470
# TODO: This should not be necessary, as CF is always in meters
From e024f5019702013c228844da410af8bc014f30ea Mon Sep 17 00:00:00 2001
From: Patrick Peglar
Date: Thu, 2 Aug 2018 12:34:54 +0100
Subject: [PATCH 20/62] Codestyle fixes.
---
lib/iris/analysis/cartography.py | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/lib/iris/analysis/cartography.py b/lib/iris/analysis/cartography.py
index 0c19b84815..dadcdedc86 100644
--- a/lib/iris/analysis/cartography.py
+++ b/lib/iris/analysis/cartography.py
@@ -352,7 +352,7 @@ def _quadrant_area(radian_lat_bounds, radian_lon_bounds, radius_of_earth):
def area_weights(cube, normalize=False):
- """
+ r"""
Returns an array of area weights, with the same dimensions as the cube.
This is a 2D lat/lon area weights array, repeated over the non lat/lon
@@ -460,7 +460,7 @@ def area_weights(cube, normalize=False):
def cosine_latitude_weights(cube):
- """
+ r"""
Returns an array of latitude weights, with the same dimensions as
the cube. The weights are the cosine of latitude.
@@ -970,7 +970,7 @@ def _transform_distance_vectors_tolerance_mask(src_crs, x, y, tgt_crs,
def rotate_winds(u_cube, v_cube, target_cs):
- """
+ r"""
Transform wind vectors to a different coordinate system.
The input cubes contain U and V components parallel to the local X and Y
From e3e82e458f68ebbc008f43eb5ce91bced038d445 Mon Sep 17 00:00:00 2001
From: Patrick Peglar
Date: Thu, 2 Aug 2018 12:53:08 +0100
Subject: [PATCH 21/62] Whatsnew entries for 2d vector support.
---
docs/iris/src/whatsnew/2.2.rst | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/docs/iris/src/whatsnew/2.2.rst b/docs/iris/src/whatsnew/2.2.rst
index 97eba3dee6..4edc305025 100644
--- a/docs/iris/src/whatsnew/2.2.rst
+++ b/docs/iris/src/whatsnew/2.2.rst
@@ -24,3 +24,13 @@ Iris 2.2.0 Features
automatically checked for contiguity. Coordinate bounds must either be
contiguous, or the cube's data must be masked at the discontiguities in
order to avoid plotting errors.
+
+ The iris plot functions :func:`iris.plot.quiver` and
+ :func:`iris.plot.streamplot` have been added, and these also work with
+ 2-dimensional plot coordinates.
+
+.. admonition:: 2-Dimensional Grid Vectors
+
+ The iris functions :func:`iris.analysis.cartography.gridcell_angles` and
+ :func:`iris.analysis.cartography.rotate_grid_vectors` have been added,
+ allowing you to convert gridcell-oriented vectors to true-North/East ones.
From b041c50ca371dacbbfc14489b35aa9a9dca44b50 Mon Sep 17 00:00:00 2001
From: Patrick Peglar
Date: Tue, 14 Aug 2018 15:55:29 +0100
Subject: [PATCH 22/62] Pin Dask to avoid 0.18.2 bug with masked arrays.
(#3127)
* Put orca_util routines in subpackage of iris.test.stock, to get existing iris.tests.unit.plot.test_2d_coords working.
* Disable broken misused testcode in test_gridcell_angles.
* Ditch test_gridcell_angles, none of it is functional.
* Further style fixes.
* Skip tests using iris-test-data, for Travis TEST_MINIMAL phases.
* Codestyle fix (though this code obsolete anyway).
* Fix unused imports.
* Made-up test cube replaces use of iris-test-data.
* Renamed keyword; improved docstring.
* Change 'co' to 'coord' for clarity.
* Review changes.
---
lib/iris/analysis/_grid_angles.py | 6 +-
lib/iris/coords.py | 2 +-
lib/iris/plot.py | 2 +-
.../tests/{stock.py => stock/__init__.py} | 3 +-
lib/iris/tests/stock/_stock_2d_latlons.py | 346 ++++++++++++++++
lib/iris/tests/test_coding_standards.py | 2 +-
.../cartography/test_gridcell_angles.py | 392 ------------------
lib/iris/tests/unit/plot/test_2d_coords.py | 46 +-
8 files changed, 382 insertions(+), 417 deletions(-)
rename lib/iris/tests/{stock.py => stock/__init__.py} (99%)
create mode 100644 lib/iris/tests/stock/_stock_2d_latlons.py
delete mode 100644 lib/iris/tests/unit/analysis/cartography/test_gridcell_angles.py
diff --git a/lib/iris/analysis/_grid_angles.py b/lib/iris/analysis/_grid_angles.py
index 1746834a65..ffe6d51c7f 100644
--- a/lib/iris/analysis/_grid_angles.py
+++ b/lib/iris/analysis/_grid_angles.py
@@ -92,7 +92,7 @@ def _angle(p, q, r):
if old_style:
mid_lons = np.deg2rad(q[0])
- pr = _3d_xyz_from_latlon(r[0], r[1]) - _3d_xyz_from_latlon(p[0], p[1])
+ pr = _3d_xyz_from_latlon(r[0], r[1]) - _3d_xyz_from_latlon(p[0], p[1])
pr_norm = np.sqrt(np.sum(pr**2, axis=0))
pr_top = pr[1] * np.cos(mid_lons) - pr[0] * np.sin(mid_lons)
@@ -124,7 +124,7 @@ def _angle(p, q, r):
lmb_hatvec_y,
lmb_hatvec_z)])
- pr = _3d_xyz_from_latlon(r[0], r[1]) - _3d_xyz_from_latlon(p[0], p[1])
+ pr = _3d_xyz_from_latlon(r[0], r[1]) - _3d_xyz_from_latlon(p[0], p[1])
# Dot products to form true-northward / true-eastward projections.
pr_cmpt_e = np.sum(pr * lmb_hatvec, axis=0)
@@ -141,7 +141,7 @@ def _angle(p, q, r):
rtol = 1.e-3
check = np.allclose(mag_rot, mag_orig, rtol=rtol)
if not check:
- print (mag_rot, mag_orig)
+ print(mag_rot, mag_orig)
assert np.allclose(mag_rot, mag_orig, rtol=rtol)
return psi
diff --git a/lib/iris/coords.py b/lib/iris/coords.py
index 8f1e48fd18..ff2f170a2f 100644
--- a/lib/iris/coords.py
+++ b/lib/iris/coords.py
@@ -1071,7 +1071,7 @@ def is_contiguous(self, rtol=1e-05, atol=1e-08):
rtol=rtol, atol=atol)
elif self.ndim == 2:
contiguous, _, _ = _discontiguity_in_2d_bounds(self.bounds,
- abs_tol=atol)
+ abs_tol=atol)
else:
contiguous = False
return contiguous
diff --git a/lib/iris/plot.py b/lib/iris/plot.py
index 8f11c8d116..7bf8ea07f3 100644
--- a/lib/iris/plot.py
+++ b/lib/iris/plot.py
@@ -334,7 +334,7 @@ def _draw_2d_from_bounds(draw_method_name, cube, *args, **kwargs):
plot_defn = _get_plot_defn(cube, mode, ndims=2)
twodim_contig_atol = kwargs.pop('two_dim_coord_contiguity_atol',
- 1e-4)
+ 1e-4)
for coord in plot_defn.coords:
if hasattr(coord, 'has_bounds'):
if coord.ndim == 2 and coord.has_bounds():
diff --git a/lib/iris/tests/stock.py b/lib/iris/tests/stock/__init__.py
similarity index 99%
rename from lib/iris/tests/stock.py
rename to lib/iris/tests/stock/__init__.py
index 1b55510d2b..5965d5a208 100644
--- a/lib/iris/tests/stock.py
+++ b/lib/iris/tests/stock/__init__.py
@@ -36,7 +36,8 @@
from iris.coords import DimCoord, AuxCoord
import iris.tests as tests
from iris.coord_systems import GeogCS, RotatedGeogCS
-
+from ._stock_2d_latlons import (sample_2d_latlons,
+ make_bounds_discontiguous_at_point)
def lat_lon_cube():
"""
diff --git a/lib/iris/tests/stock/_stock_2d_latlons.py b/lib/iris/tests/stock/_stock_2d_latlons.py
new file mode 100644
index 0000000000..75b62f31ba
--- /dev/null
+++ b/lib/iris/tests/stock/_stock_2d_latlons.py
@@ -0,0 +1,346 @@
+# (C) British Crown Copyright 2018, Met Office
+#
+# This file is part of Iris.
+#
+# Iris is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Iris is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Iris. If not, see .
+"""
+Extra stock routines for making and manipulating cubes with 2d coordinates,
+to mimic ocean grid data.
+
+"""
+from __future__ import (absolute_import, division, print_function)
+from six.moves import (filter, input, map, range, zip) # noqa
+
+import numpy as np
+import numpy.ma as ma
+
+from iris.analysis.cartography import unrotate_pole
+from iris.cube import Cube
+from iris.coords import AuxCoord, DimCoord
+from iris.coord_systems import RotatedGeogCS
+
+
+def expand_1d_x_and_y_bounds_to_2d_xy(x_bounds_1d, y_bounds_1d):
+ """
+ Convert bounds for separate 1-D X and Y coords into bounds for the
+ equivalent 2D coordinates.
+
+ The output arrays have 4 points per cell, for 4 'corners' of a gridcell,
+ in the usual anticlockwise order
+ (bottom-left, bottom-right, top-right, top-left).
+
+ If 1-dimensional X and Y coords have shapes nx and ny, then their bounds
+ have shapes (nx, 2) and (ny, 2).
+ The equivalent 2d coordinates would have values which are a "meshgrid" of
+ the original 1-D points, both having the shape (ny, ny).
+ The outputs are 2d bounds arrays suitable for such 2d coordinates.
+
+ Args:
+
+ * x_bounds_1d, y_bounds_1d : (array)
+ Coordinate bounds arrays, with shapes (nx, 2) and (ny, 2).
+
+ Result:
+
+ * x_bounds_2d, y_bounds_2d : (array)
+ Expanded 2d bounds arrays, both of shape (ny, nx, 4).
+
+ """
+ shapes = [bds.shape for bds in (x_bounds_1d, y_bounds_1d)]
+ for shape in shapes:
+ if len(shape) != 2 or shape[1] != 2:
+ msg = ('One-dimensional bounds arrays must have shapes (ny, 2) '
+ 'and (nx, 2). Got {} and {}.')
+ raise ValueError(msg.format(*shapes))
+
+ # Construct output arrays, which are both (ny, nx, 4).
+ nx, ny = [shape[0] for shape in shapes]
+ bds_2d_x = np.zeros((ny, nx, 4))
+ bds_2d_y = bds_2d_x.copy()
+
+ # Expand x bounds to 2D array (ny, nx, 4) : the same over all 'Y'.
+ # Bottom left+right corners are the original 1-D x bounds.
+ bds_2d_x[:, :, 0] = x_bounds_1d[:, 0].reshape((1, nx))
+ bds_2d_x[:, :, 1] = x_bounds_1d[:, 1].reshape((1, nx))
+ # Top left+right corners are the same as bottom left+right.
+ bds_2d_x[:, :, 2] = bds_2d_x[:, :, 1].copy()
+ bds_2d_x[:, :, 3] = bds_2d_x[:, :, 0].copy()
+
+ # Expand y bounds to 2D array (ny, nx, 4) : the same over all 'X'.
+ # Left-hand lower+upper corners are the original 1-D y bounds.
+ bds_2d_y[:, :, 0] = y_bounds_1d[:, 0].reshape((ny, 1))
+ bds_2d_y[:, :, 3] = y_bounds_1d[:, 1].reshape((ny, 1))
+ # Right-hand lower+upper corners are the same as the left-hand ones.
+ bds_2d_y[:, :, 1] = bds_2d_y[:, :, 0].copy()
+ bds_2d_y[:, :, 2] = bds_2d_y[:, :, 3].copy()
+
+ return bds_2d_x, bds_2d_y
+
+
+def grid_coords_2d_from_1d(x_coord_1d, y_coord_1d):
+ """
+ Calculate a pair of 2d X+Y coordinates from 1d ones, in a "meshgrid" style.
+ If the inputs are bounded, the outputs have 4 points per bounds in the
+ usual way, i.e. points 0,1,2,3 are the gridcell corners anticlockwise from
+ the bottom left.
+
+ """
+ for coord in (x_coord_1d, y_coord_1d):
+ if coord.ndim != 1:
+ msg = ('Input coords must be one-dimensional. '
+ 'Coordinate "{}" has shape {}.')
+ raise ValueError(msg.format(coord.name(), coord.shape))
+
+ # Calculate centre-points as a mesh of the 2 inputs.
+ pts_2d_x, pts_2d_y = np.meshgrid(x_coord_1d.points, y_coord_1d.points)
+ if not x_coord_1d.has_bounds() or not y_coord_1d.has_bounds():
+ bds_2d_x = None
+ bds_2d_y = None
+ else:
+ bds_2d_x, bds_2d_y = expand_1d_x_and_y_bounds_to_2d_xy(
+ x_coord_1d.bounds, y_coord_1d.bounds)
+
+ # Make two new coords + return them.
+ result = []
+ for pts, bds, name in zip((pts_2d_x, pts_2d_y),
+ (bds_2d_x, bds_2d_y),
+ ('longitude', 'latitude')):
+ coord = AuxCoord(pts, bounds=bds, standard_name=name, units='degrees')
+ result.append(coord)
+
+ return result
+
+
+def sample_2d_latlons(regional=False, rotated=False, transformed=False):
+ """
+ Construct small 2d cubes with 2d X and Y coordinates.
+
+ This makes cubes with 'expanded' coordinates (4 bounds per cell), analagous
+ to ORCA data.
+ The coordinates are always geographical, so either it has a coord system
+ or they are "true" lats + lons.
+ ( At present, they are always latitudes and longitudes, but maybe in a
+ rotated system. )
+ The results always have fully contiguous bounds.
+
+ Kwargs:
+ * regional (bool):
+ If False (default), results cover the whole globe, and there is
+ implicit connectivity between rhs + lhs of the array.
+ If True, coverage is regional and edges do not connect.
+ * rotated (bool):
+ If False, X and Y coordinates are true-latitudes and longitudes, with
+ an implicit coordinate system (i.e. None).
+ If True, the X and Y coordinates are lats+lons in a selected
+ rotated-latlon coordinate system.
+ * transformed (bool):
+ Build coords from rotated coords as for 'rotated', but then replace
+ their values with the equivalent "true" lats + lons, and no
+ coord-system (defaults to true-latlon).
+ In this case, the X and Y coords are no longer 'meshgrid' style,
+ i.e. the points + bounds values vary in *both* dimensions.
+
+ .. note::
+
+ 'transformed' is an alternative to 'rotated' : when 'transformed' is
+ set, then 'rotated' has no effect.
+
+ .. Some sample results printouts ::
+
+ >>> print(sample_2d_latlons())
+ test_data / (unknown) (-- : 5; -- : 6)
+ Auxiliary coordinates:
+ latitude x x
+ longitude x x
+ >>>
+ >>> print(sample_2d_latlons().coord(axis='x')[0, :2])
+ AuxCoord(array([ 37.5 , 93.75]),
+ bounds=array([[ 0. , 65.625, 65.625, 0. ],
+ [ 65.625, 121.875, 121.875, 65.625]]),
+ standard_name='longitude', units=Unit('degrees'))
+ >>> print(np.round(sample_2d_latlons().coord(axis='x').points, 3))
+ [[ 37.5 93.75 150. 206.25 262.5 318.75]
+ [ 37.5 93.75 150. 206.25 262.5 318.75]
+ [ 37.5 93.75 150. 206.25 262.5 318.75]
+ [ 37.5 93.75 150. 206.25 262.5 318.75]
+ [ 37.5 93.75 150. 206.25 262.5 318.75]]
+ >>> print(np.round(sample_2d_latlons().coord(axis='y').points, 3))
+ [[-85. -85. -85. -85. -85. -85. ]
+ [-47.5 -47.5 -47.5 -47.5 -47.5 -47.5]
+ [-10. -10. -10. -10. -10. -10. ]
+ [ 27.5 27.5 27.5 27.5 27.5 27.5]
+ [ 65. 65. 65. 65. 65. 65. ]]
+
+
+ >>> print(np.round(
+ sample_2d_latlons(rotated=True).coord(axis='x').points, 3))
+ [[ 37.5 93.75 150. 206.25 262.5 318.75]
+ [ 37.5 93.75 150. 206.25 262.5 318.75]
+ [ 37.5 93.75 150. 206.25 262.5 318.75]
+ [ 37.5 93.75 150. 206.25 262.5 318.75]
+ [ 37.5 93.75 150. 206.25 262.5 318.75]]
+ >>> print(sample_2d_latlons(rotated=True).coord(axis='y').coord_system)
+ RotatedGeogCS(75.0, 120.0)
+
+
+ >>> print(
+ sample_2d_latlons(transformed=True).coord(axis='y').coord_system)
+ None
+ >>> print(np.round(
+ sample_2d_latlons(transformed=True).coord(axis='x').points, 3))
+ [[ -50.718 -40.983 -46.74 -71.938 -79.293 -70.146]
+ [ -29.867 17.606 77.936 157.145 -141.037 -93.172]
+ [ -23.139 31.007 87.699 148.322 -154.639 -100.505]
+ [ -16.054 41.218 92.761 143.837 -164.738 -108.105]
+ [ 10.86 61.78 100.236 137.285 175.511 -135.446]]
+ >>> print(np.round(
+ sample_2d_latlons(transformed=True).coord(axis='y').points, 3))
+ [[-70.796 -74.52 -79.048 -79.26 -74.839 -70.96 ]
+ [-34.99 -46.352 -59.721 -60.34 -47.305 -35.499]
+ [ 1.976 -10.626 -22.859 -23.349 -11.595 1.37 ]
+ [ 38.914 25.531 14.312 13.893 24.585 38.215]
+ [ 74.197 60.258 51.325 51.016 59.446 73.268]]
+ >>>
+
+ """
+ def sample_cube(xargs, yargs):
+ # Make a test cube with given latitude + longitude coordinates.
+ # xargs/yargs are args for np.linspace (start, stop, N), to make the X
+ # and Y coordinate points.
+ x0, x1, nx = xargs
+ y0, y1, ny = yargs
+ # Data has cycling values, staggered a bit in successive rows.
+ data = np.zeros((ny, nx))
+ data.flat[:] = np.arange(ny * nx) % (nx + 2)
+ # Build a 2d cube with longitude + latitude coordinates.
+ cube = Cube(data, long_name='test_data')
+ x_pts = np.linspace(x0, x1, nx, endpoint=True)
+ y_pts = np.linspace(y0, y1, ny, endpoint=True)
+ co_x = DimCoord(x_pts, standard_name='longitude', units='degrees')
+ co_y = DimCoord(y_pts, standard_name='latitude', units='degrees')
+ cube.add_dim_coord(co_y, 0)
+ cube.add_dim_coord(co_x, 1)
+ return cube
+
+ if regional:
+ # Extract small region.
+ cube = sample_cube(xargs=(150., 243.75, 6), yargs=(-10., 40., 5))
+
+ # Make contiguous bounds.
+ for ax in ('x', 'y'):
+ cube.coord(axis=ax).guess_bounds()
+ else:
+ # Global data, but drastically reduced resolution.
+ cube = sample_cube(xargs=(37.5, 318.75, 6), yargs=(-85., 65., 5))
+
+ # Patch bounds to ensure it is still contiguous + global.
+ for name in ('longitude', 'latitude'):
+ coord = cube.coord(name)
+ coord.guess_bounds()
+ bds = coord.bounds.copy()
+ # Make bounds global, by fixing lowest and uppermost values.
+ if name == 'longitude':
+ bds[0, 0] = 0.0
+ bds[-1, 1] = 360.0
+ else:
+ bds[0, 0] = -90.0
+ bds[-1, 1] = 90.0
+ coord.bounds = bds
+
+ # Get 1d coordinate points + bounds + calculate 2d equivalents.
+ co_1d_x, co_1d_y = [cube.coord(axis=ax).copy() for ax in ('x', 'y')]
+ co_2d_x, co_2d_y = grid_coords_2d_from_1d(co_1d_x, co_1d_y)
+
+ # Remove the old grid coords.
+ for coord in (co_1d_x, co_1d_y):
+ cube.remove_coord(coord)
+
+ # Add the new grid coords.
+ for coord in (co_2d_x, co_2d_y):
+ cube.add_aux_coord(coord, (0, 1))
+
+ if transformed or rotated:
+ # Take the lats + lons as being in a rotated coord system.
+ pole_lat, pole_lon = 75.0, 120.0
+ if transformed:
+ # Reproject coordinate values from rotated to true lat-lons.
+ co_x, co_y = [cube.coord(axis=ax) for ax in ('x', 'y')]
+ # Unrotate points.
+ lons, lats = co_x.points, co_y.points
+ lons, lats = unrotate_pole(lons, lats, pole_lon, pole_lat)
+ co_x.points, co_y.points = lons, lats
+ # Unrotate bounds.
+ lons, lats = co_x.bounds, co_y.bounds
+ # Note: save the shape, flatten + then re-apply the shape, because
+ # "unrotate_pole" uses "cartopy.crs.CRS.transform_points", which
+ # only works on arrays of 1 or 2 dimensions.
+ shape = lons.shape
+ lons, lats = unrotate_pole(lons.flatten(), lats.flatten(),
+ pole_lon, pole_lat)
+ co_x.bounds, co_y.bounds = lons.reshape(shape), lats.reshape(shape)
+ else:
+ # "Just" rotate operation : add a coord-system to each coord.
+ cs = RotatedGeogCS(pole_lat, pole_lon)
+ for coord in cube.coords():
+ coord.coord_system = cs
+
+ return cube
+
+
+def make_bounds_discontiguous_at_point(cube, at_iy, at_ix):
+ """
+ Meddle with the XY grid bounds of a cube to make the grid discontiguous.
+
+ Changes the points and bounds of a single gridcell, so that it becomes
+ discontinuous with the next gridcell to its right.
+ Also masks the cube data at the given point.
+
+ The cube must have bounded 2d 'x' and 'y' coordinates.
+
+ TODO: add a switch to make a discontiguity in the *y*-direction instead ?
+
+ """
+ x_coord = cube.coord(axis='x')
+ y_coord = cube.coord(axis='y')
+ assert x_coord.shape == y_coord.shape
+ assert (coord.bounds.ndim == 3 and coord.shape[-1] == 4
+ for coord in (x_coord, y_coord))
+
+ # For both X and Y coord, move points + bounds to create a discontinuity.
+ def adjust_coord(coord):
+ pts, bds = coord.points, coord.bounds
+ # Fetch the 4 bounds (bottom-left, bottom-right, top-right, top-left)
+ bds_bl, bds_br, bds_tr, bds_tl = bds[at_iy, at_ix]
+ # Make a discontinuity "at" (iy, ix), by moving the right-hand edge of
+ # the cell to the midpoint of the existing left+right bounds.
+ new_bds_br = 0.5 * (bds_bl + bds_br)
+ new_bds_tr = 0.5 * (bds_tl + bds_tr)
+ bds_br, bds_tr = new_bds_br, new_bds_tr
+ bds[at_iy, at_ix] = [bds_bl, bds_br, bds_tr, bds_tl]
+ # Also reset the cell midpoint to the middle of the 4 new corners,
+ # in case having a midpoint outside the corners might cause a problem.
+ new_pt = 0.25 * sum([bds_bl, bds_br, bds_tr, bds_tl])
+ pts[at_iy, at_ix] = new_pt
+ # Write back the coord points+bounds (can only assign whole arrays).
+ coord.points, coord.bounds = pts, bds
+
+ adjust_coord(x_coord)
+ adjust_coord(y_coord)
+ # Also mask the relevant data point.
+ data = cube.data # N.B. fetch all the data.
+ if not ma.isMaskedArray(data):
+ # Promote to masked array, to avoid converting mask to NaN.
+ data = ma.masked_array(data)
+ data[at_iy, at_ix] = ma.masked
+ cube.data = data
diff --git a/lib/iris/tests/test_coding_standards.py b/lib/iris/tests/test_coding_standards.py
index 39c73e8285..c24ac46cb3 100644
--- a/lib/iris/tests/test_coding_standards.py
+++ b/lib/iris/tests/test_coding_standards.py
@@ -93,7 +93,7 @@ class StandardReportWithExclusions(pep8.StandardReport):
'*/iris/io/format_picker.py',
'*/iris/tests/__init__.py',
'*/iris/tests/pp.py',
- '*/iris/tests/stock.py',
+ '*/iris/tests/stock/__init__.py',
'*/iris/tests/system_test.py',
'*/iris/tests/test_analysis.py',
'*/iris/tests/test_analysis_calculus.py',
diff --git a/lib/iris/tests/unit/analysis/cartography/test_gridcell_angles.py b/lib/iris/tests/unit/analysis/cartography/test_gridcell_angles.py
deleted file mode 100644
index de00d2bc76..0000000000
--- a/lib/iris/tests/unit/analysis/cartography/test_gridcell_angles.py
+++ /dev/null
@@ -1,392 +0,0 @@
-# (C) British Crown Copyright 2018, Met Office
-#
-# This file is part of Iris.
-#
-# Iris is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Iris is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with Iris. If not, see .
-"""
-Unit tests for the function
-:func:`iris.analysis.cartography.gridcell_angles`.
-
-"""
-from __future__ import (absolute_import, division, print_function)
-from six.moves import (filter, input, map, range, zip) # noqa
-
-# Import iris.tests first so that some things can be initialised before
-# importing anything else.
-import iris.tests as tests
-
-import numpy as np
-import numpy.ma as ma
-
-import cartopy.crs as ccrs
-from iris.cube import Cube
-from iris.coords import DimCoord, AuxCoord
-import iris.coord_systems
-from iris.analysis.cartography import unrotate_pole
-
-from iris.analysis.cartography import (gridcell_angles,
- rotate_grid_vectors)
-
-import matplotlib.pyplot as plt
-from orca_utils.plot_testing.blockplot_from_bounds import blockplot_2dll
-
-
-def _rotated_grid_sample(pole_lat=15, pole_lon=-180,
- lon_bounds=np.linspace(-30, 30, 6, endpoint=True),
- lat_bounds=np.linspace(-30, 30, 6, endpoint=True)):
- # Calculate *true* lat_bounds+lon_bounds for the rotated grid.
- lon_bounds = np.array(lon_bounds, dtype=float)
- lat_bounds = np.array(lat_bounds, dtype=float)
- # Construct centrepoints.
- lons = 0.5 * (lon_bounds[:-1] + lon_bounds[1:])
- lats = 0.5 * (lat_bounds[:-1] + lat_bounds[1:])
- # Convert all to full 2d arrays.
- lon_bounds, lat_bounds = np.meshgrid(lon_bounds, lat_bounds)
- lons, lats = np.meshgrid(lons, lats)
- # Calculate true lats+lons for all points.
- lons_true_bds, lats_true_bds = unrotate_pole(lon_bounds, lat_bounds,
- pole_lon, pole_lat)
- lons_true, lats_true = unrotate_pole(lons, lats, pole_lon, pole_lat)
- # Make the 'unified' bounds into contiguous (ny, nx, 4) arrays.
- def expand_unified_bds(bds):
- ny, nx = bds.shape
- bds_4 = np.zeros((ny - 1, nx - 1, 4))
- bds_4[:, :, 0] = bds[:-1, :-1]
- bds_4[:, :, 1] = bds[:-1, 1:]
- bds_4[:, :, 2] = bds[1:, 1:]
- bds_4[:, :, 3] = bds[1:, :-1]
- return bds_4
-
- lon_true_bds4, lat_true_bds4 = (expand_unified_bds(bds)
- for bds in (lons_true_bds, lats_true_bds))
- # Make these into a 2d-latlon grid for a cube
- cube = Cube(np.zeros(lon_true_bds4.shape[:-1]))
- co_x = AuxCoord(lons_true, bounds=lon_true_bds4,
- standard_name='longitude', units='degrees')
- co_y = AuxCoord(lats_true, bounds=lat_true_bds4,
- standard_name='latitude', units='degrees')
- cube.add_aux_coord(co_x, (0, 1))
- cube.add_aux_coord(co_y, (0, 1))
- return cube
-
-
-class TestGridcellAngles(tests.IrisTest):
- def _singlecell_30deg_cube(self, x0=90., y0=0., dx=20., dy=10.):
- x_pts = np.array([[x0]])
- y_pts = np.array([[y0]])
- x_bds = x0 + dx * np.array([[[-1., 1, 0.5, -1.5]]])
-# self.assertArrayAllClose(x_bds, np.array([[[70., 110, 100, 60]]]))
- y_bds = y0 + dy * np.array([[[-1., 1, 3, 1]]])
-# self.assertArrayAllClose(y_bds, np.array([[[-10., 10, 30, 10]]]))
- co_x = AuxCoord(points=x_pts, bounds=x_bds,
- standard_name='longitude', units='degrees')
- co_y = AuxCoord(points=y_pts, bounds=y_bds,
- standard_name='latitude', units='degrees')
- cube = Cube(np.zeros((1, 1)))
- cube.add_aux_coord(co_x, (0, 1))
- cube.add_aux_coord(co_y, (0, 1))
- return cube
-
- def _singlecell_diamond_cube(self, x0=90., y0=0., dy=10., dx_eq=None):
- if dx_eq is None:
- dx_eq = dy
- x_pts = np.array([[x0]])
- y_pts = np.array([[y0]])
- dx = dx_eq / np.cos(np.deg2rad(y0))
- x_bds = np.array([[[x0, x0 + dx, x0, x0 - dx]]])
- y_bds = np.array([[[y0 - dy, y0, y0 + dy, y0]]])
- co_x = AuxCoord(points=x_pts, bounds=x_bds,
- standard_name='longitude', units='degrees')
- co_y = AuxCoord(points=y_pts, bounds=y_bds,
- standard_name='latitude', units='degrees')
- cube = Cube(np.zeros((1, 1)))
- cube.add_aux_coord(co_x, (0, 1))
- cube.add_aux_coord(co_y, (0, 1))
- return cube
-
- def test_single_cell_equatorial(self):
- plt.switch_backend('tkagg')
- plt.figure(figsize=(10,10))
- ax = plt.axes(projection=ccrs.Mercator())
-# ax = plt.axes(projection=ccrs.NorthPolarStereo())
-# ax = plt.axes(projection=ccrs.Orthographic(central_longitude=90.,
-# central_latitude=30.))
-
- lon0 = 90.0
- dy = 2.0
- y_0, y_n, ny = -80, 80, 9
- angles = []
- for lat in np.linspace(y_0, y_n, ny):
- cube = self._singlecell_diamond_cube(x0=lon0, y0=lat, dy=dy)
- angles_cube = gridcell_angles(cube,
-# cell_angle_boundpoints='mid-lhs, mid-rhs')
- cell_angle_boundpoints='lower-left, lower-right')
- tmp_cube = angles_cube.copy()
- tmp_cube.convert_units('degrees')
- print('')
- print(lat)
- co_x, co_y = (cube.coord(axis=ax) for ax in ('x', 'y'))
- print()
- print(' at : {}, {}'.format(co_x.points[0, 0], co_y.points[0, 0]))
- print(' x-bds:')
- print(co_x.bounds)
- print(' y-bds:')
- print(co_y.bounds)
- angle = tmp_cube.data[0, 0]
- angles.append(angle)
- print(angle)
- blockplot_2dll(cube)
-
- ax.coastlines()
- ax.set_global()
-
- # Plot constant NEly (45deg) arrows.
- xx = np.array([lon0] * ny)
- yy = np.linspace(y_0, y_n, ny) - dy
- uu = np.array([1.0] * ny)
- plt.quiver(xx, yy,
- uu, np.cos(np.deg2rad(yy)),
- zorder=2, color='red',
- scale_units='xy',
- transform=ccrs.PlateCarree())
-
- # Also plot returned angles.
- angles_arr_rad = np.deg2rad(angles)
- u_arr = uu * np.cos(angles_arr_rad)
- v_arr = uu * np.sin(angles_arr_rad) * np.cos(np.deg2rad(yy))
-
- plt.quiver(xx, yy,
- u_arr,
- v_arr,
- zorder=2, color='magenta',
- scale_units='xy',
- width=0.005,
- scale=0.2e-6,
-# width=0.5,
- transform=ccrs.PlateCarree())
-
- plt.show()
-
-
- def test_values(self):
- # Construct a rotated-pole grid and check angle calculation.
- testcube = _rotated_grid_sample()
-
- cell_angle_boundpoints = 'mid-lhs, mid-rhs'
-# cell_angle_boundpoints = 'lower-left, lower-right'
-# cell_angle_boundpoints = 'garble'
- angles_cube = gridcell_angles(
- testcube,
- cell_angle_boundpoints=cell_angle_boundpoints)
- angles_cube.convert_units('radians')
-
- # testing phase...
- print(np.rad2deg(angles_cube.data))
-
- import matplotlib.pyplot as plt
- plt.switch_backend('tkagg')
-
-# plot_map = 'north_polar_stereographic'
-# plot_map = 'plate_carree'
-# plot_map = 'mercator'
- plot_map = 'north_polar_orthographic'
- if plot_map == 'plate_carree':
- scale = 0.1
- map_proj = ccrs.PlateCarree()
- elif plot_map == 'mercator':
- scale = 3.0e-6
- map_proj = ccrs.Mercator()
- map_proj._threshold *= 0.01
- elif plot_map == 'north_polar_orthographic':
- scale = 3.0e-6
- map_proj = ccrs.Orthographic(central_longitude=0.0,
- central_latitude=90.0,)
- map_proj._threshold *= 0.01
- elif plot_map == 'north_polar_stereographic':
- scale = 3.0e-6
- map_proj = ccrs.NorthPolarStereo()
- else:
- assert 0
-
- ax = plt.axes(projection=map_proj)
- data_proj = ccrs.PlateCarree()
-
- deg_scale = 10.0
-
-# angles = 'uv'
- angles = 'xy'
-
- ax.coastlines()
- ax.gridlines()
- for i_bnd in range(4):
- color = ['black', 'red', 'blue', 'magenta'][i_bnd]
- plt.plot(testcube.coord('longitude').bounds[..., i_bnd],
- testcube.coord('latitude').bounds[..., i_bnd],
- '+', markersize=10., markeredgewidth=2.,
- markerfacecolor=color, markeredgecolor=color,
- transform=data_proj)
-
-
- # Show plain 0,1 + 1,0 (PlateCarree) vectors unrotated at the given points.
- pts_shape = testcube.coord('longitude').shape
- ny, nx = pts_shape
- u0 = np.ones(pts_shape)
- v0 = np.zeros(pts_shape)
- u1 = v0.copy()
- v1 = u0.copy()
-
- x0s = testcube.coord('longitude').points
- y0s = testcube.coord('latitude').points
- yscale = np.cos(np.deg2rad(y0s))
- plt.quiver(x0s, y0s, u0, v0 * yscale,
- color='blue', width=0.005,
- headwidth=2., # headlength=1.0, headaxislength=0.7,
- angles=angles,
- scale_units='xy', scale=scale,
- transform=data_proj)
- plt.quiver(x0s, y0s, u1, v1 * yscale,
- color='red', width=0.005,
- headwidth=2., # headlength=1.0, headaxislength=0.7,
- angles=angles,
- scale_units='xy', scale=scale,
- transform=data_proj)
-
- # Add 45deg arrows (NEly), still on a PlateCarree map.
- plt.quiver(x0s, y0s, v1, v1 * yscale,
- color='green', width=0.005,
- headwidth=2., # headlength=1.0, headaxislength=0.7,
- angles=angles,
- scale_units='xy', scale=scale,
- transform=data_proj)
-
-
-
- #
- # Repeat the above plotting short lines INSTEAD of quiver.
- #
- u0d = x0s + deg_scale * u0
- v0d = y0s + deg_scale * v0
- u1d = x0s + deg_scale * u1
- v1d = y0s + deg_scale * v1
- u2d = x0s + deg_scale * u0
- v2d = y0s + deg_scale * v1
- for iy in range(ny):
- for ix in range(nx):
- plt.plot([x0s[iy, ix], u0d[iy, ix]],
- [y0s[iy, ix], v0d[iy, ix]],
- ':', color='blue', linewidth=0.5,
- transform=data_proj)
- plt.plot([x0s[iy, ix], u1d[iy, ix]],
- [y0s[iy, ix], v1d[iy, ix]],
- ':', color='red', linewidth=0.5,
- transform=data_proj)
- plt.plot([x0s[iy, ix], u2d[iy, ix]],
- [y0s[iy, ix], v2d[iy, ix]],
- ':', color='green', linewidth=0.5,
- transform=data_proj)
-
-
- # Overplot BL-BR and BL-TL lines from the cell bounds.
- co_lon, co_lat = [testcube.coord(name).copy()
- for name in ('longitude', 'latitude')]
- for co in (co_lon, co_lat):
- co.convert_units('degrees')
- lon_bds, lat_bds = [co.bounds for co in (co_lon, co_lat)]
-# ny, nx = lon_bds.shape[:-1]
- for iy in range(ny):
- for ix in range(nx):
- x0, y0 = lon_bds[iy, ix, 0], lat_bds[iy, ix, 0]
- x1, y1 = lon_bds[iy, ix, 1], lat_bds[iy, ix, 1]
- x2, y2 = lon_bds[iy, ix, 3], lat_bds[iy, ix, 3]
- plt.plot([x0, x1], [y0, y1], 'x-',
- color='orange',
- transform=data_proj)
- plt.plot([x0, x2], [y0, y2], 'x-',
- color='orange', linestyle='--',
- transform=data_proj)
-
- # Plot U0, rotated by cell angles, also at cell bottom-lefts.
- u0_cube, u1_cube, v0_cube, v1_cube = [testcube.copy(data=aa)
- for aa in (u0, v0, u1, v1)]
- u0r_cube, v0r_cube = rotate_grid_vectors(
- u0_cube, v0_cube, grid_angles_cube=angles_cube)
- u0r, v0r = [cube.data for cube in (u0r_cube, v0r_cube)]
-
- xbl, ybl = lon_bds[..., 0], lat_bds[..., 0]
- #
- # Replace quiver here with delta-based lineplot
- #
- urd = xbl + deg_scale * u0r
- vrd = ybl + deg_scale * v0r * yscale
- for iy in range(ny):
- for ix in range(nx):
- plt.plot([xbl[iy, ix], urd[iy, ix]],
- [ybl[iy, ix], vrd[iy, ix]],
- ':', color='magenta', linewidth=2.5,
- transform=data_proj)
- # Show this is the SAME as lineplot
- plt.quiver(xbl, ybl, u0r, v0r * yscale,
- color='magenta', width=0.01,
- headwidth=1.2, # headlength=1.0, headaxislength=0.7,
- angles=angles,
- scale_units='xy', scale=scale,
- transform=data_proj)
-
- plt.suptitle('angles from "{}"'.format(cell_angle_boundpoints))
-
-# # Also draw small lines pointing at the correct (TRUE, not ) angle.
-# ny, nx = x0s.shape
-# size_degrees = 1.0
-# angles = angles_cube.copy()
-# angles.convert_units('radians')
-# angles = angles.data
-# lats = testcube.coord('latitude').copy()
-# lats.convert_units('radians')
-# lats = lats.points
-# dxs = size_degrees * u0.copy() #* np.cos(angles)
-# dys = size_degrees * u0.copy() # / np.sqrt(np.cos(lats))
-# x1s = x0s + dxs
-# y1s = y0s + dys
-## for iy in range(ny):
-## for ix in range(nx):
-## plt.plot([x0s[iy, ix], x1s[iy, ix]],
-## [y0s[iy, ix], y1s[iy, ix]],
-## 'o-', markersize=4., markeredgewidth=0.,
-## color='green', # scale_units='xy', scale=scale,
-## transform=data_proj)
-# plt.quiver(x0s, y0s, dxs, dys,
-# color='green', linewidth=0.2,
-# angles=angles,
-# scale_units='xy', scale=scale * 0.6,
-# transform=data_proj)
-
-
-
- ax.set_global()
- plt.show()
-
- angles_cube.convert_units('degrees')
-
- self.assertArrayAllClose(
- angles_cube.data,
- [[33.421, 17.928, 0., -17.928, -33.421],
- [41.981, 24.069, 0., -24.069, -41.981],
- [56.624, 37.809, 0., -37.809, -56.624],
- [79.940, 74.227, 0., -74.227, -79.940],
- [107.313, 126.361, -180., -126.361, -107.313]],
- atol=0.002)
-
-
-if __name__ == "__main__":
- tests.main()
diff --git a/lib/iris/tests/unit/plot/test_2d_coords.py b/lib/iris/tests/unit/plot/test_2d_coords.py
index bb27341baa..7397921861 100644
--- a/lib/iris/tests/unit/plot/test_2d_coords.py
+++ b/lib/iris/tests/unit/plot/test_2d_coords.py
@@ -22,20 +22,25 @@
# Import iris.tests first so that some things can be initialised before
# importing anything else.
import iris.tests as tests
-import iris.coords as coords
import numpy.ma as ma
+import iris.coords as coords
from iris.tests.stock import simple_2d_w_multidim_coords as cube_2dcoords
from iris.tests.stock import simple_3d_w_multidim_coords as cube3d_2dcoords
-from iris.tests.stock import lat_lon_cube
+from iris.tests.stock import sample_2d_latlons
+from iris.tests.stock import make_bounds_discontiguous_at_point
-from orca_utils.plot_testing import testdata_2d_coords as testdata
if tests.MPL_AVAILABLE:
import iris.plot as iplt
+def full2d_global():
+ return sample_2d_latlons(transformed=True)
+
+
+@tests.skip_data
class Test_2d_coords_plot_defn_bound_mode(tests.IrisTest):
def setUp(self):
self.multidim_cube = cube_2dcoords()
@@ -43,8 +48,8 @@ def setUp(self):
# latlon_2d is a cube with 2d coords, 4 bounds per point,
# discontiguities in the bounds but masked data at the discontiguities.
- self.latlon_2d = testdata.full2d_global()
- testdata.make_bounds_discontiguous_at_point(self.latlon_2d, 2, 2)
+ self.latlon_2d = full2d_global()
+ make_bounds_discontiguous_at_point(self.latlon_2d, 2, 2)
# # Take a latlon cube with 1D coords, broadcast the coords into 2D
# # ones, then add ONE of them back into the cube in place of original:
@@ -106,9 +111,10 @@ def test_total_span_check(self):
# # TODO Find out where I can put a catch for this (if necessary)
# cube = self.mixed_dims
# with self.assertRaises(ValueError):
- # iplt._get_plot_defn_custom_coords_picked(cube,
- # ('latitude', 'longitude'),
- # self.mode)
+ # iplt._get_plot_defn_custom_coords_picked(
+ # cube,
+ # ('latitude', 'longitude'),
+ # self.mode)
def test_map_common_not_enough_bounds(self):
# Test that a lat-lon cube with 2d coords and 2 bounds per point
@@ -129,16 +135,16 @@ def test_map_common_2d(self):
result = iplt._map_common('pcolor', None, self.mode, cube, plot_defn)
self.assertTrue(result)
- # def test_discontiguous_masked(self):
- # # Test that a contiguity check will raise a warning (not an error) for
- # # discontiguous bounds but appropriately masked data.
- # cube = self.latlon_2d
- # coord = cube.coord('longitude')
- # msg = 'The bounds of the longitude coordinate are not contiguous. ' \
- # 'However, data is masked where the discontiguity occurs so ' \
- # 'plotting anyway.'
- # with self.assertWarnsRegexp(msg):
- # iplt._check_contiguity_and_bounds(coord, cube.data)
+# def test_discontiguous_masked(self):
+# # Test that a contiguity check will raise a warning (not an error) for
+# # discontiguous bounds but appropriately masked data.
+# cube = self.latlon_2d
+# coord = cube.coord('longitude')
+# msg = 'The bounds of the longitude coordinate are not contiguous. ' \
+# 'However, data is masked where the discontiguity occurs so ' \
+# 'plotting anyway.'
+# with self.assertWarnsRegexp(msg):
+# iplt._check_contiguity_and_bounds(coord, cube.data)
def test_discontiguous_unmasked(self):
# Check that an error occurs when the contiguity check finds
@@ -155,3 +161,7 @@ def test_draw_2d_from_bounds(self):
cube = self.latlon_2d
result = iplt._draw_2d_from_bounds('pcolormesh', cube)
self.assertTrue(result)
+
+
+if __name__ == '__main__':
+ tests.main()
From 7a9cb5c6555f735c48d8d6232b50cf4d6cbbc748 Mon Sep 17 00:00:00 2001
From: hdyson
Date: Tue, 28 Aug 2018 12:34:05 +0100
Subject: [PATCH 23/62] Update pp save rules to handle time means (#3132)
---
lib/iris/fileformats/pp_save_rules.py | 9 +-
lib/iris/tests/test_cube_to_pp.py | 6 +-
.../tests/unit/fileformats/pp/test_save.py | 140 +++++++++++++++++-
3 files changed, 150 insertions(+), 5 deletions(-)
diff --git a/lib/iris/fileformats/pp_save_rules.py b/lib/iris/fileformats/pp_save_rules.py
index 84b4980647..5323311061 100644
--- a/lib/iris/fileformats/pp_save_rules.py
+++ b/lib/iris/fileformats/pp_save_rules.py
@@ -174,7 +174,14 @@ def _general_time_rules(cube, pp):
if (time_coord is not None and
time_coord.has_bounds() and
clim_season_coord is None and
- (fp_coord is not None or frt_coord is not None) and
+ cm_time_mean is not None):
+ pp.lbtim.ib = 2
+ pp.t1 = time_coord.units.num2date(time_coord.bounds[0, 0])
+ pp.t2 = time_coord.units.num2date(time_coord.bounds[0, 1])
+
+ if (time_coord is not None and
+ time_coord.has_bounds() and
+ clim_season_coord is None and
cm_time_mean is not None and
cm_time_mean.intervals != () and
cm_time_mean.intervals[0].endswith('hour')):
diff --git a/lib/iris/tests/test_cube_to_pp.py b/lib/iris/tests/test_cube_to_pp.py
index fa78f95166..46045fb55d 100644
--- a/lib/iris/tests/test_cube_to_pp.py
+++ b/lib/iris/tests/test_cube_to_pp.py
@@ -1,4 +1,4 @@
-# (C) British Crown Copyright 2010 - 2017, Met Office
+# (C) British Crown Copyright 2010 - 2018, Met Office
#
# This file is part of Iris.
#
@@ -294,8 +294,8 @@ def test_lbvc(self):
self.assertEqual(field.lbvc, lbvc)
self.assertEqual(field.lblev, lblev)
self.assertEqual(field.blev, blev)
-
-
+
+
def fields_from_cube(cubes):
"""
Return an iterator of PP fields generated from saving the given cube(s)
diff --git a/lib/iris/tests/unit/fileformats/pp/test_save.py b/lib/iris/tests/unit/fileformats/pp/test_save.py
index 0784132915..081e01fcf9 100644
--- a/lib/iris/tests/unit/fileformats/pp/test_save.py
+++ b/lib/iris/tests/unit/fileformats/pp/test_save.py
@@ -19,6 +19,9 @@
from __future__ import (absolute_import, division, print_function)
from six.moves import (filter, input, map, range, zip) # noqa
+import cftime
+import cf_units
+
# Import iris.tests first so that some things can be initialised before
# importing anything else.
import iris.tests as tests
@@ -26,7 +29,7 @@
from iris.coords import DimCoord, CellMethod
from iris.fileformats._ff_cross_references import STASH_TRANS
import iris.fileformats.pp as pp
-from iris.fileformats.pp_save_rules import _lbproc_rules
+from iris.fileformats.pp_save_rules import _lbproc_rules, verify
from iris.tests import mock
import iris.tests.stock as stock
@@ -198,5 +201,140 @@ def test_maximum(self):
self.assertEqual(lbproc, 8192)
+class TestTimeMean(tests.IrisTest):
+ '''
+ Tests that time mean cell method is converted to pp appropriately.
+
+ Pattern is pairs of tests - one with time mean method, and one without, to
+ show divergent behaviour.
+
+ '''
+ def test_t1_time_mean(self):
+ cube = _get_single_time_cube(set_time_mean=True)
+ tc = cube.coord(axis='t')
+ expected = tc.units.num2date(0)
+
+ with mock.patch('iris.fileformats.pp.PPField3',
+ autospec=True) as pp_field:
+ verify(cube, pp_field)
+ actual = pp_field.t1
+
+ self.assertEqual(expected, actual)
+
+ def test_t1_no_time_mean(self):
+ cube = _get_single_time_cube()
+ tc = cube.coord(axis='t')
+ expected = tc.units.num2date(15)
+
+ with mock.patch('iris.fileformats.pp.PPField3',
+ autospec=True) as pp_field:
+ verify(cube, pp_field)
+ actual = pp_field.t1
+
+ self.assertEqual(expected, actual)
+
+ def test_t2_time_mean(self):
+ cube = _get_single_time_cube(set_time_mean=True)
+ tc = cube.coord(axis='t')
+ expected = tc.units.num2date(30)
+
+ with mock.patch('iris.fileformats.pp.PPField3',
+ autospec=True) as pp_field:
+ verify(cube, pp_field)
+ actual = pp_field.t2
+
+ self.assertEqual(expected, actual)
+
+ def test_t2_no_time_mean(self):
+ cube = _get_single_time_cube(set_time_mean=False)
+ expected = cftime.datetime(0, 0, 0)
+
+ with mock.patch('iris.fileformats.pp.PPField3',
+ autospec=True) as pp_field:
+ verify(cube, pp_field)
+ actual = pp_field.t2
+ self.assertEqual(expected, actual)
+
+ def test_lbft_no_forecast_time(self):
+ # Different pattern here: checking that lbft hasn't been changed from
+ # the default value.
+ cube = _get_single_time_cube()
+ mock_lbft = mock.sentinel.lbft
+
+ with mock.patch('iris.fileformats.pp.PPField3',
+ autospec=True) as pp_field:
+ pp_field.lbft = mock_lbft
+ verify(cube, pp_field)
+ actual = pp_field.lbft
+
+ assert(mock_lbft is actual)
+
+ def test_lbtim_no_time_mean(self):
+ cube = _get_single_time_cube()
+ expected_ib = 0
+ expected_ic = 2 # 360 day calendar
+
+ with mock.patch('iris.fileformats.pp.PPField3',
+ autospec=True) as pp_field:
+ verify(cube, pp_field)
+ actual_ib = pp_field.lbtim.ib
+ actual_ic = pp_field.lbtim.ic
+
+ self.assertEqual(expected_ib, actual_ib)
+ self.assertEqual(expected_ic, actual_ic)
+
+ def test_lbtim_time_mean(self):
+ cube = _get_single_time_cube(set_time_mean=True)
+ expected_ib = 2 # Time mean
+ expected_ic = 2 # 360 day calendar
+
+ with mock.patch('iris.fileformats.pp.PPField3',
+ autospec=True) as pp_field:
+ verify(cube, pp_field)
+ actual_ib = pp_field.lbtim.ib
+ actual_ic = pp_field.lbtim.ic
+
+ self.assertEqual(expected_ib, actual_ib)
+ self.assertEqual(expected_ic, actual_ic)
+
+ def test_lbproc_no_time_mean(self):
+ cube = _get_single_time_cube()
+ expected = 0
+
+ with mock.patch('iris.fileformats.pp.PPField3',
+ autospec=True) as pp_field:
+ verify(cube, pp_field)
+ actual = pp_field.lbproc
+
+ self.assertEqual(expected, actual)
+
+ def test_lbproc_time_mean(self):
+ cube = _get_single_time_cube(set_time_mean=True)
+ expected = 128
+
+ with mock.patch('iris.fileformats.pp.PPField3',
+ autospec=True) as pp_field:
+ verify(cube, pp_field)
+ actual = pp_field.lbproc
+
+ self.assertEqual(expected, actual)
+
+
+def _get_single_time_cube(set_time_mean=False):
+ cube = stock.realistic_3d()[0:1, :, :]
+ cube.remove_coord('time')
+ cube.remove_coord('forecast_period')
+ tc = DimCoord(
+ points=[15, ],
+ standard_name='time',
+ units=cf_units.Unit('days since epoch', calendar='360_day'),
+ bounds=[[0, 30], ],
+ )
+ cube.add_dim_coord(tc, 0)
+ if set_time_mean:
+ cube.cell_methods = (CellMethod("mean", coords='time'), )
+ return cube
+
+
if __name__ == "__main__":
tests.main()
From 5de040fc60c2cad69ce8e8c9cc3d7bd4c1569bfb Mon Sep 17 00:00:00 2001
From: Patrick Peglar
Date: Wed, 29 Aug 2018 10:35:06 +0100
Subject: [PATCH 24/62] Vector plots 2 (#3120)
* Small improvements; first sensible tests.
* Enhanced testing; better checking and crs awareness in grid_angles routine.
* Remove crud from test_gridcell_angles.
* Use degree units for everything in _grid_angles.
* Make assertArrayAllClose print details when it fails.
* Rework and extend testing for gridcell_angles.
* Fix assertArrayAllClose; remove debug code from test_gridcell_angles.
* Remove obsolete assignments.
* Remove obsolete code.
* Small comment improvements.
* Attempt to clarify docstrings of low-level routines.
* More tests, and some functional fixes.
* Codestyle fixes.
* Review changes + fixes.
* Avoid using sample data.
---
lib/iris/analysis/_grid_angles.py | 281 +++++++++------
lib/iris/analysis/cartography.py | 5 +-
lib/iris/tests/__init__.py | 18 +-
lib/iris/tests/stock/_stock_2d_latlons.py | 16 +-
.../cartography/test_gridcell_angles.py | 327 ++++++++++++++++++
5 files changed, 526 insertions(+), 121 deletions(-)
create mode 100644 lib/iris/tests/unit/analysis/cartography/test_gridcell_angles.py
diff --git a/lib/iris/analysis/_grid_angles.py b/lib/iris/analysis/_grid_angles.py
index ffe6d51c7f..90876840af 100644
--- a/lib/iris/analysis/_grid_angles.py
+++ b/lib/iris/analysis/_grid_angles.py
@@ -24,6 +24,7 @@
import numpy as np
+import cartopy.crs as ccrs
import iris
@@ -33,12 +34,16 @@ def _3d_xyz_from_latlon(lon, lat):
Args:
- * lon, lat: (arrays in degrees)
+ * lon, lat: (float array)
+ Arrays of longitudes and latitudes, in degrees.
+ Both the same shape.
Returns:
- xyz : (array, dtype=float64)
- cartesian coordinates on a unit sphere. Dimension 0 maps x,y,z.
+ * xyz : (array, dtype=float64)
+ Cartesian coordinates on a unit sphere.
+ Shape is (3, ).
+ The x / y / z coordinates are in xyz[0 / 1 / 2].
"""
lon1 = np.deg2rad(lon).astype(np.float64)
@@ -60,91 +65,87 @@ def _latlon_from_xyz(xyz):
Args:
* xyz: (array)
- positions array, of dims (3, ), where index 0 maps x/y/z.
+ Array of 3-D cartesian coordinates.
+ Shape (3, ).
+ x / y / z values are in xyz[0 / 1 / 2],
Returns:
- lonlat : (array)
- spherical angles, of dims (2, ), in radians.
- Dim 0 maps longitude, latitude.
+ * lonlat : (array)
+ longitude and latitude position angles, in degrees.
+ Shape (2, ).
+ The longitudes / latitudes are in lonlat[0 / 1].
"""
- lons = np.arctan2(xyz[1], xyz[0])
- axial_radii = np.sqrt(xyz[0] * xyz[0] + xyz[1] * xyz[1])
- lats = np.arctan2(xyz[2], axial_radii)
+ lons = np.rad2deg(np.arctan2(xyz[1], xyz[0]))
+ radii = np.sqrt(np.sum(xyz * xyz, axis=0))
+ lats = np.rad2deg(np.arcsin(xyz[2] / radii))
return np.array([lons, lats])
def _angle(p, q, r):
"""
- Return angle (in _radians_) of grid wrt local east.
- Anticlockwise +ve, as usual.
- {P, Q, R} are consecutive points in the same row,
- eg {v(i,j),f(i,j),v(i+1,j)}, or {T(i-1,j),T(i,j),T(i+1,j)}
- Calculate dot product of PR with lambda_hat at Q.
- This gives us cos(required angle).
- Disciminate between +/- angles by comparing latitudes of P and R.
- p, q, r, are all 2-element arrays [lon, lat] of angles in degrees.
+ Estimate grid-angles to true-Eastward direction from positions in the same
+ grid row, but at increasing column (grid-Eastward) positions.
+
+ {P, Q, R} are locations of consecutive points in the same grid row.
+ These could be successive points in a single grid,
+ e.g. {T(i-1,j), T(i,j), T(i+1,j)}
+ or a mixture of U/V and T gridpoints if row positions are aligned,
+ e.g. {v(i,j), f(i,j), v(i+1,j)}.
+
+ Method:
+
+ Calculate dot product of a unit-vector parallel to P-->R, unit-scaled,
+ with the unit eastward (true longitude) vector at Q.
+ This value is cos(required angle).
+ Discriminate between +/- angles by comparing latitudes of P and R.
+ Return NaN where any P-->R are zero.
+
+ .. NOTE::
+
+ This method assumes that the vector PR is parallel to the surface
+ at the longitude of Q, as it uses the length of PR as the basis for
+ the cosine ratio.
+ That is only exact when Q is at the same longitude as the midpoint
+ of PR, and this typically causes errors which grow with increasing
+ gridcell angle.
+ However, we retain this method because it reproduces the "standard"
+ gridcell-orientation-angle arrays found in files output by the CICE
+ model, which presumably uses an equivalent calculation.
+
+ Args:
+
+ * p, q, r : (float array)
+ Arrays of angles, in degrees.
+ All the same shape.
+ Shape is (2, ).
+ Longitudes / latitudes are in array[0 / 1].
+
+ Returns:
+
+ * angle : (float array)
+ Grid angles relative to true-East, in degrees.
+ Positive when grid-East is anticlockwise from true-East.
+ Shape is same as .
"""
-# old_style = True
- old_style = False
- if old_style:
- mid_lons = np.deg2rad(q[0])
+ mid_lons = np.deg2rad(q[0])
- pr = _3d_xyz_from_latlon(r[0], r[1]) - _3d_xyz_from_latlon(p[0], p[1])
- pr_norm = np.sqrt(np.sum(pr**2, axis=0))
- pr_top = pr[1] * np.cos(mid_lons) - pr[0] * np.sin(mid_lons)
+ pr = _3d_xyz_from_latlon(r[0], r[1]) - _3d_xyz_from_latlon(p[0], p[1])
+ pr_norm = np.sqrt(np.sum(pr**2, axis=0))
+ pr_top = pr[1] * np.cos(mid_lons) - pr[0] * np.sin(mid_lons)
- index = pr_norm == 0
- pr_norm[index] = 1
+ index = pr_norm == 0
+ pr_norm[index] = 1
- cosine = np.maximum(np.minimum(pr_top / pr_norm, 1), -1)
- cosine[index] = 0
+ cosine = np.maximum(np.minimum(pr_top / pr_norm, 1), -1)
+ cosine[index] = 0
- psi = np.arccos(cosine) * np.sign(r[1] - p[1])
- psi[index] = np.nan
- else:
- # Calculate unit vectors.
- midpt_lons, midpt_lats = q[0], q[1]
- lmb_r, phi_r = (np.deg2rad(arr) for arr in (midpt_lons, midpt_lats))
- phi_hatvec_x = -np.sin(phi_r) * np.cos(lmb_r)
- phi_hatvec_y = -np.sin(phi_r) * np.sin(lmb_r)
- phi_hatvec_z = np.cos(phi_r)
- shape_xyz = (1,) + midpt_lons.shape
- phi_hatvec = np.concatenate([arr.reshape(shape_xyz)
- for arr in (phi_hatvec_x,
- phi_hatvec_y,
- phi_hatvec_z)])
- lmb_hatvec_z = np.zeros(midpt_lons.shape)
- lmb_hatvec_y = np.cos(lmb_r)
- lmb_hatvec_x = -np.sin(lmb_r)
- lmb_hatvec = np.concatenate([arr.reshape(shape_xyz)
- for arr in (lmb_hatvec_x,
- lmb_hatvec_y,
- lmb_hatvec_z)])
-
- pr = _3d_xyz_from_latlon(r[0], r[1]) - _3d_xyz_from_latlon(p[0], p[1])
-
- # Dot products to form true-northward / true-eastward projections.
- pr_cmpt_e = np.sum(pr * lmb_hatvec, axis=0)
- pr_cmpt_n = np.sum(pr * phi_hatvec, axis=0)
- psi = np.arctan2(pr_cmpt_n, pr_cmpt_e)
-
- # TEMPORARY CHECKS:
- # ensure that the two unit vectors are perpendicular.
- dotprod = np.sum(phi_hatvec * lmb_hatvec, axis=0)
- assert np.allclose(dotprod, 0.0)
- # ensure that the vector components carry the original magnitude.
- mag_orig = np.sum(pr * pr)
- mag_rot = np.sum(pr_cmpt_e * pr_cmpt_e) + np.sum(pr_cmpt_n * pr_cmpt_n)
- rtol = 1.e-3
- check = np.allclose(mag_rot, mag_orig, rtol=rtol)
- if not check:
- print(mag_rot, mag_orig)
- assert np.allclose(mag_rot, mag_orig, rtol=rtol)
-
- return psi
+ psi = np.arccos(cosine) * np.sign(r[1] - p[1])
+ psi[index] = np.nan
+
+ return np.rad2deg(psi)
def gridcell_angles(x, y=None, cell_angle_boundpoints='mid-lhs, mid-rhs'):
@@ -201,12 +202,18 @@ def gridcell_angles(x, y=None, cell_angle_boundpoints='mid-lhs, mid-rhs'):
angles : (2-dimensional cube)
Cube of angles of grid-x vector from true Eastward direction for
- each gridcell, in radians.
- It also has longitude and latitude coordinates. If coordinates
- were input the output has identical ones : If the input was 2d
- arrays, the output coords have no bounds; or, if the input was 3d
- arrays, the output coords have bounds and centrepoints which are
- the average of the 4 bounds.
+ each gridcell, in degrees.
+ It also has "true" longitude and latitude coordinates, with no
+ coordinate system.
+ When the input has coords, then the output ones are identical if
+ the inputs are true-latlons, otherwise they are transformed
+ true-latlon versions.
+ When the input has bounded coords, then the output coords have
+ matching bounds and centrepoints (possibly transformed).
+ When the input is 2d arrays, or has unbounded coords, then the
+ output coords have matching points and no bounds.
+ When the input is 3d arrays, then the output coords have matching
+ bounds, and the centrepoints are an average of the 4 boundpoints.
"""
cube = None
@@ -216,55 +223,105 @@ def gridcell_angles(x, y=None, cell_angle_boundpoints='mid-lhs, mid-rhs'):
x, y = cube.coord(axis='x'), cube.coord(axis='y')
# Now should have either 2 coords or 2 arrays.
- if not hasattr(x, 'shape') and hasattr(y, 'shape'):
+ if not hasattr(x, 'shape') or not hasattr(y, 'shape'):
msg = ('Inputs (x,y) must have array shape property.'
'Got type(x)={} and type(y)={}.')
raise ValueError(msg.format(type(x), type(y)))
x_coord, y_coord = None, None
if hasattr(x, 'bounds') and hasattr(y, 'bounds'):
+ # x and y are Coords.
x_coord, y_coord = x.copy(), y.copy()
- x_coord.convert_units('degrees')
- y_coord.convert_units('degrees')
+
+ # They must be angles : convert into degrees
+ for coord in (x_coord, y_coord):
+ if not coord.units.is_convertible('degrees'):
+ msg = ('Input X and Y coordinates must have angular '
+ 'units. Got units of "{!s}" and "{!s}".')
+ raise ValueError(msg.format(x_coord.units, y_coord.units))
+ coord.convert_units('degrees')
+
if x_coord.ndim != 2 or y_coord.ndim != 2:
- msg = ('Coordinate inputs must have 2-dimensional shape. ',
+ msg = ('Coordinate inputs must have 2-dimensional shape. '
'Got x-shape of {} and y-shape of {}.')
raise ValueError(msg.format(x_coord.shape, y_coord.shape))
if x_coord.shape != y_coord.shape:
- msg = ('Coordinate inputs must have same shape. ',
+ msg = ('Coordinate inputs must have same shape. '
'Got x-shape of {} and y-shape of {}.')
raise ValueError(msg.format(x_coord.shape, y_coord.shape))
-# NOTE: would like to check that dims are in correct order, but can't do that
-# if there is no cube.
-# TODO: **document** -- another input format requirement
-# x_dims, y_dims = (cube.coord_dims(co) for co in (x_coord, y_coord))
-# if x_dims != (0, 1) or y_dims != (0, 1):
-# msg = ('Coordinate inputs must map to cube dimensions (0, 1). ',
-# 'Got x-dims of {} and y-dims of {}.')
-# raise ValueError(msg.format(x_dims, y_dims))
+ if cube:
+ x_dims, y_dims = (cube.coord_dims(co) for co in (x, y))
+ if x_dims != y_dims:
+ msg = ('X and Y coordinates must have the same cube '
+ 'dimensions. Got x-dims = {} and y-dims = {}.')
+ raise ValueError(msg.format(x_dims, y_dims))
+ cs = x_coord.coord_system
+ if y_coord.coord_system != cs:
+ msg = ('Coordinate inputs must have same coordinate system. '
+ 'Got x of {} and y of {}.')
+ raise ValueError(msg.format(cs, y_coord.coord_system))
+
+ # Base calculation on bounds if we have them, or points as a fallback.
if x_coord.has_bounds() and y_coord.has_bounds():
x, y = x_coord.bounds, y_coord.bounds
else:
x, y = x_coord.points, y_coord.points
+ # Make sure these arrays are ordinary lats+lons, in degrees.
+ if cs is not None:
+ # Transform points into true lats + lons.
+ crs_src = cs.as_cartopy_crs()
+ crs_pc = ccrs.PlateCarree()
+
+ def transform_xy_arrays(x, y):
+ # Note: flatten, as transform_points is limited to 2D arrays.
+ shape = x.shape
+ x, y = (arr.flatten() for arr in (x, y))
+ pts = crs_pc.transform_points(crs_src, x, y)
+ x = pts[..., 0].reshape(shape)
+ y = pts[..., 1].reshape(shape)
+ return x, y
+
+ # Transform the main reference points into standard lats+lons.
+ x, y = transform_xy_arrays(x, y)
+
+ # Likewise replace the original coordinates with transformed ones,
+ # because the calculation also needs the centrepoint values.
+ xpts, ypts = (coord.points for coord in (x_coord, y_coord))
+ xbds, ybds = (coord.bounds for coord in (x_coord, y_coord))
+ xpts, ypts = transform_xy_arrays(xpts, ypts)
+ xbds, ybds = transform_xy_arrays(xbds, ybds)
+ x_coord = iris.coords.AuxCoord(
+ points=xpts, bounds=xbds,
+ standard_name='longitude', units='degrees')
+ y_coord = iris.coords.AuxCoord(
+ points=ypts, bounds=ybds,
+ standard_name='latitude', units='degrees')
+
elif hasattr(x, 'bounds') or hasattr(y, 'bounds'):
# One was a Coord, and the other not ?
is_and_not = ('x', 'y')
if hasattr(y, 'bounds'):
is_and_not = reversed(is_and_not)
msg = 'Input {!r} is a Coordinate, but {!r} is not.'
- raise ValueError(*is_and_not)
+ raise ValueError(msg.format(*is_and_not))
- # Now have either 2 points arrays or 2 bounds arrays.
- # Construct (lhs, mid, rhs) where these represent 3 adjacent points with
- # increasing longitudes.
+ # Now have either 2 points arrays (ny, nx) or 2 bounds arrays (ny, nx, 4).
+ # Construct (lhs, mid, rhs) where these represent 3 points at increasing
+ # grid-x indices (columns).
+ # Also make suitable X and Y coordinates for the result cube.
if x.ndim == 2:
- # PROBLEM: we can't use this if data is not full-longitudes,
- # i.e. rhs of array must connect to lhs (aka 'circular' coordinate).
- # But we have no means of checking that ?
+ # Data is points arrays.
+ # Use previous + subsequent points along grid-x-axis as references.
+
+ # PROBLEM: we assume that the rhs connects to the lhs, so we should
+ # really only use this if data is full-longitudes (as a 'circular'
+ # coordinate).
+ # This is mentioned in the docstring, but we have no general means of
+ # checking it.
- # Use previous + subsequent points along longitude-axis as references.
- # NOTE: we also have no way to check that dim #2 really is the 'X' dim.
+ # NOTE: we take the 2d grid as presented, so the second dimension is
+ # the 'X' dim. Again, that is implicit + can't be checked.
mid = np.array([x, y])
lhs = np.roll(mid, 1, 2)
rhs = np.roll(mid, -1, 2)
@@ -275,9 +332,11 @@ def gridcell_angles(x, y=None, cell_angle_boundpoints='mid-lhs, mid-rhs'):
x_coord = iris.coords.AuxCoord(y, standard_name='longitude',
units='degrees')
else:
- # Get lhs and rhs locations by averaging top+bottom each side.
+ # Data is bounds arrays.
+ # Use gridcell corners at different grid-x positions as references.
# NOTE: so with bounds, we *don't* need full circular longitudes.
xyz = _3d_xyz_from_latlon(x, y)
+ # Support two different choices of reference points locations.
angle_boundpoints_vals = {'mid-lhs, mid-rhs': '03_to_12',
'lower-left, lower-right': '0_to_1'}
bounds_pos = angle_boundpoints_vals.get(cell_angle_boundpoints)
@@ -294,8 +353,8 @@ def gridcell_angles(x, y=None, cell_angle_boundpoints='mid-lhs, mid-rhs'):
list(angle_boundpoints_vals.keys())))
if not x_coord:
# Create bounded coords for result cube.
- # Use average lhs+rhs points in 3d to get 'mid' points, as coords
- # with no points are not allowed.
+ # Use average of lhs+rhs points in 3d to get 'mid' points,
+ # as coords without points are not allowed.
mid_xyz = 0.5 * (lhs_xyz + rhs_xyz)
mid_latlons = _latlon_from_xyz(mid_xyz)
# Create coords with given bounds, and averaged centrepoints.
@@ -305,28 +364,30 @@ def gridcell_angles(x, y=None, cell_angle_boundpoints='mid-lhs, mid-rhs'):
y_coord = iris.coords.AuxCoord(
points=mid_latlons[1], bounds=y,
standard_name='latitude', units='degrees')
+
# Convert lhs and rhs points back to latlon form -- IN DEGREES !
- lhs = np.rad2deg(_latlon_from_xyz(lhs_xyz))
- rhs = np.rad2deg(_latlon_from_xyz(rhs_xyz))
- # mid is coord.points, whether input or made up.
+ lhs = _latlon_from_xyz(lhs_xyz)
+ rhs = _latlon_from_xyz(rhs_xyz)
+ # 'mid' is coord.points, whether from input or just made up.
mid = np.array([x_coord.points, y_coord.points])
# Do the angle calcs, and return as a suitable cube.
angles = _angle(lhs, mid, rhs)
result = iris.cube.Cube(angles,
long_name='gridcell_angle_from_true_east',
- units='radians')
+ units='degrees')
result.add_aux_coord(x_coord, (0, 1))
result.add_aux_coord(y_coord, (0, 1))
return result
-def true_vectors_from_grid_vectors(u_cube, v_cube,
- grid_angles_cube=None,
- grid_angles_kwargs=None):
+def rotate_grid_vectors(u_cube, v_cube, grid_angles_cube=None,
+ grid_angles_kwargs=None):
"""
Rotate distance vectors from grid-oriented to true-latlon-oriented.
+ Can also rotate by arbitrary angles, if they are passed in.
+
.. Note::
This operation overlaps somewhat in function with
diff --git a/lib/iris/analysis/cartography.py b/lib/iris/analysis/cartography.py
index dadcdedc86..a778f5f846 100644
--- a/lib/iris/analysis/cartography.py
+++ b/lib/iris/analysis/cartography.py
@@ -37,10 +37,7 @@
import iris.coord_systems
import iris.exceptions
from iris.util import _meshgrid
-from ._grid_angles import (
- gridcell_angles,
- true_vectors_from_grid_vectors as rotate_grid_vectors)
-
+from ._grid_angles import gridcell_angles, rotate_grid_vectors
# List of contents to control Sphinx autodocs.
# Unfortunately essential to get docs for the grid_angles functions.
diff --git a/lib/iris/tests/__init__.py b/lib/iris/tests/__init__.py
index 710a3fbac6..7550fce1ca 100644
--- a/lib/iris/tests/__init__.py
+++ b/lib/iris/tests/__init__.py
@@ -663,7 +663,23 @@ def assertArrayAllClose(self, a, b, rtol=1.0e-7, atol=0.0, **kwargs):
For full details see underlying routine numpy.testing.assert_allclose.
"""
- np.testing.assert_allclose(a, b, rtol=rtol, atol=atol, **kwargs)
+ ok = np.allclose(a, b, atol=atol, rtol=rtol, equal_nan=True)
+ if not ok:
+ # Calculate errors above a pointwise tolerance : The method is
+ # taken from "numpy.core.numeric.isclose".
+ errors = (np.abs(a-b) - atol + rtol * np.abs(b))
+ worst_inds = np.unravel_index(np.argmax(errors.flat), errors.shape)
+ # Build a more useful message than from np.testing.assert_allclose.
+ msg = ('\nARRAY CHECK FAILED "assertArrayAllClose" :'
+ '\n with shapes={} {}, atol={}, rtol={}'
+ '\n worst at element {} : a={} b={}'
+ '\n absolute error ~{:.3g}, equivalent to rtol ~{:.3e}')
+ aval, bval = a[worst_inds], b[worst_inds]
+ absdiff = np.abs(aval - bval)
+ equiv_rtol = absdiff / bval
+ raise AssertionError(msg.format(
+ a.shape, b.shape, atol, rtol, worst_inds, aval, bval, absdiff,
+ equiv_rtol))
@contextlib.contextmanager
def temp_filename(self, suffix=''):
diff --git a/lib/iris/tests/stock/_stock_2d_latlons.py b/lib/iris/tests/stock/_stock_2d_latlons.py
index 75b62f31ba..395a50d8ea 100644
--- a/lib/iris/tests/stock/_stock_2d_latlons.py
+++ b/lib/iris/tests/stock/_stock_2d_latlons.py
@@ -233,18 +233,19 @@ def sample_cube(xargs, yargs):
cube.add_dim_coord(co_x, 1)
return cube
+ # Start by making a "normal" cube with separate 1-D X and Y coords.
if regional:
- # Extract small region.
+ # Make a small regional cube.
cube = sample_cube(xargs=(150., 243.75, 6), yargs=(-10., 40., 5))
- # Make contiguous bounds.
+ # Add contiguous bounds.
for ax in ('x', 'y'):
cube.coord(axis=ax).guess_bounds()
else:
- # Global data, but drastically reduced resolution.
+ # Global data, but at a drastically reduced resolution.
cube = sample_cube(xargs=(37.5, 318.75, 6), yargs=(-85., 65., 5))
- # Patch bounds to ensure it is still contiguous + global.
+ # Make contiguous bounds and adjust outer edges to ensure it is global.
for name in ('longitude', 'latitude'):
coord = cube.coord(name)
coord.guess_bounds()
@@ -258,8 +259,11 @@ def sample_cube(xargs, yargs):
bds[-1, 1] = 90.0
coord.bounds = bds
- # Get 1d coordinate points + bounds + calculate 2d equivalents.
+ # Now convert the 1-d coords to 2-d equivalents.
+ # Get original 1-d coords.
co_1d_x, co_1d_y = [cube.coord(axis=ax).copy() for ax in ('x', 'y')]
+
+ # Calculate 2-d equivalents.
co_2d_x, co_2d_y = grid_coords_2d_from_1d(co_1d_x, co_1d_y)
# Remove the old grid coords.
@@ -271,7 +275,7 @@ def sample_cube(xargs, yargs):
cube.add_aux_coord(coord, (0, 1))
if transformed or rotated:
- # Take the lats + lons as being in a rotated coord system.
+ # Put the cube locations into a rotated coord system.
pole_lat, pole_lon = 75.0, 120.0
if transformed:
# Reproject coordinate values from rotated to true lat-lons.
diff --git a/lib/iris/tests/unit/analysis/cartography/test_gridcell_angles.py b/lib/iris/tests/unit/analysis/cartography/test_gridcell_angles.py
new file mode 100644
index 0000000000..4a1344e83d
--- /dev/null
+++ b/lib/iris/tests/unit/analysis/cartography/test_gridcell_angles.py
@@ -0,0 +1,327 @@
+# (C) British Crown Copyright 2018, Met Office
+#
+# This file is part of Iris.
+#
+# Iris is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Iris is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Iris. If not, see .
+"""
+Unit tests for the function
+:func:`iris.analysis.cartography.gridcell_angles`.
+
+"""
+from __future__ import (absolute_import, division, print_function)
+from six.moves import (filter, input, map, range, zip) # noqa
+
+# Import iris.tests first so that some things can be initialised before
+# importing anything else.
+import iris.tests as tests
+
+import numpy as np
+
+from cf_units import Unit
+from iris.cube import Cube
+from iris.coords import AuxCoord
+
+from iris.analysis.cartography import gridcell_angles
+from iris.tests.stock import sample_2d_latlons, lat_lon_cube
+
+
+def _2d_multicells_testcube(cellsize_degrees=1.0):
+ """
+ Create a test cube with a grid of X and Y points, where each gridcell
+ is independent (disjoint), arranged at an angle == the x-coord point.
+
+ """
+ # Setup np.linspace arguments to make the coordinate points.
+ x0, x1, nx = -164, 164, 9
+ y0, y1, ny = -75, 75, 7
+
+ lats = np.linspace(y0, y1, ny, endpoint=True)
+ lons_angles = np.linspace(x0, x1, nx, endpoint=True)
+ x_pts_2d, y_pts_2d = np.meshgrid(lons_angles, lats)
+
+ # Make gridcells rectangles surrounding these centrepoints, but also
+ # tilted at various angles (= same as x-point lons, as that's easy).
+
+ # Calculate centrepoint lons+lats : in radians, and shape (ny, nx, 1).
+ xangs, yangs = np.deg2rad(x_pts_2d), np.deg2rad(y_pts_2d)
+ xangs, yangs = [arr[..., None] for arr in (xangs, yangs)]
+ # Program which corners are up+down on each gridcell axis.
+ dx_corners = [[[-1, 1, 1, -1]]]
+ dy_corners = [[[-1, -1, 1, 1]]]
+ # Calculate the relative offsets in x+y at the 4 corners.
+ x_ofs_2d = cellsize_degrees * np.cos(xangs) * dx_corners
+ x_ofs_2d -= cellsize_degrees * np.sin(xangs) * dy_corners
+ y_ofs_2d = cellsize_degrees * np.cos(xangs) * dy_corners
+ y_ofs_2d += cellsize_degrees * np.sin(xangs) * dx_corners
+ # Apply a latitude stretch to make correct angles on the globe.
+ y_ofs_2d *= np.cos(yangs)
+ # Make bounds arrays by adding the corner offsets to the centrepoints.
+ x_bds_2d = x_pts_2d[..., None] + x_ofs_2d
+ y_bds_2d = y_pts_2d[..., None] + y_ofs_2d
+
+ # Create a cube with these points + bounds in its 'X' and 'Y' coords.
+ co_x = AuxCoord(points=x_pts_2d, bounds=x_bds_2d,
+ standard_name='longitude', units='degrees')
+ co_y = AuxCoord(points=y_pts_2d, bounds=y_bds_2d,
+ standard_name='latitude', units='degrees')
+ cube = Cube(np.zeros((ny, nx)))
+ cube.add_aux_coord(co_x, (0, 1))
+ cube.add_aux_coord(co_y, (0, 1))
+ return cube
+
+
+class TestGridcellAngles(tests.IrisTest):
+ def setUp(self):
+ # Make a small "normal" contiguous-bounded cube to test on.
+ # This one is regional.
+ self.standard_regional_cube = sample_2d_latlons(
+ regional=True, transformed=True)
+ # Record the standard correct angle answers.
+ result_cube = gridcell_angles(self.standard_regional_cube)
+ result_cube.convert_units('degrees')
+ self.standard_result_cube = result_cube
+ self.standard_small_cube_results = result_cube.data
+
+ def _check_multiple_orientations_and_latitudes(self,
+ method='mid-lhs, mid-rhs',
+ atol_degrees=0.005,
+ cellsize_degrees=1.0):
+
+ cube = _2d_multicells_testcube(cellsize_degrees=cellsize_degrees)
+
+ # Calculate gridcell angles at each point.
+ angles_cube = gridcell_angles(cube, cell_angle_boundpoints=method)
+
+ # Check that the results are a close match to the original intended
+ # gridcell orientation angles.
+ # NOTE: neither the above gridcell construction nor the calculation
+ # itself are exact : Errors scale as the square of gridcell sizes.
+ angles_cube.convert_units('degrees')
+ angles_calculated = angles_cube.data
+
+ # Note: the gridcell angles **should** just match the longitudes at
+ # each point
+ angles_expected = cube.coord('longitude').points
+
+ # Wrap both into standard range for comparison.
+ angles_calculated = (angles_calculated + 360.) % 360.
+ angles_expected = (angles_expected + 360.) % 360.
+
+ # Assert (toleranced) equality, and return results.
+ self.assertArrayAllClose(angles_calculated, angles_expected,
+ atol=atol_degrees)
+
+ return angles_calculated, angles_expected
+
+ def test_various_orientations_and_locations(self):
+ self._check_multiple_orientations_and_latitudes()
+
+ def test_result_form(self):
+ # Check properties of the result cube *other than* the data values.
+ test_cube = self.standard_regional_cube
+ result_cube = self.standard_result_cube
+ self.assertEqual(result_cube.long_name,
+ 'gridcell_angle_from_true_east')
+ self.assertEqual(result_cube.units, Unit('degrees'))
+ self.assertEqual(len(result_cube.coords()), 2)
+ self.assertEqual(result_cube.coord(axis='x'),
+ test_cube.coord(axis='x'))
+ self.assertEqual(result_cube.coord(axis='y'),
+ test_cube.coord(axis='y'))
+
+ def test_bottom_edge_method(self):
+ # Get results with the "other" calculation method + check to tolerance.
+ # A smallish cellsize should yield similar results in both cases.
+ r1, _ = self._check_multiple_orientations_and_latitudes()
+ r2, _ = self._check_multiple_orientations_and_latitudes(
+ method='lower-left, lower-right',
+ cellsize_degrees=0.1, atol_degrees=0.1)
+
+ # Not *exactly* the same : this checks we tested the 'other' method !
+ self.assertFalse(np.allclose(r1, r2))
+ # Note: results are a bit different in places. This is acceptable.
+ self.assertArrayAllClose(r1, r2, atol=0.1)
+
+ def test_bounded_coord_args(self):
+ # Check that passing the coords gives the same result as the cube.
+ co_x, co_y = (self.standard_regional_cube.coord(axis=ax)
+ for ax in ('x', 'y'))
+ result = gridcell_angles(co_x, co_y)
+ self.assertArrayAllClose(result.data,
+ self.standard_small_cube_results)
+
+ def test_coords_radians_args(self):
+ # Check it still works with coords converted to radians.
+ co_x, co_y = (self.standard_regional_cube.coord(axis=ax)
+ for ax in ('x', 'y'))
+ for coord in (co_x, co_y):
+ coord.convert_units('radians')
+ result = gridcell_angles(co_x, co_y)
+ self.assertArrayAllClose(result.data,
+ self.standard_small_cube_results)
+
+ def test_bounds_array_args(self):
+ # Check we can calculate from bounds values alone.
+ co_x, co_y = (self.standard_regional_cube.coord(axis=ax)
+ for ax in ('x', 'y'))
+ # Results drawn from coord bounds should be nearly the same,
+ # but not exactly, because of the different 'midpoint' values.
+ result = gridcell_angles(co_x.bounds, co_y.bounds)
+ self.assertArrayAllClose(result.data,
+ self.standard_small_cube_results, atol=0.1)
+
+ def test_unbounded_regional_coord_args(self):
+ # Remove the coord bounds to check points-based calculation.
+ co_x, co_y = (self.standard_regional_cube.coord(axis=ax)
+ for ax in ('x', 'y'))
+ for coord in (co_x, co_y):
+ coord.bounds = None
+ result = gridcell_angles(co_x, co_y)
+ # Note: in this case, we can expect the leftmost and rightmost columns
+ # to be rubbish, because the data is not global.
+ # But the rest should match okay.
+ self.assertArrayAllClose(result.data[:, 1:-1],
+ self.standard_small_cube_results[:, 1:-1])
+
+ def test_points_array_args(self):
+ # Check we can calculate from points arrays alone (no coords).
+ co_x, co_y = (self.standard_regional_cube.coord(axis=ax)
+ for ax in ('x', 'y'))
+ # As previous, the leftmost and rightmost columns are not good.
+ result = gridcell_angles(co_x.points, co_y.points)
+ self.assertArrayAllClose(result.data[:, 1:-1],
+ self.standard_small_cube_results[:, 1:-1])
+
+ def test_unbounded_global(self):
+ # For a contiguous global grid, a result based on points, i.e. with the
+ # bounds removed, should be a reasonable match for the 'ideal' one
+ # based on the bounds.
+
+ # Make a global cube + calculate ideal bounds-based results.
+ global_cube = sample_2d_latlons(transformed=True)
+ result_cube = gridcell_angles(global_cube)
+ result_cube.convert_units('degrees')
+ global_cube_results = result_cube.data
+
+ # Check a points-based calculation on the same basic grid.
+ co_x, co_y = (global_cube.coord(axis=ax)
+ for ax in ('x', 'y'))
+ for coord in (co_x, co_y):
+ coord.bounds = None
+ result = gridcell_angles(co_x, co_y)
+ # In this case, the match is actually rather poor (!).
+ self.assertArrayAllClose(result.data,
+ global_cube_results,
+ atol=7.5)
+ # Leaving off first + last columns again gives a decent result.
+ self.assertArrayAllClose(result.data[:, 1:-1],
+ global_cube_results[:, 1:-1])
+
+ # NOTE: although this looks just as bad as 'test_points_array_args',
+ # maximum errors there in the end columns are actually > 100 degrees !
+
+ def test_nonlatlon_coord_system(self):
+ # Check with points specified in an unexpected coord system.
+ cube = sample_2d_latlons(regional=True, rotated=True)
+ result = gridcell_angles(cube)
+ self.assertArrayAllClose(result.data,
+ self.standard_small_cube_results)
+ # Check that the result has transformed (true-latlon) coordinates.
+ self.assertEqual(len(result.coords()), 2)
+ x_coord = result.coord(axis='x')
+ y_coord = result.coord(axis='y')
+ self.assertEqual(x_coord.shape, cube.shape)
+ self.assertEqual(y_coord.shape, cube.shape)
+ self.assertIsNotNone(cube.coord_system)
+ self.assertIsNone(x_coord.coord_system)
+ self.assertIsNone(y_coord.coord_system)
+
+ def test_fail_coords_bad_units(self):
+ # Check error with bad coords units.
+ co_x, co_y = (self.standard_regional_cube.coord(axis=ax)
+ for ax in ('x', 'y'))
+ co_y.units = 'm'
+ with self.assertRaisesRegexp(ValueError, 'must have angular units'):
+ gridcell_angles(co_x, co_y)
+
+ def test_fail_nonarraylike(self):
+ # Check error with bad args.
+ co_x, co_y = 1, 2
+ with self.assertRaisesRegexp(ValueError,
+ 'must have array shape property'):
+ gridcell_angles(co_x, co_y)
+
+ def test_fail_non2d_coords(self):
+ # Check error with bad args.
+ cube = lat_lon_cube()
+ with self.assertRaisesRegexp(ValueError,
+ 'inputs must have 2-dimensional shape'):
+ gridcell_angles(cube)
+
+ def test_fail_different_shapes(self):
+ # Check error with mismatched shapes.
+ co_x, co_y = (self.standard_regional_cube.coord(axis=ax)
+ for ax in ('x', 'y'))
+ co_y = co_y[1:]
+ with self.assertRaisesRegexp(ValueError, 'must have same shape'):
+ gridcell_angles(co_x, co_y)
+
+ def test_fail_different_coord_system(self):
+ # Check error with mismatched coord systems.
+ cube = sample_2d_latlons(regional=True, rotated=True)
+ cube.coord(axis='x').coord_system = None
+ with self.assertRaisesRegexp(ValueError,
+ 'must have same coordinate system'):
+ gridcell_angles(cube)
+
+ def test_fail_cube_dims(self):
+ # Check error with mismatched cube dims.
+ cube = self.standard_regional_cube
+ # Make 5x6 into 5x5.
+ cube = cube[:, :-1]
+ co_x = cube.coord(axis='x')
+ pts, bds = co_x.points, co_x.bounds
+ co_new_x = co_x.copy(points=pts.transpose((1, 0)),
+ bounds=bds.transpose((1, 0, 2)))
+ cube.remove_coord(co_x)
+ cube.add_aux_coord(co_new_x, (1, 0))
+ with self.assertRaisesRegexp(ValueError,
+ 'must have the same cube dimensions'):
+ gridcell_angles(cube)
+
+ def test_fail_coord_noncoord(self):
+ # Check that passing a coord + an array gives an error.
+ co_x, co_y = (self.standard_regional_cube.coord(axis=ax)
+ for ax in ('x', 'y'))
+ with self.assertRaisesRegexp(ValueError,
+ 'is a Coordinate, but .* is not'):
+ gridcell_angles(co_x, co_y.bounds)
+
+ def test_fail_noncoord_coord(self):
+ # Check that passing an array + a coord gives an error.
+ co_x, co_y = (self.standard_regional_cube.coord(axis=ax)
+ for ax in ('x', 'y'))
+ with self.assertRaisesRegexp(ValueError,
+ 'is a Coordinate, but .* is not'):
+ gridcell_angles(co_x.points, co_y)
+
+ def test_fail_bad_method(self):
+ with self.assertRaisesRegexp(ValueError,
+ 'unrecognised cell_angle_boundpoints'):
+ self._check_multiple_orientations_and_latitudes(
+ method='something_unknown')
+
+
+if __name__ == "__main__":
+ tests.main()
From 2b6b7870e346d3eb2fecd89ae1d5d742d6e42338 Mon Sep 17 00:00:00 2001
From: Patrick Peglar
Date: Fri, 31 Aug 2018 16:28:59 +0100
Subject: [PATCH 25/62] Temporary pin to avoid problems caused by Proj4 v5.1.
(#3150)
---
requirements/core.txt | 1 +
1 file changed, 1 insertion(+)
diff --git a/requirements/core.txt b/requirements/core.txt
index 997c91c665..e9abec5732 100644
--- a/requirements/core.txt
+++ b/requirements/core.txt
@@ -4,6 +4,7 @@
# Without these, iris won't even import.
cartopy
+#conda: proj4<5
cf_units>=2
cftime
dask[array]==0.18.1 #conda: dask==0.18.1
From cb647615968b0bb07013543745205330af90210a Mon Sep 17 00:00:00 2001
From: lbdreyer
Date: Fri, 31 Aug 2018 16:35:22 +0100
Subject: [PATCH 26/62] Extending ORCA blockplotting (w/ tests) (#3135)
---
lib/iris/coords.py | 210 +++++++------
lib/iris/plot.py | 145 +++++----
lib/iris/tests/unit/coords/test_Coord.py | 293 ++++++++++++++++++
lib/iris/tests/unit/plot/test_2d_coords.py | 167 ----------
.../test__check_bounds_contiguity_and_mask.py | 96 ++++++
.../tests/unit/plot/test__get_plot_defn.py | 10 +-
...est__get_plot_defn_custom_coords_picked.py | 93 ++++++
7 files changed, 694 insertions(+), 320 deletions(-)
delete mode 100644 lib/iris/tests/unit/plot/test_2d_coords.py
create mode 100644 lib/iris/tests/unit/plot/test__check_bounds_contiguity_and_mask.py
create mode 100644 lib/iris/tests/unit/plot/test__get_plot_defn_custom_coords_picked.py
diff --git a/lib/iris/coords.py b/lib/iris/coords.py
index ff2f170a2f..42882fbc2c 100644
--- a/lib/iris/coords.py
+++ b/lib/iris/coords.py
@@ -143,81 +143,43 @@ def __new__(cls, name_or_coord, minimum, maximum,
'groupby_point, groupby_slice')
-def _discontiguity_in_2d_bounds(bds, abs_tol=1e-4):
+def _get_2d_coord_bound_grid(bounds):
"""
- Check bounds of a 2-dimensional coordinate are contiguous
- Args:
- bds: Array of bounds of shape (X,Y,4)
- abs_tol: tolerance
-
- Returns:
- Bool, if there are no discontinuities
- absolute difference along the x axis
- absolute difference along the y axis
-
- """
- # Check bds has the shape (ny, nx, 4)
- if not bds.ndim == 3 and bds.shape[2] == 4:
- raise ValueError('2D coordinates must have 4 bounds per point '
- 'for 2D coordinate plotting')
-
- # Check ordering:
- # i i+1
- # j @0 @1
- # j+1 @3 @2
- def mod360_diff(x1, x2):
- diff = x1 - x2
- diff = (diff + 360.0 + 180.0) % 360.0 - 180.0
- return diff
-
- # Compare cell with the cell next to it (i+1)
- diffs_along_x = mod360_diff(bds[:, :-1, 1], bds[:, 1:, 0])
- # Compare cell with the cell above it (j+1)
- diffs_along_y = mod360_diff(bds[:-1, :, 3], bds[1:, :, 0])
-
- def eq_diffs(x1):
- return np.all(np.abs(x1) < abs_tol)
-
- match_y0_x1 = eq_diffs(diffs_along_x)
- match_y1_x0 = eq_diffs(diffs_along_y)
+ Creates a grid using the bounds of a 2D coordinate with 4 sided cells.
- all_eq = match_y0_x1 and match_y1_x0
+ Assumes that the four vertices of the cells are in an anti-clockwise order
+ (bottom-left, bottom-right, top-right, top-left).
- return all_eq, np.abs(diffs_along_x), np.abs(diffs_along_y)
-
-
-def _get_2d_coord_bound_grid(bds):
- """
- Function used that takes a bounds array for a 2-D coordinate variable with
- 4 sides and returns the bounds grid.
-
- Cf standards requires the four vertices of the cell to be traversed
- anti-clockwise if the coordinates are defined in a right handed coordinate
- system.
-
- selects the zeroth vertex of each cell and then adds the column the first
- vertex at the end. For the top row it uses the thirs vertex, with the
- second added on to the end.
+ Selects the zeroth vertex of each cell. A final column is added, which
+ contains the first vertex of the cells in the final column. A final row
+ is added, which contains the third vertex of all the cells in the final
+ row, except for in the final column where it uses the second vertex.
e.g.
# 0-0-0-0-1
# 0-0-0-0-1
# 3-3-3-3-2
-
Args:
- bounds: array of shape (X,Y,4)
+ * bounds: (array)
+ Coordinate bounds array of shape (Y, X, 4)
Returns:
- array of shape (X+1, Y+1)
+ * grid: (array)
+ Grid of shape (Y+1, X+1)
"""
- bds_shape = bds.shape
- result = np.zeros((bds_shape[0] + 1, bds_shape[1] + 1))
+ # Check bds has the shape (ny, nx, 4)
+ if not (bounds.ndim == 3 and bounds.shape[-1] == 4):
+ raise ValueError('Bounds for 2D coordinates must be 3-dimensional and '
+ 'have 4 bounds per point.')
+
+ bounds_shape = bounds.shape
+ result = np.zeros((bounds_shape[0] + 1, bounds_shape[1] + 1))
- result[:-1, :-1] = bds[:, :, 0]
- result[:-1, -1] = bds[:, -1, 1]
- result[-1, :-1] = bds[-1, :, 3]
- result[-1, -1] = bds[-1, -1, 2]
+ result[:-1, :-1] = bounds[:, :, 0]
+ result[:-1, -1] = bounds[:, -1, 1]
+ result[-1, :-1] = bounds[-1, :, 3]
+ result[-1, -1] = bounds[-1, -1, 2]
return result
@@ -1029,29 +991,101 @@ def cells(self):
"""
return _CellIterator(self)
- def _sanity_check_contiguous(self):
+ def _sanity_check_bounds(self):
if self.ndim == 1:
if self.nbounds != 2:
- raise ValueError('Invalid operation for {!r}, with {} bounds. '
- 'Contiguous bounds are only defined for 1D '
- 'coordinates with 2 bounds.'.format
- (self.name(), self.nbounds))
+ raise ValueError('Invalid operation for {!r}, with {} '
+ 'bound(s). Contiguous bounds are only '
+ 'defined for 1D coordinates with 2 '
+ 'bounds.'.format(self.name(), self.nbounds))
elif self.ndim == 2:
if self.nbounds != 4:
- raise ValueError('Invalid operation for {!r}, with {} bounds. '
- 'Contiguous bounds are only defined for 2D '
- 'coordinates with 4 bounds.'.format
- (self.name(), self.nbounds))
+ raise ValueError('Invalid operation for {!r}, with {} '
+ 'bound(s). Contiguous bounds are only '
+ 'defined for 2D coordinates with 4 '
+ 'bounds.'.format(self.name(), self.nbounds))
else:
raise ValueError('Invalid operation for {!r}. Contiguous bounds '
'are not defined for coordinates with more than '
'2 dimensions.'.format(self.name()))
+ def _discontiguity_in_bounds(self, rtol=1e-05, atol=1e-08):
+ """
+ Checks that the bounds of the coordinate are contiguous.
+
+ Kwargs:
+ * rtol: (float)
+ Relative tolerance that is used when checking contiguity. Defaults
+ to 1e-5.
+ * atol: (float)
+ Absolute tolerance that is used when checking contiguity. Defaults
+ to 1e-8.
+
+ Returns:
+ * contiguous: (boolean)
+ True if there are no discontiguities.
+ * diffs: (array or tuple of arrays)
+ The diffs along the bounds of the coordinate. If self is a 2D
+ coord of shape (Y, X), a tuple of arrays is returned, where the
+ first is an array of differences along the x-axis, of the shape
+ (Y, X-1) and the second is an array of differences along the
+ y-axis, of the shape (Y-1, X).
+
+ """
+ self._sanity_check_bounds()
+
+ if self.ndim == 1:
+ contiguous = np.allclose(self.bounds[1:, 0],
+ self.bounds[:-1, 1],
+ rtol=rtol, atol=atol)
+ diffs = np.abs(self.bounds[:-1, 1] - self.bounds[1:, 0])
+
+ elif self.ndim == 2:
+ def mod360_adjust(compare_axis):
+ bounds = self.bounds.copy()
+
+ if compare_axis == 'x':
+ upper_bounds = bounds[:, :-1, 1]
+ lower_bounds = bounds[:, 1:, 0]
+ elif compare_axis == 'y':
+ upper_bounds = bounds[:-1, :, 3]
+ lower_bounds = bounds[1:, :, 0]
+
+ if self.name() in ['longitude', 'grid_longitude']:
+ # If longitude, adjust for longitude wrapping
+ diffs = upper_bounds - lower_bounds
+ index = diffs > 180
+ if index.any():
+ sign = np.sign(diffs)
+ modification = (index.astype(int) * 360) * sign
+ upper_bounds -= modification
+
+ diffs_along_axis = np.abs(upper_bounds - lower_bounds)
+ contiguous_along_axis = np.allclose(upper_bounds, lower_bounds,
+ rtol=rtol, atol=atol)
+ return diffs_along_axis, contiguous_along_axis
+
+ diffs_along_x, match_cell_x1 = mod360_adjust(compare_axis='x')
+ diffs_along_y, match_cell_y1 = mod360_adjust(compare_axis='y')
+
+ contiguous = match_cell_x1 and match_cell_y1
+ diffs = (diffs_along_x, diffs_along_y)
+
+ return contiguous, diffs
+
def is_contiguous(self, rtol=1e-05, atol=1e-08):
"""
Return True if, and only if, this Coord is bounded with contiguous
bounds to within the specified relative and absolute tolerances.
+ 1D coords are contiguous if the upper bound of a cell aligns,
+ within a tolerance, to the lower bound of the next cell along.
+
+ 2D coords, with 4 bounds, are contiguous if the lower right corner of
+ each cell aligns with the lower left corner of the cell to the right of
+ it, and the upper left corner of each cell aligns with the lower left
+ corner of the cell above it.
+
Args:
* rtol:
@@ -1064,14 +1098,7 @@ def is_contiguous(self, rtol=1e-05, atol=1e-08):
"""
if self.has_bounds():
- self._sanity_check_contiguous()
- if self.ndim == 1:
- contiguous = np.allclose(self.bounds[1:, 0],
- self.bounds[:-1, 1],
- rtol=rtol, atol=atol)
- elif self.ndim == 2:
- contiguous, _, _ = _discontiguity_in_2d_bounds(self.bounds,
- abs_tol=atol)
+ contiguous, _ = self._discontiguity_in_bounds(rtol=rtol, atol=atol)
else:
contiguous = False
return contiguous
@@ -1079,25 +1106,34 @@ def is_contiguous(self, rtol=1e-05, atol=1e-08):
def contiguous_bounds(self):
"""
Returns the N+1 bound values for a contiguous bounded 1D coordinate
- of length N.
-
- Returns the (N+1, M+1) bound values for a contiguous bounded 2D
+ of length N, or the (N+1, M+1) bound values for a contiguous bounded 2D
coordinate of shape (N, M).
- Assumes input is contiguous.
+ Only 1D or 2D coordinates are supported.
.. note::
- If the coordinate does not have bounds, this method will
+ If the coordinate has bounds, this method assumes they are
+ contiguous.
+
+ If the coordinate is 1D and does not have bounds, this method will
return bounds positioned halfway between the coordinate's points.
+ If the coordinate is 2D and does not have bounds, an error will be
+ raised.
+
"""
if not self.has_bounds():
- warnings.warn('Coordinate {!r} is not bounded, guessing '
- 'contiguous bounds.'.format(self.name()))
- bounds = self._guess_bounds()
+ if self.ndim == 1:
+ warnings.warn('Coordinate {!r} is not bounded, guessing '
+ 'contiguous bounds.'.format(self.name()))
+ bounds = self._guess_bounds()
+ elif self.ndim == 2:
+ raise ValueError('2D coordinate {!r} is not bounded. Guessing '
+ 'bounds of 2D coords is not currently '
+ 'supported.'.format(self.name()))
else:
- self._sanity_check_contiguous()
+ self._sanity_check_bounds()
bounds = self.bounds
if self.ndim == 1:
diff --git a/lib/iris/plot.py b/lib/iris/plot.py
index 7bf8ea07f3..0b9b7c54be 100644
--- a/lib/iris/plot.py
+++ b/lib/iris/plot.py
@@ -102,7 +102,7 @@ def get_span(coord):
raise ValueError(msg.format(coord.name()))
if mode == iris.coords.BOUND_MODE and len(span) not in [1, 2]:
raise ValueError('The coordinate {!r} has {} dimensions.'
- 'Cell-based plotting is only supporting for'
+ 'Cell-based plotting is only supported for'
'coordinates with one or two dimensions.'
.format(coord.name()), len(span))
@@ -271,54 +271,82 @@ def _invert_yaxis(v_coord, axes=None):
axes.invert_yaxis()
-def _check_contiguity_and_bounds(coord, data, abs_tol=1e-4, transpose=False):
+def _check_bounds_contiguity_and_mask(coord, data, atol=None):
"""
- Check that the discontinuous bounds occur where the data is masked.
+ Checks that any discontiguities in the bounds of the given coordinate only
+ occur where the data is masked.
- If discontinuity occurs but data is masked, raise warning
- If discontinuity occurs and data is NOT masked, raise error
+ Where a discontinuity occurs the grid created for plotting will not be
+ correct. This does not matter if the data is masked in that location as
+ this is not plotted.
+
+ If a discontiguity occurs where the data is *not* masked, an error is
+ raised.
Args:
- coords:
- Array of the bounds of a 2D coord, of shape (X,Y,4)
- data:
- data of the the cube we are plotting
- abs_tol:
- tolerance when checking the contiguity
+ coord: (iris.coord.Coord)
+ Coordinate the bounds of which will be checked for contiguity
+ data: (array)
+ Data of the the cube we are plotting
+ atol:
+ Absolute tolerance when checking the contiguity. Defaults to None.
+ If an absolute tolerance is not set, 1D coords are not checked (so
+ as to not introduce a breaking change without a major release) but
+ 2D coords are always checked, by calling
+ :meth:`iris.coords.Coord._discontiguity_in_bounds` with its default
+ tolerance.
"""
- if transpose:
- data = data.T
-
- bounds = coord.bounds
-
- both_dirs_contiguous, diffs_along_x, diffs_along_y = \
- iris.coords._discontiguity_in_2d_bounds(bounds, abs_tol=abs_tol)
-
- if not both_dirs_contiguous:
-
- # True where data exists
+ data_is_masked = hasattr(data, 'mask')
+ if data_is_masked:
+ # When checking the location of the discontiguities, we check against
+ # the opposite of the mask, which is True where data exists.
mask_invert = np.logical_not(data.mask)
- # Where a discontinuity occurs the grid will not be created correctly.
- # This does not matter if the data is masked as this is not plotted.
- # So for places where data exists (opposite of the mask) AND a
- # diff exists. If any exist, raise a warning
- not_masked_at_discontinuity_along_x = np.any(
- np.logical_and(mask_invert[:, :-1], diffs_along_x))
+ if coord.ndim == 1:
+ # 1D coords are only checked if an absolute tolerance is set, to avoid
+ # introducing a breaking change.
+ if atol:
+ contiguous, diffs = coord._discontiguity_in_bounds(atol=atol)
- not_masked_at_discontinuity_along_y = np.any(
- np.logical_and(mask_invert[:-1, ], diffs_along_y))
+ if not contiguous and data_is_masked:
+ not_masked_at_discontiguity = np.any(
+ np.logical_and(mask_invert[:-1], diffs))
+ else:
+ return
- # If discontinuity occurs but not masked, any grid will be created
- # incorrectly, so raise a warning
- if not_masked_at_discontinuity_along_x or \
- not_masked_at_discontinuity_along_y:
- raise ValueError('The bounds of the {} coordinate are not'
- ' contiguous and data is not masked where the'
- ' discontiguity occurs. Not able to create a'
- ' suitable mesh to give to'
- ' Matplotlib'.format(coord.name()))
+ elif coord.ndim == 2:
+ if atol:
+ args = {'atol': atol}
+ else:
+ args = {}
+ contiguous, diffs = coord._discontiguity_in_bounds(*args)
+ diffs_along_x, diffs_along_y = diffs
+
+ if not contiguous and data_is_masked:
+ # Check along both dimensions.
+ not_masked_at_discontiguity_along_x = np.any(
+ np.logical_and(mask_invert[:, :-1], diffs_along_x))
+
+ not_masked_at_discontiguity_along_y = np.any(
+ np.logical_and(mask_invert[:-1, ], diffs_along_y))
+
+ not_masked_at_discontiguity = not_masked_at_discontiguity_along_x \
+ or not_masked_at_discontiguity_along_y
+
+ # If any discontiguity occurs where the data is not masked the grid will be
+ # created incorrectly, so raise an error.
+ if not contiguous:
+ if not data_is_masked:
+ raise ValueError('The bounds of the {} coordinate are not '
+ 'contiguous. Not able to create a suitable grid'
+ 'to plot.'.format(coord.name()))
+ if not_masked_at_discontiguity:
+ raise ValueError('The bounds of the {} coordinate are not '
+ 'contiguous and data is not masked where the '
+ 'discontiguity occurs. Not able to create a '
+ 'suitable grid to plot.'.format(
+ coord.name()))
def _draw_2d_from_bounds(draw_method_name, cube, *args, **kwargs):
@@ -333,19 +361,12 @@ def _draw_2d_from_bounds(draw_method_name, cube, *args, **kwargs):
else:
plot_defn = _get_plot_defn(cube, mode, ndims=2)
- twodim_contig_atol = kwargs.pop('two_dim_coord_contiguity_atol',
- 1e-4)
+ contig_tol = kwargs.pop('contiguity_tolerance', None)
+
for coord in plot_defn.coords:
- if hasattr(coord, 'has_bounds'):
- if coord.ndim == 2 and coord.has_bounds():
- try:
- _check_contiguity_and_bounds(coord, data=cube.data,
- abs_tol=twodim_contig_atol)
- except ValueError:
- if _check_contiguity_and_bounds(coord, data=cube.data,
- abs_tol=twodim_contig_atol,
- transpose=True) is True:
- plot_defn.transpose = True
+ if hasattr(coord, 'has_bounds') and coord.has_bounds():
+ _check_bounds_contiguity_and_mask(coord, data=cube.data,
+ atol=contig_tol)
if _can_draw_map(plot_defn.coords):
result = _map_common(draw_method_name, None, iris.coords.BOUND_MODE,
@@ -390,11 +411,10 @@ def _draw_2d_from_bounds(draw_method_name, cube, *args, **kwargs):
u, v = plot_arrays
- # If the data is tranposed, 2D coordinates will also need to be
- # tranposed.
- if u.ndim == v.ndim == 2 and plot_defn.transpose is True:
- u = u.T
- v = v.T
+ # If the data is transposed, 2D coordinates will also need to be
+ # transposed.
+ if plot_defn.transpose is True:
+ u, v = [coord.T if coord.ndim == 2 else coord for coord in [u, v]]
if u.ndim == v.ndim == 1:
u, v = _broadcast_2d(u, v)
@@ -1102,8 +1122,7 @@ def pcolor(cube, *args, **kwargs):
Draws a pseudocolor plot based on the given 2-dimensional Cube.
The cube must have either two 1-dimensional coordinates or two
- 2-dimensional coordinates with contiguous bounds to plot against each
- other.
+ 2-dimensional coordinates with contiguous bounds to plot the cube against.
Kwargs:
@@ -1117,10 +1136,8 @@ def pcolor(cube, *args, **kwargs):
* axes: the :class:`matplotlib.axes.Axes` to use for drawing.
Defaults to the current axes if none provided.
- * two_dim_coord_contiguity_atol: absolute tolerance when checking for
- contiguity between cells in a two dimensional coordinate.
-
-
+ * contiguity_tolerance: The absolute tolerance used when checking for
+ contiguity between the bounds of the cells. Defaults to None.
See :func:`matplotlib.pyplot.pcolor` for details of other valid
keyword arguments.
@@ -1152,8 +1169,8 @@ def pcolormesh(cube, *args, **kwargs):
* axes: the :class:`matplotlib.axes.Axes` to use for drawing.
Defaults to the current axes if none provided.
- * two_dim_coord_contiguity_atol: absolute tolerance when checking for
- contiguity between cells in a two dimensional coordinate.
+ * contiguity_tolerance: The absolute tolerance used when checking for
+ contiguity between the bounds of the cells. Defaults to None.
See :func:`matplotlib.pyplot.pcolormesh` for details of other
valid keyword arguments.
diff --git a/lib/iris/tests/unit/coords/test_Coord.py b/lib/iris/tests/unit/coords/test_Coord.py
index b43df9447a..58fc3e1f9e 100644
--- a/lib/iris/tests/unit/coords/test_Coord.py
+++ b/lib/iris/tests/unit/coords/test_Coord.py
@@ -24,6 +24,8 @@
import iris.tests as tests
import collections
+import mock
+import warnings
import numpy as np
@@ -355,6 +357,297 @@ def test_different_array_attrs_incompatible(self):
self.assertFalse(self.test_coord.is_compatible(self.other_coord))
+class Test_contiguous_bounds(tests.IrisTest):
+ def test_1d_coord_no_bounds_warning(self):
+ coord = DimCoord([0, 1, 2], standard_name='latitude')
+ msg = "Coordinate 'latitude' is not bounded, guessing contiguous " \
+ "bounds."
+ with warnings.catch_warnings():
+ # Cause all warnings to raise Exceptions
+ warnings.simplefilter("error")
+ with self.assertRaisesRegexp(Warning, msg):
+ coord.contiguous_bounds()
+
+ def test_2d_coord_no_bounds_error(self):
+ coord = AuxCoord(np.array([[0, 0], [5, 5]]), standard_name='latitude')
+ emsg = 'Guessing bounds of 2D coords is not currently supported'
+ with self.assertRaisesRegexp(ValueError, emsg):
+ coord.contiguous_bounds()
+
+ def test__sanity_check_bounds_call(self):
+ coord = DimCoord([5, 15, 25], bounds=[[0, 10], [10, 20], [20, 30]])
+ with mock.patch('iris.coords.Coord._sanity_check_bounds'
+ ) as bounds_check:
+ coord.contiguous_bounds()
+ bounds_check.assert_called_once()
+
+ def test_1d_coord(self):
+ coord = DimCoord([2, 4, 6], standard_name='latitude',
+ bounds=[[1, 3], [3, 5], [5, 7]])
+ expected = np.array([1, 3, 5, 7])
+ result = coord.contiguous_bounds()
+ self.assertArrayEqual(result, expected)
+
+ def test_1d_coord_discontiguous(self):
+ coord = DimCoord([2, 4, 6], standard_name='latitude',
+ bounds=[[1, 3], [4, 5], [5, 7]])
+ expected = np.array([1, 4, 5, 7])
+ result = coord.contiguous_bounds()
+ self.assertArrayEqual(result, expected)
+
+ def test_2d_lon_bounds(self):
+ coord = AuxCoord(np.array([[1, 3], [1, 3]]),
+ bounds=np.array([[[0, 2, 2, 0], [2, 4, 4, 2]],
+ [[0, 2, 2, 0], [2, 4, 4, 2]]]))
+ expected = np.array([[0, 2, 4], [0, 2, 4], [0, 2, 4]])
+ result = coord.contiguous_bounds()
+ self.assertArrayEqual(result, expected)
+
+ def test_2d_lat_bounds(self):
+ coord = AuxCoord(np.array([[1, 1], [3, 3]]),
+ bounds=np.array([[[0, 0, 2, 2], [0, 0, 2, 2]],
+ [[2, 2, 4, 4], [2, 2, 4, 4]]]))
+ expected = np.array([[0, 0, 0], [2, 2, 2], [4, 4, 4]])
+ result = coord.contiguous_bounds()
+ self.assertArrayEqual(result, expected)
+
+
+class Test_is_contiguous(tests.IrisTest):
+ def test_no_bounds(self):
+ coord = DimCoord([1, 3])
+ result = coord.is_contiguous()
+ self.assertFalse(result)
+
+ def test__discontiguity_in_bounds_call(self):
+ # Check that :meth:`iris.coords.Coord._discontiguity_in_bounds` is
+ # called.
+ coord = DimCoord([1, 3], bounds=[[0, 2], [2, 4]])
+ with mock.patch('iris.coords.Coord._discontiguity_in_bounds'
+ ) as discontiguity_check:
+ # Discontiguity returns two objects that are unpacked in
+ # `coord.is_contiguous`.
+ discontiguity_check.return_value = [None, None]
+ coord.is_contiguous(rtol=1e-1, atol=1e-3)
+ discontiguity_check.assert_called_with(rtol=1e-1, atol=1e-3)
+
+
+class Test__discontiguity_in_bounds(tests.IrisTest):
+ def setUp(self):
+ self.points_3by3 = np.array([[1, 2, 3],
+ [1, 2, 3],
+ [1, 2, 3]])
+ self.lon_bounds_3by3 = np.array(
+ [[[0, 2, 2, 0], [2, 4, 4, 2], [4, 6, 6, 4]],
+ [[0, 2, 2, 0], [2, 4, 4, 2], [4, 6, 6, 4]],
+ [[0, 2, 2, 0], [2, 4, 4, 2], [4, 6, 6, 4]]])
+ self.lat_bounds_3by3 = np.array(
+ [[[0, 0, 2, 2], [0, 0, 2, 2], [0, 0, 2, 2]],
+ [[2, 2, 4, 4], [2, 2, 4, 4], [2, 2, 4, 4]],
+ [[4, 4, 6, 6], [4, 4, 6, 6], [4, 4, 6, 6]]])
+
+ def test_1d_contiguous(self):
+ coord = DimCoord([-20, 0, 20],
+ bounds=[[-30, -10], [-10, 10], [10, 30]])
+ contiguous, diffs = coord._discontiguity_in_bounds()
+ self.assertTrue(contiguous)
+ self.assertArrayEqual(diffs, np.zeros(2))
+
+ def test_1d_discontiguous(self):
+ coord = DimCoord([10, 20, 40],
+ bounds=[[5, 15], [15, 25], [35, 45]])
+ contiguous, diffs = coord._discontiguity_in_bounds()
+ self.assertFalse(contiguous)
+ self.assertArrayEqual(diffs, np.array([0, 10]))
+
+ def test_1d_one_cell(self):
+ # Test a 1D coord with a single cell.
+ coord = DimCoord(20, bounds=[[10, 30]])
+ contiguous, diffs = coord._discontiguity_in_bounds()
+ self.assertTrue(contiguous)
+ self.assertArrayEqual(diffs, np.array([]))
+
+ def test_2d_contiguous_both_dirs(self):
+ coord = AuxCoord(self.points_3by3, bounds=self.lon_bounds_3by3)
+ contiguous, diffs = coord._discontiguity_in_bounds()
+ diffs_along_x, diffs_along_y = diffs
+ self.assertTrue(contiguous)
+ self.assertTrue(not diffs_along_x.any())
+ self.assertTrue(not diffs_along_y.any())
+
+ def test_2d_discontiguous_along_x(self):
+ coord = AuxCoord(self.points_3by3[:, ::2],
+ bounds=self.lon_bounds_3by3[:, ::2, :])
+ contiguous, diffs = coord._discontiguity_in_bounds()
+ diffs_along_x, diffs_along_y = diffs
+ self.assertFalse(contiguous)
+ self.assertArrayEqual(diffs_along_x, np.array([2, 2, 2]).reshape(3, 1))
+ self.assertTrue(not diffs_along_y.any())
+
+ def test_2d_discontiguous_along_y(self):
+ coord = AuxCoord(self.points_3by3[::2, :],
+ bounds=self.lat_bounds_3by3[::2, :, :])
+ contiguous, diffs = coord._discontiguity_in_bounds()
+ diffs_along_x, diffs_along_y = diffs
+ self.assertFalse(contiguous)
+ self.assertTrue(not diffs_along_x.any())
+ self.assertArrayEqual(diffs_along_y, np.array([[2, 2, 2]]))
+
+ def test_2d_discontiguous_along_x_and_y(self):
+ coord = AuxCoord(np.array([[1, 5], [3, 5]]),
+ bounds=np.array([[[0, 2, 2, 0], [4, 6, 6, 4]],
+ [[2, 4, 4, 2], [4, 6, 6, 4]]]))
+ contiguous, diffs = coord._discontiguity_in_bounds()
+ diffs_along_x, diffs_along_y = diffs
+ exp_x_diffs = np.array([2, 0]).reshape(2, 1)
+ exp_y_diffs = np.array([2, 0]).reshape(1, 2)
+ self.assertFalse(contiguous)
+ self.assertArrayEqual(diffs_along_x, exp_x_diffs)
+ self.assertArrayEqual(diffs_along_y, exp_y_diffs)
+
+ def test_2d_one_cell(self):
+ # Test a 2D coord with a single cell, where the coord has shape (1, 1).
+ coord = AuxCoord(self.points_3by3[:1, :1],
+ bounds=self.lon_bounds_3by3[:1, :1, :])
+ contiguous, diffs = coord._discontiguity_in_bounds()
+ diffs_along_x, diffs_along_y = diffs
+ expected_diffs = np.array([], dtype=np.int64)
+ self.assertTrue(contiguous)
+ self.assertArrayEqual(diffs_along_x, expected_diffs.reshape(1, 0))
+ self.assertArrayEqual(diffs_along_y, expected_diffs.reshape(0, 1))
+
+ def test_2d_one_cell_along_x(self):
+ # Test a 2D coord with a single cell along the x axis, where the coord
+ # has shape (2, 1).
+ coord = AuxCoord(self.points_3by3[:, :1],
+ bounds=self.lat_bounds_3by3[:, :1, :])
+ contiguous, diffs = coord._discontiguity_in_bounds()
+ diffs_along_x, diffs_along_y = diffs
+ self.assertTrue(contiguous)
+ self.assertTrue(not diffs_along_x.any())
+ self.assertArrayEqual(diffs_along_y, np.array([0, 0]).reshape(2, 1))
+
+ def test_2d_one_cell_along_y(self):
+ # Test a 2D coord with a single cell along the y axis, where the coord
+ # has shape (1, 2).
+ coord = AuxCoord(self.points_3by3[:1, :],
+ bounds=self.lon_bounds_3by3[:1, :, :])
+ contiguous, diffs = coord._discontiguity_in_bounds()
+ diffs_along_x, diffs_along_y = diffs
+ self.assertTrue(contiguous)
+ self.assertTrue(not diffs_along_x.any())
+ self.assertTrue(not diffs_along_y.any())
+
+ def test_2d_contiguous_mod_360(self):
+ # Test that longitude coordinates are adjusted by the 360 modulus when
+ # calculating the discontiguities in contiguous bounds.
+ coord = AuxCoord(
+ [[175, -175], [175, -175]], standard_name='longitude',
+ bounds=np.array([[[170, 180, 180, 170], [-180, -170, -170, -180]],
+ [[170, 180, 180, 170], [-180, -170, -170, -180]]])
+ )
+ contiguous, diffs = coord._discontiguity_in_bounds()
+ diffs_along_x, diffs_along_y = diffs
+ self.assertTrue(contiguous)
+ self.assertTrue(not diffs_along_x.any())
+ self.assertTrue(not diffs_along_y.any())
+
+ def test_2d_discontiguous_mod_360(self):
+ # Test that longitude coordinates are adjusted by the 360 modulus when
+ # calculating the discontiguities in contiguous bounds.
+ coord = AuxCoord(
+ [[175, -175], [175, -175]], standard_name='longitude',
+ bounds=np.array([[[170, 180, 180, 170], [10, 20, 20, 10]],
+ [[170, 180, 180, 170], [10, 20, 20, 10]]]))
+ contiguous, diffs = coord._discontiguity_in_bounds()
+ diffs_along_x, diffs_along_y = diffs
+ self.assertFalse(contiguous)
+ self.assertArrayEqual(diffs_along_x, np.array([[170], [170]]))
+ self.assertTrue(not diffs_along_y.any())
+
+ def test_2d_contiguous_mod_360_not_longitude(self):
+ # Test that non-longitude coordinates are not adjusted by the 360
+ # modulus when calculating the discontiguities in contiguous bounds.
+ coord = AuxCoord(
+ [[-150, 350], [-150, 350]], standard_name='height',
+ bounds=np.array([[[-400, 100, 100, -400], [100, 600, 600, 100]],
+ [[-400, 100, 100, -400], [100, 600, 600, 100]]])
+ )
+ contiguous, diffs = coord._discontiguity_in_bounds()
+ diffs_along_x, diffs_along_y = diffs
+ self.assertTrue(contiguous)
+ self.assertTrue(not diffs_along_x.any())
+ self.assertTrue(not diffs_along_y.any())
+
+ def test_2d_discontiguous_mod_360_not_longitude(self):
+ # Test that non-longitude coordinates are not adjusted by the 360
+ # modulus when calculating the discontiguities in discontiguous bounds.
+ coord = AuxCoord(
+ [[-150, 350], [-150, 350]], standard_name='height',
+ bounds=np.array([[[-400, 100, 100, -400], [200, 600, 600, 200]],
+ [[-400, 100, 100, -400], [200, 600, 600, 200]]])
+ )
+ contiguous, diffs = coord._discontiguity_in_bounds()
+ diffs_along_x, diffs_along_y = diffs
+ self.assertFalse(contiguous)
+ self.assertArrayEqual(diffs_along_x, np.array([[100], [100]]))
+ self.assertTrue(not diffs_along_y.any())
+
+
+class Test__sanity_check_bounds(tests.IrisTest):
+ def test_coord_1d_2_bounds(self):
+ # Check that a 1d coord with 2 bounds does not raise an error.
+ coord = iris.coords.DimCoord([0, 1], standard_name='latitude',
+ bounds=[[0, 1], [1, 2]])
+ coord._sanity_check_bounds()
+
+ def test_coord_1d_no_bounds(self):
+ coord = iris.coords.DimCoord([0, 1], standard_name='latitude')
+ emsg = "Contiguous bounds are only defined for 1D coordinates with " \
+ "2 bounds."
+ with self.assertRaisesRegexp(ValueError, emsg):
+ coord._sanity_check_bounds()
+
+ def test_coord_1d_1_bounds(self):
+ coord = iris.coords.DimCoord([0, 1], standard_name='latitude',
+ bounds=np.array([[0], [1]]))
+ emsg = "Contiguous bounds are only defined for 1D coordinates with " \
+ "2 bounds."
+ with self.assertRaisesRegexp(ValueError, emsg):
+ coord._sanity_check_bounds()
+
+ def test_coord_2d_4_bounds(self):
+ coord = iris.coords.AuxCoord(
+ [[0, 0], [1, 1]], standard_name='latitude',
+ bounds=np.array([[[0, 0, 1, 1], [0, 0, 1, 1]],
+ [[1, 1, 2, 2], [1, 1, 2, 2]]]))
+ coord._sanity_check_bounds()
+
+ def test_coord_2d_no_bounds(self):
+ coord = iris.coords.AuxCoord([[0, 0], [1, 1]],
+ standard_name='latitude')
+ emsg = "Contiguous bounds are only defined for 2D coordinates with " \
+ "4 bounds."
+ with self.assertRaisesRegexp(ValueError, emsg):
+ coord._sanity_check_bounds()
+
+ def test_coord_2d_2_bounds(self):
+ coord = iris.coords.AuxCoord(
+ [[0, 0], [1, 1]], standard_name='latitude',
+ bounds=np.array([[[0, 1], [0, 1]], [[1, 2], [1, 2]]]))
+ emsg = "Contiguous bounds are only defined for 2D coordinates with " \
+ "4 bounds."
+ with self.assertRaisesRegexp(ValueError, emsg):
+ coord._sanity_check_bounds()
+
+ def test_coord_3d(self):
+ coord = iris.coords.AuxCoord(np.zeros((2, 2, 2)),
+ standard_name='height')
+ emsg = "Contiguous bounds are not defined for coordinates with more " \
+ "than 2 dimensions."
+ with self.assertRaisesRegexp(ValueError, emsg):
+ coord._sanity_check_bounds()
+
+
class Test_convert_units(tests.IrisTest):
def test_convert_unknown_units(self):
coord = iris.coords.AuxCoord(1, units='unknown')
diff --git a/lib/iris/tests/unit/plot/test_2d_coords.py b/lib/iris/tests/unit/plot/test_2d_coords.py
deleted file mode 100644
index 7397921861..0000000000
--- a/lib/iris/tests/unit/plot/test_2d_coords.py
+++ /dev/null
@@ -1,167 +0,0 @@
-# (C) British Crown Copyright 2018, Met Office
-#
-# This file is part of Iris.
-#
-# Iris is free software: you can redistribute it and/or modify it under
-# the terms of the GNU Lesser General Public License as published by the
-# Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-#
-# Iris is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public License
-# along with Iris. If not, see .
-"""Unit tests for handling and plotting of 2-dimensional coordinates"""
-
-from __future__ import (absolute_import, division, print_function)
-from six.moves import (filter, input, map, range, zip) # noqa
-
-# Import iris.tests first so that some things can be initialised before
-# importing anything else.
-import iris.tests as tests
-
-import numpy.ma as ma
-
-import iris.coords as coords
-from iris.tests.stock import simple_2d_w_multidim_coords as cube_2dcoords
-from iris.tests.stock import simple_3d_w_multidim_coords as cube3d_2dcoords
-from iris.tests.stock import sample_2d_latlons
-from iris.tests.stock import make_bounds_discontiguous_at_point
-
-
-if tests.MPL_AVAILABLE:
- import iris.plot as iplt
-
-
-def full2d_global():
- return sample_2d_latlons(transformed=True)
-
-
-@tests.skip_data
-class Test_2d_coords_plot_defn_bound_mode(tests.IrisTest):
- def setUp(self):
- self.multidim_cube = cube_2dcoords()
- self.overspan_cube = cube3d_2dcoords()
-
- # latlon_2d is a cube with 2d coords, 4 bounds per point,
- # discontiguities in the bounds but masked data at the discontiguities.
- self.latlon_2d = full2d_global()
- make_bounds_discontiguous_at_point(self.latlon_2d, 2, 2)
-
- # # Take a latlon cube with 1D coords, broadcast the coords into 2D
- # # ones, then add ONE of them back into the cube in place of original:
- # single_dims = lat_lon_cube()
- # lon = single_dims.coord('longitude')
- # lat = single_dims.coord('latitude')
- # big_lon, big_lat = testdata.grid_coords_2d_from_1d(lon, lat)
- # mixed_dims = single_dims.copy()
- # mixed_dims.remove_coord(lon)
- # # TODO Fix this coord addition:
- # # When adding an aux_coord, the function '_check_multidim_metadata'
- # # throws an error as it requires coord.shape to be (1, ) instead of
- # # (3, 4) or whatever.
- # mixed_dims.add_aux_coord(big_lon)
- #
- # # mixed_dims is now a cube with 2 1D dim coords and an additional
- # # 2D aux coord.
- # self.mixed_dims = mixed_dims
-
- self.mode = coords.BOUND_MODE
-
- def test_2d_coords_identified(self):
- # Test that 2d coords are identified in the plot definition without
- # having to be specified in the args without any errors.
- cube = self.multidim_cube
- defn = iplt._get_plot_defn(cube, mode=self.mode)
- self.assertEqual([coord.name() for coord in defn.coords],
- ['bar', 'foo'])
-
- def test_2d_coords_custom_picked(self):
- # Test that 2d coords which are specified in the args will be
- # accepted without any errors.
- cube = self.multidim_cube
- defn = iplt._get_plot_defn_custom_coords_picked(cube, ('foo', 'bar'),
- self.mode)
- self.assertEqual([coord.name() for coord in defn.coords],
- ['bar', 'foo'])
-
- def test_2d_coords_as_integers(self):
- # Test that if you pass in 2d coords as args in the form of integers,
- # they will still be correctly identified without any errors.
- cube = self.multidim_cube
- defn = iplt._get_plot_defn_custom_coords_picked(cube, (0, 1),
- self.mode)
- self.assertEqual([coord for coord in defn.coords],
- [1, 0])
-
- def test_total_span_check(self):
- # Test that an error is raised if a user tries to plot a 2d coord
- # against a different coord, making total number of dimensions 3.
- cube = self.overspan_cube
- with self.assertRaises(ValueError):
- iplt._get_plot_defn_custom_coords_picked(cube, ('wibble', 'foo'),
- self.mode)
-
- # def test_2dcoord_with_1dcoord(self):
- # # TODO Generate a cube with one 2d coord and one 1d coord
- # # TODO Try and plot them against each other
- # # TODO Find out where I can put a catch for this (if necessary)
- # cube = self.mixed_dims
- # with self.assertRaises(ValueError):
- # iplt._get_plot_defn_custom_coords_picked(
- # cube,
- # ('latitude', 'longitude'),
- # self.mode)
-
- def test_map_common_not_enough_bounds(self):
- # Test that a lat-lon cube with 2d coords and 2 bounds per point
- # throws an error in contiguity checks.
- cube = self.multidim_cube
- cube.coord('foo').rename('longitude')
- cube.coord('bar').rename('latitude')
- with self.assertRaises(ValueError):
- plot_defn = iplt._get_plot_defn(cube, self.mode)
- iplt._map_common('pcolor', None, self.mode, cube, plot_defn)
-
- def test_map_common_2d(self):
- # Test that a cube with 2d coords can be plotted as a map.
- cube = self.latlon_2d
- # Get necessary variables from _get_plot_defn to check that the test
- # case will be accepted by _map_common.
- plot_defn = iplt._get_plot_defn(cube, self.mode)
- result = iplt._map_common('pcolor', None, self.mode, cube, plot_defn)
- self.assertTrue(result)
-
-# def test_discontiguous_masked(self):
-# # Test that a contiguity check will raise a warning (not an error) for
-# # discontiguous bounds but appropriately masked data.
-# cube = self.latlon_2d
-# coord = cube.coord('longitude')
-# msg = 'The bounds of the longitude coordinate are not contiguous. ' \
-# 'However, data is masked where the discontiguity occurs so ' \
-# 'plotting anyway.'
-# with self.assertWarnsRegexp(msg):
-# iplt._check_contiguity_and_bounds(coord, cube.data)
-
- def test_discontiguous_unmasked(self):
- # Check that an error occurs when the contiguity check finds
- # discontiguous bounds but unmasked data.
- cube = self.latlon_2d
- cube.data.mask = ma.nomask
- coord = cube.coord('longitude')
- with self.assertRaises(ValueError):
- iplt._check_contiguity_and_bounds(coord, cube.data)
-
- def test_draw_2d_from_bounds(self):
- # Test this function will not raise an error even with our most
- # awkward but supported cube.
- cube = self.latlon_2d
- result = iplt._draw_2d_from_bounds('pcolormesh', cube)
- self.assertTrue(result)
-
-
-if __name__ == '__main__':
- tests.main()
diff --git a/lib/iris/tests/unit/plot/test__check_bounds_contiguity_and_mask.py b/lib/iris/tests/unit/plot/test__check_bounds_contiguity_and_mask.py
new file mode 100644
index 0000000000..b067b3f387
--- /dev/null
+++ b/lib/iris/tests/unit/plot/test__check_bounds_contiguity_and_mask.py
@@ -0,0 +1,96 @@
+# (C) British Crown Copyright 2018, Met Office
+#
+# This file is part of Iris.
+#
+# Iris is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Iris is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Iris. If not, see .
+"""Unit tests for the `iris.plot._check_bounds_contiguity_and_mask`
+function."""
+
+from __future__ import (absolute_import, division, print_function)
+from six.moves import (filter, input, map, range, zip) # noqa
+
+# Import iris.tests first so that some things can be initialised before
+# importing anything else.
+import iris.tests as tests
+
+import numpy as np
+import numpy.ma as ma
+
+from iris.coords import DimCoord
+from iris.tests.stock import (sample_2d_latlons,
+ make_bounds_discontiguous_at_point)
+
+if tests.MPL_AVAILABLE:
+ import iris.plot as iplt
+
+
+@tests.skip_plot
+class Test_check_bounds_contiguity_and_mask(tests.IrisTest):
+ def test_1d_not_checked(self):
+ # Test a 1D coordinate, which is not checked as atol is not set.
+ coord = DimCoord([1, 3, 5], bounds=[[0, 2], [2, 4], [5, 6]])
+ data = np.array([278, 300, 282])
+ iplt._check_bounds_contiguity_and_mask(coord, data)
+
+ def test_1d_contiguous(self):
+ # Test a 1D coordinate which is contiguous.
+ coord = DimCoord([1, 3, 5], bounds=[[0, 2], [2, 4], [4, 6]])
+ data = np.array([278, 300, 282])
+ iplt._check_bounds_contiguity_and_mask(coord, data, atol=1e-3)
+
+ def test_1d_discontigous_masked(self):
+ # Test a 1D coordinate which is discontiguous but masked at
+ # discontiguities.
+ coord = DimCoord([1, 3, 5], bounds=[[0, 2], [2, 4], [5, 6]])
+ data = ma.array(np.array([278, 300, 282]), mask=[0, 1, 0])
+ iplt._check_bounds_contiguity_and_mask(coord, data, atol=1e-3)
+
+ def test_1d_discontigous_unmasked(self):
+ # Test a 1D coordinate which is discontiguous and unmasked at
+ # discontiguities.
+ coord = DimCoord([1, 3, 5], bounds=[[0, 2], [2, 4], [5, 6]])
+ data = ma.array(np.array([278, 300, 282]), mask=[1, 0, 0])
+ msg = 'coordinate are not contiguous and data is not masked where ' \
+ 'the discontiguity occurs'
+ with self.assertRaisesRegexp(ValueError, msg):
+ iplt._check_bounds_contiguity_and_mask(coord, data, atol=1e-3)
+
+ def test_2d_contiguous(self):
+ # Test a 2D coordinate which is contiguous.
+ cube = sample_2d_latlons()
+ iplt._check_bounds_contiguity_and_mask(cube.coord('longitude'),
+ cube.data)
+
+ def test_2d_discontigous_masked(self):
+ # Test a 2D coordinate which is discontiguous but masked at
+ # discontiguities.
+ cube = sample_2d_latlons()
+ make_bounds_discontiguous_at_point(cube, 3, 4)
+ iplt._check_bounds_contiguity_and_mask(cube.coord('longitude'),
+ cube.data)
+
+ def test_2d_discontigous_unmasked(self):
+ # Test a 2D coordinate which is discontiguous and unmasked at
+ # discontiguities.
+ cube = sample_2d_latlons()
+ make_bounds_discontiguous_at_point(cube, 3, 4)
+ msg = 'coordinate are not contiguous'
+ cube.data[3, 4] = ma.nomask
+ with self.assertRaisesRegexp(ValueError, msg):
+ iplt._check_bounds_contiguity_and_mask(cube.coord('longitude'),
+ cube.data)
+
+
+if __name__ == "__main__":
+ tests.main()
diff --git a/lib/iris/tests/unit/plot/test__get_plot_defn.py b/lib/iris/tests/unit/plot/test__get_plot_defn.py
index 6dfb6f9f11..2947933c7d 100644
--- a/lib/iris/tests/unit/plot/test__get_plot_defn.py
+++ b/lib/iris/tests/unit/plot/test__get_plot_defn.py
@@ -1,4 +1,4 @@
-# (C) British Crown Copyright 2017, Met Office
+# (C) British Crown Copyright 2017 - 2018, Met Office
#
# This file is part of Iris.
#
@@ -24,7 +24,7 @@
import iris.tests as tests
import iris.coords
-from iris.tests.stock import simple_2d
+from iris.tests.stock import simple_2d, simple_2d_w_multidim_coords
if tests.MPL_AVAILABLE:
import iris.plot as iplt
@@ -45,6 +45,12 @@ def test_axis_order_yx(self):
self.assertEqual([coord.name() for coord in defn.coords],
['foo', 'bar'])
+ def test_2d_coords(self):
+ cube = simple_2d_w_multidim_coords()
+ defn = iplt._get_plot_defn(cube, iris.coords.BOUND_MODE)
+ self.assertEqual([coord.name() for coord in defn.coords],
+ ['bar', 'foo'])
+
if __name__ == "__main__":
tests.main()
diff --git a/lib/iris/tests/unit/plot/test__get_plot_defn_custom_coords_picked.py b/lib/iris/tests/unit/plot/test__get_plot_defn_custom_coords_picked.py
new file mode 100644
index 0000000000..d0ce55a389
--- /dev/null
+++ b/lib/iris/tests/unit/plot/test__get_plot_defn_custom_coords_picked.py
@@ -0,0 +1,93 @@
+# (C) British Crown Copyright 2018, Met Office
+#
+# This file is part of Iris.
+#
+# Iris is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Iris is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Iris. If not, see .
+"""Unit tests for the `iris.plot._get_plot_defn_custom_coords_picked`
+function."""
+
+
+from __future__ import (absolute_import, division, print_function)
+from six.moves import (filter, input, map, range, zip) # noqa
+
+# Import iris.tests first so that some things can be initialised before
+# importing anything else.
+import iris.tests as tests
+
+from iris.coords import BOUND_MODE, POINT_MODE
+from iris.tests.stock import (simple_2d, simple_2d_w_multidim_coords,
+ hybrid_height)
+
+
+if tests.MPL_AVAILABLE:
+ import iris.plot as iplt
+
+
+@tests.skip_plot
+class Test_get_plot_defn_custom_coords_picked(tests.IrisTest):
+ def test_1d_coords(self):
+ cube = simple_2d()
+ defn = iplt._get_plot_defn_custom_coords_picked(cube, ('foo', 'bar'),
+ POINT_MODE)
+ self.assertEqual([coord.name() for coord in defn.coords],
+ ['bar', 'foo'])
+ self.assertFalse(defn.transpose)
+
+ def test_1d_coords_swapped(self):
+ cube = simple_2d()
+ defn = iplt._get_plot_defn_custom_coords_picked(cube, ('bar', 'foo'),
+ POINT_MODE)
+ self.assertEqual([coord.name() for coord in defn.coords],
+ ['foo', 'bar'])
+ self.assertTrue(defn.transpose)
+
+ def test_1d_coords_as_integers(self):
+ cube = simple_2d()
+ defn = iplt._get_plot_defn_custom_coords_picked(cube, (1, 0),
+ POINT_MODE)
+ self.assertEqual([coord for coord in defn.coords], [0, 1])
+ self.assertFalse(defn.transpose)
+
+ def test_1d_coords_as_integers_swapped(self):
+ cube = simple_2d()
+ defn = iplt._get_plot_defn_custom_coords_picked(cube, (0, 1),
+ POINT_MODE)
+ self.assertEqual([coord for coord in defn.coords], [1, 0])
+ self.assertTrue(defn.transpose)
+
+ def test_2d_coords(self):
+ cube = simple_2d_w_multidim_coords()
+ defn = iplt._get_plot_defn_custom_coords_picked(cube, ('foo', 'bar'),
+ BOUND_MODE)
+ self.assertEqual([coord.name() for coord in defn.coords],
+ ['bar', 'foo'])
+ self.assertFalse(defn.transpose)
+
+ def test_2d_coords_as_integers(self):
+ cube = simple_2d_w_multidim_coords()
+ defn = iplt._get_plot_defn_custom_coords_picked(cube, (0, 1),
+ BOUND_MODE)
+ self.assertEqual([coord for coord in defn.coords], [1, 0])
+ self.assertTrue(defn.transpose)
+
+ def test_span_check(self):
+ cube = hybrid_height()
+ emsg = 'don\'t span the 2 data dimensions'
+ with self.assertRaisesRegexp(ValueError, emsg):
+ iplt._get_plot_defn_custom_coords_picked(
+ cube, ('sigma', 'level_height'), POINT_MODE)
+
+
+if __name__ == "__main__":
+ tests.main()
From 7455bb1aa2a12080e46501317ae7b54a89946d61 Mon Sep 17 00:00:00 2001
From: Patrick Peglar
Date: Mon, 3 Sep 2018 12:47:45 +0100
Subject: [PATCH 27/62] Tests for rotate_grid_vectors (#3148)
* Tests for rotate_grid_vectors.
* Small fix to assertArrayAllClose for values near 0.
* Small tweaks.
* Fix test method.
* Fix 1 test for 'equal_nans' no longer the default.
* Review changes.
---
lib/iris/tests/__init__.py | 37 +++--
.../cartography/test_rotate_grid_vectors.py | 148 ++++++++++++++++++
.../regrid/test_RectilinearRegridder.py | 3 +-
3 files changed, 173 insertions(+), 15 deletions(-)
create mode 100644 lib/iris/tests/unit/analysis/cartography/test_rotate_grid_vectors.py
diff --git a/lib/iris/tests/__init__.py b/lib/iris/tests/__init__.py
index 7550fce1ca..b7806b455b 100644
--- a/lib/iris/tests/__init__.py
+++ b/lib/iris/tests/__init__.py
@@ -642,7 +642,7 @@ def assertMaskedArrayAlmostEqual(self, a, b, decimal=6, strict=False):
self._assertMaskedArray(np.testing.assert_array_almost_equal, a, b,
strict, decimal=decimal)
- def assertArrayAllClose(self, a, b, rtol=1.0e-7, atol=0.0, **kwargs):
+ def assertArrayAllClose(self, a, b, rtol=1.0e-7, atol=1.0e-8, **kwargs):
"""
Check arrays are equal, within given relative + absolute tolerances.
@@ -660,26 +660,35 @@ def assertArrayAllClose(self, a, b, rtol=1.0e-7, atol=0.0, **kwargs):
Performs pointwise toleranced comparison, and raises an assertion if
the two are not equal 'near enough'.
- For full details see underlying routine numpy.testing.assert_allclose.
+ For full details see underlying routine numpy.allclose.
"""
- ok = np.allclose(a, b, atol=atol, rtol=rtol, equal_nan=True)
+ # Handle the 'err_msg' kwarg, which is the only API difference
+ # between np.allclose and np.testing_assert_allclose.
+ msg = kwargs.pop('err_msg', None)
+ ok = np.allclose(a, b, rtol=rtol, atol=atol, **kwargs)
if not ok:
# Calculate errors above a pointwise tolerance : The method is
# taken from "numpy.core.numeric.isclose".
+ a, b = np.broadcast_arrays(a, b)
errors = (np.abs(a-b) - atol + rtol * np.abs(b))
worst_inds = np.unravel_index(np.argmax(errors.flat), errors.shape)
- # Build a more useful message than from np.testing.assert_allclose.
- msg = ('\nARRAY CHECK FAILED "assertArrayAllClose" :'
- '\n with shapes={} {}, atol={}, rtol={}'
- '\n worst at element {} : a={} b={}'
- '\n absolute error ~{:.3g}, equivalent to rtol ~{:.3e}')
- aval, bval = a[worst_inds], b[worst_inds]
- absdiff = np.abs(aval - bval)
- equiv_rtol = absdiff / bval
- raise AssertionError(msg.format(
- a.shape, b.shape, atol, rtol, worst_inds, aval, bval, absdiff,
- equiv_rtol))
+
+ if msg is None:
+ # Build a more useful message than np.testing.assert_allclose.
+ msg = (
+ '\nARRAY CHECK FAILED "assertArrayAllClose" :'
+ '\n with shapes={} {}, atol={}, rtol={}'
+ '\n worst at element {} : a={} b={}'
+ '\n absolute error ~{:.3g}, equivalent to rtol ~{:.3e}')
+ aval, bval = a[worst_inds], b[worst_inds]
+ absdiff = np.abs(aval - bval)
+ equiv_rtol = absdiff / bval
+ msg = msg.format(
+ a.shape, b.shape, atol, rtol, worst_inds, aval, bval,
+ absdiff, equiv_rtol)
+
+ raise AssertionError(msg)
@contextlib.contextmanager
def temp_filename(self, suffix=''):
diff --git a/lib/iris/tests/unit/analysis/cartography/test_rotate_grid_vectors.py b/lib/iris/tests/unit/analysis/cartography/test_rotate_grid_vectors.py
new file mode 100644
index 0000000000..90ec37e162
--- /dev/null
+++ b/lib/iris/tests/unit/analysis/cartography/test_rotate_grid_vectors.py
@@ -0,0 +1,148 @@
+# (C) British Crown Copyright 2018, Met Office
+#
+# This file is part of Iris.
+#
+# Iris is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Iris is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Iris. If not, see .
+"""
+Unit tests for the function
+:func:`iris.analysis.cartography.rotate_grid_vectors`.
+
+"""
+from __future__ import (absolute_import, division, print_function)
+from six.moves import (filter, input, map, range, zip) # noqa
+
+# Import iris.tests first so that some things can be initialised before
+# importing anything else.
+import iris.tests as tests
+
+from mock import Mock, call as mock_call
+import numpy as np
+
+from iris.cube import Cube
+from iris.tests.stock import sample_2d_latlons
+
+from iris.analysis.cartography import rotate_grid_vectors
+
+
+class TestRotateGridVectors(tests.IrisTest):
+ def _check_angles_calculation(self, angles_in_degrees=True,
+ nan_angles_mask=None):
+ # Check basic maths on a 2d latlon grid.
+ u_cube = sample_2d_latlons(regional=True, transformed=True)
+ u_cube.units = 'ms-1'
+ u_cube.rename('dx')
+ u_cube.data[...] = 0
+ v_cube = u_cube.copy()
+ v_cube.name('dy')
+
+ # Define 6 different vectors, repeated in each data row.
+ in_vu = np.array([(0, 1), (2, -1), (-1, -1), (-3, 1), (2, 0), (0, 0)])
+ in_angs = np.rad2deg(np.arctan2(in_vu[..., 0], in_vu[..., 1]))
+ in_mags = np.sqrt(np.sum(in_vu * in_vu, axis=1))
+ v_cube.data[...] = in_vu[..., 0]
+ u_cube.data[...] = in_vu[..., 1]
+
+ # Define 5 different test rotation angles, one for each data row.
+ rotation_angles = np.array([0., -45., 135, -140., 90.])
+ ang_cube_data = np.broadcast_to(rotation_angles[:, None],
+ u_cube.shape)
+ ang_cube = u_cube.copy()
+ if angles_in_degrees:
+ ang_cube.units = 'degrees'
+ else:
+ ang_cube.units = 'radians'
+ ang_cube_data = np.deg2rad(ang_cube_data)
+ ang_cube.data[:] = ang_cube_data
+
+ if nan_angles_mask is not None:
+ ang_cube.data[nan_angles_mask] = np.nan
+
+ # Rotate all vectors by all the given angles.
+ result = rotate_grid_vectors(u_cube, v_cube, ang_cube)
+ out_u, out_v = [cube.data for cube in result]
+
+ # Check that vector magnitudes were unchanged.
+ out_mags = np.sqrt(out_u * out_u + out_v * out_v)
+ expect_mags = in_mags[None, :]
+ self.assertArrayAllClose(out_mags, expect_mags)
+
+ # Check that vector angles are all as expected.
+ out_angs = np.rad2deg(np.arctan2(out_v, out_u))
+ expect_angs = in_angs[None, :] + rotation_angles[:, None]
+ ang_diffs = out_angs - expect_angs
+ # Fix for null vectors, and +/-360 differences.
+ ang_diffs[np.abs(out_mags) < 0.001] = 0.0
+ ang_diffs = ang_diffs % 360.0
+ # Check that any differences are very small.
+ self.assertArrayAllClose(ang_diffs, 0.0)
+
+ # Check that results are always masked arrays, masked at NaN angles.
+ self.assertTrue(np.ma.isMaskedArray(out_u))
+ self.assertTrue(np.ma.isMaskedArray(out_v))
+ if nan_angles_mask is not None:
+ self.assertArrayEqual(out_u.mask, nan_angles_mask)
+ self.assertArrayEqual(out_v.mask, nan_angles_mask)
+
+ def test_angles_calculation(self):
+ self._check_angles_calculation()
+
+ def test_angles_in_radians(self):
+ self._check_angles_calculation(angles_in_degrees=False)
+
+ def test_angles_from_grid(self):
+ # Check it will gets angles from 'u_cube', and pass any kwargs on to
+ # the angles routine.
+ u_cube = sample_2d_latlons(regional=True, transformed=True)
+ u_cube = u_cube[:2, :3]
+ u_cube.units = 'ms-1'
+ u_cube.rename('dx')
+ u_cube.data[...] = 1.0
+ v_cube = u_cube.copy()
+ v_cube.name('dy')
+ v_cube.data[...] = 0.0
+
+ # Setup a fake angles result from the inner call to 'gridcell_angles'.
+ angles_result_data = np.array([[0.0, 90.0, 180.0],
+ [-180.0, -90.0, 270.0]])
+ angles_result_cube = Cube(angles_result_data, units='degrees')
+ angles_kwargs = {'this': 2}
+ angles_call_patch = self.patch(
+ 'iris.analysis._grid_angles.gridcell_angles',
+ Mock(return_value=angles_result_cube))
+
+ # Call the routine.
+ result = rotate_grid_vectors(u_cube, v_cube,
+ grid_angles_kwargs=angles_kwargs)
+
+ self.assertEqual(angles_call_patch.call_args_list,
+ [mock_call(u_cube, this=2)])
+
+ out_u, out_v = [cube.data for cube in result]
+ # Records what results should be for the various n*90deg rotations.
+ expect_u = np.array([[1.0, 0.0, -1.0],
+ [-1.0, 0.0, 0.0]])
+ expect_v = np.array([[0.0, 1.0, 0.0],
+ [0.0, -1.0, -1.0]])
+ # Check results are as expected.
+ self.assertArrayAllClose(out_u, expect_u)
+ self.assertArrayAllClose(out_v, expect_v)
+
+ def test_nan_vectors(self):
+ bad_angle_points = np.zeros((5, 6), dtype=bool)
+ bad_angle_points[2, 3] = True
+ self._check_angles_calculation(nan_angles_mask=bad_angle_points)
+
+
+if __name__ == "__main__":
+ tests.main()
diff --git a/lib/iris/tests/unit/analysis/regrid/test_RectilinearRegridder.py b/lib/iris/tests/unit/analysis/regrid/test_RectilinearRegridder.py
index ca86e5cdd7..6035630aae 100644
--- a/lib/iris/tests/unit/analysis/regrid/test_RectilinearRegridder.py
+++ b/lib/iris/tests/unit/analysis/regrid/test_RectilinearRegridder.py
@@ -86,7 +86,8 @@ def assert_values(self, values):
result = regrid(self.data, self.x_dim, self.y_dim,
self.x, self.y,
np.array([xs]), np.array([ys]))
- self.assertArrayAllClose(result, expecteds, rtol=1e-04)
+ self.assertArrayAllClose(result, expecteds, rtol=1e-04,
+ equal_nan=True)
# Check that transposing the input data results in the same values
ndim = self.data.ndim
From 42a90a260d217f59080825e0900e1f1c9c1cc366 Mon Sep 17 00:00:00 2001
From: Patrick Peglar
Date: Mon, 3 Sep 2018 14:17:00 +0100
Subject: [PATCH 28/62] Remove 'skip_2d' test decorator. (#3156)
---
lib/iris/tests/__init__.py | 6 ------
1 file changed, 6 deletions(-)
diff --git a/lib/iris/tests/__init__.py b/lib/iris/tests/__init__.py
index b7806b455b..84d4614c0e 100644
--- a/lib/iris/tests/__init__.py
+++ b/lib/iris/tests/__init__.py
@@ -1221,12 +1221,6 @@ class MyPlotTests(test.GraphicsTest):
'Test(s) require "python-stratify", which is not available.')
-SKIP_2D_TESTS = True
-skip_2d = unittest.skipIf(
- SKIP_2D_TESTS,
- 'Test(s) broken by WIP on 2d coords support -- temporarily disabled.')
-
-
def no_warnings(func):
"""
Provides a decorator to ensure that there are no warnings raised
From 2d6c6a4a66ca6ae9d7cf910e53bbcd197ac590f4 Mon Sep 17 00:00:00 2001
From: lbdreyer
Date: Mon, 3 Sep 2018 14:52:55 +0100
Subject: [PATCH 29/62] Add integration graphics tests for pcolormesh with 2d
coords (#3149)
---
.../integration/plot/test_plot_2d_coords.py | 67 ++
lib/iris/tests/results/imagerepo.json | 1036 +++++++++--------
2 files changed, 588 insertions(+), 515 deletions(-)
create mode 100644 lib/iris/tests/integration/plot/test_plot_2d_coords.py
diff --git a/lib/iris/tests/integration/plot/test_plot_2d_coords.py b/lib/iris/tests/integration/plot/test_plot_2d_coords.py
new file mode 100644
index 0000000000..5b63b10959
--- /dev/null
+++ b/lib/iris/tests/integration/plot/test_plot_2d_coords.py
@@ -0,0 +1,67 @@
+# (C) British Crown Copyright 2018, Met Office
+#
+# This file is part of Iris.
+#
+# Iris is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Iris is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Iris. If not, see .
+"""
+Test plots with two dimensional coordinates.
+
+"""
+
+from __future__ import (absolute_import, division, print_function)
+from six.moves import (filter, input, map, range, zip) # noqa
+
+# import iris tests first so that some things can be initialised before
+# importing anything else
+import iris.tests as tests
+
+import cartopy.crs as ccrs
+import matplotlib.pyplot as plt
+
+import iris
+
+# Run tests in no graphics mode if matplotlib is not available.
+if tests.MPL_AVAILABLE:
+ import iris.quickplot as qplt
+
+
+@tests.skip_data
+def simple_cube_w_2d_coords():
+ path = tests.get_data_path(('NetCDF', 'ORCA2', 'votemper.nc'))
+ cube = iris.load_cube(path)
+ return cube
+
+
+@tests.skip_plot
+@tests.skip_data
+class Test(tests.GraphicsTest):
+ def test_2d_coord_bounds_platecarree(self):
+ # To avoid a problem with Cartopy smearing the data where the
+ # longitude wraps, we set the central_longitude
+ cube = simple_cube_w_2d_coords()[0, 0]
+ ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=180))
+ qplt.pcolormesh(cube)
+ ax.coastlines(color='red')
+ self.check_graphic()
+
+ def test_2d_coord_bounds_northpolarstereo(self):
+ cube = simple_cube_w_2d_coords()[0, 0]
+ ax = plt.axes(projection=ccrs.NorthPolarStereo())
+ qplt.pcolormesh(cube)
+ ax.coastlines(color='red')
+ self.check_graphic()
+
+
+if __name__ == "__main__":
+ tests.main()
diff --git a/lib/iris/tests/results/imagerepo.json b/lib/iris/tests/results/imagerepo.json
index 51d37daf3c..e7614cae19 100644
--- a/lib/iris/tests/results/imagerepo.json
+++ b/lib/iris/tests/results/imagerepo.json
@@ -1,946 +1,952 @@
{
"example_tests.test_COP_1d_plot.TestCOP1DPlot.test_COP_1d_plot.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/baff589936602d8ec977334ae4dac9b61a6dc4d99532c86cc2913e36c4cc0f61.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/baff589936602d8ec977334ae4dac9b61a6dc4d99532c86cc2913e36c4cc0f61.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/aefec91c3601249cc9b3336dc4c8cdb31a64c6d997b3c0eccb5932d285e42f33.png"
- ],
+ ],
"example_tests.test_COP_maps.TestCOPMaps.test_cop_maps.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea9138db95668524913e6ac168997e85957e917e876396b96a81b5ce3c496935.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea9138db95668524913e6ac168997e85957e917e876396b96a81b5ce3c496935.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea9130db95668524913c6ac178995b0d956e917ec76396b96a853dcf94696935.png"
- ],
+ ],
"example_tests.test_SOI_filtering.TestSOIFiltering.test_soi_filtering.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fac460b9c17b78723e05a5a9954edaf062332799954e9ca5c63b9a52d24e5a95.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa8460b9c17b78723e05a5a9954edaf062333799954e9ca5c63b9a52d24e4a9d.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fac460b9c17b78723e05a5a9954edaf062332799954e9ca5c63b9a52d24e5a95.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa8460b9c17b78723e05a5a9954edaf062333799954e9ca5c63b9a52d24e4a9d.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa167295c5e0696a3c17a58c9568da536233da19994cdab487739b4b9b444eb5.png"
- ],
+ ],
"example_tests.test_TEC.TestTEC.test_TEC.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e1a561b69b1a9a42846e9a49c7596e3cce6c907b3a83c17e1b8239b3e4f33bc4.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e1a561b69b1a9e43846e9a49c7596e2cce6c907b3a83c16e1b9231b3e4f33b8c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e1a561b69b1a9a42846e9a49c7596e3cce6c907b3a83c17e1b8239b3e4f33bc4.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e1a561b69b1a9e43846e9a49c7596e2cce6c907b3a83c16e1b9231b3e4f33b8c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e5a761b69a589a4bc46f9e48c65c6631ce61d1ce3982c13739b33193c0ee3f8c.png"
- ],
+ ],
"example_tests.test_anomaly_log_colouring.TestAnomalyLogColouring.test_anomaly_log_colouring.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ec4464e185a39f93931e9b1e91696d2949dde6e63e26a47a5ad391938d9a5a0c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ec4464e185a39f93931e9b1e91696d2949dde6e63e26a47a5ad391938d9a5a0c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ecc164e78e979b19b3789b0885a564a56cc2c65e3ec69469db1bdb9a853c1e24.png"
- ],
+ ],
"example_tests.test_atlantic_profiles.TestAtlanticProfiles.test_atlantic_profiles.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/9f8260536bd28e1320739437b5f437b0a51d66f4cc5d08fcd00fdb1c93fcb21c.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/9f8260536bd28e1320739437b5f437b0a51d66f4cc7c09f4d00fdb1c93fcb21c.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/9f8a60536bd28e1320739437b5f437b0a53d66f4cc5c08f4d00fdb1c93fcb21c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/9f8260536bd28e1320739437b5f437b0a51d66f4cc5d08fcd00fdb1c93fcb21c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/9f8260536bd28e1320739437b5f437b0a51d66f4cc7c09f4d00fdb1c93fcb21c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/9f8a60536bd28e1320739437b5f437b0a53d66f4cc5c08f4d00fdb1c93fcb21c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/9fc060f462a08f07203ebc77a1f36707e61f4e38d8f7d08a910197fc877cec58.png"
- ],
+ ],
"example_tests.test_atlantic_profiles.TestAtlanticProfiles.test_atlantic_profiles.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a6eaa57e6e81ddf999311ba3b3775e20845d5889c199673b4e22a4675e8ca11c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a6eaa57e6e81ddf999311ba3b3775e20845d5889c199673b4e22a4675e8ca11c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eeea64dd6ea8cd99991f1322b3761e06845718d89995b3131f32a4765ec2a1cd.png"
- ],
+ ],
"example_tests.test_coriolis_plot.TestCoriolisPlot.test_coriolis_plot.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e78665de9a699659e55e9965886979966986c5e63e98c19e3a256679e1981a24.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e78665de9a699659e55e9965886979966986c5e63e98c19e3a256679e1981a24.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e68665de9a699659c1fe99a5896965966996c46e3e19c1da3a652669c51e1a26.png"
- ],
+ ],
"example_tests.test_cross_section.TestCrossSection.test_cross_section.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea95317b9562e4d1649f5a05856e4ca4da52947e4ea5f13f1b499d42f13b1b41.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea95317b9562e4d1649f5a05856e4ca4da52947e4ea5f13f1b499d42f13b1b41.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea91b17b9562e4d1609f5a05856e4ca45a52957e5ea5f13b1bca9dc0b17b1ac1.png"
- ],
+ ],
"example_tests.test_cross_section.TestCrossSection.test_cross_section.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea9521fb956a394069921e93f07f4aad856cc47e4e95857a1ea5da3591ba1b81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea9521fb956a394069921e93f07f4aad856cc47e4e95857a1ea5da3591ba1b81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea9521fb956a394068931e9be07e4aa5856cc47e4a91957a1ba55bb5b17a3b81.png"
- ],
+ ],
"example_tests.test_custom_aggregation.TestCustomAggregation.test_custom_aggregation.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fe816e81917e907eb43e873f85677ac190f0703c6a95811f1ac33ce1a57a6f18.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fe816e81917e907eb43e873f85677ac190f0703c6a95811f1ac33ce1a57a6f18.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fe816e81817e907eb43e873f85637ac198d8703c6a94811f1ac73ee1a57a6f90.png"
- ],
+ ],
"example_tests.test_custom_file_loading.TestCustomFileLoading.test_custom_file_loading.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/faa0cbf1845e34be913787416edcc8bc3bc81f9b63332662a4ed30cdc1b2cd21.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fba0cbf1845e34be912787416edcc8bc3b881f9b62332762a5ad32cdc1b2cd21.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/faa0cbf1845e34be913787416edcc8bc3bc81f9b63332662a4ed30cdc1b2cd21.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fba0cbf1845e34be912787416edcc8bc3b881f9b62332762a5ad32cdc1b2cd21.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/faa1cb47845e34bc912797436cccc8343f11359b73523746c48c72d9d9b34da5.png"
- ],
+ ],
"example_tests.test_deriving_phenomena.TestDerivingPhenomena.test_deriving_phenomena.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/b9993986866952e6c9464639c4766bd9c669916e7b99c1663f99768990763e81.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/b99139de866952e6c946c639c47e6bd18769d16e7a9981662e813699d0763e89.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/b9993986866952e6c9464639c4766bd9c669916e7b99c1663f99768990763e81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/b99139de866952e6c946c639c47e6bd18769d16e7a9981662e813699d0763e89.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ec97681793689768943c97e8926669d186e8c33f6c99c32e6b936c83d33e2c98.png"
- ],
+ ],
"example_tests.test_global_map.TestGlobalMap.test_global_map.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa9979468566857ef07e3e8978566b91cb0179883c89946686a96b9d83766f81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa9979468566857ef07e3e8978566b91cb0179883c89946686a96b9d83766f81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa997b958466846ed13e87467a997a898d66d17e2cc9906684696f99d3162f81.png"
- ],
+ ],
"example_tests.test_hovmoller.TestGlobalMap.test_hovmoller.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bab430b4ce4bce43c5becf89c54b1a63c543c56e1e64907e3bb469b490de1ac1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bab430b4ce4bce43c5becf89c54b1a63c543c56e1e64907e3bb469b490de1ac1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eeb46cb4934b934bc07e974bc14b38949943c0fe3e94c17f6ea46cb4c07b3f00.png"
- ],
+ ],
"example_tests.test_inset_plot.TestInsetPlot.test_inset_plot.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ebff6992f50096a5b245dac4f6559496b49248dbc95dcb699529912dcf244a54.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e9ff6992b50096a5b245dac4f64594b6b49248dbc95dcb699529952dcf244a56.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ebff6992f50096a5b245dac4f6559496b49248dbc95dcb699529912dcf244a54.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e9ff6992b50096a5b245dac4f64594b6b49248dbc95dcb699529952dcf244a56.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ebff6992b50096ad9267dac4d64094b294924cdbc95d4b699d29952dcda46e94.png"
- ],
+ ],
"example_tests.test_lagged_ensemble.TestLaggedEnsemble.test_lagged_ensemble.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bbbb31e1c44e64e4b0459b5bb1716ecac464f496ce34618eb1079b39b193ce25.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bbbb31e1c44e64e4b0459b5bb1716ecac464f496ce34618eb1079b39b193ce25.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bbbb31b1c44e64e4b1579b5b917133cecc61f146c414668eb1119b1bb197ce34.png"
- ],
+ ],
"example_tests.test_lagged_ensemble.TestLaggedEnsemble.test_lagged_ensemble.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/abfef958fd462c993a07d87960464b81d1009687c139d3b594e9cf87c6b89687.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/abfef958fd462c993a07d87960464b81d1009687c139d3b594e9cf87c6b89687.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/aafec5e9e5e03e099a07e0f86542db879438261ec3b13ce78d8dc65a92d83d89.png"
- ],
+ ],
"example_tests.test_lineplot_with_legend.TestLineplotWithLegend.test_lineplot_with_legend.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/eae942526540b869961f8da694589da69543cc9af1014afbc3fd596b84fe19a7.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/eae942146540b869961f8de694589da69543cc9af1014afbc3fd596b84fe19a7.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eae942526540b869961f8da694589da69543cc9af1014afbc3fd596b84fe19a7.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eae942146540b869961f8de694589da69543cc9af1014afbc3fd596b84fe19a7.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eafd9e12a5a061e9925ec716de489e9685078ec981b229e70ddb79219cc3768d.png"
- ],
+ ],
"example_tests.test_orca_projection.TestOrcaProjection.test_orca_projection.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fb11731a94cea4ee64b35e91d1d2304e9e5ac7397b20e1fe12852487e666ce46.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fb11731a94cea4ee64b35e91d1d2304e9e5ac7397b20e1fe12852487e666ce46.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bb11721a87cce5e4cce79e81d19b3b5e1e1cd3783168e07835853485e65e2e1e.png"
- ],
+ ],
"example_tests.test_orca_projection.TestOrcaProjection.test_orca_projection.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e5a665a69a599659e5db1865c2653b869996cce63e99e19a1a912639e7181e65.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e5a665a69a599659e5db1865c2653b869996cce63e99e19a1a912639e7181e65.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e58661969e799659c1f719a6c867359a1996c0773649c09c3e612679c07b3f66.png"
- ],
+ ],
"example_tests.test_orca_projection.TestOrcaProjection.test_orca_projection.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/f2c464ce9e399332e1b74ce1cc79338c6586e5b33b31b37a66c9664cc06e1a64.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/f2c464ce9e399332e1b74ce1cc79338c6586e5b33b31b37a66c9664cc06e1a64.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a58660ce9e739b31c93d1cc9c8df33863383e33b3f11c03f2664366cc8ee3cc1.png"
- ],
+ ],
"example_tests.test_orca_projection.TestOrcaProjection.test_orca_projection.3": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa817a83846ea46ce539c93391de32cc86cf87a33fa168721cdb3e896e374b04.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa817a83846ea46ce539c93391de32cc86cf87a33fa168721cdb3e896e374b04.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be817a87845ea56cec79817a919e338436a5c1e73fa16c736c4a3e816a1e6b1c.png"
- ],
+ ],
"example_tests.test_polar_stereo.TestPolarStereo.test_polar_stereo.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e168317a92d36d89c5bb9e94c55e6f0c9a93c15a6ec584763b21716791de3a81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e168317a92d36d89c5bb9e94c55e6f0c9a93c15a6ec584763b21716791de3a81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/b9e16079971e9e93c8ce0f84c31e3b929f92c0ff3ca1c17e39e03961c07e3f80.png"
- ],
+ ],
"example_tests.test_polynomial_fit.TestPolynomialFit.test_polynomial_fit.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/abff4a9df26435886520c97f12414695c4b69d23934bc86adc969237d68ccc6f.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/aaff4a9df26435886520c97f12414695c4b69d23934bc86adc969a17d69ccc6f.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/abff4a9df26435886520c97f12414695c4b69d23934bc86adc969237d68ccc6f.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/aaff4a9df26435886520c97f12414695c4b69d23934bc86adc969a17d69ccc6f.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/aeffcb34d244348be5a2c96c3a4fc6d0c4b69f2d87294ccb9f1a125684cd7c11.png"
- ],
+ ],
"example_tests.test_projections_and_annotations.TestProjectionsAndAnnotations.test_projections_and_annotations.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa854f19851a30e4cc76cd0bb179325ca7c665b0c938cb4b4e719e9cb727b5c0.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fac54f19851a30e4cc76cd0bb179325cb78665b0c938cb4b4e719e9c9727b5c0.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa854e19851a30e4cc76cd0bb179325cb7c664b0c938cb4bce739e9c37a3b5c0.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa854e19851a30e4cc76cd0bb179325cb78665b1c938c94bce739e9c3727b5c0.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa854f19851a30e4cc76cd0bb179325ca7c665b0c938cb4b4e719e9cb727b5c0.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fac54f19851a30e4cc76cd0bb179325cb78665b0c938cb4b4e719e9c9727b5c0.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa854e19851a30e4cc76cd0bb179325cb7c664b0c938cb4bce739e9c37a3b5c0.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa854e19851a30e4cc76cd0bb179325cb78665b1c938c94bce739e9c3727b5c0.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa854f19851a30e4cc76cd0bb0f932dca7c665b1c92ccb4b4ed19e9c3721b5c8.png"
- ],
+ ],
"example_tests.test_projections_and_annotations.TestProjectionsAndAnnotations.test_projections_and_annotations.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e385699d9c3896627243318fcdad5a7dc6dba492e9b69964936dc21974b18592.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e385699d9c3896727243318f8dad5a7dc65ba492b93699649b6dc25b64938592.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e385699d9c3896627243318fcdad5a7dc6dba492b93699649b6dc25964938592.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e3856b999c3896727243318f8dad5a75965ba492f9b69964db4cc65b64918592.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e3856b999c3896727243318f8dad5a75865ba492e9b69964db6cc65b74918592.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e385699d9c3896627243318fcdad5a7dc6dba492e9b69964936dc21974b18592.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e385699d9c3896727243318f8dad5a7dc65ba492b93699649b6dc25b64938592.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e385699d9c3896627243318fcdad5a7dc6dba492b93699649b6dc25964938592.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e3856b999c3896727243318f8dad5a75965ba492f9b69964db4cc65b64918592.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e3856b999c3896727243318f8dad5a75865ba492e9b69964db6cc65b74918592.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e3856d999c389662734731afcdad5a7384daa592b1b69b64d26dc29974b18590.png"
- ],
+ ],
"example_tests.test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa15615e97a193adc15e1e81c4fa3eb49d30817e3e05c17e7ba59927817e1e01.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa15615e97a193adc15e1e81c4fa3eb49d30817e3e05c17e7ba59927817e1e01.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ee46607e97a19781c0df1f81d0bb3e241f20c16f3fc0c1fe39263d33d06f3e80.png"
- ],
+ ],
"example_tests.test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ba056717c3e099e9b90f8e81c4da589499b696763e45e56b3b893929c17b7e01.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ba056717c3e099e9b90f8e81c4da589499b696763e45e56b3b893929c17b7e01.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea57685f95a886a1c0de9da090be3e2697e1c0ff3f00c17e6b266c17c07f3f00.png"
- ],
+ ],
"example_tests.test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ba1e605ec7a191a1b85e9e81c4da58909996b37e3a65e16f7b817939e57a1e01.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ba1e605ec7a193a1b85e9e81c4da58909996b3763a65e16f7b816939ed7a1e01.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ba1e605ec7a191a1b85e9e81c4da58909996b37e3a65e16f7b817939e57a1e01.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ba1e605ec7a193a1b85e9e81c4da58909996b3763a65e16f7b816939ed7a1e01.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e85a697e97a18681c6da9f8190bf3e263624c1ef3b48c17a2b223c47c0ff3f81.png"
- ],
+ ],
"example_tests.test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.3": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa8172d0847ecd2bc913939c36846c714933799cc3cc8727e67639f939996a58.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa8172d0847ecd2bc913939c36846c714933799cc3cc8727e67639f939996a58.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa8172c6857ecd38cb3392ce36c564311931d85ec64e9787719a39993c316e66.png"
- ],
+ ],
"example_tests.test_wind_speed.TestWindSpeed.test_wind_speed.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bcf924fb9306930ce12ccf97c73236b28ecec4cd3e29847b18e639e6c14f1a09.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bcf924fb9306930ce12ccf97c73236b28ecec4cd3e29847b18e639e6c14f1a09.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e9e960e996169306c1ee9e96c29e36739e13c07d3d61c07f39a139a1c07f3f01.png"
- ],
+ ],
"example_tests.test_wind_speed.TestWindSpeed.test_wind_speed.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bcf924fb9306930ce12ccf97c73236b28ecec4cc3e29847b38e639e6c14f1a09.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bcf924fb9306930ce12ccf97c73236b28ecec4cc3e29847b38e639e6c14f1a09.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e9e960e996169306c1ee9e86c29e36739e13c07d3d61c07f39a139a1c17f3f01.png"
- ],
+ ],
"iris.tests.experimental.test_animate.IntegrationTest.test_cube_animation.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fe81957ac17e6a85817e6a85857e942a3e81957a7e81917a7a81d95ec17e2ca1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fe81957ac17e6a85817e6a85857e942a3e81957a7e81917a7a81d95ec17e2ca1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fe81c17e817e3e81817e7e81857e7e817e81c07e7e81c17e7a81817e817e8c2a.png"
- ],
+ ],
"iris.tests.experimental.test_animate.IntegrationTest.test_cube_animation.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/be81c17ec17e7e81c17e3e81c57ea55a3e80c17e3e81c1fe7a81c285c95f2c03.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/be81c17ec17e7e81c17e3e81c57ea55a3e80c17e3e81c1fe7a81c285c95f2c03.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fe81857e817e6a85817e7a81857e7e817e81957a7e81817e7a81817e817e843e.png"
- ],
+ ],
"iris.tests.experimental.test_animate.IntegrationTest.test_cube_animation.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea857a81957a857e957ec17e817e6a816a853e817a853e816e818d3a862ad3fe.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea857a81957a857e957ec17e817e6a816a853e817a853e816e818d3a862ad3fe.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be81857ec17e7a81c17e7e81857e3e803e81817a3e81c17e7a81c17ec97e2c2b.png"
- ],
+ ],
+ "iris.tests.integration.plot.test_plot_2d_coords.Test.test_2d_coord_bounds_northpolarstereo.0": [
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e59661969e699659c0f719a6c967339a1992c07f3649c09c3f612669c07b3f66.png"
+ ],
+ "iris.tests.integration.plot.test_plot_2d_coords.Test.test_2d_coord_bounds_platecarree.0": [
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ee816299954a1da699b6915ec25b6e419729c42c3f84bd9fe6d262d1d1dac076.png"
+ ],
"iris.tests.test_analysis.TestProject.test_cartopy_projection.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/9e1952c9c165b4fc668a9d47c1461d7a60fb2e853eb426bd62fd229c9f04c16d.png"
- ],
+ ],
"iris.tests.test_mapping.TestBasic.test_contourf.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e85a69cc96ad92e193c9963385929e1cc3819acde6d965ce6e666b30386e65b1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e85a69cc96ad92e193c9963385929e1cc3819acde6d965ce6e666b30386e65b1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e97a346c9685cb899685c9c39695c79396ec634969ce2c74697a3864697b3c8c.png"
- ],
+ ],
"iris.tests.test_mapping.TestBasic.test_pcolor.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e95a69c896a592e59bc99e3384929636c32d98cde6d964ce7e666332386465b1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e95a69c896a592e59bc99e3384929636c32d98cde6d964ce7e666332386465b1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e97a347c96858b8d9685c9c39696c393966c634969ce3c64697a3864697b3c9c.png"
- ],
+ ],
"iris.tests.test_mapping.TestBasic.test_unmappable.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/eaa5684eb54a947ad09eb731c521978dc2fb1cc0e4966ce26e2c6b2d3a6e691a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eaa5684eb54a947ad09eb731c521978dc2fb1cc0e4966ce26e2c6b2d3a6e691a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea853e48957ac1df957ac8be852bc1b1944e7a9878e03f4c6a253e6c7a912dc2.png"
- ],
+ ],
"iris.tests.test_mapping.TestBoundedCube.test_grid.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa81917e857e6e81857e7a857a81917a7a81857e857e7e81857e7a817a81852e.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7a81857e7a817a81817e7a81857e857e7a81857e7a817a81857e.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81917e857e6e81857e7a857a81917a7a81857e857e7e81857e7a817a81852e.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7a81857e7a817a81817e7a81857e857e7a81857e7a817a81857e.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7a81857e7a817a81857a7a81857e857e7a85857e7a817a81857a.png"
- ],
+ ],
"iris.tests.test_mapping.TestBoundedCube.test_pcolormesh.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa81e535857e92ca8ec23d21b13ce15e7a811ea5c47e1a5ac17b652d3b05e4f2.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81e535857e92ca8ec23d21b13ce15e7a811ea5c47e1a5ac17b652d3b05e4f2.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81c17a857e1ea5857e634a7a81cd257e8584da857e3b29817e68f47a81c791.png"
- ],
+ ],
"iris.tests.test_mapping.TestLimitedAreaCube.test_grid.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bf80e2b1c17f1d0ac4f7c8d739a637202749699b6bb3ce3666e4b048944d9d89.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/bf80e2f1c17f1d0ac457c8d619a637213749699b6bb34e3666e4b04e944d9d89.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bf80e2b1c17f1d0ac4f7c8d739a637202749699b6bb3ce3666e4b048944d9d89.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bf80e2f1c17f1d0ac457c8d619a637213749699b6bb34e3666e4b04e944d9d89.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea05392995bac6d691ce3f21666569d86a96c6360ee195cb91e8ce54953b313b.png"
- ],
+ ],
"iris.tests.test_mapping.TestLimitedAreaCube.test_outline.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e3e80857e7a817a817a817a81817f7a81857e857e857e857e7a81.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7e21857e7a817a817a857a81857a7a81857a857e857a857e7a84.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e3e80857e7a817a817a817a81817f7a81857e857e857e857e7a81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7e21857e7a817a817a857a81857a7a81857a857e857a857e7a84.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa1585e885e87a1785fa7a177a177e807a1585e85fa0857a85e86817857f6a16.png"
- ],
+ ],
"iris.tests.test_mapping.TestLimitedAreaCube.test_pcolormesh.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bf81e6b1c17e1d4884bfc8df39a43720374969db69b34e26c4e4b0ca904f9d89.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bf81e6b1c17e1d4884bfc8df39a43720374969db69b34e26c4e4b0ca904f9d89.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea57396995a8c6d691ea3f25664569d86b16c63686ed958991ea4a549531393b.png"
- ],
+ ],
"iris.tests.test_mapping.TestLimitedAreaCube.test_scatter.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea053d2e916ac2d9c4d894346b24f3477acf68ad39329ed8c696e136c1ab9a71.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea053d2e916ac2d9c4d895346b2473477acf68ad39329ed8c69ee126c1ab9a71.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea053d2e916ac2d9c4d894346b24f3477acf68ad39329ed8c696e136c1ab9a71.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea053d2e916ac2d9c4d895346b2473477acf68ad39329ed8c69ee126c1ab9a71.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea05bd2e916ac2d984983d346b2473477acf69ad3d3296d8c696e126c1ab1e71.png"
- ],
+ ],
"iris.tests.test_mapping.TestLowLevel.test_keywords.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/be21a71bc1de58e43a31871f7e856470c1fa9b8c7b81647384665b9ed1b998c1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/be21a71bc1de58e43a31871f7e856470c1fa9b8c7b81647384665b9ed1b998c1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be21a71bc1de58e43a63a71b3e016061c1fe9b8c3e01a473847e5b94d1fb9ac3.png"
- ],
+ ],
"iris.tests.test_mapping.TestLowLevel.test_keywords.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea811831957fe3cea68c6ce0d9f29b9b6a816463953e61cc917f1ae36ac09d38.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea811831957fe3cea68c6ce0d9f29b9b6a816463953e61cc917f1ae36ac09d38.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa819097857e6560957e7bcc7a819c316e81951e857e62c281fe79a17aa19637.png"
- ],
+ ],
"iris.tests.test_mapping.TestLowLevel.test_params.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ee819cb7913b63c8846e64737bb1999c6ec52633953a69c8916f6c636e92911c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ee819cb7913b63c8846e64737bb1999c6ec52633953a69c8916f6c636e92911c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa8190be857e6739917a7bc47a8594337bb1911c857e6ec3913279007e819637.png"
- ],
+ ],
"iris.tests.test_mapping.TestLowLevel.test_params.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/be21a71bc1de58e43a31871f7e856470c1fa9b8c7b81647384665b9ed1b998c1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/be21a71bc1de58e43a31871f7e856470c1fa9b8c7b81647384665b9ed1b998c1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be21a71bc1de58e43a63a71b3e016061c1fe9b8c3e01a473847e5b94d1fb9ac3.png"
- ],
+ ],
"iris.tests.test_mapping.TestLowLevel.test_params.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea811831957ae3cea68c6ce0c9f39b9b6a816473953e63cc917f1ae36ac09d38.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea811831957ae3cea68c6ce0c9f39b9b6a816473953e63cc917f1ae36ac09d38.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81909f857e6520957e5bcc7a8194716e31851e857e6ac281fe3f817a81963f.png"
- ],
+ ],
"iris.tests.test_mapping.TestLowLevel.test_simple.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/eae0943295154bcc844e6c314fb093ce7bc7c4b3a4307bc4916f3f316ed2b4ce.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eae0943295154bcc844e6c314fb093ce7bc7c4b3a4307bc4916f3f316ed2b4ce.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/faa0e55c855fdce7857a1ab16a85a50c3ea1e55e856658a5c11837096e8fe17a.png"
- ],
+ ],
"iris.tests.test_mapping.TestMappingSubRegion.test_simple.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bd913e01d07ee07e926e87876f8196c1e0d36967393c1f181e2c3cb8b0f960d7.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bd913e01d07ee07e926e87876f8196c1e0d36967393c1f181e2c3cb8b0f960d7.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/b9913d90c66eca6ec66ec2f3689195b6cf5b2f00392cb3496695621d34db6c92.png"
- ],
+ ],
"iris.tests.test_mapping.TestUnmappable.test_simple.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fe818d6ac17e5a958d7ab12b9d677615986e666dc4f20dea7281d98833889b22.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fe818d6ac17e5a958d7ab12b9d677615986e666dc4f20dea7281d98833889b22.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81b54a817eca35817ec701857e3e64943e7bb41b846f996e817e006ee1b19b.png"
- ],
+ ],
"iris.tests.test_plot.Test1dPlotMultiArgs.test_coord.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83fec2ff7c00a56de9023b52e4143da5d16d7ecad1b76f2094c963929c6471c8.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83fec2ff7c00a56de9023b52e4143da5d16d7ecad1b76f2094c963929c6471c8.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8bfec2d77e01a5a5ed013b4ac4521c94817d4e6d91ff63349c6d61991e3278cc.png"
- ],
+ ],
"iris.tests.test_plot.Test1dPlotMultiArgs.test_coord_coord.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/87ff95776a01e1f67801cc36f4075b81c5437668c1167c88d2676d39d6867b68.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/87ff95776a01e1f67801cc36f4075b81c5437668c1167c88d2676d39d6867b68.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8fff941e7e01e1c2f801c878a41e5b0d85cf36e1837e2d9992c62f21769e6a4d.png"
- ],
+ ],
"iris.tests.test_plot.Test1dPlotMultiArgs.test_coord_coord_map.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fbe0623dc9879d91b41e4b449b6579e78798a49b7872d2644b8c919b39306e6c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fbe0623dc9879d91b41e4b449b6579e78798a49b7872d2644b8c919b39306e6c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bbe0c21ccd179dc3b05e4b689b0771b48698961b7962da446e8ca5bb36716c6e.png"
- ],
+ ],
"iris.tests.test_plot.Test1dPlotMultiArgs.test_coord_cube.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8ff897066b41f076f81dce1fb007da79c50633e9c40626b8d1066df9d6067969.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8ff897066b41f076f81dce1fb007da79c50633e9c40626b8d1066df9d6067969.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8ff897066a01f0f2f818ee1eb007ca41853e3b81c57e36a991fe2ca9725e29ed.png"
- ],
+ ],
"iris.tests.test_plot.Test1dPlotMultiArgs.test_cube.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8ffac1547a0792546c179db7f1254f6d945b7392841678e895017e3e91c17a0f.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8ffac1547a0792546c179db7f1254f6d945b7392841678e895017e3e91c17a0f.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8ff8c1fa7a05b4ea6c059d2ff1494e4b90f26304846d78d1872a6cfc938b2e3e.png"
- ],
+ ],
"iris.tests.test_plot.Test1dPlotMultiArgs.test_cube_coord.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83fec1ff7e0098757103a71ce4506dc3d11e7b20d2477ec094857db895217f6a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83fec1ff7e0098757103a71ce4506dc3d11e7b20d2477ec094857db895217f6a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8fffc1dc7e019c70f001b70ee4386de1814e7938837b6a7f84d07c9f15b02f21.png"
- ],
+ ],
"iris.tests.test_plot.Test1dPlotMultiArgs.test_cube_cube.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8ff8c2d73a09b4a76c099d26f14b0e5ad0d643b0d42763e9d51378f895867c39.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/8fe8c0173a19b4066d599946f35f0ed5d0b74729d40369d8953678e897877879.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8ff8c2d73a09b4a76c099d26f14b0e5ad0d643b0d42763e9d51378f895867c39.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8fe8c0173a19b4066d599946f35f0ed5d0b74729d40369d8953678e897877879.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8ff8c0567a01b096e4019daff10b464bd4da6391943678e5879f7e3103e67f1c.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_coord.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83fec2777e04256f68023352f6d61da5c109dec8d19bcf089cc9d99a9c85d999.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/83fec2777e06256f68023352f6d61da5c009decad19bcf089cc9d99a9c85d989.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83fec2777e04256f68023352f6d61da5c109dec8d19bcf089cc9d99a9c85d999.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83fec2777e06256f68023352f6d61da5c009decad19bcf089cc9d99a9c85d989.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/83fec2777e002427e801bb4ae65a1c94813dcec999db4bbc9ccd79991f3238cc.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_coord_coord.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83fe9dd77f00e1d73000cc1df707db8184427ef8d1367c88d2667d39d0866b68.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/83fe9d977f41e1d73000cc1df707d98184427ef8d1367c88d2667d39d0866b68.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83fe9dd77f00e1d73000cc1df707db8184427ef8d1367c88d2667d39d0866b68.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83fe9d977f41e1d73000cc1df707d98184427ef8d1367c88d2667d39d0866b68.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/83ff9d9f7e01e1c2b001c8f8f63e1b1d81cf36e1837e259982ce2f215c9a626c.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_coord_coord_map.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fbe0623dc9879d91b41e4b449b6579e78798a49b7872d2644b8c919b39306e6c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fbe0623dc9879d91b41e4b449b6579e78798a49b7872d2644b8c919b39306e6c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bbe0c21ccd179dc3b05e4b689b0771b48698961b7962da446e8ca5bb36716c6e.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_coord_cube.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/87ffb5867f0060d4301f6d9fb007d899c50699e9c8668e78d8678d69de069969.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/87ffb5867f0060d4301f6d9fb007d899c50699e9c8668e78d8678d69de069969.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/87ffb79e7f0060d8303fcd1eb007d801c52699e18d769e2199e60ce1da5629ed.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_cube.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83ffc1dc7e00b0dc66179d95f127cfc9d44959ba846658e891075a3e99415a2f.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83ffc1dc7e00b0dc66179d95f127cfc9d44959ba846658e891075a3e99415a2f.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a3ffc1d87e00b49964179d28f16bce4b98724b268c6d58e1972e4874998b2e7e.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_cube_coord.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83fec1ff7f90987720029f1ef458cd43811cdb60d647de609485ddb899215f62.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/83fec1ff7f94987720009f1ef458cd43810cdb60d647de609485ddb89921df62.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83fec1ff7f90987720029f1ef458cd43811cdb60d647de609485ddb899215f62.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83fec1ff7f94987720009f1ef458cd43810cdb60d647de609485ddb89921df62.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a3ffc1de7e009c7030019786f438cde3810fd97c93734a778ce07c9f99b02731.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_cube_cube.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83ffc8967e0098a6241f9d26e34b8e42f4d20bb4942759e9941f78f8d7867a39.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/83f9c8967e009da6245f9946e25f9ed6f0940f29f40749d8853678e8d7857879.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83ffc8967e0098a6241f9d26e34b8e42f4d20bb4942759e9941f78f8d7867a39.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83f9c8967e009da6245f9946e25f9ed6f0940f29f40749d8853678e8d7857879.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/83ffc9d67e00909624079daef160cf4bd45a439184367ae5979f7e3119e6261c.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotScatter.test_coord_coord.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a3fac1947c99184e62669ca7f65bc96ab81d97b7e248199cc7913662d94ac5a1.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a3fac1947c99184e62669ca7f65bc96ab81d97b7c248399cc7917662d84ac5a1.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a3fac1b47c99184e62669ca7f65bc96ab81d97b7e248199cc7913662d84acda0.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a3fac1947c99184e62669ca7f65bc96ab81d97b7e248199cc7913662d94ac5a1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a3fac1947c99184e62669ca7f65bc96ab81d97b7c248399cc7917662d84ac5a1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a3fac1b47c99184e62669ca7f65bc96ab81d97b7e248199cc7913662d84acda0.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/b2ecc1a8b9994a16e666b5e3ce151969a5fb4ed49909653990d46b9bfc097684.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotScatter.test_coord_coord_map.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bea07c99c15eb16e9891ce50c742394a3ced6cb13390f1cc73c29f1b2d0ecd66.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bea07c99c15eb16e9891ce50c742394a3ced6cb13390f1cc73c29f1b2d0ecd66.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bea06899c14eb16e9895ce46c74a396a74ed64b13390b3c61b439f1b4d2ccde6.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotScatter.test_coord_cube.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ae7f1f07f3e0e0f0211b9e066e074d83926ed8f8cd3792dad1964db0d80e9b09.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ae7f1f07f3e0e0f0311b9e066e074d839266d8e8cd379adad1964db0d80e9b09.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ae7f1f07f3e0e0f0211b9e066e074d83926ed8f8cd3792dad1964db0d80e9b09.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ae7f1f07f3e0e0f0311b9e066e074d839266d8e8cd379adad1964db0d80e9b09.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be852fc1e078c83eb30e3607672149c098d95c5b9e4636f2c1fc299d999f7e03.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotScatter.test_cube_coord.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a5f896d99a67b94c621deda3f69392cccd246db39018989ec4836de9ed249292.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a5f896d99a66b94c621deda3f69392cccd646db3901898dec4836de9cd249292.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a5f896d99a67b94c621ceda3f6d392cccd246db3901898dec4836de9cd249292.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a5f896d99a67b94c621deda3f69392cccd246db39018989ec4836de9ed249292.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a5f896d99a66b94c621deda3f69392cccd646db3901898dec4836de9cd249292.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a5f896d99a67b94c621ceda3f6d392cccd246db3901898dec4836de9cd249292.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/edfa96cb9a256b4f65466d9892d9c865693a1a9c94b39ed8484b35ad9a864c32.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotScatter.test_cube_cube.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a4fb19b3db04c6cd6307b98678601c738c39d71cf3866186d8616e69bd191b9e.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a4fb19b3db04c6cd6307b98678601c738c39d71cf3866186d8616e69bd191b9e.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e8b33c129649c78de3a773e578650c728e92279be12de1edc4f246b2939c3b01.png"
- ],
+ ],
"iris.tests.test_plot.Test1dScatter.test_coord_coord.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bbfac39d9899384a6f6694a7b613cb489c95b7b7c24a399cc5913262d84acda0.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bbfac39d9899384a6f6694a7b613cb489c95b7b7c24a399cc5913262d84acda0.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/b2ecc12999994e16e666b5e3ce171969a5fb4ed49909e53990c44b9b7c09f684.png"
- ],
+ ],
"iris.tests.test_plot.Test1dScatter.test_coord_coord_map.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bea07c99c15eb16e9891ce50c742394a3ced6cb13390f1cc73c29f1b2d0ecd66.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bea07c99c15eb16e9891ce50c742394a3ced6cb13390f1cc73c29f1b2d0ecd66.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bea06899c14eb16e9895ce46c74a396a74ed64b13390b3c61b439f1b4d2ccde6.png"
- ],
+ ],
"iris.tests.test_plot.Test1dScatter.test_coord_cube.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/af7e1f0ff1e1e0f0d918960e6c076d8bd266d868c537365a90966db0de0e1b09.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ae7e1f0ff1e1e0f0d918960e6c076d83d266d868c537365ad0966db0de4e1b09.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/af7e1f0ff1e1e0f0d918960e6c076d8bd266d868c537365a90966db0de0e1b09.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ae7e1f0ff1e1e0f0d918960e6c076d83d266d868c537365ad0966db0de4e1b09.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be812fc1c078c03e930e3627672369c1d8d85c5b96463662e1fc699d9b9f7e03.png"
- ],
+ ],
"iris.tests.test_plot.Test1dScatter.test_cube_coord.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/edf896d79a67b94c651ced23d29392cccd646d33901912fcc4836d69ed249292.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/edf896d79a67b94c651ced23d29392cccd646d33901912fcc4836d69ed249292.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/edda96cb9a256b4765c26d9892dbc665693a1a9494b796c86c4b37ad92864c32.png"
- ],
+ ],
"iris.tests.test_plot.Test1dScatter.test_cube_cube.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/acf939339a16c64de306318638673c738c19d71cf3866186d8636e69bd191b9e.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/acf939339a16c64de306318638673c738c19d71cf3866186d8636e69bd191b9e.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/edb23c529649c78de38773e538650c729e92279be12de1edc4f246b2139c3b01.png"
- ],
+ ],
"iris.tests.test_plot.TestAttributePositive.test_1d_positive_down.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/87fef8117980c7c160078f1ffc049e7e90159a7a95419a7e910dcf1ece19ce3a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/87fef8117980c7c160078f1ffc049e7e90159a7a95419a7e910dcf1ece19ce3a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a7fe781b708487c360079e3bb4789869816bdb64c76b4a3cce7b4e749a6130c5.png"
- ],
+ ],
"iris.tests.test_plot.TestAttributePositive.test_1d_positive_up.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/87ff85d47800bd9f660779d0863f49c9947f4e1e9141de38d700da28ce1d9a2b.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/87ff85d47a00bc9f660779d8863f49c9907f4e1e9141de38d708da28ce1d9a0b.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/87ff85d47800bd9f660779d0863f49c9947f4e1e9141de38d700da28ce1d9a2b.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/87ff85d47a00bc9f660779d8863f49c9907f4e1e9141de38d708da28ce1d9a0b.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a7ff958b7a00b09c661761c9907fcb0d9163ce7895289a618f381bffccf97200.png"
- ],
+ ],
"iris.tests.test_plot.TestAttributePositive.test_2d_positive_down.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fb946ba684e194fb901b3a0587641ad03b1ae7674e64c15a5b99c767c47e3a98.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fb946ba684e194fb901b3a0587641ad03b1ae7674e64c15a5b99c767c47e3a98.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fb946ba484e194dbc01f3665c0e4399a3f0fc2653f90c99e3f613e64c81e3f81.png"
- ],
+ ],
"iris.tests.test_plot.TestAttributePositive.test_2d_positive_up.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ee176c7f93e093a0c50f9383815e6e156859e17e6e15e17a9be08e2d851a9b83.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ee176c7f93e093a0c50f9383815e6e156859e17e6e15e17a9be08e2d851a9b83.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ebc06be1941e941ec07f941f907f6fa0950fc07e6f80c07f6b806be1c07f3f80.png"
- ],
+ ],
"iris.tests.test_plot.TestContour.test_tx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/cff8a55f7a15b55a7817854ad007a5e8c04f3ce8c04f3e2ac4706ab295b37a96.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/cff8a55f7a15b55a7817854ad007a5e8c04f3ce8c04f3e2ac4706ab295b37a96.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eaece0173d17951fbd03974a914964e8c04a72e8c1531ee1cc746bb293973ecd.png"
- ],
+ ],
"iris.tests.test_plot.TestContour.test_ty.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8bfc815e78018597fc019b65b425d121955e7eda854b7d6a80db7eb481b72b61.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8bfc815e78018597fc019b65b425d121955e7eda854b7d6a80db7eb481b72b61.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ebfa8553fc01b15ab4044a269546caa5956b7e9bc0b97f2cc2d62d360b363b49.png"
- ],
+ ],
"iris.tests.test_plot.TestContour.test_tz.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8bfe81ff780185fff800955ad4027e00d517d400855f7e0085ff7e8085ff6aed.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/8bfe81ff780085fff800855fd4027e00d517d400855f7e0085ff7e8085ff6aed.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8bfe81ff780185fff800955ad4027e00d517d400855f7e0085ff7e8085ff6aed.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8bfe81ff780085fff800855fd4027e00d517d400855f7e0085ff7e8085ff6aed.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8bfe817ffc00855ef0007e81d4027e80815fd56a03ff7a8085ff3aa883ff6aa5.png"
- ],
+ ],
"iris.tests.test_plot.TestContour.test_yx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa56c3cc34e891b1c9a91c36c5a170e3c71b3e5993a784e492c49b4ecec76393.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa56c3cc34e891b1c9a91c36c5a170e3c71b3e5993a784e492c49b4ecec76393.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e85e36cb95b199999765cd3694b06478c7396329958434c2cecb6c6d69ce1b92.png"
- ],
+ ],
"iris.tests.test_plot.TestContour.test_zx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8bfe857f7a01a56afa05854ad015bd00d015d50a90577e80857f7ea0857f7abf.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8bfe857f7a01a56afa05854ad015bd00d015d50a90577e80857f7ea0857f7abf.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/affe815ffc008554f8007e01d0027e808557d5ea815f7ea0817f2fea817d2aff.png"
- ],
+ ],
"iris.tests.test_plot.TestContour.test_zy.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8bff81ff7a0195fcf8019578d4027e00d550d402857c7e0185fe7a8385fe6aaf.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8bff81ff7a0195fcf8019578d4027e00d550d402857c7e0185fe7a8385fe6aaf.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/abff857ff8018578f8017a80d4027e00855ec42a81fe7a8185fe6a8f85fe6ab7.png"
- ],
+ ],
"iris.tests.test_plot.TestContourf.test_tx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/faa562ed68569d52857abd12953a8f12951f64e0d30f3ac96a4d6a696ee06a32.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/faa562ed68569d52857abd12953a8f12951f64e0d30f3ac96a4d6a696ee06a32.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea857a81957ac57e957a857a957a958ac5723b0d6ac56b833e856e606a923e90.png"
- ],
+ ],
"iris.tests.test_plot.TestContourf.test_ty.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/eaa5e03f957a4f80954a9e41e16e9c60970fb5b24ada634e6e93692d4ba562d8.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eaa5e03f957a4f80954a9e41e16e9c60970fb5b24ada634e6e93692d4ba562d8.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea851f00957ac0f7957ac07f957a628d815e7b126ab13e816a953ae46a859ed3.png"
- ],
+ ],
"iris.tests.test_plot.TestContourf.test_tz.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e954a7a81857e957e857efc00857e7e007a85c02a7e859f287a85c1fe.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e954a7a81857e957e857efc00857e7e007a85c02a7e859f287a85c1fe.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7a81857e7a81857e7a81857e7a806a85857a7a85857e7a85817e.png"
- ],
+ ],
"iris.tests.test_plot.TestContourf.test_yx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e95a6938b6b5969193901a4fc1e594a7c69999cbce33639879526e72330e65e4.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e95a6938b6b5969193901a4fc1e594a7c69999cbce33639879526e72330e65e4.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e97a3c7e968597b19685c9c696a7c79491c16e59691a387f6978396e68683184.png"
- ],
+ ],
"iris.tests.test_plot.TestContourf.test_zx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa85857ec45a7a81857e854a857ee56a917ec56a3a85c56a3a85c4ea7a8112fe.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa85857ec45a7a81857e854a857ee56a917ec56a3a85c56a3a85c4ea7a8112fe.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81817e857e7a81857a7a81957a6e81917a6caa3a85c57a3a8585fa6a8591fe.png"
- ],
+ ],
"iris.tests.test_plot.TestContourf.test_zy.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa81817ec40a7a81857e957e857ef40a857ef60b7a81c40a7b81e60f7a814aff.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81817ec40a7a81857e957e857ef40a857ef60b7a81c40a7b81e60f7a814aff.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81817e857e7a81857e7a81817a7e81817a668f7a91857e7a81857e7a85817e.png"
- ],
+ ],
"iris.tests.test_plot.TestHybridHeight.test_bounds.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/eab5313f954a7b9260f39789c5ec4cd084d0c4e45aa1c5fe3a04797bb13b3b06.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eab5313f954a7b9260f39789c5ec4cd084d0c4e45aa1c5fe3a04797bb13b3b06.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ee856aa5957a955ac0bf954bc17e3b819548c07f3e81c07e2ec46ea4c07f3e84.png"
- ],
+ ],
"iris.tests.test_plot.TestHybridHeight.test_bounds.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/be853f80854ac17ec0bdc2f5c17a0d09cc1fc07f5ab5e1fe3f409d7a38743e00.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/be853f80854ac17ec0bdc2f5c17a0d09cc1fc07f5ab5e1fe3f409d7a38743e00.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bf813e85c07ec57ec17e9073c07e3f81856ec17a3f80c0fe3e813f84c2733e80.png"
- ],
+ ],
"iris.tests.test_plot.TestHybridHeight.test_bounds.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/eab5313f954a7b9260f39789c5ec4cd084d0c4e45aa1c5fe3a04797bb13b3b06.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eab5313f954a7b9260f39789c5ec4cd084d0c4e45aa1c5fe3a04797bb13b3b06.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ee856aa5957a955ac0bf954bc17e3b819548c07f3e81c07e2ec46ea4c07f3e84.png"
- ],
+ ],
"iris.tests.test_plot.TestHybridHeight.test_orography.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa17291f95e895e8645e7a95c17a6eece4b4e1333b01c07e1bb13909914b9ec1.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa17291f95e895e8645e7a91c17a6ee464f4e1333b01c17e1bb1390d914b9ec1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa17291f95e895e8645e7a95c17a6eece4b4e1333b01c07e1bb13909914b9ec1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa17291f95e895e8645e7a91c17a6ee464f4e1333b01c17e1bb1390d914b9ec1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa817a91957a857ac4fe268cc07f6e846e05d9373b81d17b1b6a1b41c4fa2cc4.png"
- ],
+ ],
"iris.tests.test_plot.TestHybridHeight.test_orography.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bb07314fc4e0c6b4c31e9ee1847939a1c116c15e7b94e57e1ea9391de16e1ac3.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/bb07314fc6e1c6b4c31e9ee1846939a1c116c15e7b14e17e1ea9393de16e1ac3.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bb07314fc4e0c6b4c31e9ee1847939a1c116c15e7b94e57e1ea9391de16e1ac3.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bb07314fc6e1c6b4c31e9ee1846939a1c116c15e7b14e17e1ea9393de16e1ac3.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/af0b690f96f0d2d4c25e94a194ad3da19a52c25e3f02c07f3fa52d03c16a3fcb.png"
- ],
+ ],
"iris.tests.test_plot.TestHybridHeight.test_points.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea953bfb956ac4f4649f1a05c56e6ca45a53945e6ea5c13f1b498542c13f1b41.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea953bfb956ac4f4649f1a05c56e6ca45a53945e6ea5c13f1b498542c13f1b41.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fe857b91917a847ec0bd3f01c47e6ca43b11915a3ea4db3b1b4a84c4c03f3fc1.png"
- ],
+ ],
"iris.tests.test_plot.TestHybridHeight.test_points.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/be813fc0c15ac13dc1bfc27dc17e1d93c51fc43f1ea1c17a3ec138e4b1721a81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/be813fc0c15ac13dc1bfc27dc17e1d93c51fc43f1ea1c17a3ec138e4b1721a81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be813a81c17ec57ec17e952ac07f3f808556c17e3f80c07f3e813f80c27e3f81.png"
- ],
+ ],
"iris.tests.test_plot.TestHybridHeight.test_points.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea9561ef956a7b92609b922dc16e6ec6845ac47e5aa5c57e5ec04861957b1b81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea9561ef956a7b92609b922dc16e6ec6845ac47e5aa5c57e5ec04861957b1b81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fe856a85957a955ac03f956ac17f3f809552c07f3e81c07e3e806e85c07e3f84.png"
- ],
+ ],
"iris.tests.test_plot.TestHybridHeight.test_points.3": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea953bfb956ac4f4649f1a05c56e6ca45a53945e6ea5c13f1b498542c13f1b41.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea953bfb956ac4f4649f1a05c56e6ca45a53945e6ea5c13f1b498542c13f1b41.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fe857b91917a847ec0bd3f01c47e6ca43b11915a3ea4db3b1b4a84c4c03f3fc1.png"
- ],
+ ],
"iris.tests.test_plot.TestHybridHeight.test_points.4": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/baf5347ecf0ac3f1c1f68f83850b1f83cc11c0fc7ad0c17a1be138e4b07e1a0d.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/baf5347ecf0ac3f1c1f68f83850b1f83cc11c0fc7ad0c17a1be138e4b07e1a0d.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/b878387e978ec2f0c0f09f83878f3f81c070c0fe78d0c1763fa13856d03e3f0f.png"
- ],
+ ],
"iris.tests.test_plot.TestMissingCS.test_missing_cs.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fac16ee0953b911bc15e9648e56ec4e691be7bcc7a8184733ea16a90c17e930d.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fac16ee0953b911bc15e9648e56ec4e691be7bcc7a8184733ea16a90c17e930d.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa816ac1857e853cc17f957ac15f3e849486c8f43e81c13b3f813e91c07e3f46.png"
- ],
+ ],
"iris.tests.test_plot.TestMissingCoord.test_no_u.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fe816a95c17fb51e953e9485857a1f409552856a1f81c17e5ab94e15c0ff5a85.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fe816a95c17fb51e953e9485857a1f409552856a1f81c17e5ab94e15c0ff5a85.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea856a95955a954ac17f954ac07e3f48951ec07e3e81c0ff7ea16a81c0bf3e81.png"
- ],
+ ],
"iris.tests.test_plot.TestMissingCoord.test_no_u.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/be0e695ac3f096b5943fd2a185fc1e8590e594ee1e05c17a4f403d0fe1fe4b42.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/be0e695ac3f096b5943fd2a185fc1e8590e594ee1e05c17a4f403d0fe1fe4b42.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea956ab5954a954ac17f954a817e3f40950ac07f3e81c0ff7a856aa1c0ff3f80.png"
- ],
+ ],
"iris.tests.test_plot.TestMissingCoord.test_no_v.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562b6c0773d09956a955a857a1d88845ec57e3f81c07e4ae56b21d0ff5a85.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562b6c0773d09956a955a857a1d88845ec57e3f81c07e4ae56b21d0ff5a85.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa816a85957a857ac17e954ac17e1fa2950bc07e3e81c07f3e807a85c17f3f81.png"
- ],
+ ],
"iris.tests.test_plot.TestMissingCoord.test_no_v.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa9562d4c7c43d0bb57b97e0857a3f1995d284763a05c17a7b856a2dc0f45a84.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa9562d4c7c43d0bb57b97e0857a3f1995d284763a05c17a7b856a2dc0f45a84.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa856a85957a857ac17e954ac17e9d02954ac07e3e81c07f3e857a85c2fd3f80.png"
- ],
+ ],
"iris.tests.test_plot.TestMissingCoord.test_none.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562b6c0763d09b54a955a857a3f88845ec57a3e85c07e6a616b25d0ff7a81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562b6c0763d09b54a955a857a3f88845ec57a3e85c07e6a616b25d0ff7a81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa816a85957a857ac17e954ac17e3fa29506c07e3e81c07f3e807a84c1ff3f81.png"
- ],
+ ],
"iris.tests.test_plot.TestMissingCoord.test_none.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562f6c0773d09b54a955a857a3f81955ac47e3e85c17e7aa16a25c0765aa1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562f6c0773d09b54a955a857a3f81955ac47e3e85c17e7aa16a25c0765aa1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa856a85957a957ac17e954ac17a1f06954ac07e3e81c07f3e817a85c0ff3f80.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolor.test_tx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e85e67c9c7e1391e97a596b03a3696a13c4f63066318695ec5c9695e6c49c6a5.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e85e67c9c7e1391e97a596b03a3696a13c4f63066318695ec5c9695e6c49c6a5.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea817a81957e857e957e953e957e857e857e6aa06a816ac16a017a816a9585fa.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolor.test_ty.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b3878958b38f8c7236a557a542c7868d54b877875978abc789722.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b387895ab38f8c7236a557a542c7868d54b05787197eab478972a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b3878958b38f8c7236a557a542c7868d54b877875978abc789722.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b387895ab38f8c7236a557a542c7868d54b05787197eab478972a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea953f83954ac2bc956ac07e956a3509c0de61796ab57a816a856ad16ab590fb.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolor.test_tz.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e874978b978b6875978b6875978b7854950b78506855787468747ea2687597aa.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e874978b978b6875978b6875978b7854950b78506855787468747ea2687597aa.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857a7a84857a7a85857e7a813a2f7a817a85857a7a85857a7a85857a.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolor.test_yx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e95e696994b196b793b19a1ec3c191c5c6e596191e4e693269336c36391a6e3a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e95e696994b196b793b19a1ec3c191c5c6e596191e4e693269336c36391a6e3a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e97a387e968596319697c3c19284a62c93a560c36933393a6c7e793b6c6b31cd.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolor.test_zx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e85e87a197a1695a97a1695a97a17d5a97a17906785a7816685a7e86685ad687.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e85e87a197a1695a97a1695a97a17d5a97a17906785a7816685a7e86685ad687.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857a7e01857e7a81857e7a81e8177a816a8585fa7a85857e7a81857e.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolor.test_zy.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/af42c0bdd0ad2f52d0bd3f42d0bd7f02d0bd7f003d527f002f427ea82f42d6a8.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/af42c0bdd0ad2f52d0ad2b52d0bd7f02d0bd7f002d527f002f527e0d2f52d4ad.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/af42c0bdd0ad2f52d0bd3f42d0bd7f02d0bd7f003d527f002f427ea82f42d6a8.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/af42c0bdd0ad2f52d0ad2b52d0bd7f02d0bd7f002d527f002f527e0d2f52d4ad.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7e80857e7a81857e7a812d557a817a85857e7a81857e7a80857e.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolorNoBounds.test_tx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa1594f3858a670c94e37b1cccb13e736a1d8cf17a1f94e2c119938e9463678c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa1594f3858a670c94e37b1cccb13e736a1d8cf17a1f94e2c119938e9463678c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea858782957a703f957a3878957a7a65957a6bc06ae76f806ad50fd06a859c50.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolorNoBounds.test_ty.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ad5e94a5c3b0c3f096a5695a96a53c0f711b3c0f7d1b97b46943c3e0cc416b5a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ad5e94a5c3b0c3f096a5695a96a53c0f711b3c0f7d1b97b46943c3e0cc416b5a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea85857a857e7e81957a7a81957a6a85857acac6c1fb6aa67a81956e6a81b506.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolorNoBounds.test_tz.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a95e3c1f96a096a5d6a5eb40c3f0ebe0c1c0c3f07c0b3e3e96a13c1e6d5b694a.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a95e381f96a096a5d6a5eb40c3f0ebf0c1e0c3f07c0a3e3e96a13c1e6d5b694a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a95e3c1f96a096a5d6a5eb40c3f0ebe0c1c0c3f07c0b3e3e96a13c1e6d5b694a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a95e381f96a096a5d6a5eb40c3f0ebf0c1e0c3f07c0a3e3e96a13c1e6d5b694a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa817e81857e857a857e7a81857e6a85817b81e63a913e857e81c17e7a81956e.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolorNoBounds.test_yx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bc7a1c32d3c366cdc585c39986cdc79ec792e3a6960d584939793c3438743873.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bc7a1c32d3c366cdc585c39986cdc79ec792e3a6960d584939793c3438743873.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e96ac78796953c4c9685383996c538e69692637263696b49693ac796693ac71b.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolorNoBounds.test_zx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea1f781f95e085e885e0954295e195ea95a085e87a153e7f95e06a1778557a1f.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea1f781f95e085e885e0954295e195ea95a085e87a153e7f95e06a1778557a1f.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa817a81857e857e857e7a81857e6a81c17f95786aa77a807e81c17c7e819558.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolorNoBounds.test_zy.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ba173a1795e895e8c5e8f400c1f8c1f895a8c5e87a077a5ec5e83e173e177e02.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ba173a1795e895e8c5e8f400c1f8c1f895a8c5e87a077a5ec5e83e173e177e02.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa817a80857e857e857e7a81817e3e81817e857f6aa07a857e80c17f7e80c15f.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormesh.test_tx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e85e67c9c7e1391e97a596b03a3696a13c4fe3026318695ec5c9695e6c49c6a5.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e85e67c9c7e1391e97a596b03a3696a13c4fe3026318695ec5c9695e6c49c6a5.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea817a81957e857e957e953e957e857e857e6aa06a816ac16a017a816a9585fa.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormesh.test_ty.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b3878958b38f8c7236a557a542c7868d54b877875978abc789722.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b387895ab38f8c7236a557a542c7868d54b05787197eabc789722.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b3878958b38f8c7236a557a542c7868d54b877875978abc789722.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b387895ab38f8c7236a557a542c7868d54b05787197eabc789722.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea953f83954ac2fc956ac07e956a3509c0de61796ab57a816a854ad16ab590fb.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormesh.test_tz.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e874978b978b6875978b6875978b7854950b78506855787468747ea2687597aa.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e874978b978b6875978b6875978b7854950b78506855787468747ea2687597aa.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857a7a84857a7a85857e7a813a2f7a817a85857a7a85857a7a85857a.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormesh.test_yx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e95e696994b196b593b19a1ec3c591c5c6e596191e4e693269336c36391a6e3a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e95e696994b196b593b19a1ec3c591c5c6e596191e4e693269336c36391a6e3a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e9693878969696139296c38f9bcc3474692169cb6c7339393c6cc387c78796cc.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormesh.test_zx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e85e87a197a1695a97a16d5a97a17d5a97a17806785a7816685a7e86685ad687.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e85e87a197a1695a97a16d5a97a17d5a97a17806785a7816685a7e86685ad687.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e6e05857e7a81857e7a81a0577a816a8585fa7a85857e7a81857e.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormesh.test_zy.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/af42c0bdd0ad2f52d0bd3f42d0bd7f02d0bd7f002d527f002f427fa82f42d6a8.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/af4280bdd0ad2f52d0ad2b52d0bd7f02d0bd7f002d527f002f527f0d2f52d4ad.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/af42c0bdd0ad2f52d0bd3f42d0bd7f02d0bd7f002d527f002f427fa82f42d6a8.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/af4280bdd0ad2f52d0ad2b52d0bd7f02d0bd7f002d527f002f527f0d2f52d4ad.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7e80857e7a81857e7a8129577a817a85857e7a81857e7a80857e.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormeshNoBounds.test_tx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa1594f3858a670c94e37b1cccb13e736a1d84f17a1d94e2c11d938e9463678e.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa1594f3858a670c94e37b1cccb13e736a1d8cf17a1d94e2c11993ae9463678c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa1594f3858a670c94e37b1cccb13e736a1d84f17a1d94e2c11d938e9463678e.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa1594f3858a670c94e37b1cccb13e736a1d8cf17a1d94e2c11993ae9463678c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea858782957a703f957a3878957a7a65957e6bc06ae56f806ad50fd06a859c50.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormeshNoBounds.test_ty.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ad5e94a5c3b0c3f096a1695a96a53c1f711b3c0f791b97b46943c3e06c436b5a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ad5e94a5c3b0c3f096a1695a96a53c1f711b3c0f791b97b46943c3e06c436b5a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea85857a857e7e81957a7a81957a6a85857acae6c1fb6aa47a81956e6a81b506.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormeshNoBounds.test_tz.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a95e3c1f96a096a5d6a56b40c3f06be2c1c0c3f07c0b3ebe96a13c1e6d5b694a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a95e3c1f96a096a5d6a56b40c3f06be2c1c0c3f07c0b3ebe96a13c1e6d5b694a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa813e81857e857a857e7a81857e6a85817b00e63eb93e857e81c17e7a81956e.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormeshNoBounds.test_yx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bc7a1c32d3c366cdc785c39986cdc78ec792e7a6960d584939793c3438703873.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bc7a1c32d3c366cdc785c39986cdc78ec792e7a6960d584939793c3438703873.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e129c7169ed638ec9ed6387196c761c665396724612dcf0d693896929ed698c9.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormeshNoBounds.test_zx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea1f781f95e085e895e0fd4295e095ea95a085e87a153e7e95e06a1778157a17.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea1f781f95e085e895e0fd4295e095ea95a085e87a153e7e95e06a1778157a17.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa817a85857a857e857e7a81857e7a81817f95506aaf7a807e81c17c7a81957a.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormeshNoBounds.test_zy.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ba176a1795e895e8c5e87c00c1f8c1f894a8c5e87a077adec5e83e173e177a06.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ba176a1795e895e8c5e87c00c1f8c1f894a8c5e87a077adec5e83e173e177a06.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa817a80857a857e857e7a81857e3e81817e2fc56aa07a857e80c17f7e80c17f.png"
- ],
+ ],
"iris.tests.test_plot.TestPlot.test_t.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83fe955f6a05e5137305d9c4f443127195187e9cd5467fa3d4917b68fc007a1a.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/8ffe95027e05e7007305d9c4a447127f853f069f814f2fa7d4d12b6cfc007e5a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83fe955f6a05e5137305d9c4f443127195187e9cd5467fa3d4917b68fc007a1a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8ffe95027e05e7007305d9c4a447127f853f069f814f2fa7d4d12b6cfc007e5a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8ffe9c1a7e05e718f305d9d2e46312718138049e824e2fa783db2bed76b4fe00.png"
- ],
+ ],
"iris.tests.test_plot.TestPlot.test_t_dates.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/abffd5ae2a15cdb6b10178d7d4082e57d7290906f685814277b1dc88724cfd26.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/abffd5ae2a15c9b6a10178d7d4082c57d7290906f6c58942f7b1dc88724cfd26.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/abffd4a02a01cc84f10078d7d4082c77d73909ded6ef816273bd9c98725cdd26.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/abffd5ae2a15cdb6b10178d7d4082e57d7290906f685814277b1dc88724cfd26.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/abffd5ae2a15c9b6a10178d7d4082c57d7290906f6c58942f7b1dc88724cfd26.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/abffd4a02a01cc84f10078d7d4082c77d73909ded6ef816273bd9c98725cdd26.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/87fc9d8a7e054d83f5067bc1c1423471927ba73c8d9f864e09a1a7b358c8276f.png"
- ],
+ ],
"iris.tests.test_plot.TestPlot.test_x.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8ffe95297e87c74a6a059158f89c3d6ed0536597c0387836d0f87866d0697097.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8ffe95297e87c74a6a059158f89c3d6ed0536597c0387836d0f87866d0697097.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8bfe956b7c01c2f26300929dfc1e3c6690736f91817e3b0c84be6be5d1603ed1.png"
- ],
+ ],
"iris.tests.test_plot.TestPlot.test_y.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8fe896266f068d873b83cb71e435725cd07c607ad07e70fcd0007a7881fe7ab8.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/8fe896066f068d873b83cb71e435725cd07c607ad07c70fcd0007af881fe7bb8.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/8fe896366f0f8d93398bcb71e435f24ed074646ed07670acf010726d81f2798c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8fe896266f068d873b83cb71e435725cd07c607ad07e70fcd0007a7881fe7ab8.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8fe896066f068d873b83cb71e435725cd07c607ad07c70fcd0007af881fe7bb8.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8fe896366f0f8d93398bcb71e435f24ed074646ed07670acf010726d81f2798c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/aff8946c7a14c99fb193d263e42432d8d00c2d27944a3f8dc5223ef703ff6b90.png"
- ],
+ ],
"iris.tests.test_plot.TestPlot.test_z.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8ffac1547a0792546c179db7f1254f6d945b7392841678e895017e3e91c17a0f.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8ffac1547a0792546c179db7f1254f6d945b7392841678e895017e3e91c17a0f.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8ff8c1fa7a05b4ea6c059d2ff1494e4b90f26304846d78d1872a6cfc938b2e3e.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCitation.test.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/abf895067a1d9506f811783585437abd85426ab995067af9f00687f96afe87c8.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCitation.test_axes.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/abf895067a1d9506f811783585437abd85426ab995067af9f00687f96afe87c8.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCitation.test_figure.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/abf895067a1d9506f811783585437abd85426ab995067af9f00687f96afe87c8.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_non_cube_coordinate.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7e81857e7a81857e7a81857e7a818576c02a7e95856a7e81c17a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7e81857e7a81857e7a81857e7a818576c02a7e95856a7e81c17a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e3e85857e7a81857e7a81857e7a817e81780b7a81c56a7a81857e.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fe8142f5c17ebd2cc16eb548954a9542916a347a915e60bd4afd68793f916296.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fe8142f5c17ebd2cc16eb548954a9542916a347a915e60bd4afd68793f916296.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea853f10956ac5e1957a854e957a203e955e6aa76ae17aa16a856aaf6ab19e12.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa8542b7b503b548857abd08857abd09945eed6b91d968c161b972d76aa462b5.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa8542b7b503b548857abd08857abd09945eed6a91d96ac163b972d36aa462b5.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa8542b7b503b548857abd08857abd09945eed6b91d968c161b972d76aa462b5.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa8542b7b503b548857abd08857abd09945eed6a91d96ac163b972d36aa462b5.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea853a85857a857a957a857a957ad05a857b3e946a606b917a816f647a853af4.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8bf88f457a03b5307e16b561f007b53ed067217ac1786afec0f570bf8178681a.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/8bf98f057a03b5307e16b561f007b53ad067217ac1786afec0f570bf8178685a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8bf88f457a03b5307e16b561f007b53ed067217ac1786afec0f570bf8178681a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8bf98f057a03b5307e16b561f007b53ad067217ac1786afec0f570bf8178685a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eafdcec9bc219530b696a56694c2852a95656b7b81986acdc0e516adad186eda.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.3": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8ffe8f367e05952afe05a50b980ded4bd05d69c2c1fb71c1c06272f4d0a06af4.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8ffe8f367e05952afe05a50b980ded4bd05d69c2c1fb71c1c06272f4d0a06af4.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/aff24ab7bd05952fbd0f950f914fcd48c47860f3e1b9329094266e345a850f6c.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.4": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/aa953d0f85fab50fd0f2956a7a1785fafa176877d00f68f1d02c60f2f008d0f0.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ebeaa5419e94b5019e97950d685395bee05361fad05560fad01570fef001dabe.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ebeaa5419e95b5419e97950d6853953ee053617ad05560fad01570fef001dabe.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/aa953d0f85fab50fd0f2956a7a1785fafa176877d00f68f1d02c60f2f008d0f0.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ebeaa5419e94b5019e97950d685395bee05361fad05560fad01570fef001dabe.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ebeaa5419e95b5419e97950d6853953ee053617ad05560fad01570fef001dabe.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ebfaa56f96a1856cd681a56ee8162d52e8467e12c50c7e8095ad7e0095ad03ff.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.5": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ebfaaf439e87b5019687b5019687b56ac05561fae07103fe6079687a607178f8.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ebfa2d4b968795059e87970f6854697ae055697ac08561fad041d7aef001d6ae.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ebfaaf439e87b5019687b5019687b56ac05561fae07103fe6079687a607178f8.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ebfa2d4b968795059e87970f6854697ae055697ac08561fad041d7aef001d6ae.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eb7a3e0c978187a4950190bc6856687a607e687bc0fcc1e394acfc0197fc2bfb.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_x.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/aeb8b5095a87cd60386592d9ec97ad6dd23ca4f6d0797827f0096216c1f878e6.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/aeb8b5095a87cd60386592d9ec97ad6dd23ca4f6d0797827f0096216c1f878e6.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/affa950ddb13c03634359ad8a4c80f26911f26f3c06e0ff3f4007b4285fd6e72.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_y.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8fea97194f07c9c830d79169ce16269f91097af6c47861f6d0796076d0797a16.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/8fee970b4f07c9c930d79129ce16269f91097af6c4f861f4d0786076d0797a16.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/afea97094f07c9c870d79129ce16269f91096af6c4f861f6c07960f6d0797a16.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8fea97194f07c9c830d79169ce16269f91097af6c47861f6d0796076d0797a16.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8fee970b4f07c9c930d79129ce16269f91097af6c4f861f4d0786076d0797a16.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/afea97094f07c9c870d79129ce16269f91096af6c4f861f6c07960f6d0797a16.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/afee9632de05c9d9f180d168c454a53e931b3e84956a3b8c85d94ce703ff7284.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_yx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea85603f956a9741951e9d83c1fa8d2fd0a55af0d25f345ae5f062c72d68612d.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea85603f956a9741951e9d83c1fa8d2fd0a55af0d25f345ae5f062c72d68612d.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea853f00957ac07c957ac0be951a69f3c47c7a5f3a6127816b953e646b813761.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_yx.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e85a69cc96ad92e193c9963385929e1cc3819acde6d965ce6e666b30386e65b1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e85a69cc96ad92e193c9963385929e1cc3819acde6d965ce6e666b30386e65b1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e97a346c9685cb899685c9c39695c79396ec634969ce2c74697a3864697b3c8c.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_yx.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8ffcc65767039740bc069d9ad00b8dadd03f52f181dd347a847a62ff81e8626c.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/8ffcc65777039740bc069d9ad00b8dadd03d52f181dd707a847a62ff81e8626c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8ffcc65767039740bc069d9ad00b8dadd03f52f181dd347a847a62ff81e8626c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8ffcc65777039740bc069d9ad00b8dadd03d52f181dd707a847a62ff81e8626c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ebffca44f502b36498309c9b940999add1bb62bba784374acc5a6a246acc6b65.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_yx.3": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea5649c434ac92e5d9c9361b95b39c38c3835a5ec6d966ced34c633099ace5a5.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea5649c434ac92e5d9c9361b95b39c38c3835a5ec6d966ced34c633099ace5a5.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e85a6b6c96a597a591c9949b94b61b69c7926b5bccce66646b3869b831a52c26.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_yx.4": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2dd2d09295c3c0c7d13c1bc6d23d2c696de0e53c3ac393daf6d205c2c4.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2fd2d09295c3c0c7d13c1bc6d23d2c696ce0e53c3ac393dbf6d205c2c0.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2f92d09295c3d0c7d13c1bc6d23d2c696cf0e53c3ac2b3d9f6d201c2c4.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e85e3e2f97a1c19996a1c8f26c1e360f684a3c2c6913dca497b9d38097a903ff.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2dd2d09295c3c0c7d13c1bc6d23d2c696de0e53c3ac393daf6d205c2c4.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2fd2d09295c3c0c7d13c1bc6d23d2c696ce0e53c3ac393dbf6d205c2c0.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2f92d09295c3d0c7d13c1bc6d23d2c696cf0e53c3ac2b3d9f6d201c2c4.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e85e3e2f97a1c19996a1c8f26c1e360f684a3c2c6913dca497b9d38097a903ff.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e85e3e3f96a1c3e197a169f1785e3b0e68523e1c398bc58687b1d86096e1039f.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_yx.5": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e9686d8c9696924797879e3b86929e58696d69cc6869659379626133398d9ccd.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e961658f961e92469e1e1c7966f36cd86165618c70e166b39b9698719e1e9ec8.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e9686d8c9696924797879e3b86929e58696d69cc6869659379626133398d9ccd.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e961658f961e92469e1e1c7966f36cd86165618c70e166b39b9698719e1e9ec8.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e1a530e29e5ecf199a5acd8f64f1326161a530e265999cd29e52cf199a5e6669.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_zx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bf803f00c05fc4bfc07ec15dc05fd8bbc07cc96c333a32113bd02dd27ced3ec0.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bf803f00c05fc4bfc07ec15dc05fd8bbc07cc96c333a32113bd02dd27ced3ec0.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be813ea0c17ec55ac17ed23dc07e295ac57e3b653f803f813e816e853e81b542.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_zx.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea95956a95626993941a6a2d956e6ed6845a6e65c4bec7b64a9594686ea19578.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea95956a95626993941a6a2d956e6ed6845a6e65c4bec7b64a9594686ea19578.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea85856e857e4893957a7aa1956a7b81954b3b817a856fd46a85846e6e85857e.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_zx.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8fe82f047c018c83bc01bc5af01fd1bcd15a327c847860fdc57a69beb0be68bd.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/8fe82f047c018c83bc01bc5af01fd1bcd15a32fd847860fdc57269beb0be689d.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8fe82f047c018c83bc01bc5af01fd1bcd15a327c847860fdc57a69beb0be68bd.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8fe82f047c018c83bc01bc5af01fd1bcd15a32fd847860fdc57269beb0be689d.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8bedcf25bc03a4929c103a5bf03fdbbc81cb364d86e46da70f86899b3a0f6cc0.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_zx.3": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/cee8953a7a15856978579696d03d672cc49a6e5a842d3d2cc0b66bd1c2ea39f1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/cee8953a7a15856978579696d03d672cc49a6e5a842d3d2cc0b66bd1c2ea39f1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/aee1f93a63168569b852d697913d632485ca2e43952d3bbcc2b66bd1426b3c71.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_zx.4": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ee953f0591ea3f07914a95fa7e07d1fa68156a15d07c6a3dd038c0fef000d0fa.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ae953f0591ea3f07914a95fa7e07d1fa68156a15d07c6a7dd068c0fef000d0fa.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ee953f0591ea3f07914a95fa7e07d1fa68156a15d07c6a3dd038c0fef000d0fa.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ae953f0591ea3f07914a95fa7e07d1fa68156a15d07c6a7dd068c0fef000d0fa.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bec11ab5c1be857ac13e7ae53c422d423e017a85b542fc00c1fefe0091fe03ff.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_zx.5": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e87a973d96a56953968769439685a54ae05117eae0511fba60513bba69717aba.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e87a952d96a56953968769439685a54ae85197eae0511fba60513bba69717aba.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e87a973d96a56953968769439685a54ae05117eae0511fba60513bba69717aba.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e87a952d96a56953968769439685a54ae85197eae0511fba60513bba69717aba.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e85a96ac97a16c5897a1791e95a53b0b913c6953687c4ec3685cc6c36e7c87c3.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_coord_names.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/f9789b388786678686966c9093879ce592c79bc94d19929b6939cf66316c672c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/f9789b388786678686966c9093879ce592c79bc94d19929b6939cf66316c672c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/b87830b0c786cf269ec766c99399cce998d3b3166f2530d3658c692d30ec6735.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_coord_names.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e9a53a59961ec5a62c691a587b9662e1c0e1e53e9e0e9b873ec15a7161bc642f.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e9a53a59961ec5a62c691a587b9662e1c0e1e53e9e0e9b873ec15a7161bc642f.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/b8a53b59c71ac5a6b8791c1867876b63d9e0e65c96199d871cc23339633664ce.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_coords.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/f9789b388786678686966c9093879ce592c79bc94d19929b6939cf66316c672c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/f9789b388786678686966c9093879ce592c79bc94d19929b6939cf66316c672c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/b87830b0c786cf269ec766c99399cce998d3b3166f2530d3658c692d30ec6735.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_coords.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e9a53a59961ec5a62c691a587b9662e1c0e1e53e9e0e9b873ec15a7161bc642f.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e9a53a59961ec5a62c691a587b9662e1c0e1e53e9e0e9b873ec15a7161bc642f.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/b8a53b59c71ac5a6b8791c1867876b63d9e0e65c96199d871cc23339633664ce.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_default.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/f9789b388786678686966c9093879ce592c79bc94d19929b6939cf66316c672c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/f9789b388786678686966c9093879ce592c79bc94d19929b6939cf66316c672c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/b87830b0c786cf269ec766c99399cce998d3b3166f2530d3658c692d30ec6735.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_yx_order.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa81948e857e4971907ea72e95fa66b2952e4ead6d429b527ac7a5286e981836.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81948e857e4971907ea72e95fa66b2952e4ead6d429b527ac7a5286e981836.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa85978e837e68f094d3673089626ad792073985659a9b1a7a15b52869f19f56.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_yx_order.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea159694856a6b5096afa53a36941da1e4f5c369cd1ae6d69b6a1c80625af2f6.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea159694856a6b5096afa53a36941da1e4f5c369cd1ae6d69b6a1c80625af2f6.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea95969c874a63d39ca3ad2a231cdbc9c4973631cd6336c633182cbc61c3d3f2.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotOtherCoordSystems.test_plot_tmerc.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e63399cd99cd64b29999335965369b262649c98c9b3966c6998d3319ccd69333.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e63399cd99cd64b29999335965369b262649c98c9b3966c6998d3319ccd69333.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e665326d999ecc9b3319b3246666cce69b496cccccc9669923193336666699a6.png"
- ],
+ ],
"iris.tests.test_plot.TestQuickplotPlot.test_t.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83ffb5d67fd4e5962211d9c6a443da77d5389c8ed346d923d011d968dc00da48.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/82ffb5d67fdde5962211d9c6a441da77d5389c8cd346d927d011d968dc00da48.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/82fabd867fd5e5822201d9c6a4539a77953d8cbf834f99e7d051996cdc00da48.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83ffb5d67fd4e5962211d9c6a443da77d5389c8ed346d923d011d968dc00da48.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82ffb5d67fdde5962211d9c6a441da77d5389c8cd346d927d011d968dc00da48.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82fabd867fd5e5822201d9c6a4539a77953d8cbf834f99e7d051996cdc00da48.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/83ffb59a7f00e59a2205d9d6e4619a74d9388c8e884e8da799d30b6dddb47e00.png"
- ],
+ ],
"iris.tests.test_plot.TestQuickplotPlot.test_t_dates.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a3ffd5ae7f51efb6200378d7d4082c17d7280906d6e58962db31d800da6cdd26.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a3ffd4ae7f55efbe200178d7d4082c17d7280906d6e58962df319800da6cdd26.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a3ffd4827f51ef94200078d7c4082c57d739095ed6ed8962db759808da6cdd26.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a3ffd5ae7f51efb6200378d7d4082c17d7280906d6e58962db31d800da6cdd26.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a3ffd4ae7f55efbe200178d7d4082c17d7280906d6e58962df319800da6cdd26.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a3ffd4827f51ef94200078d7c4082c57d739095ed6ed8962db759808da6cdd26.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/82fd958a7e006f9ba0077bc5c9462c759873dd3c8d8f826699a187b358c82f67.png"
- ],
+ ],
"iris.tests.test_plot.TestQuickplotPlot.test_x.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83ffb5097e84c54a621799d8601d9966d213cd67c039d876d078d866d869d8f7.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/83ffbd097e84c54a621799d8601d9966d253cc27c039d876d078d866d869d8f7.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83ffb5097e84c54a621799d8601d9966d213cd67c039d876d078d866d869d8f7.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83ffbd097e84c54a621799d8601d9966d253cc27c039d876d078d866d869d8f7.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/82ff950b7f81c0d6620199bcfc5e986695734da1816e1b2c85be2b65d96276d1.png"
- ],
+ ],
"iris.tests.test_plot.TestQuickplotPlot.test_y.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a7ffb6067f008d87339bc973e435d86ef034c87ad07c586cd001da69897e5838.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a7ffb6067f008d87339bc973e435d86ef034c87ad07cd86cd001da68897e58a8.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a7efb6367f008d97338fc973e435d86ef030c86ed070d86cd030d86d89f0d82c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a7ffb6067f008d87339bc973e435d86ef034c87ad07c586cd001da69897e5838.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a7ffb6067f008d87339bc973e435d86ef034c87ad07cd86cd001da68897e58a8.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a7efb6367f008d97338fc973e435d86ef030c86ed070d86cd030d86d89f0d82c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a2fbb46e7f10c99f2013d863e46498dcd06c0d2798421fa5dd221e7789ff6f10.png"
- ],
+ ],
"iris.tests.test_plot.TestQuickplotPlot.test_z.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83ffc1dc7e00b0dc66179d95f127cfc9d44959ba846658e891075a3e99415a2f.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83ffc1dc7e00b0dc66179d95f127cfc9d44959ba846658e891075a3e99415a2f.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a3ffc1d87e00b49964179d28f16bce4b98724b268c6d58e1972e4874998b2e7e.png"
- ],
+ ],
"iris.tests.test_plot.TestSimple.test_bounds.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa9562fcc7c0b50bb53b9f8085727a157a95c0f67a85e07e0be08069e07d9fa0.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa9562fcc7c0b50bb53b9f8085727a157a95c0f67a85e07e0be08069e07d9fa0.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea856a85954a957ac17e954ac17a9c3e956ac07e3e81c07f3e857aa5c2753f80.png"
- ],
+ ],
"iris.tests.test_plot.TestSimple.test_points.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562b7c2763d09956a955a855a1d88d45ec57a3f81c07e6ae16b21c0ff7a81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562b7c2763d09956a955a855a1d88d45ec57a3f81c07e6ae16b21c0ff7a81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea856a85957a957ac17e954ac17e1ca2954ac07e3e81c07f3e807a85c1ff3f81.png"
- ],
+ ],
"iris.tests.test_plot.TestSymbols.test_cloud_cover.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e95a330c96a5ccf2695a330c96a5ccf2695a330c96b5ccf3694a330c96b5ccf3.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e95a330c96a5ccf2695a330c96a5ccf2695a330c96b5ccf3694a330c96b5ccf3.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eb52916494ad6e1b6b5291e494ad6e1b6b5291e494ad6e1b6b5291e494ad6e1b.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_alignment.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa95350f952ad2f0c1f66ac1c55a4af4e550a52b3e05905e1e419e6f937e3b21.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa95350f952ad3f0c1f66a81e55a4af4e550a52b3e05905e1e419e6f937e1b21.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa95350f952ad2f0c1f66ac1c55a4af4e550a52b3e05905e1e419e6f937e3b21.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa95350f952ad3f0c1f66a81e55a4af4e550a52b3e05905e1e419e6f937e1b21.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be8137f4954ac03fc0ff3e81d03f496a6d00b4af3ea0c07f6fa232c0db7f2d00.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_contour.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a3fd956a7a01a5ee321fc96666919b6ec15fdca593600d2586785a259dfa5a01.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a3fd956a7a01a5ee3217c9e66691996ec15fdca593680d2586785a259dfa5a01.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a3fd956a7a01a5ee321fc96666919b6ec15fdca593600d2586785a259dfa5a01.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a3fd956a7a01a5ee3217c9e66691996ec15fdca593680d2586785a259dfa5a01.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a7fd95da7a01654a3217c962e4819a56c96f3c8593624da584da3b658db662db.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_contour.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/faa12bc1954ef43fc0bf9f02854a4ee48548c17a5ab5c17e7a0d7875a17e3a81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/faa12bc1954ef43fc0bf9f02854a4ee48548c17a5ab5c17e7a0d7875a17e3a81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bf802f85c17fc17fc07eb42ac07f3f929130c07e3f80c07f7aa02e85c07f3e81.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_contourf.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fe812f88957a955a857a9257c17f7aa5c03dc0bf5a85c07e7f402d40a57a3f01.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fe812f88957a955a857a9257c17f7aa5c03dc0bf5a85c07e7f402d40a57a3f01.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be816a95957a957ac0fe1e8bc07f7f806e01c07f3f80c07f3fa23f00c07f3d00.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_contourf.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/faa12bc1954ef43fc0bf9f02854a4ee48548c17a5ab5c17e7a0d7875a17e3a81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/faa12bc1954ef43fc0bf9f02854a4ee48548c17a5ab5c17e7a0d7875a17e3a81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bf802f85c17fc17fc07eb42ac07f3f929130c07e3f80c07f7aa02e85c07f3e81.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_contourf.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa852f81955ac532c0bf9e89c57edae69357e13f4ea0c05a3f8561a4935a3e01.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa852f81955ac532c0bf9e89c57edae69357e13f4ea0c05a3f8561a4935a3e01.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be816a95907ae508c17e955ac07f3fa0945bc07f3f80c07f3aa36f01c0ff3f80.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_contourf_nameless.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/faa52ec1955ac536c0bf9e09c57edae69357e13f4e80c0da2f81618493da3f01.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/faa52ec1955ac536c0bf9e09c57edae69357e13f4e80c0da2f81618493da3f01.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be816af5907ee508c17e955ac03f3f809419c07f3f80c07f3a8b6f81c0ff3f80.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_map.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea5e618434ac36e5c1c9369b95b39c38c3a39a4fcee19a6e9b64cb609925cd25.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea5e618434ac36e5c1c9369b95b39c38c3a39a4fcee19a6e9b64cb609925cd25.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e85a636c86a597a593c9b49b94b79969c396c95bccc69a64db30d9b039a52c26.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_map.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea5e618434ac36e5c1c9369b95b39c38c3a39a4ecef19a6e9b64cb609925cd25.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea5e618434ac36e5c1c9369b95b39c38c3a39a4ecef19a6e9b64cb609925cd25.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e85a636c86a597a593c9b49b94b79969c396c95bccc69a64db30d9b039a52c26.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_pcolor.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bb423d4e94a5c6b9c15adaadc1fb6a469c8de43a3e07904e5f016b57984e1ea1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bb423d4e94a5c6b9c15adaadc1fb6a469c8de43a3e07904e5f016b57984e1ea1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eea16affc05ab500956e974ac53f3d80925ac03f2f81c07e3fa12da1c2fe3f80.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_pcolormesh.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bb433d4e94a4c6b9c15adaadc1fb6a469c8de43a3e07904e5f016b57984e1ea1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bb433d4e94a4c6b9c15adaadc1fb6a469c8de43a3e07904e5f016b57984e1ea1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eea16affc05ab500956e974ac53f3d80925ac03f3f81c07e3fa12da1c27e3f80.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_non_cube_coordinate.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa816a85857a955ae17e957ec57e7a81855fc17e3a81c57e1a813a85c57a1a05.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa816a85857a955ae17e957ec57e7a81855fc17e3a81c57e1a813a85c57a1a05.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fe816a85857a957ac07f957ac07f3e80956ac07f3e80c07f3e813e85c07e3f80.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa856a95e15ab51a953e9485857a1f409552857e1fc1c07e5abd4a35e07f4aa5.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa856a95e15ab51a953e9485857a1f409552857e1fc1c07e5abd4a35e07f4aa5.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea856a95955a956ac17f950ac07e3f48951ac07f3f81c0ff3ea16aa1c0be3e81.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562b7c2763d09956a955a855a1d88d45ec57a3f81c07e6ae16b21c0ff7a81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562b7c2763d09956a955a855a1d88d45ec57a3f81c07e6ae16b21c0ff7a81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea856a85957a957ac17e954ac17e1ca2954ac07e3e81c07f3e807a85c1ff3f81.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8aff878b7f00953062179561f087953ad167997a80784a7fc1e5d86d9978485f.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/8aff878b7f80953860179561f087953ad167997a80784a7fc1e5d86d9978485b.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8aff878b7f00953062179561f087953ad167997a80784a7fc1e5d86d9978485f.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8aff878b7f80953860179561f087953ad167997a80784a7fc1e5d86d9978485b.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eafdc6c9f720953030968d6795d28d6a95674b7b81304aedc9e51cad8d186c9a.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.3": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/82ff8db67f94952e76159d6bb01dcd629059c962c1fbd9c1c062da74d820ca74.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/82be8db67f95952e761d9d6bb01dcd628059c962c1fbd9e1c072da64d060ca74.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/82fe8db67f95952e76159d6bb01dcd629059c962c1fbd9e1c072da64d020ca74.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82ff8db67f94952e76159d6bb01dcd629059c962c1fbd9c1c062da74d820ca74.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82be8db67f95952e761d9d6bb01dcd628059c962c1fbd9e1c072da64d060ca74.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82fe8db67f95952e76159d6bb01dcd629059c962c1fbd9e1c072da64d020ca74.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a2ff6a967f00952eb40d9d0f900fcd62c47069f3d1f93a909c266e34d8a56f68.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.4": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/aa97b70ff5f0970f20b2956a6a17957af805da71d06f5a75d02cd870d800d8f2.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e1faa549de9497090697971d60539f3ef171c87ac075487ad025d87ed801da3e.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/aa97b70ff5f0970f20b2956a6a17957af805da71d06f5a75d02cd870d800d8f2.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e1faa549de9497090697971d60539f3ef171c87ac075487ad025d87ed801da3e.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eadab54fd7a1856d90819d6df8169962e946d862802ed8809ded7e809d2d03ff.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.5": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e8faad47f784bd0596859d03969f9962c05dc96ee07189fe6870c862687178f8.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a8fa2d4797859585b6959d07605f896ee051697ad061d9fad0619aaed801deae.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e8faad47f784bd0596859d03969f9962c05dc96ee07189fe6870c862687178f8.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a8fa2d4797859585b6959d07605f896ee051697ad061d9fad0619aaed801deae.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/aa5b3c0c978187a4b60199bc605f6976687e6873d07c99e390acdc0391fc2f7b.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_x.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a6ffb5097e84cde2224598d1649f8d6cd2388c76d0799867d009da76c9f8d866.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a6bfb5097f84cde2224599d1649f8d6cd2388c76d0799867d009da76c1f8d866.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a6ffb5097e84cde2224598d1649f8d6cd2388c76d0799867d009da76c9f8d866.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a6bfb5097f84cde2224599d1649f8d6cd2388c76d0799867d009da76c1f8d866.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a6fbb50cfbd0c036203598dce4c88d26d32f8cf3886e1df3dc047b4289ec6e72.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_y.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a7ff978b7f00c9c830d7992166179e969509d866c478d964d079c876d869da26.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a7ff97837f00c9c830d79921661f9e9695099876c478d964c079c876d879da26.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a7ff978b7f00c9c830d7992166179e969509d866c478d964d079c876d869da26.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a7ff97837f00c9c830d79921661f9e9695099876c478d964c079c876d879da26.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a2ffb6127f0dc9993085d960c6748d3e9b121ca49d6a1b048df34ce789ff7205.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_yx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea856a9ff16eb740954a9e05855a19a3c0fbc13e1ea5c07d5ad0cb58e45e3c35.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea856a9ff16eb740954a9e05855a19a3c0fbc13e1ea5c07d5ad0cb58e45e3c35.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea856a95957a957ac07e954ac17e3e87950bc07f3ea4c27d3e833ac1c1e03f80.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_yx.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e5a565b69e1a9a42917e1a19c17b3a619e59c47b3a25c53e3b8430e5c57a3e85.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e5a565b69e1a9a42917e1a19c17b3a619e59c47b3a25c53e3b8430e5c57a3e85.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e5a761a79a589e58c07d1e48c07c3f819e41c07f3d84c17e3fa62585c0fe3f83.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_yx.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/afffe6d67700958636179d92e019992dd039daf5817d987a807a48e499684a6d.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/aeffe6d67780958636179d92e019892dd139daf5815d987a807a48e699684a6d.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/afffe6d67700958636179d92e019992dd039daf5817d987a807a48e499684a6d.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/aeffe6d67780958636179d92e019892dd139daf5815d987a807a48e699684a6d.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eaff6ad4f74ab16490109c9b942999add1b74bb785a41d4acd526a254acc6365.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_yx.3": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea5e618434ac36e5c1c9369b95b39c38c3a39a4fcee19a6e9b64cb609925cd25.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea5e618434ac36e5c1c9369b95b39c38c3a39a4fcee19a6e9b64cb609925cd25.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e85a636c86a597a593c9b49b94b79969c396c95bccc69a64db30d9b039a52c26.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_yx.4": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2fd2d09295c2d1c3d33c1bc2d67d2c696ce0653c3ac2b1d976da05c2c4.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2fd2d09295c2d1c3d33c1bc2d27d2c696ce0e53c3ad2b1d976da01c2c4.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e85e3e2f97a1c19996a1c8f26d1e3a0f684a3c2c6913dc2497b9db8095e502ff.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2fd2d09295c2d1c3d33c1bc2d67d2c696ce0653c3ac2b1d976da05c2c4.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2fd2d09295c2d1c3d33c1bc2d27d2c696ce0e53c3ad2b1d976da01c2c4.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e85e3e2f97a1c19996a1c8f26d1e3a0f684a3c2c6913dc2497b9db8095e502ff.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e85e3c1f97a1c3e197a1c9f37c5e390668521e0c390bdd8685b1d86096e5279f.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_yx.5": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e968658e969692c797879e3b86929e58696d49cd6869c9a37962c923990d9c6d.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e9e1658e961e92569e9e3c7966d36c586165698c70e1ce739b3698619e1e984c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e968658e969692c797879e3b86929e58696d49cd6869c9a37962c923990d9c6d.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e9e1658e961e92569e9e3c7966d36c586165698c70e1ce739b3698619e1e984c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e1a530e29e5ecf199a5acd8f64f1326161a538e665a198d29e52cb1d9a5e6669.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_zx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bf813f80c156c05dc0fec29dc17f1a6dd05fc0ff1aa1c57e3b243b20375a1e81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bf813f80c156c05dc0fec29dc17f1a6dd05fc0ff1aa1c57e3b243b20375a1e81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be816a81d17ec57ac07e952ac07f3aa0955ec17e3f80c07f3f803f80c0bf3f81.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_zx.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea95629d956a996069939e9bc07f7aad856cc47e5e81857a1e254a35c1be1b81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea95629d956a996069939e9bc07f7aad856cc47e5e81857a1e254a35c1be1b81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa816a85957a957ac03f957ac07f3ba1954ac07e3e81c07f3ea47a85c07e3e80.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_zx.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/87ed2f867f008d8220179852f01fd9bed1789a6c847cc877c46ac972987ec8fd.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/87ed2f067f008d8220179852f01fd9bed1789a6c847cc877c468c9f6987ec8fd.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/87ed2f067f008d8220179c52f01fd9bed1789a6c847cc877c560c976987ec8fd.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/87ed2f867f008d8220179852f01fd9bed1789a6c847cc877c46ac972987ec8fd.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/87ed2f067f008d8220179852f01fd9bed1789a6c847cc877c468c9f6987ec8fd.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/87ed2f067f008d8220179c52f01fd9bed1789a6c847cc877c560c976987ec8fd.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a3eded05fe11a492b000985af07fdbb4d1e3366d8c644da79fa68993180f6ec1.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_zx.3": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a2f9b5ba7600a56962df9e96f01dc926c498cc46847f9d6cd0244bf19a6b19f1.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a2f9b5ba7600856962df9e96f01dcd26c498cc46847f9d6cd0244bf19a6b1975.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a2f9b5ba7600a56962df9e96f01dc926c498cc46847f9d6cd0244bf19a6b19f1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a2f9b5ba7600856962df9e96f01dcd26c498cc46847f9d6cd0244bf19a6b1975.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/aef9f93a770085e9205fd696d13c4b2485ca1a43952f1934daa66bd1ca6b3c71.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_zx.4": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ae953f87d5e82d86801f91ee6e1591fe7e117876c07d6877d068d878d800d07a.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ae953f87d5e82d87801b91ee6e1599fe7e117874c07d6877d068d878d800d07a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ae953f87d5e82d86801f91ee6e1591fe7e117876c07d6877d068d878d800d07a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ae953f87d5e82d87801b91ee6e1599fe7e117874c07d6877d068d878d800d07a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bec1329dc5be85dac01d58d73e419d423e41daa59822dc00c5fefe0091fe03ff.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_zx.5": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e87a952d96856943969f694696858d4ee0519d6ee07f9b6a78619b2a79711a2a.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e87a952d96856943969f694696858d4ae0519d6ee07f996a78719b2a79711a3a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e87a952d96856943969f694696858d4ee0519d6ee07f9b6a78619b2a79711a2a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e87a952d96856943969f694696858d4ae0519d6ee07f996a78719b2a79711a3a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e85e96ac97a168d897a5791695a19927913c3953687ecce3687c86e3487cc6c3.png"
- ],
+ ],
"iris.tests.test_quickplot.TestTimeReferenceUnitsLabels.test_not_reference_time_units.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/82faa1977fdf89976200ddf6e000d9e7f75f9866d560dae4dc00d966dc005e20.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/82b8a1977fdf89876200dde6e000d9e7f77f9866d560dfe4dc00d966fc005e20.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/82f8a1977fdf89876200ddf6e000d9e7f77f9866d560dee4dc00d966dc005e20.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/82f8a1977fdf89876200dde6e000d9e7f77f9866d560dfe4dc00dd64dc005e20.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82faa1977fdf89976200ddf6e000d9e7f75f9866d560dae4dc00d966dc005e20.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82b8a1977fdf89876200dde6e000d9e7f77f9866d560dfe4dc00d966fc005e20.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82f8a1977fdf89876200ddf6e000d9e7f77f9866d560dee4dc00d966dc005e20.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82f8a1977fdf89876200dde6e000d9e7f77f9866d560dfe4dc00dd64dc005e20.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/82faa19e7f51898c6001dd86845fd9a2dd7f996281ee19f389ef03ffdc007e00.png"
- ],
+ ],
"iris.tests.test_quickplot.TestTimeReferenceUnitsLabels.test_reference_time_units.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/82fe81987fd777ffe0002addd4002805dda8de65dde9d4625bfddc209841de20.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/82fe81987fdf77ffe0002a9dd4002805ddaade65d9a9d5625bfddc209841de20.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/82fe81987fdf77ffe0002addd4002805dd28df67d9a9d4625bfddc209841de20.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82fe81987fd777ffe0002addd4002805dda8de65dde9d4625bfddc209841de20.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82fe81987fdf77ffe0002a9dd4002805ddaade65d9a9d5625bfddc209841de20.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82fe81987fdf77ffe0002addd4002805dd28df67d9a9d4625bfddc209841de20.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/82fa80997f547799a0037a00d52f0956ddaf9f7e98a1816e09f5d8260bfffe00.png"
]
}
\ No newline at end of file
From f51ae8405e1e0c7e8a68bf05ddfbd4da9091cc62 Mon Sep 17 00:00:00 2001
From: Patrick Peglar
Date: Tue, 4 Sep 2018 17:27:15 +0100
Subject: [PATCH 30/62] Vector plots 4 (#3158)
---
docs/iris/src/whatsnew/2.2.rst | 5 +-
lib/iris/plot.py | 55 +-
.../integration/plot/test_vector_plots.py | 180 +++
lib/iris/tests/results/imagerepo.json | 1049 +++++++++--------
4 files changed, 718 insertions(+), 571 deletions(-)
create mode 100644 lib/iris/tests/integration/plot/test_vector_plots.py
diff --git a/docs/iris/src/whatsnew/2.2.rst b/docs/iris/src/whatsnew/2.2.rst
index 4edc305025..7b069f455e 100644
--- a/docs/iris/src/whatsnew/2.2.rst
+++ b/docs/iris/src/whatsnew/2.2.rst
@@ -25,9 +25,8 @@ Iris 2.2.0 Features
contiguous, or the cube's data must be masked at the discontiguities in
order to avoid plotting errors.
- The iris plot functions :func:`iris.plot.quiver` and
- :func:`iris.plot.streamplot` have been added, and these also work with
- 2-dimensional plot coordinates.
+ The iris plot functions :func:`iris.plot.quiver` has been added, and this
+ also works with 2-dimensional plot coordinates.
.. admonition:: 2-Dimensional Grid Vectors
diff --git a/lib/iris/plot.py b/lib/iris/plot.py
index 0b9b7c54be..f0dfccd8c5 100644
--- a/lib/iris/plot.py
+++ b/lib/iris/plot.py
@@ -1226,9 +1226,9 @@ def _vector_component_args(x_points, y_points, u_data, *args, **kwargs):
if crs:
if not isinstance(crs, (ccrs.PlateCarree, ccrs.RotatedPole)):
msg = ('Can only plot vectors provided in a lat-lon '
- 'projection, i.e. "cartopy.crs.PlateCarree" or '
- '"cartopy.crs.RotatedPole". This '
- "cubes coordinate system is {}.")
+ 'projection, i.e. equivalent to "cartopy.crs.PlateCarree" '
+ 'or "cartopy.crs.RotatedPole". This '
+ "cube coordinate system translates as Cartopy {}.")
raise ValueError(msg.format(crs))
# Given the above check, the Y points must be latitudes.
# We therefore **assume** they are in degrees : I'm not sure this
@@ -1237,7 +1237,7 @@ def _vector_component_args(x_points, y_points, u_data, *args, **kwargs):
# TODO: investigate degree units assumptions, here + elsewhere.
# Implement a latitude scaling, but preserve the given magnitudes.
- v_data = v_data.copy()
+ u_data, v_data = [arr.copy() for arr in (u_data, v_data)]
mags = np.sqrt(u_data * u_data + v_data * v_data)
v_data *= np.cos(np.deg2rad(y_points))
scales = mags / np.sqrt(u_data * u_data + v_data * v_data)
@@ -1294,53 +1294,6 @@ def quiver(u_cube, v_cube, *args, **kwargs):
*args, **kwargs)
-def streamplot(u_cube, v_cube, *args, **kwargs):
- """
- Draws a streamline plot from two vector component cubes.
-
- Args:
-
- * u_cube, v_cube : (:class:`~iris.cube.Cube`)
- u and v vector components. Must have same shape and units.
- If the cubes have geographic coordinates, the values are treated as
- true distance differentials, e.g. windspeeds, and *not* map coordinate
- vectors. The components are aligned with the North and East of the
- cube coordinate system.
-
- .. Note:
-
- At present, if u_cube and v_cube have geographic coordinates, then they
- must be in a lat-lon coordinate system, though it may be a rotated one.
- To transform wind values between coordinate systems, use
- :func:`iris.analysis.cartography.rotate_vectors`.
- To transform coordinate grid points, you will need to create
- 2-dimensional arrays of x and y values. These can be transformed with
- :meth:`cartopy.crs.CRS.transform_points`.
-
- Kwargs:
-
- * coords: (list of :class:`~iris.coords.Coord` or string)
- Coordinates or coordinate names. Use the given coordinates as the axes
- for the plot. The order of the given coordinates indicates which axis
- to use for each, where the first element is the horizontal
- axis of the plot and the second element is the vertical axis
- of the plot.
-
- * axes: the :class:`matplotlib.axes.Axes` to use for drawing.
- Defaults to the current axes if none provided.
-
- See :func:`matplotlib.pyplot.quiver` for details of other valid
- keyword arguments.
-
- """
- #
- # TODO: check u + v cubes for compatibility.
- #
- kwargs['_v_data'] = v_cube.data
- return _draw_2d_from_points('streamplot', _vector_component_args, u_cube,
- *args, **kwargs)
-
-
def plot(*args, **kwargs):
"""
Draws a line plot based on the given cube(s) or coordinate(s).
diff --git a/lib/iris/tests/integration/plot/test_vector_plots.py b/lib/iris/tests/integration/plot/test_vector_plots.py
new file mode 100644
index 0000000000..00d9d48e8d
--- /dev/null
+++ b/lib/iris/tests/integration/plot/test_vector_plots.py
@@ -0,0 +1,180 @@
+# (C) British Crown Copyright 2014 - 2016, Met Office
+#
+# This file is part of Iris.
+#
+# Iris is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Iris is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Iris. If not, see .
+"""
+Test some key usages of :func:`iris.plot.quiver`.
+
+"""
+
+from __future__ import (absolute_import, division, print_function)
+from six.moves import (filter, input, map, range, zip) # noqa
+
+# import iris tests first so that some things can be initialised before
+# importing anything else
+import iris.tests as tests
+
+import numpy as np
+
+import cartopy.crs as ccrs
+from iris.coords import AuxCoord, DimCoord
+from iris.coord_systems import Mercator
+from iris.cube import Cube
+from iris.tests.stock import sample_2d_latlons
+
+# Run tests in no graphics mode if matplotlib is not available.
+if tests.MPL_AVAILABLE:
+ import matplotlib.pyplot as plt
+ from iris.plot import quiver
+
+
+@tests.skip_plot
+class MixinVectorPlotCases(object):
+ """
+ Test examples mixin, used by separate quiver + streamplot classes.
+
+ NOTE: at present for quiver only, as streamplot does not support arbitrary
+ coordinates.
+
+ """
+
+ def plot(self, plotname, *args, **kwargs):
+ plot_function = self.plot_function_to_test()
+ plot_function(*args, **kwargs)
+ plt.suptitle(plotname)
+
+ @staticmethod
+ def _nonlatlon_xyuv():
+ # Create common x, y, u, v arrays for quiver/streamplot testing.
+ x = np.array([0., 2, 3, 5])
+ y = np.array([0., 2.5, 4])
+ uv = np.array([[(0., 0), (0, 1), (0, -1), (2, 1)],
+ [(-1, 0), (-1, -1), (-1, 1), (-2, 1)],
+ [(1., 0), (1, -1), (1, 1), (-2, 2)]])
+ uv = np.array(uv)
+ u, v = uv[..., 0], uv[..., 1]
+ return x, y, u, v
+
+ @staticmethod
+ def _nonlatlon_uv_cubes(x, y, u, v):
+ # Create u and v test cubes from x, y, u, v arrays.
+ coord_cls = DimCoord if x.ndim == 1 else AuxCoord
+ x_coord = coord_cls(x, long_name='x')
+ y_coord = coord_cls(y, long_name='y')
+ u_cube = Cube(u, long_name='u', units='ms-1')
+ if x.ndim == 1:
+ u_cube.add_dim_coord(y_coord, 0)
+ u_cube.add_dim_coord(x_coord, 1)
+ else:
+ u_cube.add_aux_coord(y_coord, (0, 1))
+ u_cube.add_aux_coord(x_coord, (0, 1))
+ v_cube = u_cube.copy()
+ v_cube.rename('v')
+ v_cube.data = v
+ return u_cube, v_cube
+
+ def test_non_latlon_1d_coords(self):
+ # Plot against simple 1D x and y coords.
+ x, y, u, v = self._nonlatlon_xyuv()
+ u_cube, v_cube = self._nonlatlon_uv_cubes(x, y, u, v)
+ self.plot('nonlatlon, 1-d coords', u_cube, v_cube)
+ plt.xlim(x.min() - 1, x.max() + 2)
+ plt.ylim(y.min() - 1, y.max() + 2)
+ self.check_graphic()
+
+ def test_non_latlon_2d_coords(self):
+ # Plot against expanded 2D x and y coords.
+ x, y, u, v = self._nonlatlon_xyuv()
+ x, y = np.meshgrid(x, y)
+ u_cube, v_cube = self._nonlatlon_uv_cubes(x, y, u, v)
+ # Call plot : N.B. default gives wrong coords order.
+ self.plot('nonlatlon_2d', u_cube, v_cube, coords=('x', 'y'))
+ plt.xlim(x.min() - 1, x.max() + 2)
+ plt.ylim(y.min() - 1, y.max() + 2)
+ self.check_graphic()
+
+ @staticmethod
+ def _latlon_uv_cubes(grid_cube):
+ # Make a sample grid into u and v data for quiver/streamplot testing.
+ u_cube = grid_cube.copy()
+ u_cube.rename('dx')
+ u_cube.units = 'ms-1'
+ v_cube = u_cube.copy()
+ v_cube.rename('dy')
+ ny, nx = u_cube.shape
+ nn = nx * ny
+ angles = np.arange(nn).reshape((ny, nx))
+ angles = (angles * 360.0 / 5.5) % 360.
+ scale = np.arange(nn) % 5
+ scale = (scale + 4) / 4
+ scale = scale.reshape((ny, nx))
+ u_cube.data = scale * np.cos(np.deg2rad(angles))
+ v_cube.data = scale * np.sin(np.deg2rad(angles))
+ return u_cube, v_cube
+
+ def test_2d_plain_latlon(self):
+ # Test 2d vector plotting with implicit (PlateCarree) coord system.
+ u_cube, v_cube = self._latlon_uv_cubes(sample_2d_latlons())
+ ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=180))
+ self.plot('latlon_2d', u_cube, v_cube,
+ coords=('longitude', 'latitude'))
+ ax.coastlines(color='red')
+ ax.set_global()
+ self.check_graphic()
+
+ def test_2d_plain_latlon_on_polar_map(self):
+ # Test 2d vector plotting onto a different projection.
+ u_cube, v_cube = self._latlon_uv_cubes(sample_2d_latlons())
+ ax = plt.axes(projection=ccrs.NorthPolarStereo())
+ self.plot('latlon_2d_polar', u_cube, v_cube,
+ coords=('longitude', 'latitude'))
+ ax.coastlines(color='red')
+ self.check_graphic()
+
+ def test_2d_rotated_latlon(self):
+ # Test plotting vectors in a rotated latlon coord system.
+ u_cube, v_cube = self._latlon_uv_cubes(
+ sample_2d_latlons(rotated=True))
+ ax = plt.axes(projection=ccrs.PlateCarree(central_longitude=180))
+ self.plot('2d_rotated', u_cube, v_cube,
+ coords=('longitude', 'latitude'))
+ ax.coastlines(color='red')
+ ax.set_global()
+ self.check_graphic()
+
+ def test_fail_unsupported_coord_system(self):
+ # Test plotting vectors in a rotated latlon coord system.
+ u_cube, v_cube = self._latlon_uv_cubes(sample_2d_latlons())
+ patch_coord_system = Mercator()
+ for cube in u_cube, v_cube:
+ for coord in cube.coords():
+ coord.coord_system = patch_coord_system
+ re_msg = ('Can only plot .* lat-lon projection, .* '
+ 'This .* translates as Cartopy.*Mercator')
+ with self.assertRaisesRegexp(ValueError, re_msg):
+ self.plot('2d_rotated', u_cube, v_cube,
+ coords=('longitude', 'latitude'))
+
+
+class TestQuiver(MixinVectorPlotCases, tests.GraphicsTest):
+ def setUp(self):
+ super(TestQuiver, self).setUp()
+
+ def plot_function_to_test(self):
+ return quiver
+
+
+if __name__ == "__main__":
+ tests.main()
diff --git a/lib/iris/tests/results/imagerepo.json b/lib/iris/tests/results/imagerepo.json
index e7614cae19..ef9bf542de 100644
--- a/lib/iris/tests/results/imagerepo.json
+++ b/lib/iris/tests/results/imagerepo.json
@@ -1,952 +1,967 @@
{
"example_tests.test_COP_1d_plot.TestCOP1DPlot.test_COP_1d_plot.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/baff589936602d8ec977334ae4dac9b61a6dc4d99532c86cc2913e36c4cc0f61.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/baff589936602d8ec977334ae4dac9b61a6dc4d99532c86cc2913e36c4cc0f61.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/aefec91c3601249cc9b3336dc4c8cdb31a64c6d997b3c0eccb5932d285e42f33.png"
- ],
+ ],
"example_tests.test_COP_maps.TestCOPMaps.test_cop_maps.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea9138db95668524913e6ac168997e85957e917e876396b96a81b5ce3c496935.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea9138db95668524913e6ac168997e85957e917e876396b96a81b5ce3c496935.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea9130db95668524913c6ac178995b0d956e917ec76396b96a853dcf94696935.png"
- ],
+ ],
"example_tests.test_SOI_filtering.TestSOIFiltering.test_soi_filtering.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fac460b9c17b78723e05a5a9954edaf062332799954e9ca5c63b9a52d24e5a95.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa8460b9c17b78723e05a5a9954edaf062333799954e9ca5c63b9a52d24e4a9d.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fac460b9c17b78723e05a5a9954edaf062332799954e9ca5c63b9a52d24e5a95.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa8460b9c17b78723e05a5a9954edaf062333799954e9ca5c63b9a52d24e4a9d.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa167295c5e0696a3c17a58c9568da536233da19994cdab487739b4b9b444eb5.png"
- ],
+ ],
"example_tests.test_TEC.TestTEC.test_TEC.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e1a561b69b1a9a42846e9a49c7596e3cce6c907b3a83c17e1b8239b3e4f33bc4.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e1a561b69b1a9e43846e9a49c7596e2cce6c907b3a83c16e1b9231b3e4f33b8c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e1a561b69b1a9a42846e9a49c7596e3cce6c907b3a83c17e1b8239b3e4f33bc4.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e1a561b69b1a9e43846e9a49c7596e2cce6c907b3a83c16e1b9231b3e4f33b8c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e5a761b69a589a4bc46f9e48c65c6631ce61d1ce3982c13739b33193c0ee3f8c.png"
- ],
+ ],
"example_tests.test_anomaly_log_colouring.TestAnomalyLogColouring.test_anomaly_log_colouring.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ec4464e185a39f93931e9b1e91696d2949dde6e63e26a47a5ad391938d9a5a0c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ec4464e185a39f93931e9b1e91696d2949dde6e63e26a47a5ad391938d9a5a0c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ecc164e78e979b19b3789b0885a564a56cc2c65e3ec69469db1bdb9a853c1e24.png"
- ],
+ ],
"example_tests.test_atlantic_profiles.TestAtlanticProfiles.test_atlantic_profiles.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/9f8260536bd28e1320739437b5f437b0a51d66f4cc5d08fcd00fdb1c93fcb21c.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/9f8260536bd28e1320739437b5f437b0a51d66f4cc7c09f4d00fdb1c93fcb21c.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/9f8a60536bd28e1320739437b5f437b0a53d66f4cc5c08f4d00fdb1c93fcb21c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/9f8260536bd28e1320739437b5f437b0a51d66f4cc5d08fcd00fdb1c93fcb21c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/9f8260536bd28e1320739437b5f437b0a51d66f4cc7c09f4d00fdb1c93fcb21c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/9f8a60536bd28e1320739437b5f437b0a53d66f4cc5c08f4d00fdb1c93fcb21c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/9fc060f462a08f07203ebc77a1f36707e61f4e38d8f7d08a910197fc877cec58.png"
- ],
+ ],
"example_tests.test_atlantic_profiles.TestAtlanticProfiles.test_atlantic_profiles.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a6eaa57e6e81ddf999311ba3b3775e20845d5889c199673b4e22a4675e8ca11c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a6eaa57e6e81ddf999311ba3b3775e20845d5889c199673b4e22a4675e8ca11c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eeea64dd6ea8cd99991f1322b3761e06845718d89995b3131f32a4765ec2a1cd.png"
- ],
+ ],
"example_tests.test_coriolis_plot.TestCoriolisPlot.test_coriolis_plot.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e78665de9a699659e55e9965886979966986c5e63e98c19e3a256679e1981a24.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e78665de9a699659e55e9965886979966986c5e63e98c19e3a256679e1981a24.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e68665de9a699659c1fe99a5896965966996c46e3e19c1da3a652669c51e1a26.png"
- ],
+ ],
"example_tests.test_cross_section.TestCrossSection.test_cross_section.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea95317b9562e4d1649f5a05856e4ca4da52947e4ea5f13f1b499d42f13b1b41.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea95317b9562e4d1649f5a05856e4ca4da52947e4ea5f13f1b499d42f13b1b41.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea91b17b9562e4d1609f5a05856e4ca45a52957e5ea5f13b1bca9dc0b17b1ac1.png"
- ],
+ ],
"example_tests.test_cross_section.TestCrossSection.test_cross_section.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea9521fb956a394069921e93f07f4aad856cc47e4e95857a1ea5da3591ba1b81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea9521fb956a394069921e93f07f4aad856cc47e4e95857a1ea5da3591ba1b81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea9521fb956a394068931e9be07e4aa5856cc47e4a91957a1ba55bb5b17a3b81.png"
- ],
+ ],
"example_tests.test_custom_aggregation.TestCustomAggregation.test_custom_aggregation.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fe816e81917e907eb43e873f85677ac190f0703c6a95811f1ac33ce1a57a6f18.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fe816e81917e907eb43e873f85677ac190f0703c6a95811f1ac33ce1a57a6f18.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fe816e81817e907eb43e873f85637ac198d8703c6a94811f1ac73ee1a57a6f90.png"
- ],
+ ],
"example_tests.test_custom_file_loading.TestCustomFileLoading.test_custom_file_loading.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/faa0cbf1845e34be913787416edcc8bc3bc81f9b63332662a4ed30cdc1b2cd21.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fba0cbf1845e34be912787416edcc8bc3b881f9b62332762a5ad32cdc1b2cd21.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/faa0cbf1845e34be913787416edcc8bc3bc81f9b63332662a4ed30cdc1b2cd21.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fba0cbf1845e34be912787416edcc8bc3b881f9b62332762a5ad32cdc1b2cd21.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/faa1cb47845e34bc912797436cccc8343f11359b73523746c48c72d9d9b34da5.png"
- ],
+ ],
"example_tests.test_deriving_phenomena.TestDerivingPhenomena.test_deriving_phenomena.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/b9993986866952e6c9464639c4766bd9c669916e7b99c1663f99768990763e81.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/b99139de866952e6c946c639c47e6bd18769d16e7a9981662e813699d0763e89.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/b9993986866952e6c9464639c4766bd9c669916e7b99c1663f99768990763e81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/b99139de866952e6c946c639c47e6bd18769d16e7a9981662e813699d0763e89.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ec97681793689768943c97e8926669d186e8c33f6c99c32e6b936c83d33e2c98.png"
- ],
+ ],
"example_tests.test_global_map.TestGlobalMap.test_global_map.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa9979468566857ef07e3e8978566b91cb0179883c89946686a96b9d83766f81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa9979468566857ef07e3e8978566b91cb0179883c89946686a96b9d83766f81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa997b958466846ed13e87467a997a898d66d17e2cc9906684696f99d3162f81.png"
- ],
+ ],
"example_tests.test_hovmoller.TestGlobalMap.test_hovmoller.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bab430b4ce4bce43c5becf89c54b1a63c543c56e1e64907e3bb469b490de1ac1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bab430b4ce4bce43c5becf89c54b1a63c543c56e1e64907e3bb469b490de1ac1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eeb46cb4934b934bc07e974bc14b38949943c0fe3e94c17f6ea46cb4c07b3f00.png"
- ],
+ ],
"example_tests.test_inset_plot.TestInsetPlot.test_inset_plot.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ebff6992f50096a5b245dac4f6559496b49248dbc95dcb699529912dcf244a54.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e9ff6992b50096a5b245dac4f64594b6b49248dbc95dcb699529952dcf244a56.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ebff6992f50096a5b245dac4f6559496b49248dbc95dcb699529912dcf244a54.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e9ff6992b50096a5b245dac4f64594b6b49248dbc95dcb699529952dcf244a56.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ebff6992b50096ad9267dac4d64094b294924cdbc95d4b699d29952dcda46e94.png"
- ],
+ ],
"example_tests.test_lagged_ensemble.TestLaggedEnsemble.test_lagged_ensemble.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bbbb31e1c44e64e4b0459b5bb1716ecac464f496ce34618eb1079b39b193ce25.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bbbb31e1c44e64e4b0459b5bb1716ecac464f496ce34618eb1079b39b193ce25.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bbbb31b1c44e64e4b1579b5b917133cecc61f146c414668eb1119b1bb197ce34.png"
- ],
+ ],
"example_tests.test_lagged_ensemble.TestLaggedEnsemble.test_lagged_ensemble.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/abfef958fd462c993a07d87960464b81d1009687c139d3b594e9cf87c6b89687.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/abfef958fd462c993a07d87960464b81d1009687c139d3b594e9cf87c6b89687.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/aafec5e9e5e03e099a07e0f86542db879438261ec3b13ce78d8dc65a92d83d89.png"
- ],
+ ],
"example_tests.test_lineplot_with_legend.TestLineplotWithLegend.test_lineplot_with_legend.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/eae942526540b869961f8da694589da69543cc9af1014afbc3fd596b84fe19a7.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/eae942146540b869961f8de694589da69543cc9af1014afbc3fd596b84fe19a7.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eae942526540b869961f8da694589da69543cc9af1014afbc3fd596b84fe19a7.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eae942146540b869961f8de694589da69543cc9af1014afbc3fd596b84fe19a7.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eafd9e12a5a061e9925ec716de489e9685078ec981b229e70ddb79219cc3768d.png"
- ],
+ ],
"example_tests.test_orca_projection.TestOrcaProjection.test_orca_projection.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fb11731a94cea4ee64b35e91d1d2304e9e5ac7397b20e1fe12852487e666ce46.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fb11731a94cea4ee64b35e91d1d2304e9e5ac7397b20e1fe12852487e666ce46.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bb11721a87cce5e4cce79e81d19b3b5e1e1cd3783168e07835853485e65e2e1e.png"
- ],
+ ],
"example_tests.test_orca_projection.TestOrcaProjection.test_orca_projection.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e5a665a69a599659e5db1865c2653b869996cce63e99e19a1a912639e7181e65.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e5a665a69a599659e5db1865c2653b869996cce63e99e19a1a912639e7181e65.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e58661969e799659c1f719a6c867359a1996c0773649c09c3e612679c07b3f66.png"
- ],
+ ],
"example_tests.test_orca_projection.TestOrcaProjection.test_orca_projection.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/f2c464ce9e399332e1b74ce1cc79338c6586e5b33b31b37a66c9664cc06e1a64.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/f2c464ce9e399332e1b74ce1cc79338c6586e5b33b31b37a66c9664cc06e1a64.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a58660ce9e739b31c93d1cc9c8df33863383e33b3f11c03f2664366cc8ee3cc1.png"
- ],
+ ],
"example_tests.test_orca_projection.TestOrcaProjection.test_orca_projection.3": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa817a83846ea46ce539c93391de32cc86cf87a33fa168721cdb3e896e374b04.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa817a83846ea46ce539c93391de32cc86cf87a33fa168721cdb3e896e374b04.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be817a87845ea56cec79817a919e338436a5c1e73fa16c736c4a3e816a1e6b1c.png"
- ],
+ ],
"example_tests.test_polar_stereo.TestPolarStereo.test_polar_stereo.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e168317a92d36d89c5bb9e94c55e6f0c9a93c15a6ec584763b21716791de3a81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e168317a92d36d89c5bb9e94c55e6f0c9a93c15a6ec584763b21716791de3a81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/b9e16079971e9e93c8ce0f84c31e3b929f92c0ff3ca1c17e39e03961c07e3f80.png"
- ],
+ ],
"example_tests.test_polynomial_fit.TestPolynomialFit.test_polynomial_fit.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/abff4a9df26435886520c97f12414695c4b69d23934bc86adc969237d68ccc6f.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/aaff4a9df26435886520c97f12414695c4b69d23934bc86adc969a17d69ccc6f.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/abff4a9df26435886520c97f12414695c4b69d23934bc86adc969237d68ccc6f.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/aaff4a9df26435886520c97f12414695c4b69d23934bc86adc969a17d69ccc6f.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/aeffcb34d244348be5a2c96c3a4fc6d0c4b69f2d87294ccb9f1a125684cd7c11.png"
- ],
+ ],
"example_tests.test_projections_and_annotations.TestProjectionsAndAnnotations.test_projections_and_annotations.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa854f19851a30e4cc76cd0bb179325ca7c665b0c938cb4b4e719e9cb727b5c0.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fac54f19851a30e4cc76cd0bb179325cb78665b0c938cb4b4e719e9c9727b5c0.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa854e19851a30e4cc76cd0bb179325cb7c664b0c938cb4bce739e9c37a3b5c0.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa854e19851a30e4cc76cd0bb179325cb78665b1c938c94bce739e9c3727b5c0.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa854f19851a30e4cc76cd0bb179325ca7c665b0c938cb4b4e719e9cb727b5c0.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fac54f19851a30e4cc76cd0bb179325cb78665b0c938cb4b4e719e9c9727b5c0.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa854e19851a30e4cc76cd0bb179325cb7c664b0c938cb4bce739e9c37a3b5c0.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa854e19851a30e4cc76cd0bb179325cb78665b1c938c94bce739e9c3727b5c0.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa854f19851a30e4cc76cd0bb0f932dca7c665b1c92ccb4b4ed19e9c3721b5c8.png"
- ],
+ ],
"example_tests.test_projections_and_annotations.TestProjectionsAndAnnotations.test_projections_and_annotations.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e385699d9c3896627243318fcdad5a7dc6dba492e9b69964936dc21974b18592.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e385699d9c3896727243318f8dad5a7dc65ba492b93699649b6dc25b64938592.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e385699d9c3896627243318fcdad5a7dc6dba492b93699649b6dc25964938592.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e3856b999c3896727243318f8dad5a75965ba492f9b69964db4cc65b64918592.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e3856b999c3896727243318f8dad5a75865ba492e9b69964db6cc65b74918592.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e385699d9c3896627243318fcdad5a7dc6dba492e9b69964936dc21974b18592.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e385699d9c3896727243318f8dad5a7dc65ba492b93699649b6dc25b64938592.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e385699d9c3896627243318fcdad5a7dc6dba492b93699649b6dc25964938592.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e3856b999c3896727243318f8dad5a75965ba492f9b69964db4cc65b64918592.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e3856b999c3896727243318f8dad5a75865ba492e9b69964db6cc65b74918592.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e3856d999c389662734731afcdad5a7384daa592b1b69b64d26dc29974b18590.png"
- ],
+ ],
"example_tests.test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa15615e97a193adc15e1e81c4fa3eb49d30817e3e05c17e7ba59927817e1e01.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa15615e97a193adc15e1e81c4fa3eb49d30817e3e05c17e7ba59927817e1e01.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ee46607e97a19781c0df1f81d0bb3e241f20c16f3fc0c1fe39263d33d06f3e80.png"
- ],
+ ],
"example_tests.test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ba056717c3e099e9b90f8e81c4da589499b696763e45e56b3b893929c17b7e01.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ba056717c3e099e9b90f8e81c4da589499b696763e45e56b3b893929c17b7e01.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea57685f95a886a1c0de9da090be3e2697e1c0ff3f00c17e6b266c17c07f3f00.png"
- ],
+ ],
"example_tests.test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ba1e605ec7a191a1b85e9e81c4da58909996b37e3a65e16f7b817939e57a1e01.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ba1e605ec7a193a1b85e9e81c4da58909996b3763a65e16f7b816939ed7a1e01.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ba1e605ec7a191a1b85e9e81c4da58909996b37e3a65e16f7b817939e57a1e01.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ba1e605ec7a193a1b85e9e81c4da58909996b3763a65e16f7b816939ed7a1e01.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e85a697e97a18681c6da9f8190bf3e263624c1ef3b48c17a2b223c47c0ff3f81.png"
- ],
+ ],
"example_tests.test_rotated_pole_mapping.TestRotatedPoleMapping.test_rotated_pole_mapping.3": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa8172d0847ecd2bc913939c36846c714933799cc3cc8727e67639f939996a58.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa8172d0847ecd2bc913939c36846c714933799cc3cc8727e67639f939996a58.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa8172c6857ecd38cb3392ce36c564311931d85ec64e9787719a39993c316e66.png"
- ],
+ ],
"example_tests.test_wind_speed.TestWindSpeed.test_wind_speed.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bcf924fb9306930ce12ccf97c73236b28ecec4cd3e29847b18e639e6c14f1a09.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bcf924fb9306930ce12ccf97c73236b28ecec4cd3e29847b18e639e6c14f1a09.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e9e960e996169306c1ee9e96c29e36739e13c07d3d61c07f39a139a1c07f3f01.png"
- ],
+ ],
"example_tests.test_wind_speed.TestWindSpeed.test_wind_speed.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bcf924fb9306930ce12ccf97c73236b28ecec4cc3e29847b38e639e6c14f1a09.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bcf924fb9306930ce12ccf97c73236b28ecec4cc3e29847b38e639e6c14f1a09.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e9e960e996169306c1ee9e86c29e36739e13c07d3d61c07f39a139a1c17f3f01.png"
- ],
+ ],
"iris.tests.experimental.test_animate.IntegrationTest.test_cube_animation.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fe81957ac17e6a85817e6a85857e942a3e81957a7e81917a7a81d95ec17e2ca1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fe81957ac17e6a85817e6a85857e942a3e81957a7e81917a7a81d95ec17e2ca1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fe81c17e817e3e81817e7e81857e7e817e81c07e7e81c17e7a81817e817e8c2a.png"
- ],
+ ],
"iris.tests.experimental.test_animate.IntegrationTest.test_cube_animation.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/be81c17ec17e7e81c17e3e81c57ea55a3e80c17e3e81c1fe7a81c285c95f2c03.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/be81c17ec17e7e81c17e3e81c57ea55a3e80c17e3e81c1fe7a81c285c95f2c03.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fe81857e817e6a85817e7a81857e7e817e81957a7e81817e7a81817e817e843e.png"
- ],
+ ],
"iris.tests.experimental.test_animate.IntegrationTest.test_cube_animation.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea857a81957a857e957ec17e817e6a816a853e817a853e816e818d3a862ad3fe.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea857a81957a857e957ec17e817e6a816a853e817a853e816e818d3a862ad3fe.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be81857ec17e7a81c17e7e81857e3e803e81817a3e81c17e7a81c17ec97e2c2b.png"
- ],
+ ],
"iris.tests.integration.plot.test_plot_2d_coords.Test.test_2d_coord_bounds_northpolarstereo.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/e59661969e699659c0f719a6c967339a1992c07f3649c09c3f612669c07b3f66.png"
- ],
+ ],
"iris.tests.integration.plot.test_plot_2d_coords.Test.test_2d_coord_bounds_platecarree.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/ee816299954a1da699b6915ec25b6e419729c42c3f84bd9fe6d262d1d1dac076.png"
- ],
+ ],
+ "iris.tests.integration.plot.test_vector_plots.TestQuiver.test_2d_plain_latlon.0": [
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fb8d4f21c472b27e919d2e216f216b3178e69c7e961ab39a84696c616d245b94.png"
+ ],
+ "iris.tests.integration.plot.test_vector_plots.TestQuiver.test_2d_plain_latlon_on_polar_map.0": [
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e66c6619999933666666c6d99999336663646d9999c1332667b60cf964d8672c.png"
+ ],
+ "iris.tests.integration.plot.test_vector_plots.TestQuiver.test_2d_rotated_latlon.0": [
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eba925a5c476d25a95a56b876f3826246a449c6b96a3731ab13f6c656a5cb48a.png"
+ ],
+ "iris.tests.integration.plot.test_vector_plots.TestQuiver.test_non_latlon_1d_coords.0": [
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a7ac24947259f3493697632df45926b6e126c4f392593b4937266f26ccf032d8.png"
+ ],
+ "iris.tests.integration.plot.test_vector_plots.TestQuiver.test_non_latlon_2d_coords.0": [
+ "https://scitools.github.io/test-iris-imagehash/images/v4/afac26367251d3493617632df45c26a6e126c6f392593b4937266f26ccf232d0.png"
+ ],
"iris.tests.test_analysis.TestProject.test_cartopy_projection.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/9e1952c9c165b4fc668a9d47c1461d7a60fb2e853eb426bd62fd229c9f04c16d.png"
- ],
+ ],
"iris.tests.test_mapping.TestBasic.test_contourf.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e85a69cc96ad92e193c9963385929e1cc3819acde6d965ce6e666b30386e65b1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e85a69cc96ad92e193c9963385929e1cc3819acde6d965ce6e666b30386e65b1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e97a346c9685cb899685c9c39695c79396ec634969ce2c74697a3864697b3c8c.png"
- ],
+ ],
"iris.tests.test_mapping.TestBasic.test_pcolor.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e95a69c896a592e59bc99e3384929636c32d98cde6d964ce7e666332386465b1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e95a69c896a592e59bc99e3384929636c32d98cde6d964ce7e666332386465b1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e97a347c96858b8d9685c9c39696c393966c634969ce3c64697a3864697b3c9c.png"
- ],
+ ],
"iris.tests.test_mapping.TestBasic.test_unmappable.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/eaa5684eb54a947ad09eb731c521978dc2fb1cc0e4966ce26e2c6b2d3a6e691a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eaa5684eb54a947ad09eb731c521978dc2fb1cc0e4966ce26e2c6b2d3a6e691a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea853e48957ac1df957ac8be852bc1b1944e7a9878e03f4c6a253e6c7a912dc2.png"
- ],
+ ],
"iris.tests.test_mapping.TestBoundedCube.test_grid.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa81917e857e6e81857e7a857a81917a7a81857e857e7e81857e7a817a81852e.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7a81857e7a817a81817e7a81857e857e7a81857e7a817a81857e.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81917e857e6e81857e7a857a81917a7a81857e857e7e81857e7a817a81852e.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7a81857e7a817a81817e7a81857e857e7a81857e7a817a81857e.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7a81857e7a817a81857a7a81857e857e7a85857e7a817a81857a.png"
- ],
+ ],
"iris.tests.test_mapping.TestBoundedCube.test_pcolormesh.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa81e535857e92ca8ec23d21b13ce15e7a811ea5c47e1a5ac17b652d3b05e4f2.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81e535857e92ca8ec23d21b13ce15e7a811ea5c47e1a5ac17b652d3b05e4f2.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81c17a857e1ea5857e634a7a81cd257e8584da857e3b29817e68f47a81c791.png"
- ],
+ ],
"iris.tests.test_mapping.TestLimitedAreaCube.test_grid.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bf80e2b1c17f1d0ac4f7c8d739a637202749699b6bb3ce3666e4b048944d9d89.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/bf80e2f1c17f1d0ac457c8d619a637213749699b6bb34e3666e4b04e944d9d89.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bf80e2b1c17f1d0ac4f7c8d739a637202749699b6bb3ce3666e4b048944d9d89.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bf80e2f1c17f1d0ac457c8d619a637213749699b6bb34e3666e4b04e944d9d89.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea05392995bac6d691ce3f21666569d86a96c6360ee195cb91e8ce54953b313b.png"
- ],
+ ],
"iris.tests.test_mapping.TestLimitedAreaCube.test_outline.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e3e80857e7a817a817a817a81817f7a81857e857e857e857e7a81.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7e21857e7a817a817a857a81857a7a81857a857e857a857e7a84.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e3e80857e7a817a817a817a81817f7a81857e857e857e857e7a81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7e21857e7a817a817a857a81857a7a81857a857e857a857e7a84.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa1585e885e87a1785fa7a177a177e807a1585e85fa0857a85e86817857f6a16.png"
- ],
+ ],
"iris.tests.test_mapping.TestLimitedAreaCube.test_pcolormesh.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bf81e6b1c17e1d4884bfc8df39a43720374969db69b34e26c4e4b0ca904f9d89.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bf81e6b1c17e1d4884bfc8df39a43720374969db69b34e26c4e4b0ca904f9d89.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea57396995a8c6d691ea3f25664569d86b16c63686ed958991ea4a549531393b.png"
- ],
+ ],
"iris.tests.test_mapping.TestLimitedAreaCube.test_scatter.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea053d2e916ac2d9c4d894346b24f3477acf68ad39329ed8c696e136c1ab9a71.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea053d2e916ac2d9c4d895346b2473477acf68ad39329ed8c69ee126c1ab9a71.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea053d2e916ac2d9c4d894346b24f3477acf68ad39329ed8c696e136c1ab9a71.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea053d2e916ac2d9c4d895346b2473477acf68ad39329ed8c69ee126c1ab9a71.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea05bd2e916ac2d984983d346b2473477acf69ad3d3296d8c696e126c1ab1e71.png"
- ],
+ ],
"iris.tests.test_mapping.TestLowLevel.test_keywords.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/be21a71bc1de58e43a31871f7e856470c1fa9b8c7b81647384665b9ed1b998c1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/be21a71bc1de58e43a31871f7e856470c1fa9b8c7b81647384665b9ed1b998c1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be21a71bc1de58e43a63a71b3e016061c1fe9b8c3e01a473847e5b94d1fb9ac3.png"
- ],
+ ],
"iris.tests.test_mapping.TestLowLevel.test_keywords.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea811831957fe3cea68c6ce0d9f29b9b6a816463953e61cc917f1ae36ac09d38.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea811831957fe3cea68c6ce0d9f29b9b6a816463953e61cc917f1ae36ac09d38.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa819097857e6560957e7bcc7a819c316e81951e857e62c281fe79a17aa19637.png"
- ],
+ ],
"iris.tests.test_mapping.TestLowLevel.test_params.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ee819cb7913b63c8846e64737bb1999c6ec52633953a69c8916f6c636e92911c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ee819cb7913b63c8846e64737bb1999c6ec52633953a69c8916f6c636e92911c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa8190be857e6739917a7bc47a8594337bb1911c857e6ec3913279007e819637.png"
- ],
+ ],
"iris.tests.test_mapping.TestLowLevel.test_params.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/be21a71bc1de58e43a31871f7e856470c1fa9b8c7b81647384665b9ed1b998c1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/be21a71bc1de58e43a31871f7e856470c1fa9b8c7b81647384665b9ed1b998c1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be21a71bc1de58e43a63a71b3e016061c1fe9b8c3e01a473847e5b94d1fb9ac3.png"
- ],
+ ],
"iris.tests.test_mapping.TestLowLevel.test_params.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea811831957ae3cea68c6ce0c9f39b9b6a816473953e63cc917f1ae36ac09d38.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea811831957ae3cea68c6ce0c9f39b9b6a816473953e63cc917f1ae36ac09d38.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81909f857e6520957e5bcc7a8194716e31851e857e6ac281fe3f817a81963f.png"
- ],
+ ],
"iris.tests.test_mapping.TestLowLevel.test_simple.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/eae0943295154bcc844e6c314fb093ce7bc7c4b3a4307bc4916f3f316ed2b4ce.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eae0943295154bcc844e6c314fb093ce7bc7c4b3a4307bc4916f3f316ed2b4ce.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/faa0e55c855fdce7857a1ab16a85a50c3ea1e55e856658a5c11837096e8fe17a.png"
- ],
+ ],
"iris.tests.test_mapping.TestMappingSubRegion.test_simple.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bd913e01d07ee07e926e87876f8196c1e0d36967393c1f181e2c3cb8b0f960d7.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bd913e01d07ee07e926e87876f8196c1e0d36967393c1f181e2c3cb8b0f960d7.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/b9913d90c66eca6ec66ec2f3689195b6cf5b2f00392cb3496695621d34db6c92.png"
- ],
+ ],
"iris.tests.test_mapping.TestUnmappable.test_simple.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fe818d6ac17e5a958d7ab12b9d677615986e666dc4f20dea7281d98833889b22.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fe818d6ac17e5a958d7ab12b9d677615986e666dc4f20dea7281d98833889b22.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81b54a817eca35817ec701857e3e64943e7bb41b846f996e817e006ee1b19b.png"
- ],
+ ],
"iris.tests.test_plot.Test1dPlotMultiArgs.test_coord.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83fec2ff7c00a56de9023b52e4143da5d16d7ecad1b76f2094c963929c6471c8.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83fec2ff7c00a56de9023b52e4143da5d16d7ecad1b76f2094c963929c6471c8.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8bfec2d77e01a5a5ed013b4ac4521c94817d4e6d91ff63349c6d61991e3278cc.png"
- ],
+ ],
"iris.tests.test_plot.Test1dPlotMultiArgs.test_coord_coord.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/87ff95776a01e1f67801cc36f4075b81c5437668c1167c88d2676d39d6867b68.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/87ff95776a01e1f67801cc36f4075b81c5437668c1167c88d2676d39d6867b68.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8fff941e7e01e1c2f801c878a41e5b0d85cf36e1837e2d9992c62f21769e6a4d.png"
- ],
+ ],
"iris.tests.test_plot.Test1dPlotMultiArgs.test_coord_coord_map.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fbe0623dc9879d91b41e4b449b6579e78798a49b7872d2644b8c919b39306e6c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fbe0623dc9879d91b41e4b449b6579e78798a49b7872d2644b8c919b39306e6c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bbe0c21ccd179dc3b05e4b689b0771b48698961b7962da446e8ca5bb36716c6e.png"
- ],
+ ],
"iris.tests.test_plot.Test1dPlotMultiArgs.test_coord_cube.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8ff897066b41f076f81dce1fb007da79c50633e9c40626b8d1066df9d6067969.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8ff897066b41f076f81dce1fb007da79c50633e9c40626b8d1066df9d6067969.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8ff897066a01f0f2f818ee1eb007ca41853e3b81c57e36a991fe2ca9725e29ed.png"
- ],
+ ],
"iris.tests.test_plot.Test1dPlotMultiArgs.test_cube.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8ffac1547a0792546c179db7f1254f6d945b7392841678e895017e3e91c17a0f.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8ffac1547a0792546c179db7f1254f6d945b7392841678e895017e3e91c17a0f.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8ff8c1fa7a05b4ea6c059d2ff1494e4b90f26304846d78d1872a6cfc938b2e3e.png"
- ],
+ ],
"iris.tests.test_plot.Test1dPlotMultiArgs.test_cube_coord.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83fec1ff7e0098757103a71ce4506dc3d11e7b20d2477ec094857db895217f6a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83fec1ff7e0098757103a71ce4506dc3d11e7b20d2477ec094857db895217f6a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8fffc1dc7e019c70f001b70ee4386de1814e7938837b6a7f84d07c9f15b02f21.png"
- ],
+ ],
"iris.tests.test_plot.Test1dPlotMultiArgs.test_cube_cube.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8ff8c2d73a09b4a76c099d26f14b0e5ad0d643b0d42763e9d51378f895867c39.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/8fe8c0173a19b4066d599946f35f0ed5d0b74729d40369d8953678e897877879.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8ff8c2d73a09b4a76c099d26f14b0e5ad0d643b0d42763e9d51378f895867c39.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8fe8c0173a19b4066d599946f35f0ed5d0b74729d40369d8953678e897877879.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8ff8c0567a01b096e4019daff10b464bd4da6391943678e5879f7e3103e67f1c.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_coord.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83fec2777e04256f68023352f6d61da5c109dec8d19bcf089cc9d99a9c85d999.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/83fec2777e06256f68023352f6d61da5c009decad19bcf089cc9d99a9c85d989.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83fec2777e04256f68023352f6d61da5c109dec8d19bcf089cc9d99a9c85d999.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83fec2777e06256f68023352f6d61da5c009decad19bcf089cc9d99a9c85d989.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/83fec2777e002427e801bb4ae65a1c94813dcec999db4bbc9ccd79991f3238cc.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_coord_coord.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83fe9dd77f00e1d73000cc1df707db8184427ef8d1367c88d2667d39d0866b68.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/83fe9d977f41e1d73000cc1df707d98184427ef8d1367c88d2667d39d0866b68.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83fe9dd77f00e1d73000cc1df707db8184427ef8d1367c88d2667d39d0866b68.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83fe9d977f41e1d73000cc1df707d98184427ef8d1367c88d2667d39d0866b68.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/83ff9d9f7e01e1c2b001c8f8f63e1b1d81cf36e1837e259982ce2f215c9a626c.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_coord_coord_map.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fbe0623dc9879d91b41e4b449b6579e78798a49b7872d2644b8c919b39306e6c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fbe0623dc9879d91b41e4b449b6579e78798a49b7872d2644b8c919b39306e6c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bbe0c21ccd179dc3b05e4b689b0771b48698961b7962da446e8ca5bb36716c6e.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_coord_cube.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/87ffb5867f0060d4301f6d9fb007d899c50699e9c8668e78d8678d69de069969.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/87ffb5867f0060d4301f6d9fb007d899c50699e9c8668e78d8678d69de069969.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/87ffb79e7f0060d8303fcd1eb007d801c52699e18d769e2199e60ce1da5629ed.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_cube.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83ffc1dc7e00b0dc66179d95f127cfc9d44959ba846658e891075a3e99415a2f.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83ffc1dc7e00b0dc66179d95f127cfc9d44959ba846658e891075a3e99415a2f.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a3ffc1d87e00b49964179d28f16bce4b98724b268c6d58e1972e4874998b2e7e.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_cube_coord.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83fec1ff7f90987720029f1ef458cd43811cdb60d647de609485ddb899215f62.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/83fec1ff7f94987720009f1ef458cd43810cdb60d647de609485ddb89921df62.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83fec1ff7f90987720029f1ef458cd43811cdb60d647de609485ddb899215f62.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83fec1ff7f94987720009f1ef458cd43810cdb60d647de609485ddb89921df62.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a3ffc1de7e009c7030019786f438cde3810fd97c93734a778ce07c9f99b02731.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotPlotMultiArgs.test_cube_cube.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83ffc8967e0098a6241f9d26e34b8e42f4d20bb4942759e9941f78f8d7867a39.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/83f9c8967e009da6245f9946e25f9ed6f0940f29f40749d8853678e8d7857879.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83ffc8967e0098a6241f9d26e34b8e42f4d20bb4942759e9941f78f8d7867a39.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83f9c8967e009da6245f9946e25f9ed6f0940f29f40749d8853678e8d7857879.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/83ffc9d67e00909624079daef160cf4bd45a439184367ae5979f7e3119e6261c.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotScatter.test_coord_coord.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a3fac1947c99184e62669ca7f65bc96ab81d97b7e248199cc7913662d94ac5a1.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a3fac1947c99184e62669ca7f65bc96ab81d97b7c248399cc7917662d84ac5a1.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a3fac1b47c99184e62669ca7f65bc96ab81d97b7e248199cc7913662d84acda0.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a3fac1947c99184e62669ca7f65bc96ab81d97b7e248199cc7913662d94ac5a1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a3fac1947c99184e62669ca7f65bc96ab81d97b7c248399cc7917662d84ac5a1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a3fac1b47c99184e62669ca7f65bc96ab81d97b7e248199cc7913662d84acda0.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/b2ecc1a8b9994a16e666b5e3ce151969a5fb4ed49909653990d46b9bfc097684.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotScatter.test_coord_coord_map.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bea07c99c15eb16e9891ce50c742394a3ced6cb13390f1cc73c29f1b2d0ecd66.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bea07c99c15eb16e9891ce50c742394a3ced6cb13390f1cc73c29f1b2d0ecd66.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bea06899c14eb16e9895ce46c74a396a74ed64b13390b3c61b439f1b4d2ccde6.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotScatter.test_coord_cube.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ae7f1f07f3e0e0f0211b9e066e074d83926ed8f8cd3792dad1964db0d80e9b09.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ae7f1f07f3e0e0f0311b9e066e074d839266d8e8cd379adad1964db0d80e9b09.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ae7f1f07f3e0e0f0211b9e066e074d83926ed8f8cd3792dad1964db0d80e9b09.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ae7f1f07f3e0e0f0311b9e066e074d839266d8e8cd379adad1964db0d80e9b09.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be852fc1e078c83eb30e3607672149c098d95c5b9e4636f2c1fc299d999f7e03.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotScatter.test_cube_coord.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a5f896d99a67b94c621deda3f69392cccd246db39018989ec4836de9ed249292.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a5f896d99a66b94c621deda3f69392cccd646db3901898dec4836de9cd249292.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a5f896d99a67b94c621ceda3f6d392cccd246db3901898dec4836de9cd249292.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a5f896d99a67b94c621deda3f69392cccd246db39018989ec4836de9ed249292.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a5f896d99a66b94c621deda3f69392cccd646db3901898dec4836de9cd249292.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a5f896d99a67b94c621ceda3f6d392cccd246db3901898dec4836de9cd249292.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/edfa96cb9a256b4f65466d9892d9c865693a1a9c94b39ed8484b35ad9a864c32.png"
- ],
+ ],
"iris.tests.test_plot.Test1dQuickplotScatter.test_cube_cube.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a4fb19b3db04c6cd6307b98678601c738c39d71cf3866186d8616e69bd191b9e.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a4fb19b3db04c6cd6307b98678601c738c39d71cf3866186d8616e69bd191b9e.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e8b33c129649c78de3a773e578650c728e92279be12de1edc4f246b2939c3b01.png"
- ],
+ ],
"iris.tests.test_plot.Test1dScatter.test_coord_coord.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bbfac39d9899384a6f6694a7b613cb489c95b7b7c24a399cc5913262d84acda0.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bbfac39d9899384a6f6694a7b613cb489c95b7b7c24a399cc5913262d84acda0.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/b2ecc12999994e16e666b5e3ce171969a5fb4ed49909e53990c44b9b7c09f684.png"
- ],
+ ],
"iris.tests.test_plot.Test1dScatter.test_coord_coord_map.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bea07c99c15eb16e9891ce50c742394a3ced6cb13390f1cc73c29f1b2d0ecd66.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bea07c99c15eb16e9891ce50c742394a3ced6cb13390f1cc73c29f1b2d0ecd66.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bea06899c14eb16e9895ce46c74a396a74ed64b13390b3c61b439f1b4d2ccde6.png"
- ],
+ ],
"iris.tests.test_plot.Test1dScatter.test_coord_cube.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/af7e1f0ff1e1e0f0d918960e6c076d8bd266d868c537365a90966db0de0e1b09.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ae7e1f0ff1e1e0f0d918960e6c076d83d266d868c537365ad0966db0de4e1b09.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/af7e1f0ff1e1e0f0d918960e6c076d8bd266d868c537365a90966db0de0e1b09.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ae7e1f0ff1e1e0f0d918960e6c076d83d266d868c537365ad0966db0de4e1b09.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be812fc1c078c03e930e3627672369c1d8d85c5b96463662e1fc699d9b9f7e03.png"
- ],
+ ],
"iris.tests.test_plot.Test1dScatter.test_cube_coord.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/edf896d79a67b94c651ced23d29392cccd646d33901912fcc4836d69ed249292.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/edf896d79a67b94c651ced23d29392cccd646d33901912fcc4836d69ed249292.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/edda96cb9a256b4765c26d9892dbc665693a1a9494b796c86c4b37ad92864c32.png"
- ],
+ ],
"iris.tests.test_plot.Test1dScatter.test_cube_cube.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/acf939339a16c64de306318638673c738c19d71cf3866186d8636e69bd191b9e.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/acf939339a16c64de306318638673c738c19d71cf3866186d8636e69bd191b9e.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/edb23c529649c78de38773e538650c729e92279be12de1edc4f246b2139c3b01.png"
- ],
+ ],
"iris.tests.test_plot.TestAttributePositive.test_1d_positive_down.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/87fef8117980c7c160078f1ffc049e7e90159a7a95419a7e910dcf1ece19ce3a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/87fef8117980c7c160078f1ffc049e7e90159a7a95419a7e910dcf1ece19ce3a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a7fe781b708487c360079e3bb4789869816bdb64c76b4a3cce7b4e749a6130c5.png"
- ],
+ ],
"iris.tests.test_plot.TestAttributePositive.test_1d_positive_up.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/87ff85d47800bd9f660779d0863f49c9947f4e1e9141de38d700da28ce1d9a2b.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/87ff85d47a00bc9f660779d8863f49c9907f4e1e9141de38d708da28ce1d9a0b.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/87ff85d47800bd9f660779d0863f49c9947f4e1e9141de38d700da28ce1d9a2b.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/87ff85d47a00bc9f660779d8863f49c9907f4e1e9141de38d708da28ce1d9a0b.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a7ff958b7a00b09c661761c9907fcb0d9163ce7895289a618f381bffccf97200.png"
- ],
+ ],
"iris.tests.test_plot.TestAttributePositive.test_2d_positive_down.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fb946ba684e194fb901b3a0587641ad03b1ae7674e64c15a5b99c767c47e3a98.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fb946ba684e194fb901b3a0587641ad03b1ae7674e64c15a5b99c767c47e3a98.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fb946ba484e194dbc01f3665c0e4399a3f0fc2653f90c99e3f613e64c81e3f81.png"
- ],
+ ],
"iris.tests.test_plot.TestAttributePositive.test_2d_positive_up.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ee176c7f93e093a0c50f9383815e6e156859e17e6e15e17a9be08e2d851a9b83.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ee176c7f93e093a0c50f9383815e6e156859e17e6e15e17a9be08e2d851a9b83.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ebc06be1941e941ec07f941f907f6fa0950fc07e6f80c07f6b806be1c07f3f80.png"
- ],
+ ],
"iris.tests.test_plot.TestContour.test_tx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/cff8a55f7a15b55a7817854ad007a5e8c04f3ce8c04f3e2ac4706ab295b37a96.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/cff8a55f7a15b55a7817854ad007a5e8c04f3ce8c04f3e2ac4706ab295b37a96.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eaece0173d17951fbd03974a914964e8c04a72e8c1531ee1cc746bb293973ecd.png"
- ],
+ ],
"iris.tests.test_plot.TestContour.test_ty.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8bfc815e78018597fc019b65b425d121955e7eda854b7d6a80db7eb481b72b61.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8bfc815e78018597fc019b65b425d121955e7eda854b7d6a80db7eb481b72b61.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ebfa8553fc01b15ab4044a269546caa5956b7e9bc0b97f2cc2d62d360b363b49.png"
- ],
+ ],
"iris.tests.test_plot.TestContour.test_tz.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8bfe81ff780185fff800955ad4027e00d517d400855f7e0085ff7e8085ff6aed.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/8bfe81ff780085fff800855fd4027e00d517d400855f7e0085ff7e8085ff6aed.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8bfe81ff780185fff800955ad4027e00d517d400855f7e0085ff7e8085ff6aed.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8bfe81ff780085fff800855fd4027e00d517d400855f7e0085ff7e8085ff6aed.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8bfe817ffc00855ef0007e81d4027e80815fd56a03ff7a8085ff3aa883ff6aa5.png"
- ],
+ ],
"iris.tests.test_plot.TestContour.test_yx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa56c3cc34e891b1c9a91c36c5a170e3c71b3e5993a784e492c49b4ecec76393.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa56c3cc34e891b1c9a91c36c5a170e3c71b3e5993a784e492c49b4ecec76393.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e85e36cb95b199999765cd3694b06478c7396329958434c2cecb6c6d69ce1b92.png"
- ],
+ ],
"iris.tests.test_plot.TestContour.test_zx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8bfe857f7a01a56afa05854ad015bd00d015d50a90577e80857f7ea0857f7abf.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8bfe857f7a01a56afa05854ad015bd00d015d50a90577e80857f7ea0857f7abf.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/affe815ffc008554f8007e01d0027e808557d5ea815f7ea0817f2fea817d2aff.png"
- ],
+ ],
"iris.tests.test_plot.TestContour.test_zy.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8bff81ff7a0195fcf8019578d4027e00d550d402857c7e0185fe7a8385fe6aaf.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8bff81ff7a0195fcf8019578d4027e00d550d402857c7e0185fe7a8385fe6aaf.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/abff857ff8018578f8017a80d4027e00855ec42a81fe7a8185fe6a8f85fe6ab7.png"
- ],
+ ],
"iris.tests.test_plot.TestContourf.test_tx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/faa562ed68569d52857abd12953a8f12951f64e0d30f3ac96a4d6a696ee06a32.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/faa562ed68569d52857abd12953a8f12951f64e0d30f3ac96a4d6a696ee06a32.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea857a81957ac57e957a857a957a958ac5723b0d6ac56b833e856e606a923e90.png"
- ],
+ ],
"iris.tests.test_plot.TestContourf.test_ty.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/eaa5e03f957a4f80954a9e41e16e9c60970fb5b24ada634e6e93692d4ba562d8.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eaa5e03f957a4f80954a9e41e16e9c60970fb5b24ada634e6e93692d4ba562d8.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea851f00957ac0f7957ac07f957a628d815e7b126ab13e816a953ae46a859ed3.png"
- ],
+ ],
"iris.tests.test_plot.TestContourf.test_tz.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e954a7a81857e957e857efc00857e7e007a85c02a7e859f287a85c1fe.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e954a7a81857e957e857efc00857e7e007a85c02a7e859f287a85c1fe.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7a81857e7a81857e7a81857e7a806a85857a7a85857e7a85817e.png"
- ],
+ ],
"iris.tests.test_plot.TestContourf.test_yx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e95a6938b6b5969193901a4fc1e594a7c69999cbce33639879526e72330e65e4.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e95a6938b6b5969193901a4fc1e594a7c69999cbce33639879526e72330e65e4.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e97a3c7e968597b19685c9c696a7c79491c16e59691a387f6978396e68683184.png"
- ],
+ ],
"iris.tests.test_plot.TestContourf.test_zx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa85857ec45a7a81857e854a857ee56a917ec56a3a85c56a3a85c4ea7a8112fe.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa85857ec45a7a81857e854a857ee56a917ec56a3a85c56a3a85c4ea7a8112fe.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81817e857e7a81857a7a81957a6e81917a6caa3a85c57a3a8585fa6a8591fe.png"
- ],
+ ],
"iris.tests.test_plot.TestContourf.test_zy.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa81817ec40a7a81857e957e857ef40a857ef60b7a81c40a7b81e60f7a814aff.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81817ec40a7a81857e957e857ef40a857ef60b7a81c40a7b81e60f7a814aff.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81817e857e7a81857e7a81817a7e81817a668f7a91857e7a81857e7a85817e.png"
- ],
+ ],
"iris.tests.test_plot.TestHybridHeight.test_bounds.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/eab5313f954a7b9260f39789c5ec4cd084d0c4e45aa1c5fe3a04797bb13b3b06.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eab5313f954a7b9260f39789c5ec4cd084d0c4e45aa1c5fe3a04797bb13b3b06.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ee856aa5957a955ac0bf954bc17e3b819548c07f3e81c07e2ec46ea4c07f3e84.png"
- ],
+ ],
"iris.tests.test_plot.TestHybridHeight.test_bounds.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/be853f80854ac17ec0bdc2f5c17a0d09cc1fc07f5ab5e1fe3f409d7a38743e00.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/be853f80854ac17ec0bdc2f5c17a0d09cc1fc07f5ab5e1fe3f409d7a38743e00.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bf813e85c07ec57ec17e9073c07e3f81856ec17a3f80c0fe3e813f84c2733e80.png"
- ],
+ ],
"iris.tests.test_plot.TestHybridHeight.test_bounds.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/eab5313f954a7b9260f39789c5ec4cd084d0c4e45aa1c5fe3a04797bb13b3b06.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/eab5313f954a7b9260f39789c5ec4cd084d0c4e45aa1c5fe3a04797bb13b3b06.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ee856aa5957a955ac0bf954bc17e3b819548c07f3e81c07e2ec46ea4c07f3e84.png"
- ],
+ ],
"iris.tests.test_plot.TestHybridHeight.test_orography.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa17291f95e895e8645e7a95c17a6eece4b4e1333b01c07e1bb13909914b9ec1.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa17291f95e895e8645e7a91c17a6ee464f4e1333b01c17e1bb1390d914b9ec1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa17291f95e895e8645e7a95c17a6eece4b4e1333b01c07e1bb13909914b9ec1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa17291f95e895e8645e7a91c17a6ee464f4e1333b01c17e1bb1390d914b9ec1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa817a91957a857ac4fe268cc07f6e846e05d9373b81d17b1b6a1b41c4fa2cc4.png"
- ],
+ ],
"iris.tests.test_plot.TestHybridHeight.test_orography.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bb07314fc4e0c6b4c31e9ee1847939a1c116c15e7b94e57e1ea9391de16e1ac3.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/bb07314fc6e1c6b4c31e9ee1846939a1c116c15e7b14e17e1ea9393de16e1ac3.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bb07314fc4e0c6b4c31e9ee1847939a1c116c15e7b94e57e1ea9391de16e1ac3.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bb07314fc6e1c6b4c31e9ee1846939a1c116c15e7b14e17e1ea9393de16e1ac3.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/af0b690f96f0d2d4c25e94a194ad3da19a52c25e3f02c07f3fa52d03c16a3fcb.png"
- ],
+ ],
"iris.tests.test_plot.TestHybridHeight.test_points.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea953bfb956ac4f4649f1a05c56e6ca45a53945e6ea5c13f1b498542c13f1b41.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea953bfb956ac4f4649f1a05c56e6ca45a53945e6ea5c13f1b498542c13f1b41.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fe857b91917a847ec0bd3f01c47e6ca43b11915a3ea4db3b1b4a84c4c03f3fc1.png"
- ],
+ ],
"iris.tests.test_plot.TestHybridHeight.test_points.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/be813fc0c15ac13dc1bfc27dc17e1d93c51fc43f1ea1c17a3ec138e4b1721a81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/be813fc0c15ac13dc1bfc27dc17e1d93c51fc43f1ea1c17a3ec138e4b1721a81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be813a81c17ec57ec17e952ac07f3f808556c17e3f80c07f3e813f80c27e3f81.png"
- ],
+ ],
"iris.tests.test_plot.TestHybridHeight.test_points.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea9561ef956a7b92609b922dc16e6ec6845ac47e5aa5c57e5ec04861957b1b81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea9561ef956a7b92609b922dc16e6ec6845ac47e5aa5c57e5ec04861957b1b81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fe856a85957a955ac03f956ac17f3f809552c07f3e81c07e3e806e85c07e3f84.png"
- ],
+ ],
"iris.tests.test_plot.TestHybridHeight.test_points.3": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea953bfb956ac4f4649f1a05c56e6ca45a53945e6ea5c13f1b498542c13f1b41.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea953bfb956ac4f4649f1a05c56e6ca45a53945e6ea5c13f1b498542c13f1b41.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fe857b91917a847ec0bd3f01c47e6ca43b11915a3ea4db3b1b4a84c4c03f3fc1.png"
- ],
+ ],
"iris.tests.test_plot.TestHybridHeight.test_points.4": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/baf5347ecf0ac3f1c1f68f83850b1f83cc11c0fc7ad0c17a1be138e4b07e1a0d.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/baf5347ecf0ac3f1c1f68f83850b1f83cc11c0fc7ad0c17a1be138e4b07e1a0d.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/b878387e978ec2f0c0f09f83878f3f81c070c0fe78d0c1763fa13856d03e3f0f.png"
- ],
+ ],
"iris.tests.test_plot.TestMissingCS.test_missing_cs.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fac16ee0953b911bc15e9648e56ec4e691be7bcc7a8184733ea16a90c17e930d.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fac16ee0953b911bc15e9648e56ec4e691be7bcc7a8184733ea16a90c17e930d.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa816ac1857e853cc17f957ac15f3e849486c8f43e81c13b3f813e91c07e3f46.png"
- ],
+ ],
"iris.tests.test_plot.TestMissingCoord.test_no_u.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fe816a95c17fb51e953e9485857a1f409552856a1f81c17e5ab94e15c0ff5a85.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fe816a95c17fb51e953e9485857a1f409552856a1f81c17e5ab94e15c0ff5a85.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea856a95955a954ac17f954ac07e3f48951ec07e3e81c0ff7ea16a81c0bf3e81.png"
- ],
+ ],
"iris.tests.test_plot.TestMissingCoord.test_no_u.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/be0e695ac3f096b5943fd2a185fc1e8590e594ee1e05c17a4f403d0fe1fe4b42.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/be0e695ac3f096b5943fd2a185fc1e8590e594ee1e05c17a4f403d0fe1fe4b42.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea956ab5954a954ac17f954a817e3f40950ac07f3e81c0ff7a856aa1c0ff3f80.png"
- ],
+ ],
"iris.tests.test_plot.TestMissingCoord.test_no_v.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562b6c0773d09956a955a857a1d88845ec57e3f81c07e4ae56b21d0ff5a85.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562b6c0773d09956a955a857a1d88845ec57e3f81c07e4ae56b21d0ff5a85.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa816a85957a857ac17e954ac17e1fa2950bc07e3e81c07f3e807a85c17f3f81.png"
- ],
+ ],
"iris.tests.test_plot.TestMissingCoord.test_no_v.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa9562d4c7c43d0bb57b97e0857a3f1995d284763a05c17a7b856a2dc0f45a84.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa9562d4c7c43d0bb57b97e0857a3f1995d284763a05c17a7b856a2dc0f45a84.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa856a85957a857ac17e954ac17e9d02954ac07e3e81c07f3e857a85c2fd3f80.png"
- ],
+ ],
"iris.tests.test_plot.TestMissingCoord.test_none.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562b6c0763d09b54a955a857a3f88845ec57a3e85c07e6a616b25d0ff7a81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562b6c0763d09b54a955a857a3f88845ec57a3e85c07e6a616b25d0ff7a81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa816a85957a857ac17e954ac17e3fa29506c07e3e81c07f3e807a84c1ff3f81.png"
- ],
+ ],
"iris.tests.test_plot.TestMissingCoord.test_none.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562f6c0773d09b54a955a857a3f81955ac47e3e85c17e7aa16a25c0765aa1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562f6c0773d09b54a955a857a3f81955ac47e3e85c17e7aa16a25c0765aa1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa856a85957a957ac17e954ac17a1f06954ac07e3e81c07f3e817a85c0ff3f80.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolor.test_tx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e85e67c9c7e1391e97a596b03a3696a13c4f63066318695ec5c9695e6c49c6a5.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e85e67c9c7e1391e97a596b03a3696a13c4f63066318695ec5c9695e6c49c6a5.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea817a81957e857e957e953e957e857e857e6aa06a816ac16a017a816a9585fa.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolor.test_ty.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b3878958b38f8c7236a557a542c7868d54b877875978abc789722.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b387895ab38f8c7236a557a542c7868d54b05787197eab478972a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b3878958b38f8c7236a557a542c7868d54b877875978abc789722.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b387895ab38f8c7236a557a542c7868d54b05787197eab478972a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea953f83954ac2bc956ac07e956a3509c0de61796ab57a816a856ad16ab590fb.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolor.test_tz.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e874978b978b6875978b6875978b7854950b78506855787468747ea2687597aa.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e874978b978b6875978b6875978b7854950b78506855787468747ea2687597aa.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857a7a84857a7a85857e7a813a2f7a817a85857a7a85857a7a85857a.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolor.test_yx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e95e696994b196b793b19a1ec3c191c5c6e596191e4e693269336c36391a6e3a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e95e696994b196b793b19a1ec3c191c5c6e596191e4e693269336c36391a6e3a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e97a387e968596319697c3c19284a62c93a560c36933393a6c7e793b6c6b31cd.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolor.test_zx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e85e87a197a1695a97a1695a97a17d5a97a17906785a7816685a7e86685ad687.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e85e87a197a1695a97a1695a97a17d5a97a17906785a7816685a7e86685ad687.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857a7e01857e7a81857e7a81e8177a816a8585fa7a85857e7a81857e.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolor.test_zy.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/af42c0bdd0ad2f52d0bd3f42d0bd7f02d0bd7f003d527f002f427ea82f42d6a8.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/af42c0bdd0ad2f52d0ad2b52d0bd7f02d0bd7f002d527f002f527e0d2f52d4ad.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/af42c0bdd0ad2f52d0bd3f42d0bd7f02d0bd7f003d527f002f427ea82f42d6a8.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/af42c0bdd0ad2f52d0ad2b52d0bd7f02d0bd7f002d527f002f527e0d2f52d4ad.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7e80857e7a81857e7a812d557a817a85857e7a81857e7a80857e.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolorNoBounds.test_tx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa1594f3858a670c94e37b1cccb13e736a1d8cf17a1f94e2c119938e9463678c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa1594f3858a670c94e37b1cccb13e736a1d8cf17a1f94e2c119938e9463678c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea858782957a703f957a3878957a7a65957a6bc06ae76f806ad50fd06a859c50.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolorNoBounds.test_ty.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ad5e94a5c3b0c3f096a5695a96a53c0f711b3c0f7d1b97b46943c3e0cc416b5a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ad5e94a5c3b0c3f096a5695a96a53c0f711b3c0f7d1b97b46943c3e0cc416b5a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea85857a857e7e81957a7a81957a6a85857acac6c1fb6aa67a81956e6a81b506.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolorNoBounds.test_tz.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a95e3c1f96a096a5d6a5eb40c3f0ebe0c1c0c3f07c0b3e3e96a13c1e6d5b694a.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a95e381f96a096a5d6a5eb40c3f0ebf0c1e0c3f07c0a3e3e96a13c1e6d5b694a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a95e3c1f96a096a5d6a5eb40c3f0ebe0c1c0c3f07c0b3e3e96a13c1e6d5b694a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a95e381f96a096a5d6a5eb40c3f0ebf0c1e0c3f07c0a3e3e96a13c1e6d5b694a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa817e81857e857a857e7a81857e6a85817b81e63a913e857e81c17e7a81956e.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolorNoBounds.test_yx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bc7a1c32d3c366cdc585c39986cdc79ec792e3a6960d584939793c3438743873.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bc7a1c32d3c366cdc585c39986cdc79ec792e3a6960d584939793c3438743873.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e96ac78796953c4c9685383996c538e69692637263696b49693ac796693ac71b.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolorNoBounds.test_zx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea1f781f95e085e885e0954295e195ea95a085e87a153e7f95e06a1778557a1f.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea1f781f95e085e885e0954295e195ea95a085e87a153e7f95e06a1778557a1f.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa817a81857e857e857e7a81857e6a81c17f95786aa77a807e81c17c7e819558.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolorNoBounds.test_zy.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ba173a1795e895e8c5e8f400c1f8c1f895a8c5e87a077a5ec5e83e173e177e02.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ba173a1795e895e8c5e8f400c1f8c1f895a8c5e87a077a5ec5e83e173e177e02.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa817a80857e857e857e7a81817e3e81817e857f6aa07a857e80c17f7e80c15f.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormesh.test_tx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e85e67c9c7e1391e97a596b03a3696a13c4fe3026318695ec5c9695e6c49c6a5.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e85e67c9c7e1391e97a596b03a3696a13c4fe3026318695ec5c9695e6c49c6a5.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea817a81957e857e957e953e957e857e857e6aa06a816ac16a017a816a9585fa.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormesh.test_ty.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b3878958b38f8c7236a557a542c7868d54b877875978abc789722.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b387895ab38f8c7236a557a542c7868d54b05787197eabc789722.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b3878958b38f8c7236a557a542c7868d54b877875978abc789722.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea74c707958b387895ab38f8c7236a557a542c7868d54b05787197eabc789722.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea953f83954ac2fc956ac07e956a3509c0de61796ab57a816a854ad16ab590fb.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormesh.test_tz.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e874978b978b6875978b6875978b7854950b78506855787468747ea2687597aa.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e874978b978b6875978b6875978b7854950b78506855787468747ea2687597aa.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857a7a84857a7a85857e7a813a2f7a817a85857a7a85857a7a85857a.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormesh.test_yx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e95e696994b196b593b19a1ec3c591c5c6e596191e4e693269336c36391a6e3a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e95e696994b196b593b19a1ec3c591c5c6e596191e4e693269336c36391a6e3a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e9693878969696139296c38f9bcc3474692169cb6c7339393c6cc387c78796cc.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormesh.test_zx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e85e87a197a1695a97a16d5a97a17d5a97a17806785a7816685a7e86685ad687.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e85e87a197a1695a97a16d5a97a17d5a97a17806785a7816685a7e86685ad687.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e6e05857e7a81857e7a81a0577a816a8585fa7a85857e7a81857e.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormesh.test_zy.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/af42c0bdd0ad2f52d0bd3f42d0bd7f02d0bd7f002d527f002f427fa82f42d6a8.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/af4280bdd0ad2f52d0ad2b52d0bd7f02d0bd7f002d527f002f527f0d2f52d4ad.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/af42c0bdd0ad2f52d0bd3f42d0bd7f02d0bd7f002d527f002f427fa82f42d6a8.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/af4280bdd0ad2f52d0ad2b52d0bd7f02d0bd7f002d527f002f527f0d2f52d4ad.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7e80857e7a81857e7a8129577a817a85857e7a81857e7a80857e.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormeshNoBounds.test_tx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa1594f3858a670c94e37b1cccb13e736a1d84f17a1d94e2c11d938e9463678e.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa1594f3858a670c94e37b1cccb13e736a1d8cf17a1d94e2c11993ae9463678c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa1594f3858a670c94e37b1cccb13e736a1d84f17a1d94e2c11d938e9463678e.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa1594f3858a670c94e37b1cccb13e736a1d8cf17a1d94e2c11993ae9463678c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea858782957a703f957a3878957a7a65957e6bc06ae56f806ad50fd06a859c50.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormeshNoBounds.test_ty.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ad5e94a5c3b0c3f096a1695a96a53c1f711b3c0f791b97b46943c3e06c436b5a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ad5e94a5c3b0c3f096a1695a96a53c1f711b3c0f791b97b46943c3e06c436b5a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea85857a857e7e81957a7a81957a6a85857acae6c1fb6aa47a81956e6a81b506.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormeshNoBounds.test_tz.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a95e3c1f96a096a5d6a56b40c3f06be2c1c0c3f07c0b3ebe96a13c1e6d5b694a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a95e3c1f96a096a5d6a56b40c3f06be2c1c0c3f07c0b3ebe96a13c1e6d5b694a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa813e81857e857a857e7a81857e6a85817b00e63eb93e857e81c17e7a81956e.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormeshNoBounds.test_yx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bc7a1c32d3c366cdc785c39986cdc78ec792e7a6960d584939793c3438703873.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bc7a1c32d3c366cdc785c39986cdc78ec792e7a6960d584939793c3438703873.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e129c7169ed638ec9ed6387196c761c665396724612dcf0d693896929ed698c9.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormeshNoBounds.test_zx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea1f781f95e085e895e0fd4295e095ea95a085e87a153e7e95e06a1778157a17.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea1f781f95e085e895e0fd4295e095ea95a085e87a153e7e95e06a1778157a17.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa817a85857a857e857e7a81857e7a81817f95506aaf7a807e81c17c7a81957a.png"
- ],
+ ],
"iris.tests.test_plot.TestPcolormeshNoBounds.test_zy.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ba176a1795e895e8c5e87c00c1f8c1f894a8c5e87a077adec5e83e173e177a06.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ba176a1795e895e8c5e87c00c1f8c1f894a8c5e87a077adec5e83e173e177a06.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa817a80857a857e857e7a81857e3e81817e2fc56aa07a857e80c17f7e80c17f.png"
- ],
+ ],
"iris.tests.test_plot.TestPlot.test_t.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83fe955f6a05e5137305d9c4f443127195187e9cd5467fa3d4917b68fc007a1a.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/8ffe95027e05e7007305d9c4a447127f853f069f814f2fa7d4d12b6cfc007e5a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83fe955f6a05e5137305d9c4f443127195187e9cd5467fa3d4917b68fc007a1a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8ffe95027e05e7007305d9c4a447127f853f069f814f2fa7d4d12b6cfc007e5a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8ffe9c1a7e05e718f305d9d2e46312718138049e824e2fa783db2bed76b4fe00.png"
- ],
+ ],
"iris.tests.test_plot.TestPlot.test_t_dates.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/abffd5ae2a15cdb6b10178d7d4082e57d7290906f685814277b1dc88724cfd26.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/abffd5ae2a15c9b6a10178d7d4082c57d7290906f6c58942f7b1dc88724cfd26.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/abffd4a02a01cc84f10078d7d4082c77d73909ded6ef816273bd9c98725cdd26.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/abffd5ae2a15cdb6b10178d7d4082e57d7290906f685814277b1dc88724cfd26.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/abffd5ae2a15c9b6a10178d7d4082c57d7290906f6c58942f7b1dc88724cfd26.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/abffd4a02a01cc84f10078d7d4082c77d73909ded6ef816273bd9c98725cdd26.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/87fc9d8a7e054d83f5067bc1c1423471927ba73c8d9f864e09a1a7b358c8276f.png"
- ],
+ ],
"iris.tests.test_plot.TestPlot.test_x.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8ffe95297e87c74a6a059158f89c3d6ed0536597c0387836d0f87866d0697097.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8ffe95297e87c74a6a059158f89c3d6ed0536597c0387836d0f87866d0697097.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8bfe956b7c01c2f26300929dfc1e3c6690736f91817e3b0c84be6be5d1603ed1.png"
- ],
+ ],
"iris.tests.test_plot.TestPlot.test_y.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8fe896266f068d873b83cb71e435725cd07c607ad07e70fcd0007a7881fe7ab8.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/8fe896066f068d873b83cb71e435725cd07c607ad07c70fcd0007af881fe7bb8.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/8fe896366f0f8d93398bcb71e435f24ed074646ed07670acf010726d81f2798c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8fe896266f068d873b83cb71e435725cd07c607ad07e70fcd0007a7881fe7ab8.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8fe896066f068d873b83cb71e435725cd07c607ad07c70fcd0007af881fe7bb8.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8fe896366f0f8d93398bcb71e435f24ed074646ed07670acf010726d81f2798c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/aff8946c7a14c99fb193d263e42432d8d00c2d27944a3f8dc5223ef703ff6b90.png"
- ],
+ ],
"iris.tests.test_plot.TestPlot.test_z.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8ffac1547a0792546c179db7f1254f6d945b7392841678e895017e3e91c17a0f.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8ffac1547a0792546c179db7f1254f6d945b7392841678e895017e3e91c17a0f.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8ff8c1fa7a05b4ea6c059d2ff1494e4b90f26304846d78d1872a6cfc938b2e3e.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCitation.test.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/abf895067a1d9506f811783585437abd85426ab995067af9f00687f96afe87c8.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCitation.test_axes.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/abf895067a1d9506f811783585437abd85426ab995067af9f00687f96afe87c8.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCitation.test_figure.0": [
"https://scitools.github.io/test-iris-imagehash/images/v4/abf895067a1d9506f811783585437abd85426ab995067af9f00687f96afe87c8.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_non_cube_coordinate.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7e81857e7a81857e7a81857e7a818576c02a7e95856a7e81c17a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e7e81857e7a81857e7a81857e7a818576c02a7e95856a7e81c17a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa81857e857e3e85857e7a81857e7a81857e7a817e81780b7a81c56a7a81857e.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fe8142f5c17ebd2cc16eb548954a9542916a347a915e60bd4afd68793f916296.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fe8142f5c17ebd2cc16eb548954a9542916a347a915e60bd4afd68793f916296.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea853f10956ac5e1957a854e957a203e955e6aa76ae17aa16a856aaf6ab19e12.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa8542b7b503b548857abd08857abd09945eed6b91d968c161b972d76aa462b5.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa8542b7b503b548857abd08857abd09945eed6a91d96ac163b972d36aa462b5.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa8542b7b503b548857abd08857abd09945eed6b91d968c161b972d76aa462b5.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa8542b7b503b548857abd08857abd09945eed6a91d96ac163b972d36aa462b5.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea853a85857a857a957a857a957ad05a857b3e946a606b917a816f647a853af4.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8bf88f457a03b5307e16b561f007b53ed067217ac1786afec0f570bf8178681a.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/8bf98f057a03b5307e16b561f007b53ad067217ac1786afec0f570bf8178685a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8bf88f457a03b5307e16b561f007b53ed067217ac1786afec0f570bf8178681a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8bf98f057a03b5307e16b561f007b53ad067217ac1786afec0f570bf8178685a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eafdcec9bc219530b696a56694c2852a95656b7b81986acdc0e516adad186eda.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.3": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8ffe8f367e05952afe05a50b980ded4bd05d69c2c1fb71c1c06272f4d0a06af4.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8ffe8f367e05952afe05a50b980ded4bd05d69c2c1fb71c1c06272f4d0a06af4.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/aff24ab7bd05952fbd0f950f914fcd48c47860f3e1b9329094266e345a850f6c.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.4": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/aa953d0f85fab50fd0f2956a7a1785fafa176877d00f68f1d02c60f2f008d0f0.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ebeaa5419e94b5019e97950d685395bee05361fad05560fad01570fef001dabe.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ebeaa5419e95b5419e97950d6853953ee053617ad05560fad01570fef001dabe.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/aa953d0f85fab50fd0f2956a7a1785fafa176877d00f68f1d02c60f2f008d0f0.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ebeaa5419e94b5019e97950d685395bee05361fad05560fad01570fef001dabe.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ebeaa5419e95b5419e97950d6853953ee053617ad05560fad01570fef001dabe.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ebfaa56f96a1856cd681a56ee8162d52e8467e12c50c7e8095ad7e0095ad03ff.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_tx.5": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ebfaaf439e87b5019687b5019687b56ac05561fae07103fe6079687a607178f8.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ebfa2d4b968795059e87970f6854697ae055697ac08561fad041d7aef001d6ae.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ebfaaf439e87b5019687b5019687b56ac05561fae07103fe6079687a607178f8.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ebfa2d4b968795059e87970f6854697ae055697ac08561fad041d7aef001d6ae.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eb7a3e0c978187a4950190bc6856687a607e687bc0fcc1e394acfc0197fc2bfb.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_x.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/aeb8b5095a87cd60386592d9ec97ad6dd23ca4f6d0797827f0096216c1f878e6.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/aeb8b5095a87cd60386592d9ec97ad6dd23ca4f6d0797827f0096216c1f878e6.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/affa950ddb13c03634359ad8a4c80f26911f26f3c06e0ff3f4007b4285fd6e72.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_y.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8fea97194f07c9c830d79169ce16269f91097af6c47861f6d0796076d0797a16.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/8fee970b4f07c9c930d79129ce16269f91097af6c4f861f4d0786076d0797a16.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/afea97094f07c9c870d79129ce16269f91096af6c4f861f6c07960f6d0797a16.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8fea97194f07c9c830d79169ce16269f91097af6c47861f6d0796076d0797a16.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8fee970b4f07c9c930d79129ce16269f91097af6c4f861f4d0786076d0797a16.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/afea97094f07c9c870d79129ce16269f91096af6c4f861f6c07960f6d0797a16.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/afee9632de05c9d9f180d168c454a53e931b3e84956a3b8c85d94ce703ff7284.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_yx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea85603f956a9741951e9d83c1fa8d2fd0a55af0d25f345ae5f062c72d68612d.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea85603f956a9741951e9d83c1fa8d2fd0a55af0d25f345ae5f062c72d68612d.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea853f00957ac07c957ac0be951a69f3c47c7a5f3a6127816b953e646b813761.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_yx.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e85a69cc96ad92e193c9963385929e1cc3819acde6d965ce6e666b30386e65b1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e85a69cc96ad92e193c9963385929e1cc3819acde6d965ce6e666b30386e65b1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e97a346c9685cb899685c9c39695c79396ec634969ce2c74697a3864697b3c8c.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_yx.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8ffcc65767039740bc069d9ad00b8dadd03f52f181dd347a847a62ff81e8626c.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/8ffcc65777039740bc069d9ad00b8dadd03d52f181dd707a847a62ff81e8626c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8ffcc65767039740bc069d9ad00b8dadd03f52f181dd347a847a62ff81e8626c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8ffcc65777039740bc069d9ad00b8dadd03d52f181dd707a847a62ff81e8626c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ebffca44f502b36498309c9b940999add1bb62bba784374acc5a6a246acc6b65.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_yx.3": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea5649c434ac92e5d9c9361b95b39c38c3835a5ec6d966ced34c633099ace5a5.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea5649c434ac92e5d9c9361b95b39c38c3835a5ec6d966ced34c633099ace5a5.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e85a6b6c96a597a591c9949b94b61b69c7926b5bccce66646b3869b831a52c26.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_yx.4": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2dd2d09295c3c0c7d13c1bc6d23d2c696de0e53c3ac393daf6d205c2c4.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2fd2d09295c3c0c7d13c1bc6d23d2c696ce0e53c3ac393dbf6d205c2c0.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2f92d09295c3d0c7d13c1bc6d23d2c696cf0e53c3ac2b3d9f6d201c2c4.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e85e3e2f97a1c19996a1c8f26c1e360f684a3c2c6913dca497b9d38097a903ff.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2dd2d09295c3c0c7d13c1bc6d23d2c696de0e53c3ac393daf6d205c2c4.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2fd2d09295c3c0c7d13c1bc6d23d2c696ce0e53c3ac393dbf6d205c2c0.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2f92d09295c3d0c7d13c1bc6d23d2c696cf0e53c3ac2b3d9f6d201c2c4.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e85e3e2f97a1c19996a1c8f26c1e360f684a3c2c6913dca497b9d38097a903ff.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e85e3e3f96a1c3e197a169f1785e3b0e68523e1c398bc58687b1d86096e1039f.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_yx.5": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e9686d8c9696924797879e3b86929e58696d69cc6869659379626133398d9ccd.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e961658f961e92469e1e1c7966f36cd86165618c70e166b39b9698719e1e9ec8.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e9686d8c9696924797879e3b86929e58696d69cc6869659379626133398d9ccd.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e961658f961e92469e1e1c7966f36cd86165618c70e166b39b9698719e1e9ec8.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e1a530e29e5ecf199a5acd8f64f1326161a530e265999cd29e52cf199a5e6669.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_zx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bf803f00c05fc4bfc07ec15dc05fd8bbc07cc96c333a32113bd02dd27ced3ec0.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bf803f00c05fc4bfc07ec15dc05fd8bbc07cc96c333a32113bd02dd27ced3ec0.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be813ea0c17ec55ac17ed23dc07e295ac57e3b653f803f813e816e853e81b542.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_zx.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea95956a95626993941a6a2d956e6ed6845a6e65c4bec7b64a9594686ea19578.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea95956a95626993941a6a2d956e6ed6845a6e65c4bec7b64a9594686ea19578.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea85856e857e4893957a7aa1956a7b81954b3b817a856fd46a85846e6e85857e.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_zx.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8fe82f047c018c83bc01bc5af01fd1bcd15a327c847860fdc57a69beb0be68bd.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/8fe82f047c018c83bc01bc5af01fd1bcd15a32fd847860fdc57269beb0be689d.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8fe82f047c018c83bc01bc5af01fd1bcd15a327c847860fdc57a69beb0be68bd.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8fe82f047c018c83bc01bc5af01fd1bcd15a32fd847860fdc57269beb0be689d.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/8bedcf25bc03a4929c103a5bf03fdbbc81cb364d86e46da70f86899b3a0f6cc0.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_zx.3": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/cee8953a7a15856978579696d03d672cc49a6e5a842d3d2cc0b66bd1c2ea39f1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/cee8953a7a15856978579696d03d672cc49a6e5a842d3d2cc0b66bd1c2ea39f1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/aee1f93a63168569b852d697913d632485ca2e43952d3bbcc2b66bd1426b3c71.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_zx.4": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ee953f0591ea3f07914a95fa7e07d1fa68156a15d07c6a3dd038c0fef000d0fa.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ae953f0591ea3f07914a95fa7e07d1fa68156a15d07c6a7dd068c0fef000d0fa.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ee953f0591ea3f07914a95fa7e07d1fa68156a15d07c6a3dd038c0fef000d0fa.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ae953f0591ea3f07914a95fa7e07d1fa68156a15d07c6a7dd068c0fef000d0fa.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bec11ab5c1be857ac13e7ae53c422d423e017a85b542fc00c1fefe0091fe03ff.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotCoordinatesGiven.test_zx.5": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e87a973d96a56953968769439685a54ae05117eae0511fba60513bba69717aba.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e87a952d96a56953968769439685a54ae85197eae0511fba60513bba69717aba.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e87a973d96a56953968769439685a54ae05117eae0511fba60513bba69717aba.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e87a952d96a56953968769439685a54ae85197eae0511fba60513bba69717aba.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e85a96ac97a16c5897a1791e95a53b0b913c6953687c4ec3685cc6c36e7c87c3.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_coord_names.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/f9789b388786678686966c9093879ce592c79bc94d19929b6939cf66316c672c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/f9789b388786678686966c9093879ce592c79bc94d19929b6939cf66316c672c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/b87830b0c786cf269ec766c99399cce998d3b3166f2530d3658c692d30ec6735.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_coord_names.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e9a53a59961ec5a62c691a587b9662e1c0e1e53e9e0e9b873ec15a7161bc642f.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e9a53a59961ec5a62c691a587b9662e1c0e1e53e9e0e9b873ec15a7161bc642f.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/b8a53b59c71ac5a6b8791c1867876b63d9e0e65c96199d871cc23339633664ce.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_coords.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/f9789b388786678686966c9093879ce592c79bc94d19929b6939cf66316c672c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/f9789b388786678686966c9093879ce592c79bc94d19929b6939cf66316c672c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/b87830b0c786cf269ec766c99399cce998d3b3166f2530d3658c692d30ec6735.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_coords.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e9a53a59961ec5a62c691a587b9662e1c0e1e53e9e0e9b873ec15a7161bc642f.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e9a53a59961ec5a62c691a587b9662e1c0e1e53e9e0e9b873ec15a7161bc642f.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/b8a53b59c71ac5a6b8791c1867876b63d9e0e65c96199d871cc23339633664ce.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_default.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/f9789b388786678686966c9093879ce592c79bc94d19929b6939cf66316c672c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/f9789b388786678686966c9093879ce592c79bc94d19929b6939cf66316c672c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/b87830b0c786cf269ec766c99399cce998d3b3166f2530d3658c692d30ec6735.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_yx_order.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa81948e857e4971907ea72e95fa66b2952e4ead6d429b527ac7a5286e981836.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa81948e857e4971907ea72e95fa66b2952e4ead6d429b527ac7a5286e981836.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa85978e837e68f094d3673089626ad792073985659a9b1a7a15b52869f19f56.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotDimAndAuxCoordsKwarg.test_yx_order.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea159694856a6b5096afa53a36941da1e4f5c369cd1ae6d69b6a1c80625af2f6.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea159694856a6b5096afa53a36941da1e4f5c369cd1ae6d69b6a1c80625af2f6.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea95969c874a63d39ca3ad2a231cdbc9c4973631cd6336c633182cbc61c3d3f2.png"
- ],
+ ],
"iris.tests.test_plot.TestPlotOtherCoordSystems.test_plot_tmerc.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e63399cd99cd64b29999335965369b262649c98c9b3966c6998d3319ccd69333.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e63399cd99cd64b29999335965369b262649c98c9b3966c6998d3319ccd69333.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e665326d999ecc9b3319b3246666cce69b496cccccc9669923193336666699a6.png"
- ],
+ ],
"iris.tests.test_plot.TestQuickplotPlot.test_t.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83ffb5d67fd4e5962211d9c6a443da77d5389c8ed346d923d011d968dc00da48.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/82ffb5d67fdde5962211d9c6a441da77d5389c8cd346d927d011d968dc00da48.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/82fabd867fd5e5822201d9c6a4539a77953d8cbf834f99e7d051996cdc00da48.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83ffb5d67fd4e5962211d9c6a443da77d5389c8ed346d923d011d968dc00da48.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82ffb5d67fdde5962211d9c6a441da77d5389c8cd346d927d011d968dc00da48.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82fabd867fd5e5822201d9c6a4539a77953d8cbf834f99e7d051996cdc00da48.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/83ffb59a7f00e59a2205d9d6e4619a74d9388c8e884e8da799d30b6dddb47e00.png"
- ],
+ ],
"iris.tests.test_plot.TestQuickplotPlot.test_t_dates.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a3ffd5ae7f51efb6200378d7d4082c17d7280906d6e58962db31d800da6cdd26.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a3ffd4ae7f55efbe200178d7d4082c17d7280906d6e58962df319800da6cdd26.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a3ffd4827f51ef94200078d7c4082c57d739095ed6ed8962db759808da6cdd26.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a3ffd5ae7f51efb6200378d7d4082c17d7280906d6e58962db31d800da6cdd26.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a3ffd4ae7f55efbe200178d7d4082c17d7280906d6e58962df319800da6cdd26.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a3ffd4827f51ef94200078d7c4082c57d739095ed6ed8962db759808da6cdd26.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/82fd958a7e006f9ba0077bc5c9462c759873dd3c8d8f826699a187b358c82f67.png"
- ],
+ ],
"iris.tests.test_plot.TestQuickplotPlot.test_x.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83ffb5097e84c54a621799d8601d9966d213cd67c039d876d078d866d869d8f7.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/83ffbd097e84c54a621799d8601d9966d253cc27c039d876d078d866d869d8f7.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83ffb5097e84c54a621799d8601d9966d213cd67c039d876d078d866d869d8f7.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83ffbd097e84c54a621799d8601d9966d253cc27c039d876d078d866d869d8f7.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/82ff950b7f81c0d6620199bcfc5e986695734da1816e1b2c85be2b65d96276d1.png"
- ],
+ ],
"iris.tests.test_plot.TestQuickplotPlot.test_y.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a7ffb6067f008d87339bc973e435d86ef034c87ad07c586cd001da69897e5838.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a7ffb6067f008d87339bc973e435d86ef034c87ad07cd86cd001da68897e58a8.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a7efb6367f008d97338fc973e435d86ef030c86ed070d86cd030d86d89f0d82c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a7ffb6067f008d87339bc973e435d86ef034c87ad07c586cd001da69897e5838.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a7ffb6067f008d87339bc973e435d86ef034c87ad07cd86cd001da68897e58a8.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a7efb6367f008d97338fc973e435d86ef030c86ed070d86cd030d86d89f0d82c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a2fbb46e7f10c99f2013d863e46498dcd06c0d2798421fa5dd221e7789ff6f10.png"
- ],
+ ],
"iris.tests.test_plot.TestQuickplotPlot.test_z.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/83ffc1dc7e00b0dc66179d95f127cfc9d44959ba846658e891075a3e99415a2f.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/83ffc1dc7e00b0dc66179d95f127cfc9d44959ba846658e891075a3e99415a2f.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a3ffc1d87e00b49964179d28f16bce4b98724b268c6d58e1972e4874998b2e7e.png"
- ],
+ ],
"iris.tests.test_plot.TestSimple.test_bounds.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa9562fcc7c0b50bb53b9f8085727a157a95c0f67a85e07e0be08069e07d9fa0.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa9562fcc7c0b50bb53b9f8085727a157a95c0f67a85e07e0be08069e07d9fa0.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea856a85954a957ac17e954ac17a9c3e956ac07e3e81c07f3e857aa5c2753f80.png"
- ],
+ ],
"iris.tests.test_plot.TestSimple.test_points.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562b7c2763d09956a955a855a1d88d45ec57a3f81c07e6ae16b21c0ff7a81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562b7c2763d09956a955a855a1d88d45ec57a3f81c07e6ae16b21c0ff7a81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea856a85957a957ac17e954ac17e1ca2954ac07e3e81c07f3e807a85c1ff3f81.png"
- ],
+ ],
"iris.tests.test_plot.TestSymbols.test_cloud_cover.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e95a330c96a5ccf2695a330c96a5ccf2695a330c96b5ccf3694a330c96b5ccf3.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e95a330c96a5ccf2695a330c96a5ccf2695a330c96b5ccf3694a330c96b5ccf3.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eb52916494ad6e1b6b5291e494ad6e1b6b5291e494ad6e1b6b5291e494ad6e1b.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_alignment.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa95350f952ad2f0c1f66ac1c55a4af4e550a52b3e05905e1e419e6f937e3b21.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa95350f952ad3f0c1f66a81e55a4af4e550a52b3e05905e1e419e6f937e1b21.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa95350f952ad2f0c1f66ac1c55a4af4e550a52b3e05905e1e419e6f937e3b21.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa95350f952ad3f0c1f66a81e55a4af4e550a52b3e05905e1e419e6f937e1b21.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be8137f4954ac03fc0ff3e81d03f496a6d00b4af3ea0c07f6fa232c0db7f2d00.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_contour.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a3fd956a7a01a5ee321fc96666919b6ec15fdca593600d2586785a259dfa5a01.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a3fd956a7a01a5ee3217c9e66691996ec15fdca593680d2586785a259dfa5a01.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a3fd956a7a01a5ee321fc96666919b6ec15fdca593600d2586785a259dfa5a01.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a3fd956a7a01a5ee3217c9e66691996ec15fdca593680d2586785a259dfa5a01.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a7fd95da7a01654a3217c962e4819a56c96f3c8593624da584da3b658db662db.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_contour.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/faa12bc1954ef43fc0bf9f02854a4ee48548c17a5ab5c17e7a0d7875a17e3a81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/faa12bc1954ef43fc0bf9f02854a4ee48548c17a5ab5c17e7a0d7875a17e3a81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bf802f85c17fc17fc07eb42ac07f3f929130c07e3f80c07f7aa02e85c07f3e81.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_contourf.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fe812f88957a955a857a9257c17f7aa5c03dc0bf5a85c07e7f402d40a57a3f01.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fe812f88957a955a857a9257c17f7aa5c03dc0bf5a85c07e7f402d40a57a3f01.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be816a95957a957ac0fe1e8bc07f7f806e01c07f3f80c07f3fa23f00c07f3d00.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_contourf.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/faa12bc1954ef43fc0bf9f02854a4ee48548c17a5ab5c17e7a0d7875a17e3a81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/faa12bc1954ef43fc0bf9f02854a4ee48548c17a5ab5c17e7a0d7875a17e3a81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bf802f85c17fc17fc07eb42ac07f3f929130c07e3f80c07f7aa02e85c07f3e81.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_contourf.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa852f81955ac532c0bf9e89c57edae69357e13f4ea0c05a3f8561a4935a3e01.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa852f81955ac532c0bf9e89c57edae69357e13f4ea0c05a3f8561a4935a3e01.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be816a95907ae508c17e955ac07f3fa0945bc07f3f80c07f3aa36f01c0ff3f80.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_contourf_nameless.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/faa52ec1955ac536c0bf9e09c57edae69357e13f4e80c0da2f81618493da3f01.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/faa52ec1955ac536c0bf9e09c57edae69357e13f4e80c0da2f81618493da3f01.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be816af5907ee508c17e955ac03f3f809419c07f3f80c07f3a8b6f81c0ff3f80.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_map.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea5e618434ac36e5c1c9369b95b39c38c3a39a4fcee19a6e9b64cb609925cd25.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea5e618434ac36e5c1c9369b95b39c38c3a39a4fcee19a6e9b64cb609925cd25.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e85a636c86a597a593c9b49b94b79969c396c95bccc69a64db30d9b039a52c26.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_map.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea5e618434ac36e5c1c9369b95b39c38c3a39a4ecef19a6e9b64cb609925cd25.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea5e618434ac36e5c1c9369b95b39c38c3a39a4ecef19a6e9b64cb609925cd25.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e85a636c86a597a593c9b49b94b79969c396c95bccc69a64db30d9b039a52c26.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_pcolor.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bb423d4e94a5c6b9c15adaadc1fb6a469c8de43a3e07904e5f016b57984e1ea1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bb423d4e94a5c6b9c15adaadc1fb6a469c8de43a3e07904e5f016b57984e1ea1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eea16affc05ab500956e974ac53f3d80925ac03f2f81c07e3fa12da1c2fe3f80.png"
- ],
+ ],
"iris.tests.test_quickplot.TestLabels.test_pcolormesh.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bb433d4e94a4c6b9c15adaadc1fb6a469c8de43a3e07904e5f016b57984e1ea1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bb433d4e94a4c6b9c15adaadc1fb6a469c8de43a3e07904e5f016b57984e1ea1.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eea16affc05ab500956e974ac53f3d80925ac03f3f81c07e3fa12da1c27e3f80.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_non_cube_coordinate.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa816a85857a955ae17e957ec57e7a81855fc17e3a81c57e1a813a85c57a1a05.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa816a85857a955ae17e957ec57e7a81855fc17e3a81c57e1a813a85c57a1a05.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fe816a85857a957ac07f957ac07f3e80956ac07f3e80c07f3e813e85c07e3f80.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa856a95e15ab51a953e9485857a1f409552857e1fc1c07e5abd4a35e07f4aa5.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa856a95e15ab51a953e9485857a1f409552857e1fc1c07e5abd4a35e07f4aa5.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea856a95955a956ac17f950ac07e3f48951ac07f3f81c0ff3ea16aa1c0be3e81.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562b7c2763d09956a955a855a1d88d45ec57a3f81c07e6ae16b21c0ff7a81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/fa8562b7c2763d09956a955a855a1d88d45ec57a3f81c07e6ae16b21c0ff7a81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea856a85957a957ac17e954ac17e1ca2954ac07e3e81c07f3e807a85c1ff3f81.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/8aff878b7f00953062179561f087953ad167997a80784a7fc1e5d86d9978485f.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/8aff878b7f80953860179561f087953ad167997a80784a7fc1e5d86d9978485b.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8aff878b7f00953062179561f087953ad167997a80784a7fc1e5d86d9978485f.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/8aff878b7f80953860179561f087953ad167997a80784a7fc1e5d86d9978485b.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eafdc6c9f720953030968d6795d28d6a95674b7b81304aedc9e51cad8d186c9a.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.3": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/82ff8db67f94952e76159d6bb01dcd629059c962c1fbd9c1c062da74d820ca74.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/82be8db67f95952e761d9d6bb01dcd628059c962c1fbd9e1c072da64d060ca74.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/82fe8db67f95952e76159d6bb01dcd629059c962c1fbd9e1c072da64d020ca74.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82ff8db67f94952e76159d6bb01dcd629059c962c1fbd9c1c062da74d820ca74.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82be8db67f95952e761d9d6bb01dcd628059c962c1fbd9e1c072da64d060ca74.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82fe8db67f95952e76159d6bb01dcd629059c962c1fbd9e1c072da64d020ca74.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a2ff6a967f00952eb40d9d0f900fcd62c47069f3d1f93a909c266e34d8a56f68.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.4": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/aa97b70ff5f0970f20b2956a6a17957af805da71d06f5a75d02cd870d800d8f2.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e1faa549de9497090697971d60539f3ef171c87ac075487ad025d87ed801da3e.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/aa97b70ff5f0970f20b2956a6a17957af805da71d06f5a75d02cd870d800d8f2.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e1faa549de9497090697971d60539f3ef171c87ac075487ad025d87ed801da3e.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eadab54fd7a1856d90819d6df8169962e946d862802ed8809ded7e809d2d03ff.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_tx.5": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e8faad47f784bd0596859d03969f9962c05dc96ee07189fe6870c862687178f8.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a8fa2d4797859585b6959d07605f896ee051697ad061d9fad0619aaed801deae.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e8faad47f784bd0596859d03969f9962c05dc96ee07189fe6870c862687178f8.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a8fa2d4797859585b6959d07605f896ee051697ad061d9fad0619aaed801deae.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/aa5b3c0c978187a4b60199bc605f6976687e6873d07c99e390acdc0391fc2f7b.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_x.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a6ffb5097e84cde2224598d1649f8d6cd2388c76d0799867d009da76c9f8d866.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a6bfb5097f84cde2224599d1649f8d6cd2388c76d0799867d009da76c1f8d866.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a6ffb5097e84cde2224598d1649f8d6cd2388c76d0799867d009da76c9f8d866.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a6bfb5097f84cde2224599d1649f8d6cd2388c76d0799867d009da76c1f8d866.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a6fbb50cfbd0c036203598dce4c88d26d32f8cf3886e1df3dc047b4289ec6e72.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_y.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a7ff978b7f00c9c830d7992166179e969509d866c478d964d079c876d869da26.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a7ff97837f00c9c830d79921661f9e9695099876c478d964c079c876d879da26.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a7ff978b7f00c9c830d7992166179e969509d866c478d964d079c876d869da26.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a7ff97837f00c9c830d79921661f9e9695099876c478d964c079c876d879da26.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a2ffb6127f0dc9993085d960c6748d3e9b121ca49d6a1b048df34ce789ff7205.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_yx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea856a9ff16eb740954a9e05855a19a3c0fbc13e1ea5c07d5ad0cb58e45e3c35.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea856a9ff16eb740954a9e05855a19a3c0fbc13e1ea5c07d5ad0cb58e45e3c35.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/ea856a95957a957ac07e954ac17e3e87950bc07f3ea4c27d3e833ac1c1e03f80.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_yx.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e5a565b69e1a9a42917e1a19c17b3a619e59c47b3a25c53e3b8430e5c57a3e85.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e5a565b69e1a9a42917e1a19c17b3a619e59c47b3a25c53e3b8430e5c57a3e85.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e5a761a79a589e58c07d1e48c07c3f819e41c07f3d84c17e3fa62585c0fe3f83.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_yx.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/afffe6d67700958636179d92e019992dd039daf5817d987a807a48e499684a6d.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/aeffe6d67780958636179d92e019892dd139daf5815d987a807a48e699684a6d.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/afffe6d67700958636179d92e019992dd039daf5817d987a807a48e499684a6d.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/aeffe6d67780958636179d92e019892dd139daf5815d987a807a48e699684a6d.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/eaff6ad4f74ab16490109c9b942999add1b74bb785a41d4acd526a254acc6365.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_yx.3": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea5e618434ac36e5c1c9369b95b39c38c3a39a4fcee19a6e9b64cb609925cd25.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea5e618434ac36e5c1c9369b95b39c38c3a39a4fcee19a6e9b64cb609925cd25.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e85a636c86a597a593c9b49b94b79969c396c95bccc69a64db30d9b039a52c26.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_yx.4": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2fd2d09295c2d1c3d33c1bc2d67d2c696ce0653c3ac2b1d976da05c2c4.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2fd2d09295c2d1c3d33c1bc2d27d2c696ce0e53c3ad2b1d976da01c2c4.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e85e3e2f97a1c19996a1c8f26d1e3a0f684a3c2c6913dc2497b9db8095e502ff.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2fd2d09295c2d1c3d33c1bc2d67d2c696ce0653c3ac2b1d976da05c2c4.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ad2f6d2fd2d09295c2d1c3d33c1bc2d27d2c696ce0e53c3ad2b1d976da01c2c4.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e85e3e2f97a1c19996a1c8f26d1e3a0f684a3c2c6913dc2497b9db8095e502ff.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e85e3c1f97a1c3e197a1c9f37c5e390668521e0c390bdd8685b1d86096e5279f.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_yx.5": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e968658e969692c797879e3b86929e58696d49cd6869c9a37962c923990d9c6d.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e9e1658e961e92569e9e3c7966d36c586165698c70e1ce739b3698619e1e984c.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e968658e969692c797879e3b86929e58696d49cd6869c9a37962c923990d9c6d.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e9e1658e961e92569e9e3c7966d36c586165698c70e1ce739b3698619e1e984c.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e1a530e29e5ecf199a5acd8f64f1326161a538e665a198d29e52cb1d9a5e6669.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_zx.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/bf813f80c156c05dc0fec29dc17f1a6dd05fc0ff1aa1c57e3b243b20375a1e81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/bf813f80c156c05dc0fec29dc17f1a6dd05fc0ff1aa1c57e3b243b20375a1e81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/be816a81d17ec57ac07e952ac07f3aa0955ec17e3f80c07f3f803f80c0bf3f81.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_zx.1": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ea95629d956a996069939e9bc07f7aad856cc47e5e81857a1e254a35c1be1b81.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ea95629d956a996069939e9bc07f7aad856cc47e5e81857a1e254a35c1be1b81.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/fa816a85957a957ac03f957ac07f3ba1954ac07e3e81c07f3ea47a85c07e3e80.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_zx.2": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/87ed2f867f008d8220179852f01fd9bed1789a6c847cc877c46ac972987ec8fd.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/87ed2f067f008d8220179852f01fd9bed1789a6c847cc877c468c9f6987ec8fd.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/87ed2f067f008d8220179c52f01fd9bed1789a6c847cc877c560c976987ec8fd.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/87ed2f867f008d8220179852f01fd9bed1789a6c847cc877c46ac972987ec8fd.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/87ed2f067f008d8220179852f01fd9bed1789a6c847cc877c468c9f6987ec8fd.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/87ed2f067f008d8220179c52f01fd9bed1789a6c847cc877c560c976987ec8fd.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/a3eded05fe11a492b000985af07fdbb4d1e3366d8c644da79fa68993180f6ec1.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_zx.3": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/a2f9b5ba7600a56962df9e96f01dc926c498cc46847f9d6cd0244bf19a6b19f1.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/a2f9b5ba7600856962df9e96f01dcd26c498cc46847f9d6cd0244bf19a6b1975.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a2f9b5ba7600a56962df9e96f01dc926c498cc46847f9d6cd0244bf19a6b19f1.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/a2f9b5ba7600856962df9e96f01dcd26c498cc46847f9d6cd0244bf19a6b1975.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/aef9f93a770085e9205fd696d13c4b2485ca1a43952f1934daa66bd1ca6b3c71.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_zx.4": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/ae953f87d5e82d86801f91ee6e1591fe7e117876c07d6877d068d878d800d07a.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/ae953f87d5e82d87801b91ee6e1599fe7e117874c07d6877d068d878d800d07a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ae953f87d5e82d86801f91ee6e1591fe7e117876c07d6877d068d878d800d07a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/ae953f87d5e82d87801b91ee6e1599fe7e117874c07d6877d068d878d800d07a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/bec1329dc5be85dac01d58d73e419d423e41daa59822dc00c5fefe0091fe03ff.png"
- ],
+ ],
"iris.tests.test_quickplot.TestQuickplotCoordinatesGiven.test_zx.5": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/e87a952d96856943969f694696858d4ee0519d6ee07f9b6a78619b2a79711a2a.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/e87a952d96856943969f694696858d4ae0519d6ee07f996a78719b2a79711a3a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e87a952d96856943969f694696858d4ee0519d6ee07f9b6a78619b2a79711a2a.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/e87a952d96856943969f694696858d4ae0519d6ee07f996a78719b2a79711a3a.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/e85e96ac97a168d897a5791695a19927913c3953687ecce3687c86e3487cc6c3.png"
- ],
+ ],
"iris.tests.test_quickplot.TestTimeReferenceUnitsLabels.test_not_reference_time_units.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/82faa1977fdf89976200ddf6e000d9e7f75f9866d560dae4dc00d966dc005e20.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/82b8a1977fdf89876200dde6e000d9e7f77f9866d560dfe4dc00d966fc005e20.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/82f8a1977fdf89876200ddf6e000d9e7f77f9866d560dee4dc00d966dc005e20.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/82f8a1977fdf89876200dde6e000d9e7f77f9866d560dfe4dc00dd64dc005e20.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82faa1977fdf89976200ddf6e000d9e7f75f9866d560dae4dc00d966dc005e20.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82b8a1977fdf89876200dde6e000d9e7f77f9866d560dfe4dc00d966fc005e20.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82f8a1977fdf89876200ddf6e000d9e7f77f9866d560dee4dc00d966dc005e20.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82f8a1977fdf89876200dde6e000d9e7f77f9866d560dfe4dc00dd64dc005e20.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/82faa19e7f51898c6001dd86845fd9a2dd7f996281ee19f389ef03ffdc007e00.png"
- ],
+ ],
"iris.tests.test_quickplot.TestTimeReferenceUnitsLabels.test_reference_time_units.0": [
- "https://scitools.github.io/test-iris-imagehash/images/v4/82fe81987fd777ffe0002addd4002805dda8de65dde9d4625bfddc209841de20.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/82fe81987fdf77ffe0002a9dd4002805ddaade65d9a9d5625bfddc209841de20.png",
- "https://scitools.github.io/test-iris-imagehash/images/v4/82fe81987fdf77ffe0002addd4002805dd28df67d9a9d4625bfddc209841de20.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82fe81987fd777ffe0002addd4002805dda8de65dde9d4625bfddc209841de20.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82fe81987fdf77ffe0002a9dd4002805ddaade65d9a9d5625bfddc209841de20.png",
+ "https://scitools.github.io/test-iris-imagehash/images/v4/82fe81987fdf77ffe0002addd4002805dd28df67d9a9d4625bfddc209841de20.png",
"https://scitools.github.io/test-iris-imagehash/images/v4/82fa80997f547799a0037a00d52f0956ddaf9f7e98a1816e09f5d8260bfffe00.png"
]
}
\ No newline at end of file
From 5923aaa8e725831a1575678fd93c938bfad36e95 Mon Sep 17 00:00:00 2001
From: lbdreyer
Date: Wed, 5 Sep 2018 11:39:06 +0100
Subject: [PATCH 31/62] Fix contig_ tolerance kwarg bug (#3162)
---
lib/iris/plot.py | 9 +++++----
lib/iris/tests/unit/coords/test_Coord.py | 10 ++++++++++
.../test__check_bounds_contiguity_and_mask.py | 15 +++++++++++++++
3 files changed, 30 insertions(+), 4 deletions(-)
diff --git a/lib/iris/plot.py b/lib/iris/plot.py
index f0dfccd8c5..e3193e96a4 100644
--- a/lib/iris/plot.py
+++ b/lib/iris/plot.py
@@ -317,13 +317,14 @@ def _check_bounds_contiguity_and_mask(coord, data, atol=None):
elif coord.ndim == 2:
if atol:
- args = {'atol': atol}
+ kwargs = {'atol': atol}
else:
- args = {}
- contiguous, diffs = coord._discontiguity_in_bounds(*args)
- diffs_along_x, diffs_along_y = diffs
+ kwargs = {}
+ contiguous, diffs = coord._discontiguity_in_bounds(**kwargs)
if not contiguous and data_is_masked:
+ diffs_along_x, diffs_along_y = diffs
+
# Check along both dimensions.
not_masked_at_discontiguity_along_x = np.any(
np.logical_and(mask_invert[:, :-1], diffs_along_x))
diff --git a/lib/iris/tests/unit/coords/test_Coord.py b/lib/iris/tests/unit/coords/test_Coord.py
index 58fc3e1f9e..8cf79caad3 100644
--- a/lib/iris/tests/unit/coords/test_Coord.py
+++ b/lib/iris/tests/unit/coords/test_Coord.py
@@ -504,6 +504,16 @@ def test_2d_discontiguous_along_x_and_y(self):
self.assertArrayEqual(diffs_along_x, exp_x_diffs)
self.assertArrayEqual(diffs_along_y, exp_y_diffs)
+ def test_2d_contiguous_along_x_atol(self):
+ coord = AuxCoord(self.points_3by3[:, ::2],
+ bounds=self.lon_bounds_3by3[:, ::2, :])
+ # Set a high atol that allows small discontiguities.
+ contiguous, diffs = coord._discontiguity_in_bounds(atol=2)
+ diffs_along_x, diffs_along_y = diffs
+ self.assertTrue(contiguous)
+ self.assertArrayEqual(diffs_along_x, np.array([2, 2, 2]).reshape(3, 1))
+ self.assertTrue(not diffs_along_y.any())
+
def test_2d_one_cell(self):
# Test a 2D coord with a single cell, where the coord has shape (1, 1).
coord = AuxCoord(self.points_3by3[:1, :1],
diff --git a/lib/iris/tests/unit/plot/test__check_bounds_contiguity_and_mask.py b/lib/iris/tests/unit/plot/test__check_bounds_contiguity_and_mask.py
index b067b3f387..225aa2890e 100644
--- a/lib/iris/tests/unit/plot/test__check_bounds_contiguity_and_mask.py
+++ b/lib/iris/tests/unit/plot/test__check_bounds_contiguity_and_mask.py
@@ -24,6 +24,8 @@
# importing anything else.
import iris.tests as tests
+import mock
+
import numpy as np
import numpy.ma as ma
@@ -72,6 +74,19 @@ def test_2d_contiguous(self):
iplt._check_bounds_contiguity_and_mask(cube.coord('longitude'),
cube.data)
+ def test_2d_contiguous_atol(self):
+ # Check the atol is passed correctly.
+ cube = sample_2d_latlons()
+ with mock.patch('iris.coords.Coord._discontiguity_in_bounds'
+ ) as discontiguity_check:
+ # Discontiguity returns two objects that are unpacked in
+ # `_check_bounds_contiguity_and_mask`.
+ discontiguity_check.return_value = [True, None]
+ iplt._check_bounds_contiguity_and_mask(cube.coord('longitude'),
+ cube.data,
+ atol=1e-3)
+ discontiguity_check.assert_called_with(atol=1e-3)
+
def test_2d_discontigous_masked(self):
# Test a 2D coordinate which is discontiguous but masked at
# discontiguities.
From 5bd0d15b1e00ca27e062cb12c251e7ffc1e91fa7 Mon Sep 17 00:00:00 2001
From: Peter Killick
Date: Mon, 10 Sep 2018 15:58:08 +0100
Subject: [PATCH 32/62] Add simple lazy aggregations
---
lib/iris/analysis/__init__.py | 38 ++++++++++++++++++-----------------
1 file changed, 20 insertions(+), 18 deletions(-)
diff --git a/lib/iris/analysis/__init__.py b/lib/iris/analysis/__init__.py
index 8cf1a5d2a7..546ba50fba 100644
--- a/lib/iris/analysis/__init__.py
+++ b/lib/iris/analysis/__init__.py
@@ -1419,23 +1419,6 @@ def interp_order(length):
"""
-MAX = Aggregator('maximum', ma.max)
-"""
-An :class:`~iris.analysis.Aggregator` instance that calculates
-the maximum over a :class:`~iris.cube.Cube`, as computed by
-:func:`numpy.ma.max`.
-
-**For example**:
-
-To compute zonal maximums over the *longitude* axis of a cube::
-
- result = cube.collapsed('longitude', iris.analysis.MAX)
-
-This aggregator handles masked data.
-
-"""
-
-
def _build_dask_mdtol_function(dask_stats_function):
"""
Make a wrapped dask statistic function that supports the 'mdtol' keyword.
@@ -1534,7 +1517,8 @@ def inner_stat(array, axis=-1, mdtol=None, **kwargs):
"""
-MIN = Aggregator('minimum', ma.min)
+MIN = Aggregator('minimum', ma.min,
+ lazy_func=_build_dask_mdtol_function(da.min))
"""
An :class:`~iris.analysis.Aggregator` instance that calculates
the minimum over a :class:`~iris.cube.Cube`, as computed by
@@ -1551,6 +1535,24 @@ def inner_stat(array, axis=-1, mdtol=None, **kwargs):
"""
+MAX = Aggregator('maximum', ma.max,
+ lazy_func=_build_dask_mdtol_function(da.max))
+"""
+An :class:`~iris.analysis.Aggregator` instance that calculates
+the maximum over a :class:`~iris.cube.Cube`, as computed by
+:func:`numpy.ma.max`.
+
+**For example**:
+
+To compute zonal maximums over the *longitude* axis of a cube::
+
+ result = cube.collapsed('longitude', iris.analysis.MAX)
+
+This aggregator handles masked data.
+
+"""
+
+
PEAK = Aggregator('peak', _peak)
"""
An :class:`~iris.analysis.Aggregator` instance that calculates
From 6186081884ecba4f8d5f18affaff6bccff7bd5e4 Mon Sep 17 00:00:00 2001
From: Peter Killick
Date: Wed, 12 Sep 2018 10:58:55 +0100
Subject: [PATCH 33/62] Lazy SUM and COUNT, tests improved
---
lib/iris/analysis/__init__.py | 40 +++++-
lib/iris/tests/unit/analysis/test_COUNT.py | 80 ++++++++++-
lib/iris/tests/unit/analysis/test_SUM.py | 149 +++++++++++++++++++++
3 files changed, 259 insertions(+), 10 deletions(-)
create mode 100644 lib/iris/tests/unit/analysis/test_SUM.py
diff --git a/lib/iris/analysis/__init__.py b/lib/iris/analysis/__init__.py
index 546ba50fba..776f40054f 100644
--- a/lib/iris/analysis/__init__.py
+++ b/lib/iris/analysis/__init__.py
@@ -1193,11 +1193,22 @@ def _weighted_percentile(data, axis, weights, percent, returned=False,
def _count(array, function, axis, **kwargs):
if not callable(function):
- raise ValueError('function must be a callable. Got %s.'
- % type(function))
+ emsg = 'function must be a callable. Got {}.'
+ raise TypeError(emsg.format(type(function)))
return ma.sum(function(array), axis=axis, **kwargs)
+def _lazy_count(array, axis, **kwargs):
+ try:
+ func = kwargs.pop('function')
+ except KeyError:
+ raise KeyError('no selection function supplied.')
+ if not callable(func):
+ emsg = 'function must be a callable. Got {}.'
+ raise TypeError(emsg.format(type(func)))
+ return da.sum(func(array), axis=axis, **kwargs)
+
+
def _proportion(array, function, axis, **kwargs):
# if the incoming array is masked use that to count the total number of
# values
@@ -1248,6 +1259,25 @@ def _sum(array, **kwargs):
return rvalue
+def _lazy_sum(array, axis, **kwargs):
+ # weighted or scaled sum
+ weights_in = kwargs.pop('weights', None)
+ returned_in = kwargs.pop('returned', False)
+ if weights_in is not None:
+ wsum = da.sum(weights_in * array, axis=axis, **kwargs)
+ else:
+ wsum = da.sum(array, axis=axis, **kwargs)
+ if returned_in:
+ if weights_in is None:
+ weights = iris_lazy_data.as_lazy_data(np.ones_like(array))
+ else:
+ weights = weights_in
+ rvalue = (wsum, da.sum(weights, axis=axis))
+ else:
+ rvalue = wsum
+ return rvalue
+
+
def _peak(array, **kwargs):
def column_segments(column):
nan_indices = np.where(np.isnan(column))[0]
@@ -1353,7 +1383,8 @@ def interp_order(length):
# Common partial Aggregation class constructors.
#
COUNT = Aggregator('count', _count,
- units_func=lambda units: 1)
+ units_func=lambda units: 1,
+ lazy_func=_lazy_count)
"""
An :class:`~iris.analysis.Aggregator` instance that counts the number
of :class:`~iris.cube.Cube` data occurrences that satisfy a particular
@@ -1452,6 +1483,7 @@ def inner_stat(array, axis=-1, mdtol=None, **kwargs):
return result
return inner_stat
+
MEAN = WeightedAggregator('mean', ma.average,
lazy_func=_build_dask_mdtol_function(da.mean))
"""
@@ -1702,7 +1734,7 @@ def inner_stat(array, axis=-1, mdtol=None, **kwargs):
"""
-SUM = WeightedAggregator('sum', _sum)
+SUM = WeightedAggregator('sum', _sum, lazy_func=_lazy_sum)
"""
An :class:`~iris.analysis.Aggregator` instance that calculates
the sum over a :class:`~iris.cube.Cube`, as computed by :func:`numpy.ma.sum`.
diff --git a/lib/iris/tests/unit/analysis/test_COUNT.py b/lib/iris/tests/unit/analysis/test_COUNT.py
index 9248a17910..63603b6059 100644
--- a/lib/iris/tests/unit/analysis/test_COUNT.py
+++ b/lib/iris/tests/unit/analysis/test_COUNT.py
@@ -1,4 +1,4 @@
-# (C) British Crown Copyright 2013 - 2017, Met Office
+# (C) British Crown Copyright 2013 - 2018, Met Office
#
# This file is part of Iris.
#
@@ -23,11 +23,51 @@
# importing anything else.
import iris.tests as tests
+import numpy as np
import numpy.ma as ma
from iris.analysis import COUNT
-import iris.cube
+from iris.cube import Cube
from iris.coords import DimCoord
+from iris._lazy_data import as_lazy_data
+
+
+class Test_basics(tests.IrisTest):
+ def setUp(self):
+ data = np.array([1, 2, 3, 4, 5])
+ coord = DimCoord([6, 7, 8, 9, 10], long_name='foo')
+ self.cube = Cube(data)
+ self.cube.add_dim_coord(coord, 0)
+ self.lazy_cube = Cube(as_lazy_data(data))
+ self.lazy_cube.add_dim_coord(coord, 0)
+ self.func = lambda x: x >= 3
+
+ def test_name(self):
+ self.assertEqual(COUNT.name(), 'count')
+
+ def test_no_function(self):
+ with self.assertRaisesRegexp(KeyError, 'no selection function'):
+ self.lazy_cube.collapsed("foo", COUNT)
+
+ def test_not_callable(self):
+ with self.assertRaisesRegexp(TypeError, 'function must be a callable'):
+ self.cube.collapsed("foo", COUNT, function='wibble')
+
+ def test_lazy_not_callable(self):
+ with self.assertRaisesRegexp(TypeError, 'function must be a callable'):
+ self.lazy_cube.collapsed("foo", COUNT, function='wibble')
+
+ def test_collapse(self):
+ cube = self.cube.collapsed("foo", COUNT, function=self.func)
+ self.assertArrayEqual(cube.data, [3])
+
+ def test_lazy(self):
+ cube = self.lazy_cube.collapsed("foo", COUNT, function=self.func)
+ self.assertTrue(cube.has_lazy_data())
+
+ def test_lazy_collapse(self):
+ cube = self.lazy_cube.collapsed("foo", COUNT, function=self.func)
+ self.assertArrayEqual(cube.data, [3])
class Test_units_func(tests.IrisTest):
@@ -39,7 +79,7 @@ def test(self):
class Test_masked(tests.IrisTest):
def setUp(self):
- self.cube = iris.cube.Cube(ma.masked_equal([1, 2, 3, 4, 5], 3))
+ self.cube = Cube(ma.masked_equal([1, 2, 3, 4, 5], 3))
self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0)
self.func = lambda x: x >= 3
@@ -48,9 +88,37 @@ def test_ma(self):
self.assertArrayEqual(cube.data, [2])
-class Test_name(tests.IrisTest):
- def test(self):
- self.assertEqual(COUNT.name(), 'count')
+class Test_lazy(tests.IrisTest):
+ def setUp(self):
+ data = np.array([1, 2, 3, 4, 5])
+ self.cube = Cube(as_lazy_data(data))
+ self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0)
+ self.func = lambda x: x >= 3
+
+ def test_lazy_oper(self):
+ cube = self.cube.collapsed("foo", COUNT, function=self.func)
+ self.assertTrue(cube.has_lazy_data())
+
+ def test_collapse(self):
+ result = self.cube.collapsed("foo", COUNT, function=self.func)
+ self.cube.data
+ expected = self.cube.collapsed("foo", COUNT, function=self.func)
+ self.assertArrayEqual(result.data, expected.data)
+
+
+class Test_lazy_masked(tests.IrisTest):
+ def setUp(self):
+ lazy_data = as_lazy_data(ma.masked_equal([1, 2, 3, 4, 5], 3))
+ self.lazy_cube = Cube(lazy_data)
+ self.lazy_cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10],
+ long_name='foo'),
+ 0)
+ self.func = lambda x: x >= 3
+
+ def test_ma(self):
+ cube = self.lazy_cube.collapsed("foo", COUNT, function=self.func)
+ self.assertTrue(cube.has_lazy_data())
+ self.assertArrayEqual(cube.data, [2])
class Test_aggregate_shape(tests.IrisTest):
diff --git a/lib/iris/tests/unit/analysis/test_SUM.py b/lib/iris/tests/unit/analysis/test_SUM.py
new file mode 100644
index 0000000000..1cf94723af
--- /dev/null
+++ b/lib/iris/tests/unit/analysis/test_SUM.py
@@ -0,0 +1,149 @@
+# (C) British Crown Copyright 2018, Met Office
+#
+# This file is part of Iris.
+#
+# Iris is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Iris is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Iris. If not, see .
+"""Unit tests for the :data:`iris.analysis.SUM` aggregator."""
+
+from __future__ import (absolute_import, division, print_function)
+from six.moves import (filter, input, map, range, zip) # noqa
+
+# Import iris.tests first so that some things can be initialised before
+# importing anything else.
+import iris.tests as tests
+
+import numpy as np
+import numpy.ma as ma
+
+from iris.analysis import SUM
+from iris.cube import Cube
+from iris.coords import DimCoord
+from iris._lazy_data import as_lazy_data
+
+
+class Test_basics(tests.IrisTest):
+ def setUp(self):
+ data = np.array([1, 2, 3, 4, 5])
+ coord = DimCoord([6, 7, 8, 9, 10], long_name='foo')
+ self.cube = Cube(data)
+ self.cube.add_dim_coord(coord, 0)
+ self.lazy_cube = Cube(as_lazy_data(data))
+ self.lazy_cube.add_dim_coord(coord, 0)
+
+ def test_name(self):
+ self.assertEqual(SUM.name(), 'sum')
+
+ def test_collapse(self):
+ cube = self.cube.collapsed("foo", SUM)
+ self.assertArrayEqual(cube.data, [15])
+
+ def test_lazy(self):
+ cube = self.lazy_cube.collapsed("foo", SUM)
+ self.assertTrue(cube.has_lazy_data())
+
+ def test_lazy_collapse(self):
+ cube = self.lazy_cube.collapsed("foo", SUM)
+ self.assertArrayEqual(cube.data, [15])
+
+
+class Test_masked(tests.IrisTest):
+ def setUp(self):
+ self.cube = Cube(ma.masked_equal([1, 2, 3, 4, 5], 3))
+ self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0)
+
+ def test_ma(self):
+ cube = self.cube.collapsed("foo", SUM)
+ self.assertArrayEqual(cube.data, [12])
+
+
+class Test_lazy_masked(tests.IrisTest):
+ def setUp(self):
+ masked_data = ma.masked_equal([1, 2, 3, 4, 5], 3)
+ self.cube = Cube(as_lazy_data(masked_data))
+ self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0)
+
+ def test_lazy_ma(self):
+ cube = self.cube.collapsed("foo", SUM)
+ self.assertTrue(cube.has_lazy_data())
+ self.assertArrayEqual(cube.data, [12])
+
+
+class Test_weights_and_returned(tests.IrisTest):
+ def setUp(self):
+ data_2d = np.arange(1, 11).reshape(2, 5)
+ coord_0 = DimCoord([11, 12], long_name='bar')
+ coord_1 = DimCoord([6, 7, 8, 9, 10], long_name='foo')
+ self.cube_2d = Cube(data_2d)
+ self.cube_2d.add_dim_coord(coord_0, 0)
+ self.cube_2d.add_dim_coord(coord_1, 1)
+ self.weights = np.array([2, 1, 1, 1, 1] * 2).reshape(2, 5)
+
+ def test_weights(self):
+ cube = self.cube_2d.collapsed('bar', SUM, weights=self.weights)
+ self.assertArrayEqual(cube.data, [14, 9, 11, 13, 15])
+
+ def test_returned(self):
+ cube, weights = self.cube_2d.collapsed('bar', SUM, returned=True)
+ self.assertArrayEqual(cube.data, [7, 9, 11, 13, 15])
+ self.assertArrayEqual(weights, [2, 2, 2, 2, 2])
+
+ def test_weights_and_returned(self):
+ cube, weights = self.cube_2d.collapsed('bar', SUM,
+ weights=self.weights,
+ returned=True)
+ self.assertArrayEqual(cube.data, [14, 9, 11, 13, 15])
+ self.assertArrayEqual(weights, [4, 2, 2, 2, 2])
+
+
+class Test_lazy_weights_and_returned(tests.IrisTest):
+ def setUp(self):
+ data_2d = np.arange(1, 11).reshape(2, 5)
+ coord_0 = DimCoord([11, 12], long_name='bar')
+ coord_1 = DimCoord([6, 7, 8, 9, 10], long_name='foo')
+ self.cube_2d = Cube(as_lazy_data(data_2d))
+ self.cube_2d.add_dim_coord(coord_0, 0)
+ self.cube_2d.add_dim_coord(coord_1, 1)
+ self.weights = np.array([2, 1, 1, 1, 1] * 2).reshape(2, 5)
+
+ def test_weights(self):
+ cube = self.cube_2d.collapsed('bar', SUM, weights=self.weights)
+ self.assertTrue(cube.has_lazy_data())
+ self.assertArrayEqual(cube.data, [14, 9, 11, 13, 15])
+
+ def test_returned(self):
+ cube, weights = self.cube_2d.collapsed('bar', SUM, returned=True)
+ self.assertTrue(cube.has_lazy_data())
+ self.assertArrayEqual(cube.data, [7, 9, 11, 13, 15])
+ self.assertArrayEqual(weights, [2, 2, 2, 2, 2])
+
+ def test_weights_and_returned(self):
+ cube, weights = self.cube_2d.collapsed('bar', SUM,
+ weights=self.weights,
+ returned=True)
+ self.assertTrue(cube.has_lazy_data())
+ self.assertArrayEqual(cube.data, [14, 9, 11, 13, 15])
+ self.assertArrayEqual(weights, [4, 2, 2, 2, 2])
+
+
+class Test_aggregate_shape(tests.IrisTest):
+ def test(self):
+ shape = ()
+ kwargs = dict()
+ self.assertTupleEqual(SUM.aggregate_shape(**kwargs), shape)
+ kwargs = dict(wibble='wobble')
+ self.assertTupleEqual(SUM.aggregate_shape(**kwargs), shape)
+
+
+if __name__ == "__main__":
+ tests.main()
From 2663a5a9b7aeb932f307cffc8298c4ac744460d7 Mon Sep 17 00:00:00 2001
From: Peter Killick
Date: Wed, 12 Sep 2018 11:10:07 +0100
Subject: [PATCH 34/62] Add tests for MAX and MIN
---
lib/iris/tests/unit/analysis/test_MAX.py | 92 ++++++++++++++++++++++++
lib/iris/tests/unit/analysis/test_MIN.py | 92 ++++++++++++++++++++++++
2 files changed, 184 insertions(+)
create mode 100644 lib/iris/tests/unit/analysis/test_MAX.py
create mode 100644 lib/iris/tests/unit/analysis/test_MIN.py
diff --git a/lib/iris/tests/unit/analysis/test_MAX.py b/lib/iris/tests/unit/analysis/test_MAX.py
new file mode 100644
index 0000000000..38bc426932
--- /dev/null
+++ b/lib/iris/tests/unit/analysis/test_MAX.py
@@ -0,0 +1,92 @@
+# (C) British Crown Copyright 2018, Met Office
+#
+# This file is part of Iris.
+#
+# Iris is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Iris is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Iris. If not, see .
+"""Unit tests for the :data:`iris.analysis.MAX` aggregator."""
+
+from __future__ import (absolute_import, division, print_function)
+from six.moves import (filter, input, map, range, zip) # noqa
+
+# Import iris.tests first so that some things can be initialised before
+# importing anything else.
+import iris.tests as tests
+
+import numpy as np
+import numpy.ma as ma
+
+from iris.analysis import MAX
+from iris.cube import Cube
+from iris.coords import DimCoord
+from iris._lazy_data import as_lazy_data
+
+
+class Test_basics(tests.IrisTest):
+ def setUp(self):
+ data = np.array([1, 2, 3, 4, 5])
+ coord = DimCoord([6, 7, 8, 9, 10], long_name='foo')
+ self.cube = Cube(data)
+ self.cube.add_dim_coord(coord, 0)
+ self.lazy_cube = Cube(as_lazy_data(data))
+ self.lazy_cube.add_dim_coord(coord, 0)
+
+ def test_name(self):
+ self.assertEqual(MAX.name(), 'maximum')
+
+ def test_collapse(self):
+ cube = self.cube.collapsed("foo", MAX)
+ self.assertArrayEqual(cube.data, [5])
+
+ def test_lazy(self):
+ cube = self.lazy_cube.collapsed("foo", MAX)
+ self.assertTrue(cube.has_lazy_data())
+
+ def test_lazy_collapse(self):
+ cube = self.lazy_cube.collapsed("foo", MAX)
+ self.assertArrayEqual(cube.data, [5])
+
+
+class Test_masked(tests.IrisTest):
+ def setUp(self):
+ self.cube = Cube(ma.masked_greater([1, 2, 3, 4, 5], 3))
+ self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0)
+
+ def test_ma(self):
+ cube = self.cube.collapsed("foo", MAX)
+ self.assertArrayEqual(cube.data, [3])
+
+
+class Test_lazy_masked(tests.IrisTest):
+ def setUp(self):
+ masked_data = ma.masked_greater([1, 2, 3, 4, 5], 3)
+ self.cube = Cube(as_lazy_data(masked_data))
+ self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0)
+
+ def test_lazy_ma(self):
+ cube = self.cube.collapsed("foo", MAX)
+ self.assertTrue(cube.has_lazy_data())
+ self.assertArrayEqual(cube.data, [3])
+
+
+class Test_aggregate_shape(tests.IrisTest):
+ def test(self):
+ shape = ()
+ kwargs = dict()
+ self.assertTupleEqual(MAX.aggregate_shape(**kwargs), shape)
+ kwargs = dict(wibble='wobble')
+ self.assertTupleEqual(MAX.aggregate_shape(**kwargs), shape)
+
+
+if __name__ == "__main__":
+ tests.main()
diff --git a/lib/iris/tests/unit/analysis/test_MIN.py b/lib/iris/tests/unit/analysis/test_MIN.py
new file mode 100644
index 0000000000..82a1d68316
--- /dev/null
+++ b/lib/iris/tests/unit/analysis/test_MIN.py
@@ -0,0 +1,92 @@
+# (C) British Crown Copyright 2018, Met Office
+#
+# This file is part of Iris.
+#
+# Iris is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Iris is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Iris. If not, see .
+"""Unit tests for the :data:`iris.analysis.MIN` aggregator."""
+
+from __future__ import (absolute_import, division, print_function)
+from six.moves import (filter, input, map, range, zip) # noqa
+
+# Import iris.tests first so that some things can be initialised before
+# importing anything else.
+import iris.tests as tests
+
+import numpy as np
+import numpy.ma as ma
+
+from iris.analysis import MIN
+from iris.cube import Cube
+from iris.coords import DimCoord
+from iris._lazy_data import as_lazy_data
+
+
+class Test_basics(tests.IrisTest):
+ def setUp(self):
+ data = np.array([1, 2, 3, 4, 5])
+ coord = DimCoord([6, 7, 8, 9, 10], long_name='foo')
+ self.cube = Cube(data)
+ self.cube.add_dim_coord(coord, 0)
+ self.lazy_cube = Cube(as_lazy_data(data))
+ self.lazy_cube.add_dim_coord(coord, 0)
+
+ def test_name(self):
+ self.assertEqual(MIN.name(), 'minimum')
+
+ def test_collapse(self):
+ cube = self.cube.collapsed("foo", MIN)
+ self.assertArrayEqual(cube.data, [1])
+
+ def test_lazy(self):
+ cube = self.lazy_cube.collapsed("foo", MIN)
+ self.assertTrue(cube.has_lazy_data())
+
+ def test_lazy_collapse(self):
+ cube = self.lazy_cube.collapsed("foo", MIN)
+ self.assertArrayEqual(cube.data, [1])
+
+
+class Test_masked(tests.IrisTest):
+ def setUp(self):
+ self.cube = Cube(ma.masked_less([1, 2, 3, 4, 5], 3))
+ self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0)
+
+ def test_ma(self):
+ cube = self.cube.collapsed("foo", MIN)
+ self.assertArrayEqual(cube.data, [3])
+
+
+class Test_lazy_masked(tests.IrisTest):
+ def setUp(self):
+ masked_data = ma.masked_less([1, 2, 3, 4, 5], 3)
+ self.cube = Cube(as_lazy_data(masked_data))
+ self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0)
+
+ def test_lazy_ma(self):
+ cube = self.cube.collapsed("foo", MIN)
+ self.assertTrue(cube.has_lazy_data())
+ self.assertArrayEqual(cube.data, [3])
+
+
+class Test_aggregate_shape(tests.IrisTest):
+ def test(self):
+ shape = ()
+ kwargs = dict()
+ self.assertTupleEqual(MIN.aggregate_shape(**kwargs), shape)
+ kwargs = dict(wibble='wobble')
+ self.assertTupleEqual(MIN.aggregate_shape(**kwargs), shape)
+
+
+if __name__ == "__main__":
+ tests.main()
From b4bf847e068f73e492a4c6bbcc3394728090a443 Mon Sep 17 00:00:00 2001
From: Peter Killick
Date: Wed, 12 Sep 2018 11:40:22 +0100
Subject: [PATCH 35/62] Update tests for STD_DEV
---
lib/iris/tests/unit/analysis/test_STD_DEV.py | 34 ++++++++++++++++----
1 file changed, 28 insertions(+), 6 deletions(-)
diff --git a/lib/iris/tests/unit/analysis/test_STD_DEV.py b/lib/iris/tests/unit/analysis/test_STD_DEV.py
index e1aac6ae63..dedc7cf053 100644
--- a/lib/iris/tests/unit/analysis/test_STD_DEV.py
+++ b/lib/iris/tests/unit/analysis/test_STD_DEV.py
@@ -1,4 +1,4 @@
-# (C) British Crown Copyright 2014 - 2017, Met Office
+# (C) British Crown Copyright 2014 - 2018, Met Office
#
# This file is part of Iris.
#
@@ -27,6 +27,33 @@
from iris._lazy_data import as_concrete_data, as_lazy_data
from iris.analysis import STD_DEV
+from iris.cube import Cube
+from iris.coords import DimCoord
+
+
+class Test_basics(tests.IrisTest):
+ def setUp(self):
+ data = np.array([1, 2, 3, 4, 5])
+ coord = DimCoord([6, 7, 8, 9, 10], long_name='foo')
+ self.cube = Cube(data)
+ self.cube.add_dim_coord(coord, 0)
+ self.lazy_cube = Cube(as_lazy_data(data))
+ self.lazy_cube.add_dim_coord(coord, 0)
+
+ def test_name(self):
+ self.assertEqual(STD_DEV.name(), 'standard_deviation')
+
+ def test_collapse(self):
+ cube = self.cube.collapsed("foo", STD_DEV)
+ self.assertArrayAlmostEqual(cube.data, [1.58113883])
+
+ def test_lazy(self):
+ cube = self.lazy_cube.collapsed("foo", STD_DEV)
+ self.assertTrue(cube.has_lazy_data())
+
+ def test_lazy_collapse(self):
+ cube = self.lazy_cube.collapsed("foo", STD_DEV)
+ self.assertArrayAlmostEqual(cube.data, [1.58113883])
class Test_lazy_aggregate(tests.IrisTest):
@@ -56,11 +83,6 @@ def test_ddof_zero(self):
self.assertArrayAlmostEqual(result, np.array(2.291287))
-class Test_name(tests.IrisTest):
- def test(self):
- self.assertEqual(STD_DEV.name(), 'standard_deviation')
-
-
class Test_aggregate_shape(tests.IrisTest):
def test(self):
shape = ()
From 718f60412913adfbf3eb35411689269bd2d5be3d Mon Sep 17 00:00:00 2001
From: Peter Killick
Date: Thu, 13 Sep 2018 05:42:49 +0100
Subject: [PATCH 36/62] Use NetCDF variable's chunks on load (#3131)
Preserve NetCDF chunks on dataset load
---
.../newfeature_2018-Aug-14_load-nc-chunks.txt | 1 +
.../fileformats/_pyke_rules/fc_rules_cf.krb | 26 +-----
lib/iris/fileformats/netcdf.py | 15 +++-
.../netcdf/test__get_cf_var_data.py | 83 +++++++++++++++++++
.../fileformats/netcdf/test__load_cube.py | 14 +++-
.../test_build_auxiliary_coordinate.py | 27 ++++--
6 files changed, 131 insertions(+), 35 deletions(-)
create mode 100644 docs/iris/src/whatsnew/contributions_2.2.0/newfeature_2018-Aug-14_load-nc-chunks.txt
create mode 100644 lib/iris/tests/unit/fileformats/netcdf/test__get_cf_var_data.py
diff --git a/docs/iris/src/whatsnew/contributions_2.2.0/newfeature_2018-Aug-14_load-nc-chunks.txt b/docs/iris/src/whatsnew/contributions_2.2.0/newfeature_2018-Aug-14_load-nc-chunks.txt
new file mode 100644
index 0000000000..2a3780115d
--- /dev/null
+++ b/docs/iris/src/whatsnew/contributions_2.2.0/newfeature_2018-Aug-14_load-nc-chunks.txt
@@ -0,0 +1 @@
+* NetCDF data variable chunk sizes are utilised at load time for significant performance improvements.
\ No newline at end of file
diff --git a/lib/iris/fileformats/_pyke_rules/fc_rules_cf.krb b/lib/iris/fileformats/_pyke_rules/fc_rules_cf.krb
index 942450847b..f301f0fc9b 100644
--- a/lib/iris/fileformats/_pyke_rules/fc_rules_cf.krb
+++ b/lib/iris/fileformats/_pyke_rules/fc_rules_cf.krb
@@ -1070,7 +1070,7 @@ fc_extras
import iris.coord_systems
import iris.fileformats.cf as cf
import iris.fileformats.netcdf
- from iris.fileformats.netcdf import parse_cell_methods, UnknownCellMethodWarning
+ from iris.fileformats.netcdf import _get_cf_var_data, parse_cell_methods, UnknownCellMethodWarning
import iris.fileformats.pp as pp
import iris.exceptions
import iris.std_names
@@ -1712,25 +1712,16 @@ fc_extras
# Get units
attr_units = get_attr_units(cf_coord_var, attributes)
- def cf_var_as_array(cf_var):
- dtype = iris.fileformats.netcdf._get_actual_dtype(cf_var)
- fill_value = getattr(cf_var.cf_data, '_FillValue',
- netCDF4.default_fillvals[dtype.str[1:]])
- proxy = iris.fileformats.netcdf.NetCDFDataProxy(
- cf_var.shape, dtype, engine.filename,
- cf_var.cf_name, fill_value)
- return as_lazy_data(proxy)
-
# Get any coordinate point data.
if isinstance(cf_coord_var, cf.CFLabelVariable):
points_data = cf_coord_var.cf_label_data(cf_var)
else:
- points_data = cf_var_as_array(cf_coord_var)
+ points_data = _get_cf_var_data(cf_coord_var, engine.filename)
# Get any coordinate bounds.
cf_bounds_var = get_cf_bounds_var(cf_coord_var)
if cf_bounds_var is not None:
- bounds_data = cf_var_as_array(cf_bounds_var)
+ bounds_data = _get_cf_var_data(cf_bounds_var, engine.filename)
# Handle transposed bounds where the vertex dimension is not
# the last one. Test based on shape to support different
@@ -1783,16 +1774,7 @@ fc_extras
# Get units
attr_units = get_attr_units(cf_cm_attr, attributes)
- def cf_var_as_array(cf_var):
- dtype = cf_var.dtype
- fill_value = getattr(cf_var.cf_data, '_FillValue',
- netCDF4.default_fillvals[dtype.str[1:]])
- proxy = iris.fileformats.netcdf.NetCDFDataProxy(
- cf_var.shape, dtype, engine.filename,
- cf_var.cf_name, fill_value)
- return as_lazy_data(proxy)
-
- data = cf_var_as_array(cf_cm_attr)
+ data = _get_cf_var_data(cf_cm_attr, engine.filename)
# Determine the name of the dimension/s shared between the CF-netCDF data variable
# and the coordinate being built.
diff --git a/lib/iris/fileformats/netcdf.py b/lib/iris/fileformats/netcdf.py
index 6ac9c26811..8c965ef1a5 100644
--- a/lib/iris/fileformats/netcdf.py
+++ b/lib/iris/fileformats/netcdf.py
@@ -501,8 +501,8 @@ def _get_actual_dtype(cf_var):
return dummy_data.dtype
-def _load_cube(engine, cf, cf_var, filename):
- """Create the cube associated with the CF-netCDF data variable."""
+def _get_cf_var_data(cf_var, filename):
+ # Get lazy chunked data out of a cf variable.
dtype = _get_actual_dtype(cf_var)
# Create cube with deferred data, but no metadata
@@ -510,7 +510,16 @@ def _load_cube(engine, cf, cf_var, filename):
netCDF4.default_fillvals[cf_var.dtype.str[1:]])
proxy = NetCDFDataProxy(cf_var.shape, dtype, filename, cf_var.cf_name,
fill_value)
- data = as_lazy_data(proxy)
+ chunks = cf_var.cf_data.chunking()
+ # Chunks can be an iterable, None, or `'contiguous'`.
+ if chunks == 'contiguous':
+ chunks = None
+ return as_lazy_data(proxy, chunks=chunks)
+
+
+def _load_cube(engine, cf, cf_var, filename):
+ """Create the cube associated with the CF-netCDF data variable."""
+ data = _get_cf_var_data(cf_var, filename)
cube = iris.cube.Cube(data)
# Reset the pyke inference engine.
diff --git a/lib/iris/tests/unit/fileformats/netcdf/test__get_cf_var_data.py b/lib/iris/tests/unit/fileformats/netcdf/test__get_cf_var_data.py
new file mode 100644
index 0000000000..6a1aeb9d61
--- /dev/null
+++ b/lib/iris/tests/unit/fileformats/netcdf/test__get_cf_var_data.py
@@ -0,0 +1,83 @@
+# (C) British Crown Copyright 2018, Met Office
+#
+# This file is part of Iris.
+#
+# Iris is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Iris is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Iris. If not, see .
+"""Unit tests for the `iris.fileformats.netcdf._get_cf_var_data` function."""
+
+from __future__ import (absolute_import, division, print_function)
+from six.moves import (filter, input, map, range, zip) # noqa
+
+# Import iris.tests first so that some things can be initialised before
+# importing anything else.
+import iris.tests as tests
+
+from dask.array import Array as dask_array
+import numpy as np
+
+from iris._lazy_data import _limited_shape
+import iris.fileformats.cf
+from iris.fileformats.netcdf import _get_cf_var_data
+from iris.tests import mock
+
+
+class Test__get_cf_var_data(tests.IrisTest):
+ def setUp(self):
+ self.filename = 'DUMMY'
+ self.shape = (3, 240, 200)
+ self.expected_chunks = _limited_shape(self.shape)
+
+ def _make(self, chunksizes):
+ cf_data = mock.Mock(_FillValue=None)
+ cf_data.chunking = mock.MagicMock(return_value=chunksizes)
+ cf_var = mock.MagicMock(spec=iris.fileformats.cf.CFVariable,
+ dtype=np.dtype('i4'),
+ cf_data=cf_data,
+ cf_name='DUMMY_VAR',
+ shape=self.shape)
+ return cf_var
+
+ def test_cf_data_type(self):
+ chunks = [1, 12, 100]
+ cf_var = self._make(chunks)
+ lazy_data = _get_cf_var_data(cf_var, self.filename)
+ self.assertIsInstance(lazy_data, dask_array)
+
+ def test_cf_data_chunks(self):
+ chunks = [1, 12, 100]
+ cf_var = self._make(chunks)
+ lazy_data = _get_cf_var_data(cf_var, self.filename)
+ lazy_data_chunks = [c[0] for c in lazy_data.chunks]
+ self.assertArrayEqual(chunks, lazy_data_chunks)
+
+ def test_cf_data_no_chunks(self):
+ # No chunks means chunks are calculated from the array's shape by
+ # `iris._lazy_data._limited_shape()`.
+ chunks = None
+ cf_var = self._make(chunks)
+ lazy_data = _get_cf_var_data(cf_var, self.filename)
+ lazy_data_chunks = [c[0] for c in lazy_data.chunks]
+ self.assertArrayEqual(lazy_data_chunks, self.expected_chunks)
+
+ def test_cf_data_contiguous(self):
+ # Chunks 'contiguous' is equivalent to no chunks.
+ chunks = 'contiguous'
+ cf_var = self._make(chunks)
+ lazy_data = _get_cf_var_data(cf_var, self.filename)
+ lazy_data_chunks = [c[0] for c in lazy_data.chunks]
+ self.assertArrayEqual(lazy_data_chunks, self.expected_chunks)
+
+
+if __name__ == "__main__":
+ tests.main()
diff --git a/lib/iris/tests/unit/fileformats/netcdf/test__load_cube.py b/lib/iris/tests/unit/fileformats/netcdf/test__load_cube.py
index 1e38baac86..41b6ca5ff0 100644
--- a/lib/iris/tests/unit/fileformats/netcdf/test__load_cube.py
+++ b/lib/iris/tests/unit/fileformats/netcdf/test__load_cube.py
@@ -57,6 +57,7 @@ def setUp(self):
def _make(self, names, attrs):
coords = [DimCoord(i, long_name=name) for i, name in enumerate(names)]
+ shape = (1,)
cf_group = {}
for name, cf_attrs in zip(names, attrs):
@@ -64,12 +65,14 @@ def _make(self, names, attrs):
cf_group[name] = mock.Mock(cf_attrs_unused=cf_attrs_unused)
cf = mock.Mock(cf_group=cf_group)
+ cf_data = mock.Mock(_FillValue=None)
+ cf_data.chunking = mock.MagicMock(return_value=shape)
cf_var = mock.MagicMock(spec=iris.fileformats.cf.CFVariable,
dtype=np.dtype('i4'),
- cf_data=mock.Mock(_FillValue=None),
+ cf_data=cf_data,
cf_name='DUMMY_VAR',
cf_group=coords,
- shape=(1,))
+ shape=shape)
return cf, cf_var
def test_flag_pass_thru(self):
@@ -129,14 +132,17 @@ def setUp(self):
self.valid_max = mock.sentinel.valid_max
def _make(self, attrs):
+ shape = (1,)
cf_attrs_unused = mock.Mock(return_value=attrs)
+ cf_data = mock.Mock(_FillValue=None)
+ cf_data.chunking = mock.MagicMock(return_value=shape)
cf_var = mock.MagicMock(spec=iris.fileformats.cf.CFVariable,
dtype=np.dtype('i4'),
- cf_data=mock.Mock(_FillValue=None),
+ cf_data=cf_data,
cf_name='DUMMY_VAR',
cf_group=mock.Mock(),
cf_attrs_unused=cf_attrs_unused,
- shape=(1,))
+ shape=shape)
return cf_var
def test_flag_pass_thru(self):
diff --git a/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_auxiliary_coordinate.py b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_auxiliary_coordinate.py
index a796621cc0..4bb653f23f 100644
--- a/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_auxiliary_coordinate.py
+++ b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_auxiliary_coordinate.py
@@ -40,11 +40,13 @@ class TestBoundsVertexDim(tests.IrisTest):
def setUp(self):
# Create coordinate cf variables and pyke engine.
points = np.arange(6).reshape(2, 3)
+
+ cf_data = self._make_cf_data(points)
self.cf_coord_var = mock.Mock(
spec=CFVariable,
dimensions=('foo', 'bar'),
cf_name='wibble',
- cf_data=mock.Mock(),
+ cf_data=cf_data,
standard_name=None,
long_name='wibble',
units='m',
@@ -54,7 +56,8 @@ def setUp(self):
self.engine = mock.Mock(
cube=mock.Mock(),
- cf_var=mock.Mock(dimensions=('foo', 'bar')),
+ cf_var=mock.Mock(dimensions=('foo', 'bar'),
+ cf_data=cf_data),
filename='DUMMY',
provides=dict(coordinates=[]))
@@ -72,14 +75,21 @@ def patched__getitem__(proxy_self, keys):
'iris.fileformats.netcdf.NetCDFDataProxy.__getitem__',
new=patched__getitem__)
+ @staticmethod
+ def _make_cf_data(vals):
+ cf_data = mock.Mock(_FillValue=None)
+ cf_data.chunking = mock.MagicMock(return_value=vals.shape)
+ return cf_data
+
def test_slowest_varying_vertex_dim(self):
# Create the bounds cf variable.
bounds = np.arange(24).reshape(4, 2, 3)
+ cf_data = self._make_cf_data(bounds)
self.cf_bounds_var = mock.Mock(
spec=CFVariable,
dimensions=('nv', 'foo', 'bar'),
cf_name='wibble_bnds',
- cf_data=mock.Mock(),
+ cf_data=cf_data,
shape=bounds.shape,
dtype=bounds.dtype,
__getitem__=lambda self, key: bounds[key])
@@ -116,11 +126,12 @@ def test_slowest_varying_vertex_dim(self):
def test_fastest_varying_vertex_dim(self):
bounds = np.arange(24).reshape(2, 3, 4)
+ cf_data = self._make_cf_data(bounds)
self.cf_bounds_var = mock.Mock(
spec=CFVariable,
dimensions=('foo', 'bar', 'nv'),
cf_name='wibble_bnds',
- cf_data=mock.Mock(),
+ cf_data=cf_data,
shape=bounds.shape,
dtype=bounds.dtype,
__getitem__=lambda self, key: bounds[key])
@@ -155,11 +166,12 @@ def test_fastest_with_different_dim_names(self):
# which are 'foo' and 'bar' (as permitted by the cf spec),
# this should still work because the vertex dim is the fastest varying.
bounds = np.arange(24).reshape(2, 3, 4)
+ cf_data = self._make_cf_data(bounds)
self.cf_bounds_var = mock.Mock(
spec=CFVariable,
dimensions=('x', 'y', 'nv'),
cf_name='wibble_bnds',
- cf_data=mock.Mock(),
+ cf_data=cf_data,
shape=bounds.shape,
dtype=bounds.dtype,
__getitem__=lambda self, key: bounds[key])
@@ -194,11 +206,14 @@ class TestDtype(tests.IrisTest):
def setUp(self):
# Create coordinate cf variables and pyke engine.
points = np.arange(6).reshape(2, 3)
+ cf_data = mock.Mock(_FillValue=None)
+ cf_data.chunking = mock.MagicMock(return_value=points.shape)
+
self.cf_coord_var = mock.Mock(
spec=CFVariable,
dimensions=('foo', 'bar'),
cf_name='wibble',
- cf_data=mock.Mock(),
+ cf_data=cf_data,
standard_name=None,
long_name='wibble',
units='m',
From b1b4b598041ec390c75d0ccf5eea364180fd8641 Mon Sep 17 00:00:00 2001
From: Peter Killick
Date: Thu, 13 Sep 2018 15:14:47 +0100
Subject: [PATCH 37/62] Iteration and less duplication
---
lib/iris/_lazy_data.py | 15 ++++
lib/iris/analysis/__init__.py | 128 ++++++++++++++--------------------
2 files changed, 69 insertions(+), 74 deletions(-)
diff --git a/lib/iris/_lazy_data.py b/lib/iris/_lazy_data.py
index 0613ba57ec..f5312b7d3a 100644
--- a/lib/iris/_lazy_data.py
+++ b/lib/iris/_lazy_data.py
@@ -23,6 +23,8 @@
from __future__ import (absolute_import, division, print_function)
from six.moves import (filter, input, map, range, zip) # noqa
+from functools import wraps
+
import dask
import dask.array as da
import dask.context
@@ -31,6 +33,19 @@
import numpy.ma as ma
+def non_lazy(func):
+ """
+ Turn a lazy function into a function that returns a result immediately.
+
+ """
+ @wraps(func)
+ def inner(*args, **kwargs):
+ """Immediately return the results of a lazy function."""
+ result = func(*args, **kwargs)
+ return dask.compute(result)[0]
+ return inner
+
+
def is_lazy_data(data):
"""
Return whether the argument is an Iris 'lazy' data array.
diff --git a/lib/iris/analysis/__init__.py b/lib/iris/analysis/__init__.py
index 776f40054f..49d9bb8172 100644
--- a/lib/iris/analysis/__init__.py
+++ b/lib/iris/analysis/__init__.py
@@ -65,7 +65,7 @@
from iris.analysis._regrid import RectilinearRegridder
import iris.coords
from iris.exceptions import LazyAggregatorError
-import iris._lazy_data as iris_lazy_data
+import iris._lazy_data
__all__ = ('COUNT', 'GMEAN', 'HMEAN', 'MAX', 'MEAN', 'MEDIAN', 'MIN',
'PEAK', 'PERCENTILE', 'PROPORTION', 'RMS', 'STD_DEV', 'SUM',
@@ -468,7 +468,7 @@ def lazy_aggregate(self, data, axis, **kwargs):
# provided to __init__.
kwargs = dict(list(self._kwargs.items()) + list(kwargs.items()))
- return self.lazy_func(data, axis, **kwargs)
+ return self.lazy_func(data, axis=axis, **kwargs)
def aggregate(self, data, axis, **kwargs):
"""
@@ -1015,6 +1015,40 @@ def post_process(self, collapsed_cube, data_result, coords, **kwargs):
return result
+def _build_dask_mdtol_function(dask_stats_function):
+ """
+ Make a wrapped dask statistic function that supports the 'mdtol' keyword.
+
+ 'dask_function' must be a dask statistical function, compatible with the
+ call signature : "dask_stats_function(data, axis, **kwargs)".
+ It must be masked-data tolerant, i.e. it ignores masked input points and
+ performs a calculation on only the unmasked points.
+ For example, mean([1, --, 2]) = (1 + 2) / 2 = 1.5.
+
+ The returned value is a new function operating on dask arrays.
+ It has the call signature `stat(data, axis=-1, mdtol=None, **kwargs)`.
+
+ """
+ @wraps(dask_stats_function)
+ def inner_stat(array, axis=-1, mdtol=None, **kwargs):
+ # Call the statistic to get the basic result (missing-data tolerant).
+ dask_result = dask_stats_function(array, axis=axis, **kwargs)
+ if mdtol is None or mdtol >= 1.0:
+ result = dask_result
+ else:
+ # Build a lazy computation to compare the fraction of missing
+ # input points at each output point to the 'mdtol' threshold.
+ point_mask_counts = da.sum(da.ma.getmaskarray(array), axis=axis)
+ points_per_calc = array.size / dask_result.size
+ masked_point_fractions = point_mask_counts / points_per_calc
+ boolean_mask = masked_point_fractions > mdtol
+ # Return an mdtol-masked version of the basic result.
+ result = da.ma.masked_array(da.ma.getdata(dask_result),
+ boolean_mask)
+ return result
+ return inner_stat
+
+
def _percentile(data, axis, percent, fast_percentile_method=False,
**kwargs):
"""
@@ -1191,14 +1225,9 @@ def _weighted_percentile(data, axis, weights, percent, returned=False,
return result
-def _count(array, function, axis, **kwargs):
- if not callable(function):
- emsg = 'function must be a callable. Got {}.'
- raise TypeError(emsg.format(type(function)))
- return ma.sum(function(array), axis=axis, **kwargs)
-
-
-def _lazy_count(array, axis, **kwargs):
+@_build_dask_mdtol_function
+def _lazy_count(array, **kwargs):
+ array = iris._lazy_data.as_lazy_data(array)
try:
func = kwargs.pop('function')
except KeyError:
@@ -1206,16 +1235,17 @@ def _lazy_count(array, axis, **kwargs):
if not callable(func):
emsg = 'function must be a callable. Got {}.'
raise TypeError(emsg.format(type(func)))
- return da.sum(func(array), axis=axis, **kwargs)
+ return da.sum(func(array), **kwargs)
def _proportion(array, function, axis, **kwargs):
+ count = iris._lazy_data.non_lazy(_lazy_count)
# if the incoming array is masked use that to count the total number of
# values
if ma.isMaskedArray(array):
# calculate the total number of non-masked values across the given axis
- total_non_masked = _count(array.mask, np.logical_not,
- axis=axis, **kwargs)
+ total_non_masked = count(
+ array.mask, axis=axis, function=np.logical_not, **kwargs)
total_non_masked = ma.masked_equal(total_non_masked, 0)
else:
total_non_masked = array.shape[axis]
@@ -1226,7 +1256,7 @@ def _proportion(array, function, axis, **kwargs):
# a dtype for its data that is different to the dtype of the fill-value,
# which can cause issues outside this function.
# Reference - tests/unit/analyis/test_PROPORTION.py Test_masked.test_ma
- numerator = _count(array, function, axis=axis, **kwargs)
+ numerator = count(array, axis=axis, function=function, **kwargs)
result = ma.asarray(numerator / total_non_masked)
return result
@@ -1239,40 +1269,23 @@ def _rms(array, axis, **kwargs):
return rval
-def _sum(array, **kwargs):
+@_build_dask_mdtol_function
+def _lazy_sum(array, **kwargs):
+ array = iris._lazy_data.as_lazy_data(array)
# weighted or scaled sum
axis_in = kwargs.get('axis', None)
weights_in = kwargs.pop('weights', None)
returned_in = kwargs.pop('returned', False)
if weights_in is not None:
- wsum = ma.sum(weights_in * array, **kwargs)
+ wsum = da.sum(weights_in * array, **kwargs)
else:
- wsum = ma.sum(array, **kwargs)
+ wsum = da.sum(array, **kwargs)
if returned_in:
if weights_in is None:
- weights = np.ones_like(array)
+ weights = iris._lazy_data.as_lazy_data(np.ones_like(array))
else:
weights = weights_in
- rvalue = (wsum, ma.sum(weights, axis=axis_in))
- else:
- rvalue = wsum
- return rvalue
-
-
-def _lazy_sum(array, axis, **kwargs):
- # weighted or scaled sum
- weights_in = kwargs.pop('weights', None)
- returned_in = kwargs.pop('returned', False)
- if weights_in is not None:
- wsum = da.sum(weights_in * array, axis=axis, **kwargs)
- else:
- wsum = da.sum(array, axis=axis, **kwargs)
- if returned_in:
- if weights_in is None:
- weights = iris_lazy_data.as_lazy_data(np.ones_like(array))
- else:
- weights = weights_in
- rvalue = (wsum, da.sum(weights, axis=axis))
+ rvalue = (wsum, da.sum(weights, axis=axis_in))
else:
rvalue = wsum
return rvalue
@@ -1382,7 +1395,7 @@ def interp_order(length):
#
# Common partial Aggregation class constructors.
#
-COUNT = Aggregator('count', _count,
+COUNT = Aggregator('count', iris._lazy_data.non_lazy(_lazy_count),
units_func=lambda units: 1,
lazy_func=_lazy_count)
"""
@@ -1450,40 +1463,6 @@ def interp_order(length):
"""
-def _build_dask_mdtol_function(dask_stats_function):
- """
- Make a wrapped dask statistic function that supports the 'mdtol' keyword.
-
- 'dask_function' must be a dask statistical function, compatible with the
- call signature : "dask_stats_function(data, axis, **kwargs)".
- It must be masked-data tolerant, i.e. it ignores masked input points and
- performs a calculation on only the unmasked points.
- For example, mean([1, --, 2]) = (1 + 2) / 2 = 1.5.
-
- The returned value is a new function operating on dask arrays.
- It has the call signature `stat(data, axis=-1, mdtol=None, **kwargs)`.
-
- """
- @wraps(dask_stats_function)
- def inner_stat(array, axis=-1, mdtol=None, **kwargs):
- # Call the statistic to get the basic result (missing-data tolerant).
- dask_result = dask_stats_function(array, axis=axis, **kwargs)
- if mdtol is None or mdtol >= 1.0:
- result = dask_result
- else:
- # Build a lazy computation to compare the fraction of missing
- # input points at each output point to the 'mdtol' threshold.
- point_mask_counts = da.sum(da.ma.getmaskarray(array), axis=axis)
- points_per_calc = array.size / dask_result.size
- masked_point_fractions = point_mask_counts / points_per_calc
- boolean_mask = masked_point_fractions > mdtol
- # Return an mdtol-masked version of the basic result.
- result = da.ma.masked_array(da.ma.getdata(dask_result),
- boolean_mask)
- return result
- return inner_stat
-
-
MEAN = WeightedAggregator('mean', ma.average,
lazy_func=_build_dask_mdtol_function(da.mean))
"""
@@ -1734,7 +1713,8 @@ def inner_stat(array, axis=-1, mdtol=None, **kwargs):
"""
-SUM = WeightedAggregator('sum', _sum, lazy_func=_lazy_sum)
+SUM = WeightedAggregator('sum', iris._lazy_data.non_lazy(_lazy_sum),
+ lazy_func=_build_dask_mdtol_function(_lazy_sum))
"""
An :class:`~iris.analysis.Aggregator` instance that calculates
the sum over a :class:`~iris.cube.Cube`, as computed by :func:`numpy.ma.sum`.
From a957ebcb289040fe1755859e2bfbebf444b24468 Mon Sep 17 00:00:00 2001
From: Thomas Green
Date: Sun, 23 Sep 2018 06:49:21 +0100
Subject: [PATCH 38/62] Attempt to fix Matplotlib issue by resticting to 2.x
---
requirements/core.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements/core.txt b/requirements/core.txt
index 997c91c665..4cad29fd1f 100644
--- a/requirements/core.txt
+++ b/requirements/core.txt
@@ -7,7 +7,7 @@ cartopy
cf_units>=2
cftime
dask[array]==0.18.1 #conda: dask==0.18.1
-matplotlib>=2
+matplotlib>=2,<3
netcdf4
numpy>=1.14
scipy
From 00ee1598ecd07f5f4519e607ffa4d6979851ab74 Mon Sep 17 00:00:00 2001
From: Peter Killick
Date: Mon, 24 Sep 2018 11:45:57 +0100
Subject: [PATCH 39/62] Non-test review actions
---
lib/iris/analysis/__init__.py | 7 ++-----
lib/iris/tests/unit/analysis/test_COUNT.py | 3 ++-
2 files changed, 4 insertions(+), 6 deletions(-)
diff --git a/lib/iris/analysis/__init__.py b/lib/iris/analysis/__init__.py
index 49d9bb8172..ec4d341d25 100644
--- a/lib/iris/analysis/__init__.py
+++ b/lib/iris/analysis/__init__.py
@@ -1020,7 +1020,7 @@ def _build_dask_mdtol_function(dask_stats_function):
Make a wrapped dask statistic function that supports the 'mdtol' keyword.
'dask_function' must be a dask statistical function, compatible with the
- call signature : "dask_stats_function(data, axis, **kwargs)".
+ call signature : "dask_stats_function(data, axis=axis, **kwargs)".
It must be masked-data tolerant, i.e. it ignores masked input points and
performs a calculation on only the unmasked points.
For example, mean([1, --, 2]) = (1 + 2) / 2 = 1.5.
@@ -1228,10 +1228,7 @@ def _weighted_percentile(data, axis, weights, percent, returned=False,
@_build_dask_mdtol_function
def _lazy_count(array, **kwargs):
array = iris._lazy_data.as_lazy_data(array)
- try:
- func = kwargs.pop('function')
- except KeyError:
- raise KeyError('no selection function supplied.')
+ func = kwargs.pop('function', None)
if not callable(func):
emsg = 'function must be a callable. Got {}.'
raise TypeError(emsg.format(type(func)))
diff --git a/lib/iris/tests/unit/analysis/test_COUNT.py b/lib/iris/tests/unit/analysis/test_COUNT.py
index 63603b6059..8f7118e7c4 100644
--- a/lib/iris/tests/unit/analysis/test_COUNT.py
+++ b/lib/iris/tests/unit/analysis/test_COUNT.py
@@ -46,7 +46,8 @@ def test_name(self):
self.assertEqual(COUNT.name(), 'count')
def test_no_function(self):
- with self.assertRaisesRegexp(KeyError, 'no selection function'):
+ exp_emsg = "function must be a callable. Got "
+ with self.assertRaisesRegexp(TypeError, exp_emsg):
self.lazy_cube.collapsed("foo", COUNT)
def test_not_callable(self):
From 76b819b91e1c1d55db4a1206eac94aa6fc21b26f Mon Sep 17 00:00:00 2001
From: Peter Killick
Date: Mon, 24 Sep 2018 11:54:39 +0100
Subject: [PATCH 40/62] Make COUNT tests truer unit tests
---
lib/iris/tests/unit/analysis/test_STD_DEV.py | 14 +++++++-------
1 file changed, 7 insertions(+), 7 deletions(-)
diff --git a/lib/iris/tests/unit/analysis/test_STD_DEV.py b/lib/iris/tests/unit/analysis/test_STD_DEV.py
index dedc7cf053..57cc00132f 100644
--- a/lib/iris/tests/unit/analysis/test_STD_DEV.py
+++ b/lib/iris/tests/unit/analysis/test_STD_DEV.py
@@ -25,7 +25,7 @@
import numpy as np
-from iris._lazy_data import as_concrete_data, as_lazy_data
+from iris._lazy_data import as_concrete_data, as_lazy_data, is_lazy_data
from iris.analysis import STD_DEV
from iris.cube import Cube
from iris.coords import DimCoord
@@ -44,16 +44,16 @@ def test_name(self):
self.assertEqual(STD_DEV.name(), 'standard_deviation')
def test_collapse(self):
- cube = self.cube.collapsed("foo", STD_DEV)
- self.assertArrayAlmostEqual(cube.data, [1.58113883])
+ data = STD_DEV.aggregate(self.cube.data, axis=0)
+ self.assertArrayAlmostEqual(data, [1.58113883])
def test_lazy(self):
- cube = self.lazy_cube.collapsed("foo", STD_DEV)
- self.assertTrue(cube.has_lazy_data())
+ lazy_data = STD_DEV.lazy_aggregate(self.lazy_cube.lazy_data(), axis=0)
+ self.assertTrue(is_lazy_data(lazy_data))
def test_lazy_collapse(self):
- cube = self.lazy_cube.collapsed("foo", STD_DEV)
- self.assertArrayAlmostEqual(cube.data, [1.58113883])
+ lazy_data = STD_DEV.lazy_aggregate(self.lazy_cube.lazy_data(), axis=0)
+ self.assertArrayAlmostEqual(lazy_data.compute(), [1.58113883])
class Test_lazy_aggregate(tests.IrisTest):
From 9908eba0f85ae968589a793dfb950b3ffbd9f94d Mon Sep 17 00:00:00 2001
From: Peter Killick
Date: Mon, 24 Sep 2018 12:17:00 +0100
Subject: [PATCH 41/62] Convert MAX and MIN tests to truer unit tests
---
lib/iris/tests/unit/analysis/test_MAX.py | 24 ++++++++++++------------
lib/iris/tests/unit/analysis/test_MIN.py | 24 ++++++++++++------------
2 files changed, 24 insertions(+), 24 deletions(-)
diff --git a/lib/iris/tests/unit/analysis/test_MAX.py b/lib/iris/tests/unit/analysis/test_MAX.py
index 38bc426932..f3a523bc93 100644
--- a/lib/iris/tests/unit/analysis/test_MAX.py
+++ b/lib/iris/tests/unit/analysis/test_MAX.py
@@ -29,7 +29,7 @@
from iris.analysis import MAX
from iris.cube import Cube
from iris.coords import DimCoord
-from iris._lazy_data import as_lazy_data
+from iris._lazy_data import as_lazy_data, is_lazy_data
class Test_basics(tests.IrisTest):
@@ -45,16 +45,16 @@ def test_name(self):
self.assertEqual(MAX.name(), 'maximum')
def test_collapse(self):
- cube = self.cube.collapsed("foo", MAX)
- self.assertArrayEqual(cube.data, [5])
+ data = MAX.aggregate(self.cube.data, axis=0)
+ self.assertArrayEqual(data, [5])
def test_lazy(self):
- cube = self.lazy_cube.collapsed("foo", MAX)
- self.assertTrue(cube.has_lazy_data())
+ lazy_data = MAX.lazy_aggregate(self.lazy_cube.lazy_data(), axis=0)
+ self.assertTrue(is_lazy_data(lazy_data))
def test_lazy_collapse(self):
- cube = self.lazy_cube.collapsed("foo", MAX)
- self.assertArrayEqual(cube.data, [5])
+ lazy_data = MAX.lazy_aggregate(self.lazy_cube.lazy_data(), axis=0)
+ self.assertArrayEqual(lazy_data.compute(), [5])
class Test_masked(tests.IrisTest):
@@ -63,8 +63,8 @@ def setUp(self):
self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0)
def test_ma(self):
- cube = self.cube.collapsed("foo", MAX)
- self.assertArrayEqual(cube.data, [3])
+ data = MAX.aggregate(self.cube.data, axis=0)
+ self.assertArrayEqual(data, [3])
class Test_lazy_masked(tests.IrisTest):
@@ -74,9 +74,9 @@ def setUp(self):
self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0)
def test_lazy_ma(self):
- cube = self.cube.collapsed("foo", MAX)
- self.assertTrue(cube.has_lazy_data())
- self.assertArrayEqual(cube.data, [3])
+ lazy_data = MAX.lazy_aggregate(self.cube.lazy_data(), axis=0)
+ self.assertTrue(is_lazy_data(lazy_data))
+ self.assertArrayEqual(lazy_data.compute(), [3])
class Test_aggregate_shape(tests.IrisTest):
diff --git a/lib/iris/tests/unit/analysis/test_MIN.py b/lib/iris/tests/unit/analysis/test_MIN.py
index 82a1d68316..13860f5306 100644
--- a/lib/iris/tests/unit/analysis/test_MIN.py
+++ b/lib/iris/tests/unit/analysis/test_MIN.py
@@ -29,7 +29,7 @@
from iris.analysis import MIN
from iris.cube import Cube
from iris.coords import DimCoord
-from iris._lazy_data import as_lazy_data
+from iris._lazy_data import as_lazy_data, is_lazy_data
class Test_basics(tests.IrisTest):
@@ -45,16 +45,16 @@ def test_name(self):
self.assertEqual(MIN.name(), 'minimum')
def test_collapse(self):
- cube = self.cube.collapsed("foo", MIN)
- self.assertArrayEqual(cube.data, [1])
+ data = MIN.aggregate(self.cube.data, axis=0)
+ self.assertArrayEqual(data, [1])
def test_lazy(self):
- cube = self.lazy_cube.collapsed("foo", MIN)
- self.assertTrue(cube.has_lazy_data())
+ lazy_data = MIN.lazy_aggregate(self.lazy_cube.lazy_data(), axis=0)
+ self.assertTrue(is_lazy_data(lazy_data))
def test_lazy_collapse(self):
- cube = self.lazy_cube.collapsed("foo", MIN)
- self.assertArrayEqual(cube.data, [1])
+ lazy_data = MIN.lazy_aggregate(self.lazy_cube.lazy_data(), axis=0)
+ self.assertArrayEqual(lazy_data.compute(), [1])
class Test_masked(tests.IrisTest):
@@ -63,8 +63,8 @@ def setUp(self):
self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0)
def test_ma(self):
- cube = self.cube.collapsed("foo", MIN)
- self.assertArrayEqual(cube.data, [3])
+ data = MIN.aggregate(self.cube.data, axis=0)
+ self.assertArrayEqual(data, [3])
class Test_lazy_masked(tests.IrisTest):
@@ -74,9 +74,9 @@ def setUp(self):
self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0)
def test_lazy_ma(self):
- cube = self.cube.collapsed("foo", MIN)
- self.assertTrue(cube.has_lazy_data())
- self.assertArrayEqual(cube.data, [3])
+ lazy_data = MIN.lazy_aggregate(self.cube.lazy_data(), axis=0)
+ self.assertTrue(is_lazy_data(lazy_data))
+ self.assertArrayEqual(lazy_data.compute(), [3])
class Test_aggregate_shape(tests.IrisTest):
From e4e07adfc10310acf95607f8c50794353a6b4536 Mon Sep 17 00:00:00 2001
From: Peter Killick
Date: Mon, 24 Sep 2018 12:50:19 +0100
Subject: [PATCH 42/62] Convert COUNT and SUM agg tests to truer unit tests
---
lib/iris/tests/unit/analysis/test_COUNT.py | 56 ++++++++----------
lib/iris/tests/unit/analysis/test_SUM.py | 66 ++++++++++++----------
2 files changed, 58 insertions(+), 64 deletions(-)
diff --git a/lib/iris/tests/unit/analysis/test_COUNT.py b/lib/iris/tests/unit/analysis/test_COUNT.py
index 8f7118e7c4..882ad2921e 100644
--- a/lib/iris/tests/unit/analysis/test_COUNT.py
+++ b/lib/iris/tests/unit/analysis/test_COUNT.py
@@ -29,7 +29,7 @@
from iris.analysis import COUNT
from iris.cube import Cube
from iris.coords import DimCoord
-from iris._lazy_data import as_lazy_data
+from iris._lazy_data import as_lazy_data, is_lazy_data
class Test_basics(tests.IrisTest):
@@ -48,27 +48,33 @@ def test_name(self):
def test_no_function(self):
exp_emsg = "function must be a callable. Got "
with self.assertRaisesRegexp(TypeError, exp_emsg):
- self.lazy_cube.collapsed("foo", COUNT)
+ COUNT.lazy_aggregate(self.lazy_cube.lazy_data(), axis=0)
def test_not_callable(self):
with self.assertRaisesRegexp(TypeError, 'function must be a callable'):
- self.cube.collapsed("foo", COUNT, function='wibble')
+ COUNT.aggregate(self.cube.data, axis=0, function='wibble')
def test_lazy_not_callable(self):
with self.assertRaisesRegexp(TypeError, 'function must be a callable'):
- self.lazy_cube.collapsed("foo", COUNT, function='wibble')
+ COUNT.lazy_aggregate(self.lazy_cube.lazy_data(),
+ axis=0,
+ function='wibble')
def test_collapse(self):
- cube = self.cube.collapsed("foo", COUNT, function=self.func)
- self.assertArrayEqual(cube.data, [3])
+ data = COUNT.aggregate(self.cube.data, axis=0, function=self.func)
+ self.assertArrayEqual(data, [3])
def test_lazy(self):
- cube = self.lazy_cube.collapsed("foo", COUNT, function=self.func)
- self.assertTrue(cube.has_lazy_data())
+ lazy_data = COUNT.lazy_aggregate(self.lazy_cube.lazy_data(),
+ axis=0,
+ function=self.func)
+ self.assertTrue(is_lazy_data(lazy_data))
def test_lazy_collapse(self):
- cube = self.lazy_cube.collapsed("foo", COUNT, function=self.func)
- self.assertArrayEqual(cube.data, [3])
+ lazy_data = COUNT.lazy_aggregate(self.lazy_cube.lazy_data(),
+ axis=0,
+ function=self.func)
+ self.assertArrayEqual(lazy_data.compute(), [3])
class Test_units_func(tests.IrisTest):
@@ -85,26 +91,8 @@ def setUp(self):
self.func = lambda x: x >= 3
def test_ma(self):
- cube = self.cube.collapsed("foo", COUNT, function=self.func)
- self.assertArrayEqual(cube.data, [2])
-
-
-class Test_lazy(tests.IrisTest):
- def setUp(self):
- data = np.array([1, 2, 3, 4, 5])
- self.cube = Cube(as_lazy_data(data))
- self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0)
- self.func = lambda x: x >= 3
-
- def test_lazy_oper(self):
- cube = self.cube.collapsed("foo", COUNT, function=self.func)
- self.assertTrue(cube.has_lazy_data())
-
- def test_collapse(self):
- result = self.cube.collapsed("foo", COUNT, function=self.func)
- self.cube.data
- expected = self.cube.collapsed("foo", COUNT, function=self.func)
- self.assertArrayEqual(result.data, expected.data)
+ data = COUNT.aggregate(self.cube.data, axis=0, function=self.func)
+ self.assertArrayEqual(data, [2])
class Test_lazy_masked(tests.IrisTest):
@@ -117,9 +105,11 @@ def setUp(self):
self.func = lambda x: x >= 3
def test_ma(self):
- cube = self.lazy_cube.collapsed("foo", COUNT, function=self.func)
- self.assertTrue(cube.has_lazy_data())
- self.assertArrayEqual(cube.data, [2])
+ lazy_data = COUNT.lazy_aggregate(self.lazy_cube.lazy_data(),
+ axis=0,
+ function=self.func)
+ self.assertTrue(is_lazy_data(lazy_data))
+ self.assertArrayEqual(lazy_data.compute(), [2])
class Test_aggregate_shape(tests.IrisTest):
diff --git a/lib/iris/tests/unit/analysis/test_SUM.py b/lib/iris/tests/unit/analysis/test_SUM.py
index 1cf94723af..0a0f2332ab 100644
--- a/lib/iris/tests/unit/analysis/test_SUM.py
+++ b/lib/iris/tests/unit/analysis/test_SUM.py
@@ -29,7 +29,7 @@
from iris.analysis import SUM
from iris.cube import Cube
from iris.coords import DimCoord
-from iris._lazy_data import as_lazy_data
+from iris._lazy_data import as_lazy_data, is_lazy_data
class Test_basics(tests.IrisTest):
@@ -45,16 +45,16 @@ def test_name(self):
self.assertEqual(SUM.name(), 'sum')
def test_collapse(self):
- cube = self.cube.collapsed("foo", SUM)
- self.assertArrayEqual(cube.data, [15])
+ data = SUM.aggregate(self.cube.data, axis=0)
+ self.assertArrayEqual(data, [15])
def test_lazy(self):
- cube = self.lazy_cube.collapsed("foo", SUM)
- self.assertTrue(cube.has_lazy_data())
+ lazy_data = SUM.lazy_aggregate(self.lazy_cube.lazy_data(), axis=0)
+ self.assertTrue(is_lazy_data(lazy_data))
def test_lazy_collapse(self):
- cube = self.lazy_cube.collapsed("foo", SUM)
- self.assertArrayEqual(cube.data, [15])
+ lazy_data = SUM.lazy_aggregate(self.lazy_cube.lazy_data(), axis=0)
+ self.assertArrayEqual(lazy_data.compute(), [15])
class Test_masked(tests.IrisTest):
@@ -63,8 +63,8 @@ def setUp(self):
self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0)
def test_ma(self):
- cube = self.cube.collapsed("foo", SUM)
- self.assertArrayEqual(cube.data, [12])
+ data = SUM.aggregate(self.cube.data, axis=0)
+ self.assertArrayEqual(data, [12])
class Test_lazy_masked(tests.IrisTest):
@@ -74,9 +74,9 @@ def setUp(self):
self.cube.add_dim_coord(DimCoord([6, 7, 8, 9, 10], long_name='foo'), 0)
def test_lazy_ma(self):
- cube = self.cube.collapsed("foo", SUM)
- self.assertTrue(cube.has_lazy_data())
- self.assertArrayEqual(cube.data, [12])
+ lazy_data = SUM.lazy_aggregate(self.cube.lazy_data(), axis=0)
+ self.assertTrue(is_lazy_data(lazy_data))
+ self.assertArrayEqual(lazy_data.compute(), [12])
class Test_weights_and_returned(tests.IrisTest):
@@ -90,19 +90,19 @@ def setUp(self):
self.weights = np.array([2, 1, 1, 1, 1] * 2).reshape(2, 5)
def test_weights(self):
- cube = self.cube_2d.collapsed('bar', SUM, weights=self.weights)
- self.assertArrayEqual(cube.data, [14, 9, 11, 13, 15])
+ data = SUM.aggregate(self.cube_2d.data, axis=0, weights=self.weights)
+ self.assertArrayEqual(data, [14, 9, 11, 13, 15])
def test_returned(self):
- cube, weights = self.cube_2d.collapsed('bar', SUM, returned=True)
- self.assertArrayEqual(cube.data, [7, 9, 11, 13, 15])
+ data, weights = SUM.aggregate(self.cube_2d.data, axis=0, returned=True)
+ self.assertArrayEqual(data, [7, 9, 11, 13, 15])
self.assertArrayEqual(weights, [2, 2, 2, 2, 2])
def test_weights_and_returned(self):
- cube, weights = self.cube_2d.collapsed('bar', SUM,
- weights=self.weights,
- returned=True)
- self.assertArrayEqual(cube.data, [14, 9, 11, 13, 15])
+ data, weights = SUM.aggregate(self.cube_2d.data, axis=0,
+ weights=self.weights,
+ returned=True)
+ self.assertArrayEqual(data, [14, 9, 11, 13, 15])
self.assertArrayEqual(weights, [4, 2, 2, 2, 2])
@@ -117,22 +117,26 @@ def setUp(self):
self.weights = np.array([2, 1, 1, 1, 1] * 2).reshape(2, 5)
def test_weights(self):
- cube = self.cube_2d.collapsed('bar', SUM, weights=self.weights)
- self.assertTrue(cube.has_lazy_data())
- self.assertArrayEqual(cube.data, [14, 9, 11, 13, 15])
+ lazy_data = SUM.lazy_aggregate(self.cube_2d.lazy_data(), axis=0,
+ weights=self.weights)
+ self.assertTrue(is_lazy_data(lazy_data))
+ self.assertArrayEqual(lazy_data.compute(), [14, 9, 11, 13, 15])
def test_returned(self):
- cube, weights = self.cube_2d.collapsed('bar', SUM, returned=True)
- self.assertTrue(cube.has_lazy_data())
- self.assertArrayEqual(cube.data, [7, 9, 11, 13, 15])
+ lazy_data, weights = SUM.lazy_aggregate(self.cube_2d.lazy_data(),
+ axis=0,
+ returned=True)
+ self.assertTrue(is_lazy_data(lazy_data))
+ self.assertArrayEqual(lazy_data.compute(), [7, 9, 11, 13, 15])
self.assertArrayEqual(weights, [2, 2, 2, 2, 2])
def test_weights_and_returned(self):
- cube, weights = self.cube_2d.collapsed('bar', SUM,
- weights=self.weights,
- returned=True)
- self.assertTrue(cube.has_lazy_data())
- self.assertArrayEqual(cube.data, [14, 9, 11, 13, 15])
+ lazy_data, weights = SUM.lazy_aggregate(self.cube_2d.lazy_data(),
+ axis=0,
+ weights=self.weights,
+ returned=True)
+ self.assertTrue(is_lazy_data(lazy_data))
+ self.assertArrayEqual(lazy_data.compute(), [14, 9, 11, 13, 15])
self.assertArrayEqual(weights, [4, 2, 2, 2, 2])
From 50fad00b92f05604f77124b696d8f63b5ee17844 Mon Sep 17 00:00:00 2001
From: Peter Killick
Date: Mon, 24 Sep 2018 16:48:41 +0100
Subject: [PATCH 43/62] Tests for new _lazy_data function
---
.../tests/unit/lazy_data/test_non_lazy.py | 51 +++++++++++++++++++
1 file changed, 51 insertions(+)
create mode 100644 lib/iris/tests/unit/lazy_data/test_non_lazy.py
diff --git a/lib/iris/tests/unit/lazy_data/test_non_lazy.py b/lib/iris/tests/unit/lazy_data/test_non_lazy.py
new file mode 100644
index 0000000000..7a736a0584
--- /dev/null
+++ b/lib/iris/tests/unit/lazy_data/test_non_lazy.py
@@ -0,0 +1,51 @@
+# (C) British Crown Copyright 2018, Met Office
+#
+# This file is part of Iris.
+#
+# Iris is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Iris is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Iris. If not, see .
+"""Test function :func:`iris._lazy data.non_lazy`."""
+
+from __future__ import (absolute_import, division, print_function)
+from six.moves import (filter, input, map, range, zip) # noqa
+
+# Import iris.tests first so that some things can be initialised before
+# importing anything else.
+import iris.tests as tests
+
+import numpy as np
+
+from iris._lazy_data import as_lazy_data, is_lazy_data, non_lazy
+
+
+class Test_non_lazy(tests.IrisTest):
+ def setUp(self):
+ self.array = np.arange(8).reshape(2, 4)
+ self.lazy_array = as_lazy_data(self.array)
+ self.func = non_lazy(lambda array: array.sum(axis=0))
+ self.func_result = [4, 6, 8, 10]
+
+ def test_lazy_input(self):
+ result = self.func(self.lazy_array)
+ self.assertFalse(is_lazy_data(result))
+ self.assertArrayEqual(result, self.func_result)
+
+ def test_non_lazy_input(self):
+ # Check that a non-lazy input doesn't trip up the functionality.
+ result = self.func(self.array)
+ self.assertFalse(is_lazy_data(result))
+ self.assertArrayEqual(result, self.func_result)
+
+
+if __name__ == '__main__':
+ tests.main()
From 63f0b5e482bab82033e44c6bb03259a17a1a1666 Mon Sep 17 00:00:00 2001
From: Patrick Peglar
Date: Fri, 28 Sep 2018 11:17:21 +0100
Subject: [PATCH 44/62] Fix for netCDF4 1.4 behaviour change. (#3177)
---
lib/iris/fileformats/cf.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lib/iris/fileformats/cf.py b/lib/iris/fileformats/cf.py
index f2fc895d1c..ddf7f2d64d 100644
--- a/lib/iris/fileformats/cf.py
+++ b/lib/iris/fileformats/cf.py
@@ -936,6 +936,11 @@ def __init__(self, filename, warn=False, monotonic=False):
self._dataset = netCDF4.Dataset(self._filename, mode='r')
+ # Return variable data as np.ma.MaskedArray *only* when masked points
+ # are found in the slice requested, otherwise as 'normal' np.ndarray.
+ # Note: this suits us better, and was standard up to netcdf 1.3.
+ self._dataset.set_always_mask(False)
+
# Issue load optimisation warning.
if warn and self._dataset.file_format in ['NETCDF3_CLASSIC', 'NETCDF3_64BIT']:
warnings.warn('Optimise CF-netCDF loading by converting data from NetCDF3 ' \
From afee89267377147c5dfd908ca4686e3a8cb1ae1a Mon Sep 17 00:00:00 2001
From: Zeb Nicholls
Date: Fri, 28 Sep 2018 18:09:00 +0200
Subject: [PATCH 45/62] Improve gracefully filling warning (#3171)
* Realise that running the tests is simpler than I thought
* Make Gracefully warning only appear when filling is required
* Add tests of warnings
* Get rid of install changes, they are in #3170
* Update after review
* Add whatsnew entry
---
docs/iris/src/conf.py | 2 +-
...fully-filling-warning-only-when-masked.txt | 1 +
lib/iris/analysis/_regrid.py | 2 +-
.../fileformats/_pyke_rules/fc_rules_cf.krb | 82 +++++++++----------
lib/iris/tests/integration/test_regridding.py | 2 +-
lib/iris/tests/test_coordsystem.py | 2 +-
.../fileformats/netcdf/test__load_cube.py | 2 +-
.../tests/unit/fileformats/pp/test_save.py | 2 +-
.../test_build_dimension_coordinate.py | 80 +++++++++++++++++-
9 files changed, 127 insertions(+), 48 deletions(-)
create mode 100644 docs/iris/src/whatsnew/contributions_2.2.0/bugfix_2018-Sep-19_gracefully-filling-warning-only-when-masked.txt
diff --git a/docs/iris/src/conf.py b/docs/iris/src/conf.py
index 2833a01674..6cdfe634c4 100644
--- a/docs/iris/src/conf.py
+++ b/docs/iris/src/conf.py
@@ -1,4 +1,4 @@
-# (C) British Crown Copyright 2010 - 2017, Met Office
+# (C) British Crown Copyright 2010 - 2018, Met Office
#
# This file is part of Iris.
#
diff --git a/docs/iris/src/whatsnew/contributions_2.2.0/bugfix_2018-Sep-19_gracefully-filling-warning-only-when-masked.txt b/docs/iris/src/whatsnew/contributions_2.2.0/bugfix_2018-Sep-19_gracefully-filling-warning-only-when-masked.txt
new file mode 100644
index 0000000000..6b612ef109
--- /dev/null
+++ b/docs/iris/src/whatsnew/contributions_2.2.0/bugfix_2018-Sep-19_gracefully-filling-warning-only-when-masked.txt
@@ -0,0 +1 @@
+* Gracefully filling warnings are only issued when the co-ordinate or bound data is actually masked.
diff --git a/lib/iris/analysis/_regrid.py b/lib/iris/analysis/_regrid.py
index 71304a5dde..83561a2b94 100644
--- a/lib/iris/analysis/_regrid.py
+++ b/lib/iris/analysis/_regrid.py
@@ -1,4 +1,4 @@
-# (C) British Crown Copyright 2014 - 2017, Met Office
+# (C) British Crown Copyright 2014 - 2018, Met Office
#
# This file is part of Iris.
#
diff --git a/lib/iris/fileformats/_pyke_rules/fc_rules_cf.krb b/lib/iris/fileformats/_pyke_rules/fc_rules_cf.krb
index f301f0fc9b..5fc68e58c2 100644
--- a/lib/iris/fileformats/_pyke_rules/fc_rules_cf.krb
+++ b/lib/iris/fileformats/_pyke_rules/fc_rules_cf.krb
@@ -40,7 +40,7 @@ fc_default
#
# Context:
-# This rule will trigger iff a grid_mapping() case specific fact
+# This rule will trigger iff a grid_mapping() case specific fact
# has been asserted that refers to a rotated pole.
#
# Purpose:
@@ -120,7 +120,7 @@ fc_provides_grid_mapping_mercator
#
# Context:
-# This rule will trigger iff a grid_mapping() case specific fact
+# This rule will trigger iff a grid_mapping() case specific fact
# has been asserted that refers to a stereographic.
#
# Purpose:
@@ -199,10 +199,10 @@ fc_provides_grid_mapping_albers_equal_area
#
# Context:
# This rule will trigger iff a coordinate() case specific fact
-# has been asserted that refers to a CF latitude coordinate.
+# has been asserted that refers to a CF latitude coordinate.
#
# Purpose:
-# Assert that the CF latitude coordinate exists.
+# Assert that the CF latitude coordinate exists.
#
fc_provides_coordinate_latitude
foreach
@@ -435,10 +435,10 @@ fc_build_auxiliary_coordinate_longitude_rotated
#
# Context:
# This rule will trigger for each auxiliary_coordinate() case specific fact
-# that is not a spatio-temporal related auxiliary coordinate.
+# that is not a spatio-temporal related auxiliary coordinate.
#
# Purpose:
-# Add the auxiliary coordinate to the cube.
+# Add the auxiliary coordinate to the cube.
#
fc_build_auxiliary_coordinate
foreach
@@ -457,7 +457,7 @@ fc_build_auxiliary_coordinate
# This rule will trigger for each cell_measure case specific fact.
#
# Purpose:
-# Add the cell measures attribute to the cube.
+# Add the cell measures attribute to the cube.
#
fc_build_cell_measure
foreach
@@ -549,7 +549,7 @@ fc_build_coordinate_longitude_rotated
python build_dimension_coordinate(engine, cf_coord_var,
coord_name=CF_VALUE_STD_NAME_GRID_LON,
coord_system=engine.provides['coordinate_system'])
- python engine.rule_triggered.add(rule.name)
+ python engine.rule_triggered.add(rule.name)
#
@@ -597,7 +597,7 @@ fc_build_coordinate_longitude_nocs
coord_system=None)
python engine.rule_triggered.add(rule.name)
-
+
#
# Context:
# This rule will trigger iff a projection_x_coordinate coordinate exists and
@@ -917,8 +917,8 @@ fc_attribute_ukmo__process_flags
python attr_value = engine.cf_var.ukmo__process_flags
python engine.cube.attributes['ukmo__process_flags'] = tuple([x.replace("_", " ") for x in attr_value.split(" ")])
python engine.rule_triggered.add(rule.name)
-
-
+
+
#
# Context:
# This rule will trigger iff a formula term that refers to a
@@ -1076,8 +1076,8 @@ fc_extras
import iris.std_names
import iris.util
from iris._lazy_data import as_lazy_data
-
-
+
+
#
# UD Units Constants (based on Unidata udunits.dat definition file)
#
@@ -1087,7 +1087,7 @@ fc_extras
UD_UNITS_LON = ['degrees_east', 'degree_east', 'degree_e', 'degrees_e',
'degreee', 'degreese', 'degrees', 'degrees east',
'degree east', 'degree e', 'degrees e']
-
+
#
# CF Dimensionless Vertical Coordinates
#
@@ -1119,7 +1119,7 @@ fc_extras
CF_GRID_MAPPING_STEREO = 'stereographic'
CF_GRID_MAPPING_TRANSVERSE = 'transverse_mercator'
CF_GRID_MAPPING_VERTICAL = 'vertical_perspective'
-
+
#
# CF Attribute Names.
#
@@ -1149,7 +1149,7 @@ fc_extras
CF_ATTR_LONG_NAME = 'long_name'
CF_ATTR_UNITS = 'units'
CF_ATTR_CELL_METHODS = 'cell_methods'
-
+
#
# CF Attribute Value Constants.
#
@@ -1158,11 +1158,11 @@ fc_extras
CF_VALUE_AXIS_Y = 'y'
CF_VALUE_AXIS_T = 't'
CF_VALUE_AXIS_Z = 'z'
-
-
+
+
# Attribute - positive.
CF_VALUE_POSITIVE = ['down', 'up']
-
+
# Attribute - standard_name.
CF_VALUE_STD_NAME_LAT = 'latitude'
CF_VALUE_STD_NAME_LON = 'longitude'
@@ -1213,7 +1213,7 @@ fc_extras
msg = msg.replace('variable', 'variable {!r}'.format(name))
warnings.warn(message=msg, category=UnknownCellMethodWarning)
- # Set the cube global attributes.
+ # Set the cube global attributes.
for attr_name, attr_value in six.iteritems(cf_var.cf_group.global_attributes):
try:
if six.PY2 and isinstance(attr_value, six.text_type):
@@ -1242,7 +1242,7 @@ fc_extras
# Check for a default spherical earth.
if major is None and minor is None and inverse_flattening is None:
- major = getattr(cf_grid_var, CF_ATTR_GRID_EARTH_RADIUS, None)
+ major = getattr(cf_grid_var, CF_ATTR_GRID_EARTH_RADIUS, None)
return major, minor, inverse_flattening
@@ -1344,7 +1344,7 @@ fc_extras
inverse_flattening is not None:
ellipsoid = iris.coord_systems.GeogCS(major, minor,
inverse_flattening)
-
+
cs = iris.coord_systems.LambertConformal(
latitude_of_projection_origin, longitude_of_central_meridian,
false_easting, false_northing, standard_parallel,
@@ -1401,7 +1401,7 @@ fc_extras
# values for false_easting, false_northing,
# scale_factor_at_projection_origin and standard_parallel. These are
# checked elsewhere.
-
+
ellipsoid = None
if major is not None or minor is not None or \
inverse_flattening is not None:
@@ -1621,7 +1621,7 @@ fc_extras
attr_units = get_attr_units(cf_coord_var, attributes)
points_data = cf_coord_var[:]
# Gracefully fill points masked array.
- if ma.isMaskedArray(points_data):
+ if ma.is_masked(points_data):
points_data = ma.filled(points_data)
msg = 'Gracefully filling {!r} dimension coordinate masked points'
warnings.warn(msg.format(str(cf_coord_var.cf_name)))
@@ -1631,7 +1631,7 @@ fc_extras
if cf_bounds_var is not None:
bounds_data = cf_bounds_var[:]
# Gracefully fill bounds masked array.
- if ma.isMaskedArray(bounds_data):
+ if ma.is_masked(bounds_data):
bounds_data = ma.filled(bounds_data)
msg = 'Gracefully filling {!r} dimension coordinate masked bounds'
warnings.warn(msg.format(str(cf_coord_var.cf_name)))
@@ -1696,7 +1696,7 @@ fc_extras
else:
# Scalar coords are placed in the aux_coords container.
cube.add_aux_coord(coord, data_dims)
-
+
# Update the coordinate to CF-netCDF variable mapping.
engine.provides['coordinates'].append((coord, cf_coord_var.cf_name))
@@ -1739,7 +1739,7 @@ fc_extras
# and the coordinate being built.
common_dims = [dim for dim in cf_coord_var.dimensions
if dim in cf_var.dimensions]
- data_dims = None
+ data_dims = None
if common_dims:
# Calculate the offset of each common dimension.
data_dims = [cf_var.dimensions.index(dim) for dim in common_dims]
@@ -1763,7 +1763,7 @@ fc_extras
# Update the coordinate to CF-netCDF variable mapping.
engine.provides['coordinates'].append((coord, cf_coord_var.cf_name))
-
+
################################################################################
def build_cell_measures(engine, cf_cm_attr, coord_name=None):
"""Create a CellMeasure instance and add it to the cube."""
@@ -1780,19 +1780,19 @@ fc_extras
# and the coordinate being built.
common_dims = [dim for dim in cf_cm_attr.dimensions
if dim in cf_var.dimensions]
- data_dims = None
+ data_dims = None
if common_dims:
# Calculate the offset of each common dimension.
data_dims = [cf_var.dimensions.index(dim) for dim in common_dims]
# Determine the standard_name, long_name and var_name
standard_name, long_name, var_name = get_names(cf_cm_attr, coord_name, attributes)
-
+
# Obtain the cf_measure.
measure = cf_cm_attr.cf_measure
-
+
# Create the CellMeasure
- cell_measure = iris.coords.CellMeasure(data,
+ cell_measure = iris.coords.CellMeasure(data,
standard_name=standard_name,
long_name=long_name,
var_name=var_name,
@@ -1802,17 +1802,17 @@ fc_extras
# Add it to the cube
cube.add_cell_measure(cell_measure, data_dims)
-
+
################################################################################
def _is_lat_lon(cf_var, ud_units, std_name, std_name_grid, axis_name, prefixes):
"""
Determine whether the CF coordinate variable is a latitude/longitude variable.
-
+
Ref: [CF] Section 4.1 Latitude Coordinate.
[CF] Section 4.2 Longitude Coordinate.
-
+
"""
is_valid = False
attr_units = getattr(cf_var, CF_ATTR_UNITS, None)
@@ -1854,7 +1854,7 @@ fc_extras
def is_latitude(engine, cf_name):
"""Determine whether the CF coordinate variable is a latitude variable."""
cf_var = engine.cf_var.cf_group[cf_name]
- return _is_lat_lon(cf_var, UD_UNITS_LAT, CF_VALUE_STD_NAME_LAT,
+ return _is_lat_lon(cf_var, UD_UNITS_LAT, CF_VALUE_STD_NAME_LAT,
CF_VALUE_STD_NAME_GRID_LAT, CF_VALUE_AXIS_Y, ['lat', 'rlat'])
@@ -1910,7 +1910,7 @@ fc_extras
is_time_reference = cf_units.Unit(attr_units or 1).is_time_reference()
except ValueError:
is_time_reference = False
-
+
return is_time_reference and (attr_std_name=='time' or attr_axis.lower()==CF_VALUE_AXIS_T)
@@ -1978,7 +1978,7 @@ fc_extras
def has_supported_mercator_parameters(engine, cf_name):
"""Determine whether the CF grid mapping variable has the supported
values for the parameters of the Mercator projection."""
-
+
is_valid = True
cf_grid_var = engine.cf_var.cf_group[cf_name]
@@ -2018,8 +2018,8 @@ fc_extras
################################################################################
def has_supported_stereographic_parameters(engine, cf_name):
"""Determine whether the CF grid mapping variable has a value of 1.0
- for the scale_factor_at_projection_origin attribute."""
-
+ for the scale_factor_at_projection_origin attribute."""
+
is_valid = True
cf_grid_var = engine.cf_var.cf_group[cf_name]
@@ -2102,6 +2102,6 @@ fc_extras
if len(d[CM_NAME]) != len(comment) and len(comment) == 1:
comment = comment*len(d[CM_NAME])
d[CM_INTERVAL] = tuple(interval)
- d[CM_COMMENT] = tuple(comment)
+ d[CM_COMMENT] = tuple(comment)
cell_methods.append(iris.coords.CellMethod(d[CM_METHOD], coords=d[CM_NAME], intervals=d[CM_INTERVAL], comments=d[CM_COMMENT]))
return tuple(cell_methods)
diff --git a/lib/iris/tests/integration/test_regridding.py b/lib/iris/tests/integration/test_regridding.py
index 47d155f3f2..80878c21b5 100644
--- a/lib/iris/tests/integration/test_regridding.py
+++ b/lib/iris/tests/integration/test_regridding.py
@@ -1,4 +1,4 @@
-# (C) British Crown Copyright 2013 - 2017, Met Office
+# (C) British Crown Copyright 2013 - 2018, Met Office
#
# This file is part of Iris.
#
diff --git a/lib/iris/tests/test_coordsystem.py b/lib/iris/tests/test_coordsystem.py
index 6def1a3123..5aef363533 100644
--- a/lib/iris/tests/test_coordsystem.py
+++ b/lib/iris/tests/test_coordsystem.py
@@ -1,4 +1,4 @@
-# (C) British Crown Copyright 2010 - 2017, Met Office
+# (C) British Crown Copyright 2010 - 2018, Met Office
#
# This file is part of Iris.
#
diff --git a/lib/iris/tests/unit/fileformats/netcdf/test__load_cube.py b/lib/iris/tests/unit/fileformats/netcdf/test__load_cube.py
index 41b6ca5ff0..603547b707 100644
--- a/lib/iris/tests/unit/fileformats/netcdf/test__load_cube.py
+++ b/lib/iris/tests/unit/fileformats/netcdf/test__load_cube.py
@@ -1,4 +1,4 @@
-# (C) British Crown Copyright 2014 - 2017, Met Office
+# (C) British Crown Copyright 2014 - 2018, Met Office
#
# This file is part of Iris.
#
diff --git a/lib/iris/tests/unit/fileformats/pp/test_save.py b/lib/iris/tests/unit/fileformats/pp/test_save.py
index 081e01fcf9..361c01f936 100644
--- a/lib/iris/tests/unit/fileformats/pp/test_save.py
+++ b/lib/iris/tests/unit/fileformats/pp/test_save.py
@@ -1,4 +1,4 @@
-# (C) British Crown Copyright 2014 - 2017, Met Office
+# (C) British Crown Copyright 2014 - 2018, Met Office
#
# This file is part of Iris.
#
diff --git a/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_dimension_coordinate.py b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_dimension_coordinate.py
index c645f984cc..38239ea9a0 100644
--- a/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_dimension_coordinate.py
+++ b/lib/iris/tests/unit/fileformats/pyke_rules/compiled_krb/fc_rules_cf_fc/test_build_dimension_coordinate.py
@@ -1,4 +1,4 @@
-# (C) British Crown Copyright 2014 - 2015, Met Office
+# (C) British Crown Copyright 2014 - 2018, Met Office
#
# This file is part of Iris.
#
@@ -112,6 +112,84 @@ def test_dim_coord_construction(self):
self.engine.cube.add_dim_coord.assert_called_with(
expected_coord, [0])
+ def test_dim_coord_construction_masked_array(self):
+ self._set_cf_coord_var(np.ma.array(
+ np.arange(6),
+ mask=[True, False, False, False, False, False],
+ fill_value=-999,
+ ))
+
+ expected_coord = DimCoord(
+ np.array([-999, 1, 2, 3, 4, 5]),
+ long_name=self.cf_coord_var.long_name,
+ var_name=self.cf_coord_var.cf_name,
+ units=self.cf_coord_var.units,
+ bounds=self.bounds)
+
+ with warnings.catch_warnings(record=True) as w:
+ # Asserts must lie within context manager because of deferred
+ # loading.
+ with self.deferred_load_patch, self.get_cf_bounds_var_patch:
+ build_dimension_coordinate(self.engine, self.cf_coord_var)
+
+ # Test that expected coord is built and added to cube.
+ self.engine.cube.add_dim_coord.assert_called_with(
+ expected_coord, [0])
+
+ # Assert warning is raised
+ assert len(w) == 1
+ assert 'Gracefully filling' in w[0].message.args[0]
+
+ def test_dim_coord_construction_masked_array_mask_does_nothing(self):
+ self._set_cf_coord_var(np.ma.array(
+ np.arange(6),
+ mask=False,
+ ))
+
+ expected_coord = DimCoord(
+ self.cf_coord_var[:],
+ long_name=self.cf_coord_var.long_name,
+ var_name=self.cf_coord_var.cf_name,
+ units=self.cf_coord_var.units,
+ bounds=self.bounds)
+
+ with warnings.catch_warnings(record=True) as w:
+ # Asserts must lie within context manager because of deferred
+ # loading.
+ with self.deferred_load_patch, self.get_cf_bounds_var_patch:
+ build_dimension_coordinate(self.engine, self.cf_coord_var)
+
+ # Test that expected coord is built and added to cube.
+ self.engine.cube.add_dim_coord.assert_called_with(
+ expected_coord, [0])
+
+ # Assert no warning is raised
+ assert len(w) == 0
+
+ def test_dim_coord_construction_masked_bounds_mask_does_nothing(self):
+ self.bounds = np.ma.array(np.arange(12).reshape(6, 2), mask=False)
+ self._set_cf_coord_var(np.arange(6))
+
+ expected_coord = DimCoord(
+ self.cf_coord_var[:],
+ long_name=self.cf_coord_var.long_name,
+ var_name=self.cf_coord_var.cf_name,
+ units=self.cf_coord_var.units,
+ bounds=self.bounds)
+
+ with warnings.catch_warnings(record=True) as w:
+ # Asserts must lie within context manager because of deferred
+ # loading.
+ with self.deferred_load_patch, self.get_cf_bounds_var_patch:
+ build_dimension_coordinate(self.engine, self.cf_coord_var)
+
+ # Test that expected coord is built and added to cube.
+ self.engine.cube.add_dim_coord.assert_called_with(
+ expected_coord, [0])
+
+ # Assert no warning is raised
+ assert len(w) == 0
+
def test_aux_coord_construction(self):
# Use non monotonically increasing coordinates to force aux coord
# construction.
From 9088c4958baee4a2833461cc6952f359fa513e58 Mon Sep 17 00:00:00 2001
From: Peter Killick
Date: Fri, 28 Sep 2018 17:11:36 +0100
Subject: [PATCH 46/62] Minor clarification to entry via a little more
punctuation
---
..._2018-Sep-19_gracefully-filling-warning-only-when-masked.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/iris/src/whatsnew/contributions_2.2.0/bugfix_2018-Sep-19_gracefully-filling-warning-only-when-masked.txt b/docs/iris/src/whatsnew/contributions_2.2.0/bugfix_2018-Sep-19_gracefully-filling-warning-only-when-masked.txt
index 6b612ef109..c720e6f07a 100644
--- a/docs/iris/src/whatsnew/contributions_2.2.0/bugfix_2018-Sep-19_gracefully-filling-warning-only-when-masked.txt
+++ b/docs/iris/src/whatsnew/contributions_2.2.0/bugfix_2018-Sep-19_gracefully-filling-warning-only-when-masked.txt
@@ -1 +1 @@
-* Gracefully filling warnings are only issued when the co-ordinate or bound data is actually masked.
+* "Gracefully filling..." warnings are only issued when the co-ordinate or bound data is actually masked.
From 94022adcc507544556f42a144378b978591c8ad3 Mon Sep 17 00:00:00 2001
From: Patrick Peglar
Date: Mon, 1 Oct 2018 11:48:48 +0100
Subject: [PATCH 47/62] Revert nc vars masking fix (temporarily). (#3178)
---
lib/iris/fileformats/cf.py | 5 -----
1 file changed, 5 deletions(-)
diff --git a/lib/iris/fileformats/cf.py b/lib/iris/fileformats/cf.py
index ddf7f2d64d..f2fc895d1c 100644
--- a/lib/iris/fileformats/cf.py
+++ b/lib/iris/fileformats/cf.py
@@ -936,11 +936,6 @@ def __init__(self, filename, warn=False, monotonic=False):
self._dataset = netCDF4.Dataset(self._filename, mode='r')
- # Return variable data as np.ma.MaskedArray *only* when masked points
- # are found in the slice requested, otherwise as 'normal' np.ndarray.
- # Note: this suits us better, and was standard up to netcdf 1.3.
- self._dataset.set_always_mask(False)
-
# Issue load optimisation warning.
if warn and self._dataset.file_format in ['NETCDF3_CLASSIC', 'NETCDF3_64BIT']:
warnings.warn('Optimise CF-netCDF loading by converting data from NetCDF3 ' \
From d7f943b744c7932be191899e40370443b1b7cfc4 Mon Sep 17 00:00:00 2001
From: Corinne Bosley
Date: Tue, 2 Oct 2018 09:08:58 +0100
Subject: [PATCH 48/62] fix for pandas column object bug (#3176)
* turn columns object into pandas array, plus test
included cml this time
* made things the way pandas like it; bambooish
* regenerated cml to match output
---
lib/iris/pandas.py | 2 +-
.../pandas/as_cube/data_frame_multidim.cml | 15 +++++++++++++++
lib/iris/tests/test_pandas.py | 11 +++++++++++
3 files changed, 27 insertions(+), 1 deletion(-)
create mode 100644 lib/iris/tests/results/pandas/as_cube/data_frame_multidim.cml
diff --git a/lib/iris/pandas.py b/lib/iris/pandas.py
index 244a7c011b..798e034017 100644
--- a/lib/iris/pandas.py
+++ b/lib/iris/pandas.py
@@ -115,7 +115,7 @@ def as_cube(pandas_array, copy=True, calendars=None):
_add_iris_coord(cube, "index", pandas_array.index, 0,
calendars.get(0, None))
if pandas_array.ndim == 2:
- _add_iris_coord(cube, "columns", pandas_array.columns, 1,
+ _add_iris_coord(cube, "columns", pandas_array.columns.values, 1,
calendars.get(1, None))
return cube
diff --git a/lib/iris/tests/results/pandas/as_cube/data_frame_multidim.cml b/lib/iris/tests/results/pandas/as_cube/data_frame_multidim.cml
new file mode 100644
index 0000000000..d377fa72d8
--- /dev/null
+++ b/lib/iris/tests/results/pandas/as_cube/data_frame_multidim.cml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/lib/iris/tests/test_pandas.py b/lib/iris/tests/test_pandas.py
index aec432692a..51a163b728 100644
--- a/lib/iris/tests/test_pandas.py
+++ b/lib/iris/tests/test_pandas.py
@@ -398,6 +398,17 @@ def test_data_frame_masked(self):
tests.get_result_path(('pandas', 'as_cube',
'data_frame_masked.cml')))
+ def test_data_frame_multidim(self):
+ data_frame = pandas.DataFrame([[0, 1, 2, 3, 4],
+ [5, 6, 7, 8, 9]],
+ index=[0, 1],
+ columns=['col_1', 'col_2', 'col_3',
+ 'col_4', 'col_5'])
+ self.assertCML(
+ iris.pandas.as_cube(data_frame),
+ tests.get_result_path(('pandas', 'as_cube',
+ 'data_frame_multidim.cml')))
+
def test_data_frame_cftime_360(self):
data_frame = pandas.DataFrame(
[[0, 1, 2, 3, 4],
From 0ac46010918e830659ad922ac422620e98fa0464 Mon Sep 17 00:00:00 2001
From: Zeb Nicholls
Date: Tue, 2 Oct 2018 10:16:39 +0200
Subject: [PATCH 49/62] Update module headers and installation instructions
(#3170)
* Update module headers and installation instructions
* Realise that running the tests is simpler than I thought
* Update install instructions for developers
* Update INSTALL to be consistent
---
.gitignore | 3 +++
INSTALL | 24 ++++++++++++++++++++----
2 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/.gitignore b/.gitignore
index 4a65981ad5..f0420cbc22 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,8 @@
*.py[co]
+# Environment file which should be autogenerated
+*conda_requirements.txt*
+
# Packages
*.egg?
*.egg-info
diff --git a/INSTALL b/INSTALL
index 3ae4855e25..c8a61769fe 100644
--- a/INSTALL
+++ b/INSTALL
@@ -32,8 +32,8 @@ Installing from source
The latest Iris source release is available from
https://github.com/SciTools/iris.
-Iris makes use of a range of other libraries and python modules. These
-dependencies must be in place before you can successfully install
+Iris makes use of a range of other libraries and python modules. These
+dependencies must be in place before you can successfully install
Iris. Once you have satisfied the requirements detailed in the
``requirements`` directory, go to the root of Iris' and run::
@@ -42,8 +42,8 @@ Iris. Once you have satisfied the requirements detailed in the
In-place build - an alternative for developers
==============================================
-We are very keen to encourage contributions to Iris. For this type of
-development activity an in-place build can be useful. Once you've cloned
+We are very keen to encourage contributions to Iris. For this type of
+development activity an in-place build can be useful. Once you've cloned
the Iris git repository you can perform an in-place build with::
pip install -e .
@@ -66,6 +66,22 @@ Alternatively, a full requirements file that includes all optional dependencies
python requirements/gen_conda_requirements.py --groups all > conda_requirements.txt
+Running the tests
+'''''''''''''''''
+
+In order to run the tests, you will need to use the `test` and `docs` groups (we include the `docs` group so that you can run the pull request tests locally).
+Hence the commands change to::
+
+ python requirements/gen_conda_requirements.py --groups test docs > conda_requirements.txt
+ conda create -n my_iris_env --file conda_requirements.txt
+ conda activate my_iris_env # or whatever other name you gave it
+ pip install -e .
+
+The tests can then be run with
+
+ python setup.py test
+
+
Custom site configuration
=========================
The default site configuration values can be overridden by creating the file
From aa0fc4eebd5903befdda38d515b1cc6e34d6c2f8 Mon Sep 17 00:00:00 2001
From: Peter Killick
Date: Tue, 2 Oct 2018 09:29:24 +0100
Subject: [PATCH 50/62] Correct some failing tests
---
lib/iris/tests/unit/analysis/test_Aggregator.py | 8 ++++----
lib/iris/tests/unit/analysis/test_COUNT.py | 2 +-
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/lib/iris/tests/unit/analysis/test_Aggregator.py b/lib/iris/tests/unit/analysis/test_Aggregator.py
index 6895a7c691..e4e7b71656 100644
--- a/lib/iris/tests/unit/analysis/test_Aggregator.py
+++ b/lib/iris/tests/unit/analysis/test_Aggregator.py
@@ -283,7 +283,7 @@ def test_kwarg_pass_through_no_kwargs(self):
axis = mock.sentinel.axis
aggregator = Aggregator('', None, lazy_func=lazy_func)
aggregator.lazy_aggregate(data, axis)
- lazy_func.assert_called_once_with(data, axis)
+ lazy_func.assert_called_once_with(data, axis=axis)
def test_kwarg_pass_through_call_kwargs(self):
lazy_func = mock.Mock()
@@ -292,7 +292,7 @@ def test_kwarg_pass_through_call_kwargs(self):
kwargs = dict(wibble='wobble', foo='bar')
aggregator = Aggregator('', None, lazy_func=lazy_func)
aggregator.lazy_aggregate(data, axis, **kwargs)
- lazy_func.assert_called_once_with(data, axis, **kwargs)
+ lazy_func.assert_called_once_with(data, axis=axis, **kwargs)
def test_kwarg_pass_through_init_kwargs(self):
lazy_func = mock.Mock()
@@ -301,7 +301,7 @@ def test_kwarg_pass_through_init_kwargs(self):
kwargs = dict(wibble='wobble', foo='bar')
aggregator = Aggregator('', None, lazy_func=lazy_func, **kwargs)
aggregator.lazy_aggregate(data, axis)
- lazy_func.assert_called_once_with(data, axis, **kwargs)
+ lazy_func.assert_called_once_with(data, axis=axis, **kwargs)
def test_kwarg_pass_through_combined_kwargs(self):
lazy_func = mock.Mock()
@@ -313,7 +313,7 @@ def test_kwarg_pass_through_combined_kwargs(self):
aggregator.lazy_aggregate(data, axis, **call_kwargs)
expected_kwargs = init_kwargs.copy()
expected_kwargs.update(call_kwargs)
- lazy_func.assert_called_once_with(data, axis, **expected_kwargs)
+ lazy_func.assert_called_once_with(data, axis=axis, **expected_kwargs)
if __name__ == "__main__":
diff --git a/lib/iris/tests/unit/analysis/test_COUNT.py b/lib/iris/tests/unit/analysis/test_COUNT.py
index 882ad2921e..5422a197e0 100644
--- a/lib/iris/tests/unit/analysis/test_COUNT.py
+++ b/lib/iris/tests/unit/analysis/test_COUNT.py
@@ -46,7 +46,7 @@ def test_name(self):
self.assertEqual(COUNT.name(), 'count')
def test_no_function(self):
- exp_emsg = "function must be a callable. Got "
+ exp_emsg = r"function must be a callable. Got <.* 'NoneType'>"
with self.assertRaisesRegexp(TypeError, exp_emsg):
COUNT.lazy_aggregate(self.lazy_cube.lazy_data(), axis=0)
From f2171a14ba7b0ffa62f009f9b857d658e6f53d58 Mon Sep 17 00:00:00 2001
From: bascrezee
Date: Tue, 2 Oct 2018 13:18:11 +0200
Subject: [PATCH 51/62] Update tests.rst (#3082)
Added one line on how to test. This is mentioned in the Iris Check List in pulls.rst list, but would be good to have it here as well (useful for new contributors like me).
---
docs/iris/src/developers_guide/tests.rst | 3 +++
1 file changed, 3 insertions(+)
diff --git a/docs/iris/src/developers_guide/tests.rst b/docs/iris/src/developers_guide/tests.rst
index d2ac826f22..929073b569 100644
--- a/docs/iris/src/developers_guide/tests.rst
+++ b/docs/iris/src/developers_guide/tests.rst
@@ -3,6 +3,9 @@
Testing
*******
+The Iris tests may be run with ``python setup.py test`` which has a
+command line utility included.
+
There are three categories of tests within Iris:
- Unit tests
- Integration tests
From 01e32852c377e25d4cf881389a54700ccdc6a383 Mon Sep 17 00:00:00 2001
From: tv3141
Date: Tue, 2 Oct 2018 15:13:19 +0100
Subject: [PATCH 52/62] Add link to developer guide. (#3093)
---
README.md | 3 +++
1 file changed, 3 insertions(+)
diff --git a/README.md b/README.md
index d7b4900c2c..a6e9dd525b 100644
--- a/README.md
+++ b/README.md
@@ -44,6 +44,7 @@
+ [Documentation](#documentation)
+ [Installation](#installation)
+ [Copyright and licence](#copyright-and-licence)
++ [Contributing](#contributing)
[](TOC)
@@ -98,5 +99,7 @@ are available in [INSTALL](INSTALL).
Iris may be freely distributed, modified and used commercially under the terms
of its [GNU LGPLv3 license](COPYING.LESSER).
+# Contributing
+Information on how to contribute can be found in the [Iris developer guide](https://scitools.org.uk/iris/docs/latest/developers_guide/index.html).
(C) British Crown Copyright 2010 - 2018, Met Office
From 7ef798572c7f921c941c514ea41e242fa7ce2040 Mon Sep 17 00:00:00 2001
From: Patrick Peglar
Date: Wed, 19 Sep 2018 11:32:21 +0100
Subject: [PATCH 53/62] Combine identical test routines for pcolor +
pcolormesh.
---
lib/iris/tests/unit/plot/_blockplot_common.py | 97 +++++++++++++++++++
lib/iris/tests/unit/plot/test_pcolor.py | 63 +++---------
lib/iris/tests/unit/plot/test_pcolormesh.py | 63 +++---------
3 files changed, 125 insertions(+), 98 deletions(-)
create mode 100644 lib/iris/tests/unit/plot/_blockplot_common.py
diff --git a/lib/iris/tests/unit/plot/_blockplot_common.py b/lib/iris/tests/unit/plot/_blockplot_common.py
new file mode 100644
index 0000000000..368d44f258
--- /dev/null
+++ b/lib/iris/tests/unit/plot/_blockplot_common.py
@@ -0,0 +1,97 @@
+# (C) British Crown Copyright 2018, Met Office
+#
+# This file is part of Iris.
+#
+# Iris is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Iris is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Iris. If not, see .
+"""Common test code for `iris.plot.pcolor` and `iris.plot.pcolormesh`."""
+
+from __future__ import (absolute_import, division, print_function)
+from six.moves import (filter, input, map, range, zip) # noqa
+
+# Import iris.tests first so that some things can be initialised before
+# importing anything else.
+import iris.tests as tests
+
+import numpy as np
+
+from iris.tests.stock import simple_2d
+from iris.tests.unit.plot import MixinCoords
+
+if tests.MPL_AVAILABLE:
+ import iris.plot as iplt
+
+
+class MixinStringCoordPlot(object):
+ # Mixin for common string-coord tests on pcolor/pcolormesh.
+ # To use, make a class that inherits from this *and*
+ # :class:`iris.tests.unit.plot.TestGraphicStringCoord`,
+ # and defines "self.blockplot_func()", to return the `iris.plot` function.
+ def test_yaxis_labels(self):
+ self.blockplot_func()(self.cube, coords=('bar', 'str_coord'))
+ self.assertBoundsTickLabels('yaxis')
+
+ def test_xaxis_labels(self):
+ self.blockplot_func()(self.cube, coords=('str_coord', 'bar'))
+ self.assertBoundsTickLabels('xaxis')
+
+ def test_xaxis_labels_with_axes(self):
+ import matplotlib.pyplot as plt
+ fig = plt.figure()
+ ax = fig.add_subplot(111)
+ ax.set_xlim(0, 3)
+ self.blockplot_func()(self.cube, coords=('str_coord', 'bar'), axes=ax)
+ plt.close(fig)
+ self.assertPointsTickLabels('xaxis', ax)
+
+ def test_yaxis_labels_with_axes(self):
+ import matplotlib.pyplot as plt
+ fig = plt.figure()
+ ax = fig.add_subplot(111)
+ ax.set_ylim(0, 3)
+ self.blockplot_func()(self.cube, axes=ax, coords=('bar', 'str_coord'))
+ plt.close(fig)
+ self.assertPointsTickLabels('yaxis', ax)
+
+ def test_geoaxes_exception(self):
+ import matplotlib.pyplot as plt
+ fig = plt.figure()
+ ax = fig.add_subplot(111)
+ self.assertRaises(TypeError, self.blockplot_func(),
+ self.lat_lon_cube, axes=ax)
+ plt.close(fig)
+
+
+class Mixin2dCoordsPlot(MixinCoords):
+ # Mixin for common coordinate tests on pcolor/pcolormesh.
+ # To use, make a class that inherits from this *and*
+ # :class:`iris.tests.IrisTest`,
+ # and defines "self.blockplot_func()", to return the `iris.plot` function.
+ def blockplot_setup(self):
+ # We have a 2d cube with dimensionality (bar: 3; foo: 4)
+ self.cube = simple_2d(with_bounds=True)
+ coord = self.cube.coord('foo')
+ self.foo = coord.contiguous_bounds()
+ self.foo_index = np.arange(coord.points.size + 1)
+ coord = self.cube.coord('bar')
+ self.bar = coord.contiguous_bounds()
+ self.bar_index = np.arange(coord.points.size + 1)
+ self.data = self.cube.data
+ self.dataT = self.data.T
+ self.draw_func = self.blockplot_func()
+ patch_target_name = 'matplotlib.pyplot.' + self.draw_func.__name__
+ self.mpl_patch = self.patch(patch_target_name)
+
+
+if __name__ == "__main__":
+ tests.main()
diff --git a/lib/iris/tests/unit/plot/test_pcolor.py b/lib/iris/tests/unit/plot/test_pcolor.py
index 46219965f9..ef681b3233 100644
--- a/lib/iris/tests/unit/plot/test_pcolor.py
+++ b/lib/iris/tests/unit/plot/test_pcolor.py
@@ -1,4 +1,4 @@
-# (C) British Crown Copyright 2014 - 2016, Met Office
+# (C) British Crown Copyright 2014 - 2018, Met Office
#
# This file is part of Iris.
#
@@ -26,64 +26,29 @@
import numpy as np
from iris.tests.stock import simple_2d
-from iris.tests.unit.plot import TestGraphicStringCoord, MixinCoords
+import iris.plot
+from iris.tests.unit.plot import TestGraphicStringCoord
+from iris.tests.unit.plot._blockplot_common import \
+ MixinStringCoordPlot, Mixin2dCoordsPlot
+
if tests.MPL_AVAILABLE:
import iris.plot as iplt
@tests.skip_plot
-class TestStringCoordPlot(TestGraphicStringCoord):
- def test_yaxis_labels(self):
- iplt.pcolor(self.cube, coords=('bar', 'str_coord'))
- self.assertBoundsTickLabels('yaxis')
-
- def test_xaxis_labels(self):
- iplt.pcolor(self.cube, coords=('str_coord', 'bar'))
- self.assertBoundsTickLabels('xaxis')
-
- def test_xaxis_labels_with_axes(self):
- import matplotlib.pyplot as plt
- fig = plt.figure()
- ax = fig.add_subplot(111)
- ax.set_xlim(0, 3)
- iplt.pcolor(self.cube, coords=('str_coord', 'bar'), axes=ax)
- plt.close(fig)
- self.assertPointsTickLabels('xaxis', ax)
-
- def test_yaxis_labels_with_axes(self):
- import matplotlib.pyplot as plt
- fig = plt.figure()
- ax = fig.add_subplot(111)
- ax.set_ylim(0, 3)
- iplt.pcolor(self.cube, axes=ax, coords=('bar', 'str_coord'))
- plt.close(fig)
- self.assertPointsTickLabels('yaxis', ax)
-
- def test_geoaxes_exception(self):
- import matplotlib.pyplot as plt
- fig = plt.figure()
- ax = fig.add_subplot(111)
- self.assertRaises(TypeError, iplt.pcolor,
- self.lat_lon_cube, axes=ax)
- plt.close(fig)
+class TestStringCoordPlot(MixinStringCoordPlot, TestGraphicStringCoord):
+ def blockplot_func(self):
+ return iris.plot.pcolor
@tests.skip_plot
-class TestCoords(tests.IrisTest, MixinCoords):
+class Test2dCoords(tests.IrisTest, Mixin2dCoordsPlot):
def setUp(self):
- # We have a 2d cube with dimensionality (bar: 3; foo: 4)
- self.cube = simple_2d(with_bounds=True)
- coord = self.cube.coord('foo')
- self.foo = coord.contiguous_bounds()
- self.foo_index = np.arange(coord.points.size + 1)
- coord = self.cube.coord('bar')
- self.bar = coord.contiguous_bounds()
- self.bar_index = np.arange(coord.points.size + 1)
- self.data = self.cube.data
- self.dataT = self.data.T
- self.mpl_patch = self.patch('matplotlib.pyplot.pcolor')
- self.draw_func = iplt.pcolor
+ self.blockplot_setup()
+
+ def blockplot_func(self):
+ return iris.plot.pcolor
if __name__ == "__main__":
diff --git a/lib/iris/tests/unit/plot/test_pcolormesh.py b/lib/iris/tests/unit/plot/test_pcolormesh.py
index fb4ceffe28..a452a7af74 100644
--- a/lib/iris/tests/unit/plot/test_pcolormesh.py
+++ b/lib/iris/tests/unit/plot/test_pcolormesh.py
@@ -1,4 +1,4 @@
-# (C) British Crown Copyright 2014 - 2016, Met Office
+# (C) British Crown Copyright 2014 - 2018, Met Office
#
# This file is part of Iris.
#
@@ -26,64 +26,29 @@
import numpy as np
from iris.tests.stock import simple_2d
-from iris.tests.unit.plot import TestGraphicStringCoord, MixinCoords
+import iris.plot
+from iris.tests.unit.plot import TestGraphicStringCoord
+from iris.tests.unit.plot._blockplot_common import \
+ MixinStringCoordPlot, Mixin2dCoordsPlot
+
if tests.MPL_AVAILABLE:
import iris.plot as iplt
@tests.skip_plot
-class TestStringCoordPlot(TestGraphicStringCoord):
- def test_yaxis_labels(self):
- iplt.pcolormesh(self.cube, coords=('bar', 'str_coord'))
- self.assertBoundsTickLabels('yaxis')
-
- def test_xaxis_labels(self):
- iplt.pcolormesh(self.cube, coords=('str_coord', 'bar'))
- self.assertBoundsTickLabels('xaxis')
-
- def test_xaxis_labels_with_axes(self):
- import matplotlib.pyplot as plt
- fig = plt.figure()
- ax = fig.add_subplot(111)
- ax.set_xlim(0, 3)
- iplt.pcolormesh(self.cube, axes=ax, coords=('str_coord', 'bar'),)
- plt.close(fig)
- self.assertPointsTickLabels('xaxis', ax)
-
- def test_yaxis_labels_with_axes(self):
- import matplotlib.pyplot as plt
- fig = plt.figure()
- ax = fig.add_subplot(111)
- ax.set_ylim(0, 3)
- iplt.pcolormesh(self.cube, axes=ax, coords=('bar', 'str_coord'))
- plt.close(fig)
- self.assertPointsTickLabels('yaxis', ax)
-
- def test_geoaxes_exception(self):
- import matplotlib.pyplot as plt
- fig = plt.figure()
- ax = fig.add_subplot(111)
- self.assertRaises(TypeError, iplt.pcolormesh,
- self.lat_lon_cube, axes=ax)
- plt.close(fig)
+class TestStringCoordPlot(MixinStringCoordPlot, TestGraphicStringCoord):
+ def blockplot_func(self):
+ return iris.plot.pcolormesh
@tests.skip_plot
-class TestCoords(tests.IrisTest, MixinCoords):
+class Test2dCoords(tests.IrisTest, Mixin2dCoordsPlot):
def setUp(self):
- # We have a 2d cube with dimensionality (bar: 3; foo: 4)
- self.cube = simple_2d(with_bounds=True)
- coord = self.cube.coord('foo')
- self.foo = coord.contiguous_bounds()
- self.foo_index = np.arange(coord.points.size + 1)
- coord = self.cube.coord('bar')
- self.bar = coord.contiguous_bounds()
- self.bar_index = np.arange(coord.points.size + 1)
- self.data = self.cube.data
- self.dataT = self.data.T
- self.mpl_patch = self.patch('matplotlib.pyplot.pcolormesh')
- self.draw_func = iplt.pcolormesh
+ self.blockplot_setup()
+
+ def blockplot_func(self):
+ return iris.plot.pcolormesh
if __name__ == "__main__":
From a4b3fb77217147ee48c031ce15751499f793b410 Mon Sep 17 00:00:00 2001
From: Patrick Peglar
Date: Wed, 3 Oct 2018 12:43:12 +0100
Subject: [PATCH 54/62] Test 'contiguity_tolerance' use in iris.plot.pcolor and
pcolormesh.
---
lib/iris/tests/unit/plot/_blockplot_common.py | 30 +++++++++++++++++--
lib/iris/tests/unit/plot/test_pcolor.py | 17 ++++++++---
lib/iris/tests/unit/plot/test_pcolormesh.py | 17 ++++++++---
3 files changed, 53 insertions(+), 11 deletions(-)
diff --git a/lib/iris/tests/unit/plot/_blockplot_common.py b/lib/iris/tests/unit/plot/_blockplot_common.py
index 368d44f258..dc69a5c991 100644
--- a/lib/iris/tests/unit/plot/_blockplot_common.py
+++ b/lib/iris/tests/unit/plot/_blockplot_common.py
@@ -25,12 +25,10 @@
import numpy as np
+from iris.tests import mock
from iris.tests.stock import simple_2d
from iris.tests.unit.plot import MixinCoords
-if tests.MPL_AVAILABLE:
- import iris.plot as iplt
-
class MixinStringCoordPlot(object):
# Mixin for common string-coord tests on pcolor/pcolormesh.
@@ -93,5 +91,31 @@ def blockplot_setup(self):
self.mpl_patch = self.patch(patch_target_name)
+class Mixin2dCoordsContigTol(object):
+ # Mixin for contiguity tolerance argument to pcolor/pcolormesh.
+ # To use, make a class that inherits from this *and*
+ # :class:`iris.tests.IrisTest`,
+ # and defines "self.blockplot_func()", to return the `iris.plot` function,
+ # and defines "self.additional_kwargs" for expected extra call args.
+ def test_contig_tol(self):
+ # Patch the inner call to ensure contiguity_tolerance is passed.
+ cube_argument = mock.sentinel.passed_arg
+ expected_result = mock.sentinel.returned_value
+ blockplot_patch = self.patch(
+ 'iris.plot._draw_2d_from_bounds',
+ mock.Mock(return_value=expected_result))
+ # Make the call
+ draw_func = self.blockplot_func()
+ other_kwargs = self.additional_kwargs
+ result = draw_func(cube_argument, contiguity_tolerance=0.0123)
+ drawfunc_name = draw_func.__name__
+ # Check details of the call that was made.
+ self.assertEqual(
+ blockplot_patch.call_args_list,
+ [mock.call(drawfunc_name, cube_argument,
+ contiguity_tolerance=0.0123, **other_kwargs)])
+ self.assertEqual(result, expected_result)
+
+
if __name__ == "__main__":
tests.main()
diff --git a/lib/iris/tests/unit/plot/test_pcolor.py b/lib/iris/tests/unit/plot/test_pcolor.py
index ef681b3233..da9a461ade 100644
--- a/lib/iris/tests/unit/plot/test_pcolor.py
+++ b/lib/iris/tests/unit/plot/test_pcolor.py
@@ -26,20 +26,20 @@
import numpy as np
from iris.tests.stock import simple_2d
-import iris.plot
from iris.tests.unit.plot import TestGraphicStringCoord
from iris.tests.unit.plot._blockplot_common import \
- MixinStringCoordPlot, Mixin2dCoordsPlot
+ MixinStringCoordPlot, Mixin2dCoordsPlot, Mixin2dCoordsContigTol
if tests.MPL_AVAILABLE:
import iris.plot as iplt
+ PLOT_FUNCTION_TO_TEST = iplt.pcolor
@tests.skip_plot
class TestStringCoordPlot(MixinStringCoordPlot, TestGraphicStringCoord):
def blockplot_func(self):
- return iris.plot.pcolor
+ return PLOT_FUNCTION_TO_TEST
@tests.skip_plot
@@ -48,7 +48,16 @@ def setUp(self):
self.blockplot_setup()
def blockplot_func(self):
- return iris.plot.pcolor
+ return PLOT_FUNCTION_TO_TEST
+
+
+@tests.skip_plot
+class Test2dContigTol(tests.IrisTest, Mixin2dCoordsContigTol):
+ # Extra call kwargs expected.
+ additional_kwargs = dict(antialiased=True, snap=False)
+
+ def blockplot_func(self):
+ return PLOT_FUNCTION_TO_TEST
if __name__ == "__main__":
diff --git a/lib/iris/tests/unit/plot/test_pcolormesh.py b/lib/iris/tests/unit/plot/test_pcolormesh.py
index a452a7af74..613a559415 100644
--- a/lib/iris/tests/unit/plot/test_pcolormesh.py
+++ b/lib/iris/tests/unit/plot/test_pcolormesh.py
@@ -26,20 +26,20 @@
import numpy as np
from iris.tests.stock import simple_2d
-import iris.plot
from iris.tests.unit.plot import TestGraphicStringCoord
from iris.tests.unit.plot._blockplot_common import \
- MixinStringCoordPlot, Mixin2dCoordsPlot
+ MixinStringCoordPlot, Mixin2dCoordsPlot, Mixin2dCoordsContigTol
if tests.MPL_AVAILABLE:
import iris.plot as iplt
+ PLOT_FUNCTION_TO_TEST = iplt.pcolormesh
@tests.skip_plot
class TestStringCoordPlot(MixinStringCoordPlot, TestGraphicStringCoord):
def blockplot_func(self):
- return iris.plot.pcolormesh
+ return PLOT_FUNCTION_TO_TEST
@tests.skip_plot
@@ -48,7 +48,16 @@ def setUp(self):
self.blockplot_setup()
def blockplot_func(self):
- return iris.plot.pcolormesh
+ return PLOT_FUNCTION_TO_TEST
+
+
+@tests.skip_plot
+class Test2dContigTol(tests.IrisTest, Mixin2dCoordsContigTol):
+ # Extra call kwargs expected -- unlike 'pcolor', there are none.
+ additional_kwargs = {}
+
+ def blockplot_func(self):
+ return PLOT_FUNCTION_TO_TEST
if __name__ == "__main__":
From 5f2aadc4c00278659be1cdd3e2035108314e5c1d Mon Sep 17 00:00:00 2001
From: Peter Killick
Date: Wed, 3 Oct 2018 13:13:14 +0100
Subject: [PATCH 55/62] Unpin dask
---
requirements/core.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/requirements/core.txt b/requirements/core.txt
index c22a43a36b..09ffb8954c 100644
--- a/requirements/core.txt
+++ b/requirements/core.txt
@@ -7,7 +7,7 @@ cartopy
#conda: proj4<5
cf_units>=2
cftime
-dask[array]==0.18.1 #conda: dask==0.18.1
+dask[array] #conda: dask
matplotlib>=2,<3
netcdf4
numpy>=1.14
From c5be03eb1c0c6ba3b4e9db020d1ec54c15f18f3c Mon Sep 17 00:00:00 2001
From: Peter Killick
Date: Wed, 3 Oct 2018 13:15:13 +0100
Subject: [PATCH 56/62] Handle printing bounds of long time interval coords
(#3140)
* Handle printing time bounds
* Whatsnew, whitespace fix for test result
---
...Aug-20_print-long-time-interval-bounds.txt | 2 ++
lib/iris/coords.py | 6 +++++-
lib/iris/tests/unit/coords/test_Coord.py | 20 +++++++++++++++++++
3 files changed, 27 insertions(+), 1 deletion(-)
create mode 100644 docs/iris/src/whatsnew/contributions_2.2.0/bugfix_2018-Aug-20_print-long-time-interval-bounds.txt
diff --git a/docs/iris/src/whatsnew/contributions_2.2.0/bugfix_2018-Aug-20_print-long-time-interval-bounds.txt b/docs/iris/src/whatsnew/contributions_2.2.0/bugfix_2018-Aug-20_print-long-time-interval-bounds.txt
new file mode 100644
index 0000000000..3651598b72
--- /dev/null
+++ b/docs/iris/src/whatsnew/contributions_2.2.0/bugfix_2018-Aug-20_print-long-time-interval-bounds.txt
@@ -0,0 +1,2 @@
+* Fixed a bug that prevented printing time coordinates with bounds when the time
+ coordinate was measured on a long interval (that is, ``months`` or ``years``).
\ No newline at end of file
diff --git a/lib/iris/coords.py b/lib/iris/coords.py
index 42882fbc2c..6402e73263 100644
--- a/lib/iris/coords.py
+++ b/lib/iris/coords.py
@@ -782,7 +782,11 @@ def __str__(self):
points = self._str_dates(self.points)
bounds = ''
if self.has_bounds():
- bounds = ', bounds=' + self._str_dates(self.bounds)
+ if self.units.is_long_time_interval():
+ bounds_vals = self.bounds
+ else:
+ bounds_vals = self._str_dates(self.bounds)
+ bounds = ', bounds={vals}'.format(vals=bounds_vals)
result = fmt.format(self=self, cls=type(self).__name__,
points=points, bounds=bounds,
other_metadata=self._repr_other_metadata())
diff --git a/lib/iris/tests/unit/coords/test_Coord.py b/lib/iris/tests/unit/coords/test_Coord.py
index 8cf79caad3..27b468044d 100644
--- a/lib/iris/tests/unit/coords/test_Coord.py
+++ b/lib/iris/tests/unit/coords/test_Coord.py
@@ -677,6 +677,17 @@ def test_short_time_interval(self):
result = coord.__str__()
self.assertEqual(expected, result)
+ def test_short_time_interval__bounded(self):
+ coord = DimCoord([5, 6], standard_name='time',
+ units='days since 1970-01-01')
+ coord.guess_bounds()
+ expected = ("DimCoord([1970-01-06 00:00:00, 1970-01-07 00:00:00], "
+ "bounds=[[1970-01-05 12:00:00, 1970-01-06 12:00:00],\n"
+ " [1970-01-06 12:00:00, 1970-01-07 12:00:00]], "
+ "standard_name='time', calendar='gregorian')")
+ result = coord.__str__()
+ self.assertEqual(expected, result)
+
def test_long_time_interval(self):
coord = DimCoord([5], standard_name='time',
units='years since 1970-01-01')
@@ -684,6 +695,15 @@ def test_long_time_interval(self):
result = coord.__str__()
self.assertEqual(expected, result)
+ def test_long_time_interval__bounded(self):
+ coord = DimCoord([5, 6], standard_name='time',
+ units='years since 1970-01-01')
+ coord.guess_bounds()
+ expected = ("DimCoord([5 6], bounds=[[4.5 5.5]\n [5.5 6.5]], "
+ "standard_name='time', calendar='gregorian')")
+ result = coord.__str__()
+ self.assertEqual(expected, result)
+
def test_non_time_unit(self):
coord = DimCoord([1.])
expected = repr(coord)
From e2c47f9580a5a3354d54185d3586302e8982b403 Mon Sep 17 00:00:00 2001
From: Ruth Comer
Date: Wed, 3 Oct 2018 14:46:43 +0100
Subject: [PATCH 57/62] iris.util.reverse on cubes (#3155)
* make cube reversing official
* review: test conventions, etc.
* review: enable coord specification
* add whatsnew
* review: AssertRaises --> AssertRaisesRegexp
* cube error handling
---
.../newfeature_2018-Oct-03_reverse_cube.txt | 1 +
lib/iris/tests/test_util.py | 25 ---
lib/iris/tests/unit/util/test_reverse.py | 185 ++++++++++++++++++
lib/iris/util.py | 50 +++--
4 files changed, 224 insertions(+), 37 deletions(-)
create mode 100644 docs/iris/src/whatsnew/contributions_2.2.0/newfeature_2018-Oct-03_reverse_cube.txt
create mode 100644 lib/iris/tests/unit/util/test_reverse.py
diff --git a/docs/iris/src/whatsnew/contributions_2.2.0/newfeature_2018-Oct-03_reverse_cube.txt b/docs/iris/src/whatsnew/contributions_2.2.0/newfeature_2018-Oct-03_reverse_cube.txt
new file mode 100644
index 0000000000..c7e3bef8a4
--- /dev/null
+++ b/docs/iris/src/whatsnew/contributions_2.2.0/newfeature_2018-Oct-03_reverse_cube.txt
@@ -0,0 +1 @@
+* :func:`iris.util.reverse` can now be used to reverse a cube by specifying one or more coordinates.
diff --git a/lib/iris/tests/test_util.py b/lib/iris/tests/test_util.py
index 97bb4d627d..d8cfcf648c 100644
--- a/lib/iris/tests/test_util.py
+++ b/lib/iris/tests/test_util.py
@@ -93,31 +93,6 @@ def test_monotonic_strict(self):
self.assertMonotonic(b)
-class TestReverse(tests.IrisTest):
- def test_simple(self):
- a = np.arange(12).reshape(3, 4)
- np.testing.assert_array_equal(a[::-1], iris.util.reverse(a, 0))
- np.testing.assert_array_equal(a[::-1, ::-1], iris.util.reverse(a, [0, 1]))
- np.testing.assert_array_equal(a[:, ::-1], iris.util.reverse(a, 1))
- np.testing.assert_array_equal(a[:, ::-1], iris.util.reverse(a, [1]))
- self.assertRaises(ValueError, iris.util.reverse, a, [])
- self.assertRaises(ValueError, iris.util.reverse, a, -1)
- self.assertRaises(ValueError, iris.util.reverse, a, 10)
- self.assertRaises(ValueError, iris.util.reverse, a, [-1])
- self.assertRaises(ValueError, iris.util.reverse, a, [0, -1])
-
- def test_single(self):
- a = np.arange(36).reshape(3, 4, 3)
- np.testing.assert_array_equal(a[::-1], iris.util.reverse(a, 0))
- np.testing.assert_array_equal(a[::-1, ::-1], iris.util.reverse(a, [0, 1]))
- np.testing.assert_array_equal(a[:, ::-1, ::-1], iris.util.reverse(a, [1, 2]))
- np.testing.assert_array_equal(a[..., ::-1], iris.util.reverse(a, 2))
- self.assertRaises(ValueError, iris.util.reverse, a, -1)
- self.assertRaises(ValueError, iris.util.reverse, a, 10)
- self.assertRaises(ValueError, iris.util.reverse, a, [-1])
- self.assertRaises(ValueError, iris.util.reverse, a, [0, -1])
-
-
class TestClipString(tests.IrisTest):
def setUp(self):
self.test_string = "Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum."
diff --git a/lib/iris/tests/unit/util/test_reverse.py b/lib/iris/tests/unit/util/test_reverse.py
new file mode 100644
index 0000000000..f5a21d259b
--- /dev/null
+++ b/lib/iris/tests/unit/util/test_reverse.py
@@ -0,0 +1,185 @@
+# (C) British Crown Copyright 2018, Met Office
+#
+# This file is part of Iris.
+#
+# Iris is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Lesser General Public License as published by the
+# Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# Iris is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public License
+# along with Iris. If not, see .
+"""Test function :func:`iris.util.reverse`."""
+
+from __future__ import (absolute_import, division, print_function)
+from six.moves import (filter, input, map, range, zip) # noqa
+
+# Import iris.tests first so that some things can be initialised before
+# importing anything else.
+import iris.tests as tests
+
+import unittest
+
+import iris
+from iris.util import reverse
+import numpy as np
+
+
+class Test_array(tests.IrisTest):
+ def test_simple_array(self):
+ a = np.arange(12).reshape(3, 4)
+ self.assertArrayEqual(a[::-1], reverse(a, 0))
+ self.assertArrayEqual(a[::-1, ::-1], reverse(a, [0, 1]))
+ self.assertArrayEqual(a[:, ::-1], reverse(a, 1))
+ self.assertArrayEqual(a[:, ::-1], reverse(a, [1]))
+
+ msg = 'Reverse was expecting a single axis or a 1d array *'
+ with self.assertRaisesRegexp(ValueError, msg):
+ reverse(a, [])
+
+ msg = 'An axis value out of range for the number of dimensions *'
+ with self.assertRaisesRegexp(ValueError, msg):
+ reverse(a, -1)
+ with self.assertRaisesRegexp(ValueError, msg):
+ reverse(a, 10)
+ with self.assertRaisesRegexp(ValueError, msg):
+ reverse(a, [-1])
+ with self.assertRaisesRegexp(ValueError, msg):
+ reverse(a, [0, -1])
+
+ msg = 'To reverse an array, provide an int *'
+ with self.assertRaisesRegexp(TypeError, msg):
+ reverse(a, 'latitude')
+
+ def test_single_array(self):
+ a = np.arange(36).reshape(3, 4, 3)
+ self.assertArrayEqual(a[::-1], reverse(a, 0))
+ self.assertArrayEqual(a[::-1, ::-1], reverse(a, [0, 1]))
+ self.assertArrayEqual(a[:, ::-1, ::-1], reverse(a, [1, 2]))
+ self.assertArrayEqual(a[..., ::-1], reverse(a, 2))
+
+ msg = 'Reverse was expecting a single axis or a 1d array *'
+ with self.assertRaisesRegexp(ValueError, msg):
+ reverse(a, [])
+
+ msg = 'An axis value out of range for the number of dimensions *'
+ with self.assertRaisesRegexp(ValueError, msg):
+ reverse(a, -1)
+ with self.assertRaisesRegexp(ValueError, msg):
+ reverse(a, 10)
+ with self.assertRaisesRegexp(ValueError, msg):
+ reverse(a, [-1])
+ with self.assertRaisesRegexp(ValueError, msg):
+ reverse(a, [0, -1])
+
+ with self.assertRaisesRegexp(
+ TypeError, 'To reverse an array, provide an int *'):
+ reverse(a, 'latitude')
+
+
+class Test_cube(tests.IrisTest):
+ def setUp(self):
+ # On this cube pair, the coordinates to perform operations on have
+ # matching long names but the points array on one cube is reversed
+ # with respect to that on the other.
+ data = np.arange(12).reshape(3, 4)
+ self.a1 = iris.coords.DimCoord([1, 2, 3], long_name='a')
+ self.b1 = iris.coords.DimCoord([1, 2, 3, 4], long_name='b')
+ a2 = iris.coords.DimCoord([3, 2, 1], long_name='a')
+ b2 = iris.coords.DimCoord([4, 3, 2, 1], long_name='b')
+ self.span = iris.coords.AuxCoord(np.arange(12).reshape(3, 4),
+ long_name='spanning')
+
+ self.cube1 = iris.cube.Cube(
+ data, dim_coords_and_dims=[(self.a1, 0), (self.b1, 1)],
+ aux_coords_and_dims=[(self.span, (0, 1))])
+
+ self.cube2 = iris.cube.Cube(
+ data, dim_coords_and_dims=[(a2, 0), (b2, 1)])
+
+ def test_cube_dim(self):
+ cube1_reverse0 = reverse(self.cube1, 0)
+ cube1_reverse1 = reverse(self.cube1, 1)
+ cube1_reverse_both = reverse(self.cube1, (0, 1))
+
+ self.assertArrayEqual(self.cube1.data[::-1], cube1_reverse0.data)
+ self.assertArrayEqual(self.cube2.coord('a').points,
+ cube1_reverse0.coord('a').points)
+ self.assertArrayEqual(self.cube1.coord('b').points,
+ cube1_reverse0.coord('b').points)
+
+ self.assertArrayEqual(self.cube1.data[:, ::-1], cube1_reverse1.data)
+ self.assertArrayEqual(self.cube1.coord('a').points,
+ cube1_reverse1.coord('a').points)
+ self.assertArrayEqual(self.cube2.coord('b').points,
+ cube1_reverse1.coord('b').points)
+
+ self.assertArrayEqual(self.cube1.data[::-1, ::-1],
+ cube1_reverse_both.data)
+ self.assertArrayEqual(self.cube2.coord('a').points,
+ cube1_reverse_both.coord('a').points)
+ self.assertArrayEqual(self.cube2.coord('b').points,
+ cube1_reverse_both.coord('b').points)
+
+ def test_cube_coord(self):
+ cube1_reverse0 = reverse(self.cube1, self.a1)
+ cube1_reverse1 = reverse(self.cube1, 'b')
+ cube1_reverse_both = reverse(self.cube1, (self.a1, self.b1))
+ cube1_reverse_spanning = reverse(self.cube1, 'spanning')
+
+ self.assertArrayEqual(self.cube1.data[::-1], cube1_reverse0.data)
+ self.assertArrayEqual(self.cube2.coord('a').points,
+ cube1_reverse0.coord('a').points)
+ self.assertArrayEqual(self.cube1.coord('b').points,
+ cube1_reverse0.coord('b').points)
+
+ self.assertArrayEqual(self.cube1.data[:, ::-1], cube1_reverse1.data)
+ self.assertArrayEqual(self.cube1.coord('a').points,
+ cube1_reverse1.coord('a').points)
+ self.assertArrayEqual(self.cube2.coord('b').points,
+ cube1_reverse1.coord('b').points)
+
+ self.assertArrayEqual(self.cube1.data[::-1, ::-1],
+ cube1_reverse_both.data)
+ self.assertArrayEqual(self.cube2.coord('a').points,
+ cube1_reverse_both.coord('a').points)
+ self.assertArrayEqual(self.cube2.coord('b').points,
+ cube1_reverse_both.coord('b').points)
+
+ self.assertArrayEqual(self.cube1.data[::-1, ::-1],
+ cube1_reverse_spanning.data)
+ self.assertArrayEqual(self.cube2.coord('a').points,
+ cube1_reverse_spanning.coord('a').points)
+ self.assertArrayEqual(self.cube2.coord('b').points,
+ cube1_reverse_spanning.coord('b').points)
+ self.assertArrayEqual(
+ self.span.points[::-1, ::-1],
+ cube1_reverse_spanning.coord('spanning').points)
+
+ msg = 'Expected to find exactly 1 latitude coordinate, but found none.'
+ with self.assertRaisesRegexp(
+ iris.exceptions.CoordinateNotFoundError, msg):
+ reverse(self.cube1, 'latitude')
+
+ msg = 'Reverse was expecting a single axis or a 1d array *'
+ with self.assertRaisesRegexp(ValueError, msg):
+ reverse(self.cube1, [])
+
+ msg = ('coords_or_dims must be int, str, coordinate or sequence of '
+ 'these. Got cube.')
+ with self.assertRaisesRegexp(TypeError, msg):
+ reverse(self.cube1, self.cube1)
+
+ msg = ('coords_or_dims must be int, str, coordinate or sequence of '
+ 'these.')
+ with self.assertRaisesRegexp(TypeError, msg):
+ reverse(self.cube1, 3.)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/lib/iris/util.py b/lib/iris/util.py
index 4f4c42dc4b..7e5b2c36a8 100644
--- a/lib/iris/util.py
+++ b/lib/iris/util.py
@@ -41,6 +41,7 @@
import iris
import iris.exceptions
+import iris.cube
def broadcast_to_shape(array, shape, dim_map):
@@ -406,16 +407,19 @@ def between(lh, rh, lh_inclusive=True, rh_inclusive=True):
return lambda c: lh < c < rh
-def reverse(array, axes):
+def reverse(cube_or_array, coords_or_dims):
"""
- Reverse the array along the given axes.
+ Reverse the cube or array along the given dimensions.
Args:
- * array
- The array to reverse
- * axes
- A single value or array of values of axes to reverse
+ * cube_or_array: :class:`iris.cube.Cube` or :class:`numpy.ndarray`
+ The cube or array to reverse.
+ * coords_or_dims: int, str, :class:`iris.coords.Coord` or sequence of these
+ Identify one or more dimensions to reverse. If cube_or_array is a
+ numpy array, use int or a sequence of ints, as in the examples below.
+ If cube_or_array is a Cube, a Coord or coordinate name (or sequence of
+ these) may be specified instead.
::
@@ -447,20 +451,42 @@ def reverse(array, axes):
[15 14 13 12]]]
"""
- index = [slice(None, None)] * array.ndim
- axes = np.array(axes, ndmin=1)
- if axes.ndim != 1:
+ index = [slice(None, None)] * cube_or_array.ndim
+
+ if isinstance(coords_or_dims, iris.cube.Cube):
+ raise TypeError('coords_or_dims must be int, str, coordinate or '
+ 'sequence of these. Got cube.')
+
+ if iris.cube._is_single_item(coords_or_dims):
+ coords_or_dims = [coords_or_dims]
+
+ axes = set()
+ for coord_or_dim in coords_or_dims:
+ if isinstance(coord_or_dim, int):
+ axes.add(coord_or_dim)
+ elif isinstance(cube_or_array, np.ndarray):
+ raise TypeError(
+ 'To reverse an array, provide an int or sequence of ints.')
+ else:
+ try:
+ axes.update(cube_or_array.coord_dims(coord_or_dim))
+ except AttributeError:
+ raise TypeError('coords_or_dims must be int, str, coordinate '
+ 'or sequence of these.')
+
+ axes = np.array(list(axes), ndmin=1)
+ if axes.ndim != 1 or axes.size == 0:
raise ValueError('Reverse was expecting a single axis or a 1d array '
'of axes, got %r' % axes)
- if np.min(axes) < 0 or np.max(axes) > array.ndim-1:
+ if np.min(axes) < 0 or np.max(axes) > cube_or_array.ndim-1:
raise ValueError('An axis value out of range for the number of '
'dimensions from the given array (%s) was received. '
- 'Got: %r' % (array.ndim, axes))
+ 'Got: %r' % (cube_or_array.ndim, axes))
for axis in axes:
index[axis] = slice(None, None, -1)
- return array[tuple(index)]
+ return cube_or_array[tuple(index)]
def monotonic(array, strict=False, return_direction=False):
From a41db2d786e1b0fc4dcfc5d1648f14ad934a86ee Mon Sep 17 00:00:00 2001
From: hdyson
Date: Wed, 3 Oct 2018 15:59:15 +0100
Subject: [PATCH 58/62] Improved Aux factory error handling: better message,
delivered earlier (#3182)
* Tests for expected behaviour
* Raise error if aux factory relies on a coordinate external to cube
* Include coordinate name in error message
* Don't check whether dependencies that are "None" are in the coords.
* Review changes: check cube name in error and variable rename
* Truncated variable for flake8
---
lib/iris/cube.py | 6 ++++++
lib/iris/tests/unit/cube/test_Cube.py | 27 ++++++++++++++++++++++++++-
2 files changed, 32 insertions(+), 1 deletion(-)
diff --git a/lib/iris/cube.py b/lib/iris/cube.py
index 9c42299c42..4bd947bca2 100644
--- a/lib/iris/cube.py
+++ b/lib/iris/cube.py
@@ -994,6 +994,12 @@ def add_aux_factory(self, aux_factory):
if not isinstance(aux_factory, iris.aux_factory.AuxCoordFactory):
raise TypeError('Factory must be a subclass of '
'iris.aux_factory.AuxCoordFactory.')
+ cube_coords = self.coords()
+ for dependency in aux_factory.dependencies:
+ ref_coord = aux_factory.dependencies[dependency]
+ if ref_coord is not None and ref_coord not in cube_coords:
+ msg = "{} coordinate for factory is not present on cube {}"
+ raise ValueError(msg.format(ref_coord.name(), self.name()))
self._aux_factories.append(aux_factory)
def add_cell_measure(self, cell_measure, data_dims=None):
diff --git a/lib/iris/tests/unit/cube/test_Cube.py b/lib/iris/tests/unit/cube/test_Cube.py
index 5633417c80..dcc3eca7cb 100644
--- a/lib/iris/tests/unit/cube/test_Cube.py
+++ b/lib/iris/tests/unit/cube/test_Cube.py
@@ -34,9 +34,9 @@
import iris.aux_factory
import iris.coords
import iris.exceptions
-from iris import FUTURE
from iris.analysis import WeightedAggregator, Aggregator
from iris.analysis import MEAN
+from iris.aux_factory import HybridHeightFactory
from iris.cube import Cube
from iris.coords import AuxCoord, DimCoord, CellMeasure
from iris.exceptions import (CoordinateNotFoundError, CellMeasureNotFoundError,
@@ -1546,6 +1546,31 @@ def test_add_cell_measure(self):
cube.add_cell_measure(a_cell_measure, [0, 1])
self.assertEqual(cube.cell_measure('area'), a_cell_measure)
+ def test_add_valid_aux_factory(self):
+ cube = Cube(np.arange(8).reshape(2, 2, 2))
+ delta = AuxCoord(points=[0, 1], long_name='delta', units='m')
+ sigma = AuxCoord(points=[0, 1], long_name='sigma')
+ orog = AuxCoord(np.arange(4).reshape(2, 2), units='m')
+ cube.add_aux_coord(delta, 0)
+ cube.add_aux_coord(sigma, 0)
+ cube.add_aux_coord(orog, (1, 2))
+ factory = HybridHeightFactory(delta=delta, sigma=sigma, orography=orog)
+ self.assertIsNone(cube.add_aux_factory(factory))
+
+ def test_error_for_add_invalid_aux_factory(self):
+ cube = Cube(np.arange(8).reshape(2, 2, 2), long_name='bar')
+ delta = AuxCoord(points=[0, 1], long_name='delta', units='m')
+ sigma = AuxCoord(points=[0, 1], long_name='sigma')
+ orog = AuxCoord(np.arange(4).reshape(2, 2), units='m', long_name='foo')
+ cube.add_aux_coord(delta, 0)
+ cube.add_aux_coord(sigma, 0)
+ # Note orography is not added to the cube here
+ factory = HybridHeightFactory(delta=delta, sigma=sigma, orography=orog)
+ expected_error = ("foo coordinate for factory is not present on cube "
+ "bar")
+ with self.assertRaisesRegexp(ValueError, expected_error):
+ cube.add_aux_factory(factory)
+
class Test_remove_metadata(tests.IrisTest):
def setUp(self):
From 25c5f4d8139784f796e2c0437d194ccfce63fb3c Mon Sep 17 00:00:00 2001
From: Peter Killick
Date: Thu, 4 Oct 2018 13:57:29 +0100
Subject: [PATCH 59/62] Correct cube collapse code
---
lib/iris/cube.py | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/iris/cube.py b/lib/iris/cube.py
index 9c42299c42..26faf91eb4 100644
--- a/lib/iris/cube.py
+++ b/lib/iris/cube.py
@@ -3241,10 +3241,10 @@ def collapsed(self, coords, aggregator, **kwargs):
# on the cube lazy array.
# NOTE: do not reform the data in this case, as 'lazy_aggregate'
# accepts multiple axes (unlike 'aggregate').
- collapse_axis = dims_to_collapse
+ collapse_axis = list(dims_to_collapse)
try:
data_result = aggregator.lazy_aggregate(self.lazy_data(),
- collapse_axis,
+ axis=collapse_axis,
**kwargs)
except TypeError:
# TypeError - when unexpected keywords passed through (such as
From 79639509cc83f9920c3a9830015a5e745c35b762 Mon Sep 17 00:00:00 2001
From: tv3141
Date: Mon, 23 Jul 2018 11:04:52 +0100
Subject: [PATCH 60/62] add contact options to README
removed gitter from contact list
---
README.md | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/README.md b/README.md
index a6e9dd525b..6dedfee592 100644
--- a/README.md
+++ b/README.md
@@ -44,6 +44,7 @@
+ [Documentation](#documentation)
+ [Installation](#installation)
+ [Copyright and licence](#copyright-and-licence)
++ [Get in touch](#get-in-touch)
+ [Contributing](#contributing)
[](TOC)
@@ -93,6 +94,12 @@ The easiest way to install Iris is with [conda](https://conda.io/miniconda.html)
Detailed instructions, including information on installing from source,
are available in [INSTALL](INSTALL).
+# Get in touch
+
+ * Report bugs, or suggest new features using an Issue or Pull Request on [Github](https://github.com/SciTools/iris). You can also comment on existing Issues and Pull Requests.
+ * For discussions from a user perspective you could join our [SciTools User's Google Group](https://groups.google.com/forum/#!forum/scitools-iris).
+ * For those involved in developing Iris we also have a [Google Group](https://groups.google.com/forum/#!forum/scitools-iris-dev).
+ * [StackOverflow](https://stackoverflow.com/questions/tagged/python-iris) For "How do I?".
# Copyright and licence
From a6c14809d44d83f0e03cdc4c7eaf10277874a09b Mon Sep 17 00:00:00 2001
From: Corinne Bosley
Date: Mon, 15 Oct 2018 11:37:37 +0100
Subject: [PATCH 61/62] expanded name of dev group
---
README.md | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/README.md b/README.md
index 6dedfee592..bfed315936 100644
--- a/README.md
+++ b/README.md
@@ -97,8 +97,8 @@ are available in [INSTALL](INSTALL).
# Get in touch
* Report bugs, or suggest new features using an Issue or Pull Request on [Github](https://github.com/SciTools/iris). You can also comment on existing Issues and Pull Requests.
- * For discussions from a user perspective you could join our [SciTools User's Google Group](https://groups.google.com/forum/#!forum/scitools-iris).
- * For those involved in developing Iris we also have a [Google Group](https://groups.google.com/forum/#!forum/scitools-iris-dev).
+ * For discussions from a user perspective you could join our [SciTools Users Google Group](https://groups.google.com/forum/#!forum/scitools-iris).
+ * For those involved in developing Iris we also have a [Iris Developers Google Group](https://groups.google.com/forum/#!forum/scitools-iris-dev).
* [StackOverflow](https://stackoverflow.com/questions/tagged/python-iris) For "How do I?".
# Copyright and licence
From 9b61b24bd9f56e70411b72a86f8287d58d94d0c5 Mon Sep 17 00:00:00 2001
From: Corinne Bosley
Date: Mon, 15 Oct 2018 11:40:22 +0100
Subject: [PATCH 62/62] added an n for better flow
---
README.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/README.md b/README.md
index bfed315936..bfb1353102 100644
--- a/README.md
+++ b/README.md
@@ -98,7 +98,7 @@ are available in [INSTALL](INSTALL).
* Report bugs, or suggest new features using an Issue or Pull Request on [Github](https://github.com/SciTools/iris). You can also comment on existing Issues and Pull Requests.
* For discussions from a user perspective you could join our [SciTools Users Google Group](https://groups.google.com/forum/#!forum/scitools-iris).
- * For those involved in developing Iris we also have a [Iris Developers Google Group](https://groups.google.com/forum/#!forum/scitools-iris-dev).
+ * For those involved in developing Iris we also have an [Iris Developers Google Group](https://groups.google.com/forum/#!forum/scitools-iris-dev).
* [StackOverflow](https://stackoverflow.com/questions/tagged/python-iris) For "How do I?".
# Copyright and licence