Skip to content

Commit

Permalink
Shared colorbar axes working.
Browse files Browse the repository at this point in the history
  • Loading branch information
pelson committed May 14, 2013
1 parent 6b442b8 commit be049b2
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 22 deletions.
99 changes: 86 additions & 13 deletions lib/matplotlib/colorbar.py
Expand Up @@ -35,6 +35,7 @@
import matplotlib.patches as mpatches
import matplotlib.path as mpath
import matplotlib.ticker as ticker
import matplotlib.transforms as mtrans

from matplotlib import docstring

Expand All @@ -52,7 +53,8 @@
*anchor* (0.0, 0.5) if vertical; (0.5, 1.0) if horizontal;
the anchor point of the colorbar axes
*panchor* (1.0, 0.5) if vertical; (0.5, 0.0) if horizontal;
the anchor point of the colorbar parent axes
the anchor point of the colorbar parent axes. If
False, the parent axes' anchor will be unchanged
============= ====================================================
'''
Expand Down Expand Up @@ -149,8 +151,9 @@
*cax*
None | axes object into which the colorbar will be drawn
*ax*
None | parent axes object from which space for a new
colorbar axes will be stolen
None | parent axes object(s) from which space for a new
colorbar axes will be stolen. If a list of axes is given
they will be resized to make room for the colorbar axes.
*use_gridspec*
False | If *cax* is None, a new *cax* is created as an instance of
Axes. If *ax* is an instance of Subplot and *use_gridspec* is True,
Expand Down Expand Up @@ -255,6 +258,7 @@ def __init__(self, ax, cmap=None,
values=None,
boundaries=None,
orientation='vertical',
location='right',
extend='neither',
spacing='uniform', # uniform or proportional
ticks=None,
Expand All @@ -278,6 +282,7 @@ def __init__(self, ax, cmap=None,
self._inside = self._slice_dict[extend]
self.spacing = spacing
self.orientation = orientation
self.location = location
self.drawedges = drawedges
self.filled = filled
self.extendfrac = extendfrac
Expand Down Expand Up @@ -336,11 +341,15 @@ def config_axis(self):
ax = self.ax
if self.orientation == 'vertical':
ax.xaxis.set_ticks([])
ax.yaxis.set_label_position('right')
ax.yaxis.set_ticks_position('right')
# location is either one of 'bottom' or 'top'
ax.yaxis.set_label_position(self.location)
ax.yaxis.set_ticks_position(self.location)
else:
ax.yaxis.set_ticks([])
ax.xaxis.set_label_position('bottom')
# location is either one of 'left' or 'right'
ax.xaxis.set_label_position(self.location)
# XXX This wasn't enabled before...
ax.xaxis.set_ticks_position(self.location)

self._set_label()

Expand Down Expand Up @@ -835,11 +844,10 @@ class Colorbar(ColorbarBase):
"""
def __init__(self, ax, mappable, **kw):
mappable.autoscale_None() # Ensure mappable.norm.vmin, vmax
# are set when colorbar is called,
# even if mappable.draw has not yet
# been called. This will not change
# vmin, vmax if they are already set.
# Ensure the given mappable's norm has appropriate vmin and vmax set
# even if mappable.draw has not yet been called.
mappable.autoscale_None()

self.mappable = mappable
kw['cmap'] = mappable.cmap
kw['norm'] = mappable.norm
Expand Down Expand Up @@ -948,7 +956,7 @@ def update_bruteforce(self, mappable):


@docstring.Substitution(make_axes_kw_doc)
def make_axes(parent, **kw):
def make_axes_orig(parent, **kw):
'''
Resize and reposition a parent axes, and return a child
axes suitable for a colorbar::
Expand Down Expand Up @@ -994,6 +1002,71 @@ def make_axes(parent, **kw):
return cax, kw


@docstring.Substitution(make_axes_kw_doc)
def make_axes(parent, location=None, orientation=None, fraction=0.15, shrink=1.0, aspect=20, **kw):
locations = ["left", "right", "top", "bottom"]
if orientation is not None and location is not None:
raise TypeError('position and orientation are mutually exclusive. Consider ' \
'setting the position to any of %s' % ','.join(locations))

# must pump out an orientation for colorbar creation
if location in ['left', 'right']:
kw['orientation'] = 'vertical'
kw['location'] = location
anchor = kw.pop('anchor', (0.0, 0.5))
# define the parent's anchor to be next to the new colorbar axes
panchor = kw.pop('panchor', (1.0, 0.5))
else:
kw['orientation'] = 'horizontal'
kw['location'] = location
anchor = kw.pop('anchor', (0.5, 1.0))
# define the parent's anchor to be next to the new colorbar axes
panchor = kw.pop('panchor', (0.5, 0.0))

# define padding between colorbar axes and parent axes in axes coordinates.
# For best outcomes, pad is best at 0.15 when location is "bottom"
if location == 'bottom':
pad = kw.pop('pad', 0.0)
else:
pad = kw.pop('pad', 0.00)

