You can subscribe to this list here.
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(115) |
Aug
(120) |
Sep
(137) |
Oct
(170) |
Nov
(461) |
Dec
(263) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2008 |
Jan
(120) |
Feb
(74) |
Mar
(35) |
Apr
(74) |
May
(245) |
Jun
(356) |
Jul
(240) |
Aug
(115) |
Sep
(78) |
Oct
(225) |
Nov
(98) |
Dec
(271) |
2009 |
Jan
(132) |
Feb
(84) |
Mar
(74) |
Apr
(56) |
May
(90) |
Jun
(79) |
Jul
(83) |
Aug
(296) |
Sep
(214) |
Oct
(76) |
Nov
(82) |
Dec
(66) |
2010 |
Jan
(46) |
Feb
(58) |
Mar
(51) |
Apr
(77) |
May
(58) |
Jun
(126) |
Jul
(128) |
Aug
(64) |
Sep
(50) |
Oct
(44) |
Nov
(48) |
Dec
(54) |
2011 |
Jan
(68) |
Feb
(52) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
2018 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
|
|
|
1
(3) |
2
|
3
|
4
(1) |
5
(8) |
6
(5) |
7
|
8
|
9
|
10
|
11
(1) |
12
|
13
(3) |
14
(1) |
15
(2) |
16
(2) |
17
(6) |
18
(1) |
19
(3) |
20
|
21
(1) |
22
|
23
(5) |
24
(4) |
25
|
26
(1) |
27
(1) |
28
(1) |
29
(3) |
30
(4) |
|
|
Revision: 7050 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7050&view=rev Author: jdh2358 Date: 2009年04月17日 20:40:29 +0000 (2009年4月17日) Log Message: ----------- use 0 for default in rec join outer join if no default given Modified Paths: -------------- trunk/matplotlib/doc/sphinxext/gen_gallery.py trunk/matplotlib/examples/misc/rec_join_demo.py trunk/matplotlib/lib/matplotlib/backend_bases.py trunk/matplotlib/lib/matplotlib/mlab.py Modified: trunk/matplotlib/doc/sphinxext/gen_gallery.py =================================================================== --- trunk/matplotlib/doc/sphinxext/gen_gallery.py 2009年04月17日 20:20:07 UTC (rev 7049) +++ trunk/matplotlib/doc/sphinxext/gen_gallery.py 2009年04月17日 20:40:29 UTC (rev 7050) @@ -38,7 +38,7 @@ print print "generating gallery: ", data = [] - for subdir in ('api', 'pylab_examples', 'widgets'): + for subdir in ('api', 'pylab_examples', 'widgets', 'mplot3d'): origdir = os.path.join('build', rootdir, subdir) thumbdir = os.path.join(outdir, rootdir, subdir, 'thumbnails') if not os.path.exists(thumbdir): Modified: trunk/matplotlib/examples/misc/rec_join_demo.py =================================================================== --- trunk/matplotlib/examples/misc/rec_join_demo.py 2009年04月17日 20:20:07 UTC (rev 7049) +++ trunk/matplotlib/examples/misc/rec_join_demo.py 2009年04月17日 20:40:29 UTC (rev 7050) @@ -6,8 +6,8 @@ r.sort() r1 = r[-10:] -# Create a new array -r2 = np.empty(12, dtype=[('date', '|O4'), ('high', np.float), +# Create a new array +r2 = np.empty(12, dtype=[('date', '|O4'), ('high', np.float), ('marker', np.float)]) r2 = r2.view(np.recarray) r2.date = r.date[-17:-5] @@ -19,9 +19,9 @@ print "r2:" print mlab.rec2txt(r2) -defaults = {'marker':-1, 'close':np.NaN, 'low':-4444.} +defaults = {'marker':-1, '_close':np.NaN, 'low':-4444.} for s in ('inner', 'outer', 'leftouter'): - rec = mlab.rec_join(['date', 'high'], r1, r2, - jointype=s, defaults=defaults) + rec = mlab.rec_join(['date', 'high'], r1, r2, + jointype=s, defaults=defaults) print "\n%sjoin :\n%s" % (s, mlab.rec2txt(rec)) Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2009年04月17日 20:20:07 UTC (rev 7049) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2009年04月17日 20:40:29 UTC (rev 7050) @@ -1058,7 +1058,7 @@ under = self.figure.hitlist(ev) enter = [a for a in under if a not in self._active] leave = [a for a in self._active if a not in under] - print "within:"," ".join([str(x) for x in under]) + #print "within:"," ".join([str(x) for x in under]) #print "entering:",[str(a) for a in enter] #print "leaving:",[str(a) for a in leave] # On leave restore the captured colour @@ -1520,6 +1520,10 @@ - 'pick_event' - 'resize_event' - 'scroll_event' + - 'figure_enter_event', + - 'figure_leave_event', + - 'axes_enter_event', + - 'axes_leave_event' For the location events (button and key press/release), if the mouse is over the axes, the variable ``event.inaxes`` will be Modified: trunk/matplotlib/lib/matplotlib/mlab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mlab.py 2009年04月17日 20:20:07 UTC (rev 7049) +++ trunk/matplotlib/lib/matplotlib/mlab.py 2009年04月17日 20:40:29 UTC (rev 7050) @@ -2303,6 +2303,17 @@ newrec = np.empty(common_len + left_len + right_len, dtype=newdtype) + if defaults is not None: + for thiskey in defaults: + if thiskey not in newdtype.names: + warnings.warn('rec_join defaults key="%s" not in new dtype names "%s"'%( + thiskey, newdtype.names)) + + for name in newdtype.names: + dt = newdtype[name] + if dt.kind in ('f', 'i'): + newrec[name] = 0 + if jointype != 'inner' and defaults is not None: # fill in the defaults enmasse newrec_fields = newrec.dtype.fields.keys() for k, v in defaults.items(): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7049 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7049&view=rev Author: leejjoon Date: 2009年04月17日 20:20:07 +0000 (2009年4月17日) Log Message: ----------- removing axes_grid.inset_locator. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/offsetbox.py Removed Paths: ------------- trunk/matplotlib/lib/mpl_toolkits/axes_grid/inset_locator.py Modified: trunk/matplotlib/lib/matplotlib/offsetbox.py =================================================================== --- trunk/matplotlib/lib/matplotlib/offsetbox.py 2009年04月17日 19:35:59 UTC (rev 7048) +++ trunk/matplotlib/lib/matplotlib/offsetbox.py 2009年04月17日 20:20:07 UTC (rev 7049) @@ -19,7 +19,7 @@ import matplotlib.artist as martist import matplotlib.text as mtext import numpy as np -from matplotlib.transforms import Bbox, TransformedBbox, BboxTransformTo +from matplotlib.transforms import Bbox, BboxBase, TransformedBbox, BboxTransformTo from matplotlib.font_manager import FontProperties from matplotlib.patches import FancyBboxPatch @@ -897,7 +897,7 @@ """ if bbox is None: self._bbox_to_anchor = None - elif isinstance(bbox, Bbox): + elif isinstance(bbox, BboxBase): self._bbox_to_anchor = bbox else: try: Deleted: trunk/matplotlib/lib/mpl_toolkits/axes_grid/inset_locator.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/inset_locator.py 2009年04月17日 19:35:59 UTC (rev 7048) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/inset_locator.py 2009年04月17日 20:20:07 UTC (rev 7049) @@ -1,191 +0,0 @@ -from matplotlib.offsetbox import AnchoredOffsetbox - - -import matplotlib.transforms as mtrans - -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, parent_bbox, offsetbox, loc, **kwargs): - - for k in ["parent_bbox", "child", "pad"]: - if kwargs.has_key(k): - raise ValueError("%s paramter should not be provided" % (k,)) - - kwargs["pad"] = 0. - kwargs["child"] = None - kwargs["parent_bbox"] = parent_bbox - - super(AnchoredLocatorBase, self).__init__(loc, **kwargs) - - - 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 - - -class AnchoredOffsetBoxLocator(AnchoredLocatorBase): - def __init__(self, parent_bbox, offsetbox, loc, **kwargs): - - for k in ["parent_bbox", "child", "pad"]: - if kwargs.has_key(k): - raise ValueError("%s paramter should not be provided" % (k,)) - - kwargs["pad"] = 0. - kwargs["child"] = offsetbox - kwargs["parent_bbox"] = parent_bbox - - super(AnchoredOffsetBoxLocator, self).__init__(loc, **kwargs) - - - -from mpl_toolkits.axes_grid.axes_divider import Size - -class AnchoredSizeLocator(AnchoredLocatorBase): - def __init__(self, parent_bbox, x_size, y_size, - loc, **kwargs): - - self.axes = None - self.x_size = Size.from_any(x_size) - self.y_size = Size.from_any(y_size) - - super(AnchoredSizeLocator, self).__init__(parent_bbox, None, loc, **kwargs) - - def get_extent(self, renderer): - - x, y, w, h = self._parent_bbox.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, **kwargs): - - self.parent_axes = parent_axes - self.zoom = zoom - - super(AnchoredZoomLocator, self).__init__(parent_axes.bbox, None, loc, **kwargs) - - 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 AnchoredAxesBoxLocator(AnchoredOffsetBoxLocator): -# def __init__(self, ax, x0, x1, y0, y1, zoom, zoomy=None, -# parent_bbox, width_inch, height_inch, -# loc, **kwargs): - -# self.width_inch = width_inch -# self.height_inch = height_inch - -# super(AnchoredFixedBoxLocator, self).__init__(parent_bbox, None, loc, **kwargs) - -# def get_extent(self, renderer): - -# w =self.width_inch * renderer.points_to_pixels(72.) -# h =self.height_inch * renderer.points_to_pixels(72.) -# xd, yd = 0, 0 - -# fontsize = renderer.points_to_pixels(self.prop.get_size_in_points()) -# pad = self.pad * fontsize - -# return w+2*pad, h+2*pad, xd+pad, yd+pad - - -if __name__ == "__main__": - - import matplotlib.pyplot as plt - - fig = plt.figure(1) - ax = fig.add_subplot(1,2,1) - ax.set_aspect(1.) - - # width : 30% of parent_bbox (ax.bbox) - # height : 1 inch - axes_locator = AnchoredSizeLocator(ax.bbox, "30%", 1, loc=1) - - axins = fig.add_axes([0, 0, 1, 1], label="inset1") - axins.set_axes_locator(axes_locator) - - - - - ax = fig.add_subplot(1,2,2) - ax.set_aspect(1.) - - # inset axes has a data scale of the parent axes multiplied by a zoom factor - axes_locator = AnchoredZoomLocator(ax, zoom=0.5, loc=1) - - axins = fig.add_axes([0, 0, 0.5, 1], label="inset2") - #axins = plt.axes([0, 0, 1, 1]) - axins.set_axes_locator(axes_locator) - - - - - - - #locator = AnchoredBoxLocator(parent_bbox, Fixed(1.), Scaled(0.2), loc=1) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7048 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7048&view=rev Author: leejjoon Date: 2009年04月17日 19:35:59 +0000 (2009年4月17日) Log Message: ----------- axes_grid toolkit initial check in Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/doc/users/toolkits.rst trunk/matplotlib/setup.py Added Paths: ----------- trunk/matplotlib/doc/_static/demo_axes_grid.png trunk/matplotlib/doc/mpl_toolkits/ trunk/matplotlib/doc/mpl_toolkits/axes_grid/ trunk/matplotlib/doc/mpl_toolkits/axes_grid/figures trunk/matplotlib/doc/mpl_toolkits/axes_grid/index.rst trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/ 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/ trunk/matplotlib/examples/axes_grid/demo_axes_divider.py trunk/matplotlib/examples/axes_grid/demo_axes_grid.py trunk/matplotlib/examples/axes_grid/demo_axes_rgb.py trunk/matplotlib/examples/axes_grid/demo_fixed_size_axes.py trunk/matplotlib/examples/axes_grid/demo_image.py trunk/matplotlib/examples/axes_grid/demo_parasite_axes.py trunk/matplotlib/examples/axes_grid/demo_parasite_axes2.py trunk/matplotlib/examples/axes_grid/parasite_simple.py trunk/matplotlib/examples/axes_grid/parasite_simple2.py trunk/matplotlib/examples/axes_grid/scatter_hist.py trunk/matplotlib/examples/axes_grid/simple_anchored_artists.py trunk/matplotlib/examples/axes_grid/simple_axes_divider1.py trunk/matplotlib/examples/axes_grid/simple_axes_divider2.py trunk/matplotlib/examples/axes_grid/simple_axes_divider3.py trunk/matplotlib/examples/axes_grid/simple_axesgrid.py trunk/matplotlib/examples/axes_grid/simple_axesgrid2.py trunk/matplotlib/examples/axes_grid/simple_axisline.py trunk/matplotlib/examples/axes_grid/simple_axisline2.py trunk/matplotlib/examples/axes_grid/simple_axisline3.py trunk/matplotlib/examples/axes_grid/simple_axisline4.py trunk/matplotlib/examples/axes_grid/simple_rgb.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/ trunk/matplotlib/lib/mpl_toolkits/axes_grid/__init__.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/anchored_artists.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_divider.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_grid.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_rgb.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/axislines.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/inset_locator.py trunk/matplotlib/lib/mpl_toolkits/axes_grid/parasite_axes.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009年04月17日 16:34:09 UTC (rev 7047) +++ trunk/matplotlib/CHANGELOG 2009年04月17日 19:35:59 UTC (rev 7048) @@ -1,5 +1,7 @@ ====================================================================== +2009年04月17日 Initial check-in of the axes_grid toolkit. - JJL + 2009年04月17日 Added a support for bbox_to_anchor in offsetbox.AnchoredOffsetbox. Improved a documentation. - JJL Added: trunk/matplotlib/doc/_static/demo_axes_grid.png =================================================================== (Binary files differ) Property changes on: trunk/matplotlib/doc/_static/demo_axes_grid.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Added: trunk/matplotlib/doc/mpl_toolkits/axes_grid/figures =================================================================== --- trunk/matplotlib/doc/mpl_toolkits/axes_grid/figures (rev 0) +++ trunk/matplotlib/doc/mpl_toolkits/axes_grid/figures 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1 @@ +link ../../../examples/axes_grid/ \ No newline at end of file Property changes on: trunk/matplotlib/doc/mpl_toolkits/axes_grid/figures ___________________________________________________________________ Added: svn:special + * Added: trunk/matplotlib/doc/mpl_toolkits/axes_grid/index.rst =================================================================== --- trunk/matplotlib/doc/mpl_toolkits/axes_grid/index.rst (rev 0) +++ trunk/matplotlib/doc/mpl_toolkits/axes_grid/index.rst 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,23 @@ + +.. _toolkit_axesgrid-index: + +Matplotlib AxesGrid Toolkit +=========================== + +The matplotlib AxesGrid toolkit is a collection of helper classes to +ease displaying multiple images in matplotlib. While the aspect +parameter in matplotlib adjust the position of the single axes, +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 +============= + +.. toctree:: + :maxdepth: 2 + + users/index.rst + Added: trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/axes_divider.rst =================================================================== --- trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/axes_divider.rst (rev 0) +++ trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/axes_divider.rst 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,89 @@ +AxesDivider +=========== + +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 + +* *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. + +for example,:: + + rect = [0.2, 0.2, 0.6, 0.6] + horiz=[h0, h1, h2, h3] + vert=[v0, v1, v2] + 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 | | | | ++-----+-----+-----+-----+ +| v1 | | | | ++-----+-----+-----+-----+ +|h0,v2| h1 | h2 | h3 | ++-----+-----+-----+-----+ + + +* h0 => 2, 0 +* h1 => 0, 2 +* h2 => 0, 3 + +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 +(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 +that can be used to set the horiz and vert. For example, for the +vertical configuration above will be:: + + from 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.:: + + 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 +location and size of the cell at the first column and the second row. +You may create a locator that spans over multiple cells.:: + + locator = divider.new_locator(nx=0, nx=2, ny=1) + +The above locator, when called, will return the position and size of +the cells spanning the first and second column and the first row. You +may consider it as [0:2, 1]. + +See the example, + +.. plot:: mpl_toolkits/axes_grid/figures/simple_axes_divider2.py + :include-source: + +You can adjust the size of the each axes accroding to their x or y +data limits (AxesX and AxesY), similar to the axes aspect parameter. + +.. plot:: mpl_toolkits/axes_grid/figures/simple_axes_divider3.py + :include-source: + Added: trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/index.rst =================================================================== --- trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/index.rst (rev 0) +++ trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/index.rst 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,12 @@ +.. _axes_grid_users-guide-index: + +################################################ + The Matplotlib AxesGrid Toolkit User's Guide +################################################ + +:Release: |version| +:Date: |today| + +.. toctree:: + + overview.rst Added: trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/overview.rst =================================================================== --- trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/overview.rst (rev 0) +++ trunk/matplotlib/doc/mpl_toolkits/axes_grid/users/overview.rst 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,349 @@ +================= +AxesGrid Overview +================= + +The matplotlib AxesGrid toolkit is a collection of helper classes, +mainly to ease displaying (multiple) images in matplotlib. + +.. contents:: + :depth: 1 + :local: + +`AxesGrid`_, `RGB Axes`_ and `AxesDivider`_ are helper classes that +deals with adjusting the location of (multiple) Axes, mainly for +displaying images. It provides a framework to adjust the position of +multiple axes at the drawing time. `ParasiteAxes`_ provides twinx(or +twiny)-like features so that you can plot different data (e.g., +different y-scale) in a same Axes. `AxisLine`_ is a custom Axes +class. Unlike default Axes in matpotlib, each axis (left, right, top +and bottom) is associated with a separate artist (which is resposible +to draw axis-line, ticks, ticklabels, label). `AnchoredArtists`_ +includes custom artists which are placed at some anchored position, +like the legend. + + + + +AxesGrid +======== + + +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. + +.. plot:: mpl_toolkits/axes_grid/figures/simple_axesgrid.py + :include-source: + +* The postion of each axes is determined at the drawing time (see + `AxesDivider`_), so that the size of the entire grid fits in the + given rectangle (like the aspec of axes). Note that in this example, + the paddings between axes are fixed even if you changes the figure + size. + +* axes in the same column has a same axes width (in figure + coordinate), and similarly, axes in the same row has a same + height. The widths (height) of the axes in the same row (column) are + scaled according to their view limits (xlim or ylim). + + .. plot:: mpl_toolkits/axes_grid/figures/simple_axesgrid2.py + :include-source: + +* xaxis are shared among axes in a same column. Similarly, yaxis are + shared among axes in a same row. Therefore, changing axis properties + (view limits, tick location, etc. either by plot commands or using + your mouse in interactive backends) of one axes will affect all + other shared axes. + + + +When initialized, AxesGrid creates given number (*ngrids* or *ncols* * +*nrows* if *ngrids* is None) of Axes instances. A sequence-like +interface is provided to access the individual Axes instances (e.g., +grid[0] is the first Axes in the grid. See below for the order of +axes). + + + +AxesGrid takes following arguments, + + + ============= ======== ================================================ + Name Default Description + ============= ======== ================================================ + fig + rect + nrows_ncols number of rows and cols. e.g. (2,2) + ngrids None number of grids. nrows x ncols if None + direction "row" increasing direction of axes number. [row|column] + axes_pad 0.02 pad between axes in inches + add_all True Add axes to figures if True + share_all False xaxis & yaxis of all axes are shared if True + aspect True aspect of axes + label_mode "L" location of tick labels thaw will be displayed. + "1" (only the lower left axes), + "L" (left most and bottom most axes), + or "all". + cbar_mode None [None|single|each] + cbar_location "right" [right|top] + cbar_pad None pad between image axes and colorbar axes + cbar_size "5%" size of the colorbar + axes_class None + ============= ======== ================================================ + + *rect* + specifies the location of the grid. You can either specify + coordinates of the rectangle to be used (e.g., (0.1, 0.1, 0.8, 0.8) + as in the Axes), or the subplot-like position (e.g., "121"). + + *direction* + means the increasing direction of the axes number. + + *aspect* + By default (False), widths and heigths of axes in the grid are + scaled independently. If True, they are scaled according to their + data limits (similar to aspect parameter in mpl). + + *share_all* + if True, xaxis and yaxis of all axes are shared. + + *direction* + direction of increasing axes number. For "row", + + +---------+---------+ + | grid[0] | grid[1] | + +---------+---------+ + | grid[2] | grid[3] | + +---------+---------+ + + For "column", + + +---------+---------+ + | grid[0] | grid[2] | + +---------+---------+ + | grid[1] | grid[3] | + +---------+---------+ + +You can also create a colorbar (or colobars). You can have colorbar +for each axes (cbar_mode="each"), or you can have a single colorbar +for the grid (cbar_mode="single"). The colorbar can be placed on your +right, or top. The axes for each colorbar is stored as a *cbar_axes* +attribute. + + + +The examples below show what you can do with AxesGrid. + +.. plot:: mpl_toolkits/axes_grid/figures/demo_axes_grid.py + + +RGB Axes +======== + +RGBAxes is a helper clase to conveniently show RGB composite +images. Like AxesGrid, the location of axes are adjusted so that the +area occupied by them fits in a given rectangle. Also, the xaxis and +yaxis of each axes are shared. :: + + from mpl_toolkits.axes_grid.axes_rgb import RGBAxes + + fig = plt.figure(1) + ax = RGBAxes(fig, [0.1, 0.1, 0.8, 0.8]) + + r, g, b = get_rgb() # r,g,b are 2-d images + ax.imshow_rgb(r, g, b, + origin="lower", interpolation="nearest") + + +.. plot:: mpl_toolkits/axes_grid/figures/simple_rgb.py + + + +AxesDivider +=========== + +Behind the scene, the AxesGrid class and the RGBAxes class utilize the +AxesDivider class, whose role is to calculate the location of the axes +at drawing time. While a more about the AxesDivider is (will be) +explained in (yet to be written) AxesDividerGuide, direct use of the +AxesDivider class will not be necessary for most users. The +axes_divider module provides a helper function make_axes_locatable, +which can be useful. It takes a exisitng axes instance and create a +divider for it. :: + + ax = subplot(1,1,1) + divider = make_axes_locatable(ax) + + + + +*make_axes_locatable* returns an isntance of the AxesLocator class, +derived from the Locator. It has *new_vertical*, and *new_horizontal* +methods. The *new_vertical* (*new_horizontal*) creates a new axes on +the upper (right) side of the original axes. + + +scatter_hist.py with AxesDivider +-------------------------------- + +The "scatter_hist.py" example in mpl can be rewritten using +*make_axes_locatable*. :: + + from mpl_toolkits.axes_grid import make_axes_locatable + + axScatter = subplot(111) + divider = make_axes_locatable(axScatter) + + # create new axes on the right and on the top of the current axes + # The first argument of the new_vertical(new_horizontal) method is + # the height (width) of the axes to be created in inches. + axHistx = divider.new_vertical(1.2, pad=0.1, sharex=axScatter) + axHisty = divider.new_horizontal(1.2, pad=0.1, sharey=axScatter) + + fig.add_axes(axHistx) + fig.add_axes(axHisty) + + + # the scatter plot: + axScatter.scatter(x, y) + axScatter.set_aspect(1.) + + # histograms + bins = np.arange(-lim, lim + binwidth, binwidth) + axHistx.hist(x, bins=bins) + axHisty.hist(y, bins=bins, orientation='horizontal') + +See the full source code below. + + +.. plot:: mpl_toolkits/axes_grid/figures/scatter_hist.py + + +The scatter_hist using the AxesDivider has some advantage over the +original scatter_hist.py in mpl. For example, you can set the aspect +ratio of the scatter plot, even with the x-axis or y-axis is shared +accordingly. + + +ParasiteAxes +============ + +The ParasiteAxes is a axes whose location is identical to its host +axes. The location is adjusted in the drawing time, thus it works even +if the host change its location (e.g., images). It provides *twinx*, +*twiny* (similar to twinx and twiny in the matplotlib). Also it +provides *twin*, which takes an arbitraty tranfromation that maps +between the data coordinates of the host and the parasite axes. +Artists in each axes are mergred and drawn acrroding to their zorder. +It also modifies some behavior of the axes. For example, color cycle +for plot lines are shared between host and parasites. Also, the legend +command in host, creates a legend that includes lines in the parasite +axes. + +Example 1. twinx +---------------- + +.. plot:: mpl_toolkits/axes_grid/figures/parasite_simple.py + :include-source: + +Example 2. twin +--------------- + +A more sophiscated example using twin. Note that if you change the +x-limit in the host axes, the x-limit of the parasite axes will change +accordingly. + + +.. plot:: mpl_toolkits/axes_grid/figures/parasite_simple2.py + + + +AxisLine +======== + +AxisLine is a custom (and very experimenta) Axes class, where each +axis (left, right, top and bottom) have a separate artist associated +(which is resposible to draw axis-line, ticks, ticklabels, label). +Also, you can create your own axis, which can pass through a fixed +position in the axes coordinate, or a fixed position in the data +coordinate (i.e., the axis floats around when viewlimit changes). + +Most of the class in this toolkit is based on this class. And it has +not been tested extensibly. You may go back to the original mpl +behanvior, by :: + + ax.toggle_axisline(False) + +The axes class, by default, provides 4 artists which are responsible +to draw axis in "left","right","bottom" and "top". They are accessed +as ax.axis["left"], ax.axis["right"], and so on, i.e., ax.axis is a +dictionary that contains artists (note that ax.axis is still a +callable methods and it behaves as an original Axes.axis method in +mpl). + +For example, you can hide right, and top axis by :: + + ax.axis["right"].set_visible(False) + ax.axis["top"].set_visible(False) + + +.. plot:: mpl_toolkits/axes_grid/figures/simple_axisline3.py + + +SubplotZero gives you two more additional (floating?) axis of x=0 and +y=0 (in data coordinate) + +.. plot:: mpl_toolkits/axes_grid/figures/simple_axisline2.py + :include-source: + + +Axisline with ParasiteAxes +-------------------------- + +Most of axes class in the axes_grid toolkit, including ParasiteAxes, +is based on the Axisline axes. The combination of the two can be +useful in some case. For example, you can have different tick-location, +tick-label, or tick-formatter for bottom and top (or left and right) +axis. :: + + ax2 = ax.twin() # now, ax2 is responsible for "top" axis and "right" axis + ax2.set_xticks([0., .5*np.pi, np.pi, 1.5*np.pi, 2*np.pi]) + ax2.set_xticklabels(["0", r"$\frac{1}{2}\pi$", + r"$\pi$", r"$\frac{3}{2}\pi$", r"2ドル\pi$"]) + + +.. plot:: mpl_toolkits/axes_grid/figures/simple_axisline4.py + + +AxisLine Axes lets you create a custom axis, :: + + # make new (right-side) yaxis, but wth some offset + offset = (20, 0) + new_axisline = ax.get_grid_helper().new_fixed_axis + ax.axis["right2"] = new_axisline(loc="right", + offset=offset) + + +And, you can use it with parasiteAxes. + + +.. plot:: mpl_toolkits/axes_grid/figures/demo_parasite_axes2.py + + +AnchoredArtists +=============== + +It's a collection of artists whose location is anchored to the (axes) +bbox, like the legend. It is derived from *OffsetBox* in mpl, and +artist need to be drawn in the canvas coordinate. But, there is a +limited support for an arbitrary transform. For example, the ellipse +in the example below will have width and height in the data +coordinate. + +.. plot:: mpl_toolkits/axes_grid/figures/simple_anchored_artists.py + :include-source: + + Modified: trunk/matplotlib/doc/users/toolkits.rst =================================================================== --- trunk/matplotlib/doc/users/toolkits.rst 2009年04月17日 16:34:09 UTC (rev 7047) +++ trunk/matplotlib/doc/users/toolkits.rst 2009年04月17日 19:35:59 UTC (rev 7048) @@ -53,3 +53,17 @@ line, mesh) tools. Not the fastest or feature complete 3D library out there, but ships with matplotlib and thus may be a lighter weight solution for some use cases. + + +.. _toolkit_axes_grid: + +AxesGrid +======== + +The matplotlib AxesGrid toolkit is a collection of helper classes to +ease displaying multiple images in matplotlib. The AxesGrid toolkit is +distributed with matplotlib source. + +.. image:: ../_static/demo_axes_grid.png + +See :ref:`toolkit_axesgrid-index` for documentations. Added: trunk/matplotlib/examples/axes_grid/demo_axes_divider.py =================================================================== --- trunk/matplotlib/examples/axes_grid/demo_axes_divider.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/demo_axes_divider.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,124 @@ +import matplotlib.pyplot as plt +from demo_image import get_demo_image +#import mpl_toolkits.imaging.axes_grid as imaging + +def demo_simple_image(ax): + 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) + + +def demo_locatable_axes_hard(fig1): + + from mpl_toolkits.axes_grid \ + import SubplotDivider, LocatableAxes, Size + + 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.axis["left"].toggle(all=False) + ax_cb.axis["right"].toggle(ticks=True) + + 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) + + +def demo_locatable_axes_easy(ax): + from mpl_toolkits.axes_grid import make_axes_locatable + + divider = make_axes_locatable(ax) + + ax_cb = divider.new_horizontal(size="5%", pad=0.05) + fig1 = ax.get_figure() + fig1.add_axes(ax_cb) + + Z, extent = get_demo_image() + im = ax.imshow(Z, extent=extent, interpolation="nearest") + + plt.colorbar(im, cax=ax_cb) + ax_cb.yaxis.tick_right() + for tl in ax_cb.get_yticklabels(): + tl.set_visible(False) + ax_cb.yaxis.tick_right() + + +def demo_images_side_by_sied(ax): + from mpl_toolkits.axes_grid import make_axes_locatable + + divider = make_axes_locatable(ax) + + Z, extent = get_demo_image() + ax2 = divider.new_horizontal(size="100%", pad=0.05) + fig1 = ax.get_figure() + fig1.add_axes(ax2) + + ax.imshow(Z, extent=extent, interpolation="nearest") + ax2.imshow(Z, extent=extent, interpolation="nearest") + for tl in ax2.get_yticklabels(): + tl.set_visible(False) + + +def demo(): + + fig1 = plt.figure(1, (6, 6)) + fig1.clf() + + ## PLOT 1 + # simple image & colorbar + ax = fig1.add_subplot(2, 2, 1) + demo_simple_image(ax) + + ## PLOT 2 + # image and colorbar whose location is adjusted in the drawing time. + # a hard way + + demo_locatable_axes_hard(fig1) + + + ## PLOT 3 + # image and colorbar whose location is adjusted in the drawing time. + # a easy way + + ax = fig1.add_subplot(2, 2, 3) + demo_locatable_axes_easy(ax) + + + ## PLOT 4 + # two images side by sied with fixed padding. + + ax = fig1.add_subplot(2, 2, 4) + demo_images_side_by_sied(ax) + + plt.draw() + plt.show() + + + +if __name__ == "__main__": + demo() Added: trunk/matplotlib/examples/axes_grid/demo_axes_grid.py =================================================================== --- trunk/matplotlib/examples/axes_grid/demo_axes_grid.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/demo_axes_grid.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,87 @@ +import matplotlib.pyplot as plt +from demo_image import get_demo_image +from mpl_toolkits.axes_grid import AxesGrid + + +def demo_simple_grid(fig): + """ + A grid of 2x2 images with 0.05 inch pad between images and only + the lower-left axes is labeld. + """ + grid = AxesGrid(fig, 131, # similar to subplot(131) + nrows_ncols = (2, 2), + axes_pad = 0.05, + label_mode = "1", + ) + + Z, extent = get_demo_image() + for i in range(4): + im = grid[i].imshow(Z, extent=extent, interpolation="nearest") + + # This only affects axes in first column and second row as share_all = False. + grid.axes_llc.set_xticks([-2, 0, 2]) + grid.axes_llc.set_yticks([-2, 0, 2]) + + +def demo_grid_with_single_cbar(fig): + """ + A grid of 2x2 images with a single colobar + """ + grid = AxesGrid(fig, 132, # similar to subplot(132) + nrows_ncols = (2, 2), + axes_pad = 0.0, + share_all=True, + label_mode = "L", + cbar_mode="single", + ) + + Z, extent = get_demo_image() + for i in range(4): + im = grid[i].imshow(Z, extent=extent, interpolation="nearest") + plt.colorbar(im, cax = grid.cbar_axes[0]) + grid.cbar_axes[0].colorbar(im) + + # This affects all axes as share_all = True. + grid.axes_llc.set_xticks([-2, 0, 2]) + grid.axes_llc.set_yticks([-2, 0, 2]) + + +def demo_grid_with_each_cbar(fig): + """ + A grid of 2x2 images. Each image has its own colobar. + """ + + grid = AxesGrid(F, 133, # similar to subplot(122) + nrows_ncols = (2, 2), + axes_pad = 0.1, + label_mode = "1", + share_all = True, + cbar_location="top", + cbar_mode="each", + cbar_size="7%", + cbar_pad="2%", + ) + Z, extent = get_demo_image() + for i in range(4): + im = grid[i].imshow(Z, extent=extent, interpolation="nearest") + grid.cbar_axes[i].colorbar(im) + + # This affects all axes because we set share_all = True. + grid.axes_llc.set_xticks([-2, 0, 2]) + grid.axes_llc.set_yticks([-2, 0, 2]) + + + +if __name__ == "__main__": + + F = plt.figure(1, (5.5, 2.5)) + + F.subplots_adjust(left=0.05, right=0.98) + + demo_simple_grid(F) + demo_grid_with_single_cbar(F) + demo_grid_with_each_cbar(F) + + plt.draw() + plt.show() + Added: trunk/matplotlib/examples/axes_grid/demo_axes_rgb.py =================================================================== --- trunk/matplotlib/examples/axes_grid/demo_axes_rgb.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/demo_axes_rgb.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,82 @@ +import numpy as np +import matplotlib.pyplot as plt + +from demo_axes_divider import get_demo_image +from mpl_toolkits.axes_grid.axes_rgb import make_rgb_axes, RGBAxes + +def get_rgb(): + Z, extent = get_demo_image() + + Z[Z<0] = 0. + Z = Z/Z.max() + + R = Z[:13,:13] + G = Z[2:,2:] + B = Z[:13,2:] + + return R, G, B + + +def make_cube(r, g, b): + ny, nx = r.shape + R = np.zeros([ny, nx, 3], dtype="d") + R[:,:,0] = r + G = np.zeros_like(R) + G[:,:,1] = g + B = np.zeros_like(R) + B[:,:,2] = b + + RGB = R + G + B + + return R, G, B, RGB + + + +def demo_rgb(): + fig = plt.figure(1) + fig.clf() + + ax = fig.add_subplot(111) + ax_r, ax_g, ax_b = make_rgb_axes(ax, pad=0.02) + #fig.add_axes(ax_r) + #fig.add_axes(ax_g) + #fig.add_axes(ax_b) + + r, g, b = get_rgb() + im_r, im_g, im_b, im_rgb = make_cube(r, g, b) + kwargs = dict(origin="lower", interpolation="nearest") + ax.imshow(im_rgb, **kwargs) + ax_r.imshow(im_r, **kwargs) + ax_g.imshow(im_g, **kwargs) + ax_b.imshow(im_b, **kwargs) + + + + +def demo_rgb2(): + fig = plt.figure(2) + ax = RGBAxes(fig, [0.1, 0.1, 0.8, 0.8], pad=0.0) + #fig.add_axes(ax) + #ax.add_RGB_to_figure() + + r, g, b = get_rgb() + kwargs = dict(origin="lower", interpolation="nearest") + ax.imshow_rgb(r, g, b, **kwargs) + + ax.RGB.set_xlim(0., 9.5) + ax.RGB.set_ylim(0.9, 10.6) + + for ax1 in [ax.RGB, ax.R, ax.G, ax.B]: + for axisline in ax1._axislines.values(): + axisline.line.set_color("w") + axisline.major_ticks.set_mec("w") + + return ax + + +if __name__ == "__main__": + demo_rgb() + ax = demo_rgb2() + + plt.draw() + plt.show() Added: trunk/matplotlib/examples/axes_grid/demo_fixed_size_axes.py =================================================================== --- trunk/matplotlib/examples/axes_grid/demo_fixed_size_axes.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/demo_fixed_size_axes.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,57 @@ +import matplotlib.pyplot as plt + +from mpl_toolkits.axes_grid \ + import Divider, LocatableAxes, Size + +def demo_fixed_size_axes(): + + fig1 = plt.figure(1, (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(fig1, (0.0, 0.0, 1., 1.), h, v, aspect=False) + # the width and height of the rectangle is ignored. + + ax = LocatableAxes(fig1, divider.get_position()) + ax.set_axes_locator(divider.new_locator(nx=1, ny=1)) + + fig1.add_axes(ax) + + ax.plot([1,2,3]) + + + + +def demo_fixed_pad_axes(): + + fig = plt.figure(2, (6, 6)) + + # The first & third items are for padding and the second items are for the axes. + # sizes are in inch. + h = [Size.Fixed(1.0), Size.Scaled(1.), Size.Fixed(.2),] + v = [Size.Fixed(0.7), Size.Scaled(1.), Size.Fixed(.5),] + + divider = Divider(fig, (0.0, 0.0, 1., 1.), h, v, aspect=False) + # the width and height of the rectangle is ignored. + + ax = LocatableAxes(fig, divider.get_position()) + ax.set_axes_locator(divider.new_locator(nx=1, ny=1)) + + fig.add_axes(ax) + + ax.plot([1,2,3]) + + + + + + +if __name__ == "__main__": + demo_fixed_size_axes() + demo_fixed_pad_axes() + + plt.draw() + plt.show() Added: trunk/matplotlib/examples/axes_grid/demo_image.py =================================================================== --- trunk/matplotlib/examples/axes_grid/demo_image.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/demo_image.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,17 @@ +import numpy as np + +def get_demo_image(): + # prepare image + delta = 0.5 + + extent = (-3,4,-4,3) + 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 + Added: trunk/matplotlib/examples/axes_grid/demo_parasite_axes.py =================================================================== --- trunk/matplotlib/examples/axes_grid/demo_parasite_axes.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/demo_parasite_axes.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,53 @@ +from mpl_toolkits.axes_grid.parasite_axes import HostAxes, ParasiteAxes +import matplotlib.pyplot as plt + +if __name__ == "__main__": + fig = plt.figure(1) + + host = HostAxes(fig, [0.15, 0.1, 0.65, 0.8]) + par1 = ParasiteAxes(host, sharex=host) + par2 = ParasiteAxes(host, sharex=host) + host.parasites.append(par1) + host.parasites.append(par2) + + host.set_ylabel("Density") + host.set_xlabel("Distance") + + host.axis["right"].set_visible(False) + par1.axis["right"].set_visible(True) + par1.set_ylabel("Temperature") + + par1.axis["right"].major_ticklabels.set_visible(True) + par1.axis["right"].label.set_visible(True) + + par2.set_ylabel("Velocity") + offset = (60, 0) + new_axisline = par2._grid_helper.new_axisline + par2.axis["right2"] = new_axisline(loc="right", + offset=offset) + + + fig.add_axes(host) + + host.set_xlim(0, 2) + host.set_ylim(0, 2) + + host.set_xlabel("Distance") + host.set_ylabel("Density") + par1.set_ylabel("Temperature") + + p1, = host.plot([0, 1, 2], [0, 1, 2], label="Density") + p2, = par1.plot([0, 1, 2], [0, 3, 2], label="Temperature") + p3, = par2.plot([0, 1, 2], [50, 30, 15], label="Velocity") + + par1.set_ylim(0, 4) + par2.set_ylim(1, 65) + + host.legend() + + host.axis["left"].label.set_color(p1.get_color()) + par1.axis["right"].label.set_color(p2.get_color()) + par2.axis["right2"].label.set_color(p3.get_color()) + + plt.draw() + plt.show() Added: trunk/matplotlib/examples/axes_grid/demo_parasite_axes2.py =================================================================== --- trunk/matplotlib/examples/axes_grid/demo_parasite_axes2.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/demo_parasite_axes2.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,54 @@ +from mpl_toolkits.axes_grid.parasite_axes import SubplotHost +import matplotlib.transforms as mtransforms +import matplotlib.pyplot as plt + +if 1: + fig = plt.figure(1) + + host = SubplotHost(fig, 111) + + host.set_ylabel("Density") + host.set_xlabel("Distance") + + par1 = host.twinx() + par2 = host.twinx() + + par1.set_ylabel("Temperature") + + par2.axis["right"].set_visible(False) + + offset = 60, 0 + new_axisline = par2.get_grid_helper().new_fixed_axis + par2.axis["right2"] = new_axisline(loc="right", + offset=offset) + + par2.axis["right2"].label.set_visible(True) + par2.axis["right2"].set_label("Velocity") + + fig.add_axes(host) + plt.subplots_adjust(right=0.75) + + host.set_xlim(0, 2) + host.set_ylim(0, 2) + + host.set_xlabel("Distance") + host.set_ylabel("Density") + par1.set_ylabel("Temperature") + + p1, = host.plot([0, 1, 2], [0, 1, 2], label="Density") + p2, = par1.plot([0, 1, 2], [0, 3, 2], label="Temperature") + p3, = par2.plot([0, 1, 2], [50, 30, 15], label="Velocity") + + par1.set_ylim(0, 4) + par2.set_ylim(1, 65) + + host.legend() + + host.axis["left"].label.set_color(p1.get_color()) + par1.axis["right"].label.set_color(p2.get_color()) + par2.axis["right2"].label.set_color(p3.get_color()) + + plt.draw() + plt.show() + + #plt.savefig("Test") Added: trunk/matplotlib/examples/axes_grid/parasite_simple.py =================================================================== --- trunk/matplotlib/examples/axes_grid/parasite_simple.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/parasite_simple.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,24 @@ +from mpl_toolkits.axes_grid.parasite_axes import SubplotHost +import matplotlib.pyplot as plt + +fig = plt.figure(1) + +host = SubplotHost(fig, 111) +fig.add_subplot(host) + +par = host.twinx() + +host.set_xlabel("Distance") +host.set_ylabel("Density") +par.set_ylabel("Temperature") + +p1, = host.plot([0, 1, 2], [0, 1, 2], label="Density") +p2, = par.plot([0, 1, 2], [0, 3, 2], label="Temperature") + +host.axis["left"].label.set_color(p1.get_color()) +par.axis["right"].label.set_color(p2.get_color()) + +host.legend() + +plt.show() + Added: trunk/matplotlib/examples/axes_grid/parasite_simple2.py =================================================================== --- trunk/matplotlib/examples/axes_grid/parasite_simple2.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/parasite_simple2.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,42 @@ +import matplotlib.transforms as mtransforms +import matplotlib.pyplot as plt +from mpl_toolkits.axes_grid.parasite_axes import SubplotHost + +obs = [["01_S1", 3.88, 0.14, 1970, 63], + ["01_S4", 5.6, 0.82, 1622, 150], + ["02_S1", 2.4, 0.54, 1570, 40], + ["03_S1", 4.1, 0.62, 2380, 170]] + + +fig = plt.figure() + +ax_kms = SubplotHost(fig, 1,1,1, aspect=1.) + +# angular proper motion("/yr) to linear velocity(km/s) at distance=2.3kpc +pm_to_kms = 1./206265.*2300*3.085e18/3.15e7/1.e5 + +aux_trans = mtransforms.Affine2D().scale(pm_to_kms, 1.) +ax_pm = ax_kms.twin(aux_trans) +ax_pm.set_viewlim_mode("transform") + +fig.add_subplot(ax_kms) + +for n, ds, dse, w, we in obs: + time = ((2007+(10. + 4/30.)/12)-1988.5) + v = ds / time * pm_to_kms + ve = dse / time * pm_to_kms + ax_kms.errorbar([v], [w], xerr=[ve], yerr=[we], color="k") + + +ax_kms.axis["bottom"].set_label("Linear velocity at 2.3 kpc [km/s]") +ax_kms.axis["left"].set_label("FWHM [km/s]") +ax_pm.axis["top"].set_label("Proper Motion [$^{''}$/yr]") +ax_pm.axis["top"].label.set_visible(True) +ax_pm.axis["right"].major_ticklabels.set_visible(False) + +ax_kms.set_xlim(950, 3700) +ax_kms.set_ylim(950, 3100) +# xlim and ylim of ax_pms will be automatically adjusted. + +plt.draw() +plt.show() Added: trunk/matplotlib/examples/axes_grid/scatter_hist.py =================================================================== --- trunk/matplotlib/examples/axes_grid/scatter_hist.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/scatter_hist.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,60 @@ +import numpy as np +import matplotlib.pyplot as plt + +# the random data +x = np.random.randn(1000) +y = np.random.randn(1000) + + +fig = plt.figure(1, figsize=(5.5,5.5)) + +from mpl_toolkits.axes_grid import make_axes_locatable + +axScatter = plt.subplot(111) +divider = make_axes_locatable(axScatter) + +# create a new axes with a height of 1.2 inch above the axScatter +axHistx = divider.new_vertical(1.2, pad=0.1, sharex=axScatter) + +# create a new axes with a width of 1.2 inch on the right side of the +# axScatter +axHisty = divider.new_horizontal(1.2, pad=0.1, sharey=axScatter) + +fig.add_axes(axHistx) +fig.add_axes(axHisty) + + +# make some labels invisible +plt.setp(axHistx.get_xticklabels() + axHisty.get_yticklabels(), + visible=False) + +# the scatter plot: +axScatter.scatter(x, y) +axScatter.set_aspect(1.) + +# now determine nice limits by hand: +binwidth = 0.25 +xymax = np.max( [np.max(np.fabs(x)), np.max(np.fabs(y))] ) +lim = ( int(xymax/binwidth) + 1) * binwidth + +bins = np.arange(-lim, lim + binwidth, binwidth) +axHistx.hist(x, bins=bins) +axHisty.hist(y, bins=bins, orientation='horizontal') + +# the xaxis of axHistx and yaxis of axHisty are shared with axScatter, +# thus there is no need to manually adjust the xlim and ylim of these +# axis. + +#axHistx.axis["bottom"].major_ticklabels.set_visible(False) +for tl in axHistx.get_xticklabels(): + tl.set_visible(False) +axHistx.set_yticks([0, 50, 100]) + +#axHisty.axis["left"].major_ticklabels.set_visible(False) +for tl in axHisty.get_yticklabels(): + tl.set_visible(False) +axHisty.set_xticks([0, 50, 100]) + +plt.draw() +#plt.show() +plt.savefig("a.pdf") Added: trunk/matplotlib/examples/axes_grid/simple_anchored_artists.py =================================================================== --- trunk/matplotlib/examples/axes_grid/simple_anchored_artists.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/simple_anchored_artists.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,60 @@ +import matplotlib.pyplot as plt + + +def draw_text(ax): + from mpl_toolkits.axes_grid.anchored_artists import AnchoredText + at = AnchoredText("Figure 1a", + loc=2, prop=dict(size=8), frameon=True, + ) + at.patch.set_boxstyle("round,pad=0.,rounding_size=0.2") + ax.add_artist(at) + + at2 = AnchoredText("Figure 1(b)", + loc=3, prop=dict(size=8), frameon=True, + bbox_to_anchor=(0., 1.) + ) + at2.patch.set_boxstyle("round,pad=0.,rounding_size=0.2") + ax.add_artist(at2) + +def draw_circle(ax): # circle in the canvas coordinate + from mpl_toolkits.axes_grid.anchored_artists import AnchoredDrawingArea + from matplotlib.patches import Circle + ada = AnchoredDrawingArea(20, 20, 0, 0, + loc=1, pad=0., frameon=False) + p = Circle((10, 10), 10) + ada.da.add_artist(p) + ax.add_artist(ada) + +def draw_ellipse(ax): + from mpl_toolkits.axes_grid.anchored_artists import AnchoredEllipse + # draw an ellipse of width=0.1, height=0.15 in the data coordinate + ae = AnchoredEllipse(ax.transData, width=0.1, height=0.15, angle=0., + loc=3, pad=0.5, borderpad=0.4, frameon=True) + + ax.add_artist(ae) + +def draw_sizebar(ax): + from mpl_toolkits.axes_grid.anchored_artists import AnchoredSizeBar + # draw a horizontal bar with length of 0.1 in Data coordinate + # (ax.transData) with a label underneath. + as = AnchoredSizeBar(ax.transData, + 0.1, + r"1$^{\prime}$", + loc=8, + pad=0.1, borderpad=0.5, sep=5, + frameon=False) + ax.add_artist(as) + + +if 1: + ax = plt.gca() + ax.set_aspect(1.) + + draw_text(ax) + draw_circle(ax) + draw_ellipse(ax) + draw_sizebar(ax) + + plt.show() + + Added: trunk/matplotlib/examples/axes_grid/simple_axes_divider1.py =================================================================== --- trunk/matplotlib/examples/axes_grid/simple_axes_divider1.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/simple_axes_divider1.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,30 @@ +from mpl_toolkits.axes_grid import Size, Divider +import matplotlib.pyplot as plt + + +fig1 = plt.figure(1, (6, 6)) + +# fixed size in inch +horiz = [Size.Fixed(1.), Size.Fixed(.5), Size.Fixed(1.5), + Size.Fixed(.5)] +vert = [Size.Fixed(1.5), Size.Fixed(.5), Size.Fixed(1.)] + +rect = (0.1, 0.1, 0.8, 0.8) +# divide the axes rectangle into grid whose size is specified by horiz * vert +divider = Divider(fig1, rect, horiz, vert, aspect=False) + +# the rect parameter will be ignore as we will set axes_locator +ax1 = fig1.add_axes(rect, label="1") +ax2 = fig1.add_axes(rect, label="2") +ax3 = fig1.add_axes(rect, label="3") +ax4 = fig1.add_axes(rect, label="4") + +ax1.set_axes_locator(divider.new_locator(nx=0, ny=0)) +ax2.set_axes_locator(divider.new_locator(nx=0, ny=2)) +ax3.set_axes_locator(divider.new_locator(nx=2, ny=2)) +ax4.set_axes_locator(divider.new_locator(nx=2, nx1=4, ny=0)) + + + +plt.draw() +plt.show() Added: trunk/matplotlib/examples/axes_grid/simple_axes_divider2.py =================================================================== --- trunk/matplotlib/examples/axes_grid/simple_axes_divider2.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/simple_axes_divider2.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,28 @@ +from mpl_toolkits.axes_grid import Size, Divider +import matplotlib.pyplot as plt + +fig1 = plt.figure(1, (5.5, 4.)) + +# the rect parameter will be ignore as we will set axes_locator +rect = (0.1, 0.1, 0.8, 0.8) +ax = [fig1.add_axes(rect, label="%d"%i) for i in range(4)] + +horiz = [Size.Scaled(1.5), Size.Fixed(.5), Size.Scaled(1.), + Size.Scaled(.5)] + +vert = [Size.Scaled(1.), Size.Fixed(.5), Size.Scaled(1.5)] + +# divide the axes rectangle into grid whose size is specified by horiz * vert +divider = Divider(fig1, rect, horiz, vert, aspect=False) + +ax[0].set_axes_locator(divider.new_locator(nx=0, ny=0)) +ax[1].set_axes_locator(divider.new_locator(nx=0, ny=2)) +ax[2].set_axes_locator(divider.new_locator(nx=2, ny=2)) +ax[3].set_axes_locator(divider.new_locator(nx=2, nx1=4, ny=0)) + +for ax1 in ax: + plt.setp(ax1.get_xticklabels()+ax1.get_yticklabels(), + visible=False) + +plt.draw() +plt.show() Added: trunk/matplotlib/examples/axes_grid/simple_axes_divider3.py =================================================================== --- trunk/matplotlib/examples/axes_grid/simple_axes_divider3.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/simple_axes_divider3.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,37 @@ +from mpl_toolkits.axes_grid import Size, Divider +import matplotlib.pyplot as plt + + +fig1 = plt.figure(1, (5.5, 4)) + +# the rect parameter will be ignore as we will set axes_locator +rect = (0.1, 0.1, 0.8, 0.8) +ax = [fig1.add_axes(rect, label="%d"%i) for i in range(4)] + + +horiz = [Size.AxesX(ax[0]), Size.Fixed(.5), Size.AxesX(ax[1])] +vert = [Size.AxesY(ax[0]), Size.Fixed(.5), Size.AxesY(ax[2])] + +# divide the axes rectangle into grid whose size is specified by horiz * vert +divider = Divider(fig1, rect, horiz, vert, aspect=False) + + +ax[0].set_axes_locator(divider.new_locator(nx=0, ny=0)) +ax[1].set_axes_locator(divider.new_locator(nx=2, ny=0)) +ax[2].set_axes_locator(divider.new_locator(nx=0, ny=2)) +ax[3].set_axes_locator(divider.new_locator(nx=2, ny=2)) + +ax[0].set_xlim(0, 2) +ax[1].set_xlim(0, 1) + +ax[0].set_ylim(0, 1) +ax[2].set_ylim(0, 2) + +divider.set_aspect(1.) + +for ax1 in ax: + plt.setp(ax1.get_xticklabels()+ax1.get_yticklabels(), + visible=False) + +plt.draw() +plt.show() Added: trunk/matplotlib/examples/axes_grid/simple_axesgrid.py =================================================================== --- trunk/matplotlib/examples/axes_grid/simple_axesgrid.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/simple_axesgrid.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,17 @@ +import matplotlib.pyplot as plt +from mpl_toolkits.axes_grid import AxesGrid +import numpy as np + +im = np.arange(100) +im.shape = 10, 10 + +fig = plt.figure(1, (4., 4.)) +grid = AxesGrid(fig, 111, # similar to subplot(111) + nrows_ncols = (2, 2), # creates 2x2 grid of axes + axes_pad=0.1, # pad between axes in inch. + ) + +for i in range(4): + grid[i].imshow(im) # The AxesGrid object work as a list of axes. + +plt.show() Added: trunk/matplotlib/examples/axes_grid/simple_axesgrid2.py =================================================================== --- trunk/matplotlib/examples/axes_grid/simple_axesgrid2.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/simple_axesgrid2.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,24 @@ +import matplotlib.pyplot as plt +from mpl_toolkits.axes_grid import AxesGrid +from demo_image import get_demo_image + +F = plt.figure(1, (5.5, 3.5)) +grid = AxesGrid(F, 111, # similar to subplot(111) + nrows_ncols = (1, 3), + axes_pad = 0.1, + add_all=True, + label_mode = "L", + ) + +Z, extent = get_demo_image() # demo image + +im1=Z +im2=Z[:,:10] +im3=Z[:,10:] +vmin, vmax = Z.min(), Z.max() +for i, im in enumerate([im1, im2, im3]): + ax = grid[i] + ax.imshow(im, origin="lower", vmin=vmin, vmax=vmax, interpolation="nearest") + +plt.draw() +plt.show() Added: trunk/matplotlib/examples/axes_grid/simple_axisline.py =================================================================== --- trunk/matplotlib/examples/axes_grid/simple_axisline.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/simple_axisline.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,37 @@ +import matplotlib.pyplot as plt + +from mpl_toolkits.axes_grid.axislines import SubplotZero + +if 1: + + fig = plt.figure(1) + fig.subplots_adjust(right=0.85) + ax = SubplotZero(fig, 1, 1, 1) + fig.add_subplot(ax) + + # make right and top axis invisible + ax.axis["right"].set_visible(False) + ax.axis["top"].set_visible(False) + + # make xzero axis (horizontal axis line through y=0) visible. + ax.axis["xzero"].set_visible(True) + ax.axis["xzero"].label.set_text("Axis Zero") + + ax.set_ylim(-2, 4) + ax.set_xlabel("Label X") + ax.set_ylabel("Label Y") + # or + #ax.axis["bottom"].label.set_text("Label X") + #ax.axis["left"].label.set_text("Label Y") + + # make new (right-side) yaxis, but wth some offset + offset = (20, 0) + new_axisline = ax.get_grid_helper().new_axisline + ax.axis["right2"] = new_axisline(loc="right", + offset=offset) + ax.axis["right2"].label.set_text("Label Y2") + + ax.plot([-2,3,2]) + plt.draw() + plt.show() + Added: trunk/matplotlib/examples/axes_grid/simple_axisline2.py =================================================================== --- trunk/matplotlib/examples/axes_grid/simple_axisline2.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/simple_axisline2.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,24 @@ +import matplotlib.pyplot as plt +from mpl_toolkits.axes_grid.axislines import SubplotZero +import numpy as np + +fig = plt.figure(1, (4,3)) + +# a subplot with two additiona axis, "xzero" and "yzero". "xzero" is +# y=0 line, and "yzero" is x=0 line. +ax = SubplotZero(fig, 1, 1, 1) +fig.add_subplot(ax) + +# make xzero axis (horizontal axis line through y=0) visible. +ax.axis["xzero"].set_visible(True) +ax.axis["xzero"].label.set_text("Axis Zero") + +# make other axis (bottom, top, right) invisible. +for n in ["bottom", "top", "right"]: + ax.axis[n].set_visible(False) + +xx = np.arange(0, 2*np.pi, 0.01) +ax.plot(xx, np.sin(xx)) + +plt.show() + Added: trunk/matplotlib/examples/axes_grid/simple_axisline3.py =================================================================== --- trunk/matplotlib/examples/axes_grid/simple_axisline3.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/simple_axisline3.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,13 @@ +import matplotlib.pyplot as plt +from mpl_toolkits.axes_grid.axislines import Subplot + +fig = plt.figure(1, (3,3)) + +ax = Subplot(fig, 111) +fig.add_subplot(ax) + +ax.axis["right"].set_visible(False) +ax.axis["top"].set_visible(False) + +plt.show() + Added: trunk/matplotlib/examples/axes_grid/simple_axisline4.py =================================================================== --- trunk/matplotlib/examples/axes_grid/simple_axisline4.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/simple_axisline4.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,22 @@ +import matplotlib.pyplot as plt +from mpl_toolkits.axes_grid.parasite_axes import SubplotHost +import numpy as np + +fig = plt.figure(1, (4,3)) + +ax = SubplotHost(fig, 111) +fig.add_subplot(ax) + +xx = np.arange(0, 2*np.pi, 0.01) +ax.plot(xx, np.sin(xx)) + +ax2 = ax.twin() # ax2 is responsible for "top" axis and "right" axis +ax2.set_xticks([0., .5*np.pi, np.pi, 1.5*np.pi, 2*np.pi]) +ax2.set_xticklabels(["0", r"$\frac{1}{2}\pi$", + r"$\pi$", r"$\frac{3}{2}\pi$", r"2ドル\pi$"]) + +ax2.axis["right"].major_ticklabels.set_visible(False) + +plt.draw() +plt.show() + Added: trunk/matplotlib/examples/axes_grid/simple_rgb.py =================================================================== --- trunk/matplotlib/examples/axes_grid/simple_rgb.py (rev 0) +++ trunk/matplotlib/examples/axes_grid/simple_rgb.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,31 @@ +import matplotlib.pyplot as plt + +from demo_image import get_demo_image +from mpl_toolkits.axes_grid.axes_rgb import RGBAxes + +def get_rgb(): + Z, extent = get_demo_image() + + Z[Z<0] = 0. + Z = Z/Z.max() + + R = Z[:13,:13] + G = Z[2:,2:] + B = Z[:13,2:] + + return R, G, B + + +fig = plt.figure(1) +ax = RGBAxes(fig, [0.1, 0.1, 0.8, 0.8]) + +r, g, b = get_rgb() +kwargs = dict(origin="lower", interpolation="nearest") +ax.imshow_rgb(r, g, b, **kwargs) + +ax.RGB.set_xlim(0., 9.5) +ax.RGB.set_ylim(0.9, 10.6) + + +plt.draw() +plt.show() Added: trunk/matplotlib/lib/mpl_toolkits/axes_grid/__init__.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/__init__.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/__init__.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,9 @@ +""" +AxesGrid +""" + + +from axes_divider import Divider, SubplotDivider, LocatableAxes, Size, \ + make_axes_locatable +from axes_grid import AxesGrid + Added: trunk/matplotlib/lib/mpl_toolkits/axes_grid/anchored_artists.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/anchored_artists.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/anchored_artists.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,122 @@ + + +from matplotlib.font_manager import FontProperties +from matplotlib import rcParams +from matplotlib.patches import Rectangle, Ellipse + +from matplotlib.offsetbox import AnchoredOffsetbox, AuxTransformBox, VPacker,\ + TextArea, DrawingArea + + +class AnchoredText(AnchoredOffsetbox): + def __init__(self, s, loc, pad=0.4, borderpad=0.5, prop=None, **kwargs): + + self.txt = TextArea(s, textprops=prop, + minimumdescent=False) + fp = self.txt._text.get_fontproperties() + + super(AnchoredText, self).__init__(loc, pad=pad, borderpad=borderpad, + child=self.txt, + prop=fp, + **kwargs) + + +class AnchoredSizeBar(AnchoredOffsetbox): + def __init__(self, transform, size, label, loc, + pad=0.1, borderpad=0.1, sep=2, prop=None, frameon=True): + """ + Draw a horizontal bar with the size in data coordinate of the give axes. + A label will be drawn underneath (center-alinged). + + pad, borderpad in fraction of the legend font size (or prop) + sep in points. + """ + self.size_bar = AuxTransformBox(transform) + self.size_bar.add_artist(Rectangle((0,0), size, 0, fc="none")) + + self.txt_label = TextArea(label, minimumdescent=False) + + self._box = VPacker(children=[self.size_bar, self.txt_label], + align="center", + pad=0, sep=sep) + + AnchoredOffsetbox.__init__(self, loc, pad=pad, borderpad=borderpad, + child=self._box, + prop=prop, + frameon=frameon) + + +class AnchoredEllipse(AnchoredOffsetbox): + def __init__(self, transform, width, height, angle, loc, + pad=0.1, borderpad=0.1, prop=None, frameon=True): + """ + Draw an ellipse the size in data coordinate of the give axes. + + pad, borderpad in fraction of the legend font size (or prop) + """ + self._box = AuxTransformBox(transform) + self.ellipse = Ellipse((0,0), width, height, angle) + self._box.add_artist(self.ellipse) + + AnchoredOffsetbox.__init__(self, loc, pad=pad, borderpad=borderpad, + child=self._box, + prop=prop, + frameon=frameon) + + + +class AnchoredDrawingArea(AnchoredOffsetbox): + def __init__(self, width, height, xdescent, ydescent, + loc, pad=0.4, borderpad=0.5, prop=None, frameon=True): + + self.da = DrawingArea(width, height, xdescent, ydescent, clip=True) + + super(AnchoredDrawingArea, self).__init__(loc, pad=pad, borderpad=borderpad, + child=self.da, + prop=None, + frameon=frameon) + + + +if __name__ == "__main__": + import matplotlib.pyplot as plt + from matplotlib.patches import Circle + + #import matplotlib.offsetbox + #matplotlib.offsetbox.DEBUG=False + + #ax = plt.subplot(1,1,1) + plt.clf() + plt.cla() + plt.draw() + ax = plt.gca() + ax.set_aspect(1.) + + at = AnchoredText("Figure 1a", + loc=2, frameon=True) + at.patch.set_boxstyle("round,pad=0.,rounding_size=0.2") + ax.add_artist(at) + + ada = AnchoredDrawingArea(20, 20, 0, 0, + loc=1, pad=0., frameon=False) + p = Circle((10, 10), 10) + ada.da.add_artist(p) + ax.add_artist(ada) + + + as = AnchoredSizeBar(ax, 0.1, r"1$^{\prime}$", + loc=8, + pad=0.1, borderpad=0.5, sep=5, + frameon=False) + ax.add_artist(as) + + + ae = AnchoredEllipse(ax, width=0.1, height=0.15, angle=0., + loc=3, pad=0.5, borderpad=0.4, frameon=True) + + ax.add_artist(ae) + + plt.draw() + plt.show() + + Added: trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_divider.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_divider.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/axes_grid/axes_divider.py 2009年04月17日 19:35:59 UTC (rev 7048) @@ -0,0 +1,652 @@ +""" +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 + + 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 + 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 + + +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 Divid... [truncated message content]
Revision: 7047 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7047&view=rev Author: leejjoon Date: 2009年04月17日 16:34:09 +0000 (2009年4月17日) Log Message: ----------- Added a support for bbox_to_anchor in offsetbox.AnchoredOffsetbox Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/offsetbox.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009年04月17日 02:31:16 UTC (rev 7046) +++ trunk/matplotlib/CHANGELOG 2009年04月17日 16:34:09 UTC (rev 7047) @@ -1,5 +1,9 @@ ====================================================================== +2009年04月17日 Added a support for bbox_to_anchor in + offsetbox.AnchoredOffsetbox. Improved a documentation. + - JJL + 2009年04月16日 Fixed a offsetbox bug that multiline texts are not correctly aligned. - JJL Modified: trunk/matplotlib/lib/matplotlib/offsetbox.py =================================================================== --- trunk/matplotlib/lib/matplotlib/offsetbox.py 2009年04月17日 02:31:16 UTC (rev 7046) +++ trunk/matplotlib/lib/matplotlib/offsetbox.py 2009年04月17日 16:34:09 UTC (rev 7047) @@ -19,7 +19,12 @@ import matplotlib.artist as martist import matplotlib.text as mtext import numpy as np +from matplotlib.transforms import Bbox, TransformedBbox, BboxTransformTo +from matplotlib.font_manager import FontProperties +from matplotlib.patches import FancyBboxPatch +from matplotlib import rcParams + from matplotlib.patches import bbox_artist as mbbox_artist DEBUG=False # for debuging use @@ -291,7 +296,7 @@ for c in self.get_visible_children(): if isinstance(c, PackerBase) and c.mode == "expand": c.set_width(self.width) - + whd_list = [c.get_extent(renderer) for c in self.get_visible_children()] whd_list = [(w, h, xd, (h-yd)) for w, h, xd, yd in whd_list] @@ -752,7 +757,7 @@ self.ref_offset_transform.translate(-ub.x0, -ub.y0) # restor offset transform self.offset_transform.matrix_from_values(*_off) - + return ub.width, ub.height, 0., 0. @@ -767,15 +772,51 @@ bbox_artist(self, renderer, fill=False, props=dict(pad=0.)) -from matplotlib.font_manager import FontProperties -from matplotlib.patches import FancyBboxPatch -from matplotlib import rcParams -from matplotlib.transforms import Bbox class AnchoredOffsetbox(OffsetBox): + """ + An offset box placed according to the legend location + loc. AnchoredOffsetbox has a single child. When multiple children + is needed, use other OffsetBox class to enlose them. By default, + the offset box is anchored against its parent axes. You may + explicitly specify the bbox_to_anchor. + """ + def __init__(self, loc, pad=0.4, borderpad=0.5, - child=None, prop=None, frameon=True): + child=None, prop=None, frameon=True, + bbox_to_anchor=None, + bbox_transform=None): + """ + loc is a string or an integer specifying the legend location. + The valid location codes are:: + 'upper right' : 1, + 'upper left' : 2, + 'lower left' : 3, + 'lower right' : 4, + 'right' : 5, + 'center left' : 6, + 'center right' : 7, + 'lower center' : 8, + 'upper center' : 9, + 'center' : 10, + + + pad : pad around the child for drawing a frame. given in + fraction of fontsize. + + borderpad : pad between offsetbox frame and the bbox_to_anchor, + + child : OffsetBox instance that will be anchored. + + prop : font property. This is only used as a reference for paddings. + + frameon : draw a frame box if True. + + bbox_to_anchor : bbox to anchor. If None, use axes.bbox. + + """ + super(AnchoredOffsetbox, self).__init__() self.set_child(child) @@ -788,7 +829,7 @@ self.prop=FontProperties(size=rcParams["legend.fontsize"]) else: self.prop = prop - + self.patch = FancyBboxPatch( xy=(0.0, 0.0), width=1., height=1., facecolor='w', edgecolor='k', @@ -797,48 +838,121 @@ ) self.patch.set_boxstyle("square",pad=0) self._drawFrame = frameon + #self._parent_bbox = bbox_to_anchor + self.set_bbox_to_anchor(bbox_to_anchor, bbox_transform) + + + def set_child(self, child): + "set the child to be anchored" self._child = child + def get_child(self): + "return the child" + return self._child + def get_children(self): + "return the list of children" return [self._child] - def get_child(self): - return self._child def get_extent(self, renderer): + """ + return the extent of the artist. The extent of the child + added with the pad is returned + """ w, h, xd, yd = self.get_child().get_extent(renderer) fontsize = renderer.points_to_pixels(self.prop.get_size_in_points()) pad = self.pad * fontsize return w+2*pad, h+2*pad, xd+pad, yd+pad + + def get_bbox_to_anchor(self): + """ + return the bbox that the legend will be anchored + """ + if self._bbox_to_anchor is None: + return self.axes.bbox + else: + transform = self._bbox_to_anchor_transform + if transform is None: + transform = BboxTransformTo(self.axes.bbox) + + return TransformedBbox(self._bbox_to_anchor, + transform) + + + + def set_bbox_to_anchor(self, bbox, transform=None): + """ + set the bbox that the child will be anchored. + + *bbox* can be a Bbox instance, a list of [left, bottom, width, + height], or a list of [left, bottom] where the width and + height will be assumed to be zero. The bbox will be + transformed to display coordinate by the given transform. If + transform is None, axes.transAxes will be use. + """ + if bbox is None: + self._bbox_to_anchor = None + elif isinstance(bbox, Bbox): + self._bbox_to_anchor = bbox + else: + try: + l = len(bbox) + except TypeError: + raise ValueError("Invalid argument for bbox : %s" % str(bbox)) + + if l == 2: + bbox = [bbox[0], bbox[1], 0, 0] + + self._bbox_to_anchor = Bbox.from_bounds(*bbox) + + self._bbox_to_anchor_transform = transform + + def get_window_extent(self, renderer): ''' get the bounding box in display space. ''' + self._update_offset_func(renderer) w, h, xd, yd = self.get_extent(renderer) ox, oy = self.get_offset(w, h, xd, yd) return Bbox.from_bounds(ox-xd, oy-yd, w, h) - def draw(self, renderer): - if not self.get_visible(): return + def _update_offset_func(self, renderer, fontsize=None): + """ + Update the offset func which depends on the dpi of the + renderer (because of the padding). + """ + if fontsize is None: + fontsize = renderer.points_to_pixels(self.prop.get_size_in_points()) - fontsize = renderer.points_to_pixels(self.prop.get_size_in_points()) - def _offset(w, h, xd, yd, fontsize=fontsize, self=self): bbox = Bbox.from_bounds(0, 0, w, h) borderpad = self.borderpad*fontsize + bbox_to_anchor = self.get_bbox_to_anchor() + x0, y0 = self._get_anchored_bbox(self.loc, bbox, - self.axes.bbox, + bbox_to_anchor, borderpad) return x0+xd, y0+yd self.set_offset(_offset) + + def draw(self, renderer): + "draw the artist" + + if not self.get_visible(): return + + fontsize = renderer.points_to_pixels(self.prop.get_size_in_points()) + self._update_offset_func(renderer, fontsize) + if self._drawFrame: # update the location and size of the legend bbox = self.get_window_extent(renderer) @@ -860,6 +974,10 @@ def _get_anchored_bbox(self, loc, bbox, parentbbox, borderpad): + """ + return the position of the bbox anchored at the parentbbox + with the loc code, with the borderpad. + """ assert loc in range(1,11) # called only internally BEST, UR, UL, LL, LR, R, CL, CR, LC, UC, C = range(11) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7046 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7046&view=rev Author: leejjoon Date: 2009年04月17日 02:31:16 +0000 (2009年4月17日) Log Message: ----------- Fixed a offsetbox bug that multiline texts are not correctly aligned. Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/offsetbox.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009年04月16日 17:30:29 UTC (rev 7045) +++ trunk/matplotlib/CHANGELOG 2009年04月17日 02:31:16 UTC (rev 7046) @@ -1,5 +1,8 @@ ====================================================================== +2009年04月16日 Fixed a offsetbox bug that multiline texts are not + correctly aligned. - JJL + 2009年04月16日 Fixed a bug in mixed mode renderer that images produced by an rasterizing backend are placed with incorrect size. - JJL @@ -17,7 +20,7 @@ create an output file. Thanks to Joao Luis Silva for reporting this. - JKS -2009年04月05日 _png.read_png() reads 12 bit PNGs (patch from +2009年04月05日 _png.read_png() reads 12 bit PNGs (patch from Tobias Wood) - ADS 2009年04月04日 Allow log axis scale to clip non-positive values to Modified: trunk/matplotlib/lib/matplotlib/offsetbox.py =================================================================== --- trunk/matplotlib/lib/matplotlib/offsetbox.py 2009年04月16日 17:30:29 UTC (rev 7045) +++ trunk/matplotlib/lib/matplotlib/offsetbox.py 2009年04月17日 02:31:16 UTC (rev 7046) @@ -620,27 +620,26 @@ line = info[0][0] # first line _, hh, dd = renderer.get_text_width_height_descent( - clean_line, self._text._fontproperties, ismath=ismath) + line, self._text._fontproperties, ismath=ismath) self._baseline_transform.clear() - if len(info) > 1 and self._multilinebaseline: # multi line - d = h-(hh-dd) # the baseline of the first line + d = h-(hh-dd) # the baseline of the first line + if len(info) > 1 and self._multilinebaseline: d_new = 0.5 * h - 0.5 * (h_ - d_) - self._baseline_transform.translate(0, d - d_new) d = d_new else: # single line - h_d = max(h_ - d_, h-dd) + h_d = max(h_ - d_, h-d) if self.get_minimumdescent(): ## to have a minimum descent, #i.e., "l" and "p" have same ## descents. - d = max(dd, d_) - else: - d = dd + d = max(d, d_) + #else: + # d = d h = h_d + d This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7045 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7045&view=rev Author: leejjoon Date: 2009年04月16日 17:30:29 +0000 (2009年4月16日) Log Message: ----------- updated changelog for r7044 Modified Paths: -------------- trunk/matplotlib/CHANGELOG Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009年04月16日 17:28:41 UTC (rev 7044) +++ trunk/matplotlib/CHANGELOG 2009年04月16日 17:30:29 UTC (rev 7045) @@ -1,5 +1,9 @@ ====================================================================== +2009年04月16日 Fixed a bug in mixed mode renderer that images produced by + an rasterizing backend are placed with incorrect size. + - JJL + 2008年04月14日 Added Jonathan Taylor's Reinier Heeres' port of John Porters' mplot3d to svn trunk. Package in mpl_toolkits.mplot3d and demo is examples/mplot3d/demo.py. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7044 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7044&view=rev Author: leejjoon Date: 2009年04月16日 17:28:41 +0000 (2009年4月16日) Log Message: ----------- Fixed a bug in mixed mode renderer that images produced by an rasterizing backend are placed with incorrect size. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backend_bases.py trunk/matplotlib/lib/matplotlib/backends/backend_mixed.py trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py trunk/matplotlib/lib/matplotlib/backends/backend_svg.py Added Paths: ----------- trunk/matplotlib/examples/misc/tight_bbox_test.py trunk/matplotlib/lib/matplotlib/tight_bbox.py Added: trunk/matplotlib/examples/misc/tight_bbox_test.py =================================================================== --- trunk/matplotlib/examples/misc/tight_bbox_test.py (rev 0) +++ trunk/matplotlib/examples/misc/tight_bbox_test.py 2009年04月16日 17:28:41 UTC (rev 7044) @@ -0,0 +1,14 @@ +import matplotlib.pyplot as plt +import numpy as np + +ax = plt.axes([0.1, 0.3, 0.5, 0.5]) + +ax.pcolormesh(np.array([[1,2],[3,4]])) +plt.yticks([0.5, 1.5], ["long long tick label", + "tick label"]) +plt.ylabel("My y-label") +plt.title("Check saved figures for their bboxes") +for ext in ["png", "pdf", "svg", "svgz", "eps"]: + print "saving tight_bbox_test.%s" % (ext,) + plt.savefig("tight_bbox_test.%s" % (ext,), bbox_inches="tight") +plt.show() Modified: trunk/matplotlib/lib/matplotlib/backend_bases.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backend_bases.py 2009年04月15日 17:52:23 UTC (rev 7043) +++ trunk/matplotlib/lib/matplotlib/backend_bases.py 2009年04月16日 17:28:41 UTC (rev 7044) @@ -36,6 +36,8 @@ from matplotlib.transforms import Bbox, TransformedBbox, Affine2D import cStringIO +import matplotlib.tight_bbox as tight_bbox + class RendererBase: """An abstract base class to handle drawing/rendering operations. @@ -271,7 +273,6 @@ gc.set_alpha(rgbFace[-1]) rgbFace = rgbFace[:3] gc.set_antialiased(antialiaseds[i % Naa]) - if Nurls: gc.set_url(urls[i % Nurls]) @@ -1426,7 +1427,16 @@ if bbox_inches: # call adjust_bbox to save only the given area if bbox_inches == "tight": - # save the figure to estimate the bounding box + # when bbox_inches == "tight", it saves the figure + # twice. The first save command is just to estimate + # the bounding box of the figure. A stringIO object is + # used as a temporary file object, but it causes a + # problem for some backends (ps backend with + # usetex=True) if they expect a filename, not a + # file-like object. As I think it is best to change + # the backend to support file-like object, i'm going + # to leave it as it is. However, a better solution + # than stringIO seems to be needed. -JJL result = getattr(self, method_name)( cStringIO.StringIO(), dpi=dpi, @@ -1439,10 +1449,13 @@ pad = kwargs.pop("pad_inches", 0.1) bbox_inches = bbox_inches.padded(pad) - restore_bbox = self._adjust_bbox(self.figure, format, - bbox_inches) + restore_bbox = tight_bbox.adjust_bbox(self.figure, format, + bbox_inches) + + _bbox_inches_restore = (bbox_inches, restore_bbox) + else: + _bbox_inches_restore = None - try: result = getattr(self, method_name)( filename, @@ -1450,6 +1463,7 @@ facecolor=facecolor, edgecolor=edgecolor, orientation=orientation, + bbox_inches_restore=_bbox_inches_restore, **kwargs) finally: if bbox_inches and restore_bbox: @@ -1463,108 +1477,8 @@ return result - def _adjust_bbox(self, fig, format, bbox_inches): - """ - Temporarily adjust the figure so that only the specified area - (bbox_inches) is saved. - It modifies fig.bbox, fig.bbox_inches, - fig.transFigure._boxout, and fig.patch. While the figure size - changes, the scale of the original figure is conserved. A - function whitch restores the original values are returned. - """ - origBbox = fig.bbox - origBboxInches = fig.bbox_inches - _boxout = fig.transFigure._boxout - - asp_list = [] - locator_list = [] - for ax in fig.axes: - pos = ax.get_position(original=False).frozen() - locator_list.append(ax.get_axes_locator()) - asp_list.append(ax.get_aspect()) - - def _l(a, r, pos=pos): return pos - ax.set_axes_locator(_l) - ax.set_aspect("auto") - - - - def restore_bbox(): - - for ax, asp, loc in zip(fig.axes, asp_list, locator_list): - ax.set_aspect(asp) - ax.set_axes_locator(loc) - - fig.bbox = origBbox - fig.bbox_inches = origBboxInches - fig.transFigure._boxout = _boxout - fig.transFigure.invalidate() - fig.patch.set_bounds(0, 0, 1, 1) - - if format in ["png", "raw", "rgba"]: - self._adjust_bbox_png(fig, bbox_inches) - return restore_bbox - elif format in ["pdf", "eps"]: - self._adjust_bbox_pdf(fig, bbox_inches) - return restore_bbox - else: - warnings.warn("bbox_inches option for %s backend is not implemented yet." % (format)) - return None - - - def _adjust_bbox_png(self, fig, bbox_inches): - """ - _adjust_bbox for png (Agg) format - """ - - tr = fig.dpi_scale_trans - - _bbox = TransformedBbox(bbox_inches, - tr) - x0, y0 = _bbox.x0, _bbox.y0 - fig.bbox_inches = Bbox.from_bounds(0, 0, - bbox_inches.width, - bbox_inches.height) - - x0, y0 = _bbox.x0, _bbox.y0 - w1, h1 = fig.bbox.width, fig.bbox.height - self.figure.transFigure._boxout = Bbox.from_bounds(-x0, -y0, - w1, h1) - self.figure.transFigure.invalidate() - - fig.bbox = TransformedBbox(fig.bbox_inches, tr) - - fig.patch.set_bounds(x0/w1, y0/h1, - fig.bbox.width/w1, fig.bbox.height/h1) - - - def _adjust_bbox_pdf(self, fig, bbox_inches): - """ - _adjust_bbox for pdf & eps format - """ - - tr = Affine2D().scale(72) - - _bbox = TransformedBbox(bbox_inches, tr) - - fig.bbox_inches = Bbox.from_bounds(0, 0, - bbox_inches.width, - bbox_inches.height) - x0, y0 = _bbox.x0, _bbox.y0 - f = 72. / fig.dpi - w1, h1 = fig.bbox.width*f, fig.bbox.height*f - self.figure.transFigure._boxout = Bbox.from_bounds(-x0, -y0, - w1, h1) - self.figure.transFigure.invalidate() - - fig.bbox = TransformedBbox(fig.bbox_inches, tr) - - fig.patch.set_bounds(x0/w1, y0/h1, - fig.bbox.width/w1, fig.bbox.height/h1) - - def get_default_filetype(self): raise NotImplementedError Modified: trunk/matplotlib/lib/matplotlib/backends/backend_mixed.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_mixed.py 2009年04月15日 17:52:23 UTC (rev 7043) +++ trunk/matplotlib/lib/matplotlib/backends/backend_mixed.py 2009年04月16日 17:28:41 UTC (rev 7044) @@ -1,5 +1,6 @@ from matplotlib._image import frombuffer from matplotlib.backends.backend_agg import RendererAgg +from matplotlib.tight_bbox import process_figure_for_rasterizing class MixedModeRenderer(object): """ @@ -9,8 +10,12 @@ complex objects, such as quad meshes, are rasterised and then output as images. """ - def __init__(self, width, height, dpi, vector_renderer, raster_renderer_class=None): + def __init__(self, figure, width, height, dpi, vector_renderer, + raster_renderer_class=None, + bbox_inches_restore=None): """ + figure: The figure instance. + width: The width of the canvas in logical units height: The height of the canvas in logical units @@ -38,6 +43,13 @@ self._raster_renderer = None self._rasterizing = 0 + # A renference to the figure is needed as we need to change + # the figure dpi before and after the rasterization. Although + # this looks ugly, I couldn't find a better solution. -JJL + self.figure=figure + + self._bbox_inches_restore = bbox_inches_restore + self._set_current_renderer(vector_renderer) _methods = """ @@ -56,6 +68,7 @@ renderer.start_rasterizing = self.start_rasterizing renderer.stop_rasterizing = self.stop_rasterizing + def start_rasterizing(self): """ Enter "raster" mode. All subsequent drawing commands (until @@ -65,12 +78,25 @@ If start_rasterizing is called multiple times before stop_rasterizing is called, this method has no effect. """ + + # change the dpi of the figure temporarily. + self.figure.set_dpi(self.dpi) + + if self._bbox_inches_restore: # when tight bbox is used + r = process_figure_for_rasterizing(self.figure, + self._bbox_inches_restore, + mode="png") + + self._bbox_inches_restore = r + + if self._rasterizing == 0: self._raster_renderer = self._raster_renderer_class( self._width*self.dpi, self._height*self.dpi, self.dpi) self._set_current_renderer(self._raster_renderer) self._rasterizing += 1 + def stop_rasterizing(self): """ Exit "raster" mode. All of the drawing that was done since @@ -91,6 +117,17 @@ image = frombuffer(buffer, w, h, True) image.is_grayscale = False image.flipud_out() - self._renderer.draw_image(l, height - b - h, image, None) + self._renderer.draw_image(int(float(l)/self.dpi*72.), + int((float(height) - b - h)/self.dpi*72.), + image, None) self._raster_renderer = None self._rasterizing = False + + # restore the figure dpi. + self.figure.set_dpi(72) + + if self._bbox_inches_restore: # when tight bbox is used + r = process_figure_for_rasterizing(self.figure, + self._bbox_inches_restore, + mode="pdf") + self._bbox_inches_restore = r Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2009年04月15日 17:52:23 UTC (rev 7043) +++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2009年04月16日 17:28:41 UTC (rev 7044) @@ -1990,8 +1990,10 @@ else: file = PdfFile(filename) file.newPage(width, height) - renderer = MixedModeRenderer( - width, height, 72, RendererPdf(file, image_dpi)) + _bbox_inches_restore = kwargs.pop("bbox_inches_restore", None) + renderer = MixedModeRenderer(self.figure, + width, height, image_dpi, RendererPdf(file, image_dpi), + bbox_inches_restore=_bbox_inches_restore) self.figure.draw(renderer) renderer.finalize() if isinstance(filename, PdfPages): # finish off this page Modified: trunk/matplotlib/lib/matplotlib/backends/backend_svg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_svg.py 2009年04月15日 17:52:23 UTC (rev 7043) +++ trunk/matplotlib/lib/matplotlib/backends/backend_svg.py 2009年04月16日 17:28:41 UTC (rev 7044) @@ -612,7 +612,7 @@ fh_to_close = None else: raise ValueError("filename must be a path or a file-like object") - return self._print_svg(filename, svgwriter, fh_to_close) + return self._print_svg(filename, svgwriter, fh_to_close, **kwargs) def print_svgz(self, filename, *args, **kwargs): if is_string_like(filename): @@ -625,7 +625,7 @@ raise ValueError("filename must be a path or a file-like object") return self._print_svg(filename, svgwriter, fh_to_close) - def _print_svg(self, filename, svgwriter, fh_to_close=None): + def _print_svg(self, filename, svgwriter, fh_to_close=None, **kwargs): self.figure.set_dpi(72.0) width, height = self.figure.get_size_inches() w, h = width*72, height*72 @@ -633,8 +633,20 @@ if rcParams['svg.image_noscale']: renderer = RendererSVG(w, h, svgwriter, filename) else: - renderer = MixedModeRenderer( - width, height, 72.0, RendererSVG(w, h, svgwriter, filename)) + # setting mixed renderer dpi other than 72 results in + # incorrect size of the rasterized image. It seems that the + # svg internally uses fixed dpi of 72 and seems to cause + # the problem. I hope someone who knows the svg backends + # take a look at this problem. Meanwhile, the dpi + # parameter is ignored and image_dpi is fixed at 72. - JJL + + #image_dpi = kwargs.pop("dpi", 72) + image_dpi = 72 + _bbox_inches_restore = kwargs.pop("bbox_inches_restore", None) + renderer = MixedModeRenderer(self.figure, + width, height, image_dpi, RendererSVG(w, h, svgwriter, filename), + bbox_inches_restore=_bbox_inches_restore) + self.figure.draw(renderer) renderer.finalize() if fh_to_close is not None: Added: trunk/matplotlib/lib/matplotlib/tight_bbox.py =================================================================== --- trunk/matplotlib/lib/matplotlib/tight_bbox.py (rev 0) +++ trunk/matplotlib/lib/matplotlib/tight_bbox.py 2009年04月16日 17:28:41 UTC (rev 7044) @@ -0,0 +1,127 @@ +""" +This module is to support *bbox_inches* option in savefig command. +""" + +import warnings +from matplotlib.transforms import Bbox, TransformedBbox, Affine2D + + +def adjust_bbox(fig, format, bbox_inches): + """ + Temporarily adjust the figure so that only the specified area + (bbox_inches) is saved. + + It modifies fig.bbox, fig.bbox_inches, + fig.transFigure._boxout, and fig.patch. While the figure size + changes, the scale of the original figure is conserved. A + function whitch restores the original values are returned. + """ + + origBbox = fig.bbox + origBboxInches = fig.bbox_inches + _boxout = fig.transFigure._boxout + + asp_list = [] + locator_list = [] + for ax in fig.axes: + pos = ax.get_position(original=False).frozen() + locator_list.append(ax.get_axes_locator()) + asp_list.append(ax.get_aspect()) + + def _l(a, r, pos=pos): return pos + ax.set_axes_locator(_l) + ax.set_aspect("auto") + + + + def restore_bbox(): + + for ax, asp, loc in zip(fig.axes, asp_list, locator_list): + ax.set_aspect(asp) + ax.set_axes_locator(loc) + + fig.bbox = origBbox + fig.bbox_inches = origBboxInches + fig.transFigure._boxout = _boxout + fig.transFigure.invalidate() + fig.patch.set_bounds(0, 0, 1, 1) + + if format in ["png", "raw", "rgba"]: + adjust_bbox_png(fig, bbox_inches) + return restore_bbox + elif format in ["pdf", "eps", "svg", "svgz"]: + adjust_bbox_pdf(fig, bbox_inches) + return restore_bbox + else: + warnings.warn("bbox_inches option for %s backend is not implemented yet." % (format)) + return None + + +def adjust_bbox_png(fig, bbox_inches): + """ + adjust_bbox for png (Agg) format + """ + + tr = fig.dpi_scale_trans + + _bbox = TransformedBbox(bbox_inches, + tr) + x0, y0 = _bbox.x0, _bbox.y0 + fig.bbox_inches = Bbox.from_bounds(0, 0, + bbox_inches.width, + bbox_inches.height) + + x0, y0 = _bbox.x0, _bbox.y0 + w1, h1 = fig.bbox.width, fig.bbox.height + fig.transFigure._boxout = Bbox.from_bounds(-x0, -y0, + w1, h1) + fig.transFigure.invalidate() + + fig.bbox = TransformedBbox(fig.bbox_inches, tr) + + fig.patch.set_bounds(x0/w1, y0/h1, + fig.bbox.width/w1, fig.bbox.height/h1) + + +def adjust_bbox_pdf(fig, bbox_inches): + """ + adjust_bbox for pdf & eps format + """ + + tr = Affine2D().scale(72) + + _bbox = TransformedBbox(bbox_inches, tr) + + fig.bbox_inches = Bbox.from_bounds(0, 0, + bbox_inches.width, + bbox_inches.height) + x0, y0 = _bbox.x0, _bbox.y0 + f = 72. / fig.dpi + w1, h1 = fig.bbox.width*f, fig.bbox.height*f + fig.transFigure._boxout = Bbox.from_bounds(-x0, -y0, + w1, h1) + fig.transFigure.invalidate() + + fig.bbox = TransformedBbox(fig.bbox_inches, tr) + + fig.patch.set_bounds(x0/w1, y0/h1, + fig.bbox.width/w1, fig.bbox.height/h1) + + +def process_figure_for_rasterizing(figure, + bbox_inches_restore, mode): + + """ + This need to be called when figure dpi changes during the drawing + (e.g., rasterizing). It recovers the bbox and re-adjust it with + the new dpi. + """ + + bbox_inches, restore_bbox = bbox_inches_restore + restore_bbox() + r = adjust_bbox(figure, mode, + bbox_inches) + + return bbox_inches, r + + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7043 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7043&view=rev Author: jdh2358 Date: 2009年04月15日 17:52:23 +0000 (2009年4月15日) Log Message: ----------- Merged revisions 7042 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r7042 | jdh2358 | 2009年04月15日 10:47:18 -0700 (2009年4月15日) | 1 line fix for tkagg filextension bug reported by fperez ........ Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py Property Changed: ---------------- trunk/matplotlib/ trunk/matplotlib/doc/pyplots/README trunk/matplotlib/doc/sphinxext/gen_gallery.py trunk/matplotlib/doc/sphinxext/gen_rst.py trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7039 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7042 Modified: svn:mergeinfo - /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035 + /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042 Property changes on: trunk/matplotlib/doc/pyplots/README ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035 + /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042 Property changes on: trunk/matplotlib/doc/sphinxext/gen_gallery.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035 + /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042 Property changes on: trunk/matplotlib/doc/sphinxext/gen_rst.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035 + /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042 Modified: trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py 2009年04月15日 17:47:18 UTC (rev 7042) +++ trunk/matplotlib/lib/matplotlib/backends/backend_tkagg.py 2009年04月15日 17:52:23 UTC (rev 7043) @@ -708,11 +708,17 @@ tk_filetypes = [ (name, '*.%s' % ext) for (ext, name) in sorted_filetypes] + # adding a default extension seems to break the + # asksaveasfilename dialog when you choose various save types + # from the dropdown. Passing in the empty string seems to + # work - JDH + #defaultextension = self.canvas.get_default_filetype() + defaultextension = '' fname = asksaveasfilename( master=self.window, title='Save the figure', filetypes = tk_filetypes, - defaultextension = self.canvas.get_default_filetype() + defaultextension = defaultextension ) if fname == "" or fname == (): Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/mathmpl.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/mathmpl.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035 + /branches/v0_91_maint/doc/sphinxext/mathmpl.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/mathmpl.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042 Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/only_directives.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/only_directives.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035 + /branches/v0_91_maint/doc/sphinxext/only_directives.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/only_directives.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042 Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/plot_directive.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py:6920-6925,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035 + /branches/v0_91_maint/doc/sphinxext/plot_directive.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py:6920-6925,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035,7042 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7042 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7042&view=rev Author: jdh2358 Date: 2009年04月15日 17:47:18 +0000 (2009年4月15日) Log Message: ----------- fix for tkagg filextension bug reported by fperez Modified Paths: -------------- branches/v0_98_5_maint/lib/matplotlib/backends/backend_tkagg.py Modified: branches/v0_98_5_maint/lib/matplotlib/backends/backend_tkagg.py =================================================================== --- branches/v0_98_5_maint/lib/matplotlib/backends/backend_tkagg.py 2009年04月14日 14:29:31 UTC (rev 7041) +++ branches/v0_98_5_maint/lib/matplotlib/backends/backend_tkagg.py 2009年04月15日 17:47:18 UTC (rev 7042) @@ -708,11 +708,17 @@ tk_filetypes = [ (name, '*.%s' % ext) for (ext, name) in sorted_filetypes] + # adding a default extension seems to break the + # asksaveasfilename dialog when you choose various save types + # from the dropdown. Passing in the empty string seems to + # work - JDH + #defaultextension = self.canvas.get_default_filetype() + defaultextension = '' fname = asksaveasfilename( master=self.window, title='Save the figure', filetypes = tk_filetypes, - defaultextension = self.canvas.get_default_filetype() + defaultextension = defaultextension ) if fname == "" or fname == (): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7041 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7041&view=rev Author: jdh2358 Date: 2009年04月14日 14:29:31 +0000 (2009年4月14日) Log Message: ----------- added mpl_toolkits.mplot3d Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/doc/users/credits.rst trunk/matplotlib/doc/users/toolkits.rst trunk/matplotlib/examples/pylab_examples/finance_work2.py trunk/matplotlib/examples/tests/backend_driver.py trunk/matplotlib/setup.py Added Paths: ----------- trunk/matplotlib/examples/mplot3d/ trunk/matplotlib/examples/mplot3d/demo.py trunk/matplotlib/lib/mpl_toolkits/mplot3d/ trunk/matplotlib/lib/mpl_toolkits/mplot3d/__init__.py trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py trunk/matplotlib/lib/mpl_toolkits/mplot3d/axis3d.py trunk/matplotlib/lib/mpl_toolkits/mplot3d/proj3d.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009年04月13日 03:02:41 UTC (rev 7040) +++ trunk/matplotlib/CHANGELOG 2009年04月14日 14:29:31 UTC (rev 7041) @@ -1,6 +1,11 @@ ====================================================================== -2008年04月12日 Release 0.98.5.3 at r7038 +2008年04月14日 Added Jonathan Taylor's Reinier Heeres' port of John + Porters' mplot3d to svn trunk. Package in + mpl_toolkits.mplot3d and demo is examples/mplot3d/demo.py. + Thanks Reiner + + 2009年04月06日 The pdf backend now escapes newlines and linefeeds in strings. Fixes sf bug #2708559; thanks to Tiago Pereira for the report. Modified: trunk/matplotlib/doc/users/credits.rst =================================================================== --- trunk/matplotlib/doc/users/credits.rst 2009年04月13日 03:02:41 UTC (rev 7040) +++ trunk/matplotlib/doc/users/credits.rst 2009年04月14日 14:29:31 UTC (rev 7041) @@ -166,4 +166,9 @@ base. He also rewrote the transformation infrastructure to support custom projections and scales. +John Porter, Jonathon Taylor and Reinier Heeres + John Porter wrote the mplot3d module for basic 3D plotting in + matplotlib, and Jonathon Taylor and Reinier Heeres ported it to the + refactored transform trunk. + Modified: trunk/matplotlib/doc/users/toolkits.rst =================================================================== --- trunk/matplotlib/doc/users/toolkits.rst 2009年04月13日 03:02:41 UTC (rev 7040) +++ trunk/matplotlib/doc/users/toolkits.rst 2009年04月14日 14:29:31 UTC (rev 7041) @@ -37,10 +37,19 @@ Natgrid ======== - + mpl_toolkits.natgrid is an interface to natgrid C library for gridding irregularly spaced data. This requires a separate installation of the natgrid toolkit from the sourceforge `download <http://sourceforge.net/project/showfiles.php?group_id=80706&package_id=142792>`_ page. - + +.. _toolkit_mplot3d: + +mplot3d +=========== + +mpl_toolkits.mplot3d provides some basic 3D plotting (scatter, surf, +line, mesh) tools. Not the fastest or feature complete 3D library out +there, but ships with matplotlib and thus may be a lighter weight +solution for some use cases. Added: trunk/matplotlib/examples/mplot3d/demo.py =================================================================== --- trunk/matplotlib/examples/mplot3d/demo.py (rev 0) +++ trunk/matplotlib/examples/mplot3d/demo.py 2009年04月14日 14:29:31 UTC (rev 7041) @@ -0,0 +1,138 @@ +import random +import numpy as np +import matplotlib.pyplot as plt +import mpl_toolkits.mplot3d.axes3d as axes3d +from matplotlib.colors import Normalize, colorConverter + +def test_scatter(): + f = plt.figure() + ax = axes3d.Axes3D(f) + + n = 100 + for c,zl,zh in [('r',-50,-25),('b',-30,-5)]: + xs,ys,zs = zip(* + [(random.randrange(23,32), + random.randrange(100), + random.randrange(zl,zh) + ) for i in range(n)]) + ax.scatter3D(xs,ys,zs, c=c) + + ax.set_xlabel('------------ X Label --------------------') + ax.set_ylabel('------------ Y Label --------------------') + ax.set_zlabel('------------ Z Label --------------------') + +def test_wire(): + f = plt.figure() + ax = axes3d.Axes3D(f) + + X,Y,Z = axes3d.get_test_data(0.05) + ax.plot_wireframe(X,Y,Z, rstride=10,cstride=10) + ax.set_xlabel('X') + ax.set_ylabel('Y') + ax.set_zlabel('Z') + +def test_surface(): + f = plt.figure() + ax = axes3d.Axes3D(f) + + X,Y,Z = axes3d.get_test_data(0.05) + ax.plot_surface(X,Y,Z, rstride=10,cstride=10) + ax.set_xlabel('X') + ax.set_ylabel('Y') + ax.set_zlabel('Z') + +def test_contour(): + f = plt.figure() + ax = axes3d.Axes3D(f) + + X,Y,Z = axes3d.get_test_data(0.05) + cset = ax.contour3D(X,Y,Z) + ax.clabel(cset, fontsize=9, inline=1) + ax.set_xlabel('X') + ax.set_ylabel('Y') + ax.set_zlabel('Z') + +def test_contourf(): + f = plt.figure() + ax = axes3d.Axes3D(f) + + X,Y,Z = axes3d.get_test_data(0.05) + cset = ax.contourf3D(X,Y,Z) + ax.clabel(cset, fontsize=9, inline=1) + ax.set_xlabel('X') + ax.set_ylabel('Y') + ax.set_zlabel('Z') + +def test_plot(): + f = plt.figure() + ax = axes3d.Axes3D(f) + + xs = np.arange(0,4*np.pi+0.1,0.1) + ys = np.sin(xs) + ax.plot(xs,ys, label='zl') + ax.plot(xs,ys+max(xs),label='zh') + ax.plot(xs,ys,dir='x', label='xl') + ax.plot(xs,ys,dir='x', z=max(xs),label='xh') + ax.plot(xs,ys,dir='y', label='yl') + ax.plot(xs,ys,dir='y', z=max(xs), label='yh') + ax.set_xlabel('X') + ax.set_ylabel('Y') + ax.set_zlabel('Z') + ax.legend() + +def test_polys(): + f = plt.figure() + ax = axes3d.Axes3D(f) + + cc = lambda arg: colorConverter.to_rgba(arg, alpha=0.6) + + xs = np.arange(0,10,0.4) + verts = [] + zs = [0.0,1.0,2.0,3.0] + for z in zs: + ys = [random.random() for x in xs] + ys[0],ys[-1] = 0,0 + verts.append(zip(xs,ys)) + + from matplotlib.collections import PolyCollection + poly = PolyCollection(verts, facecolors = [cc('r'),cc('g'),cc('b'), + cc('y')]) + poly.set_alpha(0.7) + ax.add_collection(poly,zs=zs,dir='y') + + ax.set_xlim(0,10) + ax.set_ylim(-1,4) + ax.set_zlim(0,1) + +def test_scatter2D(): + f = plt.figure() + ax = axes3d.Axes3D(f) + + xs = [random.random() for i in range(20)] + ys = [random.random() for x in xs] + ax.scatter(xs, ys) + ax.scatter(xs, ys, dir='y', c='r') + ax.scatter(xs, ys, dir='x', c='g') + +def test_bar2D(): + f = plt.figure() + ax = axes3d.Axes3D(f) + + for c,z in zip(['r','g','b', 'y'],[30,20,10,0]): + xs = np.arange(20) + ys = [random.random() for x in xs] + ax.bar(xs, ys, z=z, dir='y', color=c, alpha=0.8) + +if __name__ == "__main__": + + test_scatter() + test_wire() + test_surface() + test_contour() + test_contourf() + test_plot() + test_polys() + test_scatter2D() +# test_bar2D() + + plt.show() Modified: trunk/matplotlib/examples/pylab_examples/finance_work2.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/finance_work2.py 2009年04月13日 03:02:41 UTC (rev 7040) +++ trunk/matplotlib/examples/pylab_examples/finance_work2.py 2009年04月14日 14:29:31 UTC (rev 7041) @@ -216,10 +216,21 @@ +class MyLocator(mticker.MaxNLocator): + def __init__(self, *args, **kwargs): + mticker.MaxNLocator.__init__(self, *args, **kwargs) + + def __call__(self, *args, **kwargs): + return mticker.MaxNLocator.__call__(self, *args, **kwargs) + # at most 5 ticks, pruning the upper and lower so they don't overlap # with other ticks -ax2.yaxis.set_major_locator(mticker.MaxNLocator(5, prune='both')) -ax3.yaxis.set_major_locator(mticker.MaxNLocator(5, prune='both')) +#ax2.yaxis.set_major_locator(mticker.MaxNLocator(5, prune='both')) +#ax3.yaxis.set_major_locator(mticker.MaxNLocator(5, prune='both')) + +ax2.yaxis.set_major_locator(MyLocator(5, prune='both')) +ax3.yaxis.set_major_locator(MyLocator(5, prune='both')) + plt.show() Modified: trunk/matplotlib/examples/tests/backend_driver.py =================================================================== --- trunk/matplotlib/examples/tests/backend_driver.py 2009年04月13日 03:02:41 UTC (rev 7040) +++ trunk/matplotlib/examples/tests/backend_driver.py 2009年04月14日 14:29:31 UTC (rev 7041) @@ -240,6 +240,11 @@ ] +mplot3d_dir = os.path.join('..', 'mplot3d') +mplot3d_files = [ + 'demo.py', + ] + # dict from dir to files we know we don't want to test (eg examples # not using pyplot, examples requiring user input, animation examples, # examples that may only work in certain environs (usetex examples?), @@ -271,7 +276,8 @@ files = ( [os.path.join(api_dir, fname) for fname in api_files] + [os.path.join(pylab_dir, fname) for fname in pylab_files] + - [os.path.join(units_dir, fname) for fname in units_files] + [os.path.join(units_dir, fname) for fname in units_files] + + [os.path.join(mplot3d_dir, fname) for fname in mplot3d_files] ) # tests known to fail on a given backend Added: trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/mplot3d/art3d.py 2009年04月14日 14:29:31 UTC (rev 7041) @@ -0,0 +1,269 @@ +#!/usr/bin/python +# art3d.py, original mplot3d version by John Porter +# Parts rewritten by Reinier Heeres <re...@he...> + +from matplotlib import lines, text, path as mpath +from matplotlib.collections import Collection, LineCollection, \ + PolyCollection, PatchCollection +from matplotlib.patches import Patch, Rectangle +from matplotlib.colors import Normalize +from matplotlib import transforms + +import types +import numpy as np +import proj3d + +class Text3D(text.Text): + + def __init__(self, x=0, y=0, z=0, text='', dir='z'): + text.Text.__init__(self, x, y, text) + self.set_3d_properties(z, dir) + + def set_3d_properties(self, z=0, dir='z'): + x, y = self.get_position() + self._position3d = juggle_axes(x, y, z, dir) + + def draw(self, renderer): + x, y, z = self._position3d + x, y, z = proj3d.proj_transform(x, y, z, renderer.M) + self.set_position(x, y) + text.Text.draw(self, renderer) + +def text_2d_to_3d(obj, z=0, dir='z'): + """Convert a Text to a Text3D object.""" + obj.__class__ = Text3D + obj.set_3d_properties(z, dir) + +class Line3D(lines.Line2D): + + def __init__(self, xs, ys, zs, *args, **kwargs): + lines.Line2D.__init__(self, [], [], *args, **kwargs) + self._verts3d = xs, ys, zs + + def set_3d_properties(self, zs=0, dir='z'): + xs = self.get_xdata() + ys = self.get_ydata() + try: + zs = float(zs) + zs = [zs for x in xs] + except: + pass + self._verts3d = juggle_axes(xs, ys, zs, dir) + + def draw(self, renderer): + xs3d, ys3d, zs3d = self._verts3d + xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, renderer.M) + self.set_data(xs, ys) + lines.Line2D.draw(self, renderer) + +def line_2d_to_3d(line, z=0, dir='z'): + line.__class__ = Line3D + line.set_3d_properties(z, dir) + +def path_to_3d_segment(path, z=0, dir='z'): + '''Convert a path to a 3d segment.''' + seg = [] + for (pathseg, code) in path.iter_segments(): + seg.append(pathseg) + seg3d = [juggle_axes(x, y, z, dir) for (x, y) in seg] + return seg3d + +def paths_to_3d_segments(paths, zs=0, dir='z'): + '''Convert paths from a collection object to 3d segments.''' + + try: + zs = float(zs) + zs = [zs for i in range(len(paths))] + except: + pass + + segments = [] + for path, z in zip(paths, zs): + segments.append(path_to_3d_segment(path, z, dir)) + return segments + +class Line3DCollection(LineCollection): + + def __init__(self, segments, *args, **kwargs): + LineCollection.__init__(self, segments, *args, **kwargs) + + def set_segments(self, segments): + self._segments3d = segments + LineCollection.set_segments(self, []) + + def draw(self, renderer): + xyslist = [ + proj3d.proj_trans_points(points, renderer.M) for points in + self._segments3d] + segments_2d = [zip(xs,ys) for (xs,ys,zs) in xyslist] + LineCollection.set_segments(self, segments_2d) + LineCollection.draw(self, renderer) + +def line_collection_2d_to_3d(col, z=0, dir='z'): + """Convert a LineCollection to a Line3DCollection object.""" + segments3d = paths_to_3d_segments(col.get_paths(), z, dir) + col.__class__ = Line3DCollection + col.set_segments(segments3d) + +class Patch3D(Patch): + + def __init__(self, *args, **kwargs): + zs = kwargs.pop('zs', []) + dir = kwargs.pop('dir', 'z') + Patch.__init__(self, *args, **kwargs) + self.set_3d_properties(zs, dir) + + def set_3d_properties(self, verts, z=0, dir='z'): + self._segment3d = [juggle_axes(x, y, z, dir) for (x, y) in verts] + self._facecolor3d = Patch.get_facecolor(self) + + def get_path(self): + return self._path2d + + def get_facecolor(self): + return self._facecolor2d + + def draw(self, renderer): + s = self._segment3d + xs, ys, zs = zip(*s) + vxs,vys,vzs,vis = proj3d.proj_transform_clip(xs,ys,zs, renderer.M) + self._path2d = mpath.Path(zip(vxs, vys)) + # FIXME: coloring + self._facecolor2d = self._facecolor3d + Patch.draw(self, renderer) + +def patch_2d_to_3d(patch, z=0, dir='z'): + """Convert a Patch to a Patch3D object.""" + verts = patch.get_verts() + patch.__class__ = Patch3D + patch.set_3d_properties(verts, z, dir) + +class Patch3DCollection(PatchCollection): + + def __init__(self, *args, **kwargs): + PatchCollection.__init__(self, *args, **kwargs) + + def set_3d_properties(self, zs, dir): + xs, ys = zip(*self.get_offsets()) + self._offsets3d = juggle_axes(xs, ys, zs, dir) + self._facecolor3d = self.get_facecolor() + self._edgecolor3d = self.get_edgecolor() + + def draw(self, renderer): + xs,ys,zs = self._offsets3d + vxs,vys,vzs,vis = proj3d.proj_transform_clip(xs,ys,zs, renderer.M) + #FIXME: mpl allows us no way to unset the collection alpha value + self._alpha = None + self.set_facecolors(zalpha(self._facecolor3d, vzs)) + self.set_edgecolors(zalpha(self._edgecolor3d, vzs)) + PatchCollection.set_offsets(self, zip(vxs, vys)) + PatchCollection.draw(self, renderer) + +def patch_collection_2d_to_3d(col, zs=0, dir='z'): + """Convert a PatchCollection to a Patch3DCollection object.""" + col.__class__ = Patch3DCollection + col.set_3d_properties(zs, dir) + +class Poly3DCollection(PolyCollection): + + def __init__(self, verts, *args, **kwargs): + PolyCollection.__init__(self, verts, *args, **kwargs) + self.set_3d_properties() + + def get_vector(self, segments3d): + """optimise points for projection""" + si = 0 + ei = 0 + segis = [] + points = [] + for p in segments3d: + points.extend(p) + ei = si+len(p) + segis.append((si,ei)) + si = ei + xs,ys,zs = zip(*points) + ones = np.ones(len(xs)) + self._vec = np.array([xs,ys,zs,ones]) + self._segis = segis + + def set_verts(self, verts, closed=True): + self.get_vector(verts) + # 2D verts will be updated at draw time + PolyCollection.set_verts(self, [], closed) + + def set_3d_properties(self): + self._zsort = 1 + self._facecolors3d = PolyCollection.get_facecolors(self) + self._edgecolors3d = self.get_edgecolors() + + def get_facecolors(self): + return self._facecolors2d + get_facecolor = get_facecolors + + def draw(self, renderer): + txs, tys, tzs, tis = proj3d.proj_transform_vec_clip(self._vec, renderer.M) + xyslist = [(txs[si:ei], tys[si:ei], tzs[si:ei], tis[si:ei]) \ + for si, ei in self._segis] + colors = self._facecolors3d + # + # if required sort by depth (furthest drawn first) + if self._zsort: + z_segments_2d = [(min(zs),max(tis),zip(xs,ys),c) for + (xs,ys,zs,tis),c in zip(xyslist,colors)] + z_segments_2d.sort() + z_segments_2d.reverse() + else: + raise ValueError, "whoops" + segments_2d = [s for z,i,s,c in z_segments_2d if i] + colors = [c for z,i,s,c in z_segments_2d if i] + PolyCollection.set_verts(self, segments_2d) + self._facecolors2d = colors + return Collection.draw(self, renderer) + +def poly_collection_2d_to_3d(col, zs=None, dir='z'): + """Convert a PolyCollection to a Poly3DCollection object.""" + segments_3d = paths_to_3d_segments(col.get_paths(), zs, dir) + col.__class__ = Poly3DCollection + col.set_verts(segments_3d) + col.set_3d_properties() + +def juggle_axes(xs,ys,zs, dir): + """ + Depending on the direction of the plot re-order the axis. + This is so that 2d plots can be plotted along any direction. + """ + if dir == 'x': return zs,xs,ys + elif dir == 'y': return xs,zs,ys + else: return xs,ys,zs + +def iscolor(c): + try: + return (len(c) == 4 or len(c) == 3) and hasattr(c[0], '__float__') + except (IndexError): + return False + +def get_colors(c, num): + """Stretch the color argument to provide the required number num""" + + if type(c)==type("string"): + c = colors.colorConverter.to_rgba(colors) + + if iscolor(c): + return [c] * num + if len(c) == num: + return c + elif iscolor(c): + return [c] * num + elif iscolor(c[0]): + return [c[0]] * num + else: + raise ValueError, 'unknown color format %s' % c + +def zalpha(colors, zs): + """Modify the alphas of the color list according to depth""" + colors = get_colors(colors,len(zs)) + norm = Normalize(min(zs),max(zs)) + sats = 1 - norm(zs)*0.7 + colors = [(c[0],c[1],c[2],c[3]*s) for c,s in zip(colors,sats)] + return colors + Added: trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/mplot3d/axes3d.py 2009年04月14日 14:29:31 UTC (rev 7041) @@ -0,0 +1,868 @@ +#!/usr/bin/python +# axes3d.py, original mplot3d version by John Porter +# Created: 23 Sep 2005 +# Parts fixed by Reinier Heeres <re...@he...> + +""" +3D projection glued onto 2D Axes. + +Axes3D +""" + +from matplotlib import pyplot as plt +import random + +from matplotlib.axes import Axes +from matplotlib import cbook +from matplotlib.transforms import Bbox +import numpy as np +from matplotlib.colors import Normalize, colorConverter + +import art3d +import proj3d +import axis3d + +def sensible_format_data(self, value): + """Used to generate more comprehensible numbers in status bar""" + if abs(value) > 1e4 or abs(value)<1e-3: + s = '%1.4e'% value + return self._formatSciNotation(s) + else: + return '%4.3f' % value + +def unit_bbox(): + box = Bbox(np.array([[0,0],[1,1]])) + return box + +class Axes3DI(Axes): + """Wrap an Axes object + + The x,y data coordinates, which are manipulated by set_xlim and + set_ylim are used as the target view coordinates by the 3D + transformations. These coordinates are mostly invisible to the + outside world. + + set_w_xlim, set_w_ylim and set_w_zlim manipulate the 3D world + coordinates which are scaled to represent the data and are stored + in the xy_dataLim, zz_datalim bboxes. + + The axes representing the x,y,z world dimensions are self.w_xaxis, + self.w_yaxis and self.w_zaxis. They can probably be controlled in + more or less the normal ways. + """ + def __init__(self, fig, rect=[0.0, 0.0, 1.0, 1.0], *args, **kwargs): + self.fig = fig + self.cids = [] + + azim = kwargs.pop('azim', -60) + elev = kwargs.pop('elev', 30) + + self.xy_viewLim = unit_bbox() + self.zz_viewLim = unit_bbox() + self.xy_dataLim = unit_bbox() + self.zz_dataLim = unit_bbox() + # inihibit autoscale_view until the axises are defined + # they can't be defined until Axes.__init__ has been called + self.view_init(elev, azim) + self._ready = 0 + Axes.__init__(self, self.fig, rect, + frameon=True, + xticks=[], yticks=[], *args, **kwargs) + + self.M = None + + self._ready = 1 + self.mouse_init() + self.create_axes() + self.set_top_view() + + self.axesPatch.set_linewidth(0) + self.fig.add_axes(self) + + def set_top_view(self): + # this happens to be the right view for the viewing coordinates + # moved up and to the left slightly to fit labels and axes + xdwl = (0.95/self.dist) + xdw = (0.9/self.dist) + ydwl = (0.95/self.dist) + ydw = (0.9/self.dist) + # + self.set_xlim(-xdwl,xdw) + self.set_ylim(-ydwl,ydw) + + def really_set_xlim(self, vmin, vmax): + self.viewLim.intervalx().set_bounds(vmin, vmax) + + def really_set_ylim(self, vmin, vmax): + self.viewLim.intervaly().set_bounds(vmin, vmax) + + def vlim_argument(self, get_lim, *args): + if not args: + vmin,vmax = get_lim() + elif len(args)==2: + vmin,vmax = args + elif len(args)==1: + vmin,vmax = args[0] + return vmin,vmax + + def nset_xlim(self, *args): + raise + vmin,vmax = self.vlim_argument(self.get_xlim) + print 'xlim', vmin,vmax + + def nset_ylim(self, *args): + vmin,vmax = self.vlim_argument(self.get_ylim) + print 'ylim', vmin,vmax + + def create_axes(self): + self.w_xaxis = axis3d.XAxis('x',self.xy_viewLim.intervalx, + self.xy_dataLim.intervalx, self) + self.w_yaxis = axis3d.YAxis('y',self.xy_viewLim.intervaly, + self.xy_dataLim.intervaly, self) + self.w_zaxis = axis3d.ZAxis('z',self.zz_viewLim.intervalx, + self.zz_dataLim.intervalx, self) + + def unit_cube(self,vals=None): + minx,maxx,miny,maxy,minz,maxz = vals or self.get_w_lims() + xs,ys,zs = ([minx,maxx,maxx,minx,minx,maxx,maxx,minx], + [miny,miny,maxy,maxy,miny,miny,maxy,maxy], + [minz,minz,minz,minz,maxz,maxz,maxz,maxz]) + return zip(xs,ys,zs) + + def tunit_cube(self,vals=None,M=None): + if M is None: + M = self.M + xyzs = self.unit_cube(vals) + tcube = proj3d.proj_points(xyzs,M) + return tcube + + def tunit_edges(self, vals=None,M=None): + tc = self.tunit_cube(vals,M) + edges = [(tc[0],tc[1]), + (tc[1],tc[2]), + (tc[2],tc[3]), + (tc[3],tc[0]), + + (tc[0],tc[4]), + (tc[1],tc[5]), + (tc[2],tc[6]), + (tc[3],tc[7]), + + (tc[4],tc[5]), + (tc[5],tc[6]), + (tc[6],tc[7]), + (tc[7],tc[4])] + return edges + + def draw(self, renderer): + # draw the background patch + self.axesPatch.draw(renderer) + self._frameon = False + + # add the projection matrix to the renderer + self.M = self.get_proj() + renderer.M = self.M + renderer.vvec = self.vvec + renderer.eye = self.eye + renderer.get_axis_position = self.get_axis_position + + self.w_xaxis.draw(renderer) + self.w_yaxis.draw(renderer) + self.w_zaxis.draw(renderer) + Axes.draw(self, renderer) + + def get_axis_position(self): + vals = self.get_w_lims() + tc = self.tunit_cube(vals,self.M) + xhigh = tc[1][2]>tc[2][2] + yhigh = tc[3][2]>tc[2][2] + zhigh = tc[0][2]>tc[2][2] + return xhigh,yhigh,zhigh + + def update_datalim(self, xys): + pass + + def update_datalim_numerix(self, x, y): + pass + + def auto_scale_xyz(self, X,Y,Z=None,had_data=None): + x,y,z = map(np.asarray, (X,Y,Z)) + try: + x,y = x.flatten(),y.flatten() + if Z is not None: + z = z.flatten() + except AttributeError: + raise + + # This updates the bounding boxes as to keep a record as + # to what the minimum sized rectangular volume holds the + # data. + self.xy_dataLim.update_from_data_xy(np.array([x, y]).T, not had_data) + if z is not None: + self.zz_dataLim.update_from_data_xy(np.array([z, z]).T, not had_data) + + # Let autoscale_view figure out how to use this data. + self.autoscale_view() + + def autoscale_view(self, scalex=True, scaley=True, scalez=True): + # This method looks at the rectanglular volume (see above) + # of data and decides how to scale the view portal to fit it. + + self.set_top_view() + if not self._ready: return + + if not self.get_autoscale_on(): return + if scalex: + self.set_w_xlim(self.xy_dataLim.intervalx) + if scaley: + self.set_w_ylim(self.xy_dataLim.intervaly) + if scalez: + self.set_w_zlim(self.zz_dataLim.intervalx) + + def get_w_lims(self): + '''Get 3d world limits.''' + minpy,maxx = self.get_w_xlim() + miny,maxy = self.get_w_ylim() + minz,maxz = self.get_w_zlim() + return minpy,maxx,miny,maxy,minz,maxz + + def _determine_lims(self, xmin=None, xmax=None, *args, **kwargs): + if xmax is None and cbook.iterable(xmin): + xmin, xmax = xmin + return (xmin, xmax) + + def set_w_zlim(self, *args, **kwargs): + '''Set 3d z limits.''' + lims = self._determine_lims(*args, **kwargs) + self.zz_viewLim.intervalx = lims + return lims + + def set_w_xlim(self, *args, **kwargs): + '''Set 3d x limits.''' + lims = self._determine_lims(*args, **kwargs) + self.xy_viewLim.intervalx = lims + return lims + + def set_w_ylim(self, *args, **kwargs): + '''Set 3d y limits.''' + lims = self._determine_lims(*args, **kwargs) + self.xy_viewLim.intervaly = lims + return lims + + def get_w_zlim(self): + return self.zz_viewLim.intervalx + + def get_w_xlim(self): + return self.xy_viewLim.intervalx + + def get_w_ylim(self): + return self.xy_viewLim.intervaly + + def pany(self, numsteps): + print 'numsteps', numsteps + + def panpy(self, numsteps): + print 'numsteps', numsteps + + def view_init(self, elev, azim): + self.dist = 10 + self.elev = elev + self.azim = azim + + def get_proj(self): + """Create the projection matrix from the current viewing + position. + + elev stores the elevation angle in the z plane + azim stores the azimuth angle in the x,y plane + + dist is the distance of the eye viewing point from the object + point. + + """ + relev,razim = np.pi * self.elev/180, np.pi * self.azim/180 + + xmin,xmax = self.get_w_xlim() + ymin,ymax = self.get_w_ylim() + zmin,zmax = self.get_w_zlim() + + # transform to uniform world coordinates 0-1.0,0-1.0,0-1.0 + worldM = proj3d.world_transformation(xmin,xmax, + ymin,ymax, + zmin,zmax) + + # look into the middle of the new coordinates + R = np.array([0.5,0.5,0.5]) + # + xp = R[0] + np.cos(razim)*np.cos(relev)*self.dist + yp = R[1] + np.sin(razim)*np.cos(relev)*self.dist + zp = R[2] + np.sin(relev)*self.dist + E = np.array((xp, yp, zp)) + # + self.eye = E + self.vvec = R - E + self.vvec = self.vvec / proj3d.mod(self.vvec) + + if abs(relev) > np.pi/2: + # upside down + V = np.array((0,0,-1)) + else: + V = np.array((0,0,1)) + zfront,zback = -self.dist,self.dist + + viewM = proj3d.view_transformation(E,R,V) + perspM = proj3d.persp_transformation(zfront,zback) + M0 = np.dot(viewM,worldM) + M = np.dot(perspM,M0) + return M + + def mouse_init(self): + self.button_pressed = None + canv = self.figure.canvas + if canv != None: + c1 = canv.mpl_connect('motion_notify_event', self.on_move) + c2 = canv.mpl_connect('button_press_event', self.button_press) + c3 = canv.mpl_connect('button_release_event', self.button_release) + self.cids = [c1, c2, c3] + + def cla(self): + # Disconnect the various events we set. + for cid in self.cids: + self.figure.canvas.mpl_disconnect(cid) + self.cids = [] + Axes.cla(self) + + def button_press(self, event): + self.button_pressed = event.button + self.sx,self.sy = event.xdata,event.ydata + + def button_release(self, event): + self.button_pressed = None + + def format_xdata(self, x): + """ + Return x string formatted. This function will use the attribute + self.fmt_xdata if it is callable, else will fall back on the xaxis + major formatter + """ + try: return self.fmt_xdata(x) + except TypeError: + fmt = self.w_xaxis.get_major_formatter() + return sensible_format_data(fmt,x) + + def format_ydata(self, y): + """ + Return y string formatted. This function will use the attribute + self.fmt_ydata if it is callable, else will fall back on the yaxis + major formatter + """ + try: return self.fmt_ydata(y) + except TypeError: + fmt = self.w_yaxis.get_major_formatter() + return sensible_format_data(fmt,y) + + def format_zdata(self, z): + """ + Return y string formatted. This function will use the attribute + self.fmt_ydata if it is callable, else will fall back on the yaxis + major formatter + """ + try: return self.fmt_zdata(z) + except (AttributeError,TypeError): + fmt = self.w_zaxis.get_major_formatter() + return sensible_format_data(fmt,z) + + def format_coord(self, xd, yd): + """Given the 2D view coordinates attempt to guess a 3D coordinate + + Looks for the nearest edge to the point and then assumes that the point is + at the same z location as the nearest point on the edge. + """ + + if self.M is None: + return '' + + if self.button_pressed == 1: + return 'azimuth=%d deg, elevation=%d deg ' % (self.azim, self.elev) + # ignore xd and yd and display angles instead + + p = (xd,yd) + edges = self.tunit_edges() + #lines = [proj3d.line2d(p0,p1) for (p0,p1) in edges] + ldists = [(proj3d.line2d_seg_dist(p0,p1,p),i) for i,(p0,p1) in enumerate(edges)] + ldists.sort() + # nearest edge + edgei = ldists[0][1] + # + p0,p1 = edges[edgei] + + # scale the z value to match + x0,y0,z0 = p0 + x1,y1,z1 = p1 + d0 = np.hypot(x0-xd,y0-yd) + d1 = np.hypot(x1-xd,y1-yd) + dt = d0+d1 + z = d1/dt * z0 + d0/dt * z1 + #print 'mid', edgei, d0, d1, z0, z1, z + + x,y,z = proj3d.inv_transform(xd,yd,z,self.M) + + xs = self.format_xdata(x) + ys = self.format_ydata(y) + zs = self.format_ydata(z) + return 'x=%s, y=%s, z=%s'%(xs,ys,zs) + + def on_move(self, event): + """Mouse moving + + button-1 rotates + button-3 zooms + """ + if not self.button_pressed: + return + + if self.M is None: + return + # this shouldn't be called before the graph has been drawn for the first time! + x, y = event.xdata, event.ydata + + # In case the mouse is out of bounds. + if x == None: + + return + dx,dy = x-self.sx,y-self.sy + x0,x1 = self.get_xlim() + y0,y1 = self.get_ylim() + w = (x1-x0) + h = (y1-y0) + self.sx,self.sy = x,y + + if self.button_pressed == 1: + # rotate viewing point + # get the x and y pixel coords + if dx == 0 and dy == 0: return + # + self.elev = axis3d.norm_angle(self.elev - (dy/h)*180) + self.azim = axis3d.norm_angle(self.azim - (dx/w)*180) + self.get_proj() + self.figure.canvas.draw() + elif self.button_pressed == 2: + # pan view + # project xv,yv,zv -> xw,yw,zw + # pan + # + pass + elif self.button_pressed == 3: + # zoom view + # hmmm..this needs some help from clipping.... + minpy,maxx,miny,maxy,minz,maxz = self.get_w_lims() + df = 1-((h - dy)/h) + dx = (maxx-minpy)*df + dy = (maxy-miny)*df + dz = (maxz-minz)*df + self.set_w_xlim(minpy-dx,maxx+dx) + self.set_w_ylim(miny-dy,maxy+dy) + self.set_w_zlim(minz-dz,maxz+dz) + self.get_proj() + self.figure.canvas.draw() + + def set_xlabel(self, xlabel, fontdict=None, **kwargs): + #par = cbook.popd(kwargs, 'par',None) + #label.set_par(par) + # + label = self.w_xaxis.get_label() + label.set_text(xlabel) + if fontdict is not None: label.update(fontdict) + label.update(kwargs) + return label + + def set_ylabel(self, ylabel, fontdict=None, **kwargs): + label = self.w_yaxis.get_label() + label.set_text(ylabel) + if fontdict is not None: label.update(fontdict) + label.update(kwargs) + return label + + def set_zlabel(self, zlabel, fontdict=None, **kwargs): + label = self.w_zaxis.get_label() + label.set_text(zlabel) + if fontdict is not None: label.update(fontdict) + label.update(kwargs) + return label + + def plot(self, *args, **kwargs): + had_data = self.has_data() + + zval = kwargs.pop( 'z', 0) + zdir = kwargs.pop('dir', 'z') + lines = Axes.plot(self, *args, **kwargs) + for line in lines: + art3d.line_2d_to_3d(line, z=zval, dir=zdir) + + xs = lines[0].get_xdata() + ys = lines[0].get_ydata() + zs = [zval for x in xs] + xs,ys,zs = art3d.juggle_axes(xs,ys,zs,zdir) + self.auto_scale_xyz(xs,ys,zs, had_data) + return lines + + def plot3D(self, xs, ys, zs, *args, **kwargs): + had_data = self.has_data() + lines = Axes.plot(self, xs,ys, *args, **kwargs) + if len(lines)==1: + line = lines[0] + art3d.line_2d_to_3d(line, zs) + self.auto_scale_xyz(xs,ys,zs, had_data) + return lines + + plot3d=plot3D + + def plot_surface(self, X, Y, Z, *args, **kwargs): + had_data = self.has_data() + + rows, cols = Z.shape + tX,tY,tZ = np.transpose(X), np.transpose(Y), np.transpose(Z) + rstride = kwargs.pop('rstride', 10) + cstride = kwargs.pop('cstride', 10) + # + polys = [] + boxes = [] + for rs in np.arange(0,rows-1,rstride): + for cs in np.arange(0,cols-1,cstride): + ps = [] + corners = [] + for a,ta in [(X,tX),(Y,tY),(Z,tZ)]: + ztop = a[rs][cs:min(cols,cs+cstride+1)] + zleft = ta[min(cols-1,cs+cstride)][rs:min(rows,rs+rstride+1)] + zbase = a[min(rows-1,rs+rstride)][cs:min(cols,cs+cstride+1):] + zbase = zbase[::-1] + zright = ta[cs][rs:min(rows,rs+rstride+1):] + zright = zright[::-1] + corners.append([ztop[0],ztop[-1],zbase[0],zbase[-1]]) + z = np.concatenate((ztop,zleft,zbase,zright)) + ps.append(z) + boxes.append(map(np.array,zip(*corners))) + polys.append(zip(*ps)) + # + lines = [] + shade = [] + for box in boxes: + n = proj3d.cross(box[0]-box[1], + box[0]-box[2]) + n = n/proj3d.mod(n)*5 + shade.append(np.dot(n,[-1,-1,0.5])) + lines.append((box[0],n+box[0])) + # + color = np.array([0,0,1,1]) + norm = Normalize(min(shade),max(shade)) + colors = [color * (0.5+norm(v)*0.5) for v in shade] + for c in colors: c[3] = 1 + polyc = art3d.Poly3DCollection(polys, facecolors=colors, *args, **kwargs) + polyc._zsort = 1 + self.add_collection(polyc) + # + self.auto_scale_xyz(X,Y,Z, had_data) + return polyc + + def plot_wireframe(self, X, Y, Z, *args, **kwargs): + rstride = kwargs.pop("rstride", 1) + cstride = kwargs.pop("cstride", 1) + + had_data = self.has_data() + rows,cols = Z.shape + + tX,tY,tZ = np.transpose(X), np.transpose(Y), np.transpose(Z) + + rii = [i for i in range(0,rows,rstride)]+[rows-1] + cii = [i for i in range(0,cols,cstride)]+[cols-1] + xlines = [X[i] for i in rii] + ylines = [Y[i] for i in rii] + zlines = [Z[i] for i in rii] + # + txlines = [tX[i] for i in cii] + tylines = [tY[i] for i in cii] + tzlines = [tZ[i] for i in cii] + # + lines = [zip(xl,yl,zl) for xl,yl,zl in zip(xlines,ylines,zlines)] + lines += [zip(xl,yl,zl) for xl,yl,zl in zip(txlines,tylines,tzlines)] + linec = self.add_lines(lines, *args, **kwargs) + + self.auto_scale_xyz(X,Y,Z, had_data) + return linec + + def contour3D(self, X, Y, Z, *args, **kwargs): + had_data = self.has_data() + cset = self.contour(X, Y, Z, *args, **kwargs) + for z, linec in zip(cset.levels, cset.collections): + zl = [] + art3d.line_collection_2d_to_3d(linec, z) + self.auto_scale_xyz(X,Y,Z, had_data) + return cset + + def clabel(self, *args, **kwargs): +# r = Axes.clabel(self, *args, **kwargs) + return None + + def contourf3D(self, X, Y, Z, *args, **kwargs): + had_data = self.has_data() + + cset = self.contourf(X, Y, Z, *args, **kwargs) + levels = cset.levels + colls = cset.collections + + for z1,z2,linec in zip(levels,levels[1:],colls): + zs = [z1] * (len(linec.get_paths()[0])/2) + zs += [z2] * (len(linec.get_paths()[0])/2) + art3d.poly_collection_2d_to_3d(linec, zs) + self.auto_scale_xyz(X,Y,Z, had_data) + return cset + + def scatter3D(self, xs, ys, zs, *args, **kwargs): + had_data = self.has_data() + patches = Axes.scatter(self,xs,ys,*args,**kwargs) + patches = art3d.patch_collection_2d_to_3d(patches, zs) + self.auto_scale_xyz(xs,ys,zs, had_data) + return patches + scatter3d = scatter3D + + def add_lines(self, lines, *args, **kwargs): + linec = art3d.Line3DCollection(lines, *args, **kwargs) + self.add_collection(linec) + return linec + """ + def text3D(self, x,y,z,s, *args, **kwargs): + text = Axes.text(self,x,y,s,*args,**kwargs) + art3d.wrap_text(text,z) + return text + """ + def ahvline(self, x,y): + pass + + def ahvxplane(self, x): + pass + + def ahvyplane(self, y): + pass + +class Scaler: + def __init__(self, points): + self.inpoints = points + self.drawpoints = None + + def update(self, lims): + for x,y,z in self.points: + pass + +class Axes3D: + """ + Wrapper for Axes3DI + + Provides set_xlim, set_ylim etc. + + 2D functions can be caught here and mapped + to their 3D approximations. + + This should probably be the case for plot etc... + """ + def __init__(self, fig, *args, **kwargs): + self.__dict__['wrapped'] = Axes3DI(fig, *args, **kwargs) + + def set_xlim(self, *args, **kwargs): + self.wrapped.set_w_xlim(*args, **kwargs) + + def set_ylim(self, *args, **kwargs): + self.wrapped.set_w_ylim(*args, **kwargs) + + def set_zlim(self, *args, **kwargs): + self.wrapped.set_w_zlim(*args, **kwargs) + + def __getattr__(self, k): + return getattr(self.wrapped,k) + + def __setattr__(self, k,v): + return setattr(self.wrapped,k,v) + + def add_collection(self, polys, zs=None, dir='z'): + art3d.poly_collection_2d_to_3d(polys, zs=zs, dir=dir) + self.add_3DCollection(polys) + + def add_3DCollection(self, patches): + self.wrapped.add_collection(patches) + + def text(self, x,y, text, *args,**kwargs): + self.wrapped.text3D(x,y,0,text,*args,**kwargs) + + def scatter(self, xs,ys,zs=None,dir='z',*args,**kwargs): + patches = self.wrapped.scatter(xs,ys,*args,**kwargs) + if zs is None: + zs = [0]*len(xs) + art3d.patch_collection_2d_to_3d(patches, zs=zs, dir=dir) + return patches + + def bar(self, left, height, z=0, dir='z', *args, **kwargs): + had_data = self.has_data() + patches = self.wrapped.bar(left, height, *args, **kwargs) + verts = [] + for p in patches: + vs = p.get_verts() + zs = [z]*len(vs) + verts += vs.tolist() + art3d.patch_2d_to_3d(p, zs[0], dir) + if 'alpha' in kwargs: + p.set_alpha(kwargs['alpha']) + xs,ys = zip(*verts) + zs = [z]*len(xs) + xs,ys,zs=art3d.juggle_axes(xs,ys,zs,dir) + self.wrapped.auto_scale_xyz(xs,ys,zs, had_data) + return patches + +def test_scatter(): + f = plt.figure() + ax = Axes3D(f) + + n = 100 + for c,zl,zh in [('r',-50,-25),('b',-30,-5)]: + xs,ys,zs = zip(* + [(random.randrange(23,32), + random.randrange(100), + random.randrange(zl,zh) + ) for i in range(n)]) + ax.scatter3D(xs,ys,zs, c=c) + + ax.set_xlabel('------------ X Label --------------------') + ax.set_ylabel('------------ Y Label --------------------') + ax.set_zlabel('------------ Z Label --------------------') + +def get_test_data(delta=0.05): + from matplotlib.mlab import bivariate_normal + x = y = np.arange(-3.0, 3.0, delta) + X, Y = np.meshgrid(x,y) + + Z1 = bivariate_normal(X, Y, 1.0, 1.0, 0.0, 0.0) + Z2 = bivariate_normal(X, Y, 1.5, 0.5, 1, 1) + Z = Z2-Z1 + + X = X * 10 + Y = Y * 10 + Z = Z * 500 + return X,Y,Z + +def test_wire(): + f = plt.figure() + ax = Axes3D(f) + + X,Y,Z = get_test_data(0.05) + ax.plot_wireframe(X,Y,Z, rstride=10,cstride=10) + ax.set_xlabel('X') + ax.set_ylabel('Y') + ax.set_zlabel('Z') + +def test_surface(): + f = plt.figure() + ax = Axes3D(f) + + X,Y,Z = get_test_data(0.05) + ax.plot_surface(X,Y,Z, rstride=10,cstride=10) + ax.set_xlabel('X') + ax.set_ylabel('Y') + ax.set_zlabel('Z') + +def test_contour(): + f = plt.figure() + ax = Axes3D(f) + + X,Y,Z = get_test_data(0.05) + cset = ax.contour3D(X,Y,Z) + ax.clabel(cset, fontsize=9, inline=1) + ax.set_xlabel('X') + ax.set_ylabel('Y') + ax.set_zlabel('Z') + +def test_contourf(): + f = plt.figure() + ax = Axes3D(f) + + X,Y,Z = get_test_data(0.05) + cset = ax.contourf3D(X,Y,Z) + ax.clabel(cset, fontsize=9, inline=1) + ax.set_xlabel('X') + ax.set_ylabel('Y') + ax.set_zlabel('Z') + +def test_plot(): + f = plt.figure() + ax = Axes3D(f) + + xs = np.arange(0,4*np.pi+0.1,0.1) + ys = np.sin(xs) + ax.plot(xs,ys, label='zl') + ax.plot(xs,ys+max(xs),label='zh') + ax.plot(xs,ys,dir='x', label='xl') + ax.plot(xs,ys,dir='x', z=max(xs),label='xh') + ax.plot(xs,ys,dir='y', label='yl') + ax.plot(xs,ys,dir='y', z=max(xs), label='yh') + ax.set_xlabel('X') + ax.set_ylabel('Y') + ax.set_zlabel('Z') + ax.legend() + +def test_polys(): + f = plt.figure() + ax = Axes3D(f) + + cc = lambda arg: colorConverter.to_rgba(arg, alpha=0.6) + + xs = np.arange(0,10,0.4) + verts = [] + zs = [0.0,1.0,2.0,3.0] + for z in zs: + ys = [random.random() for x in xs] + ys[0],ys[-1] = 0,0 + verts.append(zip(xs,ys)) + + from matplotlib.collections import PolyCollection + poly = PolyCollection(verts, facecolors = [cc('r'),cc('g'),cc('b'), + cc('y')]) + poly.set_alpha(0.7) + ax.add_collection(poly,zs=zs,dir='y') + + ax.set_xlim(0,10) + ax.set_ylim(-1,4) + ax.set_zlim(0,1) + +def test_scatter2D(): + f = plt.figure() + ax = Axes3D(f) + + xs = [random.random() for i in range(20)] + ys = [random.random() for x in xs] + ax.scatter(xs, ys) + ax.scatter(xs, ys, dir='y', c='r') + ax.scatter(xs, ys, dir='x', c='g') + +def test_bar2D(): + f = plt.figure() + ax = Axes3D(f) + + for c,z in zip(['r','g','b', 'y'],[30,20,10,0]): + xs = np.arange(20) + ys = [random.random() for x in xs] + ax.bar(xs, ys, z=z, dir='y', color=c, alpha=0.8) + +if __name__ == "__main__": + import pylab + import axis3d; reload(axis3d); + import art3d; reload(art3d); + import proj3d; reload(proj3d); + + test_scatter() + test_wire() + test_surface() + test_contour() + test_contourf() + test_plot() + test_polys() + test_scatter2D() +# test_bar2D() + + pylab.show() Added: trunk/matplotlib/lib/mpl_toolkits/mplot3d/axis3d.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/mplot3d/axis3d.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/mplot3d/axis3d.py 2009年04月14日 14:29:31 UTC (rev 7041) @@ -0,0 +1,310 @@ +#!/usr/bin/python +# axis3d.py, original mplot3d version by John Porter +# Created: 23 Sep 2005 +# Parts rewritten by Reinier Heeres <re...@he...> + +import math +import copy + +from matplotlib import lines +from matplotlib import axis +from matplotlib import patches +from matplotlib import text + +import art3d +import proj3d + +import numpy as np + +def norm_angle(a): + """Return angle between -180 and +180""" + a = (a+360)%360 + if a > 180: a = a-360 + return a + +def norm_text_angle(a): + """Return angle between -90 and +90""" + a = (a + 180) % 180 + if a > 90: + a = a - 180 + return a + +def get_flip_min_max(coord, index, mins, maxs): + if coord[index] == mins[index]: + return maxs[index] + else: + return mins[index] + +def move_from_center(coord, centers, deltas, axmask=(True, True, True)): + '''Return a coordinate that is moved by "deltas" away from the center.''' + ret = copy.copy(coord) + for i in range(3): + if not axmask[i]: + continue + if coord[i] < centers[i]: + coord[i] -= deltas[i] + else: + coord[i] += deltas[i] + return coord + +def tick_update_position(tick, tickxs, tickys, labelpos): + '''Update tick line and label position and style.''' + + for (label, on) in ((tick.label1, tick.label1On), \ + (tick.label2, tick.label2On)): + if on: + label.set_position(labelpos) + + tick.tick1On, tick.tick2On = True, False + tick.tick1line.set_linestyle('-') + tick.tick1line.set_marker('') + tick.tick1line.set_data(tickxs, tickys) + +class Axis(axis.XAxis): + + # These points from the unit cube make up the x, y and z-planes + _PLANES = ( + (0, 3, 7, 4), (1, 2, 6, 5), # yz planes + (0, 1, 5, 4), (3, 2, 6, 7), # xz planes + (0, 1, 2, 3), (4, 5, 6, 7), # xy planes + ) + + # Some properties for the axes + _AXINFO = { + 'x': {'i': 0, 'tickdir': 1, + 'color': (0.95, 0.95, 0.95, 0.5)}, + 'y': {'i': 1, 'tickdir': 0, + 'color': (0.90, 0.90, 0.90, 0.5)}, + 'z': {'i': 2, 'tickdir': 0, + 'color': (0.925, 0.925, 0.925, 0.5)}, + } + + def __init__(self, adir, v_intervalx, d_intervalx, axes, *args, **kwargs): + # adir identifies which axes this is + self.adir = adir + # data and viewing intervals for this direction + self.d_interval = d_intervalx + self.v_interval = v_intervalx + # + axis.XAxis.__init__(self, axes, *args, **kwargs) + self.line = lines.Line2D(xdata=(0,0),ydata=(0,0), + linewidth=0.75, + color=(0,0,0,0), + antialiased=True, + ) + + # Store dummy data in Polygon object + self.has_pane = True + self.pane = patches.Polygon(np.array([[0,0],[0,1],[1,0],[0,0]]), + alpha=0.8, + facecolor=(1,1,1,0), + edgecolor=(1,1,1,0)) + + self.axes._set_artist_props(self.line) + self.axes._set_artist_props(self.pane) + self.gridlines = art3d.Line3DCollection([], ) + self.axes._set_artist_props(self.gridlines) + self.axes._set_artist_props(self.label) + self.label._transform = self.axes.transData + self.set_rotate_label(kwargs.get('rotate_label', None)) + + def get_tick_positions(self): + majorTicks = self.get_major_ticks() + majorLocs = self.major.locator() + self.major.formatter.set_locs(majorLocs) + majorLabels = [self.major.formatter(val, i) for i, val in enumerate(majorLocs)] + return majorLabels,majorLocs + + def get_major_ticks(self): + ticks = axis.XAxis.get_major_ticks(self) + for t in ticks: + def update_coords(renderer,self=t.label1): + return text_update_coords(self, renderer) + # Text overrides setattr so need this to force new method + t.tick1line.set_transform(self.axes.transData) + t.tick2line.set_transform(self.axes.transData) + t.gridline.set_transform(self.axes.transData) + t.label1.set_transform(self.axes.transData) + t.label2.set_transform(self.axes.transData) + return ticks + + def set_pane(self, xys, color): + if self.has_pane: + xys = np.asarray(xys) + xys = xys[:,:2] + self.pane.xy = xys + self.pane.set_edgecolor(color) + self.pane.set_facecolor(color) + self.pane.set_alpha(color[-1]) + + def set_rotate_label(self, val): + ''' + Whether to rotate the axis label: True, False or None. + If set to None the label will be rotated if longer than 4 chars. + ''' + self._rotate_label = val + + def get_rotate_label(self, text): + if self._rotate_label is not None: + return self._rotate_label + else: + return len(text) > 4 + + def draw(self, renderer): + self.label._transform = self.axes.transData + renderer.open_group('axis3d') + + # code from XAxis + majorTicks = self.get_major_ticks() + majorLocs = self.major.locator() + + # filter locations here so that no extra grid lines are drawn + interval = self.get_view_interval() + majorLocs = [loc for loc in majorLocs if interval[0] < loc < interval[1]] + self.major.formatter.set_locs(majorLocs) + majorLabels = [self.major.formatter(val, i) + for i, val in enumerate(majorLocs)] + + # Determine bounds + minx,maxx,miny,maxy,minz,maxz = self.axes.get_w_lims() + mins = (minx, miny, minz) + maxs = (maxx, maxy, maxz) + centers = [(maxv + minv) / 2 for minv, maxv in zip(mins, maxs)] + deltas = [(maxv - minv) / 12 for minv, maxv in zip(mins, maxs)] + mins = [minv - delta / 4 for minv, delta in zip(mins, deltas)] + maxs = [maxv + delta / 4 for maxv, delta in zip(maxs, deltas)] + + # Determine which planes should be visible by the avg z value + vals = mins[0], maxs[0], mins[1], maxs[1], mins[2], maxs[2] + tc = self.axes.tunit_cube(vals,renderer.M) + avgz = [tc[p1][2] + tc[p2][2] + tc[p3][2] + tc[p4][2] for \ + p1, p2, p3, p4 in self._PLANES] + highs = [avgz[2*i] < avgz[2*i+1] for i in range(3)] + + # Draw plane + info = self._AXINFO[self.adir] + index = info['i'] + if not highs[index]: + plane = self._PLANES[2 * index] + else: + plane = self._PLANES[2 * index + 1] + xys = [tc[p] for p in plane] + self.set_pane(xys, info['color']) + self.pane.draw(renderer) + + # Determine grid lines + minmax = [] + for i, val in enumerate(highs): + if val: + minmax.append(maxs[i]) + else: + minmax.append(mins[i]) + + # Draw main axis line + juggled = art3d.juggle_axes(0, 2, 1, self.adir) + edgep1 = copy.copy(minmax) + edgep1[juggled[0]] = get_flip_min_max(edgep1, juggled[0], mins, maxs) + edgep2 = copy.copy(edgep1) + edgep2[juggled[1]] = get_flip_min_max(edgep2, juggled[1], mins, maxs) + pep = proj3d.proj_trans_points([edgep1, edgep2], renderer.M) + self.line.set_data((pep[0][0], pep[0][1]), (pep[1][0], pep[1][1])) + self.line.draw(renderer) + + # Grid points where the planes meet + xyz0 = [] + for val in majorLocs: + coord = copy.copy(minmax) + coord[index] = val + xyz0.append(coord) + + # Draw labels + dy = pep[1][1] - pep[1][0] + dx = pep[0][1] - pep[0][0] + lxyz = [(v1 + v2) / 2 for v1, v2 in zip(edgep1, edgep2)] + labeldeltas = [1.3 * x for x in deltas] + lxyz = move_from_center(lxyz, centers, labeldeltas) + tlx,tly,tlz = proj3d.proj_transform(lxyz[0], lxyz[1], lxyz[2], renderer.M) + self.label.set_position((tlx, tly)) + if self.get_rotate_label(self.label.get_text()): + angle = norm_text_angle(math.degrees(math.atan2(dy, dx))) + self.label.set_rotation(angle) + self.label.set_va('center') + self.label.draw(renderer) + + # Grid points at end of one plane + xyz1 = copy.deepcopy(xyz0) + newindex = (index + 1) % 3 + newval = get_flip_min_max(xyz1[0], newindex, mins, maxs) + for i in range(len(majorLocs)): + xyz1[i][newindex] = newval + + # Grid points at end of the other plane + xyz2 = copy.deepcopy(xyz0) + newindex = (index + 2) % 3 + newval = get_flip_min_max(xyz2[0], newindex, mins, maxs) + for i in range(len(majorLocs)): + xyz2[i][newindex] = newval + + lines = zip(xyz1, xyz0, xyz2) + self.gridlines.set_segments(lines) + self.gridlines.set_color([(0.9,0.9,0.9,1)] * len(lines)) + self.gridlines.draw(renderer) + + # Draw ticks + tickdir = info['tickdir'] + tickdelta = deltas[tickdir] + if highs[tickdir]: + ticksign = 1 + else: + ticksign = -1 + + for tick, loc, label in zip(majorTicks, majorLocs, majorLabels): + if tick is None: + continue + + # Get tick line positions + pos = copy.copy(edgep1) + pos[index] = loc + pos[tickdir] = edgep1[tickdir] + 0.1 * ticksign * tickdelta + x1, y1, z1 = proj3d.proj_transform(pos[0], pos[1], pos[2], renderer.M) + pos[tickdir] = edgep1[tickdir] - 0.2 * ticksign * tickdelta + x2, y2, z2 = proj3d.proj_transform(pos[0], pos[1], pos[2], renderer.M) + + # Get position of label + labeldeltas = [0.6 * x for x in deltas] + axmask = [True, True, True] + axmask[index] = False + pos[tickdir] = edgep1[tickdir] + pos = move_from_center(pos, centers, labeldeltas, axmask) + lx, ly, lz = proj3d.proj_transform(pos[0], pos[1], pos[2], renderer.M) + + tick_update_position(tick, (x1, x2), (y1, y2), (lx, ly)) + tick.set_label1(label) + tick.set_label2(label) + tick.draw(renderer) + + renderer.close_group('axis3d') + + def get_view_interval(self): + """return the Interval instance for this axis view limits""" + return self.v_interval + +# Each type of axis should be looking in a different place for its +# current data limits so we do this with classes. I think there is +# a lot more that I can and should move down into these classes also. + +class XAxis(Axis): + def get_data_interval(self): + 'return the Interval instance for this axis data limits' + return self.axes.xy_dataLim.intervalx + + +class YAxis(Axis): + def get_data_interval(self): + 'return the Interval instance for this axis data limits' + return self.axes.xy_dataLim.intervaly + +class ZAxis(Axis): + def get_data_interval(self): + 'return the Interval instance for this axis data limits' + return self.axes.zz_dataLim.intervalx Added: trunk/matplotlib/lib/mpl_toolkits/mplot3d/proj3d.py =================================================================== --- trunk/matplotlib/lib/mpl_toolkits/mplot3d/proj3d.py (rev 0) +++ trunk/matplotlib/lib/mpl_toolkits/mplot3d/proj3d.py 2009年04月14日 14:29:31 UTC (rev 7041) @@ -0,0 +1,286 @@ +#!/usr/bin/python +# 3dproj.py +# +""" +Various transforms used for by the 3D code +""" + +from matplotlib.collections import LineCollection +from matplotlib.patches import Circle +import numpy as np +import numpy.linalg as linalg + +def _hide_cross(a,b): + """ + Cross product of two vectors + A x B = <Ay*Bz - Az*By, Az*Bx - Ax*Bz, Ax*By - Ay*Bx> + a x b = [a2b3 - a3b2, a3b1 - a1b3, a1b2 - a2b1] + """ + return np.array([a[1]*b[2]-a[2]*b[1],a[2]*b[0]-a[0]*b[2],a[0]*b[1] - a[1]*b[0]]) +cross = _hide_cross + +def line2d(p0,p1): + """ + Return 2D equation of line in the form ax+by+c = 0 + """ + # x + x1 = 0 + x0,y0 = p0[:2] + x1,y1 = p1[:2] + # + if x0==x1: + a = -1 + b = 0 + c = x1 + elif y0==y1: + a = 0 + b = 1 + c = -y1 + else: + a = (y0-y1) + b = (x0-x1) + c = (x0*y1 - x1*y0) + return a,b,c + +def line2d_dist(l, p): + """ + Distance from line to point + line is a tuple of coefficients a,b,c + """ + a,b,c = l + x0,y0 = p + return abs((a*x0 + b*y0 + c)/np.sqrt(a**2+b**2)) + + +def line2d_seg_dist(p1,p2, p0): + """distance(s) from line defined by p1 - p2 to point(s) p0 + + p0[0] = x(s) + p0[1] = y(s) + + intersection point p = p1 + u*(p2-p1) + and intersection point lies within segement if u is between 0 and 1 + """ + + x21 = p2[0] - p1[0] + y21 = p2[1] - p1[1] + x01 = np.asarray(p0[0]) - p1[0] + y01 = np.asarray(p0[1]) - p1[1] + + u = (x01*x21 + y01*y21)/float(abs(x21**2 + y21**2)) + u = np.clip(u, 0, 1) + d = np.sqrt((x01 - u*x21)**2 + (y01 - u*y21)**2) + + return d + + +def test_lines_dists(): + ax = pylab.gca() + + xs,ys = (0,30),(20,150) + pylab.plot(xs,ys) + points = zip(xs,ys) + p0,p1 = points + + xs,ys = (0,0,20,30),(100,150,30,200) + pylab.scatter(xs,ys) + # + dist = line2d_seg_dist(p0,p1,(xs[0],ys[0])) + dist = line2d_seg_dist(p0,p1,np.array((xs,ys))) + for x,y,d in zip(xs,ys,dist): + c = Circle((x,y),d,fill=0) + ax.add_patch(c) + # + pylab.xlim(-200,... [truncated message content]
Revision: 7040 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7040&view=rev Author: jdh2358 Date: 2009年04月13日 03:02:41 +0000 (2009年4月13日) Log Message: ----------- Merged revisions 7037-7039 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r7037 | cmoad | 2009年04月10日 21:24:37 -0500 (2009年4月10日) | 1 line added python 2.6 / tcltk 8.5 check ........ r7038 | cmoad | 2009年04月12日 21:22:30 -0500 (2009年4月12日) | 1 line minor rev bump ........ r7039 | jdh2358 | 2009年04月12日 21:56:11 -0500 (2009年4月12日) | 1 line fixed csv2rec bug referenced in sf bug 2745173 ........ Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/doc/matplotlibrc trunk/matplotlib/lib/matplotlib/mlab.py trunk/matplotlib/setupext.py Property Changed: ---------------- trunk/matplotlib/ Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7035 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7039 Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009年04月13日 02:56:11 UTC (rev 7039) +++ trunk/matplotlib/CHANGELOG 2009年04月13日 03:02:41 UTC (rev 7040) @@ -1,3 +1,6 @@ +====================================================================== +2008年04月12日 Release 0.98.5.3 at r7038 + 2009年04月06日 The pdf backend now escapes newlines and linefeeds in strings. Fixes sf bug #2708559; thanks to Tiago Pereira for the report. Modified: trunk/matplotlib/doc/matplotlibrc =================================================================== --- trunk/matplotlib/doc/matplotlibrc 2009年04月13日 02:56:11 UTC (rev 7039) +++ trunk/matplotlib/doc/matplotlibrc 2009年04月13日 03:02:41 UTC (rev 7040) @@ -27,7 +27,6 @@ # the default backend; one of GTK GTKAgg GTKCairo FltkAgg QtAgg TkAgg # WX WXAgg Agg Cairo GD GDK Paint PS PDF SVG Template backend : Agg -numerix : numpy # numpy, Numeric or numarray #maskedarray : False # True to use external maskedarray module # instead of numpy.ma; this is a temporary # setting for testing maskedarray. Modified: trunk/matplotlib/lib/matplotlib/mlab.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mlab.py 2009年04月13日 02:56:11 UTC (rev 7039) +++ trunk/matplotlib/lib/matplotlib/mlab.py 2009年04月13日 03:02:41 UTC (rev 7040) @@ -2552,8 +2552,14 @@ fh.seek(0) reader = csv.reader(fh, delimiter=delimiter) process_skiprows(reader) + if needheader: - skipheader = reader.next() + while 1: + # skip past any comments and consume one line of column header + row = reader.next() + if len(row) and row[0].startswith(comments): + continue + break # iterate over the remaining rows and convert the data to date # objects, ints, or floats as approriate Modified: trunk/matplotlib/setupext.py =================================================================== --- trunk/matplotlib/setupext.py 2009年04月13日 02:56:11 UTC (rev 7039) +++ trunk/matplotlib/setupext.py 2009年04月13日 03:02:41 UTC (rev 7040) @@ -952,11 +952,14 @@ message = None if sys.platform == 'win32': major, minor1, minor2, s, tmp = sys.version_info - if major == 2 and minor1 in [3, 4, 5]: - module.include_dirs.extend(['win32_static/include/tcl8.4']) + if major == 2 and minor1 == 6: + module.include_dirs.extend(['win32_static/include/tcl85']) + module.libraries.extend(['tk85', 'tcl85']) + elif major == 2 and minor1 in [3, 4, 5]: + module.include_dirs.extend(['win32_static/include/tcl84']) module.libraries.extend(['tk84', 'tcl84']) elif major == 2 and minor1 == 2: - module.include_dirs.extend(['win32_static/include/tcl8.3']) + module.include_dirs.extend(['win32_static/include/tcl83']) module.libraries.extend(['tk83', 'tcl83']) else: raise RuntimeError('No tk/win32 support for this python version yet') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7039 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7039&view=rev Author: jdh2358 Date: 2009年04月13日 02:56:11 +0000 (2009年4月13日) Log Message: ----------- fixed csv2rec bug referenced in sf bug 2745173 Modified Paths: -------------- branches/v0_98_5_maint/doc/matplotlibrc branches/v0_98_5_maint/lib/matplotlib/mlab.py Modified: branches/v0_98_5_maint/doc/matplotlibrc =================================================================== --- branches/v0_98_5_maint/doc/matplotlibrc 2009年04月13日 02:22:30 UTC (rev 7038) +++ branches/v0_98_5_maint/doc/matplotlibrc 2009年04月13日 02:56:11 UTC (rev 7039) @@ -27,7 +27,6 @@ # the default backend; one of GTK GTKAgg GTKCairo FltkAgg QtAgg TkAgg # WX WXAgg Agg Cairo GD GDK Paint PS PDF SVG Template backend : Agg -numerix : numpy # numpy, Numeric or numarray #maskedarray : False # True to use external maskedarray module # instead of numpy.ma; this is a temporary # setting for testing maskedarray. Modified: branches/v0_98_5_maint/lib/matplotlib/mlab.py =================================================================== --- branches/v0_98_5_maint/lib/matplotlib/mlab.py 2009年04月13日 02:22:30 UTC (rev 7038) +++ branches/v0_98_5_maint/lib/matplotlib/mlab.py 2009年04月13日 02:56:11 UTC (rev 7039) @@ -2532,8 +2532,14 @@ fh.seek(0) reader = csv.reader(fh, delimiter=delimiter) process_skiprows(reader) + if needheader: - skipheader = reader.next() + while 1: + # skip past any comments and consume one line of column header + row = reader.next() + if len(row) and row[0].startswith(comments): + continue + break # iterate over the remaining rows and convert the data to date # objects, ints, or floats as approriate This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7038 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7038&view=rev Author: cmoad Date: 2009年04月13日 02:22:30 +0000 (2009年4月13日) Log Message: ----------- minor rev bump Modified Paths: -------------- branches/v0_98_5_maint/CHANGELOG Modified: branches/v0_98_5_maint/CHANGELOG =================================================================== --- branches/v0_98_5_maint/CHANGELOG 2009年04月11日 02:24:37 UTC (rev 7037) +++ branches/v0_98_5_maint/CHANGELOG 2009年04月13日 02:22:30 UTC (rev 7038) @@ -1,3 +1,6 @@ +====================================================================== +2008年04月12日 Release 0.98.5.3 at r7038 + 2009年04月06日 The pdf backend now escapes newlines and linefeeds in strings. Fixes sf bug #2708559; thanks to Tiago Pereira for the report. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7037 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7037&view=rev Author: cmoad Date: 2009年04月11日 02:24:37 +0000 (2009年4月11日) Log Message: ----------- added python 2.6 / tcltk 8.5 check Modified Paths: -------------- branches/v0_98_5_maint/setupext.py Modified: branches/v0_98_5_maint/setupext.py =================================================================== --- branches/v0_98_5_maint/setupext.py 2009年04月06日 19:05:57 UTC (rev 7036) +++ branches/v0_98_5_maint/setupext.py 2009年04月11日 02:24:37 UTC (rev 7037) @@ -958,11 +958,14 @@ message = None if sys.platform == 'win32': major, minor1, minor2, s, tmp = sys.version_info - if major == 2 and minor1 in [3, 4, 5]: - module.include_dirs.extend(['win32_static/include/tcl8.4']) + if major == 2 and minor1 == 6: + module.include_dirs.extend(['win32_static/include/tcl85']) + module.libraries.extend(['tk85', 'tcl85']) + elif major == 2 and minor1 in [3, 4, 5]: + module.include_dirs.extend(['win32_static/include/tcl84']) module.libraries.extend(['tk84', 'tcl84']) elif major == 2 and minor1 == 2: - module.include_dirs.extend(['win32_static/include/tcl8.3']) + module.include_dirs.extend(['win32_static/include/tcl83']) module.libraries.extend(['tk83', 'tcl83']) else: raise RuntimeError('No tk/win32 support for this python version yet') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7036 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7036&view=rev Author: jouni Date: 2009年04月06日 19:05:57 +0000 (2009年4月06日) Log Message: ----------- Merged revisions 7035 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r7035 | jouni | 2009年04月06日 21:59:47 +0300 (2009年4月06日) | 1 line The pdf backend now escapes newlines and linefeeds in strings - fixes #2708559 ........ Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/examples/pylab_examples/usetex_demo.py trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py Property Changed: ---------------- trunk/matplotlib/ trunk/matplotlib/doc/pyplots/README trunk/matplotlib/doc/sphinxext/gen_gallery.py trunk/matplotlib/doc/sphinxext/gen_rst.py trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7033 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7035 Modified: svn:mergeinfo - /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033 + /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035 Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009年04月06日 18:59:47 UTC (rev 7035) +++ trunk/matplotlib/CHANGELOG 2009年04月06日 19:05:57 UTC (rev 7036) @@ -1,3 +1,6 @@ +2009年04月06日 The pdf backend now escapes newlines and linefeeds in strings. + Fixes sf bug #2708559; thanks to Tiago Pereira for the report. + 2009年04月06日 texmanager.make_dvi now raises an error if LaTeX failed to create an output file. Thanks to Joao Luis Silva for reporting this. - JKS Property changes on: trunk/matplotlib/doc/pyplots/README ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033 + /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035 Property changes on: trunk/matplotlib/doc/sphinxext/gen_gallery.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033 + /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035 Property changes on: trunk/matplotlib/doc/sphinxext/gen_rst.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033 + /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035 Modified: trunk/matplotlib/examples/pylab_examples/usetex_demo.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/usetex_demo.py 2009年04月06日 18:59:47 UTC (rev 7035) +++ trunk/matplotlib/examples/pylab_examples/usetex_demo.py 2009年04月06日 19:05:57 UTC (rev 7036) @@ -56,4 +56,8 @@ ## phase field equations pylab.text(0.2, 0.15, r'$\mathcal{F} = \int f\left( \phi, c \right) dV,$ \newline $ \frac{ \partial \phi } { \partial t } = -M_{ \phi } \frac{ \delta \mathcal{F} } { \delta \phi }$', {'color' : 'b', 'fontsize' : 20}) +## these went wrong in pdf in a previous version +pylab.text(-.9,.42,r'gamma: $\gamma$', {'color': 'r', 'fontsize': 20}) +pylab.text(-.9,.36,r'Omega: $\Omega$', {'color': 'b', 'fontsize': 20}) + pylab.show() Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2009年04月06日 18:59:47 UTC (rev 7035) +++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2009年04月06日 19:05:57 UTC (rev 7036) @@ -110,7 +110,20 @@ result.append(' '.join(strings[lasti:])) return '\n'.join(result) -_string_escape_regex = re.compile(r'([\\()])') +# PDF strings are supposed to be able to include any eight-bit data, +# except that unbalanced parens and backslashes must be escaped by a +# backslash. However, sf bug #2708559 shows that the carriage return +# character may get read as a newline; these characters correspond to +# \gamma and \Omega in TeX's math font encoding. Escaping them fixes +# the bug. +_string_escape_regex = re.compile(r'([\\()\r\n])') +def _string_escape(match): + m = match.group(0) + if m in r'\()': return '\\' + m + elif m == '\n': return r'\n' + elif m == '\r': return r'\r' + assert False + def pdfRepr(obj): """Map Python objects to PDF syntax.""" @@ -136,7 +149,7 @@ # simpler to escape them all. TODO: cut long strings into lines; # I believe there is some maximum line length in PDF. elif is_string_like(obj): - return '(' + _string_escape_regex.sub(r'\\1円', obj) + ')' + return '(' + _string_escape_regex.sub(_string_escape, obj) + ')' # Dictionaries. The keys must be PDF names, so if we find strings # there, we make Name objects from them. The values may be Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/mathmpl.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/mathmpl.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033 + /branches/v0_91_maint/doc/sphinxext/mathmpl.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/mathmpl.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035 Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/only_directives.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/only_directives.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033 + /branches/v0_91_maint/doc/sphinxext/only_directives.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/only_directives.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035 Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/plot_directive.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py:6920-6925,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033 + /branches/v0_91_maint/doc/sphinxext/plot_directive.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py:6920-6925,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033,7035 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7035 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7035&view=rev Author: jouni Date: 2009年04月06日 18:59:47 +0000 (2009年4月06日) Log Message: ----------- The pdf backend now escapes newlines and linefeeds in strings - fixes #2708559 Modified Paths: -------------- branches/v0_98_5_maint/CHANGELOG branches/v0_98_5_maint/examples/pylab_examples/usetex_demo.py branches/v0_98_5_maint/lib/matplotlib/backends/backend_pdf.py Modified: branches/v0_98_5_maint/CHANGELOG =================================================================== --- branches/v0_98_5_maint/CHANGELOG 2009年04月06日 17:12:37 UTC (rev 7034) +++ branches/v0_98_5_maint/CHANGELOG 2009年04月06日 18:59:47 UTC (rev 7035) @@ -1,3 +1,6 @@ +2009年04月06日 The pdf backend now escapes newlines and linefeeds in strings. + Fixes sf bug #2708559; thanks to Tiago Pereira for the report. + 2009年04月06日 texmanager.make_dvi now raises an error if LaTeX failed to create an output file. Thanks to Joao Luis Silva for reporting this. - JKS Modified: branches/v0_98_5_maint/examples/pylab_examples/usetex_demo.py =================================================================== --- branches/v0_98_5_maint/examples/pylab_examples/usetex_demo.py 2009年04月06日 17:12:37 UTC (rev 7034) +++ branches/v0_98_5_maint/examples/pylab_examples/usetex_demo.py 2009年04月06日 18:59:47 UTC (rev 7035) @@ -56,4 +56,8 @@ ## phase field equations pylab.text(0.2, 0.15, r'$\mathcal{F} = \int f\left( \phi, c \right) dV,$ \newline $ \frac{ \partial \phi } { \partial t } = -M_{ \phi } \frac{ \delta \mathcal{F} } { \delta \phi }$', {'color' : 'b', 'fontsize' : 20}) +## these went wrong in pdf in a previous version +pylab.text(-.9,.42,r'gamma: $\gamma$', {'color': 'r', 'fontsize': 20}) +pylab.text(-.9,.36,r'Omega: $\Omega$', {'color': 'b', 'fontsize': 20}) + pylab.show() Modified: branches/v0_98_5_maint/lib/matplotlib/backends/backend_pdf.py =================================================================== --- branches/v0_98_5_maint/lib/matplotlib/backends/backend_pdf.py 2009年04月06日 17:12:37 UTC (rev 7034) +++ branches/v0_98_5_maint/lib/matplotlib/backends/backend_pdf.py 2009年04月06日 18:59:47 UTC (rev 7035) @@ -112,7 +112,20 @@ result.append(' '.join(strings[lasti:])) return '\n'.join(result) -_string_escape_regex = re.compile(r'([\\()])') +# PDF strings are supposed to be able to include any eight-bit data, +# except that unbalanced parens and backslashes must be escaped by a +# backslash. However, sf bug #2708559 shows that the carriage return +# character may get read as a newline; these characters correspond to +# \gamma and \Omega in TeX's math font encoding. Escaping them fixes +# the bug. +_string_escape_regex = re.compile(r'([\\()\r\n])') +def _string_escape(match): + m = match.group(0) + if m in r'\()': return '\\' + m + elif m == '\n': return r'\n' + elif m == '\r': return r'\r' + assert False + def pdfRepr(obj): """Map Python objects to PDF syntax.""" @@ -138,7 +151,7 @@ # simpler to escape them all. TODO: cut long strings into lines; # I believe there is some maximum line length in PDF. elif is_string_like(obj): - return '(' + _string_escape_regex.sub(r'\\1円', obj) + ')' + return '(' + _string_escape_regex.sub(_string_escape, obj) + ')' # Dictionaries. The keys must be PDF names, so if we find strings # there, we make Name objects from them. The values may be This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7034 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7034&view=rev Author: jouni Date: 2009年04月06日 17:12:37 +0000 (2009年4月06日) Log Message: ----------- Merged revisions 7033 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r7033 | jouni | 2009年04月06日 20:03:09 +0300 (2009年4月06日) | 1 line texmanager.make_dvi now raises an error if LaTeX failed to create an output file ........ Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/texmanager.py Property Changed: ---------------- trunk/matplotlib/ trunk/matplotlib/doc/pyplots/README trunk/matplotlib/doc/sphinxext/gen_gallery.py trunk/matplotlib/doc/sphinxext/gen_rst.py trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7025,7027-7031 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7033 Modified: svn:mergeinfo - /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025 + /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033 Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009年04月06日 17:03:09 UTC (rev 7033) +++ trunk/matplotlib/CHANGELOG 2009年04月06日 17:12:37 UTC (rev 7034) @@ -1,3 +1,7 @@ +2009年04月06日 texmanager.make_dvi now raises an error if LaTeX failed to + create an output file. Thanks to Joao Luis Silva for reporting + this. - JKS + 2009年04月05日 _png.read_png() reads 12 bit PNGs (patch from Tobias Wood) - ADS Property changes on: trunk/matplotlib/doc/pyplots/README ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025 + /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033 Property changes on: trunk/matplotlib/doc/sphinxext/gen_gallery.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025 + /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033 Property changes on: trunk/matplotlib/doc/sphinxext/gen_rst.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025 + /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033 Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/mathmpl.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/mathmpl.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025 + /branches/v0_91_maint/doc/sphinxext/mathmpl.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/mathmpl.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033 Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/only_directives.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/only_directives.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025 + /branches/v0_91_maint/doc/sphinxext/only_directives.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/only_directives.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033 Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/plot_directive.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py:6920-6925,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025 + /branches/v0_91_maint/doc/sphinxext/plot_directive.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py:6920-6925,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025,7033 Modified: trunk/matplotlib/lib/matplotlib/texmanager.py =================================================================== --- trunk/matplotlib/lib/matplotlib/texmanager.py 2009年04月06日 17:03:09 UTC (rev 7033) +++ trunk/matplotlib/lib/matplotlib/texmanager.py 2009年04月06日 17:12:37 UTC (rev 7034) @@ -358,7 +358,12 @@ fh.close() except IOError: report = 'No latex error report available.' - if exit_status: + try: + os.stat(dvifile) + exists = True + except OSError: + exists = False + if exit_status or not exists: raise RuntimeError(('LaTeX was not able to process the following \ string:\n%s\nHere is the full report generated by LaTeX: \n\n'% repr(tex)) + report) else: mpl.verbose.report(report, 'debug') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7033 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7033&view=rev Author: jouni Date: 2009年04月06日 17:03:09 +0000 (2009年4月06日) Log Message: ----------- texmanager.make_dvi now raises an error if LaTeX failed to create an output file Modified Paths: -------------- branches/v0_98_5_maint/CHANGELOG branches/v0_98_5_maint/lib/matplotlib/texmanager.py Modified: branches/v0_98_5_maint/CHANGELOG =================================================================== --- branches/v0_98_5_maint/CHANGELOG 2009年04月06日 01:52:45 UTC (rev 7032) +++ branches/v0_98_5_maint/CHANGELOG 2009年04月06日 17:03:09 UTC (rev 7033) @@ -1,3 +1,7 @@ +2009年04月06日 texmanager.make_dvi now raises an error if LaTeX failed to + create an output file. Thanks to Joao Luis Silva for reporting + this. - JKS + 2009年04月05日 _png.read_png() reads 12 bit PNGs (patch from Tobias Wood) - ADS Modified: branches/v0_98_5_maint/lib/matplotlib/texmanager.py =================================================================== --- branches/v0_98_5_maint/lib/matplotlib/texmanager.py 2009年04月06日 01:52:45 UTC (rev 7032) +++ branches/v0_98_5_maint/lib/matplotlib/texmanager.py 2009年04月06日 17:03:09 UTC (rev 7033) @@ -285,7 +285,12 @@ fh.close() except IOError: report = 'No latex error report available.' - if exit_status: + try: + os.stat(dvifile) + exists = True + except OSError: + exists = False + if exit_status or not exists: raise RuntimeError(('LaTeX was not able to process the following \ string:\n%s\nHere is the full report generated by LaTeX: \n\n'% repr(tex)) + report) else: mpl.verbose.report(report, 'debug') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7032 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7032&view=rev Author: astraw Date: 2009年04月06日 01:52:45 +0000 (2009年4月06日) Log Message: ----------- Merged revisions 7027-7031 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r7027 | astraw | 2009年04月05日 15:06:05 -0700 (2009年4月05日) | 1 line pngsuite test: plot images in grayscale if the input array is 2 dimensional ........ r7028 | astraw | 2009年04月05日 15:07:01 -0700 (2009年4月05日) | 1 line read 12 bit PNGs (patch from Tobias Wood) ........ r7029 | astraw | 2009年04月05日 15:07:34 -0700 (2009年4月05日) | 1 line trivial: remove trailing whitespace from source code ........ r7030 | astraw | 2009年04月05日 15:08:24 -0700 (2009年4月05日) | 1 line trivial: remove outdated comment ........ r7031 | astraw | 2009年04月05日 15:09:45 -0700 (2009年4月05日) | 1 line update changelog about Tobias' patch ........ Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/examples/tests/pngsuite/pngsuite.py trunk/matplotlib/lib/matplotlib/image.py trunk/matplotlib/src/_png.cpp Property Changed: ---------------- trunk/matplotlib/ Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7025 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7025,7027-7031 Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009年04月05日 22:09:45 UTC (rev 7031) +++ trunk/matplotlib/CHANGELOG 2009年04月06日 01:52:45 UTC (rev 7032) @@ -1,3 +1,6 @@ +2009年04月05日 _png.read_png() reads 12 bit PNGs (patch from + Tobias Wood) - ADS + 2009年04月04日 Allow log axis scale to clip non-positive values to small positive value; this is useful for errorbars. - EF Modified: trunk/matplotlib/examples/tests/pngsuite/pngsuite.py =================================================================== --- trunk/matplotlib/examples/tests/pngsuite/pngsuite.py 2009年04月05日 22:09:45 UTC (rev 7031) +++ trunk/matplotlib/examples/tests/pngsuite/pngsuite.py 2009年04月06日 01:52:45 UTC (rev 7032) @@ -8,6 +8,7 @@ """ from matplotlib import pyplot as plt +import matplotlib.cm as cm import glob files = glob.glob("basn*.png") @@ -17,7 +18,11 @@ for i, fname in enumerate(files): data = plt.imread(fname) - plt.imshow(data, extent=[i,i+1,0,1]) + cmap = None # use default colormap + if data.ndim==2: + # keep grayscale images gray + cmap = cm.gray + plt.imshow(data, extent=[i,i+1,0,1], cmap=cmap) plt.gca().get_frame().set_facecolor("#ddffff") plt.gca().set_xlim(0, len(files)) Modified: trunk/matplotlib/lib/matplotlib/image.py =================================================================== --- trunk/matplotlib/lib/matplotlib/image.py 2009年04月05日 22:09:45 UTC (rev 7031) +++ trunk/matplotlib/lib/matplotlib/image.py 2009年04月06日 01:52:45 UTC (rev 7032) @@ -748,8 +748,6 @@ <http://www.pythonware.com/products/pil/>`_ is installed, it will use it to load the image and return an array (if possible) which can be used with :func:`~matplotlib.pyplot.imshow`. - - TODO: support RGB and grayscale return values in _image.readpng """ def pilread(): Modified: trunk/matplotlib/src/_png.cpp =================================================================== --- trunk/matplotlib/src/_png.cpp 2009年04月05日 22:09:45 UTC (rev 7031) +++ trunk/matplotlib/src/_png.cpp 2009年04月06日 01:52:45 UTC (rev 7032) @@ -208,38 +208,37 @@ png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); - png_read_info(png_ptr, info_ptr); png_uint_32 width = info_ptr->width; png_uint_32 height = info_ptr->height; - bool do_gray_conversion = (info_ptr->bit_depth < 8 && - info_ptr->color_type == PNG_COLOR_TYPE_GRAY); int bit_depth = info_ptr->bit_depth; - if (bit_depth == 16) { - png_set_strip_16(png_ptr); - } else if (bit_depth < 8) { + + // Unpack 1, 2, and 4-bit images + if (bit_depth < 8) png_set_packing(png_ptr); - } - // convert misc color types to rgb for simplicity - if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY || - info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { - png_set_gray_to_rgb(png_ptr); - } else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { + // If sig bits are set, shift data + png_color_8p sig_bit; + if ((info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) && png_get_sBIT(png_ptr, info_ptr, &sig_bit)) + png_set_shift(png_ptr, sig_bit); + + // Convert big endian to little + if (bit_depth == 16) + png_set_swap(png_ptr); + + // Convert palletes to full RGB + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); - } + // If there's an alpha channel convert gray to RGB + if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); + png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr, info_ptr); - bool rgba = info_ptr->color_type == PNG_COLOR_TYPE_RGBA; - if ( (info_ptr->color_type != PNG_COLOR_TYPE_RGB) && !rgba) { - std::cerr << "Found color type " << (int)info_ptr->color_type << std::endl; - throw Py::RuntimeError("_image_module::readpng: cannot handle color_type"); - } - /* read file */ if (setjmp(png_jmpbuf(png_ptr))) throw Py::RuntimeError("_image_module::readpng: error during read_image"); @@ -255,35 +254,34 @@ npy_intp dimensions[3]; dimensions[0] = height; //numrows dimensions[1] = width; //numcols - dimensions[2] = 4; + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + dimensions[2] = 4; //RGBA images + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + dimensions[2] = 3; //RGB images + else + dimensions[2] = 1; //Greyscale images + //For gray, return an x by y array, not an x by y by 1 + int num_dims = (info_ptr->color_type & PNG_COLOR_MASK_COLOR) ? 3 : 2; - PyArrayObject *A = (PyArrayObject *) PyArray_SimpleNew(3, dimensions, PyArray_FLOAT); + double max_value = (1 << ((bit_depth < 8) ? 8 : bit_depth)) - 1; + PyArrayObject *A = (PyArrayObject *) PyArray_SimpleNew(num_dims, dimensions, PyArray_FLOAT); - if (do_gray_conversion) { - float max_value = (float)((1L << bit_depth) - 1); - for (png_uint_32 y = 0; y < height; y++) { - png_byte* row = row_pointers[y]; - for (png_uint_32 x = 0; x < width; x++) { - float value = row[x] / max_value; - size_t offset = y*A->strides[0] + x*A->strides[1]; - *(float*)(A->data + offset + 0*A->strides[2]) = value; - *(float*)(A->data + offset + 1*A->strides[2]) = value; - *(float*)(A->data + offset + 2*A->strides[2]) = value; - *(float*)(A->data + offset + 3*A->strides[2]) = 1.0f; - } + for (png_uint_32 y = 0; y < height; y++) { + png_byte* row = row_pointers[y]; + for (png_uint_32 x = 0; x < width; x++) { + size_t offset = y*A->strides[0] + x*A->strides[1]; + if (bit_depth == 16) { + png_uint_16* ptr = &reinterpret_cast<png_uint_16*> (row)[x * dimensions[2]]; + for (png_uint_32 p = 0; p < dimensions[2]; p++) + *(float*)(A->data + offset + p*A->strides[2]) = (float)(ptr[p]) / max_value; + } else { + png_byte* ptr = &(row[x * dimensions[2]]); + for (png_uint_32 p = 0; p < dimensions[2]; p++) + { + *(float*)(A->data + offset + p*A->strides[2]) = (float)(ptr[p]) / max_value; + } + } } - } else { - for (png_uint_32 y = 0; y < height; y++) { - png_byte* row = row_pointers[y]; - for (png_uint_32 x = 0; x < width; x++) { - png_byte* ptr = (rgba) ? &(row[x*4]) : &(row[x*3]); - size_t offset = y*A->strides[0] + x*A->strides[1]; - *(float*)(A->data + offset + 0*A->strides[2]) = (float)(ptr[0]/255.0); - *(float*)(A->data + offset + 1*A->strides[2]) = (float)(ptr[1]/255.0); - *(float*)(A->data + offset + 2*A->strides[2]) = (float)(ptr[2]/255.0); - *(float*)(A->data + offset + 3*A->strides[2]) = rgba ? (float)(ptr[3]/255.0) : 1.0f; - } - } } //free the png memory This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7031 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7031&view=rev Author: astraw Date: 2009年04月05日 22:09:45 +0000 (2009年4月05日) Log Message: ----------- update changelog about Tobias' patch Modified Paths: -------------- branches/v0_98_5_maint/CHANGELOG Modified: branches/v0_98_5_maint/CHANGELOG =================================================================== --- branches/v0_98_5_maint/CHANGELOG 2009年04月05日 22:08:24 UTC (rev 7030) +++ branches/v0_98_5_maint/CHANGELOG 2009年04月05日 22:09:45 UTC (rev 7031) @@ -1,3 +1,6 @@ +2009年04月05日 _png.read_png() reads 12 bit PNGs (patch from + Tobias Wood) - ADS + 2009年03月17日 Fix bugs in edge color handling by contourf, found by Jae-Joon Lee. - EF This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7030 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7030&view=rev Author: astraw Date: 2009年04月05日 22:08:24 +0000 (2009年4月05日) Log Message: ----------- trivial: remove outdated comment Modified Paths: -------------- branches/v0_98_5_maint/lib/matplotlib/image.py Modified: branches/v0_98_5_maint/lib/matplotlib/image.py =================================================================== --- branches/v0_98_5_maint/lib/matplotlib/image.py 2009年04月05日 22:07:34 UTC (rev 7029) +++ branches/v0_98_5_maint/lib/matplotlib/image.py 2009年04月05日 22:08:24 UTC (rev 7030) @@ -720,8 +720,6 @@ <http://www.pythonware.com/products/pil/>`_ is installed, it will use it to load the image and return an array (if possible) which can be used with :func:`~matplotlib.pyplot.imshow`. - - TODO: support RGB and grayscale return values in _image.readpng """ def pilread(): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7029 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7029&view=rev Author: astraw Date: 2009年04月05日 22:07:34 +0000 (2009年4月05日) Log Message: ----------- trivial: remove trailing whitespace from source code Modified Paths: -------------- branches/v0_98_5_maint/src/_png.cpp Modified: branches/v0_98_5_maint/src/_png.cpp =================================================================== --- branches/v0_98_5_maint/src/_png.cpp 2009年04月05日 22:07:01 UTC (rev 7028) +++ branches/v0_98_5_maint/src/_png.cpp 2009年04月05日 22:07:34 UTC (rev 7029) @@ -214,7 +214,7 @@ png_uint_32 height = info_ptr->height; int bit_depth = info_ptr->bit_depth; - + // Unpack 1, 2, and 4-bit images if (bit_depth < 8) png_set_packing(png_ptr); @@ -231,7 +231,7 @@ // Convert palletes to full RGB if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); - + // If there's an alpha channel convert gray to RGB if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) png_set_gray_to_rgb(png_ptr); @@ -262,7 +262,7 @@ dimensions[2] = 1; //Greyscale images //For gray, return an x by y array, not an x by y by 1 int num_dims = (info_ptr->color_type & PNG_COLOR_MASK_COLOR) ? 3 : 2; - + double max_value = (1 << ((bit_depth < 8) ? 8 : bit_depth)) - 1; PyArrayObject *A = (PyArrayObject *) PyArray_SimpleNew(num_dims, dimensions, PyArray_FLOAT); @@ -283,7 +283,7 @@ } } } - + //free the png memory png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7028 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7028&view=rev Author: astraw Date: 2009年04月05日 22:07:01 +0000 (2009年4月05日) Log Message: ----------- read 12 bit PNGs (patch from Tobias Wood) Modified Paths: -------------- branches/v0_98_5_maint/src/_png.cpp Modified: branches/v0_98_5_maint/src/_png.cpp =================================================================== --- branches/v0_98_5_maint/src/_png.cpp 2009年04月05日 22:06:05 UTC (rev 7027) +++ branches/v0_98_5_maint/src/_png.cpp 2009年04月05日 22:07:01 UTC (rev 7028) @@ -208,38 +208,37 @@ png_init_io(png_ptr, fp); png_set_sig_bytes(png_ptr, 8); - png_read_info(png_ptr, info_ptr); png_uint_32 width = info_ptr->width; png_uint_32 height = info_ptr->height; - bool do_gray_conversion = (info_ptr->bit_depth < 8 && - info_ptr->color_type == PNG_COLOR_TYPE_GRAY); int bit_depth = info_ptr->bit_depth; - if (bit_depth == 16) { - png_set_strip_16(png_ptr); - } else if (bit_depth < 8) { + + // Unpack 1, 2, and 4-bit images + if (bit_depth < 8) png_set_packing(png_ptr); - } - // convert misc color types to rgb for simplicity - if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY || - info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) { - png_set_gray_to_rgb(png_ptr); - } else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { + // If sig bits are set, shift data + png_color_8p sig_bit; + if ((info_ptr->color_type != PNG_COLOR_TYPE_PALETTE) && png_get_sBIT(png_ptr, info_ptr, &sig_bit)) + png_set_shift(png_ptr, sig_bit); + + // Convert big endian to little + if (bit_depth == 16) + png_set_swap(png_ptr); + + // Convert palletes to full RGB + if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) png_set_palette_to_rgb(png_ptr); - } + + // If there's an alpha channel convert gray to RGB + if (info_ptr->color_type == PNG_COLOR_TYPE_GRAY_ALPHA) + png_set_gray_to_rgb(png_ptr); png_set_interlace_handling(png_ptr); png_read_update_info(png_ptr, info_ptr); - bool rgba = info_ptr->color_type == PNG_COLOR_TYPE_RGBA; - if ( (info_ptr->color_type != PNG_COLOR_TYPE_RGB) && !rgba) { - std::cerr << "Found color type " << (int)info_ptr->color_type << std::endl; - throw Py::RuntimeError("_image_module::readpng: cannot handle color_type"); - } - /* read file */ if (setjmp(png_jmpbuf(png_ptr))) throw Py::RuntimeError("_image_module::readpng: error during read_image"); @@ -255,37 +254,36 @@ npy_intp dimensions[3]; dimensions[0] = height; //numrows dimensions[1] = width; //numcols - dimensions[2] = 4; + if (info_ptr->color_type & PNG_COLOR_MASK_ALPHA) + dimensions[2] = 4; //RGBA images + else if (info_ptr->color_type & PNG_COLOR_MASK_COLOR) + dimensions[2] = 3; //RGB images + else + dimensions[2] = 1; //Greyscale images + //For gray, return an x by y array, not an x by y by 1 + int num_dims = (info_ptr->color_type & PNG_COLOR_MASK_COLOR) ? 3 : 2; + + double max_value = (1 << ((bit_depth < 8) ? 8 : bit_depth)) - 1; + PyArrayObject *A = (PyArrayObject *) PyArray_SimpleNew(num_dims, dimensions, PyArray_FLOAT); - PyArrayObject *A = (PyArrayObject *) PyArray_SimpleNew(3, dimensions, PyArray_FLOAT); - - if (do_gray_conversion) { - float max_value = (float)((1L << bit_depth) - 1); - for (png_uint_32 y = 0; y < height; y++) { - png_byte* row = row_pointers[y]; - for (png_uint_32 x = 0; x < width; x++) { - float value = row[x] / max_value; - size_t offset = y*A->strides[0] + x*A->strides[1]; - *(float*)(A->data + offset + 0*A->strides[2]) = value; - *(float*)(A->data + offset + 1*A->strides[2]) = value; - *(float*)(A->data + offset + 2*A->strides[2]) = value; - *(float*)(A->data + offset + 3*A->strides[2]) = 1.0f; - } + for (png_uint_32 y = 0; y < height; y++) { + png_byte* row = row_pointers[y]; + for (png_uint_32 x = 0; x < width; x++) { + size_t offset = y*A->strides[0] + x*A->strides[1]; + if (bit_depth == 16) { + png_uint_16* ptr = &reinterpret_cast<png_uint_16*> (row)[x * dimensions[2]]; + for (png_uint_32 p = 0; p < dimensions[2]; p++) + *(float*)(A->data + offset + p*A->strides[2]) = (float)(ptr[p]) / max_value; + } else { + png_byte* ptr = &(row[x * dimensions[2]]); + for (png_uint_32 p = 0; p < dimensions[2]; p++) + { + *(float*)(A->data + offset + p*A->strides[2]) = (float)(ptr[p]) / max_value; + } + } } - } else { - for (png_uint_32 y = 0; y < height; y++) { - png_byte* row = row_pointers[y]; - for (png_uint_32 x = 0; x < width; x++) { - png_byte* ptr = (rgba) ? &(row[x*4]) : &(row[x*3]); - size_t offset = y*A->strides[0] + x*A->strides[1]; - *(float*)(A->data + offset + 0*A->strides[2]) = (float)(ptr[0]/255.0); - *(float*)(A->data + offset + 1*A->strides[2]) = (float)(ptr[1]/255.0); - *(float*)(A->data + offset + 2*A->strides[2]) = (float)(ptr[2]/255.0); - *(float*)(A->data + offset + 3*A->strides[2]) = rgba ? (float)(ptr[3]/255.0) : 1.0f; - } - } } - + //free the png memory png_read_end(png_ptr, info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, png_infopp_NULL); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7027 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7027&view=rev Author: astraw Date: 2009年04月05日 22:06:05 +0000 (2009年4月05日) Log Message: ----------- pngsuite test: plot images in grayscale if the input array is 2 dimensional Modified Paths: -------------- branches/v0_98_5_maint/examples/tests/pngsuite/pngsuite.py Modified: branches/v0_98_5_maint/examples/tests/pngsuite/pngsuite.py =================================================================== --- branches/v0_98_5_maint/examples/tests/pngsuite/pngsuite.py 2009年04月05日 02:23:03 UTC (rev 7026) +++ branches/v0_98_5_maint/examples/tests/pngsuite/pngsuite.py 2009年04月05日 22:06:05 UTC (rev 7027) @@ -8,6 +8,7 @@ """ from matplotlib import pyplot as plt +import matplotlib.cm as cm import glob files = glob.glob("basn*.png") @@ -17,7 +18,11 @@ for i, fname in enumerate(files): data = plt.imread(fname) - plt.imshow(data, extent=[i,i+1,0,1]) + cmap = None # use default colormap + if data.ndim==2: + # keep grayscale images gray + cmap = cm.gray + plt.imshow(data, extent=[i,i+1,0,1], cmap=cmap) plt.gca().get_frame().set_facecolor("#ddffff") plt.gca().set_xlim(0, len(files)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
Revision: 7026 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7026&view=rev Author: efiring Date: 2009年04月05日 02:23:03 +0000 (2009年4月05日) Log Message: ----------- Merged revisions 7024-7025 via svnmerge from https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r7024 | efiring | 2009年04月04日 15:37:26 -1000 (2009年4月04日) | 2 lines Fix PatchCollection bug 2723527; thanks to Thomas Robitaille ........ r7025 | efiring | 2009年04月04日 16:16:44 -1000 (2009年4月04日) | 2 lines Fix PatchCollection bug 2732455 by letting to_rgba handle 'none' ........ Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/collections.py trunk/matplotlib/lib/matplotlib/colors.py Property Changed: ---------------- trunk/matplotlib/ trunk/matplotlib/doc/pyplots/README trunk/matplotlib/doc/sphinxext/gen_gallery.py trunk/matplotlib/doc/sphinxext/gen_rst.py trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py Property changes on: trunk/matplotlib ___________________________________________________________________ Modified: svnmerge-integrated - /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7018 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7025 Modified: svn:mergeinfo - /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018 + /branches/v0_91_maint:5753-5771 /branches/v0_98_5_maint:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6809,6811,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6906-6909,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025 Property changes on: trunk/matplotlib/doc/pyplots/README ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018 + /branches/v0_98_5_maint/doc/pyplots/README:6581,6585,6587,6589-6609,6614,6616,6625,6652,6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025 Property changes on: trunk/matplotlib/doc/sphinxext/gen_gallery.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018 + /branches/v0_91_maint/doc/_templates/gen_gallery.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_gallery.py:6660-6662,6672-6673,6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025 Property changes on: trunk/matplotlib/doc/sphinxext/gen_rst.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018 + /branches/v0_91_maint/doc/examples/gen_rst.py:5753-5771 /branches/v0_98_5_maint/doc/sphinxext/gen_rst.py:6714-6715,6717-6732,6752-6754,6761-6773,6781,6792,6800,6802,6805,6822,6827,6850,6854,6856,6859,6861-6873,6883-6884,6886,6890-6891,6911-6912,6915-6916,6918,6920-6925,6927-6928,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025 Modified: trunk/matplotlib/lib/matplotlib/collections.py =================================================================== --- trunk/matplotlib/lib/matplotlib/collections.py 2009年04月05日 02:16:44 UTC (rev 7025) +++ trunk/matplotlib/lib/matplotlib/collections.py 2009年04月05日 02:23:03 UTC (rev 7026) @@ -1126,7 +1126,7 @@ facecolors = [determine_facecolor(p) for p in patches] edgecolors = [p.get_edgecolor() for p in patches] - linewidths = [p.get_linewidths() for p in patches] + linewidths = [p.get_linewidth() for p in patches] antialiaseds = [p.get_antialiased() for p in patches] Collection.__init__( Modified: trunk/matplotlib/lib/matplotlib/colors.py =================================================================== --- trunk/matplotlib/lib/matplotlib/colors.py 2009年04月05日 02:16:44 UTC (rev 7025) +++ trunk/matplotlib/lib/matplotlib/colors.py 2009年04月05日 02:23:03 UTC (rev 7026) @@ -318,10 +318,18 @@ Returns an *RGBA* tuple of four floats from 0-1. For acceptable values of *arg*, see :meth:`to_rgb`. + In addition, if *arg* is "none" (case-insensitive), + then (0,0,0,0) will be returned. If *arg* is an *RGBA* sequence and *alpha* is not *None*, *alpha* will replace the original *A*. """ try: + if arg.lower() == 'none': + return (0.0, 0.0, 0.0, 0.0) + except AttributeError: + pass + + try: if not cbook.is_string_like(arg) and cbook.iterable(arg): if len(arg) == 4: if [x for x in arg if (float(x) < 0) or (x > 1)]: Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/mathmpl.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/mathmpl.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/mathmpl.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018 + /branches/v0_91_maint/doc/sphinxext/mathmpl.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/mathmpl.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025 Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/only_directives.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/only_directives.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/only_directives.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018 + /branches/v0_91_maint/doc/sphinxext/only_directives.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/only_directives.py:6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025 Property changes on: trunk/matplotlib/lib/matplotlib/sphinxext/plot_directive.py ___________________________________________________________________ Modified: svn:mergeinfo - /branches/v0_91_maint/doc/sphinxext/plot_directive.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py:6920-6925,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018 + /branches/v0_91_maint/doc/sphinxext/plot_directive.py:5753-5771 /branches/v0_98_5_maint/lib/matplotlib/sphinxext/plot_directive.py:6920-6925,6934,6941,6946,6948,6950,6952,6960,6972,6984-6985,6990,6995,6997-7001,7014,7016,7018,7024-7025 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.