|
From: <lee...@us...> - 2010-05-19 00:32:44
|
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.
|