Skip to content

Commit

Permalink
Make coasts and gridlines optional on plots
Browse files Browse the repository at this point in the history
There are currently a number of problems with gridlines on plots in
Jupyter notebooks. There are different solutions that depend on whether
you want an interactive plot, a static plot in a notebook, or are
saving the plot to a file. Unfortunately there is no single solution
that works in all cases currently. Until a proper solution is found,
users can disable gridlines and then re-enable them in the way that
works for their current environment.

SciTools/cartopy#2245
SciTools/cartopy#2246
SciTools/cartopy#2247
  • Loading branch information
mx-moth committed Sep 27, 2023
1 parent 4853266 commit dee760a
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 10 deletions.
8 changes: 8 additions & 0 deletions docs/releases/development.rst
Expand Up @@ -5,3 +5,11 @@ Next release (in development)
* Fix transect plot title and units.
All attributes were being dropped accidentally in `prepare_data_array_for_transect()`.
(:pr:`114`).
* Add `coast` and `gridlines` parameters to :func:`emsarray.plot.plot_on_figure()`,
allowing users to disable these components of a plot.
Currently gridlines can cause issues in interactive Jupyter notebooks
and some other environments.
There is no one solution to every situation.
Allowing users to disable gridlines is a temporary work around
while other solutions are being sought.
(:pr:`115`, :issue:`SciTools/cartopy#2245`, :issue:`SciTools/cartopy#2246`, :issue:`SciTools/cartopy#2247`).
51 changes: 41 additions & 10 deletions src/emsarray/plot.py
Expand Up @@ -62,7 +62,12 @@ def add_coast(axes: Axes, **kwargs: Any) -> None:
axes.add_feature(coast, **kwargs)


def add_gridlines(axes: Axes) -> gridliner.Gridliner:
def add_gridlines(
axes: Axes,
draw_labels={'left', 'bottom'},
auto_update=True,
**kwargs: Any,
) -> gridliner.Gridliner:
"""
Add some gridlines to the axes.
Expand All @@ -75,9 +80,11 @@ def add_gridlines(axes: Axes) -> gridliner.Gridliner:
-------
cartopy.mpl.gridliner.Gridliner
"""
gridlines = axes.gridlines(draw_labels=True, auto_update=True)
gridlines.top_labels = False
gridlines.right_labels = False
gridlines = axes.gridlines(
draw_labels=draw_labels,
auto_update=auto_update,
**kwargs,
)
return gridlines


Expand Down Expand Up @@ -270,6 +277,8 @@ def plot_on_figure(
title: Optional[str] = None,
projection: Optional[cartopy.crs.Projection] = None,
landmarks: Optional[Iterable[Landmark]] = None,
gridlines: bool = True,
coast: bool = True,
) -> None:
"""
Plot a :class:`~xarray.DataArray`
Expand Down Expand Up @@ -298,6 +307,10 @@ def plot_on_figure(
which is defined in :attr:`.Convention.data_crs`.
landmarks : list of :data:`landmarks <emsarray.types.Landmark>`, optional
Landmarks to add to the plot. These are tuples of (name, point).
gridlines : bool, default True
Whether to add gridlines to the plot using :func:`add_gridlines()`.
coast : bool, default True
Whether to add coastlines to the plot using :func:`add_coast()`.
"""
if projection is None:
projection = cartopy.crs.PlateCarree()
Expand Down Expand Up @@ -331,10 +344,19 @@ def plot_on_figure(
if landmarks:
add_landmarks(axes, landmarks)

add_coast(axes)
add_gridlines(axes)
if coast:
add_coast(axes)
if gridlines:
add_gridlines(axes)

axes.autoscale()

# Work around for gridline positioning issues
# https://github.com/SciTools/cartopy/issues/2245#issuecomment-1732313921
layout_engine = figure.get_layout_engine()
if layout_engine is not None:
layout_engine.execute(figure)


@_requires_plot
def animate_on_figure(
Expand All @@ -347,6 +369,8 @@ def animate_on_figure(
title: Optional[Union[str, Callable[[Any], str]]] = None,
projection: Optional[cartopy.crs.Projection] = None,
landmarks: Optional[Iterable[Landmark]] = None,
gridlines: bool = True,
coast: bool = True,
interval: int = 1000,
repeat: Union[bool, Literal['cycle', 'bounce']] = True,
) -> animation.FuncAnimation:
Expand Down Expand Up @@ -392,6 +416,10 @@ def animate_on_figure(
which is defined in :attr:`.Convention.data_crs`.
landmarks : list of :data:`landmarks <emsarray.types.Landmark>`, optional
Landmarks to add to the plot. These are tuples of (name, point).
gridlines : bool, default True
Whether to add gridlines to the plot using :func:`add_gridlines()`.
coast : bool, default True
Whether to add coastlines to the plot using :func:`add_coast()`.
interval : int
The interval between frames of animation
repeat : {True, False, 'cycle', 'bounce'}
Expand Down Expand Up @@ -442,8 +470,10 @@ def animate_on_figure(
axes.add_collection(quiver)

# Draw a coast overlay
add_coast(axes)
gridlines = add_gridlines(axes)
if coast:
add_coast(axes)
if gridlines:
gridliner = add_gridlines(axes)
if landmarks:
add_landmarks(axes, landmarks)
axes.autoscale()
Expand All @@ -470,8 +500,9 @@ def animate(index: int) -> Iterable[Artist]:
coordinate_value = coordinate.values[index]
axes.title.set_text(coordinate_callable(coordinate_value))
changes.append(axes.title)
changes.extend(gridlines.xline_artists)
changes.extend(gridlines.yline_artists)
if gridlines:
changes.extend(gridliner.xline_artists)
changes.extend(gridliner.yline_artists)

if collection is not None:
collection.set_array(scalar_values[index])
Expand Down

0 comments on commit dee760a

Please sign in to comment.