From: <md...@us...> - 2007-12-21 19:41:07
|
Revision: 4787 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4787&view=rev Author: mdboom Date: 2007-12-21 11:40:59 -0800 (Fri, 21 Dec 2007) Log Message: ----------- Merged revisions 4773-4785 via svnmerge from http://matplotlib.svn.sf.net/svnroot/matplotlib/trunk/matplotlib ........ r4783 | mdboom | 2007-12-21 10:08:38 -0500 (Fri, 21 Dec 2007) | 2 lines Add size-dependent highly-accurate arc drawing. ........ r4785 | jdh2358 | 2007-12-21 11:22:42 -0500 (Fri, 21 Dec 2007) | 2 lines added unit support to arc ........ Modified Paths: -------------- branches/transforms/API_CHANGES branches/transforms/CODING_GUIDE branches/transforms/examples/units/ellipse_with_units.py branches/transforms/lib/matplotlib/axes.py branches/transforms/lib/matplotlib/legend.py branches/transforms/lib/matplotlib/mlab.py branches/transforms/lib/matplotlib/patches.py branches/transforms/unit/ellipse_large.py Property Changed: ---------------- branches/transforms/ Property changes on: branches/transforms ___________________________________________________________________ Name: svnmerge-integrated - /trunk/matplotlib:1-4772 + /trunk/matplotlib:1-4785 Modified: branches/transforms/API_CHANGES =================================================================== --- branches/transforms/API_CHANGES 2007-12-21 18:53:29 UTC (rev 4786) +++ branches/transforms/API_CHANGES 2007-12-21 19:40:59 UTC (rev 4787) @@ -169,6 +169,9 @@ END OF TRANSFORMS REFACTORING + For csv2rec, checkrows=0 is the new default indicating all rows + will be checked for type inference + A warning is issued when an image is drawn on log-scaled axes, since it will not log-scale the image data. Modified: branches/transforms/CODING_GUIDE =================================================================== --- branches/transforms/CODING_GUIDE 2007-12-21 18:53:29 UTC (rev 4786) +++ branches/transforms/CODING_GUIDE 2007-12-21 19:40:59 UTC (rev 4787) @@ -12,6 +12,9 @@ # checking out the main src svn co https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/trunk/matplotlib matplotlib --username=youruser --password=yourpass +# branch checkouts, eg the transforms branch +svn co https://matplotlib.svn.sourceforge.net/svnroot/matplotlib/branches/transforms transbranch + == Committing changes == When committing changes to matplotlib, there are a few things to bear @@ -27,12 +30,6 @@ support 2.3, so avoid 2.4 only features like decorators until we remove 2.3 support - * Are your changes Numeric, numarray and numpy compatible? Try - running simple_plot.py or image_demo.py with --Numeric, --numarray - and --numpy (Note, someone should add examples to - backend_driver.py which explicitly require numpy, numarray and - Numeric so we can automatically catch these) - * Can you pass examples/backend_driver.py? This is our poor man's unit test. @@ -49,9 +46,8 @@ For numpy, use: import numpy as npy - ... a = npy.array([1,2,3]) - ... + For masked arrays, use: import matplotlib.numerix.npyma as ma @@ -64,16 +60,20 @@ For matplotlib main module, use: import matplotlib as mpl - ... mpl.rcParams['xtick.major.pad'] = 6 -For matplotlib modules, use: +For matplotlib modules (or any other modules), use: - import matplotlib.cbook as cbook as mpl_cbook - ... - if mpl_cbook.iterable(z): - ... + import matplotlib.cbook as cbook + + if cbook.iterable(z): + pass + We prefer this over the equivalent 'from matplotlib import cbook' + because the latter is ambiguous whether cbook is a module or a + function to the new developer. The former makes it explcit that + you are importing a module or package. + == Naming, spacing, and formatting conventions == In general, we want to hew as closely as possible to the standard @@ -114,15 +114,6 @@ python, C and C++ -When importing modules from the matplotlib namespace - - import matplotlib.cbook as cbook # DO - from matplotlib import cbook #DONT - -because the latter is ambiguous whether cbook is a module or a -function to the new developer. The former makes it explcit that you -are importing a module or package. - ; and similarly for c++-mode-hook and c-mode-hook (add-hook 'python-mode-hook (lambda () Modified: branches/transforms/examples/units/ellipse_with_units.py =================================================================== --- branches/transforms/examples/units/ellipse_with_units.py 2007-12-21 18:53:29 UTC (rev 4786) +++ branches/transforms/examples/units/ellipse_with_units.py 2007-12-21 19:40:59 UTC (rev 4787) @@ -1,5 +1,5 @@ """ -Compare the ellipse generated with arcs versus a polygonal approximation +Compare the ellipse generated with arcs versus a polygonal approximation """ from basic_units import cm import numpy as npy @@ -46,4 +46,24 @@ #fig.savefig('ellipse_compare.png') fig.savefig('ellipse_compare') +fig = figure() +ax = fig.add_subplot(211, aspect='auto') +ax.fill(x, y, alpha=0.2, facecolor='yellow', edgecolor='yellow', linewidth=1, zorder=1) + +e1 = patches.Arc((xcenter, ycenter), width, height, + angle=angle, linewidth=2, fill=False, zorder=2) + +ax.add_patch(e1) + +ax = fig.add_subplot(212, aspect='equal') +ax.fill(x, y, alpha=0.2, facecolor='green', edgecolor='green', zorder=1) +e2 = patches.Arc((xcenter, ycenter), width, height, + angle=angle, linewidth=2, fill=False, zorder=2) + + +ax.add_patch(e2) + +#fig.savefig('arc_compare.png') +fig.savefig('arc_compare') + show() Modified: branches/transforms/lib/matplotlib/axes.py =================================================================== --- branches/transforms/lib/matplotlib/axes.py 2007-12-21 18:53:29 UTC (rev 4786) +++ branches/transforms/lib/matplotlib/axes.py 2007-12-21 19:40:59 UTC (rev 4787) @@ -321,6 +321,8 @@ 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(zip(x, y), facecolor = facecolor, @@ -363,6 +365,8 @@ def makefill(x, y): facecolor = color + x = self.axes.convert_xunits(x) + y = self.axes.convert_yunits(y) seg = mpatches.Polygon(zip(x, y), facecolor = facecolor, fill=True, Modified: branches/transforms/lib/matplotlib/legend.py =================================================================== --- branches/transforms/lib/matplotlib/legend.py 2007-12-21 18:53:29 UTC (rev 4786) +++ branches/transforms/lib/matplotlib/legend.py 2007-12-21 19:40:59 UTC (rev 4787) @@ -140,7 +140,7 @@ self._offsetTransform = Affine2D() self._parentTransform = BboxTransformTo(parent.bbox) Artist.set_transform(self, self._offsetTransform + self._parentTransform) - + if loc is None: loc = rcParams["legend.loc"] if not self.isaxes and loc in [0,'best']: @@ -226,7 +226,7 @@ bboxesAll = bboxesText bboxesAll.extend(bboxesHandles) bbox = Bbox.union(bboxesAll) - + self.save = bbox ibox = bbox.inverse_transformed(self.get_transform()) @@ -328,7 +328,7 @@ if isinstance(handle, Rectangle): transform = handle.get_data_transform() + inverse_transform - bboxes.append(handle._bbox.transformed(transform)) + bboxes.append(handle.get_bbox().transformed(transform)) else: transform = handle.get_transform() + inverse_transform bboxes.append(handle.get_path().get_extents(transform)) @@ -499,7 +499,7 @@ bbox = bbox.expanded(1 + self.pad, 1 + self.pad) l, b, w, h = bbox.bounds self.legendPatch.set_bounds(l, b, w, h) - + ox, oy = 0, 0 # center if iterable(self._loc) and len(self._loc)==2: Modified: branches/transforms/lib/matplotlib/mlab.py =================================================================== --- branches/transforms/lib/matplotlib/mlab.py 2007-12-21 18:53:29 UTC (rev 4786) +++ branches/transforms/lib/matplotlib/mlab.py 2007-12-21 19:40:59 UTC (rev 4787) @@ -2045,7 +2045,7 @@ return newrec.view(npy.recarray) -def csv2rec(fname, comments='#', skiprows=0, checkrows=5, delimiter=',', +def csv2rec(fname, comments='#', skiprows=0, checkrows=0, delimiter=',', converterd=None, names=None, missing=None): """ Load data from comma/space/tab delimited file in fname into a @@ -2075,7 +2075,7 @@ names, if not None, is a list of header names. In this case, no header will be read from the file - if no rows are found, None is returned See examples/loadrec.py + if no rows are found, None is returned -- see examples/loadrec.py """ if converterd is None: Modified: branches/transforms/lib/matplotlib/patches.py =================================================================== --- branches/transforms/lib/matplotlib/patches.py 2007-12-21 18:53:29 UTC (rev 4786) +++ branches/transforms/lib/matplotlib/patches.py 2007-12-21 19:40:59 UTC (rev 4787) @@ -366,10 +366,11 @@ Patch.__init__(self, **kwargs) - left, right = self.convert_xunits((xy[0], xy[0] + width)) - bottom, top = self.convert_yunits((xy[1], xy[1] + height)) - self._bbox = transforms.Bbox.from_extents(left, bottom, right, top) - self._rect_transform = transforms.BboxTransformTo(self._bbox) + self._x = xy[0] + self._y = xy[1] + self._width = width + self._height = height + self._rect_transform = transforms.IdentityTransform() __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd def get_path(self): @@ -378,6 +379,19 @@ """ return Path.unit_rectangle() + def _update_patch_transform(self): + x = self.convert_xunits(self._x) + y = self.convert_yunits(self._y) + width = self.convert_xunits(self._width) + height = self.convert_yunits(self._height) + bbox = transforms.Bbox.from_bounds(x, y, width, height) + self._rect_transform = transforms.BboxTransformTo(bbox) + self._combined_transform = self._rect_transform + artist.Artist.get_transform(self) + + def draw(self, renderer): + self._update_patch_transform() + Patch.draw(self, renderer) + def get_patch_transform(self): return self._rect_transform @@ -388,19 +402,19 @@ def get_x(self): "Return the left coord of the rectangle" - return self._bbox.x0 + return self._x def get_y(self): "Return the bottom coord of the rectangle" - return self._bbox.y0 + return self._y def get_width(self): "Return the width of the rectangle" - return self._bbox.width + return self._width def get_height(self): "Return the height of the rectangle" - return self._bbox.height + return self._height def set_x(self, x): """ @@ -408,9 +422,7 @@ ACCEPTS: float """ - w = self._bbox.width - x = self.convert_xunits(x) - self._bbox.intervalx = (x, x + w) + self._x = x def set_y(self, y): """ @@ -418,9 +430,7 @@ ACCEPTS: float """ - h = self._bbox.height - y = self.convert_yunits(y) - self._bbox.intervaly = (y, y + h) + self._y = y def set_width(self, w): """ @@ -428,8 +438,7 @@ ACCEPTS: float """ - w = self.convert_xunits(w) - self._bbox.x1 = self._bbox.x0 + w + self._width = w def set_height(self, h): """ @@ -437,8 +446,7 @@ ACCEPTS: float """ - h = self.convert_yunits(h) - self._bbox.y1 = self._bbox.y0 + h + self._height = h def set_bounds(self, *args): """ @@ -450,10 +458,13 @@ l,b,w,h = args[0] else: l,b,w,h = args - l, w = self.convert_xunits((l, w)) - b, h = self.convert_yunits((b, h)) - self._bbox.bounds = l,b,w,h + self._x = l + self._y = b + self._width = w + self._height = h + def get_bbox(self): + return transforms.Bbox.from_bounds(self._x, self._y, self._width, self._height) class RegularPolygon(Patch): """ @@ -494,7 +505,6 @@ def _get_xy(self): return self._xy def _set_xy(self, xy): - self._xy = xy self._update_transform() xy = property(_get_xy, _set_xy) @@ -588,9 +598,23 @@ """ Patch.__init__(self, **kwargs) - self._path = Path.wedge(theta1, theta2) + self.center = center + self.r = r + self.theta1 = theta1 + self.theta2 = theta2 + self._patch_transform = transforms.IdentityTransform() + self._path = Path.wedge(self.theta1, self.theta2) + + def draw(self, renderer): + x = self.convert_xunits(self.center[0]) + y = self.convert_yunits(self.center[1]) + rx = self.convert_xunits(self.r) + ry = self.convert_yunits(self.r) self._patch_transform = transforms.Affine2D() \ - .scale(r).translate(*center) + .scale(rx, ry).translate(x, y) + self._combined_transform = self._patch_transform + \ + artist.Artist.get_transform(self) + Patch.draw(self, renderer) __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd def get_path(self): @@ -806,8 +830,6 @@ %(Patch)s """ - self.center = xy - self.radius = radius RegularPolygon.__init__(self, xy, resolution, radius, @@ -821,7 +843,7 @@ A scale-free ellipse """ def __str__(self): - return "Ellipse(%d,%d;%dx%d)"%(self.center[0],self.center[1],self.width,self.height) + return "Ellipse(%s,%s;%sx%s)"%(self.center[0],self.center[1],self.width,self.height) def __init__(self, xy, width, height, angle=0.0, **kwargs): """ @@ -835,18 +857,28 @@ """ Patch.__init__(self, **kwargs) - self._center = xy - self._width, self._height = width, height - self._angle = angle - self._recompute_transform() + self.center = xy + self.width, self.height = width, height + self.angle = angle self._path = Path.unit_circle() + self._patch_transform = transforms.IdentityTransform() def _recompute_transform(self): + center = (self.convert_xunits(self.center[0]), + self.convert_yunits(self.center[1])) + width = self.convert_xunits(self.width) + height = self.convert_yunits(self.height) self._patch_transform = transforms.Affine2D() \ - .scale(self._width * 0.5, self._height * 0.5) \ - .rotate_deg(self._angle) \ - .translate(*self._center) + .scale(width * 0.5, height * 0.5) \ + .rotate_deg(self.angle) \ + .translate(*center) + self._combined_transform = self._patch_transform + \ + artist.Artist.get_transform(self) + def draw(self, renderer): + self._recompute_transform() + Patch.draw(self, renderer) + def get_path(self): """ Return the vertices of the rectangle @@ -861,27 +893,7 @@ x, y = self.get_transform().inverted().transform_point((ev.x, ev.y)) return (x*x + y*y) <= 1.0, {} - def _get_center(self): - return self._center - def _set_center(self, center): - self._center = center - self._recompute_transform() - center = property(_get_center, _set_center) - def _get_xy(self): - return self._xy - def _set_xy(self, xy): - self._xy = xy - self._recompute_transform() - xy = property(_get_xy, _set_xy) - - def _get_angle(self): - return self._angle - def _set_angle(self, angle): - self._angle = angle - self._recompute_transform() - angle = property(_get_angle, _set_angle) - class Circle(Ellipse): """ A circle patch @@ -912,9 +924,14 @@ """ An elliptical arc. Because it performs various optimizations, it can not be filled. + + The arc must be used in an Axes instance it cannot be added + directly to a Figure) because it is optimized to only render the + segments that are inside the axes bounding box with high + resolution. """ def __str__(self): - return "Arc(%d,%d;%dx%d)"%(self.center[0],self.center[1],self.width,self.height) + return "Arc(%s,%s;%sx%s)"%(self.center[0],self.center[1],self.width,self.height) def __init__(self, xy, width, height, angle=0.0, theta1=0.0, theta2=360.0, **kwargs): """ @@ -938,8 +955,8 @@ Ellipse.__init__(self, xy, width, height, angle, **kwargs) - self._theta1 = theta1 - self._theta2 = theta2 + self.theta1 = theta1 + self.theta2 = theta2 def draw(self, renderer): """ @@ -984,13 +1001,20 @@ pairs of vertices are drawn using the bezier arc approximation technique implemented in Path.arc(). """ + if not hasattr(self, 'axes'): + raise RuntimeError('Arcs can only be used in Axes instances') + + self._recompute_transform() + # Get the width and height in pixels + width = self.convert_xunits(self.width) + height = self.convert_yunits(self.height) width, height = self.get_transform().transform_point( - (self._width, self._height)) - inv_error = (1.0 / 1.89818e-6) + (width, height)) + inv_error = (1.0 / 1.89818e-6) * 0.5 if width < inv_error and height < inv_error: - self._path = Path.arc(self._theta1, self._theta2) + self._path = Path.arc(self.theta1, self.theta2) return Patch.draw(self, renderer) def iter_circle_intersect_on_line(x0, y0, x1, y1): @@ -1037,7 +1061,6 @@ if x >= x0e and x <= x1e and y >= y0e and y <= y1e: yield x, y - # Transforms the axes box_path so that it is relative to the unit # circle in the same way that it is relative to the desired # ellipse. @@ -1050,8 +1073,8 @@ TWOPI = PI * 2.0 RAD2DEG = 180.0 / PI DEG2RAD = PI / 180.0 - theta1 = self._theta1 - theta2 = self._theta2 + theta1 = self.theta1 + theta2 = self.theta2 thetas = {} # For each of the point pairs, there is a line segment for p0, p1 in zip(box_path.vertices[:-1], box_path.vertices[1:]): Modified: branches/transforms/unit/ellipse_large.py =================================================================== --- branches/transforms/unit/ellipse_large.py 2007-12-21 18:53:29 UTC (rev 4786) +++ branches/transforms/unit/ellipse_large.py 2007-12-21 19:40:59 UTC (rev 4787) @@ -6,7 +6,7 @@ import math from pylab import * -from matplotlib.patches import Arc +from matplotlib.patches import Ellipse, Arc # given a point x, y x = 2692.440 @@ -47,39 +47,75 @@ ellipseLine = ax.plot( xs, ys, **kwargs ) + + ################################################## # make the axes -ax = subplot( 211, aspect='equal' ) -ax.set_aspect( 'equal', 'datalim' ) +ax1 = subplot( 311, aspect='equal' ) +ax1.set_aspect( 'equal', 'datalim' ) # make the lower-bound ellipse diam = (r - delta) * 2.0 -lower_ellipse = Arc( (0.0, 0.0), diam, diam, 0.0, fill=False, edgecolor="darkgreen" ) -ax.add_patch( lower_ellipse ) +lower_ellipse = Ellipse( (0.0, 0.0), diam, diam, 0.0, fill=False, edgecolor="darkgreen" ) +ax1.add_patch( lower_ellipse ) # make the target ellipse diam = r * 2.0 -target_ellipse = Arc( (0.0, 0.0), diam, diam, 0.0, fill=False, edgecolor="darkred" ) -ax.add_patch( target_ellipse ) +target_ellipse = Ellipse( (0.0, 0.0), diam, diam, 0.0, fill=False, edgecolor="darkred" ) +ax1.add_patch( target_ellipse ) # make the upper-bound ellipse diam = (r + delta) * 2.0 -upper_ellipse = Arc( (0.0, 0.0), diam, diam, 0.0, fill=False, edgecolor="darkblue" ) -ax.add_patch( upper_ellipse ) +upper_ellipse = Ellipse( (0.0, 0.0), diam, diam, 0.0, fill=False, edgecolor="darkblue" ) +ax1.add_patch( upper_ellipse ) # make the target diam = delta * 2.0 +target = Ellipse( (x, y), diam, diam, 0.0, fill=False, edgecolor="#DD1208" ) +ax1.add_patch( target ) + +# give it a big marker +ax1.plot( [x], [y], marker='x', linestyle='None', mfc='red', mec='red', markersize=10 ) + +################################################## +# make the axes +ax = subplot( 312, aspect='equal' , sharex=ax1, sharey=ax1) +ax.set_aspect( 'equal', 'datalim' ) + +# make the lower-bound arc +diam = (r - delta) * 2.0 +lower_arc = Arc( (0.0, 0.0), diam, diam, 0.0, fill=False, edgecolor="darkgreen" ) +ax.add_patch( lower_arc ) + +# make the target arc +diam = r * 2.0 +target_arc = Arc( (0.0, 0.0), diam, diam, 0.0, fill=False, edgecolor="darkred" ) +ax.add_patch( target_arc ) + +# make the upper-bound arc +diam = (r + delta) * 2.0 +upper_arc = Arc( (0.0, 0.0), diam, diam, 0.0, fill=False, edgecolor="darkblue" ) +ax.add_patch( upper_arc ) + +# make the target +diam = delta * 2.0 target = Arc( (x, y), diam, diam, 0.0, fill=False, edgecolor="#DD1208" ) ax.add_patch( target ) # give it a big marker ax.plot( [x], [y], marker='x', linestyle='None', mfc='red', mec='red', markersize=10 ) + + + + ################################################## # now lets do the same thing again using a custom ellipse function + + # make the axes -ax = subplot( 212, aspect='equal', sharex=ax, sharey=ax ) +ax = subplot( 313, aspect='equal', sharex=ax1, sharey=ax1 ) ax.set_aspect( 'equal', 'datalim' ) # make the lower-bound ellipse @@ -97,11 +133,17 @@ # give it a big marker ax.plot( [x], [y], marker='x', linestyle='None', mfc='red', mec='red', markersize=10 ) + +# give it a big marker +ax.plot( [x], [y], marker='x', linestyle='None', mfc='red', mec='red', markersize=10 ) + ################################################## # lets zoom in to see the area of interest -ax.set_xlim(2650, 2735) -ax.set_ylim(6705, 6735) +ax1.set_xlim(2650, 2735) +ax1.set_ylim(6705, 6735) + +savefig("ellipse") show() -# savefig("ellipse") + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |