Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 756dd8c

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

File tree

4 files changed

+70
-17
lines changed
Filter options

4 files changed

+70
-17
lines changed

‎doc/devel/add_new_projection.rst

Copy file name to clipboardExpand all lines: doc/devel/add_new_projection.rst
+27-4Lines 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

Copy file name to clipboardExpand all lines: lib/matplotlib/figure.py
+19-8Lines 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

Copy file name to clipboardExpand all lines: lib/matplotlib/projections/__init__.py
+13-4Lines 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

Copy file name to clipboardExpand all lines: lib/matplotlib/projections/polar.py
+11-1Lines 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 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.