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

cartopy: FeatureArtist is now a collection #525

Merged
merged 3 commits into from Mar 24, 2024
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Expand Up @@ -37,6 +37,9 @@ Docs
Internal Changes
~~~~~~~~~~~~~~~~

- Get upstream-dev CI to run with numpy 2.0 (:pull:`522`) and fix accrued upstream failures
for rasterio (:pull:`524`) and cartopy (:pull:`525`).


.. _changelog.0.12.1:

Expand Down
84 changes: 57 additions & 27 deletions regionmask/tests/test_plot.py
Expand Up @@ -3,6 +3,7 @@
from packaging.version import Version

try:
import cartopy
import cartopy.crs as ccrs
except ImportError: # pragma: no cover
pass
Expand Down Expand Up @@ -111,6 +112,13 @@ def assert_all_figures_closed():
]


def maybe_no_coastlines(plotfunc):

# NOTE: cartopy v0.23 moves the coastlines from artist to collection

return {"add_coastlines": False} if plotfunc == "plot" else {}


# =============================================================================


Expand Down Expand Up @@ -275,7 +283,7 @@ def test_plot_lines(plotfunc):
func = getattr(r1, plotfunc)

with figure_context():
ax = func(tolerance=None)
ax = func(tolerance=None, **maybe_no_coastlines(plotfunc))

lines = ax.collections[0].get_segments()

Expand All @@ -291,7 +299,7 @@ def test_plot_lines_float_numbers(plotfunc):
func = getattr(r4, plotfunc)

with figure_context():
ax = func(tolerance=None)
ax = func(tolerance=None, **maybe_no_coastlines(plotfunc))

lines = ax.collections[0].get_segments()

Expand All @@ -309,7 +317,7 @@ def test_plot_lines_multipoly(plotfunc):
func = getattr(r3, plotfunc)

with figure_context():
ax = func(tolerance=None)
ax = func(tolerance=None, **maybe_no_coastlines(plotfunc))

lines = ax.collections[0].get_segments()
assert len(lines) == 2
Expand All @@ -327,7 +335,7 @@ def test_plot_lines_selection(plotfunc):
with figure_context():
func = getattr(r1[0, 1], plotfunc)

ax = func(tolerance=None)
ax = func(tolerance=None, **maybe_no_coastlines(plotfunc))
lines = ax.collections[0].get_segments()
assert len(lines) == 2
assert np.allclose(lines[0], outl1_closed)
Expand Down Expand Up @@ -355,7 +363,7 @@ def test_plot_lines_tolerance(plotfunc):
func = getattr(r1, plotfunc)

with figure_context():
ax = func(tolerance=1 / 50)
ax = func(tolerance=1 / 50, **maybe_no_coastlines(plotfunc))
lines = ax.collections[0].get_paths()

assert len(lines) == 2
Expand All @@ -369,7 +377,7 @@ def test_plot_lines_tolerance_None(plotfunc):
func = getattr(r_large, plotfunc)

with figure_context():
ax = func(tolerance=None)
ax = func(tolerance=None, **maybe_no_coastlines(plotfunc))
lines = ax.collections[0].get_paths()

