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

Log Message:
-----------
gridspec supports grid of different cell sizes

Modified Paths:
--------------
    trunk/matplotlib/doc/users/gridspec.rst
    trunk/matplotlib/lib/matplotlib/gridspec.py

Added Paths:
-----------
    trunk/matplotlib/doc/users/plotting/examples/demo_gridspec05.py

Modified: trunk/matplotlib/doc/users/gridspec.rst
===================================================================
--- trunk/matplotlib/doc/users/gridspec.rst     2010-05-19 00:32:31 UTC (rev 
8322)
+++ trunk/matplotlib/doc/users/gridspec.rst     2010-05-19 00:32:37 UTC (rev 
8323)
@@ -129,3 +129,23 @@
 .. plot:: users/plotting/examples/demo_gridspec04.py
 
 
+GridSpec with Varying Cell Sizes
+================================
+
+By default, GridSpec creates cells of equal sizes. You can adjust
+relative heights and widths of rows and columns. Note that absolute
+values are meaningless, onlt their relative ratios matter. ::
+
+  gs = gridspec.GridSpec(2, 2,
+                         width_ratios=[1,2],
+                         height_ratios=[4,1]
+                         )
+  
+  ax1 = plt.subplot(gs[0])
+  ax2 = plt.subplot(gs[1])
+  ax3 = plt.subplot(gs[2])
+  ax4 = plt.subplot(gs[3])
+
+
+.. plot:: users/plotting/examples/demo_gridspec05.py
+

Added: trunk/matplotlib/doc/users/plotting/examples/demo_gridspec05.py
===================================================================
--- trunk/matplotlib/doc/users/plotting/examples/demo_gridspec05.py             
                (rev 0)
+++ trunk/matplotlib/doc/users/plotting/examples/demo_gridspec05.py     
2010-05-19 00:32:37 UTC (rev 8323)
@@ -0,0 +1,26 @@
+import matplotlib.pyplot as plt
+import matplotlib.gridspec as gridspec
+
+def make_ticklabels_invisible(fig):
+    for i, ax in enumerate(fig.axes):
+        ax.text(0.5, 0.5, "ax%d" % (i+1), va="center", ha="center")
+        for tl in ax.get_xticklabels() + ax.get_yticklabels():
+            tl.set_visible(False)
+
+
+
+f = plt.figure()
+
+gs = gridspec.GridSpec(2, 2,
+                       width_ratios=[1,2],
+                       height_ratios=[4,1]
+                       )
+
+ax1 = plt.subplot(gs[0])
+ax2 = plt.subplot(gs[1])
+ax3 = plt.subplot(gs[2])
+ax4 = plt.subplot(gs[3])
+
+make_ticklabels_invisible(f)
+plt.show()
+

Modified: trunk/matplotlib/lib/matplotlib/gridspec.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/gridspec.py 2010-05-19 00:32:31 UTC (rev 
8322)
+++ trunk/matplotlib/lib/matplotlib/gridspec.py 2010-05-19 00:32:37 UTC (rev 
8323)
@@ -21,95 +21,113 @@
 
 import matplotlib.transforms as mtransforms
 
+import numpy as np
 
-class GridSpec(object):
+class GridSpecBase(object):
     """
-    A class that specifies the geometry of the grid that a subplot
-    will be placed. 
+    A base class of GridSpec 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):
+                 height_ratios=None, width_ratios=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.
+        The number of rows and number of columns of the grid need to
+        be set. Optionally, the ratio of heights and widths of ros and
+        columns can be specified.
         """
         #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
 
+        self.set_height_ratios(height_ratios)
+        self.set_width_ratios(width_ratios)
+
     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 get_subplot_params(self, fig=None):
+        pass
 
-    def update(self, **kwargs):
+    def new_subplotspec(self, loc, rowspan=1, colspan=1):
         """
-        Update the current values.  If any kwarg is None, default to
-        the current value, if set, otherwise to rc.
+        create and return a SuplotSpec instance.
         """
+        loc1, loc2 = loc
+        subplotspec = self[loc1:loc1+rowspan, loc2:loc2+colspan]
+        return subplotspec
 
-        for k, v in kwargs.items():
-            if k in self._AllowedKeys:
-                setattr(self, k, v)
-            else:
-                raise AttributeError("%s is unknown keyword" % (k,))
 
+    def set_width_ratios(self, width_ratios):
+        self._col_width_ratios = width_ratios
 
-        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_width_ratios(self):
+        return self._col_width_ratios
 
+    def set_height_ratios(self, height_ratios):
+        self._row_height_ratios = height_ratios
 
-    def get_subplot_params(self, fig=None):
+    def get_height_ratios(self):
+        return self._row_height_ratios
+
+    
+    def get_grid_positions(self, fig):
         """
-        return a dictionary of subplot layout parameters. The default
-        parameters are from rcParams unless a figure attribute is set.
+        return lists of bottom and top position of rows, left and
+        right positions of columns.
         """
