Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Consolidate mpl version checks #2238

Merged
merged 2 commits into from
Aug 25, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions lib/cartopy/mpl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,14 @@
# This file is part of Cartopy and is released under the LGPL license.
# See COPYING and COPYING.LESSER in the root of the repository for full
# licensing details.

import matplotlib
import packaging.version


_MPL_VERSION = packaging.version.parse(matplotlib.__version__)
_MPL_34 = _MPL_VERSION.release[:2] >= (3, 4)
_MPL_35 = _MPL_VERSION.release[:2] >= (3, 5)
_MPL_38 = _MPL_VERSION.release[:2] >= (3, 8)

assert _MPL_34, 'Cartopy is only supported with Matplotlib 3.4 or greater.'
6 changes: 3 additions & 3 deletions lib/cartopy/mpl/contour.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@
# See COPYING and COPYING.LESSER in the root of the repository for full
# licensing details.

import matplotlib as mpl
from matplotlib.contour import QuadContourSet
import matplotlib.path as mpath
import numpy as np
import packaging

from cartopy.mpl import _MPL_38


class GeoContourSet(QuadContourSet):
Expand All @@ -21,7 +21,7 @@ class GeoContourSet(QuadContourSet):
# fiddling with instance.__class__.

def clabel(self, *args, **kwargs):
if packaging.version.parse(mpl.__version__).release[:2] < (3, 8):
if not _MPL_38:
# nb: contour labelling does not work very well for filled
# contours - it is recommended to only label line contours.
# This is especially true when inline=True.
Expand Down
12 changes: 4 additions & 8 deletions lib/cartopy/mpl/geoaxes.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,23 +32,19 @@
import matplotlib.transforms as mtransforms
import numpy as np
import numpy.ma as ma
import packaging
import shapely.geometry as sgeom

from cartopy import config
import cartopy.crs as ccrs
import cartopy.feature
from cartopy.mpl import _MPL_38
import cartopy.mpl.contour
import cartopy.mpl.feature_artist as feature_artist
import cartopy.mpl.geocollection
import cartopy.mpl.patch as cpatch
from cartopy.mpl.slippy_image_artist import SlippyImageArtist


_MPL_VERSION = packaging.version.parse(mpl.__version__)
assert _MPL_VERSION.release >= (3, 4), \
'Cartopy is only supported with Matplotlib 3.4 or greater.'

# A nested mapping from path, source CRS, and target projection to the
# resulting transformed paths:
# {path: {(source_crs, target_projection): list_of_paths}}
Expand Down Expand Up @@ -1604,7 +1600,7 @@ def contour(self, *args, **kwargs):
result = super().contour(*args, **kwargs)

# We need to compute the dataLim correctly for contours.
if _MPL_VERSION.release[:2] < (3, 8):
if not _MPL_38:
bboxes = [col.get_datalim(self.transData)
for col in result.collections
if col.get_paths()]
Expand Down Expand Up @@ -1655,7 +1651,7 @@ def contourf(self, *args, **kwargs):
result = super().contourf(*args, **kwargs)

# We need to compute the dataLim correctly for contours.
if _MPL_VERSION.release[:2] < (3, 8):
if not _MPL_38:
bboxes = [col.get_datalim(self.transData)
for col in result.collections
if col.get_paths()]
Expand Down Expand Up @@ -1952,7 +1948,7 @@ def _wrap_quadmesh(self, collection, **kwargs):
# masked, so this will only draw a limited subset of
# polygons that were actually wrapped.

if _MPL_VERSION.release[:2] < (3, 8):
if not _MPL_38:
# We will add the original data mask in later to
# make sure that set_array can work in future
# calls on the proper sized array inputs.
Expand Down
13 changes: 5 additions & 8 deletions lib/cartopy/mpl/geocollection.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,11 @@
# This file is part of Cartopy and is released under the LGPL license.
# See COPYING and COPYING.LESSER in the root of the repository for full
# licensing details.
import matplotlib as mpl
from matplotlib.collections import QuadMesh
import numpy as np
import numpy.ma as ma
import packaging


_MPL_VERSION = packaging.version.parse(mpl.__version__)
from cartopy.mpl import _MPL_38


def _split_wrapped_mesh_data(C, mask):
Expand All @@ -24,7 +21,7 @@ def _split_wrapped_mesh_data(C, mask):
C_mask = getattr(C, 'mask', None)
if C.ndim == 3:
# RGB(A) array.
if _MPL_VERSION.release < (3, 8):
if not _MPL_38:
raise ValueError("GeoQuadMesh wrapping for RGB(A) requires "
"Matplotlib v3.8 or later")

Expand Down Expand Up @@ -58,7 +55,7 @@ def get_array(self):
if hasattr(self, '_wrapped_mask'):
pcolor_data = self._wrapped_collection_fix.get_array()
mask = self._wrapped_mask
if _MPL_VERSION.release[:2] < (3, 8):
if not _MPL_38:
A[mask] = pcolor_data
else:
if A.ndim == 3: # RGB(A) data. Need to broadcast mask.
Expand All @@ -72,7 +69,7 @@ def get_array(self):

def set_array(self, A):
# Check the shape is appropriate up front.
if _MPL_VERSION.release[:2] < (3, 8):
if not _MPL_38:
# Need to figure out existing shape from the coordinates.
height, width = self._coordinates.shape[0:-1]
if self._shading == 'flat':
Expand Down Expand Up @@ -102,7 +99,7 @@ def set_array(self, A):
# Update the pcolor data with the wrapped masked data
A, pcolor_data, _ = _split_wrapped_mesh_data(A, self._wrapped_mask)

if _MPL_VERSION.release[:2] < (3, 8):
if not _MPL_38:
self._wrapped_collection_fix.set_array(
pcolor_data[self._wrapped_mask].ravel())
else:
Expand Down
4 changes: 0 additions & 4 deletions lib/cartopy/tests/mpl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@
import matplotlib as mpl
import matplotlib.patches as mpatches
import matplotlib.pyplot as plt
import packaging.version


MPL_VERSION = packaging.version.parse(mpl.__version__)


def show(projection, geometry):
Expand Down
4 changes: 2 additions & 2 deletions lib/cartopy/tests/mpl/test_caching.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
import cartopy.crs as ccrs
from cartopy.io.ogc_clients import _OWSLIB_AVAILABLE, WMTSRasterSource
import cartopy.io.shapereader
from cartopy.mpl import _MPL_38
from cartopy.mpl.feature_artist import FeatureArtist
import cartopy.mpl.geoaxes as cgeoaxes
import cartopy.mpl.patch
from cartopy.tests.mpl import MPL_VERSION


def sample_data(shape=(73, 145)):
Expand Down Expand Up @@ -121,7 +121,7 @@ def test_contourf_transform_path_counting():
with mock.patch('cartopy.mpl.patch.path_to_geos') as path_to_geos_counter:
x, y, z = sample_data((30, 60))
cs = ax.contourf(x, y, z, 5, transform=ccrs.PlateCarree())
if MPL_VERSION.release[:2] < (3, 8):
if not _MPL_38:
n_geom = sum(len(c.get_paths()) for c in cs.collections)
else:
n_geom = len(cs.get_paths())
Expand Down
12 changes: 4 additions & 8 deletions lib/cartopy/tests/mpl/test_crs.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,12 @@
import pytest

import cartopy.crs as ccrs
from cartopy.tests.mpl import MPL_VERSION
from cartopy.mpl import _MPL_35


@pytest.mark.natural_earth
@pytest.mark.mpl_image_compare(filename="igh_land.png",
tolerance=(3.6
if MPL_VERSION.release[:2] < (3, 5)
else 0.5))
@pytest.mark.mpl_image_compare(
filename="igh_land.png", tolerance=0.5 if _MPL_35 else 3.6)
def test_igh_land():
crs = ccrs.InterruptedGoodeHomolosine(emphasis="land")
ax = plt.axes(projection=crs)
Expand All @@ -26,9 +24,7 @@ def test_igh_land():