np.testing.assert_allclose(
Expand All @@ -390,7 +398,7 @@ def test_plot_lines_tolerance_auto(plotfunc, kwargs):
expected = (41, 2) if plotfunc == "plot" else (5, 2)

with figure_context():
ax = func(**kwargs)
ax = func(**kwargs, **maybe_no_coastlines(plotfunc))

lines = ax.collections[0].get_paths()
np.testing.assert_allclose(lines[0].vertices.shape, expected)
Expand Down Expand Up @@ -421,7 +429,7 @@ def test_plot_lines_from_poly(plotfunc):
func = getattr(r2, plotfunc)

with figure_context():
ax = func()
ax = func(**maybe_no_coastlines(plotfunc))
lines = ax.collections[0].get_segments()

assert len(lines) == 2
Expand All @@ -438,7 +446,11 @@ def test_plot_line_prop(plotfunc):
func = getattr(r1, plotfunc)

with figure_context():
ax = func(tolerance=None, line_kws=dict(lw=2, color="g"))
ax = func(
tolerance=None,
line_kws=dict(lw=2, color="g"),
**maybe_no_coastlines(plotfunc),
)

collection = ax.collections[0]

Expand Down Expand Up @@ -580,6 +592,24 @@ def test_plot_text_clip(plotfunc):
assert text.get_clip_on() is False


def assert_feature_artist(ax, expected):
# cartopy coastlines etc. are FeatureArtist instances

# NOTE: only works if cartopy never releases v0.22.1
if Version(cartopy.__version__) > Version("0.22.0"):
# + 1 because `collection` also contains the lines
assert len(ax.collections) == expected + 1
else:
assert len(ax.artists) == expected


def get_artist_or_collection(ax):

if Version(cartopy.__version__) > Version("0.22.0"):
return ax.collections[0]
return ax.artists[0]


@requires_matplotlib
@requires_cartopy
def test_plot_ocean():
Expand All @@ -589,28 +619,28 @@ def test_plot_ocean():
# no ocean per default
with figure_context():
ax = r1.plot(**kwargs)
assert len(ax.artists) == 0
assert_feature_artist(ax, 0)

with figure_context():
ax = r1.plot(add_ocean=False, **kwargs)
assert len(ax.artists) == 0
assert_feature_artist(ax, 0)

# default settings
with figure_context():
ax = r1.plot(add_ocean=True, **kwargs)
assert len(ax.artists) == 1
assert_feature_artist(ax, 1)

art = ax.artists[0]
art = get_artist_or_collection(ax)
assert art.get_zorder() == 0.9
# note testing private attribute
assert art._kwargs["lw"] == 0

# user settings
with figure_context():
ax = r1.plot(add_ocean=True, ocean_kws=dict(zorder=1), **kwargs)
assert len(ax.artists) == 1
assert_feature_artist(ax, 1)

art = ax.artists[0]
art = get_artist_or_collection(ax)
assert art.get_zorder() == 1


Expand All @@ -623,26 +653,26 @@ def test_plot_land():
# no land per default
with figure_context():
ax = r1.plot(**kwargs)
assert len(ax.artists) == 0
assert_feature_artist(ax, 0)

with figure_context():
ax = r1.plot(add_land=False, **kwargs)
assert len(ax.artists) == 0
assert_feature_artist(ax, 0)

# default settings
with figure_context():
ax = r1.plot(add_land=True, **kwargs)
assert len(ax.artists) == 1
art = ax.artists[0]
assert_feature_artist(ax, 1)
art = get_artist_or_collection(ax)
assert art.get_zorder() == 0.9
# note testing private attribute
assert art._kwargs["lw"] == 0

# user settings
with figure_context():
ax = r1.plot(add_land=True, land_kws=dict(zorder=1), **kwargs)
assert len(ax.artists) == 1
art = ax.artists[0]
assert_feature_artist(ax, 1)
art = get_artist_or_collection(ax)
assert art.get_zorder() == 1


Expand All @@ -655,22 +685,22 @@ def test_plot_add_coastlines():
# coastlines are added per default
with figure_context():
ax = r1.plot(**kwargs)
assert len(ax.artists) == 1
assert_feature_artist(ax, 1)

with figure_context():
ax = r1.plot(add_coastlines=False, **kwargs)
assert len(ax.artists) == 0
assert_feature_artist(ax, 0)

with figure_context():
ax = r1.plot(add_coastlines=True, **kwargs)
assert len(ax.artists) == 1
art = ax.artists[0]
assert_feature_artist(ax, 1)
art = get_artist_or_collection(ax)
assert art._kwargs == {"lw": 0.5, "edgecolor": "0.4", "facecolor": "none"}

with figure_context():
ax = r1.plot(add_coastlines=True, coastline_kws=dict(), **kwargs)
assert len(ax.artists) == 1
art = ax.artists[0]
assert_feature_artist(ax, 1)
art = get_artist_or_collection(ax)
assert art._kwargs == {"edgecolor": "black", "facecolor": "none"}


Expand Down