You can subscribe to this list here.
2007 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
(115) |
Aug
(120) |
Sep
(137) |
Oct
(170) |
Nov
(461) |
Dec
(263) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2008 |
Jan
(120) |
Feb
(74) |
Mar
(35) |
Apr
(74) |
May
(245) |
Jun
(356) |
Jul
(240) |
Aug
(115) |
Sep
(78) |
Oct
(225) |
Nov
(98) |
Dec
(271) |
2009 |
Jan
(132) |
Feb
(84) |
Mar
(74) |
Apr
(56) |
May
(90) |
Jun
(79) |
Jul
(83) |
Aug
(296) |
Sep
(214) |
Oct
(76) |
Nov
(82) |
Dec
(66) |
2010 |
Jan
(46) |
Feb
(58) |
Mar
(51) |
Apr
(77) |
May
(58) |
Jun
(126) |
Jul
(128) |
Aug
(64) |
Sep
(50) |
Oct
(44) |
Nov
(48) |
Dec
(54) |
2011 |
Jan
(68) |
Feb
(52) |
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(1) |
2018 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
S | M | T | W | T | F | S |
---|---|---|---|---|---|---|
|
|
|
|
|
|
1
|
2
(1) |
3
(4) |
4
(9) |
5
(14) |
6
(8) |
7
(14) |
8
(1) |
9
(2) |
10
(9) |
11
(5) |
12
(11) |
13
(4) |
14
(4) |
15
(1) |
16
|
17
(1) |
18
(2) |
19
(4) |
20
(10) |
21
(3) |
22
(3) |
23
(2) |
24
(8) |
25
(6) |
26
(5) |
27
|
28
(3) |
29
|
30
(3) |
|
|
|
|
|
|
From: <ef...@us...> - 2007-09-30 20:47:58
|
Revision: 3903 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3903&view=rev Author: efiring Date: 2007-09-30 13:47:55 -0700 (Sun, 30 Sep 2007) Log Message: ----------- Apply patch by Leon Barrett, tracker #1798196 Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes3d.py Modified: trunk/matplotlib/lib/matplotlib/axes3d.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes3d.py 2007-09-30 20:32:31 UTC (rev 3902) +++ trunk/matplotlib/lib/matplotlib/axes3d.py 2007-09-30 20:47:55 UTC (rev 3903) @@ -515,11 +515,11 @@ ps = [] corners = [] for a,ta in [(X,tX),(Y,tY),(Z,tZ)]: - ztop = a[rs][cs:min(cols-1,cs+cstride)] + 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-1,rs+rstride):] + zright = ta[cs][rs:min(rows,rs+rstride+1):] zright = zright[::-1] corners.append([ztop[0],ztop[-1],zbase[0],zbase[-1]]) z = npy.concatenate((ztop,zleft,zbase,zright)) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ef...@us...> - 2007-09-30 20:32:33
|
Revision: 3902 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3902&view=rev Author: efiring Date: 2007-09-30 13:32:31 -0700 (Sun, 30 Sep 2007) Log Message: ----------- bugfix by Zack, confirmed by Gary Ruben. http://sourceforge.net/mailarchive/forum.php?thread_name=d8cf9020703071339y43354eaerbfa1a47d272e5d26%40mail.gmail.com&forum_name=matplotlib-users Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axes3d.py Modified: trunk/matplotlib/lib/matplotlib/axes3d.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axes3d.py 2007-09-30 20:08:50 UTC (rev 3901) +++ trunk/matplotlib/lib/matplotlib/axes3d.py 2007-09-30 20:32:31 UTC (rev 3902) @@ -510,8 +510,8 @@ # polys = [] boxes = [] - for rs in npy.arange(0,rows,rstride): - for cs in npy.arange(0,cols,cstride): + for rs in npy.arange(0,rows-1,rstride): + for cs in npy.arange(0,cols-1,cstride): ps = [] corners = [] for a,ta in [(X,tX),(Y,tY),(Z,tZ)]: This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jo...@us...> - 2007-09-30 20:08:57
|
Revision: 3901 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3901&view=rev Author: jouni Date: 2007-09-30 13:08:50 -0700 (Sun, 30 Sep 2007) Log Message: ----------- use_tex in pdf backend: don't use AFM files, which are not there in some TeX distros Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py trunk/matplotlib/lib/matplotlib/dviread.py Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2007-09-28 15:57:49 UTC (rev 3900) +++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2007-09-30 20:08:50 UTC (rev 3901) @@ -500,70 +500,15 @@ finally: fh.close() - fh = open(fontinfo.afmfile, 'rb') - matplotlib.verbose.report( - 'Reading metrics from ' + fontinfo.afmfile, 'debug') - try: - afmdata = AFM(fh) - finally: - fh.close() - font = FT2Font(filename) - font.attach_file(fontinfo.afmfile) widthsObject, fontdescObject, fontdictObject, fontfileObject = \ [ self.reserveObject(n) for n in ('font widths', 'font descriptor', 'font dictionary', 'font file') ] - _, _, fullname, familyname, weight, italic_angle, fixed_pitch, \ - ul_position, ul_thickness = font.get_ps_font_info() - - if fontinfo.encodingfile is not None: - enc = dviread.Encoding(fontinfo.encodingfile) - widths = [] - for ch in enc: - try: - widths.append(afmdata.get_width_from_char_name(ch)) - except KeyError: - matplotlib.verbose.report( - 'No width for %s in %s' % (ch, fullname), 'debug-annoying') - widths.append(0) - - differencesArray = [ Name(ch) for ch in enc ] - differencesArray = [ 0 ] + differencesArray - firstchar = 0 - lastchar = len(differencesArray) - 2 - else: - widths = [ None for i in range(256) ] - for ch in range(256): - try: - widths[ch] = afmdata.get_width_char(ch, isord=True) - except KeyError: - pass - not_None = [ch for ch in range(256) - if widths[ch] is not None] - firstchar = not_None[0] - lastchar = not_None[-1] - widths = widths[firstchar:lastchar+1] - for i,w in enumerate(widths): - if w is None: widths[i] = 0 - - differencesArray = [ ] - need_idx = True - for ch in range(firstchar, lastchar+1): - try: - name = afmdata.get_name_char(ch, isord=True) - if need_idx: - differencesArray.append(ch) - need_idx = False - differencesArray.append(Name(name)) - except KeyError: - matplotlib.verbose.report( - 'No name for glyph %d in %s' % (ch, fullname), - 'debug-annoying') - need_idx = True - + firstchar = 0 + lastchar = len(fontinfo.widths) - 1 fontdict = { 'Type': Name('Font'), @@ -575,15 +520,22 @@ 'FontDescriptor': fontdescObject, } - fontdict.update({ - 'Encoding': { 'Type': Name('Encoding'), - 'Differences': differencesArray }, - }) + if fontinfo.encodingfile is not None: + enc = dviread.Encoding(fontinfo.encodingfile) + differencesArray = [ Name(ch) for ch in enc ] + differencesArray = [ 0 ] + differencesArray + fontdict.update({ + 'Encoding': { 'Type': Name('Encoding'), + 'Differences': differencesArray }, + }) + _, _, fullname, familyname, weight, italic_angle, fixed_pitch, \ + ul_position, ul_thickness = font.get_ps_font_info() + flags = 0 if fixed_pitch: flags |= 1 << 0 # fixed width if 0: flags |= 1 << 1 # TODO: serif - if 1: flags |= 1 << 2 # TODO: symbolic + if 1: flags |= 1 << 2 # TODO: symbolic (most TeX fonts are) else: flags |= 1 << 5 # non-symbolic if italic_angle: flags |= 1 << 6 # italic if 0: flags |= 1 << 16 # TODO: all caps @@ -598,33 +550,17 @@ 'ItalicAngle': italic_angle, 'Ascent': font.ascender, 'Descent': font.descender, - 'CapHeight': 1000, # default guess if missing from AFM file - 'XHeight': afmdata.get_xheight(), + 'CapHeight': 1000, # TODO: find this out + 'XHeight': 500, # TODO: this one too 'FontFile': fontfileObject, 'FontFamily': familyname, + 'StemV': 50, # TODO + # (see also revision 3874; but not all TeX distros have AFM files!) #'FontWeight': a number where 400 = Regular, 700 = Bold } - try: - descriptor['CapHeight'] = afmdata.get_capheight() - except KeyError: - pass - # StemV is obligatory in PDF font descriptors but optional in - # AFM files. The collection of AFM files in my TeX Live 2007 - # collection has values ranging from 22 to 219, with both - # median and mode 50, so if the AFM file is silent, I'm - # guessing 50. -JKS - StemV = afmdata.get_vertical_stem_width() - if StemV is None: StemV = 50 - descriptor['StemV'] = StemV - - # StemH is entirely optional: - StemH = afmdata.get_horizontal_stem_width() - if StemH is not None: - descriptor['StemH'] = StemH - self.writeObject(fontdictObject, fontdict) - self.writeObject(widthsObject, widths) + self.writeObject(widthsObject, fontinfo.widths) self.writeObject(fontdescObject, descriptor) t1font = type1font.Type1Font(filename) @@ -1470,16 +1406,13 @@ oldfont, seq = None, [] for x1, y1, dvifont, glyph, width in page.text: if dvifont != oldfont: - fontinfo = self.tex_font_mapping(dvifont.texname) - pdfname = self.file.fontName(fontinfo.filename) - if not fontinfo.afm: - matplotlib.verbose.report( - 'RendererPdf.draw_tex: No AFM file found for %s (%s)' \ - % (dvifont.texname, fontinfo.filename), - 'helpful') - self.file.fontInfo[pdfname] = Bunch( - encodingfile=fontinfo.encoding, - afmfile=fontinfo.afm) + psfont = self.tex_font_mapping(dvifont.texname) + pdfname = self.file.fontName(psfont.filename) + if self.file.fontInfo.get(pdfname, None) is None: + self.file.fontInfo[pdfname] = Bunch( + encodingfile=psfont.encoding, + widths=dvifont.widths, + dvifont=dvifont) seq += [['font', pdfname, dvifont.size]] oldfont = dvifont seq += [['text', x1, y1, [chr(glyph)], x1+width]] Modified: trunk/matplotlib/lib/matplotlib/dviread.py =================================================================== --- trunk/matplotlib/lib/matplotlib/dviread.py 2007-09-28 15:57:49 UTC (rev 3900) +++ trunk/matplotlib/lib/matplotlib/dviread.py 2007-09-30 20:08:50 UTC (rev 3901) @@ -84,7 +84,7 @@ e = 0 # zero depth else: # glyph x,y,font,g,w = elt - h = _mul2012(font._scale, font._tfm.height[g]) + 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) @@ -380,19 +380,21 @@ class DviFont(object): """ - Object that holds a font's texname and size and supports comparison. + Object that holds a font's texname and size, supports comparison, + and knows the widths of glyphs in the same units as the AFM file. There are also internal attributes (for use by dviread.py) that are _not_ used for comparison. The size is in Adobe points (converted from TeX points). """ - __slots__ = ('texname', 'size', '_scale', '_vf', '_tfm') + __slots__ = ('texname', 'size', 'widths', '_scale', '_vf', '_tfm') 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.size = scale * (72.0 / (72.27 * 2**16)) + self.widths = [ (1000*tfm.width.get(char, 0)) >> 20 + for char in range(0, max(tfm.width)) ] def __eq__(self, other): return self.__class__ == other.__class__ and \ @@ -402,6 +404,10 @@ return not self.__eq__(other) def _width_of(self, char): + """ + Width of char in dvi units. For internal use by dviread.py. + """ + width = self._tfm.width.get(char, None) if width is not None: return _mul2012(width, self._scale) @@ -598,7 +604,6 @@ fn, enc = result.filename, result.encoding if fn is not None and not fn.startswith('/'): result.filename = find_tex_file(fn) - result.afm = find_tex_file(fn[:-4] + '.afm') if enc is not None and not enc.startswith('/'): result.encoding = find_tex_file(result.encoding) return result This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jo...@us...> - 2007-09-28 15:57:52
|
Revision: 3900 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3900&view=rev Author: jouni Date: 2007-09-28 08:57:49 -0700 (Fri, 28 Sep 2007) Log Message: ----------- More debugging output when using TeX with the pdf backend Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py trunk/matplotlib/lib/matplotlib/dviread.py Modified: trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2007-09-28 15:50:01 UTC (rev 3899) +++ trunk/matplotlib/lib/matplotlib/backends/backend_pdf.py 2007-09-28 15:57:49 UTC (rev 3900) @@ -1472,6 +1472,11 @@ if dvifont != oldfont: fontinfo = self.tex_font_mapping(dvifont.texname) pdfname = self.file.fontName(fontinfo.filename) + if not fontinfo.afm: + matplotlib.verbose.report( + 'RendererPdf.draw_tex: No AFM file found for %s (%s)' \ + % (dvifont.texname, fontinfo.filename), + 'helpful') self.file.fontInfo[pdfname] = Bunch( encodingfile=fontinfo.encoding, afmfile=fontinfo.afm) Modified: trunk/matplotlib/lib/matplotlib/dviread.py =================================================================== --- trunk/matplotlib/lib/matplotlib/dviread.py 2007-09-28 15:50:01 UTC (rev 3899) +++ trunk/matplotlib/lib/matplotlib/dviread.py 2007-09-28 15:57:49 UTC (rev 3900) @@ -734,6 +734,9 @@ result = pipe.readline().rstrip() pipe.close() + matplotlib.verbose.report('find_tex_file: %s -> %s' \ + % (filename, result), + 'debug') return result # With multiple text objects per figure (e.g. tick labels) we may end This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jo...@us...> - 2007-09-28 15:50:29
|
Revision: 3899 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3899&view=rev Author: jouni Date: 2007-09-28 08:50:01 -0700 (Fri, 28 Sep 2007) Log Message: ----------- Catch UnboundLocalError in checkdep_pdftops; it is raised if no output line of pdftops -v contains the word "version". Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/__init__.py Modified: trunk/matplotlib/lib/matplotlib/__init__.py =================================================================== --- trunk/matplotlib/lib/matplotlib/__init__.py 2007-09-28 12:41:08 UTC (rev 3898) +++ trunk/matplotlib/lib/matplotlib/__init__.py 2007-09-28 15:50:01 UTC (rev 3899) @@ -270,7 +270,7 @@ v = line.split()[-1] float(v) return v - except (IndexError, ValueError): + except (IndexError, ValueError, UnboundLocalError): return None def compare_versions(a, b): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <jd...@us...> - 2007-09-28 12:41:15
|
Revision: 3898 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3898&view=rev Author: jdh2358 Date: 2007-09-28 05:41:08 -0700 (Fri, 28 Sep 2007) Log Message: ----------- fixed some tick accessor bugs Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/axis.py trunk/matplotlib/lib/matplotlib/widgets.py Modified: trunk/matplotlib/lib/matplotlib/axis.py =================================================================== --- trunk/matplotlib/lib/matplotlib/axis.py 2007-09-26 14:08:12 UTC (rev 3897) +++ trunk/matplotlib/lib/matplotlib/axis.py 2007-09-28 12:41:08 UTC (rev 3898) @@ -519,8 +519,11 @@ def get_children(self): children = [self.label] - children.extend(self.majorTicks) - children.extend(self.minorTicks) + majorticks = self.get_major_ticks() + minorticks = self.get_minor_ticks() + + children.extend(majorticks) + children.extend(minorticks) return children def cla(self): @@ -643,7 +646,8 @@ def get_gridlines(self): 'Return the grid lines as a list of Line2D instance' - return silent_list('Line2D gridline', [tick.gridline for tick in self.majorTicks]) + ticks = self.get_major_ticks() + return silent_list('Line2D gridline', [tick.gridline for tick in ticks]) def get_label(self): 'Return the axis label as a Text instance' @@ -659,14 +663,16 @@ def get_ticklabels(self): 'Return a list of Text instances for ticklabels' - labels1 = [tick.label1 for tick in self.majorTicks if tick.label1On] - labels2 = [tick.label2 for tick in self.majorTicks if tick.label2On] + ticks = self.get_major_ticks() + labels1 = [tick.label1 for tick in ticks if tick.label1On] + labels2 = [tick.label2 for tick in ticks if tick.label2On] return silent_list('Text ticklabel', labels1+labels2) def get_ticklines(self): 'Return the ticklines lines as a list of Line2D instance' lines = [] - for tick in self.majorTicks: + ticks = self.get_major_ticks() + for tick in ticks: lines.append(tick.tick1line) lines.append(tick.tick2line) return silent_list('Line2D ticklines', lines) @@ -1081,9 +1087,10 @@ """ assert position == 'top' or position == 'bottom' or position == 'both' or position == 'default' - ticks = list(self.majorTicks) # a copy - ticks.extend( self.minorTicks ) + ticks = list( self.get_major_ticks() ) # a copy + ticks.extend( self.get_minor_ticks() ) + if position == 'top': for t in ticks: t.tick1On = False @@ -1277,8 +1284,8 @@ """ assert position == 'left' or position == 'right' or position == 'both' or position == 'default' - ticks = list(self.majorTicks) # a copy - ticks.extend( self.minorTicks ) + ticks = list( self.get_major_ticks() ) # a copy + ticks.extend( self.get_minor_ticks() ) if position == 'right': self.set_offset_position('right') Modified: trunk/matplotlib/lib/matplotlib/widgets.py =================================================================== --- trunk/matplotlib/lib/matplotlib/widgets.py 2007-09-26 14:08:12 UTC (rev 3897) +++ trunk/matplotlib/lib/matplotlib/widgets.py 2007-09-28 12:41:08 UTC (rev 3898) @@ -971,14 +971,14 @@ print ' endposition : (%f, %f)' % (erelease.xdata, erelease.ydata) print ' used button : ', eclick.button - def toggle_Selector(event): + def toggle_selector(event): print ' Key pressed.' - if event.key in ['Q', 'q'] and toggle_Selector.RS.active: + if event.key in ['Q', 'q'] and toggle_selector.RS.active: print ' RectangleSelector deactivated.' - toggle_Selector.RS.set_active(False) - if event.key in ['A', 'a'] and not toggle_Selector.RS.active: + toggle_selector.RS.set_active(False) + if event.key in ['A', 'a'] and not toggle_selector.RS.active: print ' RectangleSelector activated.' - toggle_Selector.RS.set_active(True) + toggle_selector.RS.set_active(True) x = arange(100)/(99.0) y = sin(x) @@ -986,8 +986,8 @@ ax = subplot(111) ax.plot(x,y) - toggle_Selector.RS = RectangleSelector(ax, onselect, drawtype='line') - connect('key_press_event', toggle_Selector) + toggle_selector.RS = RectangleSelector(ax, onselect, drawtype='line') + connect('key_press_event', toggle_selector) show() """ def __init__(self, ax, onselect, drawtype='box', This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2007-09-26 14:09:29
|
Revision: 3897 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3897&view=rev Author: mdboom Date: 2007-09-26 07:08:12 -0700 (Wed, 26 Sep 2007) Log Message: ----------- Fix log transforms a little. Modified Paths: -------------- branches/transforms/lib/matplotlib/scale.py branches/transforms/lib/matplotlib/transforms.py Modified: branches/transforms/lib/matplotlib/scale.py =================================================================== --- branches/transforms/lib/matplotlib/scale.py 2007-09-26 13:55:41 UTC (rev 3896) +++ branches/transforms/lib/matplotlib/scale.py 2007-09-26 14:08:12 UTC (rev 3897) @@ -73,6 +73,36 @@ def inverted(self): return LogScale.Log2Transform() + class NaturalLogTransform(Transform): + input_dims = 1 + output_dims = 1 + def __init__(self): + Transform.__init__(self) + + def is_separable(self): + return True + + def transform(self, a): + return ma.log(ma.masked_where(a <= 0.0, a * npy.e)) + + def inverted(self): + return LogScale.InvertedNaturalLogTransform() + + class InvertedNaturalLogTransform(Transform): + input_dims = 1 + output_dims = 1 + def __init__(self): + Transform.__init__(self) + + def is_separable(self): + return True + + def transform(self, a): + return ma.power(npy.e, a) / npy.e + + def inverted(self): + return LogScale.Log2Transform() + class LogTransform(Transform): input_dims = 1 output_dims = 1 @@ -84,14 +114,12 @@ return True def transform(self, a): - if len(a) > 10: - print "Log Transforming..." return ma.log(ma.masked_where(a <= 0.0, a * self._base)) / npy.log(self._base) def inverted(self): return LogScale.InvertedLogTransform(self._base) - class InvertedLog2Transform(Transform): + class InvertedLogTransform(Transform): input_dims = 1 output_dims = 1 def __init__(self, base): @@ -113,7 +141,8 @@ self._transform = self.Log10Transform() elif base == 2.0: self._transform = self.Log2Transform() - # MGDTODO: Natural log etc. + elif base == npy.e: + self._transform = self.NaturalLogTransform() else: self._transform = self.LogTransform(base) Modified: branches/transforms/lib/matplotlib/transforms.py =================================================================== --- branches/transforms/lib/matplotlib/transforms.py 2007-09-26 13:55:41 UTC (rev 3896) +++ branches/transforms/lib/matplotlib/transforms.py 2007-09-26 14:08:12 UTC (rev 3897) @@ -1069,15 +1069,6 @@ return CompositeGenericTransform(a, b) -class LogTransform(Transform): - input_dims = 1 - output_dims = 1 - - def transform(self, a): - m = ma.masked_where(a < 0, a) - return npy.log10(m) - - class TestPolarTransform(Transform): input_dims = 2 output_dims = 2 This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2007-09-26 13:55:53
|
Revision: 3896 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3896&view=rev Author: mdboom Date: 2007-09-26 06:55:41 -0700 (Wed, 26 Sep 2007) Log Message: ----------- Merged revisions 3885-3895 via svnmerge from http://matplotlib.svn.sf.net/svnroot/matplotlib/trunk/matplotlib ........ r3894 | mdboom | 2007-09-26 09:41:15 -0400 (Wed, 26 Sep 2007) | 3 lines Bugfix: Display exponents in tick values in the default font (not the default math font) ........ Modified Paths: -------------- branches/transforms/lib/matplotlib/mathtext.py branches/transforms/lib/matplotlib/ticker.py Property Changed: ---------------- branches/transforms/ Property changes on: branches/transforms ___________________________________________________________________ Name: svnmerge-integrated - /trunk/matplotlib:1-3884 + /trunk/matplotlib:1-3895 Modified: branches/transforms/lib/matplotlib/mathtext.py =================================================================== --- branches/transforms/lib/matplotlib/mathtext.py 2007-09-26 13:53:53 UTC (rev 3895) +++ branches/transforms/lib/matplotlib/mathtext.py 2007-09-26 13:55:41 UTC (rev 3896) @@ -1855,7 +1855,7 @@ "tanh") fontname = oneOf("rm cal it tt sf bf") - latex2efont = oneOf("mathrm mathcal mathit mathtt mathsf mathbf") + latex2efont = oneOf("mathrm mathcal mathit mathtt mathsf mathbf mathdefault") space =(FollowedBy(bslash) + (Literal(r'\ ') Modified: branches/transforms/lib/matplotlib/ticker.py =================================================================== --- branches/transforms/lib/matplotlib/ticker.py 2007-09-26 13:53:53 UTC (rev 3895) +++ branches/transforms/lib/matplotlib/ticker.py 2007-09-26 13:55:41 UTC (rev 3896) @@ -300,9 +300,12 @@ sciNotStr = r'{\times}'+self.format_data(10**self.orderOfMagnitude) else: sciNotStr = u'\xd7'+'1e%d'% self.orderOfMagnitude - if self._useMathText or self._usetex: + if self._useMathText: + return ''.join(('$\mathdefault{',sciNotStr,offsetStr,'}$')) + elif self._usetex: return ''.join(('$',sciNotStr,offsetStr,'$')) - else: return ''.join((sciNotStr,offsetStr)) + else: + return ''.join((sciNotStr,offsetStr)) else: return '' def set_locs(self, locs): @@ -363,8 +366,11 @@ for loc in locs] sigfigs.sort() self.format = '%1.' + str(sigfigs[-1]) + 'f' - if self._usetex or self._useMathText: self.format = '$%s$'%self.format - + if self._usetex: + self.format = '$%s$' % self.format + elif self._useMathText: + self.format = '$\mathdefault{%s}$' % self.format + def pprint_val(self, x): xp = (x-self.offset)/10**self.orderOfMagnitude if npy.absolute(xp) < 1e-8: xp = 0 @@ -511,11 +517,13 @@ elif not isDecade: if usetex: s = r'$%d^{%.2f}$'% (b, fx) - else: s = '$%d^{%.2f}$'% (b, fx) + else: + s = '$\mathdefault{%d^{%.2f}}$'% (b, fx) else: if usetex: s = r'$%d^{%d}$'% (b, self.nearest_long(fx)) - else: s = r'$%d^{%d}$'% (b, self.nearest_long(fx)) + else: + s = r'$\mathdefault{%d^{%d}}$'% (b, self.nearest_long(fx)) return s This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2007-09-26 13:54:39
|
Revision: 3895 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3895&view=rev Author: mdboom Date: 2007-09-26 06:53:53 -0700 (Wed, 26 Sep 2007) Log Message: ----------- Fix log limits. For minor speed improvements. Modified Paths: -------------- branches/transforms/lib/matplotlib/axes.py branches/transforms/lib/matplotlib/axis.py branches/transforms/lib/matplotlib/lines.py branches/transforms/lib/matplotlib/scale.py branches/transforms/lib/matplotlib/ticker.py branches/transforms/lib/matplotlib/transforms.py Modified: branches/transforms/lib/matplotlib/axes.py =================================================================== --- branches/transforms/lib/matplotlib/axes.py 2007-09-26 13:41:15 UTC (rev 3894) +++ branches/transforms/lib/matplotlib/axes.py 2007-09-26 13:53:53 UTC (rev 3895) @@ -1095,18 +1095,9 @@ line._remove_method = lambda h: self.lines.remove(h) def _update_line_limits(self, line): - xdata = line.get_xdata(orig=False) - ydata = line.get_ydata(orig=False) + xydata = line.get_xydata() + self.update_datalim( xydata ) - if line.get_transform() != self.transData: - xys = self._get_verts_in_data_coords( - line.get_transform(), zip(xdata, ydata)) - xdata = npy.array([x for x,y in xys]) - ydata = npy.array([y for x,y in xys]) - - self.update_datalim_numerix( xdata, ydata ) - - def add_patch(self, p): """ Add a patch to the list of Axes patches; the clipbox will be @@ -1151,7 +1142,6 @@ xys = npy.asarray(xys) self.update_datalim_numerix(xys[:, 0], xys[:, 1]) - def update_datalim_numerix(self, x, y): 'Update the data lim bbox with seq of xy tups' # if no data is set currently, the bbox will ignore it's Modified: branches/transforms/lib/matplotlib/axis.py =================================================================== --- branches/transforms/lib/matplotlib/axis.py 2007-09-26 13:41:15 UTC (rev 3894) +++ branches/transforms/lib/matplotlib/axis.py 2007-09-26 13:53:53 UTC (rev 3895) @@ -334,6 +334,9 @@ 'return the Interval instance for this axis view limits' return self.axes.viewLim.intervalx + def get_minpos(self): + return self.axes.dataLim.minposx + def get_data_interval(self): 'return the Interval instance for this axis data limits' return self.axes.dataLim.intervalx @@ -458,6 +461,9 @@ 'return the Interval instance for this axis view limits' return self.axes.viewLim.intervaly + def get_minpos(self): + return self.axes.dataLim.minposy + def get_data_interval(self): 'return the Interval instance for this axis data limits' return self.axes.dataLim.intervaly @@ -518,7 +524,13 @@ def get_scale(self): return self._scale.name - def set_scale(self, value, base=10, subs=None): + def set_scale(self, value, basex=10, subsx=None, basey=10, subsy=None): + if self.axis_name == 'x': + base = basex + subs = subsx + else: + base = basey + subs = subsy # MGDTODO: Move these settings (ticker etc.) into the scale class itself value = value.lower() assert value.lower() in ('log', 'linear') @@ -534,7 +546,7 @@ self.set_minor_locator(LogLocator(base,subs)) # MGDTODO: Pass base along self._scale = LogScale() - miny, maxy = getattr(self.axes.viewLim, 'interval' + self.axis) + miny, maxy = getattr(self.axes.viewLim, 'interval' + self.axis_name) if min(miny, maxy)<=0: self.axes.autoscale_view() @@ -980,7 +992,7 @@ class XAxis(Axis): __name__ = 'xaxis' - axis = 'x' + axis_name = 'x' def contains(self,mouseevent): """Test whether the mouse event occured in the x axis. @@ -1156,6 +1168,9 @@ 'return the Interval instance for this axis view limits' return self.axes.viewLim.intervalx + def get_minpos(self): + return self.axes.dataLim.minposx + def get_data_interval(self): 'return the Interval instance for this axis data limits' return self.axes.dataLim.intervalx @@ -1163,7 +1178,7 @@ class YAxis(Axis): __name__ = 'yaxis' - axis = 'y' + axis_name = 'y' def contains(self,mouseevent): """Test whether the mouse event occurred in the y axis. @@ -1357,6 +1372,9 @@ 'return the Interval instance for this axis view limits' return self.axes.viewLim.intervaly + def get_minpos(self): + return self.axes.dataLim.minposy + def get_data_interval(self): 'return the Interval instance for this axis data limits' return self.axes.dataLim.intervaly Modified: branches/transforms/lib/matplotlib/lines.py =================================================================== --- branches/transforms/lib/matplotlib/lines.py 2007-09-26 13:41:15 UTC (rev 3894) +++ branches/transforms/lib/matplotlib/lines.py 2007-09-26 13:53:53 UTC (rev 3895) @@ -564,6 +564,9 @@ return self._yorig return self._y + def get_xydata(self): + return self._xy + def set_antialiased(self, b): """ True if line should be drawin with antialiased rendering Modified: branches/transforms/lib/matplotlib/scale.py =================================================================== --- branches/transforms/lib/matplotlib/scale.py 2007-09-26 13:41:15 UTC (rev 3894) +++ branches/transforms/lib/matplotlib/scale.py 2007-09-26 13:53:53 UTC (rev 3895) @@ -13,6 +13,66 @@ return IdentityTransform() class LogScale(ScaleBase): + class Log10Transform(Transform): + input_dims = 1 + output_dims = 1 + def __init__(self): + Transform.__init__(self) + + def is_separable(self): + return True + + def transform(self, a): + return ma.log10(ma.masked_where(a <= 0.0, a * 10.0)) + + def inverted(self): + return LogScale.InvertedLog10Transform() + + class InvertedLog10Transform(Transform): + input_dims = 1 + output_dims = 1 + def __init__(self): + Transform.__init__(self) + + def is_separable(self): + return True + + def transform(self, a): + return ma.power(10.0, a) / 10.0 + + def inverted(self): + return LogScale.Log10Transform() + + class Log2Transform(Transform): + input_dims = 1 + output_dims = 1 + def __init__(self): + Transform.__init__(self) + + def is_separable(self): + return True + + def transform(self, a): + return ma.log2(ma.masked_where(a <= 0.0, a * 2.0)) + + def inverted(self): + return LogScale.InvertedLog2Transform() + + class InvertedLog2Transform(Transform): + input_dims = 1 + output_dims = 1 + def __init__(self): + Transform.__init__(self) + + def is_separable(self): + return True + + def transform(self, a): + return ma.power(2.0, a) / 2.0 + + def inverted(self): + return LogScale.Log2Transform() + class LogTransform(Transform): input_dims = 1 output_dims = 1 @@ -26,12 +86,12 @@ def transform(self, a): if len(a) > 10: print "Log Transforming..." - return ma.log10(ma.masked_where(a <= 0.0, a * 10.0)) + return ma.log(ma.masked_where(a <= 0.0, a * self._base)) / npy.log(self._base) def inverted(self): return LogScale.InvertedLogTransform(self._base) - class InvertedLogTransform(Transform): + class InvertedLog2Transform(Transform): input_dims = 1 output_dims = 1 def __init__(self, base): @@ -42,14 +102,21 @@ return True def transform(self, a): - return ma.power(10.0, a) / 10.0 + return ma.power(self._base, a) / self._base def inverted(self): return LogScale.LogTransform(self._base) + + + def __init__(self, base=10): + if base == 10.0: + self._transform = self.Log10Transform() + elif base == 2.0: + self._transform = self.Log2Transform() + # MGDTODO: Natural log etc. + else: + self._transform = self.LogTransform(base) - def __init__(self, base=10): - self._transform = self.LogTransform(base) - def get_transform(self): return self._transform Modified: branches/transforms/lib/matplotlib/ticker.py =================================================================== --- branches/transforms/lib/matplotlib/ticker.py 2007-09-26 13:41:15 UTC (rev 3894) +++ branches/transforms/lib/matplotlib/ticker.py 2007-09-26 13:53:53 UTC (rev 3895) @@ -919,21 +919,21 @@ def autoscale(self): 'Try to choose the view limits intelligently' - vmin, vmax = self.axis.get_view_interval() + vmin, vmax = self.axis.get_data_interval() if vmax<vmin: vmin, vmax = vmax, vmin -# minpos = self.dataInterval.minpos() + minpos = self.axis.get_minpos() -# if minpos<=0: -# raise RuntimeError('No positive data to plot') + if minpos<=0: + raise RuntimeError('No positive data to plot') - # MGDTODO: Find a good way to track minpos - if vmin <= 0.0: - vmin = 0.1 - + if vmin <= minpos: + vmin = minpos + if not is_decade(vmin,self._base): vmin = decade_down(vmin,self._base) if not is_decade(vmax,self._base): vmax = decade_up(vmax,self._base) + if vmin==vmax: vmin = decade_down(vmin,self._base) vmax = decade_up(vmax,self._base) Modified: branches/transforms/lib/matplotlib/transforms.py =================================================================== --- branches/transforms/lib/matplotlib/transforms.py 2007-09-26 13:41:15 UTC (rev 3894) +++ branches/transforms/lib/matplotlib/transforms.py 2007-09-26 13:53:53 UTC (rev 3895) @@ -224,6 +224,7 @@ def __init__(self, points): BboxBase.__init__(self) self._points = npy.asarray(points, npy.float_) + self._minpos = npy.array([0.0000001, 0.0000001]) self._invalid = False #@staticmethod @@ -252,15 +253,22 @@ return result def update_from_data(self, x, y, ignore=True): - if ignore: + if ignore: + self._points = npy.array( + [[x.min(), y.min()], [x.max(), y.max()]], + npy.float_) + self._minpos = npy.array( + [npy.where(x > 0.0, x, npy.inf).min(), npy.where(y > 0.0, y, npy.inf).min()], + npy.float_) + else: self._points = npy.array( - [[x.min(), y.min()], [x.max(), y.max()]], - npy.float_) - else: - self._points = npy.array( [[min(x.min(), self.xmin), min(y.min(), self.ymin)], [max(x.max(), self.xmax), max(y.max(), self.ymax)]], npy.float_) + minpos = npy.array( + [npy.where(x > 0.0, x, npy.inf).min(), npy.where(y > 0.0, y, npy.inf).min()], + npy.float_) + self._minpos = npy.minimum(minpos, self._minpos) self.invalidate() def _set_xmin(self, val): @@ -309,6 +317,18 @@ self.invalidate() bounds = property(BboxBase._get_bounds, _set_bounds) + def _get_minpos(self): + return self._minpos + minpos = property(_get_minpos) + + def _get_minposx(self): + return self._minpos[0] + minposx = property(_get_minposx) + + def _get_minposy(self): + return self._minpos[1] + minposy = property(_get_minposy) + def get_points(self): self._invalid = False return self._points @@ -541,7 +561,7 @@ # print "".join(traceback.format_stack()) # print points mtx = self.get_matrix() - points = npy.asarray(values, npy.float_) + # points = npy.asarray(values, npy.float_) return points * mtx[0,0] + mtx[0,1] transform_affine = transform @@ -695,10 +715,15 @@ # print "".join(traceback.format_stack()) # print points mtx = self.get_matrix() - points = npy.asarray(points, npy.float_) - points = points.transpose() - points = npy.dot(mtx[0:2, 0:2], points) - points = points + mtx[0:2, 2:] + if ma.isarray(points): + points = points.transpose() + points = ma.dot(mtx[0:2, 0:2], points) + points = points + mtx[0:2, 2:] + else: + points = npy.asarray(points, npy.float_) + points = points.transpose() + points = npy.dot(mtx[0:2, 0:2], points) + points = points + mtx[0:2, 2:] return points.transpose() transform_affine = transform @@ -869,7 +894,7 @@ y_points = y.transform(points[:, 1]) y_points = y_points.reshape((len(y_points), 1)) - return npy.concatenate((x_points, y_points), 1) + return ma.concatenate((x_points, y_points), 1) transform_non_affine = transform def transform_affine(self, points): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2007-09-26 13:41:29
|
Revision: 3894 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3894&view=rev Author: mdboom Date: 2007-09-26 06:41:15 -0700 (Wed, 26 Sep 2007) Log Message: ----------- Bugfix: Display exponents in tick values in the default font (not the default math font) Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/mathtext.py trunk/matplotlib/lib/matplotlib/ticker.py Modified: trunk/matplotlib/lib/matplotlib/mathtext.py =================================================================== --- trunk/matplotlib/lib/matplotlib/mathtext.py 2007-09-26 12:29:05 UTC (rev 3893) +++ trunk/matplotlib/lib/matplotlib/mathtext.py 2007-09-26 13:41:15 UTC (rev 3894) @@ -1855,7 +1855,7 @@ "tanh") fontname = oneOf("rm cal it tt sf bf") - latex2efont = oneOf("mathrm mathcal mathit mathtt mathsf mathbf") + latex2efont = oneOf("mathrm mathcal mathit mathtt mathsf mathbf mathdefault") space =(FollowedBy(bslash) + (Literal(r'\ ') Modified: trunk/matplotlib/lib/matplotlib/ticker.py =================================================================== --- trunk/matplotlib/lib/matplotlib/ticker.py 2007-09-26 12:29:05 UTC (rev 3893) +++ trunk/matplotlib/lib/matplotlib/ticker.py 2007-09-26 13:41:15 UTC (rev 3894) @@ -332,9 +332,12 @@ sciNotStr = r'{\times}'+self.format_data(10**self.orderOfMagnitude) else: sciNotStr = u'\xd7'+'1e%d'% self.orderOfMagnitude - if self._useMathText or self._usetex: + if self._useMathText: + return ''.join(('$\mathdefault{',sciNotStr,offsetStr,'}$')) + elif self._usetex: return ''.join(('$',sciNotStr,offsetStr,'$')) - else: return ''.join((sciNotStr,offsetStr)) + else: + return ''.join((sciNotStr,offsetStr)) else: return '' def set_locs(self, locs): @@ -395,8 +398,11 @@ for loc in locs] sigfigs.sort() self.format = '%1.' + str(sigfigs[-1]) + 'f' - if self._usetex or self._useMathText: self.format = '$%s$'%self.format - + if self._usetex: + self.format = '$%s$' % self.format + elif self._useMathText: + self.format = '$\mathdefault{%s}$' % self.format + def pprint_val(self, x): xp = (x-self.offset)/10**self.orderOfMagnitude if npy.absolute(xp) < 1e-8: xp = 0 @@ -545,11 +551,13 @@ elif not isDecade: if usetex: s = r'$%d^{%.2f}$'% (b, fx) - else: s = '$%d^{%.2f}$'% (b, fx) + else: + s = '$\mathdefault{%d^{%.2f}}$'% (b, fx) else: if usetex: s = r'$%d^{%d}$'% (b, self.nearest_long(fx)) - else: s = r'$%d^{%d}$'% (b, self.nearest_long(fx)) + else: + s = r'$\mathdefault{%d^{%d}}$'% (b, self.nearest_long(fx)) return s This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2007-09-26 12:29:17
|
Revision: 3893 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3893&view=rev Author: mdboom Date: 2007-09-26 05:29:05 -0700 (Wed, 26 Sep 2007) Log Message: ----------- Committing simple_ploy_fps.py Added Paths: ----------- branches/transforms/examples/simple_plot_fps.py Added: branches/transforms/examples/simple_plot_fps.py =================================================================== --- branches/transforms/examples/simple_plot_fps.py (rev 0) +++ branches/transforms/examples/simple_plot_fps.py 2007-09-26 12:29:05 UTC (rev 3893) @@ -0,0 +1,32 @@ +#!/usr/bin/env python +""" +Example: simple line plot. +Show how to make and save a simple line plot with labels, title and grid +""" +from pylab import * + +plot([1,2]) +show() + +t = arange(0.0, 1.0+0.001, 0.001) +s = cos(2*2*pi*t) +plot(t, s, '-', lw=2) + +xlabel('time (s)') +ylabel('voltage (mV)') +title('About as simple as it gets, folks') +grid(True) + +#savefig('simple_plot.png') +#savefig('simple_plot') + +import time + +frames = 100.0 +t = time.clock() +ion() +for i in xrange(int(frames)): + part = i / frames + axis([0.0, 1.0 - part, -1.0 + part, 1.0 - part]) + show() +print "fps:", frames / (time.clock() - t) Property changes on: branches/transforms/examples/simple_plot_fps.py ___________________________________________________________________ Name: svn:executable + * This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2007-09-25 19:54:01
|
Revision: 3892 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3892&view=rev Author: mdboom Date: 2007-09-25 12:53:56 -0700 (Tue, 25 Sep 2007) Log Message: ----------- Important bugfixes. Modified Paths: -------------- branches/transforms/lib/matplotlib/lines.py branches/transforms/lib/matplotlib/path.py branches/transforms/lib/matplotlib/transforms.py Modified: branches/transforms/lib/matplotlib/lines.py =================================================================== --- branches/transforms/lib/matplotlib/lines.py 2007-09-25 19:08:51 UTC (rev 3891) +++ branches/transforms/lib/matplotlib/lines.py 2007-09-25 19:53:56 UTC (rev 3892) @@ -499,7 +499,7 @@ lineFunc(renderer, gc, *self._transformed_path.get_path_and_affine()) # MGDTODO: Deal with markers - if self._marker is not None and False: + if self._marker is not None: gc = renderer.new_gc() self._set_gc_clip(gc) gc.set_foreground(self.get_markeredgecolor()) @@ -507,7 +507,7 @@ gc.set_alpha(self._alpha) funcname = self._markers.get(self._marker, '_draw_nothing') markerFunc = getattr(self, funcname) - markerFunc(renderer, gc, self._path) + markerFunc(renderer, gc, *self._transformed_path.get_path_and_affine()) #renderer.close_group('line2d') Modified: branches/transforms/lib/matplotlib/path.py =================================================================== --- branches/transforms/lib/matplotlib/path.py 2007-09-25 19:08:51 UTC (rev 3891) +++ branches/transforms/lib/matplotlib/path.py 2007-09-25 19:53:56 UTC (rev 3892) @@ -65,7 +65,10 @@ def __repr__(self): return "Path(%s, %s)" % (self.vertices, self.codes) - + + def __len__(self): + return len(self._vertices) + def _get_codes(self): return self._codes codes = property(_get_codes) @@ -108,7 +111,7 @@ # This initial rotation is to make sure the polygon always # "points-up" theta += npy.pi / 2.0 - verts = npy.concatenate((npy.cos(theta), npy.sin(theta))) + verts = npy.concatenate((npy.cos(theta), npy.sin(theta)), 1) path = Path(verts) cls._unit_regular_polygons[numVertices] = path return path Modified: branches/transforms/lib/matplotlib/transforms.py =================================================================== --- branches/transforms/lib/matplotlib/transforms.py 2007-09-25 19:08:51 UTC (rev 3891) +++ branches/transforms/lib/matplotlib/transforms.py 2007-09-25 19:53:56 UTC (rev 3892) @@ -24,7 +24,10 @@ _gid = 0 def __init__(self): - self._parents = WeakKeyDictionary() + # MGDTODO: I'd like to use a WeakKeyDictionary here, but it makes + # these instances uncopyable. As it stands, _parents grows + # unboundedly... Not a good idea. + self._parents = Set() self._children = Set() self._id = TransformNode._gid @@ -34,7 +37,7 @@ if not self._do_invalidation(affine_only): self._id = TransformNode._gid TransformNode._gid += 1 - for parent in self._parents.iterkeys(): + for parent in self._parents: parent.invalidate(affine_only) def _do_invalidation(self, affine_only): @@ -42,7 +45,7 @@ def set_children(self, children): for child in children: - getattr(self, child)._parents[self] = None + getattr(self, child)._parents.add(self) self._children = children def make_graphviz(self, fobj): @@ -1034,8 +1037,8 @@ def composite_transform_factory(a, b): - if isinstance(a, BboxTransform) and isinstance(b, BboxTransform): - return BboxTransform(a._boxin, b._boxout) +# if isinstance(a, BboxTransform) and isinstance(b, BboxTransform): +# return BboxTransform(a._boxin, b._boxout) if isinstance(a, AffineBase) and isinstance(b, AffineBase): return CompositeAffine2D(a, b) return CompositeGenericTransform(a, b) @@ -1162,19 +1165,23 @@ self._path = path self._transform = transform + self.set_children(['_transform']) self._transformed_path = None - self._last_id = transform.get_id() + + def _do_invalidation(self, affine_only): + if not affine_only: + self._transformed_path = None + return True def get_path_and_affine(self): - if (self._transformed_path is None or - self._last_id != self._transform.get_id()): + if self._transformed_path is None: vertices = self._transform.transform_non_affine(self._path.vertices) self._transformed_path = Path(vertices, self._path.codes) + return self._transformed_path, self._transform.get_affine() def get_path(self): - if (self._transformed_path is None or - self._last_id != self._transform.get_id()): + if self._transformed_path is None: vertices = self._tranform.transform_non_affine(self._path.vertices) self._transformed_path = Path(vertices, self._path.codes) vertices = self._transform.transform_affine(self._transformed_path.vertices) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <js...@us...> - 2007-09-25 19:08:56
|
Revision: 3891 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3891&view=rev Author: jswhit Date: 2007-09-25 12:08:51 -0700 (Tue, 25 Sep 2007) Log Message: ----------- clarify satellite height units Modified Paths: -------------- trunk/toolkits/basemap/examples/geos_demo.py Modified: trunk/toolkits/basemap/examples/geos_demo.py =================================================================== --- trunk/toolkits/basemap/examples/geos_demo.py 2007-09-25 18:29:44 UTC (rev 3890) +++ trunk/toolkits/basemap/examples/geos_demo.py 2007-09-25 19:08:51 UTC (rev 3891) @@ -2,7 +2,7 @@ from pylab import title, show, arange # create Basemap instance for Geostationary (satellite view) projection. lon_0 = float(raw_input('enter reference longitude (lon_0):')) -h = float(raw_input('enter satellite height above equator (satellite_height):')) +h = float(raw_input('enter satellite height above equator in meters (satellite_height):')) m = Basemap(projection='geos',lon_0=lon_0,satellite_height=h,rsphere=(6378137.00,6356752.3142),) # plot land-sea mask. rgba_land = (0,255,0,255) # land green. This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2007-09-25 18:29:47
|
Revision: 3890 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3890&view=rev Author: mdboom Date: 2007-09-25 11:29:44 -0700 (Tue, 25 Sep 2007) Log Message: ----------- Minor speed improvements in new transformations. Modified Paths: -------------- branches/transforms/lib/matplotlib/path.py branches/transforms/lib/matplotlib/text.py branches/transforms/lib/matplotlib/transforms.py Modified: branches/transforms/lib/matplotlib/path.py =================================================================== --- branches/transforms/lib/matplotlib/path.py 2007-09-25 17:04:51 UTC (rev 3889) +++ branches/transforms/lib/matplotlib/path.py 2007-09-25 18:29:44 UTC (rev 3890) @@ -41,9 +41,10 @@ assert len(codes) == len(vertices) # The path being passed in may have masked values. However, - # the backends are not expected to deal with masked arrays, so - # we must remove them from the array (using compressed), and - # add MOVETO commands to the codes array accordingly. + # the backends (and any affine transformations in matplotlib + # itself), are not expected to deal with masked arrays, so we + # must remove them from the array (using compressed), and add + # MOVETO commands to the codes array accordingly. mask = ma.getmask(vertices) if mask is not ma.nomask: mask1d = ma.mask_or(mask[:, 0], mask[:, 1]) Modified: branches/transforms/lib/matplotlib/text.py =================================================================== --- branches/transforms/lib/matplotlib/text.py 2007-09-25 17:04:51 UTC (rev 3889) +++ branches/transforms/lib/matplotlib/text.py 2007-09-25 18:29:44 UTC (rev 3890) @@ -402,9 +402,7 @@ return (x, y, self._text, self._color, self._verticalalignment, self._horizontalalignment, hash(self._fontproperties), self._rotation, - # MGDTODO: Find a better way to determine if the - # transform as changed - str(self.get_transform()) + self.get_transform().get_id() ) def get_text(self): Modified: branches/transforms/lib/matplotlib/transforms.py =================================================================== --- branches/transforms/lib/matplotlib/transforms.py 2007-09-25 17:04:51 UTC (rev 3889) +++ branches/transforms/lib/matplotlib/transforms.py 2007-09-25 18:29:44 UTC (rev 3890) @@ -21,24 +21,28 @@ # relationships class TransformNode(object): + _gid = 0 + def __init__(self): - self._parents = Set() - self._children = [] + self._parents = WeakKeyDictionary() + self._children = Set() + self._id = TransformNode._gid - def invalidate(self, which_child=None, affine_only=[]): - if which_child is None: - which_child = self - self._do_invalidation(which_child, affine_only) - # affine_only = affine_only and (self.is_affine() or self.is_bbox()) - for parent in self._parents: - parent.invalidate(self, affine_only + [self]) + def invalidate(self, affine_only=None): + if affine_only is None: + affine_only = self.is_affine() or self.is_bbox() + if not self._do_invalidation(affine_only): + self._id = TransformNode._gid + TransformNode._gid += 1 + for parent in self._parents.iterkeys(): + parent.invalidate(affine_only) - def _do_invalidation(self, which_child, affine_only): - pass + def _do_invalidation(self, affine_only): + return False def set_children(self, children): for child in children: - getattr(self, child)._parents.add(self) + getattr(self, child)._parents[self] = None self._children = children def make_graphviz(self, fobj): @@ -74,7 +78,10 @@ def is_bbox(self): return False + def get_id(self): + return self._id + class BboxBase(TransformNode): ''' This is the read-only part of a bounding-box @@ -214,6 +221,7 @@ def __init__(self, points): BboxBase.__init__(self) self._points = npy.asarray(points, npy.float_) + self._invalid = False #@staticmethod def unit(): @@ -235,6 +243,11 @@ return 'Bbox(%s)' % repr(self._points) __str__ = __repr__ + def _do_invalidation(self, affine_only): + result = self._invalid + self._invalid = True + return result + def update_from_data(self, x, y, ignore=True): if ignore: self._points = npy.array( @@ -294,6 +307,7 @@ bounds = property(BboxBase._get_bounds, _set_bounds) def get_points(self): + self._invalid = False return self._points def set_points(self, points): @@ -348,21 +362,23 @@ assert transform.output_dims == 2 BboxBase.__init__(self) - self.bbox = bbox - self.transform = transform - self.set_children(['bbox', 'transform']) + self._bbox = bbox + self._transform = transform + self.set_children(['_bbox', '_transform']) self._points = None def __repr__(self): - return "TransformedBbox(%s, %s)" % (self.bbox, self.transform) + return "TransformedBbox(%s, %s)" % (self._bbox, self._transform) __str__ = __repr__ - def _do_invalidation(self, which_child, affine_only): + def _do_invalidation(self, affine_only): + result = self._points is None self._points = None + return result def get_points(self): if self._points is None: - self._points = self.transform.transform(self.bbox.get_points()) + self._points = self._transform.transform(self._bbox.get_points()) return self._points @@ -461,9 +477,6 @@ def __array__(self, *args, **kwargs): return self.get_matrix() - def _do_invalidation(self, which_child, affine_only): - self._inverted = None - #@staticmethod def _concat(a, b): return npy.dot(b, a) @@ -477,9 +490,6 @@ def get_matrix(self): raise NotImplementedError() - def transform_affine(self, points): - return self.transform(points) - def transform_non_affine(self, points): return points @@ -528,9 +538,11 @@ # print "".join(traceback.format_stack()) # print points mtx = self.get_matrix() - points = ma.asarray(values, npy.float_) + points = npy.asarray(values, npy.float_) return points * mtx[0,0] + mtx[0,1] + transform_affine = transform + def inverted(self): if self._inverted is None: mtx = self.get_matrix() @@ -575,7 +587,7 @@ def set_matrix(self, mtx): self._mtx = mtx self.invalidate() - + def set(self, other): self._mtx = other.get_matrix() self.invalidate() @@ -620,9 +632,11 @@ return "IntervalTransform(%s)" % (getattr(self._bbox, self._direction)) __str__ = __repr__ - def _do_invalidation(self, which_child, affine_only): + def _do_invalidation(self, affine_only): + result = self._mtx is None self._mtx = None - Affine1DBase._do_invalidation(self, which_child, affine_only) + self._inverted = None + return result def get_matrix(self): if self._mtx is None: @@ -678,12 +692,14 @@ # print "".join(traceback.format_stack()) # print points mtx = self.get_matrix() - points = ma.asarray(points, npy.float_) + points = npy.asarray(points, npy.float_) points = points.transpose() - points = ma.dot(mtx[0:2, 0:2], points) + points = npy.dot(mtx[0:2, 0:2], points) points = points + mtx[0:2, 2:] return points.transpose() + transform_affine = transform + def inverted(self): if self._inverted is None: mtx = self.get_matrix() @@ -801,19 +817,12 @@ def transform(self, points): return points + transform_affine = transform_non_affine = transform - def transform_affine(self, points): - return points - - def transform_non_affine(self, points): - return points - def get_affine(self): return self + inverted = get_affine - def inverted(self): - return self - class BlendedGenericTransform(Transform): input_dims = 2 @@ -857,14 +866,12 @@ y_points = y.transform(points[:, 1]) y_points = y_points.reshape((len(y_points), 1)) - return ma.concatenate((x_points, y_points), 1) - + return npy.concatenate((x_points, y_points), 1) + transform_non_affine = transform + def transform_affine(self, points): return points - def transform_non_affine(self, points): - return self.transform(points) - def get_affine(self): return IdentityTransform() @@ -892,9 +899,10 @@ return "BlendedAffine1D(%s,%s)" % (self._x, self._y) __str__ = __repr__ - def _do_invalidation(self, which_child, affine_only): + def _do_invalidation(self, affine_only): + result = self._mtx is None self._mtx = None - Affine2DBase._do_invalidation(self, which_child, affine_only) + self._inverted = None def get_matrix(self): if self._mtx is None: @@ -928,9 +936,11 @@ return "BlendedAffine2D(%s,%s)" % (self._x, self._y) __str__ = __repr__ - def _do_invalidation(self, which_child, affine_only): + def _do_invalidation(self, affine_only): + result = self._mtx is None self._mtx = None - Affine2DBase._do_invalidation(self, which_child, affine_only) + self._inverted = None + return result def get_matrix(self): if self._mtx is None: @@ -985,7 +995,7 @@ return self._b.transform_non_affine(self._a.transform_non_affine(points)) def get_affine(self): - return self._a.get_affine() + self._b.get_affine() + return CompositeAffine2D(self._a.get_affine(), self._b.get_affine()) def inverted(self): return CompositeGenericTransform(self._b.inverted(), self._a.inverted()) @@ -1009,9 +1019,11 @@ return "CompositeAffine2D(%s, %s)" % (self._a, self._b) __str__ = __repr__ - def _do_invalidation(self, which_child, affine_only): + def _do_invalidation(self, affine_only): + result = self._mtx is None self._mtx = None - Affine2DBase._do_invalidation(self, which_child, affine_only) + self._inverted = None + return result def get_matrix(self): if self._mtx is None: @@ -1117,10 +1129,12 @@ return "BboxTransform(%s, %s)" % (self._boxin, self._boxout) __str__ = __repr__ - def _do_invalidation(self, which_child, affine_only): + def _do_invalidation(self, affine_only): + result = self._mtx is None self._mtx = None - Affine2DBase._do_invalidation(self, which_child, affine_only) - + self._inverted = None + return result + def is_separable(self): return True @@ -1148,21 +1162,19 @@ self._path = path self._transform = transform - self.set_children(['_transform']) self._transformed_path = None + self._last_id = transform.get_id() - def _do_invalidation(self, which_child, affine_only): - if not (affine_only[0].is_affine() or affine_only[0].is_bbox()): - self._transformed_path = None - def get_path_and_affine(self): - if self._transformed_path is None: + if (self._transformed_path is None or + self._last_id != self._transform.get_id()): vertices = self._transform.transform_non_affine(self._path.vertices) self._transformed_path = Path(vertices, self._path.codes) return self._transformed_path, self._transform.get_affine() def get_path(self): - if self._transformed_path is None: + if (self._transformed_path is None or + self._last_id != self._transform.get_id()): vertices = self._tranform.transform_non_affine(self._path.vertices) self._transformed_path = Path(vertices, self._path.codes) vertices = self._transform.transform_affine(self._transformed_path.vertices) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2007-09-25 17:05:56
|
Revision: 3889 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3889&view=rev Author: mdboom Date: 2007-09-25 10:04:51 -0700 (Tue, 25 Sep 2007) Log Message: ----------- Automaticall separate affine from non-affine transforms Modified Paths: -------------- branches/transforms/lib/matplotlib/axes.py branches/transforms/lib/matplotlib/axis.py branches/transforms/lib/matplotlib/backends/backend_agg.py branches/transforms/lib/matplotlib/lines.py branches/transforms/lib/matplotlib/path.py branches/transforms/lib/matplotlib/scale.py branches/transforms/lib/matplotlib/ticker.py branches/transforms/lib/matplotlib/transforms.py Modified: branches/transforms/lib/matplotlib/axes.py =================================================================== --- branches/transforms/lib/matplotlib/axes.py 2007-09-25 12:15:22 UTC (rev 3888) +++ branches/transforms/lib/matplotlib/axes.py 2007-09-25 17:04:51 UTC (rev 3889) @@ -545,7 +545,7 @@ "move this out of __init__ because non-separable axes don't use it" self.xaxis = maxis.XAxis(self) self.yaxis = maxis.YAxis(self) - self._update_transAxisXY() + self._update_transScale() def sharex_foreign(self, axforeign): """ @@ -631,12 +631,28 @@ self.viewLim = mtransforms.Bbox.unit() self.transAxes = mtransforms.BboxTransform( mtransforms.Bbox.unit(), self.bbox) - self.transAxisXY = mtransforms.TransformWrapper() - self.transData = self.transAxisXY + self.transAxes - def _update_transAxisXY(self): - self.transAxisXY.set(mtransforms.blended_transform_factory( + # Transforms the x and y axis separately by a scale factor + # It is assumed that this part will have non-linear components + self.transScale = mtransforms.TransformWrapper(mtransforms.IdentityTransform()) + + # A (possibly non-linear) projection on the (already scaled) data + self.transProjection = mtransforms.IdentityTransform() + + # An affine transformation on the data, generally to limit the + # range of the axes + self.transLimits = mtransforms.BboxTransform( + mtransforms.TransformedBbox(self.viewLim, self.transScale), mtransforms.Bbox.unit()) + + self.transData = self.transScale + self.transProjection + self.transLimits + self.transAxes + + + def _update_transScale(self): + self.transScale.set( + mtransforms.blended_transform_factory( self.xaxis.get_transform(), self.yaxis.get_transform())) + + self.transData.make_graphviz(open("trans.dot", "w")) def get_position(self, original=False): 'Return the axes rectangle left, bottom, width, height' @@ -1537,7 +1553,7 @@ ACCEPTS: ['log' | 'linear' ] """ self.xaxis.set_scale(value, **kwargs) - self._update_transAxisXY() + self._update_transScale() def get_xticks(self): 'Return the x ticks as a list of locations' @@ -1647,7 +1663,7 @@ ACCEPTS: ['log' | 'linear'] """ self.yaxis.set_scale(value, basey, subsy) - self._update_transAxisXY() + self._update_transScale() def get_yticks(self): 'Return the y ticks as a list of locations' Modified: branches/transforms/lib/matplotlib/axis.py =================================================================== --- branches/transforms/lib/matplotlib/axis.py 2007-09-25 12:15:22 UTC (rev 3888) +++ branches/transforms/lib/matplotlib/axis.py 2007-09-25 17:04:51 UTC (rev 3889) @@ -508,16 +508,15 @@ self.majorTicks = [] self.minorTicks = [] self.pickradius = pickradius - self._transform = LinearScale(self.axes.viewLim, self.axis).get_transform() - self._scale = 'linear' + self._scale = LinearScale() self.cla() def get_transform(self): - return self._transform - + return self._scale.get_transform() + def get_scale(self): - return self._scale + return self._scale.name def set_scale(self, value, base=10, subs=None): # MGDTODO: Move these settings (ticker etc.) into the scale class itself @@ -528,17 +527,16 @@ self.set_major_formatter(ScalarFormatter()) self.set_minor_locator(NullLocator()) self.set_minor_formatter(NullFormatter()) - self._transform = LinearScale(self.axes.viewLim, self.axis).get_transform() + self._scale = LinearScale() elif value == 'log': self.set_major_locator(LogLocator(base)) self.set_major_formatter(LogFormatterMathtext(base)) self.set_minor_locator(LogLocator(base,subs)) # MGDTODO: Pass base along - self._transform = LogScale(self.axes.viewLim, self.axis).get_transform() + self._scale = LogScale() miny, maxy = getattr(self.axes.viewLim, 'interval' + self.axis) if min(miny, maxy)<=0: self.axes.autoscale_view() - self._scale = value def get_children(self): children = [self.label] Modified: branches/transforms/lib/matplotlib/backends/backend_agg.py =================================================================== --- branches/transforms/lib/matplotlib/backends/backend_agg.py 2007-09-25 12:15:22 UTC (rev 3888) +++ branches/transforms/lib/matplotlib/backends/backend_agg.py 2007-09-25 17:04:51 UTC (rev 3889) @@ -132,14 +132,14 @@ # MGDTODO: This is a hack for now to allow for arbitrary transformations def draw_path(self, gc, path, trans, rgbFace=None): - new_path, affine = path.transformed_without_affine(trans) - self._renderer.draw_path(gc, new_path, affine, rgbFace) + assert trans.is_affine() + self._renderer.draw_path(gc, path, trans, rgbFace) # MGDTODO: This is a hack for now to allow for arbitrary transformations def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None): assert marker_trans.is_affine() - new_path, affine = path.transformed_without_affine(trans) - self._renderer.draw_markers(gc, marker_path, marker_trans, new_path, affine, rgbFace) + assert trans.is_affine() + self._renderer.draw_markers(gc, marker_path, marker_trans, path, trans, rgbFace) def draw_mathtext(self, gc, x, y, s, prop, angle): """ Modified: branches/transforms/lib/matplotlib/lines.py =================================================================== --- branches/transforms/lib/matplotlib/lines.py 2007-09-25 12:15:22 UTC (rev 3888) +++ branches/transforms/lib/matplotlib/lines.py 2007-09-25 17:04:51 UTC (rev 3889) @@ -17,7 +17,7 @@ from cbook import iterable, is_string_like, is_numlike from colors import colorConverter from path import Path -from transforms import Affine2D, Bbox +from transforms import Affine2D, Bbox, TransformedPath from matplotlib import rcParams @@ -416,8 +416,18 @@ self._logcache = None # Masked arrays are now handled by the Path class itself self._path = Path(self._xy, closed=False) + self._transformed_path = TransformedPath(self._path, self.get_transform()) # MGDTODO: If _draw_steps is removed, remove the following line also self._step_path = None + + def set_transform(self, t): + """ + set the Transformation instance used by this artist + + ACCEPTS: a matplotlib.transform transformation instance + """ + Artist.set_transform(self, t) + self._transformed_path = TransformedPath(self._path, self.get_transform()) def _is_sorted(self, x): "return true if x is sorted" @@ -486,10 +496,10 @@ funcname = self._lineStyles.get(self._linestyle, '_draw_nothing') lineFunc = getattr(self, funcname) - lineFunc(renderer, gc, self._path) + lineFunc(renderer, gc, *self._transformed_path.get_path_and_affine()) # MGDTODO: Deal with markers - if self._marker is not None: + if self._marker is not None and False: gc = renderer.new_gc() self._set_gc_clip(gc) gc.set_foreground(self.get_markeredgecolor()) @@ -678,7 +688,7 @@ self.set_linestyle('--') self._dashSeq = seq # TODO: offset ignored for now - def _draw_nothing(self, renderer, gc, path): + def _draw_nothing(self, *args, **kwargs): pass @@ -704,191 +714,191 @@ renderer.draw_path(gc, self._step_path, self.get_transform()) - def _draw_solid(self, renderer, gc, path): + def _draw_solid(self, renderer, gc, path, trans): gc.set_linestyle('solid') - renderer.draw_path(gc, path, self.get_transform()) + renderer.draw_path(gc, path, trans) - def _draw_dashed(self, renderer, gc, path): + def _draw_dashed(self, renderer, gc, path, trans): gc.set_linestyle('dashed') if self._dashSeq is not None: gc.set_dashes(0, self._dashSeq) - renderer.draw_path(gc, path, self.get_transform()) + renderer.draw_path(gc, path, trans) - def _draw_dash_dot(self, renderer, gc, path): + def _draw_dash_dot(self, renderer, gc, path, trans): gc.set_linestyle('dashdot') - renderer.draw_path(gc, path, self.get_transform()) + renderer.draw_path(gc, path, trans) - def _draw_dotted(self, renderer, gc, path): + def _draw_dotted(self, renderer, gc, path, trans): gc.set_linestyle('dotted') - renderer.draw_path(gc, path, self.get_transform()) + renderer.draw_path(gc, path, trans) - def _draw_point(self, renderer, gc, path): + def _draw_point(self, renderer, gc, path, path_trans): w = renderer.points_to_pixels(self._markersize) * \ self._point_size_reduction * 0.5 rgbFace = self._get_rgb_face() transform = Affine2D().scale(w) renderer.draw_markers( - gc, Path.unit_circle(), transform, path, self.get_transform(), + gc, Path.unit_circle(), transform, path, path_trans, rgbFace) - def _draw_pixel(self, renderer, gc, path): + def _draw_pixel(self, renderer, gc, path, path_trans): rgbFace = self._get_rgb_face() transform = Affine2D().translate(-0.5, -0.5) renderer.draw_markers(gc, Path.unit_rectangle, transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) - def _draw_circle(self, renderer, gc, path): + def _draw_circle(self, renderer, gc, path, path_trans): w = renderer.points_to_pixels(self._markersize) * 0.5 rgbFace = self._get_rgb_face() transform = Affine2D().scale(w, w) renderer.draw_markers( - gc, Path.unit_circle(), transform, path, self.get_transform(), + gc, Path.unit_circle(), transform, path, path_trans, rgbFace) _triangle_path = Path([[0.0, 1.0], [-1.0, -1.0], [1.0, -1.0]]) - def _draw_triangle_up(self, renderer, gc, path): + def _draw_triangle_up(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset, offset) rgbFace = self._get_rgb_face() renderer.draw_markers(gc, self._triangle_path, transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) - def _draw_triangle_down(self, renderer, gc, path): + def _draw_triangle_down(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset, -offset) rgbFace = self._get_rgb_face() renderer.draw_markers(gc, self._triangle_path, transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) - def _draw_triangle_left(self, renderer, gc, path): + def _draw_triangle_left(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset, offset).rotate_deg(90) rgbFace = self._get_rgb_face() renderer.draw_markers(gc, self._triangle_path, transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) - def _draw_triangle_right(self, renderer, gc, path): + def _draw_triangle_right(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset, offset).rotate_deg(-90) rgbFace = self._get_rgb_face() renderer.draw_markers(gc, self._triangle_path, transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) - def _draw_square(self, renderer, gc, path): + def _draw_square(self, renderer, gc, path, path_trans): side = renderer.points_to_pixels(self._markersize) transform = Affine2D().translate(-0.5, -0.5).scale(side) rgbFace = self._get_rgb_face() renderer.draw_markers(gc, Path.unit_rectangle(), transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) - def _draw_diamond(self, renderer, gc, path): + def _draw_diamond(self, renderer, gc, path, path_trans): side = renderer.points_to_pixels(self._markersize) transform = Affine2D().translate(0.5, 0.5).rotate_deg(45).scale(side) rgbFace = self._get_rgb_face() renderer.draw_markers(gc, Path.unit_rectangle(), transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) - def _draw_thin_diamond(self, renderer, gc, path): + def _draw_thin_diamond(self, renderer, gc, path, path_trans): offset = renderer.points_to_pixels(self._markersize) transform = Affine2D().translate(0.5, 0.5) \ .rotate_deg(45).scale(offset * 0.8, offset) rgbFace = self._get_rgb_face() renderer.draw_markers(gc, Path.unit_rectangle(), transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) - def _draw_pentagon(self, renderer, gc, path): + def _draw_pentagon(self, renderer, gc, path, path_trans): offset = 0.5 * renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset) rgbFace = self._get_rgb_face() renderer.draw_markers(gc, Path.unit_regular_polygon(5), transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) - def _draw_hexagon1(self, renderer, gc, path): + def _draw_hexagon1(self, renderer, gc, path, path_trans): offset = 0.5 * renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset) rgbFace = self._get_rgb_face() renderer.draw_markers(gc, Path.unit_regular_polygon(6), transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) - def _draw_hexagon2(self, renderer, gc, path): + def _draw_hexagon2(self, renderer, gc, path, path_trans): offset = 0.5 * renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset).rotate_deg(30) rgbFace = self._get_rgb_face() renderer.draw_markers(gc, Path.unit_regular_polygon(6), transform, - path, self.get_transform(), rgbFace) + path, path_trans, rgbFace) _line_marker_path = Path([[0.0, -1.0], [0.0, 1.0]], closed=False) - def _draw_vline(self, renderer, gc, path): + def _draw_vline(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset) renderer.draw_markers(gc, self._line_marker_path, transform, - path, self.get_transform()) + path, path_trans) - def _draw_hline(self, renderer, gc, path): + def _draw_hline(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset).rotate_deg(90) renderer.draw_markers(gc, self._line_marker_path, transform, - path, self.get_transform()) + path, path_trans) _tickhoriz_path = Path([[0.0, 0.5], [1.0, 0.5]], closed=False) - def _draw_tickleft(self, renderer, gc, path): + def _draw_tickleft(self, renderer, gc, path, path_trans): offset = renderer.points_to_pixels(self._markersize) marker_transform = Affine2D().scale(-offset, 1.0) renderer.draw_markers(gc, self._tickhoriz_path, marker_transform, - path, self.get_transform()) + path, path_trans) - def _draw_tickright(self, renderer, gc, path): + def _draw_tickright(self, renderer, gc, path, path_trans): offset = renderer.points_to_pixels(self._markersize) marker_transform = Affine2D().scale(offset, 1.0) renderer.draw_markers(gc, self._tickhoriz_path, marker_transform, - path, self.get_transform()) + path, path_trans) _tickvert_path = Path([[-0.5, 0.0], [-0.5, 1.0]], closed=False) - def _draw_tickup(self, renderer, gc, path): + def _draw_tickup(self, renderer, gc, path, path_trans): offset = renderer.points_to_pixels(self._markersize) marker_transform = Affine2D().scale(1.0, offset) renderer.draw_markers(gc, self._tickvert_path, marker_transform, - path, self.get_transform()) + path, path_trans) - def _draw_tickdown(self, renderer, gc, path): + def _draw_tickdown(self, renderer, gc, path, path_trans): offset = renderer.points_to_pixels(self._markersize) marker_transform = Affine2D().scale(1.0, -offset) renderer.draw_markers(gc, self._tickvert_path, marker_transform, - path, self.get_transform()) + path, path_trans) _plus_path = Path([[-1.0, 0.0], [1.0, 0.0], [0.0, -1.0], [0.0, 1.0]], [Path.MOVETO, Path.LINETO, Path.MOVETO, Path.LINETO]) - def _draw_plus(self, renderer, gc, path): + def _draw_plus(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset) renderer.draw_markers(gc, self._plus_path, transform, - path, self.get_transform()) + path, path_trans) _tri_path = Path([[0.0, 0.0], [0.0, -1.0], @@ -897,61 +907,61 @@ [Path.MOVETO, Path.LINETO, Path.MOVETO, Path.LINETO, Path.MOVETO, Path.LINETO]) - def _draw_tri_down(self, renderer, gc, path): + def _draw_tri_down(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset) renderer.draw_markers(gc, self._tri_path, transform, - path, self.get_transform()) + path, path_trans) - def _draw_tri_up(self, renderer, gc, path): + def _draw_tri_up(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset).rotate_deg(180) renderer.draw_markers(gc, self._tri_path, transform, - path, self.get_transform()) + path, path_trans) - def _draw_tri_left(self, renderer, gc, path): + def _draw_tri_left(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset).rotate_deg(90) renderer.draw_markers(gc, self._tri_path, transform, - path, self.get_transform()) + path, path_trans) - def _draw_tri_right(self, renderer, gc, path): + def _draw_tri_right(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset).rotate_deg(270) renderer.draw_markers(gc, self._tri_path, transform, - path, self.get_transform()) + path, path_trans) _caret_path = Path([[-1.0, 1.5], [0.0, 0.0], [1.0, 1.5]], closed=False) - def _draw_caretdown(self, renderer, gc, path): + def _draw_caretdown(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset) renderer.draw_markers(gc, self._caret_path, transform, - path, self.get_transform()) + path, path_trans) - def _draw_caretup(self, renderer, gc, path): + def _draw_caretup(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset).rotate_deg(180) renderer.draw_markers(gc, self._caret_path, transform, - path, self.get_transform()) + path, path_trans) - def _draw_caretleft(self, renderer, gc, path): + def _draw_caretleft(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset).rotate_deg(90) renderer.draw_markers(gc, self._caret_path, transform, - path, self.get_transform()) + path, path_trans) - def _draw_caretright(self, renderer, gc, path): + def _draw_caretright(self, renderer, gc, path, path_trans): offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset).rotate_deg(270) renderer.draw_markers(gc, self._caret_path, transform, - path, self.get_transform()) + path, path_trans) _x_path = Path([[-1.0, -1.0], [1.0, 1.0], @@ -962,7 +972,7 @@ offset = 0.5*renderer.points_to_pixels(self._markersize) transform = Affine2D().scale(offset) renderer.draw_markers(gc, self._x_path, transform, - path, self.get_transform()) + path, path_trans) def update_from(self, other): Modified: branches/transforms/lib/matplotlib/path.py =================================================================== --- branches/transforms/lib/matplotlib/path.py 2007-09-25 12:15:22 UTC (rev 3888) +++ branches/transforms/lib/matplotlib/path.py 2007-09-25 17:04:51 UTC (rev 3889) @@ -88,10 +88,6 @@ def transformed(self, transform): return Path(transform.transform(self.vertices), self.codes) - - def transformed_without_affine(self, transform): - vertices, affine = transform.transform_without_affine(self.vertices) - return Path(vertices, self.codes), affine _unit_rectangle = None #@classmethod @@ -152,6 +148,3 @@ cls._unit_circle = Path(vertices, codes) return cls._unit_circle unit_circle = classmethod(unit_circle) - -# MGDTODO: Add a transformed path that would automatically invalidate -# itself when its transform changes Modified: branches/transforms/lib/matplotlib/scale.py =================================================================== --- branches/transforms/lib/matplotlib/scale.py 2007-09-25 12:15:22 UTC (rev 3888) +++ branches/transforms/lib/matplotlib/scale.py 2007-09-25 17:04:51 UTC (rev 3889) @@ -1,66 +1,54 @@ import numpy as npy from numpy import ma +from numpy.linalg import inv -from transforms import Affine1D, IntervalTransform, Transform +from transforms import Affine1DBase, IntervalTransform, Transform, \ + composite_transform_factory, IdentityTransform class ScaleBase(object): pass class LinearScale(ScaleBase): - def __init__(self, viewLim, direction): - direction = 'interval' + direction - self._transform = IntervalTransform(viewLim, direction) - def get_transform(self): - return self._transform + return IdentityTransform() class LogScale(ScaleBase): class LogTransform(Transform): input_dims = 1 output_dims = 1 - def __init__(self, viewLim, direction, base): + def __init__(self, base): Transform.__init__(self) self._base = base - self._viewLim = viewLim - self._direction = direction - self.set_children(['_viewLim']) + def is_separable(self): + return True + def transform(self, a): - a, affine = self.transform_without_affine(a) - return affine.transform(a) + if len(a) > 10: + print "Log Transforming..." + return ma.log10(ma.masked_where(a <= 0.0, a * 10.0)) - def transform_without_affine(self, a): - # MGDTODO: Support different bases - base = self._base - marray = ma.masked_where(a <= 0.0, a * 10.0) - marray = npy.log10(marray) - minimum, maximum = npy.log10(getattr(self._viewLim, self._direction) * 10.0) - return marray, Affine1D.from_values(maximum - minimum, minimum).inverted() - def inverted(self): - return LogScale.InvertedLogTransform(self._viewLim, self._direction, self._base) + return LogScale.InvertedLogTransform(self._base) class InvertedLogTransform(Transform): input_dims = 1 output_dims = 1 - def __init__(self, viewLim, direction, base): + def __init__(self, base): Transform.__init__(self) self._base = base - self._viewLim = viewLim - self._direction = direction - self.set_children(['_viewLim']) + + def is_separable(self): + return True def transform(self, a): - minimum, maximum = npy.log10(getattr(self._viewLim, self._direction) * 10.0) - a = Affine1D.from_values(maximum - minimum, minimum).transform(a) return ma.power(10.0, a) / 10.0 def inverted(self): - return LogScale.LogTransform(self._viewLim, self._direction, self._base) + return LogScale.LogTransform(self._base) - def __init__(self, viewLim, direction, base=10): - direction = 'interval' + direction - self._transform = self.LogTransform(viewLim, direction, base) + def __init__(self, base=10): + self._transform = self.LogTransform(base) def get_transform(self): return self._transform Modified: branches/transforms/lib/matplotlib/ticker.py =================================================================== --- branches/transforms/lib/matplotlib/ticker.py 2007-09-25 12:15:22 UTC (rev 3888) +++ branches/transforms/lib/matplotlib/ticker.py 2007-09-25 17:04:51 UTC (rev 3889) @@ -937,9 +937,7 @@ if vmin==vmax: vmin = decade_down(vmin,self._base) vmax = decade_up(vmax,self._base) - print vmin, vmax result = mtransforms.nonsingular(vmin, vmax) - print result return result class AutoLocator(MaxNLocator): Modified: branches/transforms/lib/matplotlib/transforms.py =================================================================== --- branches/transforms/lib/matplotlib/transforms.py 2007-09-25 12:15:22 UTC (rev 3888) +++ branches/transforms/lib/matplotlib/transforms.py 2007-09-25 17:04:51 UTC (rev 3889) @@ -8,7 +8,10 @@ from numpy import ma as ma from numpy.linalg import inv from sets import Set +from weakref import WeakKeyDictionary +from path import Path + DEBUG = False # MGDTODO: This creates a ton of cyclical references. We may want to @@ -22,45 +25,54 @@ self._parents = Set() self._children = [] - def invalidate(self): - self._do_invalidation() + def invalidate(self, which_child=None, affine_only=[]): + if which_child is None: + which_child = self + self._do_invalidation(which_child, affine_only) + # affine_only = affine_only and (self.is_affine() or self.is_bbox()) for parent in self._parents: - parent.invalidate() + parent.invalidate(self, affine_only + [self]) - def _do_invalidation(self): - return False - + def _do_invalidation(self, which_child, affine_only): + pass + def set_children(self, children): for child in children: getattr(self, child)._parents.add(self) self._children = children def make_graphviz(self, fobj): + seen = Set() + def recurse(root): + if root in seen: + return + seen.add(root) fobj.write('%s [label="%s"];\n' % (hash(root), root.__class__.__name__)) - if isinstance(root, Affine2DBase): + if root.is_affine(): fobj.write('%s [style=filled, color=".7 .7 .9"];\n' % hash(root)) - elif isinstance(root, BboxBase): + elif root.is_bbox(): fobj.write('%s [style=filled, color=".9 .9 .7"];\n' % hash(root)) for child_name in root._children: child = getattr(root, child_name) - fobj.write("%s -> %s;\n" % ( + fobj.write('%s -> %s [label="%s"];\n' % ( hash(root), - hash(child))) + hash(child), + child_name)) recurse(child) - + fobj.write("digraph G {\n") recurse(self) fobj.write("}\n") def is_affine(self): - return isinstance(self, Affine2DBase) + return False def is_bbox(self): - return isinstance(self, BboxBase) + return False class BboxBase(TransformNode): @@ -70,7 +82,10 @@ def __init__(self): TransformNode.__init__(self) - + + def is_bbox(self): + return True + def __array__(self): return self.get_points() @@ -125,63 +140,81 @@ height = property(_get_height) def _get_bounds(self): - return (self.xmin, self.ymin, - self.xmax - self.xmin, self.ymax - self.ymin) + ((xmin, ymin), (xmax, ymax)) = self.get_points() + return (xmin, ymin, xmax - xmin, ymax - ymin) bounds = property(_get_bounds) + def _get_lbrt(self): + return self.get_points().flatten().copy() + lbrt = property(_get_lbrt) + def get_points(self): return NotImplementedError() - + # MGDTODO: Optimize def containsx(self, x): - return x >= self.xmin and x <= self.xmax + xmin, xmax = self.intervalx + return x >= xmin and x <= xmax def containsy(self, y): - return y >= self.ymin and y <= self.ymax + ymin, ymax = self.intervaly + return y >= ymin and y <= ymax def contains(self, x, y): return self.containsx(x) and self.containsy(y) def overlapsx(self, other): - return self.containsx(other.xmin) \ - or self.containsx(other.xmax) + xmin, xmax = other.intervalx + return self.containsx(xmin) \ + or self.containsx(xmax) def overlapsy(self, other): - return self.containsy(other.ymin) \ - or self.containsx(other.ymax) + ymin, ymax = other.intervaly + return self.containsy(ymin) \ + or self.containsx(ymax) def overlaps(self, other): return self.overlapsx(other) \ and self.overlapsy(other) def fully_containsx(self, x): - return x > self.xmin and x < self.xmax + xmin, xmax = self.intervalx + return x > xmin and x < xmax def fully_containsy(self, y): - return y > self.ymin and y < self.ymax + ymin, ymax = self.intervaly + return y > ymin and y < ymax def fully_contains(self, x, y): return self.fully_containsx(x) \ and self.fully_containsy(y) def fully_overlapsx(self, other): - return self.fully_containsx(other.xmin) \ - or self.fully_containsx(other.xmax) + xmin, xmax = other.intervalx + return self.fully_containsx(xmin) \ + or self.fully_containsx(xmax) def fully_overlapsy(self, other): - return self.fully_containsy(other.ymin) \ - or self.fully_containsx(other.ymax) + ymin, ymax = other.intervaly + return self.fully_containsy(ymin) \ + or self.fully_containsx(ymax) def fully_overlaps(self, other): return self.fully_overlapsx(other) and \ self.fully_overlapsy(other) + def transformed(self, transform): + return Bbox(transform.transform(self.get_points())) + + def inverse_transformed(self, transform): + return Bbox(transform.inverted().transform(self.get_points())) + class Bbox(BboxBase): def __init__(self, points): BboxBase.__init__(self) self._points = npy.asarray(points, npy.float_) - + #@staticmethod def unit(): return Bbox.from_lbrt(0., 0., 1., 1.) @@ -198,12 +231,6 @@ return Bbox(points) from_lbrt = staticmethod(from_lbrt) - def __cmp__(self, other): - # MGDTODO: Totally suboptimal - if isinstance(other, Bbox) and (self._points == other._points).all(): - return 0 - return -1 - def __repr__(self): return 'Bbox(%s)' % repr(self._points) __str__ = __repr__ @@ -219,8 +246,7 @@ [max(x.max(), self.xmax), max(y.max(), self.ymax)]], npy.float_) self.invalidate() - - # MGDTODO: Probably a more efficient ways to do this... + def _set_xmin(self, val): self._points[0, 0] = val self.invalidate() @@ -278,12 +304,6 @@ self._points = other.get_points() self.invalidate() - def transformed(self, transform): - return Bbox(transform.transform(self._points)) - - def inverse_transformed(self, transform): - return Bbox(transform.inverted().transform(self._points)) - def expanded(self, sw, sh): width = self.width height = self.height @@ -324,6 +344,8 @@ def __init__(self, bbox, transform): assert bbox.is_bbox() assert isinstance(transform, Transform) + assert transform.input_dims == 2 + assert transform.output_dims == 2 BboxBase.__init__(self) self.bbox = bbox @@ -335,7 +357,7 @@ return "TransformedBbox(%s, %s)" % (self.bbox, self.transform) __str__ = __repr__ - def _do_invalidation(self): + def _do_invalidation(self, which_child, affine_only): self._points = None def get_points(self): @@ -347,13 +369,10 @@ class Transform(TransformNode): def __init__(self): TransformNode.__init__(self) - - def transform(self, points): - raise NotImplementedError() - def transform_without_affine(self, points): - return self.transform(points), IDENTITY - + def is_separable(self): + return False + def __add__(self, other): if isinstance(other, Transform): return composite_transform_factory(self, other) @@ -366,39 +385,69 @@ raise TypeError( "Can not add Transform to object of type '%s'" % type(other)) + def transform(self, points): + raise NotImplementedError + + def transform_affine(self, points): + raise NotImplementedError + + def transform_non_affine(self, points): + raise NotImplementedError + + def get_affine(self): + raise NotImplementedError + def transform_point(self, point): return self.transform(npy.asarray([point]))[0] - + def has_inverse(self): raise NotImplementedError() def inverted(self): raise NotImplementedError() - def is_separable(self): - return False +class TransformWrapper(Transform): + def __init__(self, child): + assert isinstance(child, Transform) + + Transform.__init__(self) + self.input_dims = child.input_dims + self.output_dims = child.output_dims + self._child = child + self.set_children(['_child']) -class TransformWrapper(Transform): - input_dims = 2 - output_dims = 2 - + def __repr__(self): + return "TransformWrapper(%r)" % self._child + __str__ = __repr__ + def set(self, child): - self.child = child - self.child._parents.add(self) + assert child.input_dims == self.input_dims + assert child.output_dims == self.output_dims + self._child = child + self.set_children(['_child']) self.invalidate() + + def is_separable(self): + return self._child.is_separable() + def is_affine(self): + return self._child.is_affine() + def transform(self, points): - return self.child.transform(points) + return self._child.transform(points) - def transform_without_affine(points): - return self.child.transform_without_affine(points) + def transform_affine(self, points): + return self._child.transform_affine(points) + + def transform_non_affine(self, points): + return self._child.transform_non_affine(points) + + def get_affine(self): + return self._child.get_affine() def inverted(self): - return self.child.inverted() - - def is_separable(self): - return self.child.is_separable() + return self._child.inverted() class AffineBase(Transform): @@ -406,10 +455,13 @@ Transform.__init__(self) self._inverted = None + def is_affine(self): + return True + def __array__(self, *args, **kwargs): return self.get_matrix() - def _do_invalidation(self): + def _do_invalidation(self, which_child, affine_only): self._inverted = None #@staticmethod @@ -425,10 +477,14 @@ def get_matrix(self): raise NotImplementedError() - def transform_without_affine(self, points): - # MGDTODO: Should we copy the points here? I'd like to avoid it, - # if possible - return points, self + def transform_affine(self, points): + return self.transform(points) + + def transform_non_affine(self, points): + return points + + def get_affine(self): + return self class Affine1DBase(AffineBase): @@ -437,13 +493,16 @@ def __init__(self): AffineBase.__init__(self) - + + def is_separable(self): + return True + def __array__(self, *args, **kwargs): return self.get_matrix() - + def to_values(self): mtx = self.get_matrix() - return tuple(mtx[0]) + return mtx[0] #@staticmethod def matrix_from_values(a, b): @@ -472,9 +531,6 @@ points = ma.asarray(values, npy.float_) return points * mtx[0,0] + mtx[0,1] - def is_separable(self): - return True - def inverted(self): if self._inverted is None: mtx = self.get_matrix() @@ -551,9 +607,12 @@ class IntervalTransform(Affine1DBase): def __init__(self, bbox, direction): + assert direction in ('x', 'y') + assert bbox.is_bbox() + Affine1DBase.__init__(self) self._bbox = bbox - self._direction = direction + self._direction = "interval" + direction self.set_children(['_bbox']) self._mtx = None @@ -561,10 +620,9 @@ return "IntervalTransform(%s)" % (getattr(self._bbox, self._direction)) __str__ = __repr__ - def _do_invalidation(self): - print "IntervalTransform.invalidation", self._bbox + def _do_invalidation(self, which_child, affine_only): self._mtx = None - Affine1DBase._do_invalidation(self) + Affine1DBase._do_invalidation(self, which_child, affine_only) def get_matrix(self): if self._mtx is None: @@ -581,6 +639,10 @@ def __init__(self): AffineBase.__init__(self) + def is_separable(self): + mtx = self.get_matrix() + return mtx[0, 1] == 0.0 and mtx[1, 0] == 0.0 + def __array__(self, *args, **kwargs): return self.get_matrix() @@ -627,10 +689,6 @@ mtx = self.get_matrix() self._inverted = Affine2D(inv(mtx)) return self._inverted - - def is_separable(self): - mtx = self.get_matrix() - return mtx[0, 1] == 0.0 and mtx[1, 0] == 0.0 class Affine2D(Affine2DBase): @@ -728,6 +786,10 @@ """ _mtx = npy.identity(3) + def __repr__(self): + return "IdentityTransform()" + __str__ = __repr__ + def __cmp__(self, other): if (isinstance(other, Affine2D) and (other == IDENTITY)): @@ -735,34 +797,44 @@ return -1 def get_matrix(self): - return _mtx + return self._mtx def transform(self, points): return points - def transform_without_affine(self, points): - return points, self + def transform_affine(self, points): + return points + def transform_non_affine(self, points): + return points + + def get_affine(self): + return self + def inverted(self): return self + -IDENTITY = Affine2D() - class BlendedGenericTransform(Transform): input_dims = 2 output_dims = 2 def __init__(self, x_transform, y_transform): # Here we ask: "Does it blend?" - # MGDTODO: Turn these checks back on - # assert x_transform.is_separable() - # assert y_transform.is_separable() + assert x_transform.is_separable() + assert y_transform.is_separable() Transform.__init__(self) self._x = x_transform self._y = y_transform self.set_children(['_x', '_y']) + def is_affine(self): + return self._x.is_affine() and self._y.is_affine() + + def is_separable(self): + return True + def __repr__(self): return "BlendedGenericTransform(%s,%s)" % (self._x, self._y) __str__ = __repr__ @@ -787,33 +859,17 @@ return ma.concatenate((x_points, y_points), 1) - def transform_without_affine(self, points): - x = self._x - y = self._y - if x == y and x.input_dims == 2: - return self._x.transform_without_affine(points) - - if x.input_dims == 2: - x_points, x_affine = x.transform_without_affine(points) - x_points = x_points[:, 0:1] - else: - x_points, x_affine = x.transform_without_affine(points[:, 0]) - x_points = x_points.reshape((len(x_points), 1)) - - if y.input_dims == 2: - y_points, y_affine = y.transform_without_affine(points) - y_points = y_points[:, 1:] - else: - y_points, y_affine = y.transform_without_affine(points[:, 1]) - y_points = y_points.reshape((len(y_points), 1)) - - return ma.concatenate((x_points, y_points), 1), blended_transform_factory(x_affine, y_affine) + def transform_affine(self, points): + return points + + def transform_non_affine(self, points): + return self.transform(points) + + def get_affine(self): + return IdentityTransform() def inverted(self): return BlendedGenericTransform(self._x.inverted(), self._y.inverted()) - - def is_separable(self): - return True class BlendedAffine1D(Affine2DBase, Transform): @@ -829,17 +885,17 @@ Affine2DBase.__init__(self) self._mtx = None + def is_separable(self): + return True + def __repr__(self): return "BlendedAffine1D(%s,%s)" % (self._x, self._y) __str__ = __repr__ - def _do_invalidation(self): + def _do_invalidation(self, which_child, affine_only): self._mtx = None - Affine2DBase._do_invalidation(self) + Affine2DBase._do_invalidation(self, which_child, affine_only) - def is_separable(self): - return True - def get_matrix(self): if self._mtx is None: x_mtx = self._x.get_matrix() @@ -854,9 +910,9 @@ def __init__(self, x_transform, y_transform): assert x_transform.is_affine() assert y_transform.is_affine() - # MGDTODO: Turn these checks back on - # assert x_transform.is_separable() - # assert y_transform.is_separable() + assert x_transform.is_separable() + assert y_transform.is_separable() + Transform.__init__(self) self._x = x_transform self._y = y_transform @@ -865,17 +921,17 @@ Affine2DBase.__init__(self) self._mtx = None + def is_separable(self): + return True + def __repr__(self): return "BlendedAffine2D(%s,%s)" % (self._x, self._y) __str__ = __repr__ - def _do_invalidation(self): + def _do_invalidation(self, which_child, affine_only): self._mtx = None - Affine2DBase._do_invalidation(self) + Affine2DBase._do_invalidation(self, which_child, affine_only) - def is_separable(self): - return True - def get_matrix(self): if self._mtx is None: if self._x == self._y: @@ -909,8 +965,12 @@ self._b = b self.set_children(['_a', '_b']) - self.take_shortcut = b.is_affine() - + def is_affine(self): + return self._a.is_affine() and self._b.is_affine() + + def is_separable(self): + return self._a.is_separable() and self._b.is_separable() + def __repr__(self): return "CompositeGenericTransform(%s, %s)" % (self._a, self._b) __str__ = __repr__ @@ -918,20 +978,24 @@ def transform(self, points): return self._b.transform(self._a.transform(points)) - def transform_without_affine(self, points): - if self.take_shortcut: - return self._a.transform(points), self._b - return self.transform(points), IDENTITY + def transform_affine(self, points): + return self._b.transform_affine(self._a.transform_affine(points)) + + def transform_non_affine(self, points): + return self._b.transform_non_affine(self._a.transform_non_affine(points)) + + def get_affine(self): + return self._a.get_affine() + self._b.get_affine() def inverted(self): return CompositeGenericTransform(self._b.inverted(), self._a.inverted()) - - def is_separable(self): - return self._a.is_separable() and self._b.is_separable() class CompositeAffine2D(Affine2DBase): def __init__(self, a, b): + assert a.output_dims == b.input_dims + self.input_dims = a.input_dims + self.output_dims = b.output_dims assert a.is_affine() assert b.is_affine() @@ -945,9 +1009,9 @@ return "CompositeAffine2D(%s, %s)" % (self._a, self._b) __str__ = __repr__ - def _do_invalidation(self): + def _do_invalidation(self, which_child, affine_only): self._mtx = None - Affine2DBase._do_invalidation(self) + Affine2DBase._do_invalidation(self, which_child, affine_only) def get_matrix(self): if self._mtx is None: @@ -958,7 +1022,9 @@ def composite_transform_factory(a, b): - if a.is_affine() and b.is_affine(): + if isinstance(a, BboxTransform) and isinstance(b, BboxTransform): + return BboxTransform(a._boxin, b._boxout) + if isinstance(a, AffineBase) and isinstance(b, AffineBase): return CompositeAffine2D(a, b) return CompositeGenericTransform(a, b) @@ -972,33 +1038,6 @@ return npy.log10(m) -class TestLogTransform(Transform): - input_dims = 1 - output_dims = 1 - def transform(self, a): - marray = ma.masked_where(a <= 0.0, a * 10.0) - return (npy.log10(marray) * 0.5) + 0.5 - - def inverted(self): - return TestInvertLogTransform() - - def is_separable(self): - return True - - -class TestInvertLogTransform(Transform): - input_dims = 1 - output_dims = 1 - def transform(self, a): - return ma.power(10, (a - 0.5) * 2.0) / 10.0 - - def inverted(self): - return TestLogTransform() - - def is_separable(self): - return True - - class TestPolarTransform(Transform): input_dims = 2 output_dims = 2 @@ -1078,9 +1117,9 @@ return "BboxTransform(%s, %s)" % (self._boxin, self._boxout) __str__ = __repr__ - def _do_invalidation(self): + def _do_invalidation(self, which_child, affine_only): self._mtx = None - Affine2DBase._do_invalidation(self) + Affine2DBase._do_invalidation(self, which_child, affine_only) def is_separable(self): return True @@ -1101,7 +1140,38 @@ self._mtx = affine._mtx return self._mtx + +class TransformedPath(TransformNode): + def __init__(self, path, transform): + assert isinstance(transform, Transform) + TransformNode.__init__(self) + + self._path = path + self._transform = transform + self.set_children(['_transform']) + self._transformed_path = None + + def _do_invalidation(self, which_child, affine_only): + if not (affine_only[0].is_affine() or affine_only[0].is_bbox()): + self._transformed_path = None + + def get_path_and_affine(self): + if self._transformed_path is None: + vertices = self._transform.transform_non_affine(self._path.vertices) + self._transformed_path = Path(vertices, self._path.codes) + return self._transformed_path, self._transform.get_affine() + + def get_path(self): + if self._transformed_path is None: + vertices = self._tranform.transform_non_affine(self._path.vertices) + self._transformed_path = Path(vertices, self._path.codes) + vertices = self._transform.transform_affine(self._transformed_path.vertices) + return Path(vertices, self._transformed_path.codes) + + def get_affine(self): + return self._transform.get_affine() + def nonsingular(vmin, vmax, expander=0.001, tiny=1e-15, increasing=True): ''' Ensure the endpoints of a range are not too close together. @@ -1128,6 +1198,7 @@ vmin, vmax = vmax, vmin return vmin, vmax + # MGDTODO: Optimize (perhaps in an extension) def interval_contains(interval, val): return interval[0] <= val and interval[1] >= val @@ -1173,8 +1244,8 @@ bbox = Bbox.from_lbwh(10, 11, 12, 13) assert bbox.bounds == (10, 11, 12, 13) - bbox_copy = copy.copy(bbox) - assert bbox == bbox_copy + bbox_copy = copy.deepcopy(bbox) + assert (bbox.lbrt == bbox_copy.lbrt).all() bbox_copy.max = (14, 15) assert bbox.bounds == (10, 11, 12, 13) assert bbox_copy.bounds == (10, 11, 4, 4) @@ -1183,7 +1254,7 @@ bbox2 = Bbox([[30., 35.], [40., 45.]]) trans = BboxTransform(bbox1, bbox2) bbox3 = bbox1.transformed(trans) - assert bbox3 == bbox2 + assert (bbox3.lbrt == bbox2.lbrt).all() translation = Affine2D().translate(10, 20) assert translation.to_values() == (1, 0, 0, 1, 10, 20) @@ -1210,12 +1281,6 @@ print points - comp = TestLogTransform() + Affine2D().rotate_deg(15) - tpoints = comp.transform(points) - itpoints = comp.inverted().transform(tpoints) - print tpoints, itpoints - assert (points.round() == itpoints.round()).all() - # Here are some timing tests points = npy.asarray([(random(), random()) for i in xrange(10000)]) t = timeit.Timer("trans_sum.transform(points)", "from __main__ import trans_sum, points") This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <js...@us...> - 2007-09-25 12:15:28
|
Revision: 3888 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3888&view=rev Author: jswhit Date: 2007-09-25 05:15:22 -0700 (Tue, 25 Sep 2007) Log Message: ----------- fix addcyclic Modified Paths: -------------- trunk/toolkits/basemap/Changelog Modified: trunk/toolkits/basemap/Changelog =================================================================== --- trunk/toolkits/basemap/Changelog 2007-09-25 12:14:28 UTC (rev 3887) +++ trunk/toolkits/basemap/Changelog 2007-09-25 12:15:22 UTC (rev 3888) @@ -1,4 +1,5 @@ -version 0.9.6 (svn revision 3878) +version 0.9.6 (svn revision 3888) + * fix addcyclic function so it handles masked arrays. * labelling of meridians and parallels now works with very small map regions (less than 0.2 degrees square). * Subregions of the globe may be specified with llcrnrlat, This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <js...@us...> - 2007-09-25 12:14:32
|
Revision: 3887 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3887&view=rev Author: jswhit Date: 2007-09-25 05:14:28 -0700 (Tue, 25 Sep 2007) Log Message: ----------- fix addcyclic so it can handle masked arrays Modified Paths: -------------- trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py Modified: trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py =================================================================== --- trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py 2007-09-24 17:33:03 UTC (rev 3886) +++ trunk/toolkits/basemap/lib/matplotlib/toolkits/basemap/basemap.py 2007-09-25 12:14:28 UTC (rev 3887) @@ -2917,10 +2917,16 @@ """ nlats = arrin.shape[0] nlons = arrin.shape[1] - arrout = NX.zeros((nlats,nlons+1),arrin.dtype) + if hasattr(arrin,'mask'): + arrout = ma.zeros((nlats,nlons+1),arrin.dtype) + else: + arrout = NX.zeros((nlats,nlons+1),arrin.dtype) arrout[:,0:nlons] = arrin[:,:] arrout[:,nlons] = arrin[:,0] - lonsout = NX.zeros(nlons+1,lonsin.dtype) + if hasattr(lonsin,'mask'): + lonsout = ma.zeros(nlons+1,lonsin.dtype) + else: + lonsout = NX.zeros(nlons+1,lonsin.dtype) lonsout[0:nlons] = lonsin[:] lonsout[nlons] = lonsin[-1] + lonsin[1]-lonsin[0] return arrout,lonsout This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2007-09-24 17:33:08
|
Revision: 3886 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3886&view=rev Author: mdboom Date: 2007-09-24 10:33:03 -0700 (Mon, 24 Sep 2007) Log Message: ----------- Fixed log scaling again. Modified Paths: -------------- branches/transforms/lib/matplotlib/scale.py branches/transforms/lib/matplotlib/ticker.py branches/transforms/lib/matplotlib/transforms.py Modified: branches/transforms/lib/matplotlib/scale.py =================================================================== --- branches/transforms/lib/matplotlib/scale.py 2007-09-24 16:54:37 UTC (rev 3885) +++ branches/transforms/lib/matplotlib/scale.py 2007-09-24 17:33:03 UTC (rev 3886) @@ -23,6 +23,7 @@ self._base = base self._viewLim = viewLim self._direction = direction + self.set_children(['_viewLim']) def transform(self, a): a, affine = self.transform_without_affine(a) @@ -31,13 +32,9 @@ def transform_without_affine(self, a): # MGDTODO: Support different bases base = self._base - marray = ma.masked_where(a <= 0.0, a) + marray = ma.masked_where(a <= 0.0, a * 10.0) marray = npy.log10(marray) - minimum, maximum = getattr(self._viewLim, self._direction) - minimum, maximum = npy.log10([minimum, maximum]) - print marray - print Affine1D.from_values(maximum - minimum, minimum).inverted() - print minimum, maximum + minimum, maximum = npy.log10(getattr(self._viewLim, self._direction) * 10.0) return marray, Affine1D.from_values(maximum - minimum, minimum).inverted() def inverted(self): @@ -51,11 +48,12 @@ self._base = base self._viewLim = viewLim self._direction = direction - + self.set_children(['_viewLim']) + def transform(self, a): - minimum, maximum = getattr(self._viewLim, self._direction) - Affine1D.from_values(maximum - minimum, minimum).transform(a) - return ma.power(10.0, a) + minimum, maximum = npy.log10(getattr(self._viewLim, self._direction) * 10.0) + a = Affine1D.from_values(maximum - minimum, minimum).transform(a) + return ma.power(10.0, a) / 10.0 def inverted(self): return LogScale.LogTransform(self._viewLim, self._direction, self._base) Modified: branches/transforms/lib/matplotlib/ticker.py =================================================================== --- branches/transforms/lib/matplotlib/ticker.py 2007-09-24 16:54:37 UTC (rev 3885) +++ branches/transforms/lib/matplotlib/ticker.py 2007-09-24 17:33:03 UTC (rev 3886) @@ -928,15 +928,19 @@ # if minpos<=0: # raise RuntimeError('No positive data to plot') - minpos = max(vmin, 0.00001) #MGDTODO - if vmin<=0: - vmin = minpos + # MGDTODO: Find a good way to track minpos + if vmin <= 0.0: + vmin = 0.1 + if not is_decade(vmin,self._base): vmin = decade_down(vmin,self._base) if not is_decade(vmax,self._base): vmax = decade_up(vmax,self._base) if vmin==vmax: vmin = decade_down(vmin,self._base) vmax = decade_up(vmax,self._base) - return mtransforms.nonsingular(vmin, vmax) + print vmin, vmax + result = mtransforms.nonsingular(vmin, vmax) + print result + return result class AutoLocator(MaxNLocator): def __init__(self): Modified: branches/transforms/lib/matplotlib/transforms.py =================================================================== --- branches/transforms/lib/matplotlib/transforms.py 2007-09-24 16:54:37 UTC (rev 3885) +++ branches/transforms/lib/matplotlib/transforms.py 2007-09-24 17:33:03 UTC (rev 3886) @@ -181,7 +181,7 @@ def __init__(self, points): BboxBase.__init__(self) self._points = npy.asarray(points, npy.float_) - + #@staticmethod def unit(): return Bbox.from_lbrt(0., 0., 1., 1.) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2007-09-24 16:54:40
|
Revision: 3885 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3885&view=rev Author: mdboom Date: 2007-09-24 09:54:37 -0700 (Mon, 24 Sep 2007) Log Message: ----------- Merged revisions 3873-3884 via svnmerge from http://matplotlib.svn.sf.net/svnroot/matplotlib/trunk/matplotlib ........ r3874 | jouni | 2007-09-22 02:48:49 -0400 (Sat, 22 Sep 2007) | 3 lines Replace some generator expressions by list comprehensions for Python 2.3 compatibility ........ r3879 | dsdale | 2007-09-24 08:56:38 -0400 (Mon, 24 Sep 2007) | 2 lines fix backend_qt* bug with multiple plot windows and show() ........ r3880 | dsdale | 2007-09-24 09:00:12 -0400 (Mon, 24 Sep 2007) | 2 lines backend_qt* bugfix for multiple plot windows and show() ........ r3881 | dsdale | 2007-09-24 09:01:17 -0400 (Mon, 24 Sep 2007) | 2 lines fix backend_wxagg reference in new config module ........ r3882 | dsdale | 2007-09-24 09:03:01 -0400 (Mon, 24 Sep 2007) | 3 lines modifed embedding_in_qt* examples so they can be run from ipython with -q*thread ........ r3883 | dsdale | 2007-09-24 11:11:58 -0400 (Mon, 24 Sep 2007) | 2 lines fix bug in improved support for multiple windows in backend_qt4 ........ Modified Paths: -------------- branches/transforms/CHANGELOG branches/transforms/examples/embedding_in_qt.py branches/transforms/examples/embedding_in_qt4.py branches/transforms/lib/matplotlib/backends/backend_pdf.py branches/transforms/lib/matplotlib/backends/backend_qt.py branches/transforms/lib/matplotlib/backends/backend_qt4.py branches/transforms/lib/matplotlib/config/mpltraits.py branches/transforms/lib/matplotlib/dviread.py Property Changed: ---------------- branches/transforms/ Property changes on: branches/transforms ___________________________________________________________________ Name: svnmerge-integrated - /trunk/matplotlib:1-3872 + /trunk/matplotlib:1-3884 Modified: branches/transforms/CHANGELOG =================================================================== --- branches/transforms/CHANGELOG 2007-09-24 16:53:38 UTC (rev 3884) +++ branches/transforms/CHANGELOG 2007-09-24 16:54:37 UTC (rev 3885) @@ -1,3 +1,7 @@ +2007-09-24 Applied Eike Welk's patch reported on mpl-dev on 2007-09-22 + Fixes a bug with multiple plot windows in the qt backend, + ported the changes to backend_qt4 as well - DSD + 2007-09-21 Changed cbook.reversed to yield the same result as the python reversed builtin - DSD Modified: branches/transforms/examples/embedding_in_qt.py =================================================================== --- branches/transforms/examples/embedding_in_qt.py 2007-09-24 16:53:38 UTC (rev 3884) +++ branches/transforms/examples/embedding_in_qt.py 2007-09-24 16:54:37 UTC (rev 3885) @@ -25,7 +25,7 @@ # Note: color-intensive applications may require a different color allocation # strategy. -QApplication.setColorSpec(QApplication.NormalColor) +#QApplication.setColorSpec(QApplication.NormalColor) app = QApplication(sys.argv) class MyMplCanvas(FigureCanvas): @@ -129,12 +129,8 @@ % {"prog": progname, "version": progversion}) -def main(): - aw = ApplicationWindow() - aw.setCaption("%s" % progname) - qApp.setMainWidget(aw) - aw.show() - sys.exit(qApp.exec_loop()) - - -if __name__ == "__main__": main() +aw = ApplicationWindow() +aw.setCaption("%s" % progname) +qApp.setMainWidget(aw) +aw.show() +sys.exit(qApp.exec_loop()) Modified: branches/transforms/examples/embedding_in_qt4.py =================================================================== --- branches/transforms/examples/embedding_in_qt4.py 2007-09-24 16:53:38 UTC (rev 3884) +++ branches/transforms/examples/embedding_in_qt4.py 2007-09-24 16:54:37 UTC (rev 3885) @@ -122,17 +122,10 @@ % {"prog": progname, "version": progversion}) -def main(): - # Note: color-intensive applications may require a different color - # allocation strategy. - QtGui.QApplication.setColorSpec(QtGui.QApplication.NormalColor) - qApp = QtGui.QApplication(sys.argv) +qApp = QtGui.QApplication(sys.argv) - aw = ApplicationWindow() - aw.setWindowTitle("%s" % progname) - aw.show() -# sys.exit(qApp.exec_()) - qApp.exec_() - - -if __name__ == "__main__": main() +aw = ApplicationWindow() +aw.setWindowTitle("%s" % progname) +aw.show() +sys.exit(qApp.exec_()) +#qApp.exec_() Modified: branches/transforms/lib/matplotlib/backends/backend_pdf.py =================================================================== --- branches/transforms/lib/matplotlib/backends/backend_pdf.py 2007-09-24 16:53:38 UTC (rev 3884) +++ branches/transforms/lib/matplotlib/backends/backend_pdf.py 2007-09-24 16:54:37 UTC (rev 3885) @@ -541,10 +541,10 @@ widths[ch] = afmdata.get_width_char(ch, isord=True) except KeyError: pass - not_None = (ch for ch in range(256) - if widths[ch] is not None) - firstchar = not_None.next() - lastchar = max(not_None) + not_None = [ch for ch in range(256) + if widths[ch] is not None] + firstchar = not_None[0] + lastchar = not_None[-1] widths = widths[firstchar:lastchar+1] for i,w in enumerate(widths): if w is None: widths[i] = 0 Modified: branches/transforms/lib/matplotlib/backends/backend_qt.py =================================================================== --- branches/transforms/lib/matplotlib/backends/backend_qt.py 2007-09-24 16:53:38 UTC (rev 3884) +++ branches/transforms/lib/matplotlib/backends/backend_qt.py 2007-09-24 16:54:37 UTC (rev 3885) @@ -46,11 +46,11 @@ qApp = qt.QApplication( [" "] ) qt.QObject.connect( qApp, qt.SIGNAL( "lastWindowClosed()" ), qApp, qt.SLOT( "quit()" ) ) - else: - # someone else aready created the qApp and - # we let them handle the event-loop control. - show._needmain = False + #remember that matplotlib created the qApp - will be used by show() + _create_qApp.qAppCreatedHere = True +_create_qApp.qAppCreatedHere = False + def show(): """ Show all the figures and enter the qt main loop @@ -65,13 +65,10 @@ if figManager != None: figManager.canvas.draw() - if ( show._needmain ): - qt.qApp.exec_loop() - show._needmain = False + if _create_qApp.qAppCreatedHere: + qt.qApp.exec_loop() -show._needmain = True - def new_figure_manager( num, *args, **kwargs ): """ Create a new figure manager instance Modified: branches/transforms/lib/matplotlib/backends/backend_qt4.py =================================================================== --- branches/transforms/lib/matplotlib/backends/backend_qt4.py 2007-09-24 16:53:38 UTC (rev 3884) +++ branches/transforms/lib/matplotlib/backends/backend_qt4.py 2007-09-24 16:54:37 UTC (rev 3885) @@ -46,11 +46,11 @@ qApp = QtGui.QApplication( [" "] ) QtCore.QObject.connect( qApp, QtCore.SIGNAL( "lastWindowClosed()" ), qApp, QtCore.SLOT( "quit()" ) ) - else: - # someone else aready created the qApp and - # we let them handle the event-loop control. - show._needmain = False + #remember that matplotlib created the qApp - will be used by show() + _create_qApp.qAppCreatedHere = True +_create_qApp.qAppCreatedHere = False + def show(): """ Show all the figures and enter the qt main loop @@ -65,13 +65,10 @@ if figManager != None: figManager.canvas.draw() - if ( show._needmain ): - qApp.exec_() - show._needmain = False + if _create_qApp.qAppCreatedHere: + QtGui.qApp.exec_() -show._needmain = True - def new_figure_manager( num, *args, **kwargs ): """ Create a new figure manager instance Modified: branches/transforms/lib/matplotlib/config/mpltraits.py =================================================================== --- branches/transforms/lib/matplotlib/config/mpltraits.py 2007-09-24 16:53:38 UTC (rev 3884) +++ branches/transforms/lib/matplotlib/config/mpltraits.py 2007-09-24 16:54:37 UTC (rev 3885) @@ -29,7 +29,7 @@ 'gtkcairo': 'GTKCairo', 'qt4agg': 'Qt4Agg', 'qtagg': 'QtAgg', - 'wxagg': 'WxAgg', + 'wxagg': 'WXAgg', 'agg': 'Agg', 'cairo': 'Cairo', 'ps': 'PS', Modified: branches/transforms/lib/matplotlib/dviread.py =================================================================== --- branches/transforms/lib/matplotlib/dviread.py 2007-09-24 16:53:38 UTC (rev 3884) +++ branches/transforms/lib/matplotlib/dviread.py 2007-09-24 16:54:37 UTC (rev 3885) @@ -350,9 +350,9 @@ def _xxx(self, special): matplotlib.verbose.report( 'Dvi._xxx: encountered special: %s' - % ''.join((32 <= ord(ch) < 127) and ch - or '<%02x>' % ord(ch) - for ch in special), + % ''.join([(32 <= ord(ch) < 127) and ch + or '<%02x>' % ord(ch) + for ch in special]), 'debug') def _fnt_def(self, k, c, s, d, a, l, n): This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <md...@us...> - 2007-09-24 16:53:40
|
Revision: 3884 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3884&view=rev Author: mdboom Date: 2007-09-24 09:53:38 -0700 (Mon, 24 Sep 2007) Log Message: ----------- More progress. (Kind of a broken mess at the moment.) Modified Paths: -------------- branches/transforms/lib/matplotlib/axes.py branches/transforms/lib/matplotlib/axis.py branches/transforms/lib/matplotlib/ticker.py branches/transforms/lib/matplotlib/transforms.py Added Paths: ----------- branches/transforms/lib/matplotlib/scale.py Modified: branches/transforms/lib/matplotlib/axes.py =================================================================== --- branches/transforms/lib/matplotlib/axes.py 2007-09-24 15:11:58 UTC (rev 3883) +++ branches/transforms/lib/matplotlib/axes.py 2007-09-24 16:53:38 UTC (rev 3884) @@ -25,6 +25,7 @@ from matplotlib import patches as mpatches from matplotlib import pbox as mpbox from matplotlib import quiver as mquiver +from matplotlib import scale as mscale from matplotlib import table as mtable from matplotlib import text as mtext from matplotlib import ticker as mticker @@ -449,7 +450,6 @@ **kwargs ): """ - Build an Axes instance in Figure with rect=[left, bottom, width,height in Figure coords @@ -467,8 +467,8 @@ navigate: True|False navigate_mode: the navigation toolbar button status: 'PAN', 'ZOOM', or None position: [left, bottom, width,height in Figure coords - sharex : an Axes instance to share the x-axis with - sharey : an Axes instance to share the y-axis with + sharex: an Axes instance to share the x-axis with + sharey: an Axes instance to share the y-axis with title: the title string visible: a boolean - whether the axes is visible xlabel: the xlabel @@ -491,7 +491,7 @@ self.set_adjustable('box') self.set_anchor('C') - # must be set before set_figure + # MGDTODO: Check that the axes being shared are scalable self._sharex = sharex self._sharey = sharey if sharex is not None: @@ -508,7 +508,7 @@ # this call may differ for non-sep axes, eg polar self._init_axis() - + if axisbg is None: axisbg = rcParams['axes.facecolor'] self._axisbg = axisbg self._frameon = frameon @@ -545,8 +545,8 @@ "move this out of __init__ because non-separable axes don't use it" self.xaxis = maxis.XAxis(self) self.yaxis = maxis.YAxis(self) + self._update_transAxisXY() - def sharex_foreign(self, axforeign): """ You can share your x-axis view limits with another Axes in the @@ -627,26 +627,17 @@ set the dataLim and viewLim BBox attributes and the transData and transAxes Transformation attributes """ - self.viewLim = mtransforms.Bbox.unit() self.dataLim = mtransforms.Bbox.unit() - + self.viewLim = mtransforms.Bbox.unit() self.transAxes = mtransforms.BboxTransform( mtransforms.Bbox.unit(), self.bbox) - # self.set_transform(self.transAxes) -# self.transData = mtransforms.BboxTransform( -# self.viewLim, self.bbox) - self.preDataTransform = mtransforms.BboxTransform( - self.viewLim, mtransforms.Bbox.unit()) -# self.dataTransform = mtransforms.TestPolarTransform() -# self.dataTransform = mtransforms.blended_transform_factory( -# mtransforms.TestLogTransform(), -# mtransforms.Affine2D()) - self.dataTransform = mtransforms.Affine2D() - self.transData = self.preDataTransform + self.dataTransform + mtransforms.BboxTransform( - mtransforms.Bbox.unit(), self.bbox) - self.transData.make_graphviz(open("trans.dot", "w")) + self.transAxisXY = mtransforms.TransformWrapper() + self.transData = self.transAxisXY + self.transAxes + + def _update_transAxisXY(self): + self.transAxisXY.set(mtransforms.blended_transform_factory( + self.xaxis.get_transform(), self.yaxis.get_transform())) - def get_position(self, original=False): 'Return the axes rectangle left, bottom, width, height' if original: @@ -1525,11 +1516,9 @@ def get_xscale(self): 'return the xaxis scale string: log or linear' - # MGDTODO - # return self.scaled[self.transData.get_funcx().get_type()] - return 'log' + return self.xaxis.get_scale() - def set_xscale(self, value, basex = 10, subsx=None): + def set_xscale(self, value, **kwargs): """ SET_XSCALE(value, basex=10, subsx=None) @@ -1547,27 +1536,9 @@ ACCEPTS: ['log' | 'linear' ] """ - - #if subsx is None: subsx = range(2, basex) - assert(value.lower() in ('log', 'linear', )) - if value == 'log': - # MGDTODO -# self.xaxis.set_major_locator(mticker.LogLocator(basex)) -# self.xaxis.set_major_formatter(mticker.LogFormatterMathtext(basex)) -# self.xaxis.set_minor_locator(mticker.LogLocator(basex,subsx)) -# self.transData.get_funcx().set_type(mtrans.LOG10) -# minx, maxx = self.get_xlim() -# if min(minx, maxx)<=0: -# self.autoscale_view() - pass - elif value == 'linear': - self.xaxis.set_major_locator(mticker.AutoLocator()) - self.xaxis.set_major_formatter(mticker.ScalarFormatter()) - self.xaxis.set_minor_locator(mticker.NullLocator()) - self.xaxis.set_minor_formatter(mticker.NullFormatter()) - # self.transData.get_funcx().set_type( mtrans.IDENTITY ) - self.transData.get_funcx().set_type( 0 ) # MGDTODO - + self.xaxis.set_scale(value, **kwargs) + self._update_transAxisXY() + def get_xticks(self): 'Return the x ticks as a list of locations' return self.xaxis.get_ticklocs() @@ -1655,9 +1626,8 @@ def get_yscale(self): 'return the yaxis scale string: log or linear' - # return self.scaled[self.transData.get_funcy().get_type()] - return 'linear' - + return self.yaxis.get_scale() + def set_yscale(self, value, basey=10, subsy=None): """ SET_YSCALE(value, basey=10, subsy=None) @@ -1676,29 +1646,9 @@ ACCEPTS: ['log' | 'linear'] """ - - #if subsy is None: subsy = range(2, basey) - assert(value.lower() in ('log', 'linear', )) - - if value == 'log': - # MGDTODO -# self.yaxis.set_major_locator(mticker.LogLocator(basey)) -# self.yaxis.set_major_formatter(mticker.LogFormatterMathtext(basey)) -# self.yaxis.set_minor_locator(mticker.LogLocator(basey,subsy)) -# self.transData.get_funcy().set_type(mtrans.LOG10) -# miny, maxy = self.get_ylim() -# if min(miny, maxy)<=0: -# self.autoscale_view() - pass - - elif value == 'linear': - self.yaxis.set_major_locator(mticker.AutoLocator()) - self.yaxis.set_major_formatter(mticker.ScalarFormatter()) - self.yaxis.set_minor_locator(mticker.NullLocator()) - self.yaxis.set_minor_formatter(mticker.NullFormatter()) - # self.transData.get_funcy().set_type( mtrans.IDENTITY ) MGDTODO - self.transData.get_funcy().set_type( 0 ) - + self.yaxis.set_scale(value, basey, subsy) + self._update_transAxisXY() + def get_yticks(self): 'Return the y ticks as a list of locations' return self.yaxis.get_ticklocs() Modified: branches/transforms/lib/matplotlib/axis.py =================================================================== --- branches/transforms/lib/matplotlib/axis.py 2007-09-24 15:11:58 UTC (rev 3883) +++ branches/transforms/lib/matplotlib/axis.py 2007-09-24 16:53:38 UTC (rev 3884) @@ -12,14 +12,15 @@ from lines import Line2D, TICKLEFT, TICKRIGHT, TICKUP, TICKDOWN from matplotlib import rcParams from patches import bbox_artist -from ticker import NullFormatter, FixedFormatter, ScalarFormatter, LogFormatter +from ticker import NullFormatter, FixedFormatter, ScalarFormatter, LogFormatter, LogFormatterMathtext from ticker import NullLocator, FixedLocator, LinearLocator, LogLocator, AutoLocator from font_manager import FontProperties from text import Text, TextWithDash, _process_text_args from transforms import Affine2D, Bbox, blended_transform_factory, interval_contains, \ - interval_contains_open + interval_contains_open, IntervalTransform from patches import bbox_artist +from scale import LinearScale, LogScale import matplotlib.units as units #import pdb @@ -479,7 +480,7 @@ """ LABELPAD = 5 OFFSETTEXTPAD = 3 - + def __str__(self): return str(self.__class__).split('.')[-1] \ + "(%d,%d)"%self.axes.transAxes.xy_tup((0,0)) @@ -507,9 +508,38 @@ self.majorTicks = [] self.minorTicks = [] self.pickradius = pickradius - + self._transform = LinearScale(self.axes.viewLim, self.axis).get_transform() + self._scale = 'linear' + self.cla() + def get_transform(self): + return self._transform + + def get_scale(self): + return self._scale + + def set_scale(self, value, base=10, subs=None): + # MGDTODO: Move these settings (ticker etc.) into the scale class itself + value = value.lower() + assert value.lower() in ('log', 'linear') + if value == 'linear': + self.set_major_locator(AutoLocator()) + self.set_major_formatter(ScalarFormatter()) + self.set_minor_locator(NullLocator()) + self.set_minor_formatter(NullFormatter()) + self._transform = LinearScale(self.axes.viewLim, self.axis).get_transform() + elif value == 'log': + self.set_major_locator(LogLocator(base)) + self.set_major_formatter(LogFormatterMathtext(base)) + self.set_minor_locator(LogLocator(base,subs)) + # MGDTODO: Pass base along + self._transform = LogScale(self.axes.viewLim, self.axis).get_transform() + miny, maxy = getattr(self.axes.viewLim, 'interval' + self.axis) + if min(miny, maxy)<=0: + self.axes.autoscale_view() + self._scale = value + def get_children(self): children = [self.label] children.extend(self.majorTicks) @@ -595,7 +625,7 @@ for tick, loc, label in zip(minorTicks, minorLocs, minorLabels): if tick is None: continue - if not interval.contains(loc): continue + if not interval_contains(interval, loc): continue #if seen.has_key(loc): continue tick.update_position(loc) tick.set_label1(label) @@ -952,7 +982,8 @@ class XAxis(Axis): __name__ = 'xaxis' - + axis = 'x' + def contains(self,mouseevent): """Test whether the mouse event occured in the x axis. """ @@ -1134,7 +1165,8 @@ class YAxis(Axis): __name__ = 'yaxis' - + axis = 'y' + def contains(self,mouseevent): """Test whether the mouse event occurred in the y axis. Added: branches/transforms/lib/matplotlib/scale.py =================================================================== --- branches/transforms/lib/matplotlib/scale.py (rev 0) +++ branches/transforms/lib/matplotlib/scale.py 2007-09-24 16:53:38 UTC (rev 3884) @@ -0,0 +1,78 @@ +import numpy as npy +from numpy import ma + +from transforms import Affine1D, IntervalTransform, Transform + +class ScaleBase(object): + pass + +class LinearScale(ScaleBase): + def __init__(self, viewLim, direction): + direction = 'interval' + direction + self._transform = IntervalTransform(viewLim, direction) + + def get_transform(self): + return self._transform + +class LogScale(ScaleBase): + class LogTransform(Transform): + input_dims = 1 + output_dims = 1 + def __init__(self, viewLim, direction, base): + Transform.__init__(self) + self._base = base + self._viewLim = viewLim + self._direction = direction + + def transform(self, a): + a, affine = self.transform_without_affine(a) + return affine.transform(a) + + def transform_without_affine(self, a): + # MGDTODO: Support different bases + base = self._base + marray = ma.masked_where(a <= 0.0, a) + marray = npy.log10(marray) + minimum, maximum = getattr(self._viewLim, self._direction) + minimum, maximum = npy.log10([minimum, maximum]) + print marray + print Affine1D.from_values(maximum - minimum, minimum).inverted() + print minimum, maximum + return marray, Affine1D.from_values(maximum - minimum, minimum).inverted() + + def inverted(self): + return LogScale.InvertedLogTransform(self._viewLim, self._direction, self._base) + + class InvertedLogTransform(Transform): + input_dims = 1 + output_dims = 1 + def __init__(self, viewLim, direction, base): + Transform.__init__(self) + self._base = base + self._viewLim = viewLim + self._direction = direction + + def transform(self, a): + minimum, maximum = getattr(self._viewLim, self._direction) + Affine1D.from_values(maximum - minimum, minimum).transform(a) + return ma.power(10.0, a) + + def inverted(self): + return LogScale.LogTransform(self._viewLim, self._direction, self._base) + + def __init__(self, viewLim, direction, base=10): + direction = 'interval' + direction + self._transform = self.LogTransform(viewLim, direction, base) + + def get_transform(self): + return self._transform + + +_scale_mapping = { + 'linear': LinearScale, + 'log': LogScale + } +def scale_factory(scale, viewLim, direction): + if scale is None: + scale = 'linear' + return _scale_mapping[scale](viewLim, direction) Modified: branches/transforms/lib/matplotlib/ticker.py =================================================================== --- branches/transforms/lib/matplotlib/ticker.py 2007-09-24 15:11:58 UTC (rev 3883) +++ branches/transforms/lib/matplotlib/ticker.py 2007-09-24 16:53:38 UTC (rev 3884) @@ -500,8 +500,6 @@ def __call__(self, x, pos=None): 'Return the format for tick val x at position pos' - self.verify_intervals() - b = self._base # only label the decades fx = math.log(x)/math.log(b) @@ -890,10 +888,9 @@ def __call__(self): 'Return the locations of the ticks' - self.verify_intervals() b=self._base - vmin, vmax = self.viewInterval.get_bounds() + vmin, vmax = self.axis.get_view_interval() vmin = math.log(vmin)/math.log(b) vmax = math.log(vmax)/math.log(b) @@ -922,16 +919,16 @@ def autoscale(self): 'Try to choose the view limits intelligently' - self.verify_intervals() - - vmin, vmax = self.dataInterval.get_bounds() + vmin, vmax = self.axis.get_view_interval() if vmax<vmin: vmin, vmax = vmax, vmin - minpos = self.dataInterval.minpos() +# minpos = self.dataInterval.minpos() - if minpos<=0: - raise RuntimeError('No positive data to plot') +# if minpos<=0: +# raise RuntimeError('No positive data to plot') + + minpos = max(vmin, 0.00001) #MGDTODO if vmin<=0: vmin = minpos if not is_decade(vmin,self._base): vmin = decade_down(vmin,self._base) Modified: branches/transforms/lib/matplotlib/transforms.py =================================================================== --- branches/transforms/lib/matplotlib/transforms.py 2007-09-24 15:11:58 UTC (rev 3883) +++ branches/transforms/lib/matplotlib/transforms.py 2007-09-24 16:53:38 UTC (rev 3884) @@ -9,7 +9,7 @@ from numpy.linalg import inv from sets import Set -DEBUG = True +DEBUG = False # MGDTODO: This creates a ton of cyclical references. We may want to # consider using weak references @@ -61,8 +61,8 @@ def is_bbox(self): return isinstance(self, BboxBase) + - class BboxBase(TransformNode): ''' This is the read-only part of a bounding-box @@ -378,11 +378,30 @@ def is_separable(self): return False - -class Affine2DBase(Transform): + +class TransformWrapper(Transform): input_dims = 2 output_dims = 2 + + def set(self, child): + self.child = child + self.child._parents.add(self) + self.invalidate() + def transform(self, points): + return self.child.transform(points) + + def transform_without_affine(points): + return self.child.transform_without_affine(points) + + def inverted(self): + return self.child.inverted() + + def is_separable(self): + return self.child.is_separable() + + +class AffineBase(Transform): def __init__(self): Transform.__init__(self) self._inverted = None @@ -400,11 +419,173 @@ #@staticmethod def concat(a, b): - return Affine2D(Affine2D._concat(a.get_matrix(), b.get_matrix())) + return Affine1D(Affine1D._concat(a.get_matrix(), b.get_matrix())) concat = staticmethod(concat) + + def get_matrix(self): + raise NotImplementedError() + + def transform_without_affine(self, points): + # MGDTODO: Should we copy the points here? I'd like to avoid it, + # if possible + return points, self + +class Affine1DBase(AffineBase): + input_dims = 1 + output_dims = 1 + + def __init__(self): + AffineBase.__init__(self) + + def __array__(self, *args, **kwargs): + return self.get_matrix() + def to_values(self): mtx = self.get_matrix() + return tuple(mtx[0]) + + #@staticmethod + def matrix_from_values(a, b): + affine = npy.zeros((2, 2), npy.float_) + affine[0, :] = (a, b) + affine[1, 1] = 1 + return affine + matrix_from_values = staticmethod(matrix_from_values) + + def transform(self, values): + """ + Applies the transformation to an array of values and + returns the result. + """ + # MGDTODO: The major speed trap here is just converting to + # the points to an array in the first place. If we can use + # more arrays upstream, that should help here. +# if not isinstance(points, npy.ndarray): +# import traceback +# print '-' * 60 +# print 'A non-numpy array was passed in for transformation. Please ' +# print 'correct this.' +# print "".join(traceback.format_stack()) +# print points + mtx = self.get_matrix() + points = ma.asarray(values, npy.float_) + return points * mtx[0,0] + mtx[0,1] + + def is_separable(self): + return True + + def inverted(self): + if self._inverted is None: + mtx = self.get_matrix() + self._inverted = Affine1D(inv(mtx)) + return self._inverted + + +class Affine1D(Affine1DBase): + def __init__(self, matrix = None): + """ + Initialize an Affine transform from a 2x2 numpy float array. + + a b + 0 1 + """ + Affine1DBase.__init__(self) + if matrix is None: + matrix = npy.identity(2) + else: + matrix = npy.asarray(matrix, npy.float_) + assert matrix.shape == (2, 2) + self._mtx = matrix + + def __repr__(self): + return "Affine1D(%s)" % repr(self._mtx) + __str__ = __repr__ + + def __cmp__(self, other): + if (isinstance(other, Affine1D) and + (self.get_matrix() == other.get_matrix()).all()): + return 0 + return -1 + + #@staticmethod + def from_values(a, b): + return Affine1D(Affine1D.matrix_from_values(a, b)) + from_values = staticmethod(from_values) + + def get_matrix(self): + return self._mtx + + def set_matrix(self, mtx): + self._mtx = mtx + self.invalidate() + + def set(self, other): + self._mtx = other.get_matrix() + self.invalidate() + + #@staticmethod + def identity(): + return Affine1D(npy.identity(2)) + identity = staticmethod(identity) + + def clear(self): + self._mtx = npy.identity(2) + self.invalidate() + return self + + def translate(self, t): + self._mtx[0, 1] += t + self.invalidate() + return self + + def scale(self, s): + self._mtx[0, 0] *= s + self.invalidate() + return self + + def is_separable(self): + mtx = self.get_matrix() + return mtx[0, 1] == 0.0 and mtx[1, 0] == 0.0 + + +class IntervalTransform(Affine1DBase): + def __init__(self, bbox, direction): + Affine1DBase.__init__(self) + self._bbox = bbox + self._direction = direction + self.set_children(['_bbox']) + self._mtx = None + + def __repr__(self): + return "IntervalTransform(%s)" % (getattr(self._bbox, self._direction)) + __str__ = __repr__ + + def _do_invalidation(self): + print "IntervalTransform.invalidation", self._bbox + self._mtx = None + Affine1DBase._do_invalidation(self) + + def get_matrix(self): + if self._mtx is None: + min, max = getattr(self._bbox, self._direction) + self._mtx = inv(npy.array([[max - min, min], + [0.0, 1.0]], npy.float_)) + return self._mtx + + +class Affine2DBase(AffineBase): + input_dims = 2 + output_dims = 2 + + def __init__(self): + AffineBase.__init__(self) + + def __array__(self, *args, **kwargs): + return self.get_matrix() + + def to_values(self): + mtx = self.get_matrix() return tuple(mtx[:2].swapaxes(0, 1).flatten()) #@staticmethod @@ -416,9 +597,6 @@ return affine matrix_from_values = staticmethod(matrix_from_values) - def get_matrix(self): - raise NotImplementedError() - def transform(self, points): """ Applies the transformation to an array of 2D points and @@ -444,11 +622,6 @@ points = points + mtx[0:2, 2:] return points.transpose() - def transform_without_affine(self, points): - # MGDTODO: Should we copy the points here? I'd like to avoid it, - # if possible - return points, self - def inverted(self): if self._inverted is None: mtx = self.get_matrix() @@ -476,7 +649,6 @@ matrix = npy.asarray(matrix, npy.float_) assert matrix.shape == (3, 3) self._mtx = matrix - self._inverted = None def __repr__(self): return "Affine2D(%s)" % repr(self._mtx) @@ -545,12 +717,6 @@ self.invalidate() return self - def inverted(self): - if self._inverted is None: - mtx = self.get_matrix() - self._inverted = Affine2D(inv(mtx)) - return self._inverted - def is_separable(self): mtx = self.get_matrix() return mtx[0, 1] == 0.0 and mtx[1, 0] == 0.0 @@ -602,12 +768,10 @@ __str__ = __repr__ def transform(self, points): - # MGDTODO: Optimize the case where one of these is - # an affine x = self._x y = self._y if x == y and x.input_dims == 2: - return self._x(points) + return self._x.transform(points) if x.input_dims == 2: x_points = x.transform(points)[:, 0:1] @@ -623,13 +787,69 @@ return ma.concatenate((x_points, y_points), 1) + def transform_without_affine(self, points): + x = self._x + y = self._y + if x == y and x.input_dims == 2: + return self._x.transform_without_affine(points) + + if x.input_dims == 2: + x_points, x_affine = x.transform_without_affine(points) + x_points = x_points[:, 0:1] + else: + x_points, x_affine = x.transform_without_affine(points[:, 0]) + x_points = x_points.reshape((len(x_points), 1)) + + if y.input_dims == 2: + y_points, y_affine = y.transform_without_affine(points) + y_points = y_points[:, 1:] + else: + y_points, y_affine = y.transform_without_affine(points[:, 1]) + y_points = y_points.reshape((len(y_points), 1)) + + return ma.concatenate((x_points, y_points), 1), blended_transform_factory(x_affine, y_affine) + def inverted(self): return BlendedGenericTransform(self._x.inverted(), self._y.inverted()) def is_separable(self): return True + + +class BlendedAffine1D(Affine2DBase, Transform): + def __init__(self, x_transform, y_transform): + assert isinstance(x_transform, Affine1DBase) + assert isinstance(y_transform, Affine1DBase) + + Transform.__init__(self) + self._x = x_transform + self._y = y_transform + self.set_children(['_x', '_y']) + + Affine2DBase.__init__(self) + self._mtx = None + + def __repr__(self): + return "BlendedAffine1D(%s,%s)" % (self._x, self._y) + __str__ = __repr__ + + def _do_invalidation(self): + self._mtx = None + Affine2DBase._do_invalidation(self) + + def is_separable(self): + return True + + def get_matrix(self): + if self._mtx is None: + x_mtx = self._x.get_matrix() + y_mtx = self._y.get_matrix() + self._mtx = npy.array([[x_mtx[0, 0], 0.0, x_mtx[0, 1]], + [0.0, y_mtx[0, 0], y_mtx[0, 1]], + [0.0, 0.0, 1.0]]) + return self._mtx + - class BlendedAffine2D(Affine2DBase, Transform): def __init__(self, x_transform, y_transform): assert x_transform.is_affine() @@ -650,9 +870,8 @@ __str__ = __repr__ def _do_invalidation(self): - if self._mtx is not None: - self._mtx = None - Affine2DBase._do_invalidation(self) + self._mtx = None + Affine2DBase._do_invalidation(self) def is_separable(self): return True @@ -672,8 +891,10 @@ def blended_transform_factory(x_transform, y_transform): - if x_transform.is_affine() and y_transform.is_affine(): + if isinstance(x_transform, Affine2DBase) and isinstance(y_transform, Affine2DBase): return BlendedAffine2D(x_transform, y_transform) + elif isinstance(x_transform, Affine1DBase) and isinstance(y_transform, Affine1DBase): + return BlendedAffine1D(x_transform, y_transform) return BlendedGenericTransform(x_transform, y_transform) @@ -726,7 +947,7 @@ def _do_invalidation(self): self._mtx = None - return Affine2DBase._do_invalidation(self) + Affine2DBase._do_invalidation(self) def get_matrix(self): if self._mtx is None: @@ -754,8 +975,8 @@ class TestLogTransform(Transform): input_dims = 1 output_dims = 1 - def transform(self, xy): - marray = ma.masked_where(xy <= 0.0, xy * 10.0) + def transform(self, a): + marray = ma.masked_where(a <= 0.0, a * 10.0) return (npy.log10(marray) * 0.5) + 0.5 def inverted(self): @@ -768,8 +989,8 @@ class TestInvertLogTransform(Transform): input_dims = 1 output_dims = 1 - def transform(self, xy): - return ma.power(10, (xy - 0.5) * 2.0) / 10.0 + def transform(self, a): + return ma.power(10, (a - 0.5) * 2.0) / 10.0 def inverted(self): return TestLogTransform() @@ -782,18 +1003,31 @@ input_dims = 2 output_dims = 2 + def __init__(self, limits): + assert limits.is_bbox() + + Transform.__init__(self) + self._limits = limits + self.set_children(['_limits']) + def transform(self, xy): debug = len(xy) > 4 - x = xy[:, 0:1] - y = xy[:, 1:] - x, y = ((y * npy.cos(x)) + 1.0) * 0.5, ((y * npy.sin(x)) + 1.0) * 0.5 - if debug: - print npy.min(xy[:, 0:1]), npy.max(xy[:, 0:1]), npy.min(xy[:, 1:]), npy.max(xy[:, 1:]) - print x.min(), x.max(), y.min(), y.max() - return ma.concatenate((x, y), 1) + limmin, limmax = self._limits.intervaly + mask = (xy[:, 1:] < limmin) | (xy[:, 1:] > limmax) + mask = ma.concatenate((mask, mask), 1) + masked_xy = npy.ma.masked_where(mask, xy) + x = masked_xy[:, 0:1] + y = masked_xy[:, 1:2] + if x.shape == () or y.shape == (): + return masked_xy + y = (y - limmin) / (limmax - limmin) + x, y = y * ma.cos(x), y * ma.sin(x) + result = ma.concatenate((x, y), 1) + result = result * 0.5 + 0.5 + return result def inverted(self): - return TestInvertPolarTransform() + return TestInvertPolarTransform(self._limits) def is_separable(self): return False @@ -803,16 +1037,26 @@ input_dims = 2 output_dims = 2 + def __init__(self, limits): + assert limits.is_bbox() + + Transform.__init__(self) + self._limits = limits + self.set_children(['_limits']) + def transform(self, xy): + limmin, limmax = self._limits.intervaly + xy = (xy - 0.5) * 2.0 x = xy[:, 0:1] y = xy[:, 1:] r = ma.sqrt(ma.power(x, 2) + ma.power(y, 2)) theta = ma.arccos(x / r) theta = ma.where(y < 0, 2 * npy.pi - theta, theta) - return ma.concatenate((theta / (npy.pi * 2), r), 1) + r = r * (limmax - limmin) + limmin + return ma.concatenate((theta, r), 1) def inverted(self): - return TestInvertPolarTransform() + return TestInvertPolarTransform(self._limits) def is_separable(self): return False @@ -835,9 +1079,8 @@ __str__ = __repr__ def _do_invalidation(self): - if self._mtx is not None: - self._mtx = None - Affine2DBase._do_invalidation(self) + self._mtx = None + Affine2DBase._do_invalidation(self) def is_separable(self): return True This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ds...@us...> - 2007-09-24 15:12:15
|
Revision: 3883 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3883&view=rev Author: dsdale Date: 2007-09-24 08:11:58 -0700 (Mon, 24 Sep 2007) Log Message: ----------- fix bug in improved support for multiple windows in backend_qt4 Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py 2007-09-24 13:03:01 UTC (rev 3882) +++ trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py 2007-09-24 15:11:58 UTC (rev 3883) @@ -46,7 +46,7 @@ qApp = QtGui.QApplication( [" "] ) QtCore.QObject.connect( qApp, QtCore.SIGNAL( "lastWindowClosed()" ), qApp, QtCore.SLOT( "quit()" ) ) - else: + #remember that matplotlib created the qApp - will be used by show() _create_qApp.qAppCreatedHere = True _create_qApp.qAppCreatedHere = False This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ds...@us...> - 2007-09-24 13:03:06
|
Revision: 3882 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3882&view=rev Author: dsdale Date: 2007-09-24 06:03:01 -0700 (Mon, 24 Sep 2007) Log Message: ----------- modifed embedding_in_qt* examples so they can be run from ipython with -q*thread Modified Paths: -------------- trunk/matplotlib/examples/embedding_in_qt.py trunk/matplotlib/examples/embedding_in_qt4.py Modified: trunk/matplotlib/examples/embedding_in_qt.py =================================================================== --- trunk/matplotlib/examples/embedding_in_qt.py 2007-09-24 13:01:17 UTC (rev 3881) +++ trunk/matplotlib/examples/embedding_in_qt.py 2007-09-24 13:03:01 UTC (rev 3882) @@ -25,7 +25,7 @@ # Note: color-intensive applications may require a different color allocation # strategy. -QApplication.setColorSpec(QApplication.NormalColor) +#QApplication.setColorSpec(QApplication.NormalColor) app = QApplication(sys.argv) class MyMplCanvas(FigureCanvas): @@ -129,12 +129,8 @@ % {"prog": progname, "version": progversion}) -def main(): - aw = ApplicationWindow() - aw.setCaption("%s" % progname) - qApp.setMainWidget(aw) - aw.show() - sys.exit(qApp.exec_loop()) - - -if __name__ == "__main__": main() +aw = ApplicationWindow() +aw.setCaption("%s" % progname) +qApp.setMainWidget(aw) +aw.show() +sys.exit(qApp.exec_loop()) Modified: trunk/matplotlib/examples/embedding_in_qt4.py =================================================================== --- trunk/matplotlib/examples/embedding_in_qt4.py 2007-09-24 13:01:17 UTC (rev 3881) +++ trunk/matplotlib/examples/embedding_in_qt4.py 2007-09-24 13:03:01 UTC (rev 3882) @@ -122,17 +122,10 @@ % {"prog": progname, "version": progversion}) -def main(): - # Note: color-intensive applications may require a different color - # allocation strategy. - QtGui.QApplication.setColorSpec(QtGui.QApplication.NormalColor) - qApp = QtGui.QApplication(sys.argv) +qApp = QtGui.QApplication(sys.argv) - aw = ApplicationWindow() - aw.setWindowTitle("%s" % progname) - aw.show() -# sys.exit(qApp.exec_()) - qApp.exec_() - - -if __name__ == "__main__": main() +aw = ApplicationWindow() +aw.setWindowTitle("%s" % progname) +aw.show() +sys.exit(qApp.exec_()) +#qApp.exec_() This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ds...@us...> - 2007-09-24 13:01:19
|
Revision: 3881 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3881&view=rev Author: dsdale Date: 2007-09-24 06:01:17 -0700 (Mon, 24 Sep 2007) Log Message: ----------- fix backend_wxagg reference in new config module Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/config/mpltraits.py Modified: trunk/matplotlib/lib/matplotlib/config/mpltraits.py =================================================================== --- trunk/matplotlib/lib/matplotlib/config/mpltraits.py 2007-09-24 13:00:12 UTC (rev 3880) +++ trunk/matplotlib/lib/matplotlib/config/mpltraits.py 2007-09-24 13:01:17 UTC (rev 3881) @@ -29,7 +29,7 @@ 'gtkcairo': 'GTKCairo', 'qt4agg': 'Qt4Agg', 'qtagg': 'QtAgg', - 'wxagg': 'WxAgg', + 'wxagg': 'WXAgg', 'agg': 'Agg', 'cairo': 'Cairo', 'ps': 'PS', This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ds...@us...> - 2007-09-24 13:00:13
|
Revision: 3880 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3880&view=rev Author: dsdale Date: 2007-09-24 06:00:12 -0700 (Mon, 24 Sep 2007) Log Message: ----------- backend_qt* bugfix for multiple plot windows and show() Modified Paths: -------------- trunk/matplotlib/CHANGELOG Modified: trunk/matplotlib/CHANGELOG =================================================================== --- trunk/matplotlib/CHANGELOG 2007-09-24 12:56:38 UTC (rev 3879) +++ trunk/matplotlib/CHANGELOG 2007-09-24 13:00:12 UTC (rev 3880) @@ -1,3 +1,7 @@ +2007-09-24 Applied Eike Welk's patch reported on mpl-dev on 2007-09-22 + Fixes a bug with multiple plot windows in the qt backend, + ported the changes to backend_qt4 as well - DSD + 2007-09-21 Changed cbook.reversed to yield the same result as the python reversed builtin - DSD This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
From: <ds...@us...> - 2007-09-24 12:56:53
|
Revision: 3879 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3879&view=rev Author: dsdale Date: 2007-09-24 05:56:38 -0700 (Mon, 24 Sep 2007) Log Message: ----------- fix backend_qt* bug with multiple plot windows and show() Modified Paths: -------------- trunk/matplotlib/lib/matplotlib/backends/backend_qt.py trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qt.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_qt.py 2007-09-23 13:50:01 UTC (rev 3878) +++ trunk/matplotlib/lib/matplotlib/backends/backend_qt.py 2007-09-24 12:56:38 UTC (rev 3879) @@ -46,11 +46,11 @@ qApp = qt.QApplication( [" "] ) qt.QObject.connect( qApp, qt.SIGNAL( "lastWindowClosed()" ), qApp, qt.SLOT( "quit()" ) ) - else: - # someone else aready created the qApp and - # we let them handle the event-loop control. - show._needmain = False + #remember that matplotlib created the qApp - will be used by show() + _create_qApp.qAppCreatedHere = True +_create_qApp.qAppCreatedHere = False + def show(): """ Show all the figures and enter the qt main loop @@ -65,13 +65,10 @@ if figManager != None: figManager.canvas.draw() - if ( show._needmain ): - qt.qApp.exec_loop() - show._needmain = False + if _create_qApp.qAppCreatedHere: + qt.qApp.exec_loop() -show._needmain = True - def new_figure_manager( num, *args, **kwargs ): """ Create a new figure manager instance Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py =================================================================== --- trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py 2007-09-23 13:50:01 UTC (rev 3878) +++ trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py 2007-09-24 12:56:38 UTC (rev 3879) @@ -47,10 +47,10 @@ QtCore.QObject.connect( qApp, QtCore.SIGNAL( "lastWindowClosed()" ), qApp, QtCore.SLOT( "quit()" ) ) else: - # someone else aready created the qApp and - # we let them handle the event-loop control. - show._needmain = False + _create_qApp.qAppCreatedHere = True +_create_qApp.qAppCreatedHere = False + def show(): """ Show all the figures and enter the qt main loop @@ -65,13 +65,10 @@ if figManager != None: figManager.canvas.draw() - if ( show._needmain ): - qApp.exec_() - show._needmain = False + if _create_qApp.qAppCreatedHere: + QtGui.qApp.exec_() -show._needmain = True - def new_figure_manager( num, *args, **kwargs ): """ Create a new figure manager instance This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |