Revision: 8320
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=8320&view=rev
Author:   leejjoon
Date:     2010-05-19 00:32:18 +0000 (Wed, 19 May 2010)

Log Message:
-----------
merge mpl_toolkits.gridspec into the main tree

Modified Paths:
--------------
    trunk/matplotlib/lib/matplotlib/axes.py
    trunk/matplotlib/lib/matplotlib/pyplot.py

Added Paths:
-----------
    trunk/matplotlib/lib/matplotlib/gridspec.py

Modified: trunk/matplotlib/lib/matplotlib/axes.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/axes.py     2010-05-18 17:14:45 UTC (rev 
8319)
+++ trunk/matplotlib/lib/matplotlib/axes.py     2010-05-19 00:32:18 UTC (rev 
8320)
@@ -8039,6 +8039,8 @@
     triplot.__doc__ = mtri.triplot.__doc__
 
 
+from gridspec import GridSpec, SubplotSpec
+
 class SubplotBase:
     """
     Base class for subplots, which are :class:`Axes` instances with
@@ -8062,92 +8064,63 @@
 
         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)
+        if len(args) == 1:
+            if isinstance(args[0], SubplotSpec):
+                self._subplotspec = args[0]
+
+            else:
+                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)
+                self._subplotspec = GridSpec(rows, cols)[num-1]
+                # num - 1 for converting from matlab to python indexing
         elif len(args)==3:
             rows, cols, num = args
+            if isinstance(num, tuple) and len(num) == 2:
+                self._subplotspec = GridSpec(rows, cols)[num[0]-1:num[1]]
+            else:
+                self._subplotspec = GridSpec(rows, cols)[num-1]
+                # num - 1 for converting from matlab to python indexing
         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()
 
         # _axes_class is set in the subplot_class_factory
         self._axes_class.__init__(self, fig, self.figbox, **kwargs)
 
+
+
     def get_geometry(self):
         'get the subplot geometry, eg 2,2,3'
-        return self._rows, self._cols, self._num+1
+        rows, cols, num1, num2 = self.get_subplotspec().get_geometry()
+        return rows, cols, num1+1 # for compatibility
 
     # COVERAGE NOTE: Never used internally or from examples
     def change_geometry(self, numrows, numcols, num):
         'change subplot geometry, eg. from 1,1,1 to 2,2,3'
-        self._rows = numrows
-        self._cols = numcols
-        self._num = num-1
+        self._subplotspec = GridSpec(numrows, numcols)[num-1]
         self.update_params()
         self.set_position(self.figbox)
 
+    def get_subplotspec(self):
+        'get the SubplotSpec instance associated with the subplot'
+        return self._subplotspec
+
+    def set_subplotspec(self, subplotspec):
+        'set the SubplotSpec instance associated with the subplot'
+        self._subplotspec = subplotspec
+
     def update_params(self):
         'update the subplot position from fig.subplotpars'
 
-        rows = self._rows
-        cols = self._cols
-        num = self._num
+        self.figbox, self.rowNum, self.colNum, self.numRows, self.numCols = \
+                     self.get_subplotspec().get_position(self.figure,
+                                                         return_all=True)
 
-        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)
-        self.rowNum = rowNum
-        self.colNum = colNum
-        self.numRows = rows
-        self.numCols = cols
-
-        if 0:
-            print 'rcn', rows, cols, num
-            print 'lbrt', left, bottom, right, top
-            print 'self.figBottom', self.figBottom
-            print 'self.figLeft', self.figLeft
-            print 'self.figW', self.figW
-            print 'self.figH', self.figH
-            print 'self.rowNum', self.rowNum
-            print 'self.colNum', self.colNum
-            print 'self.numRows', self.numRows
-            print 'self.numCols', self.numCols
-
-
     def is_first_col(self):
         return self.colNum==0
 

Added: trunk/matplotlib/lib/matplotlib/gridspec.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/gridspec.py                         (rev 0)
+++ trunk/matplotlib/lib/matplotlib/gridspec.py 2010-05-19 00:32:18 UTC (rev 
8320)
@@ -0,0 +1,298 @@
+"""
+:mod:`~matplotlib.gridspec` is a module which specifies the location
+of the subplot in the figure.
+
+    ``GridSpec``
+        specifies the geometry of the grid that a subplot will be
+        placed. The number of rows and number of columns of the grid
+        need to be set. Optionally, the subplot layout parameters
+        (e.g., left, right, etc.) can be tuned.
+
+    ``SubplotSpec``
+        specifies the location of the subplot in the given *GridSpec*.
+
+
+"""
+
+from __future__ import division
+
+import matplotlib
+rcParams = matplotlib.rcParams
+
+import matplotlib.transforms as mtransforms
+
+
+class GridSpec(object):
+    """
+    A class that specifies the geometry of the grid that a subplot
+    will be placed. 
+    """
+    def __init__(self, nrows, ncols,
+                 left=None, bottom=None, right=None, top=None,
+                 wspace=None, hspace=None):
+        """
+        The number of rows and number of columns of the
+        grid need to be set. Optionally, the subplot layout parameters
+        (e.g., left, right, etc.) can be tuned.
+        """
+        #self.figure = figure
+        self._nrows , self._ncols = nrows, ncols
+        self.left=left
+        self.bottom=bottom
+        self.right=right
+        self.top=top
+        self.wspace=wspace
+        self.hspace=hspace
+
+    def get_geometry(self):
+        'get the geometry of the grid, eg 2,3'
+        return self._nrows, self._ncols
+
+    _AllowedKeys = ["left", "bottom", "right", "top", "wspace", "hspace"]
+
+    def update(self, **kwargs):
+        """
+        Update the current values.  If any kwarg is None, default to
+        the current value, if set, otherwise to rc.
+        """
+
+        for k, v in kwargs.items():
+            if k in self._AllowedKeys:
+                setattr(self, k, v)
+            else:
+                raise AttributeError("%s is unknown keyword" % (k,))
+
+
+        from matplotlib import _pylab_helpers
+        from matplotlib.axes import SubplotBase
+        for figmanager in _pylab_helpers.Gcf.figs.values():
+            for ax in figmanager.canvas.figure.axes:
+                # copied from Figure.subplots_adjust
+                if not isinstance(ax, SubplotBase):
+                    # Check if sharing a subplots axis
+                    if ax._sharex is not None and isinstance(ax._sharex, 
SubplotBase):
+                        ax._sharex.update_params()
+                        ax.set_position(ax._sharex.figbox)
+                    elif ax._sharey is not None and 
isinstance(ax._sharey,SubplotBase):
+                        ax._sharey.update_params()
+                        ax.set_position(ax._sharey.figbox)
+                else:
+                    ax.update_params()
+                    ax.set_position(ax.figbox)
+
+
+    def get_subplot_params(self, fig=None):
+        """
+        return a dictionary of subplot layout parameters. The default
+        parameters are from rcParams unless a figure attribute is set.
+        """
+        from matplotlib.figure import SubplotParams
+        import copy
+        if fig is None:
+            kw = dict([(k, rcParams["figure.subplot."+k]) \
+                       for k in self._AllowedKeys])
+            subplotpars = SubplotParams(**kw)
+        else:
+            subplotpars = copy.copy(fig.subplotpars)
+
+        update_kw = dict([(k, getattr(self, k)) for k in self._AllowedKeys])
+        subplotpars.update(**update_kw)
+
+        return subplotpars
+
+
+    def new_subplotspec(self, loc, rowspan=1, colspan=1):
+        """
+        create and return a SuplotSpec instance.
+        """
+        loc1, loc2 = loc
+        subplotspec = self[loc1:loc1+rowspan, loc2:loc2+colspan]
+        return subplotspec
+
+
+    def __getitem__(self, key):
+        """
+        create and return a SuplotSpec instance.
+        """
+        nrows, ncols = self.get_geometry()
+        total = nrows*ncols
+
+        if isinstance(key, tuple):
+            try:
+                k1, k2 = key
+            except ValueError:
+                raise ValueError("unrecognized subplot spec")
+
+            if isinstance(k1, slice):
+                row1, row2, _ = k1.indices(nrows)
+            else:
+                if k1 < 0:
+                    k1 += nrows
+                row1, row2 = k1, k1+1
+
+
+            if isinstance(k2, slice):
+                col1, col2, _ = k2.indices(ncols)
+            else:
+                if k2 < 0:
+                    k2 += ncols
+                col1, col2 = k2, k2+1
+
+
+            num1 = row1*nrows + col1
+            num2 = (row2-1)*nrows + (col2-1)
+
+        # single key
+        else:
+            if isinstance(key, slice):
+                num1, num2, _ = key.indices(total)
+                num2 -= 1
+            else:
+                if key < 0:
+                    key += total
+                num1, num2 = key, None
+
+
+        return SubplotSpec(self, num1, num2)
+
+
+class GridSpecFromSubplotSpec(GridSpec):
+    """
+    GridSpec whose subplot layout parameters are inherited from the
+    location specified by a given SubplotSpec.
+    """
+    def __init__(self, nrows, ncols,
+                 subplot_spec,
+                 wspace=None, hspace=None):
+        """
+        The number of rows and number of columns of the grid need to
+        be set. An instance of SubplotSpec is also need to be set from
+        which the layout parameters will be inheirted. The wspace and
+        hspace of the layout can be optionally specified or the
+        default values (from the figure or rcParams) will be used.
+        """
+        self._nrows , self._ncols = nrows, ncols
+        self._wspace=wspace
+        self._hspace=hspace
+
+        self._subplot_spec = subplot_spec
+
+    def get_subplot_params(self, fig=None):
+
+        if fig is None:
+            hspace = rcParams["figure.subplot.hspace"]
+            wspace = rcParams["figure.subplot.wspace"]
+        else:
+            hspace = fig.subplotpars.hspace
+            wspace = fig.subplotpars.wspace
+
+        if self._hspace is not None:
+            hspace = self._hspace
+
+        if self._wspace is not None:
+            wspace = self._wspace
+
+        figbox = self._subplot_spec.get_position(fig, return_all=False)
+
+        left, bottom, right, top = figbox.extents
+
+        from matplotlib.figure import SubplotParams
+        sp = SubplotParams(left=left,
+                           right=right,
+                           bottom=bottom,
+                           top=top,
+                           wspace=wspace,
+                           hspace=hspace)
+
+        return sp
+
+
+
+
+class SubplotSpec(object):
+    """
+    specifies the location of the subplot in the given *GridSpec*.
+    """
+    
+    def __init__(self, gridspec, num1, num2=None):
+        """
+        The subplot will occupy the num1-th cell of the given
+        gridspec.  If num2 is provided, the subplot will span between
+        num1-th cell and num2-th cell.
+
+        The index stars from 0.
+        """
+
+        rows, cols = gridspec.get_geometry()
+        total = rows*cols
+
+        self._gridspec = gridspec
+        self.num1 = num1
+        self.num2 = num2
+
+    def get_gridspec(self):
+        return self._gridspec
+
+
+    def get_geometry(self):
+        """
+        get the subplot geometry, eg 2,2,3. Unlike SuplorParams,
+        index is 0-based
+        """
+        rows, cols = self.get_gridspec().get_geometry()
+        return rows, cols, self.num1, self.num2
+
+
+    def get_position(self, fig, return_all=False):
+        """
+        update the subplot position from fig.subplotpars
+        """
+
+        gridspec = self.get_gridspec()
+        rows, cols = gridspec.get_geometry()
+
+        subplot_params = gridspec.get_subplot_params(fig)
+        left = subplot_params.left
+        right = subplot_params.right
+        bottom = subplot_params.bottom
+        top = subplot_params.top
+        wspace = subplot_params.wspace
+        hspace = subplot_params.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(self.num1, cols)
+        figBottom = top - (rowNum+1)*figH - rowNum*sepH
+        figLeft = left + colNum*(figW + sepW)
+        figTop = figBottom + figH
+        figRight = figLeft + figW
+
+        if self.num2 is not None:
+
+            rowNum2, colNum2 =  divmod(self.num2, cols)
+            figBottom2 = top - (rowNum2+1)*figH - rowNum2*sepH
+            figLeft2 = left + colNum2*(figW + sepW)
+            figTop2 = figBottom2 + figH
+            figRight2 = figLeft2 + figW
+
+            figBottom = min(figBottom, figBottom2)
+            figLeft = min(figLeft, figLeft2)
+            figTop = max(figTop, figTop2)
+            figRight = max(figRight, figRight2)
+
+        figbox = mtransforms.Bbox.from_extents(figLeft, figBottom,
+                                               figRight, figTop)
+
+
+        if return_all:
+            return figbox, rowNum, colNum, rows, cols
+        else:
+            return figbox
+
+

Modified: trunk/matplotlib/lib/matplotlib/pyplot.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/pyplot.py   2010-05-18 17:14:45 UTC (rev 
8319)
+++ trunk/matplotlib/lib/matplotlib/pyplot.py   2010-05-19 00:32:18 UTC (rev 
8320)
@@ -12,7 +12,7 @@
 from matplotlib.rcsetup import interactive_bk as _interactive_bk
 from matplotlib.artist import getp, get, Artist
 from matplotlib.artist import setp as _setp
-from matplotlib.axes import Axes
+from matplotlib.axes import Axes, Subplot
 from matplotlib.projections import PolarAxes
 from matplotlib import mlab  # for csv2rec, detrend_none, window_hanning
 from matplotlib.scale import get_scale_docs, get_scale_names
@@ -764,6 +764,44 @@
         return fig, axarr.reshape(nrows, ncols)
 
 
+from gridspec import GridSpec
+def subplot2grid(shape, loc, rowspan=1, colspan=1, **kwargs):
+    """
+
+    It creates a subplot in a grid of *shape*, at location of *loc*,
+    spanning *rowspan*, *colspan* cells in each direction.
+    The index for loc is 0-based. ::
+
+      subplot2grid(shape, loc, rowspan=1, colspan=1)
+
+    is identical to ::
+
+      gridspec=GridSpec(shape[0], shape[2])
+      subplotspec=gridspec.new_subplotspec(loc, rowspan, colspan)
+      subplot(subplotspec)
+
+
+    """
+
+    fig = gcf()
+    s1, s2 = shape
+    subplotspec = GridSpec(s1, s2).new_subplotspec(loc,
+                                                   rowspan=rowspan,
+                                                   colspan=colspan)
+    a = Subplot(fig, subplotspec, **kwargs)
+    fig.add_subplot(a)
+    bbox = a.bbox
+    byebye = []
+    for other in fig.axes:
+        if other==a: continue
+        if bbox.fully_overlaps(other.bbox):
+            byebye.append(other)
+    for ax in byebye: delaxes(ax)
+
+    draw_if_interactive()
+    return a
+
+
 def twinx(ax=None):
     """
     Make a second axes overlay *ax* (or the current axes if *ax* is


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

------------------------------------------------------------------------------

_______________________________________________
Matplotlib-checkins mailing list
Matplotlib-checkins@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to