From: <jd...@us...> - 2009-03-18 16:40:38
|
Revision: 6993 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6993&view=rev Author: jdh2358 Date: 2009-03-18 16:40:26 +0000 (Wed, 18 Mar 2009) Log Message: ----------- use urllib2 for yahoo finace; more cleanups to demo Modified Paths: -------------- trunk/matplotlib/examples/pylab_examples/finance_work2.py trunk/matplotlib/lib/matplotlib/finance.py Modified: trunk/matplotlib/examples/pylab_examples/finance_work2.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/finance_work2.py 2009-03-18 16:07:19 UTC (rev 6992) +++ trunk/matplotlib/examples/pylab_examples/finance_work2.py 2009-03-18 16:40:26 UTC (rev 6993) @@ -139,8 +139,8 @@ ax1.plot(r.date, rsi, color=fillcolor) ax1.axhline(70, color=fillcolor) ax1.axhline(30, color=fillcolor) -ax1.fill_between(r.date, rsi, 70, facecolor=fillcolor, where=(rsi>=70)) -ax1.fill_between(r.date, rsi, 30, facecolor=fillcolor, where=(rsi<=30)) +ax1.fill_between(r.date, rsi, 70, where=(rsi>=70), facecolor=fillcolor, edgecolor=fillcolor) +ax1.fill_between(r.date, rsi, 30, where=(rsi<=30), facecolor=fillcolor, edgecolor=fillcolor) ax1.text(0.6, 0.9, '>70 = overbought', va='top', transform=ax1.transAxes, fontsize=textsize) ax1.text(0.6, 0.1, '<30 = oversold', transform=ax1.transAxes, fontsize=textsize) ax1.set_ylim(0, 100) @@ -181,7 +181,7 @@ volume = (r.close*r.volume)/1e6 # dollar volume in millions vmax = volume.max() -poly = ax2t.fill_between(r.date, volume, 0, facecolor=fillcolor, label='Volume') +poly = ax2t.fill_between(r.date, volume, 0, label='Volume', facecolor=fillcolor, edgecolor=fillcolor) ax2t.set_ylim(0, 5*vmax) ax2t.set_yticks([]) @@ -195,14 +195,14 @@ ema9 = moving_average(macd, nema, type='exponential') ax3.plot(r.date, macd, color='black', lw=2) ax3.plot(r.date, ema9, color='blue', lw=1) -ax3.fill_between(r.date, macd-ema9, 0, facecolor=fillcolor, alpha=0.5) +ax3.fill_between(r.date, macd-ema9, 0, alpha=0.5, facecolor=fillcolor, edgecolor=fillcolor) ax3.text(0.025, 0.95, 'MACD (%d, %d, %d)'%(nfast, nslow, nema), va='top', transform=ax3.transAxes, fontsize=textsize) ax3.set_yticks([]) -# turn off tick labels, rorate them, etc +# turn off upper axis tick labels, rotate the lower ones, etc for ax in ax1, ax2, ax2t, ax3: if ax!=ax3: for label in ax.get_xticklabels(): Modified: trunk/matplotlib/lib/matplotlib/finance.py =================================================================== --- trunk/matplotlib/lib/matplotlib/finance.py 2009-03-18 16:07:19 UTC (rev 6992) +++ trunk/matplotlib/lib/matplotlib/finance.py 2009-03-18 16:40:26 UTC (rev 6993) @@ -5,7 +5,7 @@ """ #from __future__ import division import os, time, warnings -from urllib import urlopen +from urllib2 import urlopen try: from hashlib import md5 @@ -121,8 +121,10 @@ verbose.report('Using cachefile %s for %s'%(cachename, ticker)) else: if not os.path.isdir(cachedir): os.mkdir(cachedir) + urlfh = urlopen(url) + fh = file(cachename, 'w') - fh.write(urlopen(url).read()) + fh.write(urlfh.read()) fh.close() verbose.report('Saved %s data to cache file %s'%(ticker, cachename)) fh = file(cachename, 'r') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2009-03-19 12:55:12
|
Revision: 6996 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6996&view=rev Author: mdboom Date: 2009-03-19 12:55:07 +0000 (Thu, 19 Mar 2009) Log Message: ----------- Merged revisions 6995 via svnmerge from https://matplotlib.svn.sf.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r6995 | mdboom | 2009-03-19 08:52:46 -0400 (Thu, 19 Mar 2009) | 2 lines Fix wavy baseline with STIX fonts -- again. ........ Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/mathtext.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-6990 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-6995 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 + /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 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 + /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 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 + /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 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 + /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 Modified: trunk/matplotlib/lib/matplotlib/mathtext.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mathtext.py 2009-03-19 12:52:46 UTC (rev 6995) +++ trunk/matplotlib/lib/matplotlib/mathtext.py 2009-03-19 12:55:07 UTC (rev 6996) @@ -201,7 +201,7 @@ def render_glyph(self, ox, oy, info): info.font.draw_glyph_to_bitmap( - self.image, ox, oy - info.metrics.ymax, info.glyph) + self.image, ox, oy - info.metrics.iceberg, info.glyph) def render_rect_filled(self, x1, y1, x2, y2): height = max(int(y2 - y1) - 1, 0) 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 + /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 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 + /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 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 + /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 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lee...@us...> - 2009-03-20 20:10:56
|
Revision: 6999 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=6999&view=rev Author: leejjoon Date: 2009-03-20 20:10:42 +0000 (Fri, 20 Mar 2009) Log Message: ----------- Add bar connection style for annotation Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/examples/pylab_examples/annotation_demo2.py trunk/matplotlib/lib/matplotlib/patches.py trunk/matplotlib/lib/matplotlib/text.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-03-19 14:44:01 UTC (rev 6998) +++ trunk/matplotlib/CHANGELOG 2009-03-20 20:10:42 UTC (rev 6999) @@ -1,3 +1,5 @@ +2009-03-20 Add "bar" connection style for annotation - JJL + 2009-03-17 Fix bugs in edge color handling by contourf, found by Jae-Joon Lee. - EF Modified: trunk/matplotlib/examples/pylab_examples/annotation_demo2.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/annotation_demo2.py 2009-03-19 14:44:01 UTC (rev 6998) +++ trunk/matplotlib/examples/pylab_examples/annotation_demo2.py 2009-03-20 20:10:42 UTC (rev 6999) @@ -71,6 +71,14 @@ ) + ann = ax.annotate('', xy=(4., 1.), xycoords='data', + xytext=(4.5, -1), textcoords='data', + arrowprops=dict(arrowstyle="<->", + connectionstyle="bar", + ec="k", + shrinkA=5, shrinkB=5, + ) + ) if 1: @@ -144,4 +152,5 @@ ) ) + show() Modified: trunk/matplotlib/lib/matplotlib/patches.py =================================================================== --- trunk/matplotlib/lib/matplotlib/patches.py 2009-03-19 14:44:01 UTC (rev 6998) +++ trunk/matplotlib/lib/matplotlib/patches.py 2009-03-20 20:10:42 UTC (rev 6999) @@ -2545,6 +2545,92 @@ _style_list["arc"] = Arc + + + class Bar(_Base): + """ + A line with *angle* between A and B with *armA* and + *armB*. One of the arm is extend so that they are connected in + a right angle. The length of armA is determined by (*armA* + + *fraction* x AB distance). Same for armB. + """ + + def __init__(self, armA=0., armB=0., fraction=0.3, angle=None): + """ + *armA* : minimum length of armA + *armB* : minimum length of armB + *fraction* : a fraction of the distance between two points that will be added to armA and armB. + *angle* : anlge of the connecting line (if None, parallel to A and B) + """ + self.armA = armA + self.armB = armB + self.fraction = fraction + self.angle = angle + + def connect(self, posA, posB): + x1, y1 = posA + x20, y20 = x2, y2 = posB + + x12, y12 = (x1 + x2)/2., (y1 + y2)/2. + + theta1 = math.atan2(y2-y1, x2-x1) + dx, dy = x2 - x1, y2 - y1 + dd = (dx*dx + dy*dy)**.5 + ddx, ddy = dx/dd, dy/dd + + armA, armB = self.armA, self.armB + + if self.angle is not None: + #angle = self.angle % 180. + #if angle < 0. or angle > 180.: + # angle + theta0 = (self.angle%180.)/180.*math.pi + #theta0 = (((self.angle+90)%180.) - 90.)/180.*math.pi + dtheta = theta1 - theta0 + dl = dd*math.sin(dtheta) + + dL = dd*math.cos(dtheta) + + #x2, y2 = x2 + dl*ddy, y2 - dl*ddx + x2, y2 = x1 + dL*math.cos(theta0), y1 + dL*math.sin(theta0) + + armB = armB - dl + + # update + dx, dy = x2 - x1, y2 - y1 + dd2 = (dx*dx + dy*dy)**.5 + ddx, ddy = dx/dd2, dy/dd2 + + else: + dl = 0. + + #if armA > armB: + # armB = armA + dl + #else: + # armA = armB - dl + + + arm = max(armA, armB) + f = self.fraction*dd + arm + #fB = self.fraction*dd + armB + + cx1, cy1 = x1 + f*ddy, y1 - f*ddx + cx2, cy2 = x2 + f*ddy, y2 - f*ddx + + vertices = [(x1, y1), + (cx1, cy1), + (cx2, cy2), + (x20, y20)] + codes = [Path.MOVETO, + Path.LINETO, + Path.LINETO, + Path.LINETO] + + return Path(vertices, codes) + + _style_list["bar"] = Bar + + __doc__ = cbook.dedent(__doc__) % \ {"AvailableConnectorstyles": _pprint_styles(_style_list)} Modified: trunk/matplotlib/lib/matplotlib/text.py =================================================================== --- trunk/matplotlib/lib/matplotlib/text.py 2009-03-19 14:44:01 UTC (rev 6998) +++ trunk/matplotlib/lib/matplotlib/text.py 2009-03-20 20:10:42 UTC (rev 6999) @@ -406,6 +406,10 @@ props = props.copy() # don't want to alter the pad externally pad = props.pop('pad', 4) pad = renderer.points_to_pixels(pad) + if self._text == "": + self.arrow_patch.set_patchA(None) + return + bbox = self.get_window_extent(renderer) l,b,w,h = bbox.bounds l-=pad/2. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <lee...@us...> - 2009-03-20 20:26:10
|
Revision: 7000 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7000&view=rev Author: leejjoon Date: 2009-03-20 20:26:00 +0000 (Fri, 20 Mar 2009) Log Message: ----------- Add AuxTransformBox in offsetbox.py Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/offsetbox.py Added Paths: ----------- trunk/matplotlib/examples/pylab_examples/anchored_artists.py Removed Paths: ------------- trunk/matplotlib/examples/pylab_examples/anchored_text.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-03-20 20:10:42 UTC (rev 6999) +++ trunk/matplotlib/CHANGELOG 2009-03-20 20:26:00 UTC (rev 7000) @@ -1,3 +1,7 @@ +2009-03-20 Add AuxTransformBox in offsetbox.py to support some transformation. + anchored_text.py example is enhanced and renamed + (anchored_artists.py). - JJL + 2009-03-20 Add "bar" connection style for annotation - JJL 2009-03-17 Fix bugs in edge color handling by contourf, found Copied: trunk/matplotlib/examples/pylab_examples/anchored_artists.py (from rev 6998, trunk/matplotlib/examples/pylab_examples/anchored_text.py) =================================================================== --- trunk/matplotlib/examples/pylab_examples/anchored_artists.py (rev 0) +++ trunk/matplotlib/examples/pylab_examples/anchored_artists.py 2009-03-20 20:26:00 UTC (rev 7000) @@ -0,0 +1,117 @@ +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, frameon=True): + + self.txt = TextArea(s, + minimumdescent=False) + + + super(AnchoredText, self).__init__(loc, pad=pad, borderpad=borderpad, + child=self.txt, + prop=prop, + frameon=frameon) + + +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 + + 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) + + 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) + + # 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) + + # 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) + + plt.draw() + plt.show() + + + + Deleted: trunk/matplotlib/examples/pylab_examples/anchored_text.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/anchored_text.py 2009-03-20 20:10:42 UTC (rev 6999) +++ trunk/matplotlib/examples/pylab_examples/anchored_text.py 2009-03-20 20:26:00 UTC (rev 7000) @@ -1,183 +0,0 @@ -""" -Place a text (or any offsetbox artist) at the corner of the axes, like a lenged. -""" - -from matplotlib.offsetbox import TextArea, OffsetBox, DrawingArea -from matplotlib.transforms import Bbox -from matplotlib.font_manager import FontProperties -from matplotlib import rcParams -from matplotlib.patches import FancyBboxPatch -from matplotlib.patches import Circle - - -class AnchoredOffsetbox(OffsetBox): - def __init__(self, loc, pad=0.4, borderpad=0.5, - child=None, fontsize=None, frameon=True): - - super(AnchoredOffsetbox, self).__init__() - - self.set_child(child) - - self.loc = loc - self.borderpad=borderpad - self.pad = pad - - if fontsize is None: - prop=FontProperties(size=rcParams["legend.fontsize"]) - self._fontsize = prop.get_size_in_points() - else: - self._fontsize = fontsize - - - - self.patch = FancyBboxPatch( - xy=(0.0, 0.0), width=1., height=1., - facecolor='w', edgecolor='k', - mutation_scale=self._fontsize, - snap=True - ) - self.patch.set_boxstyle("square",pad=0) - self._drawFrame = frameon - - def set_child(self, child): - self._child = child - - def get_children(self): - return [self._child] - - def get_child(self): - return self._child - - def get_extent(self, renderer): - w, h, xd, yd = self.get_child().get_extent(renderer) - fontsize = renderer.points_to_pixels(self._fontsize) - pad = self.pad * fontsize - - return w+2*pad, h+2*pad, xd+pad, yd+pad - - def get_window_extent(self, renderer): - ''' - get the bounding box in display space. - ''' - 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 - - fontsize = renderer.points_to_pixels(self._fontsize) - - def _offset(w, h, xd, yd, fontsize=fontsize, self=self): - bbox = Bbox.from_bounds(0, 0, w, h) - borderpad = self.borderpad*fontsize - x0, y0 = self._get_anchored_bbox(self.loc, - bbox, - self.axes.bbox, - borderpad) - return x0+xd, y0+yd - - self.set_offset(_offset) - - if self._drawFrame: - # update the location and size of the legend - bbox = self.get_window_extent(renderer) - self.patch.set_bounds(bbox.x0, bbox.y0, - bbox.width, bbox.height) - - self.patch.set_mutation_scale(fontsize) - - self.patch.draw(renderer) - - - width, height, xdescent, ydescent = self.get_extent(renderer) - - px, py = self.get_offset(width, height, xdescent, ydescent) - - self.get_child().set_offset((px, py)) - self.get_child().draw(renderer) - - - - def _get_anchored_bbox(self, loc, bbox, parentbbox, borderpad): - assert loc in range(1,11) # called only internally - - BEST, UR, UL, LL, LR, R, CL, CR, LC, UC, C = range(11) - - anchor_coefs={UR:"NE", - UL:"NW", - LL:"SW", - LR:"SE", - R:"E", - CL:"W", - CR:"E", - LC:"S", - UC:"N", - C:"C"} - - c = anchor_coefs[loc] - - container = parentbbox.padded(-borderpad) - anchored_box = bbox.anchored(c, container=container) - return anchored_box.x0, anchored_box.y0 - - -class AnchoredText(AnchoredOffsetbox): - def __init__(self, s, loc, pad=0.4, borderpad=0.5, prop=None, frameon=True): - - self.txt = TextArea(s, - minimumdescent=False) - - - if prop is None: - self.prop=FontProperties(size=rcParams["legend.fontsize"]) - else: - self.prop=prop - - - super(AnchoredText, self).__init__(loc, pad=pad, borderpad=borderpad, - child=self.txt, - fontsize=self.prop.get_size_in_points(), - frameon=frameon) - - -class AnchoredDrawingArea(AnchoredOffsetbox): - def __init__(self, width, height, xdescent, ydescent, - loc, pad=0.4, borderpad=0.5, fontsize=None, frameon=True): - - self.da = DrawingArea(width, height, xdescent, ydescent, clip=True) - - super(AnchoredDrawingArea, self).__init__(loc, pad=pad, borderpad=borderpad, - child=self.da, - fontsize=fontsize, - frameon=frameon) - - - -if __name__ == "__main__": - import matplotlib.pyplot as plt - - #ax = plt.subplot(1,1,1) - plt.clf() - plt.cla() - plt.draw() - ax = plt.gca() - #ax.set_aspect(1.) - - at = AnchoredText("Figure 1(a)", loc=2, frameon=False) - ax.add_artist(at) - - ada = AnchoredDrawingArea(20, 20, 0, 0, loc=3, pad=0., frameon=False) - - p = Circle((10, 10), 10) - ada.da.add_artist(p) - ax.add_artist(ada) - - ax.plot([0,1]) - plt.draw() - - plt.show() - - - Modified: trunk/matplotlib/lib/matplotlib/offsetbox.py =================================================================== --- trunk/matplotlib/lib/matplotlib/offsetbox.py 2009-03-20 20:10:42 UTC (rev 6999) +++ trunk/matplotlib/lib/matplotlib/offsetbox.py 2009-03-20 20:26:00 UTC (rev 7000) @@ -656,3 +656,228 @@ bbox_artist(self, renderer, fill=False, props=dict(pad=0.)) + + +class AuxTransformBox(OffsetBox): + """ + Offset Box with the aux_transform . Its children will be + transformed with the aux_transform first then will be + offseted. The absolute coordinate of the aux_transform is meaning + as it will be automaticcaly adjust so that the left-lower corner + of the bounding box of children will be set to (0,0) before the + offset trnasform. + + It is similar to drawing area, except that the extent of the box + is not predetemined but calculated from the window extent of its + children. Furthermore, the extent of the children will be + calculated in the transformed coordinate. + """ + + def __init__(self, aux_transform): + self.aux_transform = aux_transform + OffsetBox.__init__(self) + + self.offset_transform = mtransforms.Affine2D() + self.offset_transform.clear() + self.offset_transform.translate(0, 0) + + # ref_offset_transform is used to make the offset_transform is + # always reference to the lower-left corner of the bbox of its + # children. + self.ref_offset_transform = mtransforms.Affine2D() + self.ref_offset_transform.clear() + + def add_artist(self, a): + 'Add any :class:`~matplotlib.artist.Artist` to the container box' + self._children.append(a) + a.set_transform(self.get_transform()) + + def get_transform(self): + """ + Return the :class:`~matplotlib.transforms.Transform` applied + to the children + """ + + return self.aux_transform + \ + self.ref_offset_transform + \ + self.offset_transform + + def set_transform(self, t): + """ + set_transform is ignored. + """ + pass + + + def set_offset(self, xy): + """ + set offset of the container. + + Accept : tuple of x,y cooridnate in disokay units. + """ + self._offset = xy + + self.offset_transform.clear() + self.offset_transform.translate(xy[0], xy[1]) + + + def get_offset(self): + """ + return offset of the container. + """ + return self._offset + + + def get_window_extent(self, renderer): + ''' + get the bounding box in display space. + ''' + w, h, xd, yd = self.get_extent(renderer) + ox, oy = self.get_offset() #w, h, xd, yd) + return mtransforms.Bbox.from_bounds(ox-xd, oy-yd, w, h) + + + def get_extent(self, renderer): + + # clear the offset transforms + _off = self.ref_offset_transform.to_values() # to be restored later + self.ref_offset_transform.clear() + self.offset_transform.clear() + + # calculate the extent + bboxes = [c.get_window_extent(renderer) for c in self._children] + ub = mtransforms.Bbox.union(bboxes) + + + # adjust ref_offset_tansform + 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. + + + def draw(self, renderer): + """ + Draw the children + """ + + for c in self._children: + c.draw(renderer) + + 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): + def __init__(self, loc, pad=0.4, borderpad=0.5, + child=None, prop=None, frameon=True): + + super(AnchoredOffsetbox, self).__init__() + + self.set_child(child) + + self.loc = loc + self.borderpad=borderpad + self.pad = pad + + if prop is None: + 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', + mutation_scale=self.prop.get_size_in_points(), + snap=True + ) + self.patch.set_boxstyle("square",pad=0) + self._drawFrame = frameon + + def set_child(self, child): + self._child = child + + def get_children(self): + return [self._child] + + def get_child(self): + return self._child + + def get_extent(self, renderer): + 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_window_extent(self, renderer): + ''' + get the bounding box in display space. + ''' + 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 + + 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 + x0, y0 = self._get_anchored_bbox(self.loc, + bbox, + self.axes.bbox, + borderpad) + return x0+xd, y0+yd + + self.set_offset(_offset) + + if self._drawFrame: + # update the location and size of the legend + bbox = self.get_window_extent(renderer) + self.patch.set_bounds(bbox.x0, bbox.y0, + bbox.width, bbox.height) + + self.patch.set_mutation_scale(fontsize) + + self.patch.draw(renderer) + + + width, height, xdescent, ydescent = self.get_extent(renderer) + + px, py = self.get_offset(width, height, xdescent, ydescent) + + self.get_child().set_offset((px, py)) + self.get_child().draw(renderer) + + + + def _get_anchored_bbox(self, loc, bbox, parentbbox, borderpad): + assert loc in range(1,11) # called only internally + + BEST, UR, UL, LL, LR, R, CL, CR, LC, UC, C = range(11) + + anchor_coefs={UR:"NE", + UL:"NW", + LL:"SW", + LR:"SE", + R:"E", + CL:"W", + CR:"E", + LC:"S", + UC:"N", + C:"C"} + + c = anchor_coefs[loc] + + container = parentbbox.padded(-borderpad) + anchored_box = bbox.anchored(c, container=container) + return anchored_box.x0, anchored_box.y0 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2009-03-23 19:18:43
|
Revision: 7002 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7002&view=rev Author: mdboom Date: 2009-03-23 19:18:35 +0000 (Mon, 23 Mar 2009) Log Message: ----------- Merged revisions 6997,7001 via svnmerge from https://matplotlib.svn.sf.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r6997 | mdboom | 2009-03-19 09:15:00 -0400 (Thu, 19 Mar 2009) | 2 lines Fix bug in Cairo backend related to clipping -- thanks Nathaniel Smith ........ r7001 | ryanmay | 2009-03-23 14:52:29 -0400 (Mon, 23 Mar 2009) | 1 line Fix typo. Thanks to Sandro Tosi. ........ Modified Paths: -------------- trunk/matplotlib/doc/users/screenshots.rst trunk/matplotlib/lib/matplotlib/backends/backend_cairo.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-6995 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7001 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 + /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 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 + /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 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 + /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 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 + /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 Modified: trunk/matplotlib/doc/users/screenshots.rst =================================================================== --- trunk/matplotlib/doc/users/screenshots.rst 2009-03-23 18:52:29 UTC (rev 7001) +++ trunk/matplotlib/doc/users/screenshots.rst 2009-03-23 19:18:35 UTC (rev 7002) @@ -82,7 +82,7 @@ ========== The :func:`~matplotlib.pyplot.pie` command -uses a matlab(TM) compatible syntax to produce py charts. Optional +uses a matlab(TM) compatible syntax to produce pie charts. Optional features include auto-labeling the percentage of area, exploding one or more wedges out from the center of the pie, and a shadow effect. Take a close look at the attached code that produced this figure; nine @@ -268,6 +268,3 @@ :ref:`user_interfaces-mpl_with_glade`. .. image:: ../_static/eeg_small.png - - - Modified: trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py 2009-03-23 18:52:29 UTC (rev 7001) +++ trunk/matplotlib/lib/matplotlib/backends/backend_cairo.py 2009-03-23 19:18:35 UTC (rev 7002) @@ -109,6 +109,23 @@ # font transform? + def _do_clip(self, ctx, cliprect, clippath): + if cliprect is not None: + x,y,w,h = cliprect.bounds + # pixel-aligned clip-regions are faster + x,y,w,h = round(x), round(y), round(w), round(h) + ctx.new_path() + ctx.rectangle (x, self.height - h - y, w, h) + ctx.clip () + + if clippath is not None: + tpath, affine = clippath.get_transformed_path_and_affine() + ctx.new_path() + affine = affine + Affine2D().scale(1.0, -1.0).translate(0.0, self.height) + tpath = affine.transform_path(tpath) + RendererCairo.convert_path(ctx, tpath) + ctx.clip() + def _fill_and_stroke (self, ctx, fill_c, alpha): if fill_c is not None: ctx.save() @@ -120,7 +137,6 @@ ctx.restore() ctx.stroke() - @staticmethod def convert_path(ctx, path, transform): for points, code in path.iter_segments(transform): @@ -143,6 +159,9 @@ raise ValueError("The Cairo backend can not draw paths longer than 18980 points.") ctx = gc.ctx + ctx.save() + self._do_clip(ctx, gc._cliprect, gc._clippath) + transform = transform + \ Affine2D().scale(1.0, -1.0).translate(0, self.height) @@ -150,6 +169,7 @@ self.convert_path(ctx, path, transform) self._fill_and_stroke(ctx, rgbFace, gc.get_alpha()) + ctx.restore() def draw_image(self, x, y, im, bbox, clippath=None, clippath_trans=None): # bbox - not currently used @@ -162,9 +182,16 @@ buf, cairo.FORMAT_ARGB32, cols, rows, cols*4) # function does not pass a 'gc' so use renderer.ctx ctx = self.ctx + ctx.save() + if clippath is not None: + tpath = clippath_trans.transform_path(clippath) + ctx.new_path() + RendererCairo.convert_path(ctx, tpath) + ctx.clip() y = self.height - y - rows ctx.set_source_surface (surface, x, y) ctx.paint() + ctx.restore() im.flipud_out() @@ -322,30 +349,10 @@ def set_clip_rectangle(self, rectangle): self._cliprect = rectangle - if rectangle is None: - return - x,y,w,h = rectangle.bounds - # pixel-aligned clip-regions are faster - x,y,w,h = round(x), round(y), round(w), round(h) - ctx = self.ctx - ctx.new_path() - ctx.rectangle (x, self.renderer.height - h - y, w, h) - ctx.clip () - # Alternative: just set _cliprect here and actually set cairo clip rect - # in fill_and_stroke() inside ctx.save() ... ctx.restore() - - def set_clip_path(self, path): - if path is not None: - tpath, affine = path.get_transformed_path_and_affine() - ctx = self.ctx - ctx.new_path() - affine = affine + Affine2D().scale(1.0, -1.0).translate(0.0, self.renderer.height) - RendererCairo.convert_path(ctx, path, affine) - ctx.clip() + self._clippath = path - def set_dashes(self, offset, dashes): self._dashes = offset, dashes if dashes == None: 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 + /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 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 + /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 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 + /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 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2009-03-24 01:49:26
|
Revision: 7003 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7003&view=rev Author: jdh2358 Date: 2009-03-24 01:49:18 +0000 (Tue, 24 Mar 2009) Log Message: ----------- added prune option to maxnlocataor; updated finance demo Modified Paths: -------------- trunk/matplotlib/examples/pylab_examples/finance_work2.py trunk/matplotlib/lib/matplotlib/ticker.py Modified: trunk/matplotlib/examples/pylab_examples/finance_work2.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/finance_work2.py 2009-03-23 19:18:35 UTC (rev 7002) +++ trunk/matplotlib/examples/pylab_examples/finance_work2.py 2009-03-24 01:49:18 UTC (rev 7003) @@ -201,7 +201,7 @@ ax3.text(0.025, 0.95, 'MACD (%d, %d, %d)'%(nfast, nslow, nema), va='top', transform=ax3.transAxes, fontsize=textsize) -ax3.set_yticks([]) +#ax3.set_yticks([]) # turn off upper axis tick labels, rotate the lower ones, etc for ax in ax1, ax2, ax2t, ax3: if ax!=ax3: @@ -215,15 +215,11 @@ ax.fmt_xdata = mdates.DateFormatter('%Y-%m-%d') -class PriceFormatter(mticker.FormatStrFormatter): - 'suppress the lowest tick label to prevent overlap' - def __call__(self, x, pos=None): - if pos==0: - return '' - else: - return mticker.FormatStrFormatter.__call__(self, x, pos=None) -ax2.yaxis.set_major_formatter(PriceFormatter('%d')) +# 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')) plt.show() Modified: trunk/matplotlib/lib/matplotlib/ticker.py =================================================================== --- trunk/matplotlib/lib/matplotlib/ticker.py 2009-03-23 19:18:35 UTC (rev 7002) +++ trunk/matplotlib/lib/matplotlib/ticker.py 2009-03-24 01:49:18 UTC (rev 7003) @@ -913,13 +913,27 @@ """ def __init__(self, nbins = 10, steps = None, - trim = True, - integer=False, - symmetric=False): + trim = True, + integer=False, + symmetric=False, + prune=None): + """ + Keyword args: + *prune* + Remove edge ticks -- useful for stacked or ganed plots + where the upper tick of one axes overlaps with the lower + tick of the axes above it. one of 'lower' | 'upper'| + 'both' | None. If prune=='lower', the smallest tick will + be removed. If prune=='upper', the largest tick will be + removed. If prune=='both', the largest and smallest ticks + will be removed. If prune==None, no ticks will be removed + + """ self._nbins = int(nbins) self._trim = trim self._integer = integer self._symmetric = symmetric + self._prune = prune if steps is None: self._steps = [1, 1.5, 2, 2.5, 3, 4, 5, 6, 8, 10] else: @@ -957,7 +971,16 @@ def __call__(self): vmin, vmax = self.axis.get_view_interval() vmin, vmax = mtransforms.nonsingular(vmin, vmax, expander = 0.05) - return self.bin_boundaries(vmin, vmax) + locs = self.bin_boundaries(vmin, vmax) + #print 'locs=', locs + prune = self._prune + if prune=='lower': + locs = locs[1:] + elif prune=='upper': + locs = locs[:-1] + elif prune=='both': + locs = locs[1:-1] + return locs def view_limits(self, dmin, dmax): if self._symmetric: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2009-03-25 19:27:32
|
Revision: 7005 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7005&view=rev Author: efiring Date: 2009-03-25 19:27:28 +0000 (Wed, 25 Mar 2009) Log Message: ----------- Contouring handles nans in Z via masking. (The bug in filled contouring with internal masked regions remains.) Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/examples/pylab_examples/contourf_demo.py trunk/matplotlib/lib/matplotlib/contour.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-03-24 01:57:26 UTC (rev 7004) +++ trunk/matplotlib/CHANGELOG 2009-03-25 19:27:28 UTC (rev 7005) @@ -1,5 +1,7 @@ -2009-03-20 Add AuxTransformBox in offsetbox.py to support some transformation. - anchored_text.py example is enhanced and renamed +2009-03-25 Make contour and contourf handle nan in their Z argument. - EF + +2009-03-20 Add AuxTransformBox in offsetbox.py to support some transformation. + anchored_text.py example is enhanced and renamed (anchored_artists.py). - JJL 2009-03-20 Add "bar" connection style for annotation - JJL Modified: trunk/matplotlib/examples/pylab_examples/contourf_demo.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/contourf_demo.py 2009-03-24 01:57:26 UTC (rev 7004) +++ trunk/matplotlib/examples/pylab_examples/contourf_demo.py 2009-03-25 19:27:28 UTC (rev 7005) @@ -3,7 +3,9 @@ origin = 'lower' #origin = 'upper' -test_masking = False # There is a bug in filled contour masking. +# The following controls only interior masking. +test_masking = False # There is a bug in filled contour masking with + # interior masks. if test_masking: # Use a coarse grid so only a few masked points are needed. @@ -30,6 +32,18 @@ Z[0,0] = 0 Z = ma.array(Z, mask=badmask) +nr, nc = Z.shape + +# put NaNs in one corner: +Z[-nr//6:, -nc//6:] = nan +# contourf will convert these to masked + + +Z = ma.array(Z) +# mask another corner: +Z[:nr//6, :nc//6] = ma.masked + + # We are using automatic selection of contour levels; # this is usually not such a good idea, because they don't # occur on nice boundaries, but we do it here for purposes @@ -48,7 +62,7 @@ origin=origin, hold='on') -title('Nonsense') +title('Nonsense (with 2 masked corners)') xlabel('word length anomaly') ylabel('sentence length anomaly') @@ -72,7 +86,7 @@ colors = ('k',), linewidths = (3,), origin = origin) -title('Listed colors') +title('Listed colors (with 2 masked corners)') clabel(CS4, fmt = '%2.1f', colors = 'w', fontsize=14) colorbar(CS3) Modified: trunk/matplotlib/lib/matplotlib/contour.py =================================================================== --- trunk/matplotlib/lib/matplotlib/contour.py 2009-03-24 01:57:26 UTC (rev 7004) +++ trunk/matplotlib/lib/matplotlib/contour.py 2009-03-25 19:27:28 UTC (rev 7005) @@ -756,6 +756,7 @@ x,y,z = self._check_xyz(args[:3]) else: raise TypeError("Too many arguments to %s; see help(%s)" % (fn,fn)) + z = ma.masked_invalid(z, copy=False) self.zmax = ma.maximum(z) self.zmin = ma.minimum(z) if self.logscale and self.zmin <= 0: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <js...@us...> - 2009-03-27 21:10:51
|
Revision: 7007 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7007&view=rev Author: jswhit Date: 2009-03-27 21:10:24 +0000 (Fri, 27 Mar 2009) Log Message: ----------- changed name of lightsource class to LightSource to conform to coding guidelines. Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/examples/pylab_examples/shading_example.py trunk/matplotlib/lib/matplotlib/colors.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-03-27 18:11:18 UTC (rev 7006) +++ trunk/matplotlib/CHANGELOG 2009-03-27 21:10:24 UTC (rev 7007) @@ -9,7 +9,7 @@ 2009-03-17 Fix bugs in edge color handling by contourf, found by Jae-Joon Lee. - EF -2009-03-14 Added 'lightsource' class to colors module for +2009-03-14 Added 'LightSource' class to colors module for creating shaded relief maps. shading_example.py added to illustrate usage. - JSW Modified: trunk/matplotlib/examples/pylab_examples/shading_example.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/shading_example.py 2009-03-27 18:11:18 UTC (rev 7006) +++ trunk/matplotlib/examples/pylab_examples/shading_example.py 2009-03-27 21:10:24 UTC (rev 7007) @@ -1,6 +1,6 @@ import numpy as np import matplotlib.pyplot as plt -from matplotlib.colors import lightsource +from matplotlib.colors import LightSource # example showing how to make shaded relief plots # like mathematica @@ -12,7 +12,7 @@ X,Y=np.mgrid[-5:5:0.05,-5:5:0.05] Z=np.sqrt(X**2+Y**2)+np.sin(X**2+Y**2) # creat light source object. -ls = lightsource(azdeg=0,altdeg=65) +ls = LightSource(azdeg=0,altdeg=65) # shade data, creating an rgb array. rgb = ls.shade(Z,plt.cm.copper) # plot un-shaded and shaded images. Modified: trunk/matplotlib/lib/matplotlib/colors.py =================================================================== --- trunk/matplotlib/lib/matplotlib/colors.py 2009-03-27 18:11:18 UTC (rev 7006) +++ trunk/matplotlib/lib/matplotlib/colors.py 2009-03-27 21:10:24 UTC (rev 7007) @@ -955,7 +955,7 @@ rgb[:,:,0]=r; rgb[:,:,1]=g; rgb[:,:,2]=b return rgb -class lightsource(object): +class LightSource(object): """ Create a light source coming from the specified azimuth and elevation. Angles are in degrees, with the azimuth measured This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2009-03-28 21:13:47
|
Revision: 7010 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7010&view=rev Author: efiring Date: 2009-03-28 21:13:38 +0000 (Sat, 28 Mar 2009) Log Message: ----------- Make images handle invalid values as if masked. A little cleanup and docstring addition to image.py was included. Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/lib/matplotlib/cbook.py trunk/matplotlib/lib/matplotlib/image.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-03-28 00:59:44 UTC (rev 7009) +++ trunk/matplotlib/CHANGELOG 2009-03-28 21:13:38 UTC (rev 7010) @@ -1,3 +1,6 @@ +2009-03-28 Make images handle nan in their array argument. + A helper, cbook.safe_masked_invalid() was added. - EF + 2009-03-25 Make contour and contourf handle nan in their Z argument. - EF 2009-03-20 Add AuxTransformBox in offsetbox.py to support some transformation. Modified: trunk/matplotlib/lib/matplotlib/cbook.py =================================================================== --- trunk/matplotlib/lib/matplotlib/cbook.py 2009-03-28 00:59:44 UTC (rev 7009) +++ trunk/matplotlib/lib/matplotlib/cbook.py 2009-03-28 21:13:38 UTC (rev 7010) @@ -933,6 +933,15 @@ except TypeError: return False +def safe_masked_invalid(x): + x = np.asanyarray(x) + try: + xm = np.ma.masked_invalid(x, copy=False) + xm.shrink_mask() + except TypeError: + return x + return xm + class MemoryMonitor: def __init__(self, nmax=20000): self._nmax = nmax Modified: trunk/matplotlib/lib/matplotlib/image.py =================================================================== --- trunk/matplotlib/lib/matplotlib/image.py 2009-03-28 00:59:44 UTC (rev 7009) +++ trunk/matplotlib/lib/matplotlib/image.py 2009-03-28 21:13:38 UTC (rev 7010) @@ -10,13 +10,14 @@ from numpy import ma from matplotlib import rcParams -from matplotlib import artist as martist -from matplotlib import colors as mcolors -from matplotlib import cm +import matplotlib.artist as martist +import matplotlib.colors as mcolors +import matplotlib.cm as cm +import matplotlib.cbook as cbook # For clarity, names from _image are given explicitly in this module: -from matplotlib import _image -from matplotlib import _png +import matplotlib._image as _image +import matplotlib._png as _png # For user convenience, the names from _image are also imported into # the image namespace: @@ -238,8 +239,9 @@ clippath, affine) def contains(self, mouseevent): - """Test whether the mouse event occured within the image. """ + Test whether the mouse event occured within the image. + """ if callable(self._contains): return self._contains(self,mouseevent) # TODO: make sure this is consistent with patch and patch # collection on nonlinear transformed coordinates. @@ -271,18 +273,17 @@ rows, cols, buffer = im.as_rgba_str() _png.write_png(buffer, cols, rows, fname) - def set_data(self, A, shape=None): + def set_data(self, A): """ Set the image array - ACCEPTS: numpy/PIL Image A""" + ACCEPTS: numpy/PIL Image A + """ # check if data is PIL Image without importing Image if hasattr(A,'getpixel'): self._A = pil_to_array(A) - elif ma.isMA(A): - self._A = A else: - self._A = np.asarray(A) # assume array + self._A = cbook.safe_masked_invalid(A) if self._A.dtype != np.uint8 and not np.can_cast(self._A.dtype, np.float): raise TypeError("Image data can not convert to float") @@ -310,8 +311,9 @@ def set_extent(self, extent): - """extent is data axes (left, right, bottom, top) for making image plots """ + extent is data axes (left, right, bottom, top) for making image plots + """ self._extent = extent xmin, xmax, ymin, ymax = extent @@ -375,7 +377,8 @@ return (-0.5, numcols-0.5, -0.5, numrows-0.5) def set_filternorm(self, filternorm): - """Set whether the resize filter norms the weights -- see + """ + Set whether the resize filter norms the weights -- see help for imshow ACCEPTS: 0 or 1 @@ -390,7 +393,8 @@ return self._filternorm def set_filterrad(self, filterrad): - """Set the resize filter radius only applicable to some + """ + Set the resize filter radius only applicable to some interpolation schemes -- see help for imshow ACCEPTS: positive float @@ -405,9 +409,11 @@ class NonUniformImage(AxesImage): - def __init__(self, ax, - **kwargs - ): + def __init__(self, ax, **kwargs): + """ + kwargs are identical to those for AxesImage, except + that 'interpolation' defaults to 'nearest' + """ interp = kwargs.pop('interpolation', 'nearest') AxesImage.__init__(self, ax, **kwargs) @@ -434,10 +440,19 @@ return im def set_data(self, x, y, A): + """ + Set the grid for the pixel centers, and the pixel values. + + *x* and *y* are 1-D ndarrays of lengths N and M, respectively, + specifying pixel centers + + *A* is an (M,N) ndarray or masked array of values to be + colormapped, or a (M,N,3) RGB array, or a (M,N,4) RGBA + array. + """ x = np.asarray(x,np.float32) y = np.asarray(y,np.float32) - if not ma.isMA(A): - A = np.asarray(A) + A = cbook.safe_masked_invalid(A) if len(x.shape) != 1 or len(y.shape) != 1\ or A.shape[0:2] != (y.shape[0], x.shape[0]): raise TypeError("Axes don't match array shape") @@ -567,8 +582,7 @@ def set_data(self, x, y, A): - if not ma.isMA(A): - A = np.asarray(A) + A = cbook.safe_masked_invalid(A) if x is None: x = np.arange(0, A.shape[1]+1, dtype=np.float64) else: @@ -666,6 +680,19 @@ return (-0.5+self.ox, numcols-0.5+self.ox, -0.5+self.oy, numrows-0.5+self.oy) + def set_data(self, A): + """ + Set the image array + + """ + cm.ScalarMappable.set_array(self, cbook.safe_masked_invalid(A)) + + def set_array(self, A): + """ + Deprecated; use set_data for consistency with other image types. + """ + self.set_data(A) + def make_image(self, magnification=1.0): if self._A is None: raise RuntimeError('You must first set the image array') This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2009-03-31 15:13:38
|
Revision: 7015 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7015&view=rev Author: mdboom Date: 2009-03-31 15:13:24 +0000 (Tue, 31 Mar 2009) Log Message: ----------- Merged revisions 7014 via svnmerge from https://matplotlib.svn.sf.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r7014 | mdboom | 2009-03-31 10:50:12 -0400 (Tue, 31 Mar 2009) | 2 lines Remove some global caches in order to remove a theoretical threading problem. ........ Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/mathtext.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-7001 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7014 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 + /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 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 + /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 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 + /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 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 + /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 Modified: trunk/matplotlib/lib/matplotlib/mathtext.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mathtext.py 2009-03-31 14:50:12 UTC (rev 7014) +++ trunk/matplotlib/lib/matplotlib/mathtext.py 2009-03-31 15:13:24 UTC (rev 7015) @@ -653,17 +653,16 @@ 'sf' : 'cmss10', 'ex' : 'cmex10' } - fontmap = {} def __init__(self, *args, **kwargs): self._stix_fallback = StixFonts(*args, **kwargs) TruetypeFonts.__init__(self, *args, **kwargs) - if not len(self.fontmap): - for key, val in self._fontmap.iteritems(): - fullpath = findfont(val) - self.fontmap[key] = fullpath - self.fontmap[val] = fullpath + self.fontmap = {} + for key, val in self._fontmap.iteritems(): + fullpath = findfont(val) + self.fontmap[key] = fullpath + self.fontmap[val] = fullpath _slanted_symbols = set(r"\int \oint".split()) @@ -765,7 +764,6 @@ This class will "fallback" on the Bakoma fonts when a required symbol can not be found in the font. """ - fontmap = {} use_cmex = True def __init__(self, *args, **kwargs): @@ -775,14 +773,14 @@ else: self.cm_fallback = None TruetypeFonts.__init__(self, *args, **kwargs) - if not len(self.fontmap): - for texfont in "cal rm tt it bf sf".split(): - prop = rcParams['mathtext.' + texfont] - font = findfont(prop) - self.fontmap[texfont] = font - prop = FontProperties('cmex10') + self.fontmap = {} + for texfont in "cal rm tt it bf sf".split(): + prop = rcParams['mathtext.' + texfont] font = findfont(prop) - self.fontmap['ex'] = font + self.fontmap[texfont] = font + prop = FontProperties('cmex10') + font = findfont(prop) + self.fontmap['ex'] = font _slanted_symbols = set(r"\int \oint".split()) @@ -891,18 +889,17 @@ 4 : 'STIXSize4', 5 : 'STIXSize5' } - fontmap = {} use_cmex = False cm_fallback = False _sans = False def __init__(self, *args, **kwargs): TruetypeFonts.__init__(self, *args, **kwargs) - if not len(self.fontmap): - for key, name in self._fontmap.iteritems(): - fullpath = findfont(name) - self.fontmap[key] = fullpath - self.fontmap[name] = fullpath + self.fontmap = {} + for key, name in self._fontmap.iteritems(): + fullpath = findfont(name) + self.fontmap[key] = fullpath + self.fontmap[name] = fullpath def _map_virtual_font(self, fontname, font_class, uniindex): # Handle these "fonts" that are actually embedded in 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 + /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 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 + /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 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 + /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 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2009-03-31 15:24:03
|
Revision: 7017 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7017&view=rev Author: mdboom Date: 2009-03-31 15:23:54 +0000 (Tue, 31 Mar 2009) Log Message: ----------- Merged revisions 7016 via svnmerge from https://matplotlib.svn.sf.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r7016 | mdboom | 2009-03-31 11:22:06 -0400 (Tue, 31 Mar 2009) | 2 lines Fix bug when specifying both scale and label in the axes constructor. Change to use new numpy putmask API. ........ Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/transforms.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-7014 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7016 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 + /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 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 + /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 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 + /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 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 + /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 Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2009-03-31 15:22:06 UTC (rev 7016) +++ trunk/matplotlib/lib/matplotlib/axes.py 2009-03-31 15:23:54 UTC (rev 7017) @@ -442,6 +442,8 @@ sharex=None, # use Axes instance's xaxis info sharey=None, # use Axes instance's yaxis info label='', + xscale=None, + yscale=None, **kwargs ): """ @@ -548,6 +550,11 @@ self._axes_locator = None + if xscale: + self.set_xscale(xscale) + if yscale: + self.set_yscale(yscale) + if len(kwargs): martist.setp(self, **kwargs) if self.xaxis is not None: 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 + /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 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 + /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 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 + /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 Modified: trunk/matplotlib/lib/matplotlib/transforms.py =================================================================== --- trunk/matplotlib/lib/matplotlib/transforms.py 2009-03-31 15:22:06 UTC (rev 7016) +++ trunk/matplotlib/lib/matplotlib/transforms.py 2009-03-31 15:23:54 UTC (rev 7017) @@ -971,8 +971,7 @@ if self._invalid: points = self._transform.transform(self._bbox.get_points()) if ma.isMaskedArray(points): - points.putmask(0.0) - points = np.asarray(points) + np.putmask(points, points.mask, 0.0) self._points = points self._invalid = 0 return self._points This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2009-03-31 18:00:12
|
Revision: 7019 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7019&view=rev Author: mdboom Date: 2009-03-31 17:59:53 +0000 (Tue, 31 Mar 2009) Log Message: ----------- Merged revisions 7018 via svnmerge from https://matplotlib.svn.sf.net/svnroot/matplotlib/branches/v0_98_5_maint ........ r7018 | mdboom | 2009-03-31 13:47:27 -0400 (Tue, 31 Mar 2009) | 2 lines Fix putmask update -- use np.ma.filled instead. ........ Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/transforms.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-7016 + /branches/v0_91_maint:1-6428 /branches/v0_98_5_maint:1-7018 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 + /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 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 + /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 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 + /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 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 + /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 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 + /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 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 + /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 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 + /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 Modified: trunk/matplotlib/lib/matplotlib/transforms.py =================================================================== --- trunk/matplotlib/lib/matplotlib/transforms.py 2009-03-31 17:47:27 UTC (rev 7018) +++ trunk/matplotlib/lib/matplotlib/transforms.py 2009-03-31 17:59:53 UTC (rev 7019) @@ -970,8 +970,7 @@ def get_points(self): if self._invalid: points = self._transform.transform(self._bbox.get_points()) - if ma.isMaskedArray(points): - np.putmask(points, points.mask, 0.0) + points = np.ma.filled(points, 0.0) self._points = points self._invalid = 0 return self._points This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jr...@us...> - 2009-04-01 17:28:21
|
Revision: 7020 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7020&view=rev Author: jrevans Date: 2009-04-01 17:28:11 +0000 (Wed, 01 Apr 2009) Log Message: ----------- Updated 'fill' to handle unitized data. Added a unit-test for it. Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/test/mplTest/units/__init__.py Added Paths: ----------- trunk/matplotlib/test/test_plots/TestFill.py trunk/matplotlib/test/test_plots/baseline/TestFill/ trunk/matplotlib/test/test_plots/baseline/TestFill/fill_units.png Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2009-03-31 17:59:53 UTC (rev 7019) +++ trunk/matplotlib/lib/matplotlib/axes.py 2009-04-01 17:28:11 UTC (rev 7020) @@ -216,9 +216,10 @@ if self.axes.xaxis is not None and self.axes.yaxis is not None: bx = self.axes.xaxis.update_units(x) by = self.axes.yaxis.update_units(y) - # right now multicol is not supported if either x or y are - # unit enabled but this can be fixed.. - if bx or by: return x, y, False + if bx: + x = self.axes.convert_xunits(x) + if by: + y = self.axes.convert_yunits(y) x = ma.asarray(x) y = ma.asarray(y) @@ -310,8 +311,6 @@ ret.append(seg) def makefill(x, y): - x = self.axes.convert_xunits(x) - y = self.axes.convert_yunits(y) facecolor = self._get_next_cycle_color() seg = mpatches.Polygon(np.hstack( (x[:,np.newaxis],y[:,np.newaxis])), @@ -358,8 +357,6 @@ def makefill(x, y): facecolor = color - x = self.axes.convert_xunits(x) - y = self.axes.convert_yunits(y) seg = mpatches.Polygon(np.hstack( (x[:,np.newaxis],y[:,np.newaxis])), facecolor = facecolor, Modified: trunk/matplotlib/test/mplTest/units/__init__.py =================================================================== --- trunk/matplotlib/test/mplTest/units/__init__.py 2009-03-31 17:59:53 UTC (rev 7019) +++ trunk/matplotlib/test/mplTest/units/__init__.py 2009-04-01 17:28:11 UTC (rev 7020) @@ -71,6 +71,7 @@ # Angles deg = UnitDbl( 1.0, "deg" ) +rad = UnitDbl( 1.0, "rad" ) # Time sec = UnitDbl( 1.0, "sec" ) Added: trunk/matplotlib/test/test_plots/TestFill.py =================================================================== --- trunk/matplotlib/test/test_plots/TestFill.py (rev 0) +++ trunk/matplotlib/test/test_plots/TestFill.py 2009-04-01 17:28:11 UTC (rev 7020) @@ -0,0 +1,87 @@ +#======================================================================= +"""The Fill unit-test class implementation.""" +#======================================================================= + +from mplTest import * + +#======================================================================= +# Add import modules below. +import matplotlib +matplotlib.use( "Agg", warn = False ) + +import pylab +import numpy as npy +from datetime import datetime +# +#======================================================================= + +#======================================================================= +class TestFill( MplTestCase ): + """Test the various axes fill methods.""" + + # Uncomment any appropriate tags + tags = [ + # 'gui', # requires the creation of a gui window + 'agg', # uses agg in the backend + 'agg-only', # uses only agg in the backend + # 'wx', # uses wx in the backend + # 'qt', # uses qt in the backend + # 'ps', # uses the postscript backend + # 'units', # uses units in the test + 'PIL', # uses PIL for image comparison + ] + + #-------------------------------------------------------------------- + def setUp( self ): + """Setup any data needed for the unit test.""" + units.register() + + #-------------------------------------------------------------------- + def tearDown( self ): + """Clean-up any generated files here.""" + pass + + #-------------------------------------------------------------------- + def test_fill_units( self ): + """Test the fill method with unitized-data.""" + + fname = self.outFile( "fill_units.png" ) + + # generate some data + t = units.Epoch( "ET", dt=datetime(2009, 4, 27) ) + value = 10.0 * units.deg + day = units.Duration( "ET", 24.0 * 60.0 * 60.0 ) + + fig = pylab.figure() + + # Top-Left + ax1 = fig.add_subplot( 221 ) + ax1.plot( [t], [value], yunits='deg', color='red' ) + ax1.fill( [733525.0, 733525.0, 733526.0, 733526.0], + [0.0, 0.0, 90.0, 0.0], 'b' ) + + # Top-Right + ax2 = fig.add_subplot( 222 ) + ax2.plot( [t], [value], yunits='deg', color='red' ) + ax2.fill( [t, t, t+day, t+day], + [0.0, 0.0, 90.0, 0.0], 'b' ) + + # Bottom-Left + ax3 = fig.add_subplot( 223 ) + ax3.plot( [t], [value], yunits='deg', color='red' ) + ax1.fill( [733525.0, 733525.0, 733526.0, 733526.0], + [0*units.deg, 0*units.deg, 90*units.deg, 0*units.deg], 'b' ) + + # Bottom-Right + ax4 = fig.add_subplot( 224 ) + ax4.plot( [t], [value], yunits='deg', color='red' ) + ax4.fill( [t, t, t+day, t+day], + [0*units.deg, 0*units.deg, 90*units.deg, 0*units.deg], + facecolor="blue" ) + + fig.autofmt_xdate() + fig.savefig( fname ) + self.checkImage( fname ) + + #-------------------------------------------------------------------- + Added: trunk/matplotlib/test/test_plots/baseline/TestFill/fill_units.png =================================================================== (Binary files differ) Property changes on: trunk/matplotlib/test/test_plots/baseline/TestFill/fill_units.png ___________________________________________________________________ Added: svn:mime-type + application/octet-stream This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2009-04-04 22:52:59
|
Revision: 7023 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7023&view=rev Author: efiring Date: 2009-04-04 22:52:53 +0000 (Sat, 04 Apr 2009) Log Message: ----------- Add log scale option to clip non-positive values instead of masking Modified Paths: -------------- trunk/matplotlib/CHANGELOG trunk/matplotlib/doc/api/api_changes.rst trunk/matplotlib/examples/pylab_examples/log_demo.py trunk/matplotlib/lib/matplotlib/axes.py trunk/matplotlib/lib/matplotlib/scale.py Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2009-04-01 20:44:58 UTC (rev 7022) +++ trunk/matplotlib/CHANGELOG 2009-04-04 22:52:53 UTC (rev 7023) @@ -1,3 +1,6 @@ +2009-04-04 Allow log axis scale to clip non-positive values to + small positive value; this is useful for errorbars. - EF + 2009-03-28 Make images handle nan in their array argument. A helper, cbook.safe_masked_invalid() was added. - EF Modified: trunk/matplotlib/doc/api/api_changes.rst =================================================================== --- trunk/matplotlib/doc/api/api_changes.rst 2009-04-01 20:44:58 UTC (rev 7022) +++ trunk/matplotlib/doc/api/api_changes.rst 2009-04-04 22:52:53 UTC (rev 7023) @@ -19,6 +19,12 @@ Changes for 0.98.x ================== +* Added new keyword parameters *nonposx*, *nonposy* to + :class:`matplotlib.axes.Axes` methods that set log scale + parameters. The default is still to mask out non-positive + values, but the kwargs accept 'clip', which causes non-positive + values to be replaced with a very small positive value. + * Added new :func:`matplotlib.pyplot.fignum_exists` and :func:`matplotlib.pyplot.get_fignums`; they merely expose information that had been hidden in :mod:`matplotlib._pylab_helpers`. Modified: trunk/matplotlib/examples/pylab_examples/log_demo.py =================================================================== --- trunk/matplotlib/examples/pylab_examples/log_demo.py 2009-04-01 20:44:58 UTC (rev 7022) +++ trunk/matplotlib/examples/pylab_examples/log_demo.py 2009-04-04 22:52:53 UTC (rev 7023) @@ -6,21 +6,33 @@ t = np.arange(0.01, 20.0, 0.01) # log y axis -plt.subplot(311) +plt.subplot(221) plt.semilogy(t, np.exp(-t/5.0)) -plt.ylabel('semilogy') +plt.title('semilogy') plt.grid(True) # log x axis -plt.subplot(312) +plt.subplot(222) plt.semilogx(t, np.sin(2*np.pi*t)) -plt.ylabel('semilogx') +plt.title('semilogx') plt.grid(True) # log x and y axis -plt.subplot(313) +plt.subplot(223) plt.loglog(t, 20*np.exp(-t/10.0), basex=4) plt.grid(True) -plt.ylabel('loglog base 4 on x') +plt.title('loglog base 4 on x') +# with errorbars: clip non-positive values +ax = plt.subplot(224) +ax.set_xscale("log", nonposx='clip') +ax.set_yscale("log", nonposy='clip') + +x = 10.0**np.linspace(0.0, 2.0, 20) +y = x**2.0 +plt.errorbar(x, y, xerr=0.1*x, yerr=5.0+0.75*y) +ax.set_ylim(ymin=0.1) +ax.set_title('Errorbars go negative') + + plt.show() Modified: trunk/matplotlib/lib/matplotlib/axes.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes.py 2009-04-01 20:44:58 UTC (rev 7022) +++ trunk/matplotlib/lib/matplotlib/axes.py 2009-04-04 22:52:53 UTC (rev 7023) @@ -3455,6 +3455,10 @@ plot; see :meth:`matplotlib.axes.Axes.set_xscale` / :meth:`matplotlib.axes.Axes.set_yscale` for details + *nonposx*/*nonposy*: ['mask' | 'clip' ] + non-positive values in *x* or *y* can be masked as + invalid, or clipped to a very small positive number + The remaining valid kwargs are :class:`~matplotlib.lines.Line2D` properties: @@ -3469,9 +3473,11 @@ dx = {'basex': kwargs.pop('basex', 10), 'subsx': kwargs.pop('subsx', None), + 'nonposx': kwargs.pop('nonposx', 'mask'), } dy = {'basey': kwargs.pop('basey', 10), 'subsy': kwargs.pop('subsy', None), + 'nonposy': kwargs.pop('nonposy', 'mask'), } self.set_xscale('log', **dx) @@ -3508,6 +3514,10 @@ plot; see :meth:`~matplotlib.axes.Axes.set_xscale` for details. + *nonposx*: ['mask' | 'clip' ] + non-positive values in *x* can be masked as + invalid, or clipped to a very small positive number + The remaining valid kwargs are :class:`~matplotlib.lines.Line2D` properties: @@ -3521,6 +3531,7 @@ if not self._hold: self.cla() d = {'basex': kwargs.pop( 'basex', 10), 'subsx': kwargs.pop( 'subsx', None), + 'nonposx': kwargs.pop('nonposx', 'mask'), } self.set_xscale('log', **d) @@ -3554,6 +3565,10 @@ plot; see :meth:`~matplotlib.axes.Axes.set_yscale` for details. + *nonposy*: ['mask' | 'clip' ] + non-positive values in *y* can be masked as + invalid, or clipped to a very small positive number + The remaining valid kwargs are :class:`~matplotlib.lines.Line2D` properties: @@ -3567,6 +3582,7 @@ if not self._hold: self.cla() d = {'basey': kwargs.pop('basey', 10), 'subsy': kwargs.pop('subsy', None), + 'nonposy': kwargs.pop('nonposy', 'mask'), } self.set_yscale('log', **d) b = self._hold Modified: trunk/matplotlib/lib/matplotlib/scale.py =================================================================== --- trunk/matplotlib/lib/matplotlib/scale.py 2009-04-01 20:44:58 UTC (rev 7022) +++ trunk/matplotlib/lib/matplotlib/scale.py 2009-04-04 22:52:53 UTC (rev 7023) @@ -87,6 +87,10 @@ return ma.MaskedArray(a, mask=mask) return a +def _clip_non_positives(a): + a[a <= 0.0] = 1e-300 + return a + class LogScale(ScaleBase): """ A standard logarithmic scale. Care is taken so non-positive @@ -104,14 +108,24 @@ name = 'log' - class Log10Transform(Transform): + class LogTransformBase(Transform): input_dims = 1 output_dims = 1 is_separable = True + + def __init__(self, nonpos): + Transform.__init__(self) + if nonpos == 'mask': + self._handle_nonpos = _mask_non_positives + else: + self._handle_nonpos = _clip_non_positives + + + class Log10Transform(LogTransformBase): base = 10.0 def transform(self, a): - a = _mask_non_positives(a * 10.0) + a = self._handle_nonpos(a * 10.0) if isinstance(a, MaskedArray): return ma.log10(a) return np.log10(a) @@ -131,14 +145,11 @@ def inverted(self): return LogScale.Log10Transform() - class Log2Transform(Transform): - input_dims = 1 - output_dims = 1 - is_separable = True + class Log2Transform(LogTransformBase): base = 2.0 def transform(self, a): - a = _mask_non_positives(a * 2.0) + a = self._handle_nonpos(a * 2.0) if isinstance(a, MaskedArray): return ma.log(a) / np.log(2) return np.log2(a) @@ -158,14 +169,11 @@ def inverted(self): return LogScale.Log2Transform() - class NaturalLogTransform(Transform): - input_dims = 1 - output_dims = 1 - is_separable = True + class NaturalLogTransform(LogTransformBase): base = np.e def transform(self, a): - a = _mask_non_positives(a * np.e) + a = self._handle_nonpos(a * np.e) if isinstance(a, MaskedArray): return ma.log(a) return np.log(a) @@ -190,12 +198,16 @@ output_dims = 1 is_separable = True - def __init__(self, base): + def __init__(self, base, nonpos): Transform.__init__(self) self.base = base + if nonpos == 'mask': + self._handle_nonpos = _mask_non_positives + else: + self._handle_nonpos = _clip_non_positives def transform(self, a): - a = _mask_non_positives(a * self.base) + a = self._handle_nonpos(a * self.base) if isinstance(a, MaskedArray): return ma.log(a) / np.log(self.base) return np.log(a) / np.log(self.base) @@ -224,6 +236,10 @@ *basex*/*basey*: The base of the logarithm + *nonposx*/*nonposy*: ['mask' | 'clip' ] + non-positive values in *x* or *y* can be masked as + invalid, or clipped to a very small positive number + *subsx*/*subsy*: Where to place the subticks between each major tick. Should be a sequence of integers. For example, in a log10 @@ -235,18 +251,23 @@ if axis.axis_name == 'x': base = kwargs.pop('basex', 10.0) subs = kwargs.pop('subsx', None) + nonpos = kwargs.pop('nonposx', 'mask') else: base = kwargs.pop('basey', 10.0) subs = kwargs.pop('subsy', None) + nonpos = kwargs.pop('nonposy', 'mask') + if nonpos not in ['mask', 'clip']: + raise ValueError("nonposx, nonposy kwarg must be 'mask' or 'clip'") + if base == 10.0: - self._transform = self.Log10Transform() + self._transform = self.Log10Transform(nonpos) elif base == 2.0: - self._transform = self.Log2Transform() + self._transform = self.Log2Transform(nonpos) elif base == np.e: - self._transform = self.NaturalLogTransform() + self._transform = self.NaturalLogTransform(nonpos) else: - self._transform = self.LogTransform(base) + self._transform = self.LogTransform(base, nonpos) self.base = base self.subs = subs This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2009-04-05 02:23:08
|
Revision: 7026 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7026&view=rev Author: efiring Date: 2009-04-05 02:23:03 +0000 (Sun, 05 Apr 2009) 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 (Sat, 04 Apr 2009) | 2 lines Fix PatchCollection bug 2723527; thanks to Thomas Robitaille ........ r7025 | efiring | 2009-04-04 16:16:44 -1000 (Sat, 04 Apr 2009) | 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. |
From: <as...@us...> - 2009-04-06 01:52:54
|
Revision: 7032 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7032&view=rev Author: astraw Date: 2009-04-06 01:52:45 +0000 (Mon, 06 Apr 2009) 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 (Sun, 05 Apr 2009) | 1 line pngsuite test: plot images in grayscale if the input array is 2 dimensional ........ r7028 | astraw | 2009-04-05 15:07:01 -0700 (Sun, 05 Apr 2009) | 1 line read 12 bit PNGs (patch from Tobias Wood) ........ r7029 | astraw | 2009-04-05 15:07:34 -0700 (Sun, 05 Apr 2009) | 1 line trivial: remove trailing whitespace from source code ........ r7030 | astraw | 2009-04-05 15:08:24 -0700 (Sun, 05 Apr 2009) | 1 line trivial: remove outdated comment ........ r7031 | astraw | 2009-04-05 15:09:45 -0700 (Sun, 05 Apr 2009) | 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. |
From: <jo...@us...> - 2009-04-06 17:12:43
|
Revision: 7034 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7034&view=rev Author: jouni Date: 2009-04-06 17:12:37 +0000 (Mon, 06 Apr 2009) 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 (Mon, 06 Apr 2009) | 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. |
From: <jo...@us...> - 2009-04-06 19:06:03
|
Revision: 7036 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7036&view=rev Author: jouni Date: 2009-04-06 19:05:57 +0000 (Mon, 06 Apr 2009) 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 (Mon, 06 Apr 2009) | 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. |
From: <jd...@us...> - 2009-04-13 03:02:51
|
Revision: 7040 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7040&view=rev Author: jdh2358 Date: 2009-04-13 03:02:41 +0000 (Mon, 13 Apr 2009) 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 (Fri, 10 Apr 2009) | 1 line added python 2.6 / tcltk 8.5 check ........ r7038 | cmoad | 2009-04-12 21:22:30 -0500 (Sun, 12 Apr 2009) | 1 line minor rev bump ........ r7039 | jdh2358 | 2009-04-12 21:56:11 -0500 (Sun, 12 Apr 2009) | 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. |
From: <jd...@us...> - 2009-04-14 14:29:36
|
Revision: 7041 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7041&view=rev Author: jdh2358 Date: 2009-04-14 14:29:31 +0000 (Tue, 14 Apr 2009) 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] |
From: <jd...@us...> - 2009-04-15 17:52:32
|
Revision: 7043 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7043&view=rev Author: jdh2358 Date: 2009-04-15 17:52:23 +0000 (Wed, 15 Apr 2009) 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 (Wed, 15 Apr 2009) | 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. |
From: <lee...@us...> - 2009-04-16 17:28:53
|
Revision: 7044 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7044&view=rev Author: leejjoon Date: 2009-04-16 17:28:41 +0000 (Thu, 16 Apr 2009) 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. |
From: <lee...@us...> - 2009-04-17 02:31:20
|
Revision: 7046 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7046&view=rev Author: leejjoon Date: 2009-04-17 02:31:16 +0000 (Fri, 17 Apr 2009) 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. |
From: <lee...@us...> - 2009-04-17 16:34:14
|
Revision: 7047 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7047&view=rev Author: leejjoon Date: 2009-04-17 16:34:09 +0000 (Fri, 17 Apr 2009) 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. |
From: <lee...@us...> - 2009-04-17 19:36:09
|
Revision: 7048 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=7048&view=rev Author: leejjoon Date: 2009-04-17 19:35:59 +0000 (Fri, 17 Apr 2009) 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] |