Revision: 3847 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3847&view=rev Author: mdboom Date: 2007-09-13 05:50:05 -0700 (Thu, 13 Sep 2007)
Log Message: ----------- Merged revisions 3836-3846 via svnmerge from http://matplotlib.svn.sf.net/svnroot/matplotlib/trunk/matplotlib ........ r3844 | jdh2358 | 2007-09-12 16:37:41 -0400 (Wed, 12 Sep 2007) | 1 line fixed a bar units bug ........ r3845 | jouni | 2007-09-13 02:29:14 -0400 (Thu, 13 Sep 2007) | 3 lines More work on dviread and usetex in pdf. It is more usable now, so I am renaming the method from _draw_tex to draw_tex. ........ Modified Paths: -------------- branches/transforms/API_CHANGES branches/transforms/CHANGELOG branches/transforms/lib/matplotlib/artist.py branches/transforms/lib/matplotlib/axes.py branches/transforms/lib/matplotlib/axis.py branches/transforms/lib/matplotlib/backends/backend_pdf.py branches/transforms/lib/matplotlib/dviread.py branches/transforms/lib/matplotlib/mlab.py branches/transforms/lib/matplotlib/patches.py Added Paths: ----------- branches/transforms/examples/units/bar_demo2.py Property Changed: ---------------- branches/transforms/ Property changes on: branches/transforms ___________________________________________________________________ Name: svnmerge-integrated - /trunk/matplotlib:1-3835 + /trunk/matplotlib:1-3846 Modified: branches/transforms/API_CHANGES =================================================================== --- branches/transforms/API_CHANGES 2007-09-13 12:44:16 UTC (rev 3846) +++ branches/transforms/API_CHANGES 2007-09-13 12:50:05 UTC (rev 3847) @@ -1,3 +1,5 @@ + Made skiprows=1 the default on csv2rec + The gd and paint backends have been deleted. The errorbar method and function now accept additional kwargs Modified: branches/transforms/CHANGELOG =================================================================== --- branches/transforms/CHANGELOG 2007-09-13 12:44:16 UTC (rev 3846) +++ branches/transforms/CHANGELOG 2007-09-13 12:50:05 UTC (rev 3847) @@ -1,3 +1,10 @@ +2007-09-13 The usetex support in the pdf backend is more usable now, + so I am enabling it. - JKS + +2007-09-12 Fixed a Axes.bar unit bug - JDH + +2007-09-10 Made skiprows=1 the default on csv2rec - JDH + 2007-09-09 Split out the plotting part of pylab and put it in pyplot.py; removed numerix from the remaining pylab.py, which imports everything from pyplot.py. The intention Copied: branches/transforms/examples/units/bar_demo2.py (from rev 3845, trunk/matplotlib/examples/units/bar_demo2.py) =================================================================== --- branches/transforms/examples/units/bar_demo2.py (rev 0) +++ branches/transforms/examples/units/bar_demo2.py 2007-09-13 12:50:05 UTC (rev 3847) @@ -0,0 +1,34 @@ +""" +plot using a variety of cm vs inches conversions. The example shows +how default unit instrospection works (ax1), how various keywords can +be used to set the x and y units to override the defaults (ax2, ax3, +ax4) and how one can set the xlimits using scalars (ax3, current units +assumed) or units (conversions applied to get the numbers to current +units) + +""" +from basic_units import cm, inch +from pylab import figure, show, nx + +cms = cm *nx.arange(0, 10, 2) +bottom=0*cm +width=0.8*cm + +fig = figure() + +ax1 = fig.add_subplot(2,2,1) +ax1.bar(cms, cms, bottom=bottom) + +ax2 = fig.add_subplot(2,2,2) +ax2.bar(cms, cms, bottom=bottom, width=width, xunits=cm, yunits=inch) + +ax3 = fig.add_subplot(2,2,3) +ax3.bar(cms, cms, bottom=bottom, width=width, xunits=inch, yunits=cm) +ax3.set_xlim(3, 6) # scalars are interpreted in current units + +ax4 = fig.add_subplot(2,2,4) +ax4.bar(cms, cms, bottom=bottom, width=width, xunits=inch, yunits=inch) +#fig.savefig('simple_conversion_plot.png') +ax4.set_xlim(3*cm, 6*cm) # cm are converted to inches + +show() Modified: branches/transforms/lib/matplotlib/artist.py =================================================================== --- branches/transforms/lib/matplotlib/artist.py 2007-09-13 12:44:16 UTC (rev 3846) +++ branches/transforms/lib/matplotlib/artist.py 2007-09-13 12:50:05 UTC (rev 3847) @@ -51,7 +51,7 @@ self._remove_method = None def remove(self): - ''' + """ Remove the artist from the figure if possible. The effect will not be visible until the figure is redrawn, e.g., with ax.draw_idle(). Call ax.relim() to update the axes limits if desired. @@ -60,7 +60,7 @@ was added to axes with autolim=True. Note: there is no support for removing the artist's legend entry. - ''' + """ # There is no method to set the callback. Instead the parent should set # the _remove_method attribute directly. This would be a protected Modified: branches/transforms/lib/matplotlib/axes.py =================================================================== --- branches/transforms/lib/matplotlib/axes.py 2007-09-13 12:44:16 UTC (rev 3846) +++ branches/transforms/lib/matplotlib/axes.py 2007-09-13 12:50:05 UTC (rev 3847) @@ -1193,23 +1193,27 @@ def _process_unit_info(self, xdata=None, ydata=None, kwargs=None): 'look for unit kwargs and update the axis instances as necessary' - if self.xaxis is None or self.xaxis is None: return + if self.xaxis is None or self.yaxis is None: return - + #print 'processing', self.get_geometry() if xdata is not None: self.xaxis.update_units(xdata) + #print '\tset from xdata', self.xaxis.units if ydata is not None: self.yaxis.update_units(ydata) + #print '\tset from ydata', self.yaxis.units # process kwargs 2nd since these will override default units if kwargs is not None: xunits = kwargs.pop( 'xunits', self.xaxis.units) if xunits!=self.xaxis.units: + #print '\tkw setting xunits', xunits self.xaxis.set_units(xunits) yunits = kwargs.pop('yunits', self.yaxis.units) if yunits!=self.yaxis.units: + #print '\tkw setting yunits', yunits self.yaxis.set_units(yunits) def in_axes(self, xwin, ywin): @@ -3122,11 +3126,13 @@ else: raise ValueError, 'invalid orientation: %s' % orientation - left = npy.asarray(left) - height = npy.asarray(height) - width = npy.asarray(width) - bottom = npy.asarray(bottom) + # do not convert to array here as unit info is lost + #left = npy.asarray(left) + #height = npy.asarray(height) + #width = npy.asarray(width) + #bottom = npy.asarray(bottom) + if len(linewidth) == 1: linewidth = linewidth * nbars # if color looks like a color string, an RGB tuple or a @@ -3169,14 +3175,14 @@ # lets do some conversions now if self.xaxis is not None: xconv = self.xaxis.converter - if ( xconv ): + if xconv is not None: units = self.xaxis.get_units() left = xconv.convert( left, units ) width = xconv.convert( width, units ) if self.yaxis is not None: yconv = self.yaxis.converter - if ( yconv ): + if yconv is not None : units = self.yaxis.get_units() bottom = yconv.convert( bottom, units ) height = yconv.convert( height, units ) @@ -3216,12 +3222,14 @@ if xerr is not None or yerr is not None: if orientation == 'vertical': - x = left + 0.5*width - y = bottom + height + # using list comps rather than arrays to preserve unit info + x = [l+0.5*w for l, w in zip(left, width)] + y = [b+h for b,h in zip(bottom, height)] elif orientation == 'horizontal': - x = left + width - y = bottom + 0.5*height + # using list comps rather than arrays to preserve unit info + x = [l+w for l,w in zip(left, width)] + y = [b+0.5*h for b,h in zip(bottom, height)] self.errorbar( x, y, Modified: branches/transforms/lib/matplotlib/axis.py =================================================================== --- branches/transforms/lib/matplotlib/axis.py 2007-09-13 12:44:16 UTC (rev 3846) +++ branches/transforms/lib/matplotlib/axis.py 2007-09-13 12:50:05 UTC (rev 3847) @@ -821,7 +821,7 @@ return x ret = self.converter.convert(x, self.units) - #print 'convert_units converting: units=%s, converter=%s, in=%s, out=%s'%(self.units, self.converter, x, ret) + #print 'convert_units converting: axis=%s, units=%s, converter=%s, in=%s, out=%s'%(self, self.units, self.converter, x, ret) return ret def set_units(self, u): Modified: branches/transforms/lib/matplotlib/backends/backend_pdf.py =================================================================== --- branches/transforms/lib/matplotlib/backends/backend_pdf.py 2007-09-13 12:44:16 UTC (rev 3846) +++ branches/transforms/lib/matplotlib/backends/backend_pdf.py 2007-09-13 12:50:05 UTC (rev 3847) @@ -527,7 +527,7 @@ widths.append(afmdata.get_width_from_char_name(ch)) except KeyError: matplotlib.verbose.report( - 'No width for %s in %s' % (ch, fullname), 'debug') + 'No width for %s in %s' % (ch, fullname), 'debug-annoying') widths.append(0) differencesArray = [ Name(ch) for ch in enc ] @@ -561,7 +561,7 @@ except KeyError: matplotlib.verbose.report( 'No name for glyph %d in %s' % (ch, fullname), - 'debug') + 'debug-annoying') need_idx = True @@ -1449,9 +1449,7 @@ # Pop off the global transformation self.file.output(Op.grestore) - def _draw_tex(self, gc, x, y, s, prop, angle): - # Rename to draw_tex to enable - + def draw_tex(self, gc, x, y, s, prop, angle): texmanager = self.get_texmanager() fontsize = prop.get_size_in_points() dvifile = texmanager.make_dvi(s, fontsize) @@ -1494,7 +1492,7 @@ elt[3][-1] += next[3][0] elt[4] += next[4]-next[1] else: - elt[3] += [offset, next[3][0]] + elt[3] += [offset*1000.0/dvifont.size, next[3][0]] elt[4] = next[4] del seq[i+1] continue Modified: branches/transforms/lib/matplotlib/dviread.py =================================================================== --- branches/transforms/lib/matplotlib/dviread.py 2007-09-13 12:44:16 UTC (rev 3846) +++ branches/transforms/lib/matplotlib/dviread.py 2007-09-13 12:50:05 UTC (rev 3847) @@ -84,16 +84,22 @@ e = 0 # zero depth else: # glyph x,y,font,g,w = elt - h = (font.scale * font.tfm.height[g]) >> 20 - e = (font.scale * font.tfm.depth[g]) >> 20 + h = _mul2012(font._scale, font._tfm.height[g]) + e = _mul2012(font._scale, font._tfm.depth[g]) minx = min(minx, x) miny = min(miny, y - h) maxx = max(maxx, x + w) maxy = max(maxy, y + e) maxy_pure = max(maxy_pure, y) + if self.dpi is None: + # special case for ease of debugging: output raw dvi coordinates + return mpl_cbook.Bunch(text=self.text, boxes=self.boxes, + width=maxx-minx, height=maxy_pure-miny, + descent=maxy-maxy_pure) + d = self.dpi / (72.27 * 2**16) # from TeX's "scaled points" to dpi units - text = [ ((x-minx)*d, (maxy-y)*d, DviFont(f), g, w*d) + text = [ ((x-minx)*d, (maxy-y)*d, f, g, w*d) for (x,y,f,g,w) in self.text ] boxes = [ ((x-minx)*d, (maxy-y)*d, h*d, w*d) for (x,y,h,w) in self.boxes ] @@ -110,11 +116,11 @@ while True: byte = ord(self.file.read(1)) self._dispatch(byte) - if self.state == _dvistate.inpage: - matplotlib.verbose.report( - 'Dvi._read: after %d at %f,%f' % - (byte, self.h, self.v), - 'debug-annoying') +# if self.state == _dvistate.inpage: +# matplotlib.verbose.report( +# 'Dvi._read: after %d at %f,%f' % +# (byte, self.h, self.v), +# 'debug-annoying') if byte == 140: # end of page return True if self.state == _dvistate.post_post: # end of file @@ -225,21 +231,11 @@ # I think we can assume this is constant self.state = _dvistate.outer - def _width_of(self, char, font): - width = font.tfm.width.get(char, None) - if width is not None: - return (width * font.scale) >> 20 - - matplotlib.verbose.report( - 'No width for char %d in font %s' % (char, font.name), - 'debug') - return 0 - def _set_char(self, char): if self.state != _dvistate.inpage: raise ValueError, "misplaced set_char in dvi file" self._put_char(char) - self.h += self._width_of(char, self.fonts[self.f]) + self.h += self.fonts[self.f]._width_of(char) def _set_rule(self, a, b): if self.state != _dvistate.inpage: @@ -251,20 +247,33 @@ if self.state != _dvistate.inpage: raise ValueError, "misplaced put_char in dvi file" font = self.fonts[self.f] - if font.vf is None: + if font._vf is None: self.text.append((self.h, self.v, font, char, - self._width_of(char, font))) + font._width_of(char))) +# matplotlib.verbose.report( +# 'Dvi._put_char: %d,%d %d' %(self.h, self.v, char), +# 'debug-annoying') else: - self.text.extend([(self.h + x, self.v + y, f, g, w) - for x, y, f, g, w in font.vf[char].text]) - self.boxes.extend([(self.h + x, self.v + y, a, b) - for x, y, a, b in font.vf[char].boxes]) + scale = font._scale + for x, y, f, g, w in font._vf[char].text: + newf = DviFont(scale=_mul2012(scale, f._scale), + tfm=f._tfm, texname=f.texname, vf=f._vf) + self.text.append((self.h + _mul2012(x, scale), + self.v + _mul2012(y, scale), + newf, g, newf._width_of(g))) + self.boxes.extend([(self.h + _mul2012(x, scale), + self.v + _mul2012(y, scale), + _mul2012(a, scale), _mul2012(b, scale)) + for x, y, a, b in font._vf[char].boxes]) def _put_rule(self, a, b): if self.state != _dvistate.inpage: raise ValueError, "misplaced put_rule in dvi file" if a > 0 and b > 0: self.boxes.append((self.h, self.v, a, b)) +# matplotlib.verbose.report( +# 'Dvi._put_rule: %d,%d %d,%d' % (self.h, self.v, a, b), +# 'debug-annoying') def _nop(self): pass @@ -357,7 +366,7 @@ vf = _vffile(n[-l:]) - self.fonts[k] = mpl_cbook.Bunch(scale=s, tfm=tfm, name=n, vf=vf) + self.fonts[k] = DviFont(scale=s, tfm=tfm, texname=n, vf=vf) def _post(self): if self.state != _dvistate.outer: @@ -370,17 +379,20 @@ raise NotImplementedError class DviFont(object): - __slots__ = ('texname', 'size') + """ + Object that holds a font's texname and size and supports comparison. + There are also internal attributes (for use by dviread.py) that + are _not_ used for comparison. - def __init__(self, f): - """ - Object that holds a font's texname and size and supports comparison. + The size is in Adobe points (converted from TeX points). + """ + __slots__ = ('texname', 'size', '_scale', '_vf', '_tfm') - The size is in Adobe points (converted from TeX points). - """ + def __init__(self, scale, tfm, texname, vf): + self._scale, self._tfm, self.texname, self._vf = \ + scale, tfm, texname, vf # TODO: would it make more sense to have the size in dpi units? - self.texname = f.name - self.size = f.scale * (72.0 / (72.27 * 2**16)) + self.size = scale * (72.0 / (72.27 * 2**16)) def __eq__(self, other): return self.__class__ == other.__class__ and \ @@ -389,6 +401,16 @@ def __ne__(self, other): return not self.__eq__(other) + def _width_of(self, char): + width = self._tfm.width.get(char, None) + if width is not None: + return _mul2012(width, self._scale) + + matplotlib.verbose.report( + 'No width for char %d in font %s' % (char, self.texname), + 'debug') + return 0 + class Vf(Dvi): """ A virtual font (*.vf file) containing subroutines for dvi files. @@ -465,7 +487,8 @@ raise ValueError, "pre command in middle of vf file" if i != 202: raise ValueError, "Unknown vf format %d" % i - matplotlib.verbose.report('vf file comment: ' + x, 'debug') + if len(x): + matplotlib.verbose.report('vf file comment: ' + x, 'debug') self.state = _dvistate.outer # cs = checksum, ds = design size @@ -474,7 +497,7 @@ if self._first_font is None: self._first_font = k -def fix2comp(num): +def _fix2comp(num): """ Convert from two's complement to negative. """ @@ -484,6 +507,13 @@ else: return num +def _mul2012(num1, num2): + """ + Multiply two numbers in 20.12 fixed point format. + """ + # Separated into a function because >> has surprising precedence + return (num1*num2) >> 20 + class Tfm(object): """ A TeX Font Metric file. This implementation covers only the bare @@ -497,6 +527,7 @@ (this is a dict because indexing may not start from 0) height[i], depth[i]: height and depth of character #i """ + __slots__ = ('checksum', 'design_size', 'width', 'height', 'depth') def __init__(self, filename): matplotlib.verbose.report('opening tfm file ' + filename, 'debug') @@ -525,9 +556,9 @@ [ struct.unpack('!%dI' % (len(x)/4), x) for x in (widths, heights, depths) ] for i in range(ec-bc): - self.width[bc+i] = fix2comp(widths[ord(char_info[4*i])]) - self.height[bc+i] = fix2comp(heights[ord(char_info[4*i+1]) >> 4]) - self.depth[bc+i] = fix2comp(depths[ord(char_info[4*i+1]) & 0xf]) + self.width[bc+i] = _fix2comp(widths[ord(char_info[4*i])]) + self.height[bc+i] = _fix2comp(heights[ord(char_info[4*i+1]) >> 4]) + self.depth[bc+i] = _fix2comp(depths[ord(char_info[4*i+1]) & 0xf]) class PsfontsMap(object): @@ -552,6 +583,7 @@ the pdf-related files perhaps only avoid the "Base 14" pdf fonts. But the user may have configured these files differently. """ + __slots__ = ('_font',) def __init__(self, filename): self._font = {} @@ -627,7 +659,17 @@ encoding=encoding, filename=filename) class Encoding(object): + """ + Parses a *.enc file referenced from a psfonts.map style file. + The format this class understands is a very limited subset of + PostScript. + Usage (subject to change): + for name in Encoding(filename): + whatever(name) + """ + __slots__ = ('encoding',) + def __init__(self, filename): file = open(filename, 'rt') try: @@ -694,6 +736,10 @@ return result +# With multiple text objects per figure (e.g. tick labels) we may end +# up reading the same tfm and vf files many times, so we implement a +# simple cache. TODO: is this worth making persistent? + _tfmcache = {} _vfcache = {} @@ -721,19 +767,22 @@ if __name__ == '__main__': - matplotlib.verbose.set_level('debug') - dvi = Dvi('foo.dvi', 72) + import sys + matplotlib.verbose.set_level('debug-annoying') + fname = sys.argv[1] + try: dpi = float(sys.argv[2]) + except IndexError: dpi = None + dvi = Dvi(fname, dpi) fontmap = PsfontsMap(find_tex_file('pdftex.map')) - for text,boxes in dvi: + for page in dvi: print '=== new page ===' fPrev = None - for x,y,f,c in text: - texname = dvi.fonts[f].name - print x,y,c,chr(c),texname + for x,y,f,c,w in page.text: if f != fPrev: - print 'font', texname, '=', fontmap[texname].__dict__ + print 'font', f.texname, 'scaled', f._scale/pow(2.0,20) fPrev = f - for x,y,w,h in boxes: + print x,y,c, 32 <= c < 128 and chr(c) or '.', w + for x,y,w,h in page.boxes: print x,y,'BOX',w,h Modified: branches/transforms/lib/matplotlib/mlab.py =================================================================== --- branches/transforms/lib/matplotlib/mlab.py 2007-09-13 12:44:16 UTC (rev 3846) +++ branches/transforms/lib/matplotlib/mlab.py 2007-09-13 12:50:05 UTC (rev 3847) @@ -1253,9 +1253,9 @@ if r==1 or c==1: X.shape = max(r,c), if unpack: return X.transpose() - return X + else: return X -def csv2rec(fname, comments='#', skiprows=0, checkrows=5, delimiter=',', +def csv2rec(fname, comments='#', skiprows=1, checkrows=5, delimiter=',', converterd=None, names=None, missing=None): """ Load data from comma/space/tab delimited file in fname into a Modified: branches/transforms/lib/matplotlib/patches.py =================================================================== --- branches/transforms/lib/matplotlib/patches.py 2007-09-13 12:44:16 UTC (rev 3846) +++ branches/transforms/lib/matplotlib/patches.py 2007-09-13 12:50:05 UTC (rev 3847) @@ -77,6 +77,8 @@ if len(kwargs): artist.setp(self, **kwargs) __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd + + def contains(self, mouseevent): """Test whether the mouse event occurred in the patch. @@ -352,7 +354,6 @@ Return the vertices of the rectangle """ x, y = self.xy - left, right = self.convert_xunits((x, x + self.width)) bottom, top = self.convert_yunits((y, y + self.height)) 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: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2005. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ _______________________________________________ Matplotlib-checkins mailing list Matplotlib-checkins@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins