Revision: 3956 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3956&view=rev Author: mdboom Date: 2007-10-16 07:35:12 -0700 (Tue, 16 Oct 2007)
Log Message: ----------- Merged revisions 3933-3955 via svnmerge from http://matplotlib.svn.sf.net/svnroot/matplotlib/trunk/matplotlib ........ r3935 | mdboom | 2007-10-11 13:03:50 -0400 (Thu, 11 Oct 2007) | 1 line Fixed minor import bug ........ r3941 | jdh2358 | 2007-10-14 15:00:50 -0400 (Sun, 14 Oct 2007) | 1 line added ellipse compare script ........ r3949 | jdh2358 | 2007-10-15 16:00:54 -0400 (Mon, 15 Oct 2007) | 3 lines fixed an aspect=auto problem with bezier ellipse approx ........ r3950 | jdh2358 | 2007-10-15 16:52:32 -0400 (Mon, 15 Oct 2007) | 2 lines Fixed a texst clipping bug in backend agg ........ r3951 | jdh2358 | 2007-10-15 17:08:35 -0400 (Mon, 15 Oct 2007) | 2 lines Fixed an annotation unit bug ........ r3952 | jdh2358 | 2007-10-15 17:22:03 -0400 (Mon, 15 Oct 2007) | 2 lines fixed a unit problem with annotations ........ r3953 | mdboom | 2007-10-16 08:28:49 -0400 (Tue, 16 Oct 2007) | 1 line Fix build on Windows with MSVC .NET 2003 ........ r3954 | jdh2358 | 2007-10-16 09:45:59 -0400 (Tue, 16 Oct 2007) | 2 lines restored unit support for ellipses -- and added examples/units/ellipse_with_units.py ........ Modified Paths: -------------- branches/transforms/CHANGELOG branches/transforms/boilerplate.py branches/transforms/lib/matplotlib/backends/backend_ps.py branches/transforms/lib/matplotlib/cbook.py branches/transforms/lib/matplotlib/mlab.py branches/transforms/lib/matplotlib/patches.py branches/transforms/lib/matplotlib/text.py branches/transforms/src/_backend_agg.cpp branches/transforms/ttconv/ttutil.cpp branches/transforms/unit/ellipse_compare.py Added Paths: ----------- branches/transforms/examples/units/annotate_with_units.py branches/transforms/examples/units/ellipse_with_units.py Property Changed: ---------------- branches/transforms/ Property changes on: branches/transforms ___________________________________________________________________ Name: svnmerge-integrated - /trunk/matplotlib:1-3932 + /trunk/matplotlib:1-3955 Modified: branches/transforms/CHANGELOG =================================================================== --- branches/transforms/CHANGELOG 2007-10-16 14:17:53 UTC (rev 3955) +++ branches/transforms/CHANGELOG 2007-10-16 14:35:12 UTC (rev 3956) @@ -1,3 +1,12 @@ +2007-10-15 Fixed a bug in patches.Ellipse that was broken for + aspect='auto'. Scale free ellipses now work properly for + equal and auto on Agg and PS, and they fall back on a + polygonal approximation for nonlinear transformations until + we convince oursleves that the spline approximation holds + for nonlinear transformations. Added + unit/ellipse_compare.py to compare spline with vertex + approx for both aspects. JDH + 2007-10-05 remove generator expressions from texmanager and mpltraits. generator expressions are not supported by python-2.3 - DSD Modified: branches/transforms/boilerplate.py =================================================================== --- branches/transforms/boilerplate.py 2007-10-16 14:17:53 UTC (rev 3955) +++ branches/transforms/boilerplate.py 2007-10-16 14:35:12 UTC (rev 3956) @@ -2,10 +2,9 @@ # file is pasted into pylab.py. We did try to do this the smart way, # with callable functions and new.function, but could never get the # docstrings right for python2.2. See -# http://groups-beta.google.com/group/comp.lang.python/messages/1b14640f3a4ad3dc,b3d7453af21e5f82,17739e70ac6f710c,9d5291fce29cbbb1,c5b578e4ffc6af28,056ff270daa2f414?thread_id=dcd63ec13096a0f6&mode=thread +# http://groups.google.com/group/comp.lang.python/browse_frm/thread/dcd63ec13096a0f6/1b14640f3a4ad3dc?#1b14640f3a4ad3dc - # note we check for __doc__ is not None since py2exe optimize removes # the docstrings Copied: branches/transforms/examples/units/annotate_with_units.py (from rev 3954, trunk/matplotlib/examples/units/annotate_with_units.py) =================================================================== --- branches/transforms/examples/units/annotate_with_units.py (rev 0) +++ branches/transforms/examples/units/annotate_with_units.py 2007-10-16 14:35:12 UTC (rev 3956) @@ -0,0 +1,27 @@ + +import pylab +from basic_units import cm + +fig = pylab.figure() +ax = fig.add_subplot(111) + + +ax.annotate( "Note 01", [0.5*cm, 0.5*cm] ) + +# xy and text both unitized +ax.annotate('local max', xy=(3*cm, 1*cm), xycoords='data', + xytext=(0.8*cm, 0.95*cm), textcoords='data', + arrowprops=dict(facecolor='black', shrink=0.05), + horizontalalignment='right', verticalalignment='top') + +# mixing units w/ nonunits +ax.annotate('local max', xy=(3*cm, 1*cm), xycoords='data', + xytext=(0.8, 0.95), textcoords='axes fraction', + arrowprops=dict(facecolor='black', shrink=0.05), + horizontalalignment='right', verticalalignment='top') + + +ax.set_xlim(0*cm, 4*cm) +ax.set_ylim(0*cm, 4*cm) +pylab.show() + Copied: branches/transforms/examples/units/ellipse_with_units.py (from rev 3954, trunk/matplotlib/examples/units/ellipse_with_units.py) =================================================================== --- branches/transforms/examples/units/ellipse_with_units.py (rev 0) +++ branches/transforms/examples/units/ellipse_with_units.py 2007-10-16 14:35:12 UTC (rev 3956) @@ -0,0 +1,49 @@ +""" +Compare the ellipse generated with arcs versus a polygonal approximation +""" +from basic_units import cm +import numpy as npy +from matplotlib import patches +from pylab import figure, show + +xcenter, ycenter = 0.38*cm, 0.52*cm +#xcenter, ycenter = 0., 0. +width, height = 1e-1*cm, 3e-1*cm +angle = -30 + +theta = npy.arange(0.0, 360.0, 1.0)*npy.pi/180.0 +x = 0.5 * width * npy.cos(theta) +y = 0.5 * height * npy.sin(theta) + +rtheta = angle*npy.pi/180. +R = npy.array([ + [npy.cos(rtheta), -npy.sin(rtheta)], + [npy.sin(rtheta), npy.cos(rtheta)], + ]) + + +x, y = npy.dot(R, npy.array([x, y])) +x += xcenter +y += ycenter + +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.Ellipse((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.Ellipse((xcenter, ycenter), width, height, + angle=angle, linewidth=2, fill=False, zorder=2) + + +ax.add_patch(e2) + +#fig.savefig('ellipse_compare.png') +fig.savefig('ellipse_compare') + +show() Modified: branches/transforms/lib/matplotlib/backends/backend_ps.py =================================================================== --- branches/transforms/lib/matplotlib/backends/backend_ps.py 2007-10-16 14:17:53 UTC (rev 3955) +++ branches/transforms/lib/matplotlib/backends/backend_ps.py 2007-10-16 14:35:12 UTC (rev 3956) @@ -331,7 +331,7 @@ size = prop.get_size_in_points() font.set_size(size, 72.0) return font - + def _rgba(self, im): return im.as_rgba_str() @@ -398,7 +398,7 @@ #print 'values', origin, flipud, figh, h, y if bbox is not None: - clipx,clipy,clipw,cliph = bbox.get_bounds() + clipx,clipy,clipw,cliph = bbox.bounds clip = '%s clipbox' % _nums_to_str(clipw, cliph, clipx, clipy) #y = figh-(y+h) ps = """gsave @@ -1425,5 +1425,15 @@ box clip newpath - } bind def""" + } bind def""", + """/unitcircle { + newpath +-1. 0. moveto +-1.0 0.552284749831 -0.552284749831 1.0 0.0 1.0 curveto +0.552284749831 1.0 1.0 0.552284749831 1.0 0.0 curveto +1.0 -0.552284749831 0.552284749831 -1.0 0.0 -1.0 curveto +-0.552284749831 -1.0 -1.0 -0.552284749831 -1.0 0.0 curveto +closepath + } bind def""", + ] Modified: branches/transforms/lib/matplotlib/cbook.py =================================================================== --- branches/transforms/lib/matplotlib/cbook.py 2007-10-16 14:17:53 UTC (rev 3955) +++ branches/transforms/lib/matplotlib/cbook.py 2007-10-16 14:35:12 UTC (rev 3956) @@ -232,17 +232,18 @@ except TypeError: return False else: return True -def to_filehandle(fname): +def to_filehandle(fname, flag='r'): """ fname can be a filename or a file handle. Support for gzipped - files is automatic, if the filename ends in .gz + files is automatic, if the filename ends in .gz. flag is a + read/write flag for file """ if is_string_like(fname): if fname.endswith('.gz'): import gzip - fh = gzip.open(fname) + fh = gzip.open(fname, flag) else: - fh = file(fname) + fh = file(fname, flag) elif hasattr(fname, 'seek'): fh = fname else: Modified: branches/transforms/lib/matplotlib/mlab.py =================================================================== --- branches/transforms/lib/matplotlib/mlab.py 2007-10-16 14:17:53 UTC (rev 3955) +++ branches/transforms/lib/matplotlib/mlab.py 2007-10-16 14:35:12 UTC (rev 3956) @@ -809,6 +809,8 @@ If p is a scalar, the largest value of x less than or equal to the p percentage point in the sequence is returned. """ + + x = npy.ravel(x) x.sort() Nx = len(x) @@ -1282,7 +1284,10 @@ converterd, if not None, is a dictionary mapping column number or munged column name to a converter function - See examples/loadrec.py + 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 converterd is None: @@ -1291,9 +1296,42 @@ import dateutil.parser parsedate = dateutil.parser.parse + fh = cbook.to_filehandle(fname) - reader = csv.reader(fh, delimiter=delimiter) + + class FH: + """ + for space delimited files, we want different behavior than + comma or tab. Generally, we want multiple spaces to be + treated as a single separator, whereas with comma and tab we + want multiple commas to return multiple (empty) fields. The + join/strip trick below effects this + """ + def __init__(self, fh): + self.fh = fh + + def close(self): + self.fh.close() + + def seek(self, arg): + self.fh.seek(arg) + + def fix(self, s): + return ' '.join(s.split()) + + + def next(self): + return self.fix(self.fh.next()) + + def __iter__(self): + for line in self.fh: + yield self.fix(line) + + if delimiter==' ': + fh = FH(fh) + + reader = csv.reader(fh, delimiter=delimiter) def process_skiprows(reader): if skiprows: for i, row in enumerate(reader): @@ -1388,9 +1426,131 @@ rows.append([func(val) for func, val in zip(converters, row)]) fh.close() + if not len(rows): + return None r = npy.rec.fromrecords(rows, names=names) return r + +def rec2csv(r, fname, delimiter=','): + """ + Save the data from numpy record array r into a comma/space/tab + delimited file. The record array dtype names will be used for + column headers. + + + fname - can be a filename or a file handle. Support for gzipped + files is automatic, if the filename ends in .gz + """ + fh = cbook.to_filehandle(fname, 'w') + writer = csv.writer(fh, delimiter=delimiter) + header = r.dtype.names + writer.writerow(header) + for row in r: + writer.writerow(map(str, row)) + fh.close() + +# some record array helpers +def rec_append_field(rec, name, arr, dtype=None): + 'return a new record array with field name populated with data from array arr' + arr = npy.asarray(arr) + if dtype is None: + dtype = arr.dtype + newdtype = npy.dtype(rec.dtype.descr + [(name, dtype)]) + newrec = npy.empty(rec.shape, dtype=newdtype) + for field in rec.dtype.fields: + newrec[field] = rec[field] + newrec[name] = arr + return newrec.view(npy.recarray) + + +def rec_drop_fields(rec, names): + 'return a new numpy record array with fields in names dropped' + + names = set(names) + Nr = len(rec) + + newdtype = npy.dtype([(name, rec.dtype[name]) for name in rec.dtype.names + if name not in names]) + + newrec = npy.empty(Nr, dtype=newdtype) + for field in newdtype.names: + newrec[field] = rec[field] + + return newrec.view(npy.recarray) + + +def rec_join(key, r1, r2): + """ + join record arrays r1 and r2 on key; key is a tuple of field + names. if r1 and r2 have equal values on all the keys in the key + tuple, then their fields will be merged into a new record array + containing the union of the fields of r1 and r2 + """ + + for name in key: + if name not in r1.dtype.names: + raise ValueError('r1 does not have key field %s'%name) + if name not in r2.dtype.names: + raise ValueError('r2 does not have key field %s'%name) + + def makekey(row): + return tuple([row[name] for name in key]) + + + names = list(r1.dtype.names) + [name for name in r2.dtype.names if name not in set(r1.dtype.names)] + + + + r1d = dict([(makekey(row),i) for i,row in enumerate(r1)]) + r2d = dict([(makekey(row),i) for i,row in enumerate(r2)]) + + r1keys = set(r1d.keys()) + r2keys = set(r2d.keys()) + + keys = r1keys & r2keys + + r1ind = [r1d[k] for k in keys] + r2ind = [r2d[k] for k in keys] + + + r1 = r1[r1ind] + r2 = r2[r2ind] + + r2 = rec_drop_fields(r2, r1.dtype.names) + + + def key_desc(name): + 'if name is a string key, use the larger size of r1 or r2 before merging' + dt1 = r1.dtype[name] + if dt1.type != npy.string_: + return (name, dt1.descr[0][1]) + + dt2 = r1.dtype[name] + assert dt2==dt1 + if dt1.num>dt2.num: + return (name, dt1.descr[0][1]) + else: + return (name, dt2.descr[0][1]) + + + + keydesc = [key_desc(name) for name in key] + + newdtype = npy.dtype(keydesc + + [desc for desc in r1.dtype.descr if desc[0] not in key ] + + [desc for desc in r2.dtype.descr if desc[0] not in key ] ) + + + newrec = npy.empty(len(r1), dtype=newdtype) + for field in r1.dtype.names: + newrec[field] = r1[field] + + for field in r2.dtype.names: + newrec[field] = r2[field] + + return newrec.view(npy.recarray) + def slopes(x,y): """ SLOPES calculate the slope y'(x) Given data vectors X and Y SLOPES Modified: branches/transforms/lib/matplotlib/patches.py =================================================================== --- branches/transforms/lib/matplotlib/patches.py 2007-10-16 14:17:53 UTC (rev 3955) +++ branches/transforms/lib/matplotlib/patches.py 2007-10-16 14:35:12 UTC (rev 3956) @@ -771,6 +771,32 @@ """ A scale-free ellipse """ + offset = 4.0 * (npy.sqrt(2) - 1) / 3.0 + + circle = npy.array([ + [-1.0, 0.0], + + [-1.0, offset], + [-offset, 1.0], + [0.0, 1.0], + + [offset, 1.0], + [1.0, offset], + [1.0, 0.0], + + [1.0, -offset], + [offset, -1.0], + [0.0, -1.0], + + [-offset, -1.0], + [-1.0, -offset], + [-1.0, 0.0], + + [-1.0, 0.0] + ], + npy.float_) + + def __str__(self): return "Ellipse(%d,%d;%dx%d)"%(self.center[0],self.center[1],self.width,self.height) @@ -807,8 +833,8 @@ if ev.x is None or ev.y is None: return False,{} x, y = self.get_transform().inverted().transform_point((ev.x, ev.y)) return (x*x + y*y) <= 1.0, {} + - class Circle(Ellipse): """ A circle patch Modified: branches/transforms/lib/matplotlib/text.py =================================================================== --- branches/transforms/lib/matplotlib/text.py 2007-10-16 14:17:53 UTC (rev 3955) +++ branches/transforms/lib/matplotlib/text.py 2007-10-16 14:35:12 UTC (rev 3956) @@ -1041,6 +1041,8 @@ def _get_xy(self, x, y, s): if s=='data': trans = self.axes.transData + x = float(self.convert_xunits(x)) + y = float(self.convert_yunits(y)) return trans.transform_point((x, y)) elif s=='polar': theta, r = x, y Modified: branches/transforms/src/_backend_agg.cpp =================================================================== --- branches/transforms/src/_backend_agg.cpp 2007-10-16 14:17:53 UTC (rev 3955) +++ branches/transforms/src/_backend_agg.cpp 2007-10-16 14:35:12 UTC (rev 3956) @@ -653,7 +653,6 @@ } - /** * This is a custom span generator that converts spans in the * 8-bit inverted greyscale font buffer to rgba that agg can use. @@ -776,11 +775,16 @@ srcbuf, 0, interpolator, filter); span_gen_type output_span_generator(&image_span_generator, gc.color); renderer_type ri(*rendererBase, output_span_generator); - agg::rasterizer_scanline_aa<> rasterizer; - agg::scanline_p8 scanline; - rasterizer.add_path(rect2); - agg::render_scanlines(rasterizer, scanline, ri); + //agg::rasterizer_scanline_aa<> rasterizer; + //agg::scanline_p8 scanline; + //rasterizer.add_path(rect2); + //agg::render_scanlines(rasterizer, scanline, ri); + + theRasterizer->add_path(rect2); + agg::render_scanlines(*theRasterizer, *slineP8, ri); + + return Py::Object(); } Modified: branches/transforms/ttconv/ttutil.cpp =================================================================== --- branches/transforms/ttconv/ttutil.cpp 2007-10-16 14:17:53 UTC (rev 3955) +++ branches/transforms/ttconv/ttutil.cpp 2007-10-16 14:35:12 UTC (rev 3956) @@ -32,14 +32,14 @@ va_start(arg_list, format); char buffer[PRINTF_BUFFER_SIZE]; -#ifdef WIN32 +#if defined(WIN32) || defined(_MSC_VER) int size = _vsnprintf(buffer, PRINTF_BUFFER_SIZE, format, arg_list); #else int size = vsnprintf(buffer, PRINTF_BUFFER_SIZE, format, arg_list); #endif if (size >= PRINTF_BUFFER_SIZE) { char* buffer2 = (char*)malloc(size); -#ifdef WIN32 +#if defined(WIN32) || defined(_MSC_VER) _vsnprintf(buffer2, size, format, arg_list); #else vsnprintf(buffer2, size, format, arg_list); Modified: branches/transforms/unit/ellipse_compare.py =================================================================== --- branches/transforms/unit/ellipse_compare.py 2007-10-16 14:17:53 UTC (rev 3955) +++ branches/transforms/unit/ellipse_compare.py 2007-10-16 14:35:12 UTC (rev 3956) @@ -27,27 +27,22 @@ fig = figure() ax = fig.add_subplot(211, aspect='auto') -ax.fill(x, y, alpha=0.2, facecolor='yellow') +ax.fill(x, y, alpha=0.2, facecolor='yellow', edgecolor='yellow', linewidth=1, zorder=1) e1 = patches.Ellipse((xcenter, ycenter), width, height, - angle=angle, linewidth=2, fill=False) + angle=angle, linewidth=2, fill=False, zorder=2) -ax.add_artist(e1) +ax.add_patch(e1) ax = fig.add_subplot(212, aspect='equal') -ax.fill(x, y, alpha=0.2, facecolor='yellow') +ax.fill(x, y, alpha=0.2, facecolor='green', edgecolor='green', zorder=1) e2 = patches.Ellipse((xcenter, ycenter), width, height, - angle=angle, linewidth=2, fill=False) + angle=angle, linewidth=2, fill=False, zorder=2) -ax.add_artist(e2) -ax.autoscale_view() +ax.add_patch(e2) - -ax.set_xlim(0.2, .5) -ax.set_ylim(0.3, 0.7) - #fig.savefig('ellipse_compare.png') -#fig.savefig('ellipse_compare.ps') +fig.savefig('ellipse_compare') show() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. ------------------------------------------------------------------------- This SF.net email is sponsored by: Splunk Inc. Still grepping through log files to find problems? Stop. Now Search log events and configuration files using AJAX and a browser. Download your FREE copy of Splunk now >> http://get.splunk.com/ _______________________________________________ Matplotlib-checkins mailing list Matplotlib-checkins@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins