From: <lee...@us...> - 2010-04-06 17:05:58
|
Revision: 8223 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8223&view=rev Author: leejjoon Date: 2010-04-06 17:05:51 +0000 (Tue, 06 Apr 2010) Log Message: ----------- axes_grid toolkit is splitted into two separate modules, axes_grid1 and axisartist. Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/setup.py Added Paths: ----------- trunk/matplotlib/lib/mpl_toolkits/axes_grid1/ trunk/matplotlib/lib/mpl_toolkits/axes_grid1/__init__.py trunk/matplotlib/lib/mpl_toolkits/axes_grid1/anchored_artists.py trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_divider.py trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_grid.py trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_rgb.py trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_size.py trunk/matplotlib/lib/mpl_toolkits/axes_grid1/colorbar.py trunk/matplotlib/lib/mpl_toolkits/axes_grid1/inset_locator.py trunk/matplotlib/lib/mpl_toolkits/axes_grid1/mpl_axes.py trunk/matplotlib/lib/mpl_toolkits/axes_grid1/parasite_axes.py trunk/matplotlib/lib/mpl_toolkits/axisartist/ trunk/matplotlib/lib/mpl_toolkits/axisartist/__init__.py trunk/matplotlib/lib/mpl_toolkits/axisartist/angle_helper.py trunk/matplotlib/lib/mpl_toolkits/axisartist/axis_artist.py trunk/matplotlib/lib/mpl_toolkits/axisartist/axisline_style.py trunk/matplotlib/lib/mpl_toolkits/axisartist/axislines.py trunk/matplotlib/lib/mpl_toolkits/axisartist/clip_path.py trunk/matplotlib/lib/mpl_toolkits/axisartist/floating_axes.py trunk/matplotlib/lib/mpl_toolkits/axisartist/grid_finder.py trunk/matplotlib/lib/mpl_toolkits/axisartist/grid_helper_curvelinear.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2010-04-05 18:46:18 UTC (rev 8222) +++ trunk/matplotlib/CHANGELOG 2010-04-06 17:05:51 UTC (rev 8223) @@ -1,3 +1,6 @@ +2010-04-06 axes_grid toolkit is splitted into two separate modules, + axes_grid1 and axisartist. -JJL + 2010-04-05 Speed up import: import pytz only if and when it is needed. It is not needed if the rc timezone is UTC. - EF Added: trunk/matplotlib/lib/mpl_toolkits/axes_grid1/__init__.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid1/__init__.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid1/__init__.py 2010-04-06 17:05:51 UTC (rev 8223) @@ -0,0 +1,5 @@ +import axes_size as Size +from axes_divider import Divider, SubplotDivider, LocatableAxes, \ + make_axes_locatable +from axes_grid import Grid, ImageGrid, AxesGrid +#from axes_divider import make_axes_locatable Added: trunk/matplotlib/lib/mpl_toolkits/axes_grid1/anchored_artists.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid1/anchored_artists.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid1/anchored_artists.py 2010-04-06 17:05:51 UTC (rev 8223) @@ -0,0 +1,160 @@ + +from matplotlib.patches import Rectangle, Ellipse + +import numpy as np + +from matplotlib.offsetbox import AnchoredOffsetbox, AuxTransformBox, VPacker,\ + TextArea, AnchoredText, DrawingArea, AnnotationBbox + + +class AnchoredDrawingArea(AnchoredOffsetbox): + """ + AnchoredOffsetbox with DrawingArea + """ + + def __init__(self, width, height, xdescent, ydescent, + loc, pad=0.4, borderpad=0.5, prop=None, frameon=True, + **kwargs): + """ + *width*, *height*, *xdescent*, *ydescent* : the dimensions of the DrawingArea. + *prop* : font property. this is only used for scaling the paddings. + """ + + self.da = DrawingArea(width, height, xdescent, ydescent, clip=True) + self.drawing_area = self.da + + super(AnchoredDrawingArea, self).__init__(loc, pad=pad, borderpad=borderpad, + child=self.da, + prop=None, + frameon=frameon, + **kwargs) + + +class AnchoredAuxTransformBox(AnchoredOffsetbox): + def __init__(self, transform, loc, + pad=0.4, borderpad=0.5, prop=None, frameon=True, **kwargs): + + self.drawing_area = AuxTransformBox(transform) + + AnchoredOffsetbox.__init__(self, loc, pad=pad, borderpad=borderpad, + child=self.drawing_area, + prop=prop, + frameon=frameon, + **kwargs) + + + +class AnchoredEllipse(AnchoredOffsetbox): + def __init__(self, transform, width, height, angle, loc, + pad=0.1, borderpad=0.1, prop=None, frameon=True, **kwargs): + """ + Draw an ellipse the size in data coordinate of the give axes. + + pad, borderpad in fraction of the legend font size (or prop) + """ + self._box = AuxTransformBox(transform) + self.ellipse = Ellipse((0,0), width, height, angle) + self._box.add_artist(self.ellipse) + + AnchoredOffsetbox.__init__(self, loc, pad=pad, borderpad=borderpad, + child=self._box, + prop=prop, + frameon=frameon, **kwargs) + + + +class AnchoredSizeBar(AnchoredOffsetbox): + def __init__(self, transform, size, label, loc, + pad=0.1, borderpad=0.1, sep=2, prop=None, frameon=True, + **kwargs): + """ + Draw a horizontal bar with the size in data coordinate of the give axes. + A label will be drawn underneath (center-alinged). + + pad, borderpad in fraction of the legend font size (or prop) + sep in points. + """ + self.size_bar = AuxTransformBox(transform) + self.size_bar.add_artist(Rectangle((0,0), size, 0, fc="none")) + + self.txt_label = TextArea(label, minimumdescent=False) + + self._box = VPacker(children=[self.size_bar, self.txt_label], + align="center", + pad=0, sep=sep) + + AnchoredOffsetbox.__init__(self, loc, pad=pad, borderpad=borderpad, + child=self._box, + prop=prop, + frameon=frameon, **kwargs) + + +if __name__ == "__main__": + + import matplotlib.pyplot as plt + + fig = plt.gcf() + fig.clf() + ax = plt.subplot(111) + + offsetbox = AnchoredText("Test", loc=6, pad=0.3, + borderpad=0.3, prop=None) + xy = (0.5, 0.5) + ax.plot([0.5], [0.5], "xk") + ab = AnnotationBbox(offsetbox, xy, + xybox=(1., .5), + xycoords='data', + boxcoords=("axes fraction", "data"), + arrowprops=dict(arrowstyle="->")) + #arrowprops=None) + + ax.add_artist(ab) + + + from matplotlib.patches import Circle + ada = AnchoredDrawingArea(20, 20, 0, 0, + loc=6, pad=0.1, borderpad=0.3, frameon=True) + p = Circle((10, 10), 10) + ada.da.add_artist(p) + + ab = AnnotationBbox(ada, (0.3, 0.4), + xybox=(1., 0.4), + xycoords='data', + boxcoords=("axes fraction", "data"), + arrowprops=dict(arrowstyle="->")) + #arrowprops=None) + + ax.add_artist(ab) + + + arr = np.arange(100).reshape((10,10)) + im = AnchoredImage(arr, + loc=4, + pad=0.5, borderpad=0.2, prop=None, frameon=True, + zoom=1, + cmap = None, + norm = None, + interpolation=None, + origin=None, + extent=None, + filternorm=1, + filterrad=4.0, + resample = False, + ) + + ab = AnnotationBbox(im, (0.5, 0.5), + xybox=(-10., 10.), + xycoords='data', + boxcoords="offset points", + arrowprops=dict(arrowstyle="->")) + #arrowprops=None) + + ax.add_artist(ab) + + ax.set_xlim(0, 1) + ax.set_ylim(0, 1) + + + plt.draw() + plt.show() + Added: trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_divider.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_divider.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_divider.py 2010-04-06 17:05:51 UTC (rev 8223) @@ -0,0 +1,753 @@ +""" +The axes_divider module provide helper classes to adjust the positions of +multiple axes at the drawing time. + + Divider: this is the class that is used calculates the axes + position. It divides the given renctangular area into several sub + rectangles. You intialize the divider by setting the horizontal + and vertical list of sizes that the division will be based on. You + then use the new_locator method, whose return value is a callable + object that can be used to set the axes_locator of the axes. + +""" + +import matplotlib.transforms as mtransforms + +from matplotlib.axes import SubplotBase + +import new + +import axes_size as Size + + +class Divider(object): + """ + This is the class that is used calculates the axes position. It + divides the given renctangular area into several + sub-rectangles. You intialize the divider by setting the + horizontal and vertical lists of sizes + (:mod:`mpl_toolkits.axes_grid.axes_size`) that the division will + be based on. You then use the new_locator method to create a + callable object that can be used to as the axes_locator of the + axes. + """ + + + def __init__(self, fig, pos, horizontal, vertical, aspect=None, anchor="C"): + """ + :param fig: matplotlib figure + :param pos: position (tuple of 4 floats) of the rectangle that + will be divided. + :param horizontal: list of sizes + (:mod:`~mpl_toolkits.axes_grid.axes_size`) + for horizontal division + :param vertical: list of sizes + (:mod:`~mpl_toolkits.axes_grid.axes_size`) + for vertical division + :param aspect: if True, the overall rectalngular area is reduced + so that the relative part of the horizontal and + vertical scales have same scale. + :param anchor: Detrmine how the reduced rectangle is placed + when aspect is True, + """ + + self._fig = fig + self._pos = pos + self._horizontal = horizontal + self._vertical = vertical + self._anchor = anchor + self._aspect = aspect + self._xrefindex = 0 + self._yrefindex = 0 + + + @staticmethod + def _calc_k(l, total_size, renderer): + + rs_sum, as_sum = 0., 0. + + for s in l: + _rs, _as = s.get_size(renderer) + rs_sum += _rs + as_sum += _as + + if rs_sum != 0.: + k = (total_size - as_sum) / rs_sum + return k + else: + return 0. + + + @staticmethod + def _calc_offsets(l, k, renderer): + + offsets = [0.] + + for s in l: + _rs, _as = s.get_size(renderer) + offsets.append(offsets[-1] + _rs*k + _as) + + return offsets + + + def set_position(self, pos): + """ + set the position of the rectangle. + + :param pos: position (tuple of 4 floats) of the rectangle that + will be divided. + """ + self._pos = pos + + def get_position(self): + "return the position of the rectangle." + return self._pos + + def set_anchor(self, anchor): + """ + :param anchor: anchor position + + ===== ============ + value description + ===== ============ + 'C' Center + 'SW' bottom left + 'S' bottom + 'SE' bottom right + 'E' right + 'NE' top right + 'N' top + 'NW' top left + 'W' left + ===== ============ + + """ + if anchor in mtransforms.Bbox.coefs.keys() or len(anchor) == 2: + self._anchor = anchor + else: + raise ValueError('argument must be among %s' % + ', '.join(mtransforms.BBox.coefs.keys())) + + def get_anchor(self): + "return the anchor" + return self._anchor + + def set_horizontal(self, h): + """ + :param horizontal: list of sizes + (:mod:`~mpl_toolkits.axes_grid.axes_size`) + for horizontal division + """ + self._horizontal = h + + + def get_horizontal(self): + "return horizontal sizes" + return self._horizontal + + def set_vertical(self, v): + """ + :param horizontal: list of sizes + (:mod:`~mpl_toolkits.axes_grid.axes_size`) + for horizontal division + """ + self._vertical = v + + def get_vertical(self): + "return vertical sizes" + return self._vertical + + + def set_aspect(self, aspect=False): + """ + :param anchor: True or False + """ + self._aspect = aspect + + def get_aspect(self): + "return aspect" + return self._aspect + + + def locate(self, nx, ny, nx1=None, ny1=None, renderer=None): + """ + + :param nx, nx1: Integers specifying the column-position of the + cell. When nx1 is None, a single nx-th column is + specified. Otherwise location of columns spanning between nx + to nx1 (but excluding nx1-th column) is specified. + + :param ny, ny1: same as nx and nx1, but for row positions. + """ + + + figW,figH = self._fig.get_size_inches() + x, y, w, h = self.get_position() + + k_h = self._calc_k(self._horizontal, figW*w, renderer) + k_v = self._calc_k(self._vertical, figH*h, renderer) + + if self.get_aspect(): + k = min(k_h, k_v) + ox = self._calc_offsets(self._horizontal, k, renderer) + oy = self._calc_offsets(self._vertical, k, renderer) + + ww = (ox[-1] - ox[0])/figW + hh = (oy[-1] - oy[0])/figH + pb = mtransforms.Bbox.from_bounds(x, y, w, h) + pb1 = mtransforms.Bbox.from_bounds(x, y, ww, hh) + pb1_anchored = pb1.anchored(self.get_anchor(), pb) + x0, y0 = pb1_anchored.x0, pb1_anchored.y0 + + else: + ox = self._calc_offsets(self._horizontal, k_h, renderer) + oy = self._calc_offsets(self._vertical, k_v, renderer) + x0, y0 = x, y + + + if nx1 is None: + nx1=nx+1 + if ny1 is None: + ny1=ny+1 + + x1, w1 = x0 + ox[nx]/figW, (ox[nx1] - ox[nx])/figW + y1, h1 = y0 + oy[ny]/figH, (oy[ny1] - oy[ny])/figH + + return mtransforms.Bbox.from_bounds(x1, y1, w1, h1) + + + def new_locator(self, nx, ny, nx1=None, ny1=None): + """ + returns a new locator + (:class:`mpl_toolkits.axes_grid.axes_divider.AxesLocator`) for + specified cell. + + :param nx, nx1: Integers specifying the column-position of the + cell. When nx1 is None, a single nx-th column is + specified. Otherwise location of columns spanning between nx + to nx1 (but excluding nx1-th column) is specified. + + :param ny, ny1: same as nx and nx1, but for row positions. + """ + return AxesLocator(self, nx, ny, nx1, ny1) + + + +class AxesLocator(object): + """ + A simple callable object, initiallized with AxesDivider class, + returns the position and size of the given cell. + """ + def __init__(self, axes_divider, nx, ny, nx1=None, ny1=None): + """ + :param axes_divider: An instance of AxesDivider class. + + :param nx, nx1: Integers specifying the column-position of the + cell. When nx1 is None, a single nx-th column is + specified. Otherwise location of columns spanning between nx + to nx1 (but excluding nx1-th column) is is specified. + + :param ny, ny1: same as nx and nx1, but for row positions. + """ + self._axes_divider = axes_divider + + _xrefindex = axes_divider._xrefindex + _yrefindex = axes_divider._yrefindex + + self._nx, self._ny = nx - _xrefindex, ny - _yrefindex + + if nx1 is None: + nx1 = nx+1 + if ny1 is None: + ny1 = ny+1 + + self._nx1 = nx1 - _xrefindex + self._ny1 = ny1 - _yrefindex + + + def __call__(self, axes, renderer): + + _xrefindex = self._axes_divider._xrefindex + _yrefindex = self._axes_divider._yrefindex + + return self._axes_divider.locate(self._nx + _xrefindex, + self._ny + _yrefindex, + self._nx1 + _xrefindex, + self._ny1 + _yrefindex, + renderer) + + + +class SubplotDivider(Divider): + """ + The Divider class whose rectangle area is specified as a subplot grometry. + """ + + + def __init__(self, fig, *args, **kwargs): + """ + *fig* is a :class:`matplotlib.figure.Figure` instance. + + *args* is the tuple (*numRows*, *numCols*, *plotNum*), where + the array of subplots in the figure has dimensions *numRows*, + *numCols*, and where *plotNum* is the number of the subplot + being created. *plotNum* starts at 1 in the upper left + corner and increases to the right. + + If *numRows* <= *numCols* <= *plotNum* < 10, *args* can be the + decimal integer *numRows* * 100 + *numCols* * 10 + *plotNum*. + """ + + self.figure = fig + + if len(args)==1: + s = str(args[0]) + if len(s) != 3: + raise ValueError('Argument to subplot must be a 3 digits long') + rows, cols, num = map(int, s) + elif len(args)==3: + rows, cols, num = args + else: + raise ValueError( 'Illegal argument to subplot') + + + total = rows*cols + num -= 1 # convert from matlab to python indexing + # ie num in range(0,total) + if num >= total: + raise ValueError( 'Subplot number exceeds total subplots') + self._rows = rows + self._cols = cols + self._num = num + + self.update_params() + + pos = self.figbox.bounds + horizontal = kwargs.pop("horizontal", []) + vertical = kwargs.pop("vertical", []) + aspect = kwargs.pop("aspect", None) + anchor = kwargs.pop("anchor", "C") + + if kwargs: + raise Exception("") + + Divider.__init__(self, fig, pos, horizontal, vertical, + aspect=aspect, anchor=anchor) + + + def get_position(self): + "return the bounds of the subplot box" + self.update_params() + return self.figbox.bounds + + + def update_params(self): + 'update the subplot position from fig.subplotpars' + + rows = self._rows + cols = self._cols + num = self._num + + pars = self.figure.subplotpars + left = pars.left + right = pars.right + bottom = pars.bottom + top = pars.top + wspace = pars.wspace + hspace = pars.hspace + totWidth = right-left + totHeight = top-bottom + + figH = totHeight/(rows + hspace*(rows-1)) + sepH = hspace*figH + + figW = totWidth/(cols + wspace*(cols-1)) + sepW = wspace*figW + + rowNum, colNum = divmod(num, cols) + + figBottom = top - (rowNum+1)*figH - rowNum*sepH + figLeft = left + colNum*(figW + sepW) + + self.figbox = mtransforms.Bbox.from_bounds(figLeft, figBottom, + figW, figH) + + +class AxesDivider(Divider): + """ + Divider based on the pre-existing axes. + """ + + def __init__(self, axes): + """ + :param axes: axes + """ + self._axes = axes + self._xref = Size.AxesX(axes) + self._yref = Size.AxesY(axes) + Divider.__init__(self, fig=axes.get_figure(), pos=None, + horizontal=[self._xref], vertical=[self._yref], + aspect=None, anchor="C") + + def _get_new_axes(self, **kwargs): + axes = self._axes + + axes_class = kwargs.pop("axes_class", None) + + if axes_class is None: + if isinstance(axes, SubplotBase): + axes_class = axes._axes_class + else: + axes_class = type(axes) + + ax = axes_class(axes.get_figure(), + axes.get_position(original=True), **kwargs) + + return ax + + + def new_horizontal(self, size, pad=None, pack_start=False, **kwargs): + """ + Add a new axes on the right (or left) side of the main axes. + + :param size: A width of the axes. A :mod:`~mpl_toolkits.axes_grid.axes_size` + instance or if float or string is given, *from_any* + fucntion is used to create one, with *ref_size* set to AxesX instance + of the current axes. + :param pad: pad between the axes. It takes same argument as *size*. + :param pack_start: If False, the new axes is appended at the end + of the list, i.e., it became the right-most axes. If True, it is + inseted at the start of the list, and becomes the left-most axes. + + All extra keywords argument is passed to when creating a axes. + if *axes_class* is given, the new axes will be created as an + instance of the given class. Otherwise, the same class of the + main axes will be used. if Not provided + + """ + + if pad: + if not isinstance(pad, Size._Base): + pad = Size.from_any(pad, + fraction_ref=self._xref) + if pack_start: + self._horizontal.insert(0, pad) + self._xrefindex += 1 + else: + self._horizontal.append(pad) + + if not isinstance(size, Size._Base): + size = Size.from_any(size, + fraction_ref=self._xref) + + if pack_start: + self._horizontal.insert(0, size) + self._xrefindex += 1 + locator = self.new_locator(nx=0, ny=0) + else: + self._horizontal.append(size) + locator = self.new_locator(nx=len(self._horizontal)-1, ny=0) + + ax = self._get_new_axes(**kwargs) + ax.set_axes_locator(locator) + + return ax + + def new_vertical(self, size, pad=None, pack_start=False, **kwargs): + """ + Add a new axes on the top (or bottom) side of the main axes. + + :param size: A height of the axes. A :mod:`~mpl_toolkits.axes_grid.axes_size` + instance or if float or string is given, *from_any* + fucntion is used to create one, with *ref_size* set to AxesX instance + of the current axes. + :param pad: pad between the axes. It takes same argument as *size*. + :param pack_start: If False, the new axes is appended at the end + of the list, i.e., it became the top-most axes. If True, it is + inseted at the start of the list, and becomes the bottom-most axes. + + All extra keywords argument is passed to when creating a axes. + if *axes_class* is given, the new axes will be created as an + instance of the given class. Otherwise, the same class of the + main axes will be used. if Not provided + + """ + + if pad: + if not isinstance(pad, Size._Base): + pad = Size.from_any(pad, + fraction_ref=self._yref) + if pack_start: + self._vertical.insert(0, pad) + self._yrefindex += 1 + else: + self._vertical.append(pad) + + if not isinstance(size, Size._Base): + size = Size.from_any(size, + fraction_ref=self._yref) + + if pack_start: + self._vertical.insert(0, size) + self._yrefindex += 1 + locator = self.new_locator(nx=0, ny=0) + else: + self._vertical.append(size) + locator = self.new_locator(nx=0, ny=len(self._vertical)-1) + + ax = self._get_new_axes(**kwargs) + ax.set_axes_locator(locator) + + return ax + + + def append_axes(self, position, size, pad=None, **kwargs): + """ + create an axes at the given *position* with the same height + (or width) of the main axes. + + *position* + ["left"|"right"|"bottom"|"top"] + + *size* and *pad* should be axes_grid.axes_size compatible. + """ + + if position == "left": + ax = self.new_horizontal(size, pad, pack_start=True, **kwargs) + elif position == "right": + ax = self.new_horizontal(size, pad, pack_start=False, **kwargs) + elif position == "bottom": + ax = self.new_vertical(size, pad, pack_start=True, **kwargs) + elif position == "top": + ax = self.new_vertical(size, pad, pack_start=False, **kwargs) + else: + raise ValueError("the position must be one of left, right, bottom, or top") + + self._fig.add_axes(ax) + return ax + + def get_aspect(self): + if self._aspect is None: + aspect = self._axes.get_aspect() + if aspect == "auto": + return False + else: + return True + else: + return self._aspect + + def get_position(self): + if self._pos is None: + bbox = self._axes.get_position(original=True) + return bbox.bounds + else: + return self._pos + + def get_anchor(self): + if self._anchor is None: + return self._axes.get_anchor() + else: + return self._anchor + + + +class LocatableAxesBase: + def __init__(self, *kl, **kw): + + self._axes_class.__init__(self, *kl, **kw) + + self._locator = None + self._locator_renderer = None + + def set_axes_locator(self, locator): + self._locator = locator + + def get_axes_locator(self): + return self._locator + + def apply_aspect(self, position=None): + + if self.get_axes_locator() is None: + self._axes_class.apply_aspect(self, position) + else: + pos = self.get_axes_locator()(self, self._locator_renderer) + self._axes_class.apply_aspect(self, position=pos) + + + def draw(self, renderer=None, inframe=False): + + self._locator_renderer = renderer + + self._axes_class.draw(self, renderer, inframe) + + + +_locatableaxes_classes = {} +def locatable_axes_factory(axes_class): + + new_class = _locatableaxes_classes.get(axes_class) + if new_class is None: + new_class = new.classobj("Locatable%s" % (axes_class.__name__), + (LocatableAxesBase, axes_class), + {'_axes_class': axes_class}) + _locatableaxes_classes[axes_class] = new_class + + return new_class + +#if hasattr(maxes.Axes, "get_axes_locator"): +# LocatableAxes = maxes.Axes +#else: + +def make_axes_locatable(axes): + if not hasattr(axes, "set_axes_locator"): + new_class = locatable_axes_factory(type(axes)) + axes.__class__ = new_class + + divider = AxesDivider(axes) + locator = divider.new_locator(nx=0, ny=0) + axes.set_axes_locator(locator) + + return divider + + +#from matplotlib.axes import Axes +from mpl_axes import Axes +LocatableAxes = locatable_axes_factory(Axes) + + + +def get_demo_image(): + # prepare image + delta = 0.5 + + extent = (-3,4,-4,3) + import numpy as np + x = np.arange(-3.0, 4.001, delta) + y = np.arange(-4.0, 3.001, delta) + X, Y = np.meshgrid(x, y) + import matplotlib.mlab as mlab + Z1 = mlab.bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0) + Z2 = mlab.bivariate_normal(X, Y, 1.5, 0.5, 1, 1) + Z = (Z1 - Z2) * 10 + + return Z, extent + +def demo_locatable_axes(): + import matplotlib.pyplot as plt + + fig1 = plt.figure(1, (6, 6)) + fig1.clf() + + ## PLOT 1 + # simple image & colorbar + ax = fig1.add_subplot(2, 2, 1) + + Z, extent = get_demo_image() + + im = ax.imshow(Z, extent=extent, interpolation="nearest") + cb = plt.colorbar(im) + plt.setp(cb.ax.get_yticklabels(), visible=False) + + + ## PLOT 2 + # image and colorbar whose location is adjusted in the drawing time. + # a hard way + + divider = SubplotDivider(fig1, 2, 2, 2, aspect=True) + + # axes for image + ax = LocatableAxes(fig1, divider.get_position()) + + # axes for coloarbar + ax_cb = LocatableAxes(fig1, divider.get_position()) + + h = [Size.AxesX(ax), # main axes + Size.Fixed(0.05), # padding, 0.1 inch + Size.Fixed(0.2), # colorbar, 0.3 inch + ] + + v = [Size.AxesY(ax)] + + divider.set_horizontal(h) + divider.set_vertical(v) + + ax.set_axes_locator(divider.new_locator(nx=0, ny=0)) + ax_cb.set_axes_locator(divider.new_locator(nx=2, ny=0)) + + fig1.add_axes(ax) + fig1.add_axes(ax_cb) + + ax_cb.yaxis.set_ticks_position("right") + + Z, extent = get_demo_image() + + im = ax.imshow(Z, extent=extent, interpolation="nearest") + plt.colorbar(im, cax=ax_cb) + plt.setp(ax_cb.get_yticklabels(), visible=False) + + plt.draw() + #plt.colorbar(im, cax=ax_cb) + + + ## PLOT 3 + # image and colorbar whose location is adjusted in the drawing time. + # a easy way + + ax = fig1.add_subplot(2, 2, 3) + divider = make_axes_locatable(ax) + + ax_cb = divider.new_horizontal(size="5%", pad=0.05) + fig1.add_axes(ax_cb) + + im = ax.imshow(Z, extent=extent, interpolation="nearest") + plt.colorbar(im, cax=ax_cb) + plt.setp(ax_cb.get_yticklabels(), visible=False) + + + ## PLOT 4 + # two images side by sied with fixed padding. + + ax = fig1.add_subplot(2, 2, 4) + divider = make_axes_locatable(ax) + + ax2 = divider.new_horizontal(size="100%", pad=0.05) + fig1.add_axes(ax2) + + ax.imshow(Z, extent=extent, interpolation="nearest") + ax2.imshow(Z, extent=extent, interpolation="nearest") + plt.setp(ax2.get_yticklabels(), visible=False) + plt.draw() + plt.show() + + +def demo_fixed_size_axes(): + import matplotlib.pyplot as plt + + fig2 = plt.figure(2, (6, 6)) + + # The first items are for padding and the second items are for the axes. + # sizes are in inch. + h = [Size.Fixed(1.0), Size.Fixed(4.5)] + v = [Size.Fixed(0.7), Size.Fixed(5.)] + + divider = Divider(fig2, (0.0, 0.0, 1., 1.), h, v, aspect=False) + # the width and height of the rectangle is ignored. + + ax = LocatableAxes(fig2, divider.get_position()) + ax.set_axes_locator(divider.new_locator(nx=1, ny=1)) + + fig2.add_axes(ax) + + ax.plot([1,2,3]) + + plt.draw() + plt.show() + #plt.colorbar(im, cax=ax_cb) + + + + + +if __name__ == "__main__": + demo_locatable_axes() + demo_fixed_size_axes() Added: trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_grid.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_grid.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_grid.py 2010-04-06 17:05:51 UTC (rev 8223) @@ -0,0 +1,786 @@ +import matplotlib.cbook as cbook + +import matplotlib.pyplot as plt +import matplotlib.axes as maxes +#import matplotlib.colorbar as mcolorbar +import colorbar as mcolorbar +import matplotlib as mpl +import matplotlib.patches as mpatches +import matplotlib.lines as mlines +import matplotlib.ticker as ticker + +from axes_divider import Size, SubplotDivider, LocatableAxes, Divider + +#import numpy as np + +def _tick_only(ax, bottom_on, left_on): + bottom_off = not bottom_on + left_off = not left_on + # [l.set_visible(bottom_off) for l in ax.get_xticklabels()] + # [l.set_visible(left_off) for l in ax.get_yticklabels()] + # ax.xaxis.label.set_visible(bottom_off) + # ax.yaxis.label.set_visible(left_off) + ax.axis["bottom"].toggle(ticklabels=bottom_off, label=bottom_off) + ax.axis["left"].toggle(ticklabels=left_off, label=left_off) + +class Colorbar(mcolorbar.Colorbar): + def _config_axes_deprecated(self, X, Y): + ''' + Make an axes patch and outline. + ''' + ax = self.ax + ax.set_frame_on(False) + ax.set_navigate(False) + xy = self._outline(X, Y) + ax.update_datalim(xy) + ax.set_xlim(*ax.dataLim.intervalx) + ax.set_ylim(*ax.dataLim.intervaly) + self.outline = mlines.Line2D(xy[:, 0], xy[:, 1], color=mpl.rcParams['axes.edgecolor'], + linewidth=mpl.rcParams['axes.linewidth']) + ax.add_artist(self.outline) + self.outline.set_clip_box(None) + self.outline.set_clip_path(None) + c = mpl.rcParams['axes.facecolor'] + self.patch = mpatches.Polygon(xy, edgecolor=c, + facecolor=c, + linewidth=0.01, + zorder=-1) + ax.add_artist(self.patch) + ticks, ticklabels, offset_string = self._ticker() + + if self.orientation == 'vertical': + ax.set_yticks(ticks) + ax.set_yticklabels(ticklabels) + ax.yaxis.get_major_formatter().set_offset_string(offset_string) + + else: + ax.set_xticks(ticks) + ax.set_xticklabels(ticklabels) + ax.xaxis.get_major_formatter().set_offset_string(offset_string) + + + +class CbarAxesBase(object): + + def colorbar(self, mappable, **kwargs): + locator=kwargs.pop("locator", None) + if locator is None: + locator = ticker.MaxNLocator(5) + self.locator = locator + + kwargs["ticks"] = locator + + + self.hold(True) + if self.orientation in ["top", "bottom"]: + orientation="horizontal" + else: + orientation="vertical" + + cb = Colorbar(self, mappable, orientation=orientation, **kwargs) + self._config_axes() + + def on_changed(m): + #print 'calling on changed', m.get_cmap().name + cb.set_cmap(m.get_cmap()) + cb.set_clim(m.get_clim()) + cb.update_bruteforce(m) + + self.cbid = mappable.callbacksSM.connect('changed', on_changed) + mappable.set_colorbar(cb, self) + return cb + + def _config_axes(self): + ''' + Make an axes patch and outline. + ''' + ax = self + ax.set_navigate(False) + + ax.axis[:].toggle(all=False) + b = self._default_label_on + ax.axis[self.orientation].toggle(all=b) + + # for axis in ax.axis.values(): + # axis.major_ticks.set_visible(False) + # axis.minor_ticks.set_visible(False) + # axis.major_ticklabels.set_visible(False) + # axis.minor_ticklabels.set_visible(False) + # axis.label.set_visible(False) + + # axis = ax.axis[self.orientation] + # axis.major_ticks.set_visible(True) + # axis.minor_ticks.set_visible(True) + + + #axis.major_ticklabels.set_size(int(axis.major_ticklabels.get_size()*.9)) + #axis.major_tick_pad = 3 + + # axis.major_ticklabels.set_visible(b) + # axis.minor_ticklabels.set_visible(b) + # axis.label.set_visible(b) + + + def toggle_label(self, b): + self._default_label_on = b + axis = self.axis[self.orientation] + axis.toggle(ticklabels=b, label=b) + #axis.major_ticklabels.set_visible(b) + #axis.minor_ticklabels.set_visible(b) + #axis.label.set_visible(b) + + + +class CbarAxes(CbarAxesBase, LocatableAxes): + def __init__(self, *kl, **kwargs): + orientation=kwargs.pop("orientation", None) + if orientation is None: + raise ValueError("orientation must be specified") + self.orientation = orientation + self._default_label_on = True + self.locator = None + + super(LocatableAxes, self).__init__(*kl, **kwargs) + + def cla(self): + super(LocatableAxes, self).cla() + self._config_axes() + + +class Grid(object): + """ + A class that creates a grid of Axes. In matplotlib, the axes + location (and size) is specified in the normalized figure + coordinates. This may not be ideal for images that needs to be + displayed with a given aspect ratio. For example, displaying + images of a same size with some fixed padding between them cannot + be easily done in matplotlib. AxesGrid is used in such case. + """ + + _defaultLocatableAxesClass = LocatableAxes + + def __init__(self, fig, + rect, + nrows_ncols, + ngrids = None, + direction="row", + axes_pad = 0.02, + add_all=True, + share_all=False, + share_x=True, + share_y=True, + #aspect=True, + label_mode="L", + axes_class=None, + ): + """ + Build an :class:`Grid` instance with a grid nrows*ncols + :class:`~matplotlib.axes.Axes` in + :class:`~matplotlib.figure.Figure` *fig* with + *rect=[left, bottom, width, height]* (in + :class:`~matplotlib.figure.Figure` coordinates) or + the subplot position code (e.g., "121"). + + Optional keyword arguments: + + ================ ======== ========================================= + Keyword Default Description + ================ ======== ========================================= + direction "row" [ "row" | "column" ] + axes_pad 0.02 float| pad betweein axes given in inches + add_all True [ True | False ] + share_all False [ True | False ] + share_x True [ True | False ] + share_y True [ True | False ] + label_mode "L" [ "L" | "1" | "all" ] + axes_class None a type object which must be a subclass + of :class:`~matplotlib.axes.Axes` + ================ ======== ========================================= + """ + self._nrows, self._ncols = nrows_ncols + + if ngrids is None: + ngrids = self._nrows * self._ncols + else: + if (ngrids > self._nrows * self._ncols) or (ngrids <= 0): + raise Exception("") + + self.ngrids = ngrids + + self._init_axes_pad(axes_pad) + + if direction not in ["column", "row"]: + raise Exception("") + + self._direction = direction + + + if axes_class is None: + axes_class = self._defaultLocatableAxesClass + axes_class_args = {} + else: + if isinstance(axes_class, maxes.Axes): + axes_class_args = {} + else: + axes_class, axes_class_args = axes_class + + self.axes_all = [] + self.axes_column = [[] for i in range(self._ncols)] + self.axes_row = [[] for i in range(self._nrows)] + + + h = [] + v = [] + if cbook.is_string_like(rect) or cbook.is_numlike(rect): + self._divider = SubplotDivider(fig, rect, horizontal=h, vertical=v, + aspect=False) + elif len(rect) == 3: + kw = dict(horizontal=h, vertical=v, aspect=False) + self._divider = SubplotDivider(fig, *rect, **kw) + elif len(rect) == 4: + self._divider = Divider(fig, rect, horizontal=h, vertical=v, + aspect=False) + else: + raise Exception("") + + + rect = self._divider.get_position() + + # reference axes + self._column_refax = [None for i in range(self._ncols)] + self._row_refax = [None for i in range(self._nrows)] + self._refax = None + + for i in range(self.ngrids): + + col, row = self._get_col_row(i) + + if share_all: + sharex = self._refax + sharey = self._refax + else: + if share_x: + sharex = self._column_refax[col] + else: + sharex = None + + if share_y: + sharey = self._row_refax[row] + else: + sharey = None + + ax = axes_class(fig, rect, sharex=sharex, sharey=sharey, + **axes_class_args) + + if share_all: + if self._refax is None: + self._refax = ax + else: + if sharex is None: + self._column_refax[col] = ax + if sharey is None: + self._row_refax[row] = ax + + self.axes_all.append(ax) + self.axes_column[col].append(ax) + self.axes_row[row].append(ax) + + self.axes_llc = self.axes_column[0][-1] + + self._update_locators() + + if add_all: + for ax in self.axes_all: + fig.add_axes(ax) + + self.set_label_mode(label_mode) + + + def _init_axes_pad(self, axes_pad): + self._axes_pad = axes_pad + + self._horiz_pad_size = Size.Fixed(axes_pad) + self._vert_pad_size = Size.Fixed(axes_pad) + + + def _update_locators(self): + + h = [] + + h_ax_pos = [] + h_cb_pos = [] + + for ax in self._column_refax: + #if h: h.append(Size.Fixed(self._axes_pad)) + if h: h.append(self._horiz_pad_size) + + h_ax_pos.append(len(h)) + + sz = Size.Scaled(1) + h.append(sz) + + v = [] + + v_ax_pos = [] + v_cb_pos = [] + for ax in self._row_refax[::-1]: + #if v: v.append(Size.Fixed(self._axes_pad)) + if v: v.append(self._vert_pad_size) + + v_ax_pos.append(len(v)) + sz = Size.Scaled(1) + v.append(sz) + + + for i in range(self.ngrids): + col, row = self._get_col_row(i) + locator = self._divider.new_locator(nx=h_ax_pos[col], + ny=v_ax_pos[self._nrows -1 - row]) + self.axes_all[i].set_axes_locator(locator) + + self._divider.set_horizontal(h) + self._divider.set_vertical(v) + + + + def _get_col_row(self, n): + if self._direction == "column": + col, row = divmod(n, self._nrows) + else: + row, col = divmod(n, self._ncols) + + return col, row + + + def __getitem__(self, i): + return self.axes_all[i] + + + def get_geometry(self): + """ + get geometry of the grid. Returns a tuple of two integer, + representing number of rows and number of columns. + """ + return self._nrows, self._ncols + + def set_axes_pad(self, axes_pad): + "set axes_pad" + self._axes_pad = axes_pad + + self._horiz_pad_size.fixed_size = axes_pad + self._vert_pad_size.fixed_size = axes_pad + + + def get_axes_pad(self): + "get axes_pad" + return self._axes_pad + + def set_aspect(self, aspect): + "set aspect" + self._divider.set_aspect(aspect) + + def get_aspect(self): + "get aspect" + return self._divider.get_aspect() + + def set_label_mode(self, mode): + "set label_mode" + if mode == "all": + for ax in self.axes_all: + _tick_only(ax, False, False) + elif mode == "L": + # left-most axes + for ax in self.axes_column[0][:-1]: + _tick_only(ax, bottom_on=True, left_on=False) + # lower-left axes + ax = self.axes_column[0][-1] + _tick_only(ax, bottom_on=False, left_on=False) + + for col in self.axes_column[1:]: + # axes with no labels + for ax in col[:-1]: + _tick_only(ax, bottom_on=True, left_on=True) + + # bottom + ax = col[-1] + _tick_only(ax, bottom_on=False, left_on=True) + + elif mode == "1": + for ax in self.axes_all: + _tick_only(ax, bottom_on=True, left_on=True) + + ax = self.axes_llc + _tick_only(ax, bottom_on=False, left_on=False) + + +class ImageGrid(Grid): + """ + A class that creates a grid of Axes. In matplotlib, the axes + location (and size) is specified in the normalized figure + coordinates. This may not be ideal for images that needs to be + displayed with a given aspect ratio. For example, displaying + images of a same size with some fixed padding between them cannot + be easily done in matplotlib. ImageGrid is used in such case. + """ + + _defaultCbarAxesClass = CbarAxes + + def __init__(self, fig, + rect, + nrows_ncols, + ngrids = None, + direction="row", + axes_pad = 0.02, + add_all=True, + share_all=False, + aspect=True, + label_mode="L", + cbar_mode=None, + cbar_location="right", + cbar_pad=None, + cbar_size="5%", + cbar_set_cax=True, + axes_class=None, + ): + """ + Build an :class:`ImageGrid` instance with a grid nrows*ncols + :class:`~matplotlib.axes.Axes` in + :class:`~matplotlib.figure.Figure` *fig* with + *rect=[left, bottom, width, height]* (in + :class:`~matplotlib.figure.Figure` coordinates) or + the subplot position code (e.g., "121"). + + Optional keyword arguments: + + ================ ======== ========================================= + Keyword Default Description + ================ ======== ========================================= + direction "row" [ "row" | "column" ] + axes_pad 0.02 float| pad betweein axes given in inches + add_all True [ True | False ] + share_all False [ True | False ] + aspect True [ True | False ] + label_mode "L" [ "L" | "1" | "all" ] + cbar_mode None [ "each" | "single" ] + cbar_location "right" [ "right" | "top" ] + cbar_pad None + cbar_size "5%" + cbar_set_cax True [ True | False ] + axes_class None a type object which must be a subclass + of :class:`~matplotlib.axes.Axes` + ================ ======== ========================================= + + *cbar_set_cax* : if True, each axes in the grid has a cax + attribute that is bind to associated cbar_axes. + """ + self._nrows, self._ncols = nrows_ncols + + if ngrids is None: + ngrids = self._nrows * self._ncols + else: + if (ngrids > self._nrows * self._ncols) or (ngrids <= 0): + raise Exception("") + + self.ngrids = ngrids + + self._axes_pad = axes_pad + + self._colorbar_mode = cbar_mode + self._colorbar_location = cbar_location + if cbar_pad is None: + self._colorbar_pad = axes_pad + else: + self._colorbar_pad = cbar_pad + + self._colorbar_size = cbar_size + + self._init_axes_pad(axes_pad) + + if direction not in ["column", "row"]: + raise Exception("") + + self._direction = direction + + + if axes_class is None: + axes_class = self._defaultLocatableAxesClass + axes_class_args = {} + else: + if isinstance(axes_class, maxes.Axes): + axes_class_args = {} + else: + axes_class, axes_class_args = axes_class + + + + self.axes_all = [] + self.axes_column = [[] for i in range(self._ncols)] + self.axes_row = [[] for i in range(self._nrows)] + + self.cbar_axes = [] + + h = [] + v = [] + if cbook.is_string_like(rect) or cbook.is_numlike(rect): + self._divider = SubplotDivider(fig, rect, horizontal=h, vertical=v, + aspect=aspect) + elif len(rect) == 3: + kw = dict(horizontal=h, vertical=v, aspect=aspect) + self._divider = SubplotDivider(fig, *rect, **kw) + elif len(rect) == 4: + self._divider = Divider(fig, rect, horizontal=h, vertical=v, + aspect=aspect) + else: + raise Exception("") + + + rect = self._divider.get_position() + + # reference axes + self._column_refax = [None for i in range(self._ncols)] + self._row_refax = [None for i in range(self._nrows)] + self._refax = None + + for i in range(self.ngrids): + + col, row = self._get_col_row(i) + + if share_all: + sharex = self._refax + sharey = self._refax + else: + sharex = self._column_refax[col] + sharey = self._row_refax[row] + + ax = axes_class(fig, rect, sharex=sharex, sharey=sharey, + **axes_class_args) + + if share_all: + if self._refax is None: + self._refax = ax + else: + if sharex is None: + self._column_refax[col] = ax + if sharey is None: + self._row_refax[row] = ax + + self.axes_all.append(ax) + self.axes_column[col].append(ax) + self.axes_row[row].append(ax) + + cax = self._defaultCbarAxesClass(fig, rect, + orientation=self._colorbar_location) + self.cbar_axes.append(cax) + + self.axes_llc = self.axes_column[0][-1] + + self._update_locators() + + if add_all: + for ax in self.axes_all+self.cbar_axes: + fig.add_axes(ax) + + if cbar_set_cax: + if self._colorbar_mode == "single": + for ax in self.axes_all: + ax.cax = self.cbar_axes[0] + else: + for ax, cax in zip(self.axes_all, self.cbar_axes): + ax.cax = cax + + self.set_label_mode(label_mode) + + + + def _update_locators(self): + + h = [] + + h_ax_pos = [] + h_cb_pos = [] + for ax in self._column_refax: + if h: h.append(self._horiz_pad_size) #Size.Fixed(self._axes_pad)) + + h_ax_pos.append(len(h)) + + if ax: + sz = Size.AxesX(ax) + else: + sz = Size.AxesX(self.axes_llc) + h.append(sz) + + if self._colorbar_mode == "each" and self._colorbar_location == "right": + h.append(Size.from_any(self._colorbar_pad, sz)) + h_cb_pos.append(len(h)) + h.append(Size.from_any(self._colorbar_size, sz)) + + + v = [] + + v_ax_pos = [] + v_cb_pos = [] + for ax in self._row_refax[::-1]: + if v: v.append(self._horiz_pad_size) #Size.Fixed(self._axes_pad)) + + v_ax_pos.append(len(v)) + if ax: + sz = Size.AxesY(ax) + else: + sz = Size.AxesY(self.axes_llc) + v.append(sz) + + + if self._colorbar_mode == "each" and self._colorbar_location == "top": + v.append(Size.from_any(self._colorbar_pad, sz)) + v_cb_pos.append(len(v)) + v.append(Size.from_any(self._colorbar_size, sz)) + + + for i in range(self.ngrids): + col, row = self._get_col_row(i) + #locator = self._divider.new_locator(nx=4*col, ny=2*(self._nrows - row - 1)) + locator = self._divider.new_locator(nx=h_ax_pos[col], + ny=v_ax_pos[self._nrows -1 - row]) + self.axes_all[i].set_axes_locator(locator) + + if self._colorbar_mode == "each": + if self._colorbar_location == "right": + locator = self._divider.new_locator(nx=h_cb_pos[col], + ny=v_ax_pos[self._nrows -1 - row]) + elif self._colorbar_location == "top": + locator = self._divider.new_locator(nx=h_ax_pos[col], + ny=v_cb_pos[self._nrows -1 - row]) + self.cbar_axes[i].set_axes_locator(locator) + + + if self._colorbar_mode == "single": + if self._colorbar_location == "right": + #sz = Size.Fraction(Size.AxesX(self.axes_llc), self._nrows) + sz = Size.Fraction(self._nrows, Size.AxesX(self.axes_llc)) + h.append(Size.from_any(self._colorbar_pad, sz)) + h.append(Size.from_any(self._colorbar_size, sz)) + locator = self._divider.new_locator(nx=-2, ny=0, ny1=-1) + elif self._colorbar_location == "top": + #sz = Size.Fraction(Size.AxesY(self.axes_llc), self._ncols) + sz = Size.Fraction(self._ncols, Size.AxesY(self.axes_llc)) + v.append(Size.from_any(self._colorbar_pad, sz)) + v.append(Size.from_any(self._colorbar_size, sz)) + locator = self._divider.new_locator(nx=0, nx1=-1, ny=-2) + for i in range(self.ngrids): + self.cbar_axes[i].set_visible(False) + self.cbar_axes[0].set_axes_locator(locator) + self.cbar_axes[0].set_visible(True) + elif self._colorbar_mode == "each": + for i in range(self.ngrids): + self.cbar_axes[i].set_visible(True) + else: + for i in range(self.ngrids): + self.cbar_axes[i].set_visible(False) + self.cbar_axes[i].set_position([1., 1., 0.001, 0.001], + which="active") + + self._divider.set_horizontal(h) + self._divider.set_vertical(v) + + +AxesGrid = ImageGrid + + + +#if __name__ == "__main__": +if 0: + F = plt.figure(1, (7, 6)) + F.clf() + + F.subplots_adjust(left=0.15, right=0.9) + + grid = Grid(F, 111, # similar to subplot(111) + nrows_ncols = (2, 2), + direction="row", + axes_pad = 0.05, + add_all=True, + label_mode = "1", + ) + + + +#if __name__ == "__main__": +if 0: + from axes_divider import get_demo_image + F = plt.figure(1, (9, 3.5)) + F.clf() + + F.subplots_adjust(left=0.05, right=0.98) + + grid = ImageGrid(F, 131, # similar to subplot(111) + nrows_ncols = (2, 2), + direction="row", + axes_pad = 0.05, + add_all=True, + label_mode = "1", + ) + + Z, extent = get_demo_image() + plt.ioff() + for i in range(4): + im = grid[i].imshow(Z, extent=extent, interpolation="nearest") + + # This only affects axes in first column and second row as share_all = False. + grid.axes_llc.set_xticks([-2, 0, 2]) + grid.axes_llc.set_yticks([-2, 0, 2]) + plt.ion() + + + grid = ImageGrid(F, 132, # similar to subplot(111) + nrows_ncols = (2, 2), + direction="row", + axes_pad = 0.0, + add_all=True, + share_all=True, + label_mode = "1", + cbar_mode="single", + ) + + Z, extent = get_demo_image() + plt.ioff() + for i in range(4): + im = grid[i].imshow(Z, extent=extent, interpolation="nearest") + plt.colorbar(im, cax = grid.cbar_axes[0]) + plt.setp(grid.cbar_axes[0].get_yticklabels(), visible=False) + + # This affects all axes as share_all = True. + grid.axes_llc.set_xticks([-2, 0, 2]) + grid.axes_llc.set_yticks([-2, 0, 2]) + + plt.ion() + + + + grid = ImageGrid(F, 133, # similar to subplot(122) + nrows_ncols = (2, 2), + direction="row", + axes_pad = 0.1, + add_all=True, + label_mode = "1", + share_all = True, + cbar_location="top", + cbar_mode="each", + cbar_size="7%", + cbar_pad="2%", + ) + plt.ioff() + for i in range(4): + im = grid[i].imshow(Z, extent=extent, interpolation="nearest") + plt.colorbar(im, cax = grid.cbar_axes[i], + orientation="horizontal") + grid.cbar_axes[i].xaxis.set_ticks_position("top") + plt.setp(grid.cbar_axes[i].get_xticklabels(), visible=False) + + # This affects all axes as share_all = True. + grid.axes_llc.set_xticks([-2, 0, 2]) + grid.axes_llc.set_yticks([-2, 0, 2]) + + plt.ion() + plt.draw() + + Added: trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_rgb.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_rgb.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid1/axes_rgb.py 2010-04-06 17:05:51 UTC (rev 8223) @@ -0,0 +1,162 @@ +import numpy as np +from axes_divider import make_axes_locatable, Size, locatable_axes_factory + +def make_rgb_axes(ax, pad=0.01, axes_class=None, add_all=True): + """ + pad : fraction of the axes height. + """ + + divider = make_axes_locatable(ax) + + pad_size = Size.Fraction(pad, Size.AxesY(ax)) + + xsize = Size.Fraction((1.-2.*pad)/3., Size.AxesX(ax)) + ysize = Size.Fraction((1.-2.*pad)/3., Size.AxesY(ax)) + + divider.set_horizontal([Size.AxesX(ax), pad_size, xsize]) + divider.set_vertical([ysize, pad_size, ysize, pad_size, ysize]) + + ax.set_axes_locator(divider.new_locator(0, 0, ny1=-1)) + + ax_rgb = [] + if axes_class is None: + try: + axes_class = locatable_axes_factory(ax._axes_class) + except AttributeError: + axes_class = locatable_axes_factory(type(ax)) + + for ny in [4, 2, 0]: + ax1 = axes_class(ax.get_figure(), + ax.get_position(original=True), + sharex=ax, sharey=ax) + locator = divider.new_locator(nx=2, ny=ny) + ax1.set_axes_locator(locator) + for t in ax1.yaxis.get_ticklabels() + ax1.xaxis.get_ticklabels(): + t.set_visible(False) + try: + for axis in ax1.axis.values(): + axis.major_ticklabels.set_visible(False) + except AttributeError: + pass + + ax_rgb.append(ax1) + + if add_all: + fig = ax.get_figure() + for ax1 in ax_rgb: + fig.add_axes(ax1) ... [truncated message content] |