From: <lee...@us...> - 2009-04-21 03:13:09
|
Revision: 7056 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7056&view=rev Author: leejjoon Date: 2009-04-21 03:12:53 +0000 (Tue, 21 Apr 2009) Log Message: ----------- Added axes_grid.inset_locator Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/doc/mpl_toolkits/axes_grid/index.rst trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/axes_divider.rst trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/index.rst trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/overview.rst trunk/matplotlib/examples/axes_grid/simple_axes_divider2.py trunk/matplotlib/examples/axes_grid/simple_axes_divider3.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/__init__.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_divider.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_grid.py Added Paths: ----------- trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/ trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/axes_divider_api.rst trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/axes_grid_api.rst trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/axes_size_api.rst trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/index.rst trunk/matplotlib/examples/axes_grid/inset_locator_demo.py trunk/matplotlib/examples/axes_grid/inset_locator_demo2.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_size.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/inset_locator.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-04-19 14:29:07 UTC (rev 7055) +++ trunk/matplotlib/CHANGELOG 2009-04-21 03:12:53 UTC (rev 7056) @@ -1,5 +1,8 @@ ====================================================================== +2009-04-20 Worked on axes_grid documentation. Added + axes_grid.inset_locator. - JJL + 2009-04-17 Initial check-in of the axes_grid toolkit. - JJL 2009-04-17 Added a support for bbox_to_anchor in Added: trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/axes_divider_api.rst =================================================================== --- trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/axes_divider_api.rst (rev 0) +++ trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/axes_divider_api.rst 2009-04-21 03:12:53 UTC (rev 7056) @@ -0,0 +1,18 @@ + +:mod:`mpl_toolkits.axes_grid.axes_divider` +========================================== + +.. autoclass:: mpl_toolkits.axes_grid.axes_divider.Divider + :members: + :undoc-members: + + +.. autoclass:: mpl_toolkits.axes_grid.axes_divider.AxesLocator + :members: + :undoc-members: + +.. autoclass:: mpl_toolkits.axes_grid.axes_divider.SubplotDivider + :members: + +.. autoclass:: mpl_toolkits.axes_grid.axes_divider.AxesDivider + :members: Added: trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/axes_grid_api.rst =================================================================== --- trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/axes_grid_api.rst (rev 0) +++ trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/axes_grid_api.rst 2009-04-21 03:12:53 UTC (rev 7056) @@ -0,0 +1,7 @@ + +:mod:`mpl_toolkits.axes_grid.axes_grid` +======================================= + +.. autoclass:: mpl_toolkits.axes_grid.axes_grid.AxesGrid + :members: + :undoc-members: Added: trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/axes_size_api.rst =================================================================== --- trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/axes_size_api.rst (rev 0) +++ trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/axes_size_api.rst 2009-04-21 03:12:53 UTC (rev 7056) @@ -0,0 +1,6 @@ +:mod:`mpl_toolkits.axes_grid.axes_size` +======================================= + +.. automodule:: mpl_toolkits.axes_grid.axes_size + :members: Fixed, Scaled, AxesX, AxesY, MaxWidth, MaxHeight, Fraction, Padded, from_any + Added: trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/index.rst =================================================================== --- trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/index.rst (rev 0) +++ trunk/matplotlib/doc/mpl_toolkits/axes_grid/api/index.rst 2009-04-21 03:12:53 UTC (rev 7056) @@ -0,0 +1,14 @@ +.. _axes_grid-api-index: + +####################################### + The Matplotlib AxesGrid Toolkit API +####################################### + +:Release: |version| +:Date: |today| + +.. toctree:: + + axes_size_api.rst + axes_divider_api.rst + axes_grid_api.rst Modified: trunk/matplotlib/doc/mpl_toolkits/axes_grid/index.rst =================================================================== --- trunk/matplotlib/doc/mpl_toolkits/axes_grid/index.rst 2009-04-19 14:29:07 UTC (rev 7055) +++ trunk/matplotlib/doc/mpl_toolkits/axes_grid/index.rst 2009-04-21 03:12:53 UTC (rev 7056) @@ -10,7 +10,6 @@ AxesGrid toolkit provides a framework to adjust the position of multiple axes according to their aspects. -.. plot:: mpl_toolkits/axes_grid/figures/demo_axes_grid.py Documentation @@ -20,4 +19,4 @@ :maxdepth: 2 users/index.rst - + api/index.rst Modified: trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/axes_divider.rst =================================================================== --- trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/axes_divider.rst 2009-04-19 14:29:07 UTC (rev 7055) +++ trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/axes_divider.rst 2009-04-21 03:12:53 UTC (rev 7056) @@ -4,15 +4,17 @@ The axes_divider module provide helper classes to adjust the axes positions of set of images in the drawing time. -* *Size* This provides a classese of units that the size of each axes - will be determined. For example, you can specify a fixed size +* :mod:`~mpl_toolkits.axes_grid.axes_size` provides a classese of + units that the size of each axes will be determined. For example, + you can specify a fixed size -* *Divider* this is the class that is used calculates the axes - position. It divides the given renctangular area into several - areas. 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. +* :class:`~mpl_toolkits.axes_grid.axes_size.Divider` this is the class + that is used calculates the axes position. It divides the given + renctangular area into several areas. 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. You first initialize the divider by specifying its grids, i.e., horiz and vert. @@ -25,10 +27,11 @@ divider = Divider(fig, rect, horiz, vert) where, rect is a bounds of the box that will be divided and h0,..h3, -v0,..v2 need to be an callable object that returns a tuple of two -floats. The first float is the relative size, and the second float is -the absolute size. Use of the subclasses contained in the Size class -is recommanded. Lets' consider a following grid. +v0,..v2 need to be an instance of classes in the +:mod:`~mpl_toolkits.axes_grid.axes_size`. They have *get_size* method +that returns a tuple of two floats. The first float is the relative +size, and the second float is the absolute size. Consider a following +grid. +-----+-----+-----+-----+ | v0 | | | | @@ -39,34 +42,34 @@ +-----+-----+-----+-----+ -* h0 => 2, 0 -* h1 => 0, 2 -* h2 => 0, 3 +* v0 => 0, 2 +* v1 => 2, 0 +* v2 => 3, 0 The height of the bottom row is always 2 (axes_divider internally assumes that the unit is inch). The first and the second rows with -height ration of 2:3. For example, if the total height of the grid 6, -the the first and second row will each occupy 2/(2+3) and 3/(2+3) of +height ratio of 2:3. For example, if the total height of the grid 6, +then the first and second row will each occupy 2/(2+3) and 3/(2+3) of (6-1) inches. The widths of columns (horiz) will be similarly determined. When aspect ratio is set, the total height (or width) will be adjusted accordingly. -The Size class is a container class that contains several sub-class +The :mod:`mpl_toolkits.axes_grid.axes_size` contains several classes that can be used to set the horiz and vert. For example, for the vertical configuration above will be:: - from Size import Fixed, Scaled + from mpl_toolkits.axes_grid.axes_size import Fixed, Scaled vert = [Fixed(2), Scaled(2), Scaled(3)] -After you set up the divider object, you -Then you create a locator instance which will be given to the axes.:: +After you set up the divider object, then you create a locator +instance which will be given to the axes.:: locator = divider.new_locator(nx=0, ny=1) ax.set_axes_locator(locator) The return value of the new_locator method is a instance of the -AxesLocator class. It is a callable object that will return the +AxesLocator class. It is a callable object that returns the location and size of the cell at the first column and the second row. You may create a locator that spans over multiple cells.:: Modified: trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/index.rst =================================================================== --- trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/index.rst 2009-04-19 14:29:07 UTC (rev 7055) +++ trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/index.rst 2009-04-21 03:12:53 UTC (rev 7056) @@ -10,3 +10,4 @@ .. toctree:: overview.rst + axes_divider.rst Modified: trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/overview.rst =================================================================== --- trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/overview.rst 2009-04-19 14:29:07 UTC (rev 7055) +++ trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/overview.rst 2009-04-21 03:12:53 UTC (rev 7056) @@ -1,6 +1,6 @@ -================= -AxesGrid Overview -================= +======== +Overview +======== The matplotlib AxesGrid toolkit is a collection of helper classes, mainly to ease displaying (multiple) images in matplotlib. @@ -347,3 +347,44 @@ :include-source: +InsetLocator +============ + +:mod:`mpl_toolkits.axes_grid.inset_locator` provides helper classes +and functions to place your (inset) axes at the anchored position of +the parent axes, similarly to AnchoredArtis. + +Using :func:`mpl_toolkits.axes_grid.inset_locator.inset_axes`, you +can have inset axes whose size is either fixed, or a fixed proportion +of the parent axes. For example,:: + + inset_axes = inset_axes(parent_axes, + width="30%", # width = 30% of parent_bbox + height=1., # height : 1 inch + loc=3) + +creates an inset axes whose width is 30% of the parent axes and whose +height is fixed at 1 inch. + +You may creates your inset whose size is determined so that the data +scale of the inset axes to be that of the parent axes multiplied by +some factor. For example, :: + + inset_axes = zoomed_inset_axes(ax, + 0.5, # zoom = 0.5 + loc=1) + +creates an inset axes whose data scale is half of the parent axes. +Here is complete examples. + +.. plot:: mpl_toolkits/axes_grid/figures/inset_locator_demo.py + +For example, :func:`zoomed_inset_axes` can be used when you want the +inset represents the zoom-up of the small portion in the parent axes. +And :mod:`~mpl_toolkits/axes_grid/inset_locator` provides a helper +function :func:`mark_inset` to mark the location of the area +represented by the inset axes. + +.. plot:: mpl_toolkits/axes_grid/figures/inset_locator_demo2.py + :include-source: + Added: trunk/matplotlib/examples/axes_grid/inset_locator_demo.py =================================================================== --- trunk/matplotlib/examples/axes_grid/inset_locator_demo.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/inset_locator_demo.py 2009-04-21 03:12:53 UTC (rev 7056) @@ -0,0 +1,45 @@ +import matplotlib.pyplot as plt + +from mpl_toolkits.axes_grid.inset_locator import inset_axes, zoomed_inset_axes +from mpl_toolkits.axes_grid.anchored_artists import AnchoredSizeBar + + +def add_sizebar(ax, size): + as = AnchoredSizeBar(ax.transData, + size, + str(size), + loc=8, + pad=0.1, borderpad=0.5, sep=5, + frameon=False) + ax.add_artist(as) + + +fig = plt.figure(1, [5.5, 3]) + +# first subplot +ax = fig.add_subplot(1,2,1) +ax.set_aspect(1.) + +axins = inset_axes(ax, + width="30%", # width = 30% of parent_bbox + height=1., # height : 1 inch + loc=3) + +plt.xticks(visible=False) +plt.yticks(visible=False) + + +# second subplot +ax = fig.add_subplot(1,2,2) +ax.set_aspect(1.) + +axins = zoomed_inset_axes(ax, 0.5, loc=1) # zoom = 0.5 + +plt.xticks(visible=False) +plt.yticks(visible=False) + +add_sizebar(ax, 0.5) +add_sizebar(axins, 0.5) + +plt.draw() +plt.show() Added: trunk/matplotlib/examples/axes_grid/inset_locator_demo2.py =================================================================== --- trunk/matplotlib/examples/axes_grid/inset_locator_demo2.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/inset_locator_demo2.py 2009-04-21 03:12:53 UTC (rev 7056) @@ -0,0 +1,42 @@ +import matplotlib.pyplot as plt + +from mpl_toolkits.axes_grid.inset_locator import zoomed_inset_axes +from mpl_toolkits.axes_grid.inset_locator import mark_inset + +import numpy as np + +from demo_image import get_demo_image + + +fig = plt.figure(1, [5,4]) +ax = fig.add_subplot(111) + +# prepare the demo image +Z, extent = get_demo_image() +Z2 = np.zeros([150, 150], dtype="d") +ny, nx = Z.shape +Z2[30:30+ny, 30:30+nx] = Z + +# extent = [-3, 4, -4, 3] +ax.imshow(Z2, extent=extent, interpolation="nearest", + origin="lower") + +axins = zoomed_inset_axes(ax, 6, loc=1) # zoom = 6 +axins.imshow(Z2, extent=extent, interpolation="nearest", + origin="lower") + +# sub region of the original image +x1, x2, y1, y2 = -1.5, -0.9, -2.5, -1.9 +axins.set_xlim(x1, x2) +axins.set_ylim(y1, y2) + +plt.xticks(visible=False) +plt.yticks(visible=False) + +# draw a bbox of the region of the inset axes in the parent axes and +# connecting lines between the bbox and the inset axes area +mark_inset(ax, axins, loc1=2, loc2=4, fc="none", ec="0.5") + +plt.draw() +plt.show() + Modified: trunk/matplotlib/examples/axes_grid/simple_axes_divider2.py =================================================================== --- trunk/matplotlib/examples/axes_grid/simple_axes_divider2.py 2009-04-19 14:29:07 UTC (rev 7055) +++ trunk/matplotlib/examples/axes_grid/simple_axes_divider2.py 2009-04-21 03:12:53 UTC (rev 7056) @@ -1,4 +1,5 @@ -from mpl_toolkits.axes_grid import Size, Divider +import mpl_toolkits.axes_grid.axes_size as Size +from mpl_toolkits.axes_grid import Divider import matplotlib.pyplot as plt fig1 = plt.figure(1, (5.5, 4.)) Modified: trunk/matplotlib/examples/axes_grid/simple_axes_divider3.py =================================================================== --- trunk/matplotlib/examples/axes_grid/simple_axes_divider3.py 2009-04-19 14:29:07 UTC (rev 7055) +++ trunk/matplotlib/examples/axes_grid/simple_axes_divider3.py 2009-04-21 03:12:53 UTC (rev 7056) @@ -1,4 +1,5 @@ -from mpl_toolkits.axes_grid import Size, Divider +import mpl_toolkits.axes_grid.axes_size as Size +from mpl_toolkits.axes_grid import Divider import matplotlib.pyplot as plt Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/__init__.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/__init__.py 2009-04-19 14:29:07 UTC (rev 7055) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/__init__.py 2009-04-21 03:12:53 UTC (rev 7056) @@ -3,7 +3,8 @@ """ -from axes_divider import Divider, SubplotDivider, LocatableAxes, Size, \ +from axes_divider import Divider, SubplotDivider, LocatableAxes, \ make_axes_locatable from axes_grid import AxesGrid +#from axes_divider import make_axes_locatable Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_divider.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_divider.py 2009-04-19 14:29:07 UTC (rev 7055) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_divider.py 2009-04-21 03:12:53 UTC (rev 7056) @@ -1,189 +1,56 @@ """ -The axes_divider module provide helper classes to adjust the axes -positions of set of images in the drawing time. +The axes_divider module provide helper classes to adjust the positions of +multiple axes at the drawing time. - Size: This provides a classese of units that the size of each axes - will be determined. For example, you can specify a fixed size - - Divider: this is the class that uis used calculates the axes - position. It divides the given renctangular area into several - areas. You intialize the divider by setting the horizontal and - vertical list of sizes that the division will be based on. You + 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.axes as maxes import matplotlib.transforms as mtransforms -import matplotlib.cbook as cbook from matplotlib.axes import SubplotBase import new +import axes_size as Size -class Size(object): - """ - provides a classese of units that will be used with AxesDivider - class (or others) to determine the size of each axes. The unit - classes define __call__ that returns a tuple of two floats, - meaning relative and absolute sizes, respectively. - Note that this class is nothing more than a simple tuple of two - floats. Take a look at the Divider class to see how these two - values are used. - +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. + """ - class _Base(object): - "Base class" - pass - - class Fixed(_Base): - "Simple fixed size with relative part = 0" - def __init__(self, fixed_size): - self._fixed_size = fixed_size - - def get_size(self, renderer): - rel_size = 0. - abs_size = self._fixed_size - return rel_size, abs_size - - class Scaled(_Base): - "Simple scaled(?) size with absolute part = 0" - def __init__(self, scalable_size): - self._scalable_size = scalable_size - - def get_size(self, renderer): - rel_size = self._scalable_size - abs_size = 0. - return rel_size, abs_size - - Scalable=Scaled - - class AxesX(_Base): + + def __init__(self, fig, pos, horizontal, vertical, aspect=None, anchor="C"): """ - Scaled size whose relative part corresponds to the data width - of the given axes + :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, """ - def __init__(self, axes, aspect=1.): - self._axes = axes - self._aspect = aspect - - def get_size(self, renderer): - l1, l2 = self._axes.get_xlim() - rel_size = abs(l2-l1)*self._aspect - abs_size = 0. - return rel_size, abs_size - - class AxesY(_Base): - """ - Scaled size whose relative part corresponds to the data height - of the given axes - """ - def __init__(self, axes, aspect=1.): - self._axes = axes - self._aspect = aspect - - def get_size(self, renderer): - l1, l2 = self._axes.get_ylim() - rel_size = abs(l2-l1)*self._aspect - abs_size = 0. - return rel_size, abs_size - - - class MaxExtent(_Base): - """ - Size whose absolute part is the largest width (or height) of - the given list of artists. - """ - def __init__(self, artist_list, w_or_h): - self._artist_list = artist_list - - if w_or_h not in ["width", "height"]: - raise ValueError() - - self._w_or_h = w_or_h - - def add_artist(self, a): - self._artist_list.append(a) - - def get_size(self, renderer): - rel_size = 0. - w_list, h_list = [], [] - for a in self._artist_list: - bb = a.get_window_extent(renderer) - w_list.append(bb.width) - h_list.append(bb.height) - dpi = a.get_figure().get_dpi() - if self._w_or_h == "width": - abs_size = max(w_list)/dpi - elif self._w_or_h == "height": - abs_size = max(h_list)/dpi - - return rel_size, abs_size - - class Fraction(_Base): - """ - An instance whose size is a fraction of the reference size. - ex) s = Fraction(0.3, AxesX(ax)) - """ - def __init__(self, fraction, fraction_ref): - self._fraction_ref = fraction_ref - self._fraction = fraction - - def get_size(self, renderer): - if self._fraction_ref is None: - return self._fraction, 0. - else: - r, a = self._fraction_ref.get_size(renderer) - rel_size = r*self._fraction - abs_size = a*self._fraction - return rel_size, abs_size - - @classmethod - def from_any(self, size, fraction_ref=None): - """ - Creates Fixed unit when the first argument is a float, or a - Fraction unit if that is a string that ends with %. The second - argument is only meaningful when Fraction unit is created. - - >>> a = Size.from_any(1.2) # => Size.Fixed(1.2) - >>> Size.from_any("50%", a) # => Size.Fraction(0.5, a) - - """ - if cbook.is_numlike(size): - return Size.Fixed(size) - elif cbook.is_string_like(size): - if size[-1] == "%": - return Size.Fraction(float(size[:-1])/100., fraction_ref) - - raise ValueError("Unknown format") - - - - class Padded(_Base): - """ - Return a instance where the absolute part of *size* is - increase by the amount of *pad*. - """ - def __init__(self, size, pad): - self._size = size - self._pad = pad - - def get_size(self, renderer): - r, a = self._size.get_size(renderer) - rel_size = r - abs_size = a + self._pad - return rel_size, abs_size - - - - -class Divider(object): - - def __init__(self, fig, pos, horizontal, vertical, aspect=None, anchor="C"): + self._fig = fig self._pos = pos self._horizontal = horizontal @@ -224,14 +91,21 @@ 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): """ - *anchor* + :param anchor: anchor position ===== ============ value description @@ -254,43 +128,56 @@ 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 get_anchor(self): - return self._anchor - - def set_aspect(self, aspect=False): """ - *aspect* : True or 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): """ - 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 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. - ny, ny1 : same as nx and nx1, but for row positions. + :param ny, ny1: same as nx and nx1, but for row positions. """ @@ -330,6 +217,18 @@ 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) @@ -341,14 +240,14 @@ """ def __init__(self, axes_divider, nx, ny, nx1=None, ny1=None): """ - 'axes_divider' : An instance of AxesDivider class. + :param axes_divider: An instance of AxesDivider class. - 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 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. - ny, ny1 : same as nx and nx1, but for row positions. + :param ny, ny1: same as nx and nx1, but for row positions. """ self._axes_divider = axes_divider @@ -371,14 +270,20 @@ _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, + 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. @@ -431,6 +336,7 @@ def get_position(self): + "return the bounds of the subplot box" self.update_params() return self.figbox.bounds @@ -468,9 +374,14 @@ 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) @@ -494,8 +405,27 @@ 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, @@ -518,18 +448,32 @@ self._horizontal.append(size) locator = self.new_locator(nx=len(self._horizontal)-1, ny=0) - #axes_class = type(self._axes) ax = self._get_new_axes(**kwargs) - #ax = axes_class(self._axes.get_figure(), - # self._axes.get_position(original=True), - # **kwargs) locator = self.new_locator(nx=len(self._horizontal)-1, ny=0) 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, @@ -553,10 +497,6 @@ locator = self.new_locator(nx=0, ny=len(self._vertical)-1) ax = self._get_new_axes(**kwargs) - #axes_class = type(self._axes) - #ax = axes_class(self._axes.get_figure(), - # self._axes.get_position(original=True), - # **kwargs) ax.set_axes_locator(locator) return ax @@ -650,3 +590,138 @@ return divider +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() Modified: trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_grid.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_grid.py 2009-04-19 14:29:07 UTC (rev 7055) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_grid.py 2009-04-21 03:12:53 UTC (rev 7056) @@ -53,16 +53,11 @@ ticks, ticklabels, offset_string = self._ticker() if self.orientation == 'vertical': - #ax.set_xticks([]) - #ax.yaxis.set_label_position('right') - #ax.yaxis.set_ticks_position('right') ax.set_yticks(ticks) ax.set_yticklabels(ticklabels) ax.yaxis.get_major_formatter().set_offset_string(offset_string) else: - #ax.set_yticks([]) - #ax.xaxis.set_label_position('bottom') ax.set_xticks(ticks) ax.set_xticklabels(ticklabels) ax.xaxis.get_major_formatter().set_offset_string(offset_string) @@ -150,17 +145,12 @@ class AxesGrid(object): """ - The :class:`Axes` contains most of the figure elements: - :class:`~matplotlib.axis.Axis`, :class:`~matplotlib.axis.Tick`, - :class:`~matplotlib.lines.Line2D`, :class:`~matplotlib.text.Text`, - :class:`~matplotlib.patches.Polygon`, etc., and sets the - coordinate system. - - The :class:`Axes` instance supports callbacks through a callbacks - attribute which is a :class:`~matplotlib.cbook.CallbackRegistry` - instance. The events you can connect to are 'xlim_changed' and - 'ylim_changed' and the callback will be called with func(*ax*) - where *ax* is the :class:`Axes` instance. + 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. """ def __init__(self, fig, @@ -275,7 +265,7 @@ for i in range(self.ngrids): - col, row = self.get_col_row(i) + col, row = self._get_col_row(i) if share_all: sharex = self._refax @@ -359,7 +349,7 @@ for i in range(self.ngrids): - col, row = self.get_col_row(i) + 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]) @@ -406,7 +396,7 @@ - def get_col_row(self, n): + def _get_col_row(self, n): if self._direction == "column": col, row = divmod(n, self._nrows) else: @@ -420,80 +410,57 @@ 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 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) - #[l.set_visible(True) for l in ax.get_xticklabels()] - #[l.set_visible(True) for l in ax.get_yticklabels()] elif mode == "L": # left-most axes for ax in self.axes_column[0][:-1]: _tick_only(ax, bottom_on=True, left_on=False) - #[l.set_visible(False) for l in ax.get_xticklabels()] - #[l.set_visible(True) for l in ax.get_yticklabels()] - #if hasattr(ax, "_axislines"): - # ax._axislines["left"].major_ticklabels.set_visible(True) - # ax._axislines["bottom"].major_ticklabels.set_visible(False) # lower-left axes ax = self.axes_column[0][-1] _tick_only(ax, bottom_on=False, left_on=False) - #[l.set_visible(True) for l in ax.get_xticklabels()] - #[l.set_visible(True) for l in ax.get_yticklabels()] - #if hasattr(ax, "_axislines"): - # ax._axislines["left"].major_ticklabels.set_visible(True) - # ax._axislines["bottom"].major_ticklabels.set_visible(True) 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) - #[l.set_visible(False) for l in ax.get_xticklabels()] - #[l.set_visible(False) for l in ax.get_yticklabels()] - #if hasattr(ax, "_axislines"): - # ax._axislines["left"].major_ticklabels.set_visible(False) - # ax._axislines["bottom"].major_ticklabels.set_visible(False) # bottom ax = col[-1] _tick_only(ax, bottom_on=False, left_on=True) - #[l.set_visible(True) for l in ax.get_xticklabels()] - #[l.set_visible(False) for l in ax.get_yticklabels()] - #if hasattr(ax, "_axislines"): - # ax._axislines["left"].major_ticklabels.set_visible(False) - # ax._axislines["bottom"].major_ticklabels.set_visible(True) elif mode == "1": for ax in self.axes_all: _tick_only(ax, bottom_on=True, left_on=True) - #[l.set_visible(False) for l in ax.get_xticklabels()] - #[l.set_visible(False) for l in ax.get_yticklabels()] - #if hasattr(ax, "_axislines"): - # for axisline in ax._axislines.values(): - # axisline.major_ticklabels.set_visible(False) ax = self.axes_llc _tick_only(ax, bottom_on=False, left_on=False) - #[l.set_visible(True) for l in ax.get_xticklabels()] - #[l.set_visible(True) for l in ax.get_yticklabels()] - #if hasattr(ax, "_axislines"): - # ax._axislines["left"].major_ticklabels.set_visible(True) - # ax._axislines["bottom"].major_ticklabels.set_visible(True) Added: trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_size.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_size.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_size.py 2009-04-21 03:12:53 UTC (rev 7056) @@ -0,0 +1,207 @@ + +""" +provides a classese of simlpe units that will be used with AxesDivider +class (or others) to determine the size of each axes. The unit +classes define `get_size` method that returns a tuple of two floats, +meaning relative and absolute sizes, respectively. + +Note that this class is nothing more than a simple tuple of two +floats. Take a look at the Divider class to see how these two +values are used. + +""" + +import matplotlib.cbook as cbook + + +class _Base(object): + "Base class" + pass + +class Fixed(_Base): + "Simple fixed size with absolute part = *fixed_size* and relative part = 0" + def __init__(self, fixed_size): + self._fixed_size = fixed_size + + def get_size(self, renderer): + rel_size = 0. + abs_size = self._fixed_size + return rel_size, abs_size + +class Scaled(_Base): + "Simple scaled(?) size with absolute part = 0 and relative part = *scalable_size*" + def __init__(self, scalable_size): + self._scalable_size = scalable_size + + def get_size(self, renderer): + rel_size = self._scalable_size + abs_size = 0. + return rel_size, abs_size + +Scalable=Scaled + + +class AxesX(_Base): + """ + Scaled size whose relative part corresponds to the data width + of the *axes* multiplied by the *aspect*. + """ + def __init__(self, axes, aspect=1.): + self._axes = axes + self._aspect = aspect + + def get_size(self, renderer): + l1, l2 = self._axes.get_xlim() + rel_size = abs(l2-l1)*self._aspect + abs_size = 0. + return rel_size, abs_size + +class AxesY(_Base): + """ + Scaled size whose relative part corresponds to the data height + of the *axes* multiplied by the *aspect*. + """ + def __init__(self, axes, aspect=1.): + self._axes = axes + self._aspect = aspect + + def get_size(self, renderer): + l1, l2 = self._axes.get_ylim() + rel_size = abs(l2-l1)*self._aspect + abs_size = 0. + return rel_size, abs_size + + +class MaxExtent(_Base): + """ + Size whose absolute part is the largest width (or height) of + the given *artist_list*. + """ + def __init__(self, artist_list, w_or_h): + self._artist_list = artist_list + + if w_or_h not in ["width", "height"]: + raise ValueError() + + self._w_or_h = w_or_h + + def add_artist(self, a): + self._artist_list.append(a) + + def get_size(self, renderer): + rel_size = 0. + w_list, h_list = [], [] + for a in self._artist_list: + bb = a.get_window_extent(renderer) + w_list.append(bb.width) + h_list.append(bb.height) + dpi = a.get_figure().get_dpi() + if self._w_or_h == "width": + abs_size = max(w_list)/dpi + elif self._w_or_h == "height": + abs_size = max(h_list)/dpi + + return rel_size, abs_size + + +class MaxWidth(_Base): + """ + Size whose absolute part is the largest width of + the given *artist_list*. + """ + def __init__(self, artist_list): + self._artist_list = artist_list + + def add_artist(self, a): + self._artist_list.append(a) + + def get_size(self, renderer): + rel_size = 0. + w_list = [] + for a in self._artist_list: + bb = a.get_window_extent(renderer) + w_list.append(bb.width) + dpi = a.get_figure().get_dpi() + abs_size = max(w_list)/dpi + + return rel_size, abs_size + + + +class MaxHeight(_Base): + """ + Size whose absolute part is the largest height of + the given *artist_list*. + """ + def __init__(self, artist_list): + self._artist_list = artist_list + + def add_artist(self, a): + self._artist_list.append(a) + + def get_size(self, renderer): + rel_size = 0. + h_list = [] + for a in self._artist_list: + bb = a.get_window_extent(renderer) + h_list.append(bb.height) + dpi = a.get_figure().get_dpi() + abs_size = max(h_list)/dpi + + return rel_size, abs_size + + +class Fraction(_Base): + """ + An instance whose size is a *fraction* of the *ref_size*. + + >>> s = Fraction(0.3, AxesX(ax)) + + """ + def __init__(self, fraction, ref_size): + self._fraction_ref = ref_size + self._fraction = fraction + + def get_size(self, renderer): + if self._fraction_ref is None: + return self._fraction, 0. + else: + r, a = self._fraction_ref.get_size(renderer) + rel_size = r*self._fraction + abs_size = a*self._fraction + return rel_size, abs_size + +class Padded(_Base): + """ + Return a instance where the absolute part of *size* is + increase by the amount of *pad*. + """ + def __init__(self, size, pad): + self._size = size + self._pad = pad + + def get_size(self, renderer): + r, a = self._size.get_size(renderer) + rel_size = r + abs_size = a + self._pad + return rel_size, abs_size + +def from_any(size, fraction_ref=None): + """ + Creates Fixed unit when the first argument is a float, or a + Fraction unit if that is a string that ends with %. The second + argument is only meaningful when Fraction unit is created. + + >>> a = Size.from_any(1.2) # => Size.Fixed(1.2) + >>> Size.from_any("50%", a) # => Size.Fraction(0.5, a) + + """ + if cbook.is_numlike(size): + return Fixed(size) + elif cbook.is_string_like(size): + if size[-1] == "%": + return Fraction(float(size[:-1])/100., fraction_ref) + + raise ValueError("Unknown format") + + Added: trunk/matplotlib/lib/mpl_toolkits/axes_grid/inset_locator.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/inset_locator.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/inset_locator.py 2009-04-21 03:12:53 UTC (rev 7056) @@ -0,0 +1,308 @@ +from matplotlib.offsetbox import AnchoredOffsetbox +#from matplotlib.transforms import IdentityTransform + +import matplotlib.transforms as mtrans +from matplotlib.axes import Axes + +from matplotlib.transforms import Bbox, TransformedBbox, IdentityTransform + +from matplotlib.patches import Patch +from matplotlib.path import Path + +from matplotlib.patches import Rectangle + + +class InsetPosition(object): + def __init__(self, parent, lbwh): + self.parent = parent + self.lbwh = lbwh # position of the inset axes in the normalized coordinate of the parent axes + + def __call__(self, ax, renderer): + bbox_parent = self.parent.get_position(original=False) + trans = mtrans.BboxTransformTo(bbox_parent) + bbox_inset = mtrans.Bbox.from_bounds(*self.lbwh) + bb = mtrans.TransformedBbox(bbox_inset, trans) + return bb + + +class AnchoredLocatorBase(AnchoredOffsetbox): + def __init__(self, bbox_to_anchor, offsetbox, loc, + borderpad=0.5, bbox_transform=None): + + super(AnchoredLocatorBase, self).__init__(loc, + pad=0., child=None, + borderpad=borderpad, + bbox_to_anchor=bbox_to_anchor, + bbox_transform=bbox_transform) + + + def draw(self, renderer): + raise RuntimeError("No draw method should be called") + + + def __call__(self, ax, renderer): + + fontsize = renderer.points_to_pixels(self.prop.get_size_in_points()) + self._update_offset_func(renderer, fontsize) + + width, height, xdescent, ydescent = self.get_extent(renderer) + + px, py = self.get_offset(width, height, 0, 0) + bbox_canvas = mtrans.Bbox.from_bounds(px, py, width, height) + tr = ax.figure.transFigure.inverted() + bb = mtrans.TransformedBbox(bbox_canvas, tr) + + return bb + + + + +from mpl_toolkits.axes_grid.axes_divider import Size + +class AnchoredSizeLocator(AnchoredLocatorBase): + def __init__(self, bbox_to_anchor, x_size, y_size, loc, + borderpad=0.5, bbox_transform=None): + + self.axes = None + self.x_size = Size.from_any(x_size) + self.y_size = Size.from_any(y_size) + + super(AnchoredSizeLocator, self).__init__(bbox_to_anchor, None, loc, + borderpad=borderpad, + bbox_transform=bbox_transform) + + def get_extent(self, renderer): + + x, y, w, h = self.get_bbox_to_anchor().bounds + + dpi = renderer.points_to_pixels(72.) + + r, a = self.x_size.get_size(renderer) + width = w*r + a*dpi + + r, a = self.y_size.get_size(renderer) + height = h*r + a*dpi + xd, yd = 0, 0 + + fontsize = renderer.points_to_pixels(self.prop.get_size_in_points()) + pad = self.pad * fontsize + + return width+2*pad, height+2*pad, xd+pad, yd+pad + + + def __call__(self, ax, renderer): + + self.axes = ax + return super(AnchoredSizeLocator, self).__call__(ax, renderer) + + +class AnchoredZoomLocator(AnchoredLocatorBase): + def __init__(self, parent_axes, zoom, loc, + borderpad=0.5, + bbox_to_anchor=None, + bbox_transform=None): + + self.parent_axes = parent_axes + self.zoom = zoom + + if bbox_to_anchor is None: + bbox_to_anchor = parent_axes.bbox + + super(AnchoredZoomLocator, self).__init__(bbox_to_anchor, None, loc, + borderpad=borderpad, + bbox_transform=bbox_transform) + + self.axes = None + + + def get_extent(self, renderer): + + bb = mtrans.TransformedBbox(self.axes.viewLim, self.parent_axes.transData) + + x, y, w, h = bb.bounds + + xd, yd = 0, 0 + + fontsize = renderer.points_to_pixels(self.prop.get_size_in_points()) + pad = self.pad * fontsize + + return w*self.zoom+2*pad, h*self.zoom+2*pad, xd+pad, yd+pad + + + def __call__(self, ax, renderer): + + self.axes = ax + return super(AnchoredZoomLocator, self).__call__(ax, renderer) + + + + + + +class BboxPatch(Patch): + def __init__(self, bbox, **kwargs): + if "transform" in kwargs: + raise ValueError("trnasform should nt be set") + + kwargs["transform"] = IdentityTransform() + Patch.__init__(self, **kwargs) + self.bbox = bbox + + def get_path(self): + x0, y0, x1, y1 = self.bbox.extents + + verts = [(x0, y0), + (x1, y0), + (x1, y1), + (x0, y1), + (x0, y0), + (0,0)] + + codes = [Path.MOVETO, + Path.LINETO, + Path.LINETO, + Path.LINETO, + Path.LINETO, + Path.CLOSEPOLY] + + return Path(verts, codes) + + + + +class BboxConnector(Patch): + + @staticmethod + def get_bbox_edge_pos(bbox, loc): + x0, y0, x1, y1 = bbox.extents + if loc==1: + return x1, y1 + elif loc==2: + return x0, y1 + elif loc==3: + return x0, y0 + elif loc==4: + return x1, y0 + + @staticmethod + def connect_bbox(bbox1, bbox2, loc1, loc2=None): + if isinstance(bbox1, Rectangle): + transform = bbox1.get_transfrom() + bbox1 = Bbox.from_bounds(0, 0, 1, 1) + bbox1 = TransformedBbox(bbox1, transform) + + if isinstance(bbox2, Rectangle): + transform = bbox2.get_transform() + bbox2 = Bbox.from_bounds(0, 0, 1, 1) + bbox2 = TransformedBbox(bbox2, transform) + + if loc2 is None: + loc2 = loc1 + + x1, y1 = BboxConnector.get_bbox_edge_pos(bbox1, loc1) + x2, y2 = BboxConnector.get_bbox_edge_pos(bbox2, loc2) + + verts = [[x1, y1], [x2,y2]] + #Path() + + codes = [Path.MOVETO, Path.LINETO] + + return Path(verts, codes) + + + def __init__(self, bbox1, bbox2, loc1, loc2=None, **kwargs): + """ + *path* is a :class:`matplotlib.path.Path` object. + + Valid kwargs are: + %(Patch)s + + .. seealso:: + + :class:`Patch` + For additional kwargs + + """ + if "transform" in kwargs: + raise ValueError("trnasform should nt be set") + + kwargs["transform"] = IdentityTransform() + Patch.__init__(self, **kwargs) + self.bbox1 = bbox1 + self.bbox2 = bbox2 + self.loc1 = loc1 + self.loc2 = loc2 + + + def get_path(self): + return self.connect_bbox(self.bbox1, self.bbox2, + self.loc1, self.loc2) + + +def _add_inset_axes(parent_axes, inset_axes): + parent_axes.figure.add_axes(inset_axes) + inset_axes.set_navigate(False) + + +def inset_axes(parent_axes, width, height, loc=1, + bbox_to_anchor=None, bbox_transform=None, + axes_kwargs=None, + **kwargs): + + if axes_kwargs is None: + inset_axes = Axes(parent_axes.figure, parent_axes.get_position()) + else: + inset_axes = Axes(parent_axes.figure, parent_axes.get_position(), + **axes_kwargs) + + axes_locator = AnchoredSizeLocator(parent_axes.bbox, + width, height, + loc=loc) + + inset_axes.set_axes_locator(axes_locator) + + _add_inset_axes(parent_axes, inset_axes) + + return inset_axes + + +def zoomed_inset_axes(parent_axes, zoom, loc=1, + bbox_to_anchor=None, bbox_transform=None, + axes_kwargs=None, + connects=None, + **kwargs): + + if axes_kwargs is None: + inset_axes = Axes(parent_axes.figure, parent_axes.get_position()) + else: + inset_axes = Axes(parent_axes.figure, parent_axes.get_position(), + **axes_kwargs) + + axes_locator = AnchoredZoomLocator(parent_axes, zoom=zoom, loc=loc) + inset_axes.set_axes_locator(axes_locator) + + _add_inset_axes(parent_axes, inset_axes) + + if connects is not None: + pass + + return inset_axes + + +def mark_inset(parent_axes, inset_axes, loc1, loc2, **kwargs): + rect = TransformedBbox(inset_axes.viewLim, parent_axes.transData) + + pp = BboxPatch(rect, **kwargs) + parent_axes.add_patch(pp) + + p1 = BboxConnector(inset_axes.bbox, rect, loc1=loc1, **kwargs) + inset_axes.add_patch(p1) + p1.set_clip_on(False) + p2 = BboxConnector(inset_axes.bbox, rect, loc1=loc2, **kwargs) + inset_axes.add_patch(p2) + p2.set_clip_on(False) + + return pp, p1, p2 + + + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |