From b1457de6f58858275af61a0ed59db16ed16c32fa Mon Sep 17 00:00:00 2001 From: "Sebastian D. Eastham" Date: Fri, 11 Sep 2020 14:48:09 -0400 Subject: [PATCH 1/3] Combine wrapped collection into GeoMesh data when get_array is called When calling get_array with a QuadMesh object (from pcolormesh), the returned array only includes the unmasked data. This change fills in the masked data when present. --- lib/cartopy/mpl/geocollection.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/cartopy/mpl/geocollection.py b/lib/cartopy/mpl/geocollection.py index 5a8bae8cd..98cd65a36 100644 --- a/lib/cartopy/mpl/geocollection.py +++ b/lib/cartopy/mpl/geocollection.py @@ -16,6 +16,14 @@ class GeoQuadMesh(QuadMesh): # come from GeoAxes.pcolormesh. These methods morph a QuadMesh by # fiddling with instance.__class__. + def get_array(self): + # Retrieve the array - use copy to avoid any chance of overwrite + A = super(QuadMesh, self).get_array().copy() + # If the input array has a mask, retrieve the associated data + if hasattr(self, '_wrapped_mask'): + A[self._wrapped_mask] = self._wrapped_collection_fix.get_array() + return A + def set_array(self, A): # raise right away if A is 2-dimensional. if A.ndim > 1: From bbd3748ad800ec67fb09e274b0bafe721c697062 Mon Sep 17 00:00:00 2001 From: "Sebastian D. Eastham" Date: Sun, 11 Oct 2020 09:47:41 -0400 Subject: [PATCH 2/3] Updated tests to handle new get_array behavior with masking A new test has been added which verifies that the data returned by a pcolormesh get_array() command matches the data which was first given to the pcolormesh command, even if wrapping has occurred. One of the other tests (pcolormesh_diagonal_wrap) was also failing due to a faulty check, which has been removed. --- lib/cartopy/tests/mpl/test_mpl_integration.py | 44 ++++++++++++++++++- 1 file changed, 42 insertions(+), 2 deletions(-) diff --git a/lib/cartopy/tests/mpl/test_mpl_integration.py b/lib/cartopy/tests/mpl/test_mpl_integration.py index 3df623059..7eb4bba65 100644 --- a/lib/cartopy/tests/mpl/test_mpl_integration.py +++ b/lib/cartopy/tests/mpl/test_mpl_integration.py @@ -321,6 +321,48 @@ def test_pcolormesh_global_with_wrap1(): ax.coastlines() ax.set_global() # make sure everything is visible +#@pytest.mark.natural_earth +#@ImageTesting(['pcolormesh_global_wrap1'], tolerance=1.27) +def test_pcolormesh_get_array_with_mask(): + # make up some realistic data with bounds (such as data from the UM) + nx, ny = 36, 18 + xbnds = np.linspace(0, 360, nx, endpoint=True) + ybnds = np.linspace(-90, 90, ny, endpoint=True) + + x, y = np.meshgrid(xbnds, ybnds) + data = np.exp(np.sin(np.deg2rad(x)) + np.cos(np.deg2rad(y))) + data = data[:-1, :-1] + + ax = plt.subplot(211, projection=ccrs.PlateCarree()) + c = plt.pcolormesh(xbnds, ybnds, data, transform=ccrs.PlateCarree()) + assert c._wrapped_collection_fix is not None, \ + 'No pcolormesh wrapping was done when it should have been.' + + assert np.array_equal(data.ravel(),c.get_array()), \ + 'Data supplied does not match data retrieved in wrapped case' + + ax.coastlines() + ax.set_global() # make sure everything is visible + + # Case without wrapping + nx, ny = 36, 18 + xbnds = np.linspace(-60, 60, nx, endpoint=True) + ybnds = np.linspace(-80, 80, ny, endpoint=True) + + x, y = np.meshgrid(xbnds, ybnds) + data = np.exp(np.sin(np.deg2rad(x)) + np.cos(np.deg2rad(y))) + data2 = data[:-1, :-1] + + ax = plt.subplot(212, projection=ccrs.PlateCarree()) + c = plt.pcolormesh(xbnds, ybnds, data2, transform=ccrs.PlateCarree()) + ax.coastlines() + ax.set_global() # make sure everything is visible + + assert getattr(c,"_wrapped_collection_fix",None) is None, \ + 'pcolormesh wrapping was done when it should not have been.' + + assert np.array_equal(data2.ravel(),c.get_array()), \ + 'Data supplied does not match data retrieved in unwrapped case' tolerance = 1.61 if (5, 0, 0) <= ccrs.PROJ4_VERSION < (5, 1, 0): @@ -519,8 +561,6 @@ def test_pcolormesh_diagonal_wrap(): ax = plt.axes(projection=ccrs.PlateCarree()) mesh = ax.pcolormesh(xs, ys, zs) - # Check that the quadmesh is masked - assert np.ma.is_masked(mesh.get_array()) # And that the wrapped_collection is added assert hasattr(mesh, "_wrapped_collection_fix") From 8c2367cd2c781914623833ee8bf7959001c0cc2f Mon Sep 17 00:00:00 2001 From: "Sebastian D. Eastham" Date: Sun, 11 Oct 2020 10:02:44 -0400 Subject: [PATCH 3/3] Fix style issues from previous commit (comments, whitespace) Stickler Bot identified six issues with the previous commit. Two were with commented-out code which was no longer necessary, one was because of a missing newline, and three were because of missing whitespace after commas. All have now been resolved. --- lib/cartopy/tests/mpl/test_mpl_integration.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/lib/cartopy/tests/mpl/test_mpl_integration.py b/lib/cartopy/tests/mpl/test_mpl_integration.py index 7eb4bba65..de4f72560 100644 --- a/lib/cartopy/tests/mpl/test_mpl_integration.py +++ b/lib/cartopy/tests/mpl/test_mpl_integration.py @@ -321,8 +321,7 @@ def test_pcolormesh_global_with_wrap1(): ax.coastlines() ax.set_global() # make sure everything is visible -#@pytest.mark.natural_earth -#@ImageTesting(['pcolormesh_global_wrap1'], tolerance=1.27) + def test_pcolormesh_get_array_with_mask(): # make up some realistic data with bounds (such as data from the UM) nx, ny = 36, 18 @@ -338,7 +337,7 @@ def test_pcolormesh_get_array_with_mask(): assert c._wrapped_collection_fix is not None, \ 'No pcolormesh wrapping was done when it should have been.' - assert np.array_equal(data.ravel(),c.get_array()), \ + assert np.array_equal(data.ravel(), c.get_array()), \ 'Data supplied does not match data retrieved in wrapped case' ax.coastlines() @@ -358,10 +357,10 @@ def test_pcolormesh_get_array_with_mask(): ax.coastlines() ax.set_global() # make sure everything is visible - assert getattr(c,"_wrapped_collection_fix",None) is None, \ + assert getattr(c, "_wrapped_collection_fix", None) is None, \ 'pcolormesh wrapping was done when it should not have been.' - assert np.array_equal(data2.ravel(),c.get_array()), \ + assert np.array_equal(data2.ravel(), c.get_array()), \ 'Data supplied does not match data retrieved in unwrapped case' tolerance = 1.61