@pytest.mark.natural_earth
@pytest.mark.mpl_image_compare(filename="igh_ocean.png",
tolerance=(4.5
if MPL_VERSION.release[:2] < (3, 5)
else 0.5))
tolerance=0.5 if _MPL_35 else 4.5)
def test_igh_ocean():
crs = ccrs.InterruptedGoodeHomolosine(
central_longitude=-160, emphasis="ocean"
Expand Down
5 changes: 2 additions & 3 deletions lib/cartopy/tests/mpl/test_examples.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import pytest

import cartopy.crs as ccrs
from cartopy.tests.mpl import MPL_VERSION
from cartopy.mpl import _MPL_38


@pytest.mark.natural_earth
Expand All @@ -33,8 +33,7 @@ def test_global_map():

@pytest.mark.natural_earth
@pytest.mark.mpl_image_compare(
filename='contour_label.png',
tolerance=3.9 if MPL_VERSION.release[:2] >= (3, 8) else 0.5)
filename='contour_label.png', tolerance=3.9 if _MPL_38 else 0.5)
def test_contour_label():
from cartopy.tests.mpl.test_caching import sample_data
fig = plt.figure()
Expand Down
16 changes: 7 additions & 9 deletions lib/cartopy/tests/mpl/test_mpl_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import pytest

import cartopy.crs as ccrs
from cartopy.tests.mpl import MPL_VERSION
from cartopy.mpl import _MPL_35, _MPL_38


@pytest.mark.natural_earth
Expand Down Expand Up @@ -197,8 +197,7 @@ def test_simple_global():
),
])
@pytest.mark.mpl_image_compare(
tolerance=0.97 if MPL_VERSION.release[:2] < (3, 5) else 0.5,
style='mpl20')
tolerance=0.5 if _MPL_35 else 0.97, style='mpl20')
def test_global_map(proj):
if isinstance(proj, tuple):
proj, kwargs = proj
Expand Down Expand Up @@ -241,8 +240,7 @@ def test_cursor_values():
r.encode('ascii', 'ignore'))


SKIP_PRE_MPL38 = pytest.mark.skipif(
MPL_VERSION.release[:2] < (3, 8), reason='mpl < 3.8')
SKIP_PRE_MPL38 = pytest.mark.skipif(not _MPL_38, reason='mpl < 3.8')
PARAMETRIZE_PCOLORMESH_WRAP = pytest.mark.parametrize(
'mesh_data_kind',
[
Expand Down Expand Up @@ -357,7 +355,7 @@ def test_pcolormesh_get_array_with_mask(mesh_data_kind):
result = c.get_array()

expected = data2
if MPL_VERSION.release[:2] < (3, 8):
if not _MPL_38:
expected = expected.ravel()

np.testing.assert_array_equal(np.ma.getmask(result), np.isnan(expected))
Expand Down Expand Up @@ -521,7 +519,7 @@ def test_pcolormesh_set_array_nowrap():
assert not hasattr(mesh, '_wrapped_collection_fix')

expected = data
if MPL_VERSION.release[:2] < (3, 8):
if not _MPL_38:
expected = expected.ravel()
np.testing.assert_array_equal(mesh.get_array(), expected)

Expand Down Expand Up @@ -681,7 +679,7 @@ def test_pcolormesh_nan_wrap():
ax = plt.axes(projection=ccrs.PlateCarree())
mesh = ax.pcolormesh(xs, ys, data)
pcolor = getattr(mesh, "_wrapped_collection_fix")
if MPL_VERSION.release[:2] < (3, 8):
if not _MPL_38:
assert len(pcolor.get_paths()) == 2
else:
assert not pcolor.get_paths()
Expand Down Expand Up @@ -961,7 +959,7 @@ def test_barbs_1d_transformed():
@pytest.mark.natural_earth
@pytest.mark.mpl_image_compare(
filename='streamplot.png', style='mpl20',
tolerance=9.77 if MPL_VERSION.release[:2] < (3, 5) else 0.5)
tolerance=0.5 if _MPL_35 else 9.77)
def test_streamplot():
x = np.arange(-60, 42.5, 2.5)
y = np.arange(30, 72.5, 2.5)
Expand Down