Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 756dd8c

Browse files
author
Phil Elson
committed
Added documentation, supported add_axes regarding _as_mpl_axes.
1 parent ab0615c commit 756dd8c

File tree

4 files changed

+70
-17
lines changed

4 files changed

+70
-17
lines changed

doc/devel/add_new_projection.rst

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,9 @@ in :mod:`matplotlib.scale` that may be used as starting points.
7171
Creating a new projection
7272
=========================
7373

74-
Adding a new projection consists of defining a subclass of
75-
:class:`matplotlib.axes.Axes`, that includes the following elements:
74+
Adding a new projection consists of defining a projection axes which
75+
subclasses :class:`matplotlib.axes.Axes` and includes the following
76+
elements:
7677

7778
- A transformation from data coordinates into display coordinates.
7879

@@ -98,11 +99,33 @@ Adding a new projection consists of defining a subclass of
9899
- Set up interactive panning and zooming. This is left as an
99100
"advanced" feature left to the reader, but there is an example of
100101
this for polar plots in :mod:`matplotlib.projections.polar`.
102+
103+
- Optionally define the class attribute ``NAME`` which can be
104+
registered with :func:`matplotlib.projections.register_projection`
105+
and used for simple projection instantiation such as
106+
``plt.axes(projection=NAME)``, where ``NAME`` is a string.
101107

102108
- Any additional methods for additional convenience or features.
103109

104-
Once the class is defined, it must be registered with matplotlib
105-
so that the user can select it.
110+
Once the projection axes is defined, it can be used in one of two ways:
111+
112+
- By defining the class attribute ``NAME``, the projection axes can be
113+
registered with :func:`matplotlib.projections.register_projection`
114+
and subsequently simply invoked by name::
115+
116+
plt.axes(projection=NAME)
117+
118+
- For more complex, parameterisable projections, a generic "projection"
119+
object may be defined which includes the method ``_as_mpl_axes``.
120+
``_as_mpl_axes`` should take no arguments and return the projection's
121+
axes subclass and a dictionary of additional arguments to pass to the
122+
subclass' ``__init__`` method. Subsequently a parameterised projection
123+
can be initialised with::
124+
125+
plt.axes(projection=MyProjection(param1=param1_value))
126+
127+
where MyProjection is an object which implements a ``_as_mpl_axes`` method.
128+
106129

107130
A full-fledged and heavily annotated example is in
108131
:file:`examples/api/custom_projection_example.py`. The polar plot

lib/matplotlib/figure.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -702,8 +702,16 @@ def add_axes(self, *args, **kwargs):
702702
projection)
703703
projection = 'polar'
704704

705+
if isinstance(projection, basestring) or projection is None:
706+
projection_class = get_projection_class(projection)
707+
elif hasattr(projection, '_as_mpl_axes'):
708+
projection_class, extra_kwargs = projection._as_mpl_axes()
709+
kwargs.update(**extra_kwargs)
710+
else:
711+
TypeError('projection must be a string, None or implement a _as_mpl_axes method. Got %r' % projection)
712+
705713
a = projection_factory(projection, self, rect, **kwargs)
706-
714+
707715
self._axstack.add(key, a)
708716
self.sca(a)
709717
return a
@@ -714,10 +722,11 @@ def add_subplot(self, *args, **kwargs):
714722
Add a subplot. Examples:
715723
716724
fig.add_subplot(111)
717-
fig.add_subplot(1,1,1) # equivalent but more general
718-
fig.add_subplot(212, axisbg='r') # add subplot with red background
719-
fig.add_subplot(111, polar=True) # add a polar subplot
720-
fig.add_subplot(sub) # add Subplot instance sub
725+
fig.add_subplot(1,1,1) # equivalent but more general
726+
fig.add_subplot(212, axisbg='r') # add subplot with red background
727+
fig.add_subplot(111, projection='polar') # add a polar subplot
728+
fig.add_subplot(111, polar=True) # add a polar subplot
729+
fig.add_subplot(sub) # add Subplot instance sub
721730
722731
*kwargs* are legal :class:`!matplotlib.axes.Axes` kwargs plus
723732
*projection*, which chooses a projection type for the axes.
@@ -751,18 +760,20 @@ def add_subplot(self, *args, **kwargs):
751760
ispolar = kwargs.pop('polar', False)
752761
projection = kwargs.pop('projection', None)
753762
if ispolar:
754-
if projection is not None and projection != 'polar':
763+
if projection is not None:
755764
raise ValueError(
756-
"polar=True, yet projection='%s'. " +
765+
"polar=True, yet projection=%r. " +
757766
"Only one of these arguments should be supplied." %
758767
projection)
759768
projection = 'polar'
760769

761770
if isinstance(projection, basestring) or projection is None:
762771
projection_class = get_projection_class(projection)
763-
else:
772+
elif hasattr(projection, '_as_mpl_axes'):
764773
projection_class, extra_kwargs = projection._as_mpl_axes()
765774
kwargs.update(**extra_kwargs)
775+
else:
776+
TypeError('projection must be a string, None or implement a _as_mpl_axes method. Got %r' % projection)
766777

767778
# Remake the key without projection kwargs:
768779
key = self._make_key(*args, **kwargs)

lib/matplotlib/projections/__init__.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -56,10 +56,19 @@ def get_projection_class(projection=None):
5656
if projection is None:
5757
projection = 'rectilinear'
5858

59-
try:
60-
return projection_registry.get_projection_class(projection)
61-
except KeyError:
62-
raise ValueError("Unknown projection '%s'" % projection)
59+
if isinstance(projection, basestring):
60+
try:
61+
return projection_registry.get_projection_class(projection)
62+
except KeyError:
63+
raise ValueError("Unknown projection '%s'" % projection)
64+
65+
elif hasattr(projection, '_as_mpl_axes'):
66+
projection_class, extra_kwargs = projection._as_mpl_axes()
67+
kwargs.update(**extra_kwargs)
68+
else:
69+
TypeError('projection must be a string, None or implement a _as_mpl_axes method. Got %r' % projection)
70+
71+
6372

6473
def projection_factory(projection, figure, rect, **kwargs):
6574
"""

lib/matplotlib/projections/polar.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -757,4 +757,14 @@ def drag_pan(self, button, key, x, y):
757757
# return mpath.Path(result, codes)
758758
# transform_path_non_affine = transform_path
759759

760-
760+
class Polar(object):
761+
"""
762+
Represents the polar projection, a Polar instance can be used to initialise
763+
a polar plot in the standard ways, for example::
764+
765+
plt.axes(projection=Polar())
766+
767+
"""
768+
def _as_mpl_axes(self):
769+
# implement the matplotlib axes interface
770+
return PolarAxes, {}

0 commit comments

Comments
 (0)