if isinstance(parent, list):
parents_bbox = mtrans.Bbox.union([ax.get_position(original=True).frozen() \
for ax in parent])

pb = parents_bbox
if location in ('left', 'right'):
if location == 'left':
pbcb, _, pb1 = pb.splitx(1 - fraction, fraction + pad)
else:
pb1, _, pbcb = pb.splitx(1 - fraction - pad, 1 - fraction)
pbcb = pbcb.shrunk(1.0, shrink).anchored('C', pbcb)

else:
if location == 'top':
pb1, _, pbcb = pb.splity(1 - fraction - pad, fraction)
else:
pbcb, _, pb1 = pb.splity(fraction, fraction + pad)
pbcb = pbcb.shrunk(shrink, 1.0).anchored('C', pbcb)
# define the aspect ratio in terms of y's per x rather than x's per y
aspect = 1.0/aspect

shrinking_trans = mtrans.BboxTransform(parents_bbox, pb1)

for ax in parent:
new_posn = shrinking_trans.transform(ax.get_position())
new_posn = mtrans.Bbox(new_posn)
ax.set_position(new_posn)
if panchor is not False:
ax.set_anchor(panchor)

# XXX test all axes must be on the same figure...
fig = parent[0].get_figure()
cax = fig.add_axes(pbcb)
cax.set_aspect(aspect, anchor=anchor, adjustable='box')
return cax, kw


@docstring.Substitution(make_axes_kw_doc)
def make_axes_gridspec(parent, **kw):
'''
Expand All @@ -1018,7 +1091,7 @@ def make_axes_gridspec(parent, **kw):
Keyword arguments may include the following (with defaults):
*orientation*
'vertical' or 'horizontal'
'vertical' or 'horizontal'
%s
Expand Down
4 changes: 2 additions & 2 deletions lib/matplotlib/figure.py
Expand Up @@ -1418,7 +1418,7 @@ def savefig(self, *args, **kwargs):
ax.patch.set_edgecolor(cc[1])

@docstring.dedent_interpd
def colorbar(self, mappable, cax=None, ax=None, **kw):
def colorbar(self, mappable, cax=None, ax=None, use_gridspec=False, **kw):
"""
Create a colorbar for a ScalarMappable instance, *mappable*.
Expand All @@ -1427,7 +1427,7 @@ def colorbar(self, mappable, cax=None, ax=None, **kw):
"""
if ax is None:
ax = self.gca()
use_gridspec = kw.pop("use_gridspec", True)

if cax is None:
if use_gridspec and isinstance(ax, SubplotBase):
cax, kw = cbar.make_axes_gridspec(ax, **kw)
Expand Down
12 changes: 5 additions & 7 deletions lib/matplotlib/pyplot.py
Expand Up @@ -21,11 +21,13 @@
import warnings

import matplotlib
import matplotlib.colorbar
from matplotlib import _pylab_helpers, interactive
from matplotlib.cbook import dedent, silent_list, is_string_like, is_numlike
from matplotlib import docstring
from matplotlib.figure import Figure, figaspect
from matplotlib.backend_bases import FigureCanvasBase
from matplotlib.figure import Figure, figaspect
from matplotlib.gridspec import GridSpec
from matplotlib.image import imread as _imread
from matplotlib.image import imsave as _imsave
from matplotlib import rcParams, rcParamsDefault, get_backend
Expand Down Expand Up @@ -207,16 +209,16 @@ def rc_context(rc=None, fname=None):
return matplotlib.rc_context(rc, fname)



@docstring.copy_dedent(matplotlib.rcdefaults)
def rcdefaults():
matplotlib.rcdefaults()
draw_if_interactive()


# The current "image" (ScalarMappable) is retrieved or set
# only via the pyplot interface using the following two
# functions:


def gci():
"""
Get the current colorable artist. Specifically, returns the
Expand Down Expand Up @@ -246,9 +248,7 @@ def sci(im):


## Any Artist ##

# (getp is simply imported)

@docstring.copy(_setp)
def setp(*args, **kwargs):
ret = _setp(*args, **kwargs)
Expand Down Expand Up @@ -1099,7 +1099,6 @@ def subplots(nrows=1, ncols=1, sharex=False, sharey=False, squeeze=True,
return ret


from gridspec import GridSpec
def subplot2grid(shape, loc, rowspan=1, colspan=1, **kwargs):
"""
Create a subplot in a grid. The grid is specified by *shape*, at
Expand Down Expand Up @@ -2091,7 +2090,6 @@ def pad(s, l):

## Plotting part 1: manually generated functions and wrappers ##

import matplotlib.colorbar
def colorbar(mappable=None, cax=None, ax=None, **kw):
if mappable is None:
mappable = gci()
Expand Down

0 comments on commit be049b2

Please sign in to comment.