-        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)
+        nrows, ncols = self.get_geometry()
+
+        subplot_params = self.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
+
+        # calculate accumulated heights of columns
+        cellH = totHeight/(nrows + hspace*(nrows-1))
+        sepH = hspace*cellH
+
+        if self._row_height_ratios is not None:
+            netHeight = cellH * nrows
+            tr = float(sum(self._row_height_ratios))
+            cellHeights = [netHeight*r/tr for r in self._row_height_ratios]
         else:
-            subplotpars = copy.copy(fig.subplotpars)
+            cellHeights = [cellH] * nrows
 
-        update_kw = dict([(k, getattr(self, k)) for k in self._AllowedKeys])
-        subplotpars.update(**update_kw)
+        sepHeights = [0] + ([sepH] * (nrows-1))
+        cellHs = np.add.accumulate(np.ravel(zip(sepHeights, cellHeights)))
 
-        return subplotpars
 
+        # calculate accumulated widths of rows
+        cellW = totWidth/(ncols + wspace*(ncols-1))
+        sepW = wspace*cellW
 
-    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
+        if self._col_width_ratios is not None:
+            netWidth = cellW * ncols
+            tr = float(sum(self._col_width_ratios))
+            cellWidths = [netWidth*r/tr for r in self._col_width_ratios]
+        else:
+            cellWidths = [cellW] * ncols
 
+        sepWidths = [0] + ([sepW] * (ncols-1))
+        cellWs = np.add.accumulate(np.ravel(zip(sepWidths, cellWidths)))
+            
 
+
+        figTops = [top - cellHs[2*rowNum] for rowNum in range(nrows)]
+        figBottoms = [top - cellHs[2*rowNum+1] for rowNum in range(nrows)]
+        figLefts = [left + cellWs[2*colNum] for colNum in range(ncols)]
+        figRights = [left + cellWs[2*colNum+1] for colNum in range(ncols)]
+
+
+        return figBottoms, figTops, figLefts, figRights
+        
+
     def __getitem__(self, key):
         """
         create and return a SuplotSpec instance.
@@ -156,28 +174,121 @@
         return SubplotSpec(self, num1, num2)
 
 
-class GridSpecFromSubplotSpec(GridSpec):
+class GridSpec(GridSpecBase):
     """
+    A class that specifies the geometry of the grid that a subplot
+    will be placed. The location of grid is determined by similar way
+    as the SubplotParams.
+    """
+
+    def __init__(self, nrows, ncols,
+                 left=None, bottom=None, right=None, top=None,
+                 wspace=None, hspace=None,
+                 width_ratios=None, height_ratios=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.left=left
+        self.bottom=bottom
+        self.right=right
+        self.top=top
+        self.wspace=wspace
+        self.hspace=hspace
+
+        GridSpecBase.__init__(self, nrows, ncols,
+                              width_ratios=width_ratios,
+                              height_ratios=height_ratios)
+        #self.set_width_ratios(width_ratios)
+        #self.set_height_ratios(height_ratios)
+
+
+    _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
+
+
+class GridSpecFromSubplotSpec(GridSpecBase):
+    """
     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):
+                 wspace=None, hspace=None,
+                 height_ratios=None, width_ratios=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
+        be set. An instance of SubplotSpec is also needed 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
 
+        GridSpecBase.__init__(self, nrows, ncols,
+                              width_ratios=width_ratios,
+                              height_ratios=height_ratios)
+
+
     def get_subplot_params(self, fig=None):
+        """
+        return a dictionary of subplot layout parameters. 
+        """
 
         if fig is None:
             hspace = rcParams["figure.subplot.hspace"]
@@ -249,37 +360,25 @@
         """
 
         gridspec = self.get_gridspec()
-        rows, cols = gridspec.get_geometry()
+        nrows, ncols = 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
+        figBottoms, figTops, figLefts, figRights = \
+                    gridspec.get_grid_positions(fig)
 
-        figH = totHeight/(rows + hspace*(rows-1))
-        sepH = hspace*figH
 
-        figW = totWidth/(cols + wspace*(cols-1))
-        sepW = wspace*figW
+        rowNum, colNum =  divmod(self.num1, ncols)
+        figBottom = figBottoms[rowNum]
+        figTop = figTops[rowNum]
+        figLeft = figLefts[colNum]
+        figRight = figRights[colNum]
 
-        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
+            rowNum2, colNum2 =  divmod(self.num2, ncols)
+            figBottom2 = figBottoms[rowNum2]
+            figTop2 = figTops[rowNum2]
+            figLeft2 = figLefts[colNum2]
+            figRight2 = figRights[colNum2]
 
             figBottom = min(figBottom, figBottom2)
             figLeft = min(figLeft, figLeft2)
@@ -291,7 +390,7 @@
 
 
         if return_all:
-            return figbox, rowNum, colNum, rows, cols
+            return figbox, rowNum, colNum, nrows, ncols
         else:
             return figbox
 


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