Skip to content

Commit 6d3cc56

Browse files
committed
Split plot module up
It was getting long, and with the geometry rewrite on the way it was about to get longer. This split makes it easier to support matplotlib as an optional dependency via the plot extra.
1 parent bbfa00e commit 6d3cc56

File tree

9 files changed

+393
-278
lines changed

9 files changed

+393
-278
lines changed

docs/api/plot.rst

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,37 @@
22
emsarray.plot
33
=============
44

5-
.. automodule:: emsarray.plot
6-
:members:
5+
.. currentmodule:: emsarray.plot
76

7+
Plotting an entire figure
8+
=========================
9+
10+
The :func:`plot_on_figure` and :func:`animate_on_figure` functions
11+
will generate a simple plot of any supported variables.
12+
These functions are intended as quick and simple ways of exploring a dataset
13+
and have limited customisation options.
14+
Consult the :ref:`examples gallery <examples>`
15+
for demonstrations on making more customised plots.
16+
17+
.. autofunction:: plot_on_figure
18+
.. autofunction:: animate_on_figure
19+
20+
Shortcuts
21+
=========
22+
23+
These functions make common plotting operations simple.
24+
They are designed as quick shortcuts
25+
and aim for ease of use and simplicity over being fully featured.
26+
Most of these functions defer to other parts of matplotlib or cartopy for the actual implementation,
27+
and users are encouraged to call these underlying implementations directly if more customisation is required.
28+
29+
.. autofunction:: add_coast
30+
.. autofunction:: add_gridlines
31+
.. autofunction:: add_landmarks
32+
33+
Utilities
34+
=========
35+
36+
.. autofunction:: polygons_to_collection
37+
.. autofunction:: bounds_to_extent
38+
.. autofunction:: make_plot_title

docs/examples/index.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
.. _examples:
2+
13
========
24
Examples
35
========

docs/releases/development.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,3 +28,8 @@ Next release (in development)
2828
In practice this will usually be "viridis"
2929
unless the user has changed their local defaults
3030
(:pr:`206`).
31+
* Split the :mod:`emsarray.plot` module in to multiple files.
32+
It was getting unruly in size and was about to become larger again.
33+
The documentation has been updated to match the conceptual divisions.
34+
The new layout makes it easier to support matplotlib as an optional dependency
35+
(:pr:`207`).

src/emsarray/conventions/_base.py

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,11 @@
1515
from shapely.geometry.base import BaseGeometry
1616
from shapely.strtree import STRtree
1717

18+
from emsarray import plot as _plot
1819
from emsarray import utils
1920
from emsarray.exceptions import InvalidPolygonWarning, NoSuchCoordinateError
2021
from emsarray.operations import depth, point_extraction
2122
from emsarray.operations.cache import hash_attributes, hash_int, hash_string
22-
from emsarray.plot import (
23-
_requires_plot, animate_on_figure, make_plot_title, plot_on_figure,
24-
polygons_to_collection
25-
)
2623
from emsarray.state import State
2724
from emsarray.types import Bounds, DataArrayOrName, Pathish
2825

@@ -709,7 +706,7 @@ def wind(
709706
pass
710707

711708
@cached_property # type: ignore
712-
@_requires_plot
709+
@_plot._requires_plot
713710
def data_crs(self) -> 'CRS':
714711
"""
715712
The coordinate reference system that coordinates in this dataset are
@@ -721,7 +718,7 @@ def data_crs(self) -> 'CRS':
721718
from cartopy.crs import PlateCarree
722719
return PlateCarree()
723720

724-
@_requires_plot
721+
@_plot._requires_plot
725722
def plot_on_figure(
726723
self,
727724
figure: 'Figure',
@@ -778,11 +775,11 @@ def plot_on_figure(
778775
#
779776
# Users can supply their own titles
780777
# if this automatic behaviour is insufficient
781-
kwargs['title'] = make_plot_title(self.dataset, kwargs['scalar'])
778+
kwargs['title'] = _plot.make_plot_title(self.dataset, kwargs['scalar'])
782779

783-
plot_on_figure(figure, self, **kwargs)
780+
_plot.plot_on_figure(figure, self, **kwargs)
784781

785-
@_requires_plot
782+
@_plot._requires_plot
786783
def plot(self, *args: Any, **kwargs: Any) -> None:
787784
"""Plot a data array and automatically display it.
788785
@@ -801,7 +798,7 @@ def plot(self, *args: Any, **kwargs: Any) -> None:
801798
self.plot_on_figure(pyplot.figure(), *args, **kwargs)
802799
pyplot.show()
803800

804-
@_requires_plot
801+
@_plot._requires_plot
805802
def animate_on_figure(
806803
self,
807804
figure: 'Figure',
@@ -899,9 +896,9 @@ def animate_on_figure(
899896
title_bits.append('{}')
900897
kwargs['title'] = '\n'.join(title_bits)
901898

902-
return animate_on_figure(figure, self, coordinate=coordinate, **kwargs)
899+
return _plot.animate_on_figure(figure, self, coordinate=coordinate, **kwargs)
903900

904-
@_requires_plot
901+
@_plot._requires_plot
905902
@utils.timed_func
906903
def make_poly_collection(
907904
self,
@@ -978,9 +975,9 @@ def make_poly_collection(
978975
if 'transform' not in kwargs:
979976
kwargs['transform'] = self.data_crs
980977

981-
return polygons_to_collection(self.polygons[self.mask], **kwargs)
978+
return _plot.polygons_to_collection(self.polygons[self.mask], **kwargs)
982979

983-
@_requires_plot
980+
@_plot._requires_plot
984981
def make_quiver(
985982
self,
986983
axes: 'Axes',

src/emsarray/plot/__init__.py

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
from typing import Any
2+
3+
from emsarray.utils import RequiresExtraException, requires_extra
4+
5+
try:
6+
from . import utils
7+
from .base import animate_on_figure, plot_on_figure
8+
from .shortcuts import add_coast, add_gridlines, add_landmarks
9+
from .utils import (
10+
bounds_to_extent, make_plot_title, polygons_to_collection
11+
)
12+
13+
CAN_PLOT = True
14+
IMPORT_EXCEPTION = None
15+
16+
except ImportError as exc:
17+
CAN_PLOT = False
18+
IMPORT_EXCEPTION = exc
19+
20+
def __getattr__(name: str) -> Any:
21+
# module.__getattr__("name") is called when code accessed module.name,
22+
# but the module doesn't have that attribute set.
23+
# We use this to raise a RequiresExtraException with the assumption
24+
# that importing something failed.
25+
26+
if name in __all__:
27+
raise RequiresExtraException("plot") from IMPORT_EXCEPTION
28+
else:
29+
raise AttributeError(name)
30+
31+
32+
# The external API of this module.
33+
__all__ = [
34+
'CAN_PLOT', '_requires_plot',
35+
36+
# Export the utils module explicitly. Future utility methods may not be
37+
# exported using this public API, and instead be accessed using `plot.utils.some_method`
38+
'utils',
39+
40+
# Methods from .base
41+
'animate_on_figure', 'plot_on_figure',
42+
43+
# Methods from .utils
44+
'add_coast', 'add_gridlines', 'add_landmarks', 'polygons_to_collection',
45+
'bounds_to_extent', 'make_plot_title'
46+
]
47+
48+
49+
_requires_plot = requires_extra(extra='plot', import_error=IMPORT_EXCEPTION)

0 commit comments

Comments
 (0)