SourceForge logo
SourceForge logo
Menu

matplotlib-checkins — Commit notification. DO NOT POST to this list, just subscribe to it.

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

Showing results of 5455

<< < 1 .. 202 203 204 205 206 .. 219 > >> (Page 204 of 219)
From: <jr...@us...> - 2007年10月03日 23:05:32
Revision: 3911
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3911&view=rev
Author: jrevans
Date: 2007年10月03日 16:05:30 -0700 (2007年10月03日)
Log Message:
-----------
Removed an erroneous print statment in backend_qt.py.
Added a feature to keep track of axes inversions.
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/axes.py
 trunk/matplotlib/lib/matplotlib/backends/backend_qt.py
Modified: trunk/matplotlib/lib/matplotlib/axes.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/axes.py	2007年10月03日 22:23:48 UTC (rev 3910)
+++ trunk/matplotlib/lib/matplotlib/axes.py	2007年10月03日 23:05:30 UTC (rev 3911)
@@ -503,6 +503,9 @@
 self.set_label(label)
 self.set_figure(fig)
 
+ self._invertedx = False
+ self._invertedy = False
+
 # this call may differ for non-sep axes, eg polar
 self._init_axis()
 
@@ -1500,10 +1503,25 @@
 
 ### data limits, ticks, tick labels, and formatting
 
+ def invert_xaxis(self, invert=True):
+ "Invert the x-axis if 'invert' is True."
+ self._invertedx = invert
+
+ def xaxis_inverted(self):
+ 'Returns True if the x-axis is inverted.'
+ return self._invertedx
+
 def get_xlim(self):
- 'Get the x axis range [xmin, xmax]'
- return self.viewLim.intervalx().get_bounds()
+ """Get the x-axis range [xmin, xmax]
 
+ NOTE: The returned values are always [xmin, xmax] such that
+ xmin < xmax; regardless of whether or not the axes are inverted.
+ """
+ bound1, bound2 = self.viewLim.intervalx().get_bounds()
+ if ( self._invertedx ):
+ return bound2, bound1
+ else:
+ return bound1, bound2
 
 def set_xlim(self, xmin=None, xmax=None, emit=True, **kwargs):
 """
@@ -1542,12 +1560,25 @@
 if xmin is None: xmin = old_xmin
 if xmax is None: xmax = old_xmax
 
+ # provided for backwards compatability
+ if ( xmax < xmin ):
+ # swap the values so that xmin < xmax and set inverted flag
+ tmp = xmin
+ xmin = xmax
+ xmax = tmp
+ self.invert_xaxis( True )
+
 if (self.transData.get_funcx().get_type()==mtrans.LOG10
 and min(xmin, xmax)<=0):
 raise ValueError('Cannot set nonpositive limits with log transform')
 
- xmin, xmax = mtrans.nonsingular(xmin, xmax, increasing=False)
- self.viewLim.intervalx().set_bounds(xmin, xmax)
+ if ( self._invertedx ):
+ xmax, xmin = mtrans.nonsingular(xmax, xmin, increasing=False)
+ self.viewLim.intervalx().set_bounds(xmax, xmin)
+ else:
+ xmin, xmax = mtrans.nonsingular(xmin, xmax, increasing=False)
+ self.viewLim.intervalx().set_bounds(xmin, xmax)
+
 if emit: self.callbacks.process('xlim_changed', self)
 
 return xmin, xmax
@@ -1623,10 +1654,26 @@
 return self.xaxis.set_ticklabels(labels, fontdict, **kwargs)
 set_xticklabels.__doc__ = cbook.dedent(set_xticklabels.__doc__) % martist.kwdocd
 
+ def invert_yaxis(self, invert=True):
+ "Invert the y-axis if 'invert' is True."
+ self._invertedy = invert
+
+ def yaxis_inverted(self):
+ 'Returns True if the y-axis is inverted.'
+ return self._invertedy
+
 def get_ylim(self):
- 'Get the y axis range [ymin, ymax]'
- return self.viewLim.intervaly().get_bounds()
+ """Get the y-axis range [xmin, xmax]
 
+ NOTE: The returned values are always [ymin, ymax] such that
+ ymin < ymax; regardless of whether or not the axes are inverted.
+ """
+ bound1, bound2 = self.viewLim.intervaly().get_bounds()
+ if ( self._invertedy ):
+ return bound2, bound1
+ else:
+ return bound1, bound2
+
 def set_ylim(self, ymin=None, ymax=None, emit=True, **kwargs):
 """
 set_ylim(self, *args, **kwargs):
@@ -1649,7 +1696,6 @@
 ACCEPTS: len(2) sequence of floats
 """
 
-
 if ymax is None and iterable(ymin):
 ymin,ymax = ymin
 
@@ -1663,12 +1709,25 @@
 if ymin is None: ymin = old_ymin
 if ymax is None: ymax = old_ymax
 
+ # provided for backwards compatability
+ if ( ymax < ymin ):
+ # swap the values so that ymin < ymax and set inverted flag
+ tmp = ymin
+ ymin = ymax
+ ymax = tmp
+ self.invert_yaxis( True )
+
 if (self.transData.get_funcy().get_type()==mtrans.LOG10
 and min(ymin, ymax)<=0):
 raise ValueError('Cannot set nonpositive limits with log transform')
 
- ymin, ymax = mtrans.nonsingular(ymin, ymax, increasing=False)
- self.viewLim.intervaly().set_bounds(ymin, ymax)
+ if ( self._invertedy ):
+ ymax, ymin = mtrans.nonsingular(ymax, ymin, increasing=False)
+ self.viewLim.intervaly().set_bounds(ymax, ymin)
+ else:
+ ymin, ymax = mtrans.nonsingular(ymin, ymax, increasing=False)
+ self.viewLim.intervaly().set_bounds(ymin, ymax)
+
 if emit: self.callbacks.process('ylim_changed', self)
 
 return ymin, ymax
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qt.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_qt.py	2007年10月03日 22:23:48 UTC (rev 3910)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_qt.py	2007年10月03日 23:05:30 UTC (rev 3911)
@@ -135,7 +135,6 @@
 
 def resizeEvent( self, event ):
 if DEBUG: print 'resize (%d x %d)' % (event.size().width(), event.size().height())
- print "JRE--DBG: qt : resizeEvent"
 qt.QWidget.resizeEvent( self, event )
 w = event.size().width()
 h = event.size().height()
@@ -147,7 +146,6 @@
 self.draw()
 
 def resize( self, w, h ):
- print "JRE--DBG: qt : resize"
 # Pass through to Qt to resize the widget.
 qt.QWidget.resize( self, w, h )
 
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <jr...@us...> - 2007年10月03日 22:23:50
Revision: 3910
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3910&view=rev
Author: jrevans
Date: 2007年10月03日 15:23:48 -0700 (2007年10月03日)
Log Message:
-----------
Moved a couple of routines from the Agg version of the FigureCanvas to the base qt
version where they belong. Added a couple of overloaded qt methods that should be
there and reduce having to inherit when embedding in another QWidget.
Modified Paths:
--------------
 trunk/matplotlib/lib/matplotlib/backends/backend_qt.py
 trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py
 trunk/matplotlib/lib/matplotlib/backends/backend_qt4agg.py
 trunk/matplotlib/lib/matplotlib/backends/backend_qtagg.py
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qt.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_qt.py	2007年10月03日 12:51:16 UTC (rev 3909)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_qt.py	2007年10月03日 22:23:48 UTC (rev 3910)
@@ -135,11 +135,38 @@
 
 def resizeEvent( self, event ):
 if DEBUG: print 'resize (%d x %d)' % (event.size().width(), event.size().height())
+ print "JRE--DBG: qt : resizeEvent"
 qt.QWidget.resizeEvent( self, event )
+ w = event.size().width()
+ h = event.size().height()
+ if DEBUG: print "FigureCanvasQt.resizeEvent(", w, ",", h, ")"
+ dpival = self.figure.dpi.get()
+ winch = w/dpival
+ hinch = h/dpival
+ self.figure.set_size_inches( winch, hinch )
+ self.draw()
 
 def resize( self, w, h ):
+ print "JRE--DBG: qt : resize"
+ # Pass through to Qt to resize the widget.
 qt.QWidget.resize( self, w, h )
 
+ # Resize the figure by converting pixels to inches.
+ pixelPerInch = self.figure.dpi.get()
+ wInch = w / pixelPerInch
+ hInch = h / pixelPerInch
+ self.figure.set_size_inches( wInch, hInch )
+
+ # Redraw everything.
+ self.draw()
+
+ def sizeHint( self ):
+ w, h = self.get_width_height()
+ return qt.QSize( w, h )
+
+ def minumumSizeHint( self ):
+ return qt.QSize( 10, 10 )
+
 def _get_key( self, event ):
 if event.key() < 256:
 key = event.text().latin1()
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py	2007年10月03日 12:51:16 UTC (rev 3909)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_qt4.py	2007年10月03日 22:23:48 UTC (rev 3910)
@@ -135,10 +135,35 @@
 def resizeEvent( self, event ):
 if DEBUG: print 'resize (%d x %d)' % (event.size().width(), event.size().height())
 QtGui.QWidget.resizeEvent( self, event )
+ w = event.size().width()
+ h = event.size().height()
+ if DEBUG: print "FigureCanvasQtAgg.resizeEvent(", w, ",", h, ")"
+ dpival = self.figure.dpi.get()
+ winch = w/dpival
+ hinch = h/dpival
+ self.figure.set_size_inches( winch, hinch )
+ self.draw()
 
 def resize( self, w, h ):
+ # Pass through to Qt to resize the widget.
 QtGui.QWidget.resize( self, w, h )
 
+ # Resize the figure by converting pixels to inches.
+ pixelPerInch = self.figure.dpi.get()
+ wInch = w / pixelPerInch
+ hInch = h / pixelPerInch
+ self.figure.set_size_inches( wInch, hInch )
+
+ # Redraw everything.
+ self.draw()
+
+ def sizeHint( self ):
+ w, h = self.get_width_height()
+ return QtCore.QSize( w, h )
+
+ def minumumSizeHint( self ):
+ return QtCore.QSize( 10, 10 )
+
 def _get_key( self, event ):
 if event.key() < 256:
 key = str(event.text())
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qt4agg.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_qt4agg.py	2007年10月03日 12:51:16 UTC (rev 3909)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_qt4agg.py	2007年10月03日 22:23:48 UTC (rev 3910)
@@ -65,14 +65,6 @@
 
 def resizeEvent( self, e ):
 FigureCanvasQT.resizeEvent( self, e )
- w = e.size().width()
- h = e.size().height()
- if DEBUG: print "FigureCanvasQtAgg.resizeEvent(", w, ",", h, ")"
- dpival = self.figure.dpi.get()
- winch = w/dpival
- hinch = h/dpival
- self.figure.set_size_inches( winch, hinch )
- self.draw()
 
 def drawRectangle( self, rect ):
 self.rect = rect
Modified: trunk/matplotlib/lib/matplotlib/backends/backend_qtagg.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/backends/backend_qtagg.py	2007年10月03日 12:51:16 UTC (rev 3909)
+++ trunk/matplotlib/lib/matplotlib/backends/backend_qtagg.py	2007年10月03日 22:23:48 UTC (rev 3910)
@@ -64,14 +64,6 @@
 
 def resizeEvent( self, e ):
 FigureCanvasQT.resizeEvent( self, e )
- w = e.size().width()
- h = e.size().height()
- if DEBUG: print "FigureCanvasQtAgg.resizeEvent(", w, ",", h, ")"
- dpival = self.figure.dpi.get()
- winch = w/dpival
- hinch = h/dpival
- self.figure.set_size_inches( winch, hinch )
- self.draw()
 
 def drawRectangle( self, rect ):
 self.rect = rect
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年10月03日 12:51:20
Revision: 3909
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3909&view=rev
Author: mdboom
Date: 2007年10月03日 05:51:16 -0700 (2007年10月03日)
Log Message:
-----------
Merged revisions 3906-3908 via svnmerge from 
http://matplotlib.svn.sf.net/svnroot/matplotlib/trunk/matplotlib
........
 r3907 | efiring | 2007年10月02日 04:30:29 -0400 (2007年10月02日) | 2 lines
 
 matplotlib.use() raises an exception if called too late
........
Modified Paths:
--------------
 branches/transforms/CHANGELOG
 branches/transforms/lib/matplotlib/__init__.py
Property Changed:
----------------
 branches/transforms/
Property changes on: branches/transforms
___________________________________________________________________
Name: svnmerge-integrated
 - /trunk/matplotlib:1-3905
 + /trunk/matplotlib:1-3908
Modified: branches/transforms/CHANGELOG
===================================================================
--- branches/transforms/CHANGELOG	2007年10月03日 12:50:04 UTC (rev 3908)
+++ branches/transforms/CHANGELOG	2007年10月03日 12:51:16 UTC (rev 3909)
@@ -1,3 +1,6 @@
+2007年10月01日 Made matplotlib.use() raise an exception if called after
+ backends has been imported.
+
 2007年09月30日 Modified update* methods of Bbox and Interval so they
 work with reversed axes. Prior to this, trying to
 set the ticks on a reversed axis failed with an
Modified: branches/transforms/lib/matplotlib/__init__.py
===================================================================
--- branches/transforms/lib/matplotlib/__init__.py	2007年10月03日 12:50:04 UTC (rev 3908)
+++ branches/transforms/lib/matplotlib/__init__.py	2007年10月03日 12:51:16 UTC (rev 3909)
@@ -716,6 +716,9 @@
 except:
 from config import rcParams, rcdefaults
 
+_use_error_msg = """ matplotlib.use() must be called *before* pylab
+or matplotlib.backends is imported for the first time."""
+
 def use(arg):
 """
 Set the matplotlib backend to one of the known backends.
@@ -732,6 +735,8 @@
 for the first time; or, if you are not using pylab, it must
 be called before importing matplotlib.backends.
 """
+ if 'matplotlib.backends' in sys.modules:
+ raise RuntimeError(_use_error_msg)
 be_parts = arg.split('.')
 name = validate_backend(be_parts[0])
 rcParams['backend'] = name
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年10月03日 12:50:11
Revision: 3908
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3908&view=rev
Author: mdboom
Date: 2007年10月03日 05:50:04 -0700 (2007年10月03日)
Log Message:
-----------
Lots of progress on Polar transform refactoring. Added point_in_path algorithm.
Modified Paths:
--------------
 branches/transforms/lib/matplotlib/artist.py
 branches/transforms/lib/matplotlib/axes.py
 branches/transforms/lib/matplotlib/axis.py
 branches/transforms/lib/matplotlib/backend_bases.py
 branches/transforms/lib/matplotlib/cbook.py
 branches/transforms/lib/matplotlib/figure.py
 branches/transforms/lib/matplotlib/patches.py
 branches/transforms/lib/matplotlib/path.py
 branches/transforms/lib/matplotlib/scale.py
 branches/transforms/lib/matplotlib/text.py
 branches/transforms/lib/matplotlib/ticker.py
 branches/transforms/lib/matplotlib/transforms.py
 branches/transforms/setup.py
 branches/transforms/src/_backend_agg.cpp
 branches/transforms/src/_backend_agg.h
Added Paths:
-----------
 branches/transforms/lib/matplotlib/projections/
 branches/transforms/lib/matplotlib/projections/polar.py
Removed Paths:
-------------
 branches/transforms/lib/matplotlib/pbox.py
Modified: branches/transforms/lib/matplotlib/artist.py
===================================================================
--- branches/transforms/lib/matplotlib/artist.py	2007年10月02日 08:30:29 UTC (rev 3907)
+++ branches/transforms/lib/matplotlib/artist.py	2007年10月03日 12:50:04 UTC (rev 3908)
@@ -1,7 +1,8 @@
 from __future__ import division
 import sys, re
 from cbook import iterable, flatten
-from transforms import Affine2D
+from transforms import Affine2D, Bbox, IdentityTransform, TransformedBbox, \
+ TransformedPath
 import matplotlib.units as units
 
 ## Note, matplotlib artists use the doc strings for set and get
@@ -145,7 +146,7 @@
 def get_transform(self):
 'return the Transformation instance used by this artist'
 if self._transform is None:
- self._transform = Affine2D()
+ self._transform = IdentityTransform()
 return self._transform
 
 def hitlist(self,event):
@@ -284,17 +285,29 @@
 self._clipon = clipbox is not None or self._clippath is not None
 self.pchanged()
 
- def set_clip_path(self, path):
+ def set_clip_path(self, path, transform=None):
 """
 Set the artist's clip path
 
- ACCEPTS: an agg.path_storage instance
+ ACCEPTS: a Path instance and a Transform instance, or a Patch instance
 """
- self._clippath = path
+ from patches import Patch, Rectangle
+ if transform is None:
+ if isinstance(path, Rectangle):
+ self.clipbox = TransformedBbox(Bbox.unit(), path.get_transform())
+ elif isinstance(path, Patch):
+ self._clippath = TransformedPath(
+ path.get_path(),
+ path.get_transform())
+ elif path is None:
+ self._clippath = None
+ else:
+ raise TypeError("Invalid arguments to set_clip_path")
+ else:
+ self._clippath = TransformedPath(path, transform)
 self._clipon = self.clipbox is not None or path is not None
 self.pchanged()
 
-
 def get_alpha(self):
 """
 Return the alpha value used for blending - not supported on all
@@ -431,6 +444,7 @@
 self._alpha = other._alpha
 self.clipbox = other.clipbox
 self._clipon = other._clipon
+ self._clippath = other._clippath
 self._lod = other._lod
 self._label = other._label
 self.pchanged()
Modified: branches/transforms/lib/matplotlib/axes.py
===================================================================
--- branches/transforms/lib/matplotlib/axes.py	2007年10月02日 08:30:29 UTC (rev 3907)
+++ branches/transforms/lib/matplotlib/axes.py	2007年10月03日 12:50:04 UTC (rev 3908)
@@ -1,5 +1,5 @@
 from __future__ import division, generators
-import math, sys, warnings, copy
+import math, sys, warnings, copy, new
 
 import numpy as npy
 
@@ -24,7 +24,6 @@
 from matplotlib import cm
 from matplotlib import patches as mpatches
 from matplotlib import path as mpath
-from matplotlib import pbox as mpbox
 from matplotlib import quiver as mquiver
 from matplotlib import scale as mscale
 from matplotlib import table as mtable
@@ -428,15 +427,8 @@
 
 
 """
-
- # MGDTODO
-# scaled = {mtrans.IDENTITY : 'linear',
-# mtrans.LOG10 : 'log',
-# }
- scaled = {0 : 'linear',
- 1 : 'log',
- }
-
+ name = "rectilinear"
+ 
 _shared_x_axes = cbook.Grouper()
 _shared_y_axes = cbook.Grouper()
 
@@ -474,16 +466,16 @@
 visible: a boolean - whether the axes is visible
 xlabel: the xlabel
 xlim: (xmin, xmax) view limits
- xscale: ['log' | 'linear' ]
+ xscale: [%(scale)s]
 xticklabels: sequence of strings
 xticks: sequence of floats
 ylabel: the ylabel strings
 ylim: (ymin, ymax) view limits
- yscale: ['log' | 'linear']
+ yscale: [%(scale)s]
 yticklabels: sequence of strings
 yticks: sequence of floats
 
- """
+ """ % {'scale': ' | '.join([repr(x) for x in mscale.get_scale_names()])}
 martist.Artist.__init__(self)
 self._position = mtransforms.Bbox.from_lbwh(*rect)
 self._originalPosition = copy.deepcopy(self._position)
@@ -637,6 +629,10 @@
 # It is assumed that this part will have non-linear components
 self.transScale = mtransforms.TransformWrapper(mtransforms.IdentityTransform())
 
+ self._set_transData()
+
+ # MGDTODO: Rename this method
+ def _set_transData(self):
 # A (possibly non-linear) projection on the (already scaled) data
 self.transProjection = mtransforms.IdentityTransform()
 
@@ -647,7 +643,33 @@
 
 self.transData = self.transScale + self.transProjection + self.transLimits + self.transAxes
 
+ self._xaxis_transform = mtransforms.blended_transform_factory(
+ self.axes.transData, self.axes.transAxes)
+ self._yaxis_transform = mtransforms.blended_transform_factory(
+ self.axes.transAxes, self.axes.transData)
 
+ def get_xaxis_transform(self):
+ return self._xaxis_transform
+
+ def get_xaxis_text1_transform(self, pad_pixels):
+ return (self._xaxis_transform +
+ mtransforms.Affine2D().translate(0, -1 * pad_pixels))
+
+ def get_xaxis_text2_transform(self, pad_pixels):
+ return (self._xaxis_transform +
+ mtransforms.Affine2D().translate(0, pad_pixels))
+
+ def get_yaxis_transform(self):
+ return self._yaxis_transform
+
+ def get_yaxis_text1_transform(self, pad_pixels):
+ return (self._yaxis_transform +
+ mtransforms.Affine2D().translate(-1 * pad_pixels, 0))
+
+ def get_yaxis_text2_transform(self, pad_pixels):
+ return (self._yaxis_transform +
+ mtransforms.Affine2D().translate(pad_pixels, 0))
+ 
 def _update_transScale(self):
 self.transScale.set(
 mtransforms.blended_transform_factory(
@@ -691,6 +713,9 @@
 a.set_transform(self.transData)
 a.axes = self
 
+ def get_axes_patch(self):
+ return mpatches.Rectangle((0.0, 0.0), 1.0, 1.0)
+ 
 def cla(self):
 'Clear the current axes'
 
@@ -734,24 +759,26 @@
 self.title.set_clip_box(None)
 
 self._set_artist_props(self.title)
-
- self.axesPatch = mpatches.Rectangle(
- xy=(0,0), width=1, height=1,
- facecolor=self._axisbg,
- edgecolor=rcParams['axes.edgecolor'],
- )
+ 
+ self.axesPatch = self.get_axes_patch()
 self.axesPatch.set_figure(self.figure)
- self.axesPatch.set_transform(self.transAxes)
+ self.axesPatch.set_facecolor(self._axisbg)
+ self.axesPatch.set_edgecolor(rcParams['axes.edgecolor'])
 self.axesPatch.set_linewidth(rcParams['axes.linewidth'])
- # MGDTODO: What is axesFrame for? We already have axesPatch
- self.axesFrame = mlines.Line2D((0,1,1,0,0), (0,0,1,1,0),
- linewidth=rcParams['axes.linewidth'],
- color=rcParams['axes.edgecolor'],
- figure=self.figure)
+ self.axesPatch.set_transform(self.transAxes)
+
+ self.axesFrame = self.get_axes_patch()
+ self.axesFrame.set_figure(self.figure)
+ self.axesFrame.set_facecolor(None)
+ self.axesFrame.set_edgecolor(rcParams['axes.edgecolor'])
+ self.axesFrame.set_linewidth(rcParams['axes.linewidth'])
 self.axesFrame.set_transform(self.transAxes)
 self.axesFrame.set_zorder(2.5)
 self.axison = True
 
+ self.xaxis.set_clip_path(self.axesPatch)
+ self.yaxis.set_clip_path(self.axesPatch)
+
 def clear(self):
 'clear the axes'
 self.cla()
@@ -838,19 +865,23 @@
 """
 ACCEPTS: ['C', 'SW', 'S', 'SE', 'E', 'NE', 'N', 'NW', 'W']
 """
- if anchor in mpbox.PBox.coefs.keys() or len(anchor) == 2:
+ if anchor in mtransforms.Bbox.coefs.keys() or len(anchor) == 2:
 self._anchor = anchor
 else:
 raise ValueError('argument must be among %s' %
- ', '.join(PBox.coefs.keys()))
+ ', '.join(mtransforms.BBox.coefs.keys()))
 
-
- def apply_aspect(self, data_ratio = None):
+ def get_data_ratio(self):
+ xmin,xmax = self.get_xlim()
+ xsize = max(math.fabs(xmax-xmin), 1e-30)
+ ymin,ymax = self.get_ylim()
+ ysize = max(math.fabs(ymax-ymin), 1e-30)
+ return ysize/xsize
+ 
+ def apply_aspect(self):
 '''
 Use self._aspect and self._adjustable to modify the
 axes box or the view limits.
- The data_ratio kwarg is set to 1 for polar axes. It is
- used only when _adjustable is 'box'.
 '''
 
 if self._aspect == 'auto':
@@ -869,18 +900,11 @@
 
 figW,figH = self.get_figure().get_size_inches()
 fig_aspect = figH/figW
- #print 'figW, figH, fig_aspect', figW, figH, fig_aspect
- xmin,xmax = self.get_xlim()
- xsize = max(math.fabs(xmax-xmin), 1e-30)
- ymin,ymax = self.get_ylim()
- ysize = max(math.fabs(ymax-ymin), 1e-30)
 if self._adjustable == 'box':
- if data_ratio is None:
- data_ratio = ysize/xsize
- box_aspect = A * data_ratio
- pb = mpbox.PBox(self._originalPosition)
- pb1 = pb.shrink_to_aspect(box_aspect, fig_aspect)
- self.set_position(pb1.anchor(self._anchor), 'active')
+ box_aspect = A * self.get_data_ratio()
+ pb = self._originalPosition.frozen()
+ pb1 = pb.shrunk_to_aspect(box_aspect, pb, fig_aspect)
+ self.set_position(pb1.anchored(self._anchor, pb), 'active')
 return
 
 
@@ -1079,7 +1103,7 @@
 collection.set_label('collection%d'%len(self.collections))
 self.collections.append(collection)
 self._set_artist_props(collection)
- collection.set_clip_box(self.bbox)
+ collection.set_clip_path(self.axesPatch)
 if autolim:
 self.update_datalim(collection.get_verts(self.transData))
 collection._remove_method = lambda h: self.collections.remove(h)
@@ -1087,7 +1111,7 @@
 def add_line(self, line):
 'Add a line to the list of plot lines'
 self._set_artist_props(line)
- line.set_clip_box(self.bbox)
+ line.set_clip_path(self.axesPatch)
 
 self._update_line_limits(line)
 if not line.get_label():
@@ -1107,7 +1131,7 @@
 """
 
 self._set_artist_props(p)
- p.set_clip_box(self.bbox)
+ p.set_clip_path(self.axesPatch)
 self._update_patch_limits(p)
 self.patches.append(p)
 p._remove_method = lambda h: self.patches.remove(h)
@@ -1115,7 +1139,7 @@
 def _update_patch_limits(self, p):
 'update the datalimits for patch p'
 xys = self._get_verts_in_data_coords(
- p.get_transform(), p.get_verts())
+ p.get_transform(), p.get_path().vertices)
 self.update_datalim(xys)
 
 
@@ -1160,8 +1184,8 @@
 # display and then back to data to get it in data units
 #xys = trans.seq_xy_tups(xys)
 #return [ self.transData.inverse_xy_tup(xy) for xy in xys]
- xys = trans(npy.asarray(xys))
- return self.transData.inverted()(xys)
+ xys = trans.transform(npy.asarray(xys))
+ return self.transData.inverted().transform(xys)
 
 def _process_unit_info(self, xdata=None, ydata=None, kwargs=None):
 'look for unit kwargs and update the axis instances as necessary'
@@ -1189,9 +1213,9 @@
 #print '\tkw setting yunits', yunits
 self.yaxis.set_units(yunits)
 
- def in_axes(self, xwin, ywin):
+ def in_axes(self, mouseevent):
 'return True is the point xwin, ywin (display coords) are in the Axes'
- return self.bbox.contains(xwin, ywin)
+ return self.axesPatch.contains(mouseevent)[0]
 
 def get_autoscale_on(self):
 """
@@ -1207,7 +1231,6 @@
 """
 self._autoscaleon = b
 
-
 def autoscale_view(self, tight=False, scalex=True, scaley=True):
 """
 autoscale the view limits using the data limits. You can
@@ -1239,8 +1262,8 @@
 if yl[1] < yl[0]:
 YL = YL[::-1]
 self.set_ylim(YL)
- #### Drawing
 
+ #### Drawing
 def draw(self, renderer=None, inframe=False):
 "Draw everything (plot lines, axes, labels)"
 	if renderer is None:
@@ -1252,7 +1275,9 @@
 renderer.open_group('axes')
 self.apply_aspect()
 
- if self.axison and self._frameon: self.axesPatch.draw(renderer)
+ if self.axison and self._frameon:
+ self.axesPatch.draw(renderer)
+ 
 artists = []
 
 if len(self.images)<=1 or renderer.option_image_nocomposite():
@@ -1262,7 +1287,6 @@
 # make a composite image blending alpha
 # list of (mimage.Image, ox, oy)
 
-
 mag = renderer.get_image_magnification()
 ims = [(im.make_image(mag),0,0)
 for im in self.images if im.get_visible()]
@@ -1277,8 +1301,6 @@
 # respect z-order for now
 renderer.draw_image(l, b, im, self.bbox)
 
-
-
 artists.extend(self.collections)
 artists.extend(self.patches)
 artists.extend(self.lines)
@@ -1517,14 +1539,15 @@
 return xmin, xmax
 
 def get_xscale(self):
- 'return the xaxis scale string: log or linear'
+ 'return the xaxis scale string: %s' % (
+ ", ".join(mscale.get_scale_names()))
 	return self.xaxis.get_scale()
 
 def set_xscale(self, value, **kwargs):
 """
- SET_XSCALE(value, basex=10, subsx=None)
+ SET_XSCALE(value)
 
- Set the xscaling: 'log' or 'linear'
+ Set the xscaling: %(scale)s
 
 If value is 'log', the additional kwargs have the following meaning
 
@@ -1536,8 +1559,8 @@
 put minor ticks on 1,2,5,11,12,15,21, ....To turn off
 minor ticking, set subsx=[]
 
- ACCEPTS: ['log' | 'linear' ]
- """
+ ACCEPTS: [%(scale)s]
+ """ % {'scale': ' | '.join([repr(x) for x in mscale.get_scale_names()])}
 self.xaxis.set_scale(value, **kwargs)
 self._update_transScale()
 
@@ -1610,11 +1633,6 @@
 if ymin is None: ymin = old_ymin
 if ymax is None: ymax = old_ymax
 
-	# MGDTODO
-# if (self.transData.get_funcy().get_type()==mtrans.LOG10
-# and min(ymin, ymax)<=0):
-# raise ValueError('Cannot set nonpositive limits with log transform')
-
 ymin, ymax = mtransforms.nonsingular(ymin, ymax, increasing=False)
 	self.viewLim.intervaly = (ymin, ymax)
 if emit:
@@ -1627,14 +1645,15 @@
 return ymin, ymax
 
 def get_yscale(self):
- 'return the yaxis scale string: log or linear'
+ 'return the xaxis scale string: %s' % (
+ ", ".join(mscale.get_scale_names()))
 return self.yaxis.get_scale()
 
 def set_yscale(self, value, **kwargs):
 """
 SET_YSCALE(value, basey=10, subsy=None)
 
- Set the yscaling: 'log' or 'linear'
+ Set the yscaling: %(scale)s
 
 If value is 'log', the additional kwargs have the following meaning
 
@@ -1646,8 +1665,8 @@
 put minor ticks on 1,2,5,11,12,15, 21, ....To turn off
 minor ticking, set subsy=[]
 
- ACCEPTS: ['log' | 'linear']
- """
+ ACCEPTS: %(scale)s
+ """ % {'scale': ' | '.join([repr(x) for x in mscale.get_scale_names()])}
 self.yaxis.set_scale(value, **kwargs)
 self._update_transScale()
 
@@ -1682,14 +1701,6 @@
 return self.yaxis.set_ticklabels(labels, fontdict, **kwargs)
 set_yticklabels.__doc__ = cbook.dedent(set_yticklabels.__doc__) % martist.kwdocd
 
- def toggle_log_lineary(self):
- 'toggle between log and linear on the y axis'
-	# MGDTODO
-# funcy = self.transData.get_funcy().get_type()
-# if funcy==mtrans.LOG10: self.set_yscale('linear')
-# elif funcy==mtrans.IDENTITY: self.set_yscale('log')
-	pass
-
 def xaxis_date(self, tz=None):
 """Sets up x-axis ticks and labels that treat the x data as dates.
 
@@ -1748,12 +1759,12 @@
 
 def format_coord(self, x, y):
 'return a format string formatting the x, y coord'
-
+ if x is None or y is None:
+ return ''
 xs = self.format_xdata(x)
 ys = self.format_ydata(y)
 return 'x=%s, y=%s'%(xs,ys)
-
-
+ 
 #### Interactive manipulation
 
 def get_navigate(self):
@@ -1784,17 +1795,40 @@
 """
 self._navigate_mode = b
 
- def drag_pan(self, button, x, y, startx, starty, start_lim, start_trans):
+ def drag_pan(self, button, key, startx, starty, dx, dy,
+ start_lim, start_trans):
+ def format_deltas(key, dx, dy):
+ if key=='control':
+ if(abs(dx)>abs(dy)):
+ dy = dx
+ else:
+ dx = dy
+ elif key=='x':
+ dy = 0
+ elif key=='y':
+ dx = 0
+ elif key=='shift':
+ if 2*abs(dx) < abs(dy):
+ dx=0
+ elif 2*abs(dy) < abs(dx):
+ dy=0
+ elif(abs(dx)>abs(dy)):
+ dy=dy/abs(dy)*abs(dx)
+ else:
+ dx=dx/abs(dx)*abs(dy)
+ return (dx,dy)
+
 if button == 1:
 inverse = start_trans.inverted()
- dx = startx - x
- dy = starty - y
- result = self.bbox.frozen().translated(dx, dy).transformed(inverse)
+ dx, dy = format_deltas(key, dx, dy)
+ result = self.bbox.frozen().translated(-dx, -dy).transformed(inverse)
 elif button == 3:
 try:
+ # MGDTODO: This is broken with log scales
 inverse = start_trans.inverted()
- dx = (startx - x) / float(self.bbox.width)
- dy = (starty - y) / float(self.bbox.height)
+ dx, dy = format_deltas(key, dx, dy)
+ dx = -dx / float(self.bbox.width)
+ dy = -dy / float(self.bbox.height)
 xmin, ymin, xmax, ymax = start_lim.lbrt
 
 alpha = npy.power(10.0, (dx, dy))
@@ -1806,7 +1840,6 @@
 warnings.warn('Overflow while panning')
 return
 
- # MGDTODO: Could we do this with a single set_lim?
 self.set_xlim(*result.intervalx)
 self.set_ylim(*result.intervaly)
 
@@ -1880,7 +1913,7 @@
 """
 if callable(self._contains): return self._contains(self,mouseevent)
 
- inside = self.bbox.contains(mouseevent.x,mouseevent.y)
+ inside = self.axesPatch.contains(mouseevent.x, mouseevent.y)
 return inside,{}
 
 def pick(self,*args):
@@ -2100,7 +2133,7 @@
 
 
 #if t.get_clip_on(): t.set_clip_box(self.bbox)
- if kwargs.has_key('clip_on'): t.set_clip_box(self.bbox)
+ if kwargs.has_key('clip_on'): t.set_clip_path(self.axesPatch)
 return t
 text.__doc__ = cbook.dedent(text.__doc__) % martist.kwdocd
 
@@ -2118,7 +2151,7 @@
 a = mtext.Annotation(*args, **kwargs)
 a.set_transform(mtransforms.Affine2D())
 self._set_artist_props(a)
- if kwargs.has_key('clip_on'): a.set_clip_box(self.bbox)
+ if kwargs.has_key('clip_on'): a.set_clip_path(self.axesPatch)
 self.texts.append(a)
 return a
 annotate.__doc__ = cbook.dedent(annotate.__doc__) % martist.kwdocd
@@ -5056,7 +5089,7 @@
 Subplot(211) # 2 rows, 1 column, first (upper) plot
 """
 
- def __init__(self, fig, *args):
+ def __init__(self, fig, *args, **kwargs):
 """
 fig is a figure instance
 
@@ -5087,6 +5120,10 @@
 
 self.update_params()
 
+ # _axes_class is set in the subplot_class_factory
+ self._axes_class.__init__(self, fig, [self.figLeft, self.figBottom,
+ self.figW, self.figH], **kwargs)
+ 
 def get_geometry(self):
 'get the subplot geometry, eg 2,2,3'
 return self._rows, self._cols, self._num+1
@@ -5176,36 +5213,18 @@
 for label in self.get_yticklabels():
 label.set_visible(firstcol)
 
-class Subplot(SubplotBase, Axes):
- """
- Emulate matlab's(TM) subplot command, creating axes with
+def subplot_class_factory(axes_class=None):
+ # MGDTODO: This is a little bit strange to make a new class on the
+ # fly like this, but it keeps things relatively similar to how they
+ # were before
+ new_class = new.classobj("%sSubplot" % (axes_class.__name__),
+ (SubplotBase, axes_class),
+ {'_axes_class': axes_class})
+ return new_class
 
- Subplot(numRows, numCols, plotNum)
 
- where plotNum=1 is the first plot number and increasing plotNums
- fill rows first. max(plotNum)==numRows*numCols
-
- You can leave out the commas if numRows<=numCols<=plotNum<10, as
- in
-
- Subplot(211) # 2 rows, 1 column, first (upper) plot
- """
- def __str__(self):
- return "Subplot(%f,%f,%f,%f)" % (self.bbox.bounds)
-
- def __init__(self, fig, *args, **kwargs):
- """
- See Axes base class documentation for args and kwargs
- """
- SubplotBase.__init__(self, fig, *args)
- Axes.__init__(self, fig, [self.figLeft, self.figBottom,
- self.figW, self.figH], **kwargs)
-
-
-
 class PolarAxes(Axes):
 """
-
 Make a PolarAxes. The rectangular bounding box of the axes is given by
 
 
@@ -5644,11 +5663,6 @@
 'return the yaxis scale string'
 return 'polar'
 
- def toggle_log_lineary(self):
- 'toggle between log and linear axes ignored for polar'
- pass
-
-
 def table(self, *args, **kwargs):
 """
 TABLE(*args, **kwargs)
@@ -5679,255 +5693,9 @@
 PolarAxes.__init__(
 self, fig,
 [self.figLeft, self.figBottom, self.figW, self.figH], **kwargs)
-
-######################################################################
-# New Polar Axes
 
-class PolarAxes(Axes):
- class PolarTransform(mtransforms.Transform):
- input_dims = 2
- output_dims = 2
- is_separable = False
-
- def transform(self, tr):
- xy = npy.zeros(tr.shape, npy.float_)
- t = tr[:, 0:1]
- r = tr[:, 1:2]
- x = xy[:, 0:1]
- y = xy[:, 1:2]
- x += r * npy.cos(t)
- y += r * npy.sin(t)
- return xy
- transform_non_affine = transform
-
- def interpolate(self, a, steps):
- steps = npy.floor(steps)
- new_length = ((len(a) - 1) * steps) + 1
- new_shape = list(a.shape)
- new_shape[0] = new_length
- result = npy.zeros(new_shape, a.dtype)
-
- result[0] = a[0]
- a0 = a[0:-1]
- a1 = a[1: ]
- delta = ((a1 - a0) / steps)
- 
- for i in range(1, int(steps)+1):
- result[i::steps] = delta * i + a0
-
- return result
- 
-# def transform_path(self, path):
-# twopi = 2.0 * npy.pi
-# halfpi = 0.5 * npy.pi
- 
-# vertices = path.vertices
-# t0 = vertices[0:-1, 0]
-# t1 = vertices[1: , 0]
-# td = npy.where(t1 > t0, t1 - t0, twopi - (t0 - t1))
-# maxtd = td.max()
-# interpolate = npy.ceil(maxtd / halfpi)
-# if interpolate > 1.0:
-# vertices = self.interpolate(vertices, interpolate)
-
-# vertices = self.transform(vertices)
-
-# result = npy.zeros((len(vertices) * 3 - 2, 2), npy.float_)
-# codes = mpath.Path.CURVE4 * npy.ones((len(vertices) * 3 - 2, ), mpath.Path.code_type)
-# result[0] = vertices[0]
-# codes[0] = mpath.Path.MOVETO
-
-# kappa = 4.0 * ((npy.sqrt(2.0) - 1.0) / 3.0)
-# kappa = 0.5
- 
-# p0 = vertices[0:-1]
-# p1 = vertices[1: ]
-
-# x0 = p0[:, 0:1]
-# y0 = p0[:, 1: ]
-# b0 = ((y0 - x0) - y0) / ((x0 + y0) - x0)
-# a0 = y0 - b0*x0
-
-# x1 = p1[:, 0:1]
-# y1 = p1[:, 1: ]
-# b1 = ((y1 - x1) - y1) / ((x1 + y1) - x1)
-# a1 = y1 - b1*x1
-
-# x = -(a0-a1) / (b0-b1)
-# y = a0 + b0*x
-
-# xk = (x - x0) * kappa + x0
-# yk = (y - y0) * kappa + y0
-
-# result[1::3, 0:1] = xk
-# result[1::3, 1: ] = yk
-
-# xk = (x - x1) * kappa + x1
-# yk = (y - y1) * kappa + y1
-
-# result[2::3, 0:1] = xk
-# result[2::3, 1: ] = yk
- 
-# result[3::3] = p1
-
-# print vertices[-2:]
-# print result[-2:]
- 
-# return mpath.Path(result, codes)
- 
-# twopi = 2.0 * npy.pi
-# halfpi = 0.5 * npy.pi
- 
-# vertices = path.vertices
-# t0 = vertices[0:-1, 0]
-# t1 = vertices[1: , 0]
-# td = npy.where(t1 > t0, t1 - t0, twopi - (t0 - t1))
-# maxtd = td.max()
-# interpolate = npy.ceil(maxtd / halfpi)
-
-# print "interpolate", interpolate
-# if interpolate > 1.0:
-# vertices = self.interpolate(vertices, interpolate)
- 
-# result = npy.zeros((len(vertices) * 3 - 2, 2), npy.float_)
-# codes = mpath.Path.CURVE4 * npy.ones((len(vertices) * 3 - 2, ), mpath.Path.code_type)
-# result[0] = vertices[0]
-# codes[0] = mpath.Path.MOVETO
-
-# kappa = 4.0 * ((npy.sqrt(2.0) - 1.0) / 3.0)
-# tkappa = npy.arctan(kappa)
-# hyp_kappa = npy.sqrt(kappa*kappa + 1.0)
-
-# t0 = vertices[0:-1, 0]
-# t1 = vertices[1: , 0]
-# r0 = vertices[0:-1, 1]
-# r1 = vertices[1: , 1]
-
-# td = npy.where(t1 > t0, t1 - t0, twopi - (t0 - t1))
-# td_scaled = td / (npy.pi * 0.5)
-# rd = r1 - r0
-# r0kappa = r0 * kappa * td_scaled
-# r1kappa = r1 * kappa * td_scaled
-# ravg_kappa = ((r1 + r0) / 2.0) * kappa * td_scaled
-
-# result[1::3, 0] = t0 + (tkappa * td_scaled)
-# result[1::3, 1] = r0*hyp_kappa
-# # result[1::3, 1] = r0 / npy.cos(tkappa * td_scaled) # npy.sqrt(r0*r0 + ravg_kappa*ravg_kappa)
-
-# result[2::3, 0] = t1 - (tkappa * td_scaled)
-# result[2::3, 1] = r1*hyp_kappa
-# # result[2::3, 1] = r1 / npy.cos(tkappa * td_scaled) # npy.sqrt(r1*r1 + ravg_kappa*ravg_kappa)
- 
-# result[3::3, 0] = t1
-# result[3::3, 1] = r1
-
-# print vertices[:6], result[:6], t0[:6], t1[:6], td[:6], td_scaled[:6], tkappa
-# result = self.transform(result)
-# return mpath.Path(result, codes)
-# transform_path_non_affine = transform_path
-
- def inverted(self):
- return PolarAxes.InvertedPolarTransform()
-
- class PolarAffine(mtransforms.Affine2DBase):
- def __init__(self, limits):
- mtransforms.Affine2DBase.__init__(self)
- self._limits = limits
- self.set_children(limits)
- self._mtx = None
-
- def get_matrix(self):
- if self._invalid:
- xmin, ymin, xmax, ymax = self._limits.lbrt
- affine = mtransforms.Affine2D().rotate(xmin).scale(0.5 / ymax).translate(0.5, 0.5)
- self._mtx = affine.get_matrix()
- self._inverted = None
- self._invalid = 0
- return self._mtx
- 
- class InvertedPolarTransform(mtransforms.Transform):
- input_dims = 2
- output_dims = 2
- is_separable = False
-
- def transform(self, xy):
- x = xy[:, 0:1]
- y = xy[:, 1:]
- r = npy.sqrt(x*x + y*y)
- theta = npy.arccos(x / r)
- theta = npy.where(y < 0, 2 * npy.pi - theta, theta)
- return npy.concatenate((theta, r), 1)
-
- def inverted(self):
- return PolarAxes.PolarTransform()
- 
- def _set_lim_and_transforms(self):
- """
- set the dataLim and viewLim BBox attributes and the
- transData and transAxes Transformation attributes
- """
-	self.dataLim = mtransforms.Bbox.unit()
- self.viewLim = mtransforms.Bbox.unit()
- self.transAxes = mtransforms.BboxTransform(
- mtransforms.Bbox.unit(), self.bbox)
-
- # 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 = self.PolarTransform()
-
- # An affine transformation on the data, generally to limit the
- # range of the axes
- self.transProjectionAffine = self.PolarAffine(self.viewLim)
- 
- self.transData = self.transScale + self.transProjection + \
- self.transProjectionAffine + self.transAxes
-
- def drag_pan(self, button, x, y, startx, starty, start_lim, start_trans):
- if button == 1:
- inverse = start_trans.inverted()
- startt, startr = inverse.transform_point((startx, starty))
- t, r = inverse.transform_point((x, y))
-
- scale = r / startr
- self.set_ylim(start_lim.ymin, start_lim.ymax / scale)
-
- dt0 = t - startt
- dt1 = startt - t
- if abs(dt1) < abs(dt0):
- dt = abs(dt1) * sign(dt0) * -1.0
- else:
- dt = dt0 * -1.0
- self.set_xlim(start_lim.xmin - dt, start_lim.xmin - dt + npy.pi*2.0)
- 
- def set_rmax(self, rmax):
- self.viewLim.maxy = rmax
- 
-class PolarSubplot(SubplotBase, PolarAxes):
- """
- Create a polar subplot with
-
- PolarSubplot(numRows, numCols, plotNum)
-
- where plotNum=1 is the first plot number and increasing plotNums
- fill rows first. max(plotNum)==numRows*numCols
-
- You can leave out the commas if numRows<=numCols<=plotNum<10, as
- in
-
- Subplot(211) # 2 rows, 1 column, first (upper) plot
- """
- def __str__(self):
- return "PolarSubplot(%gx%g)"%(self.figW,self.figH)
- def __init__(self, fig, *args, **kwargs):
- SubplotBase.__init__(self, fig, *args)
- PolarAxes.__init__(
- self, fig,
- [self.figLeft, self.figBottom, self.figW, self.figH], **kwargs)
- 
 martist.kwdocd['Axes'] = martist.kwdocd['Subplot'] = martist.kwdoc(Axes)
+
 """
 # this is some discarded code I was using to find the minimum positive
 # data point for some log scaling fixes. I realized there was a
Modified: branches/transforms/lib/matplotlib/axis.py
===================================================================
--- branches/transforms/lib/matplotlib/axis.py	2007年10月02日 08:30:29 UTC (rev 3907)
+++ branches/transforms/lib/matplotlib/axis.py	2007年10月03日 12:50:04 UTC (rev 3908)
@@ -18,12 +18,11 @@
 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, IntervalTransform
+ interval_contains_open, IntervalTransform, IdentityTransform
 from patches import bbox_artist
 from scale import scale_factory
 
 import matplotlib.units as units
-#import pdb
 
 
 class Tick(Artist):
@@ -112,6 +111,12 @@
 children = [self.tick1line, self.tick2line, self.gridline, self.label1, self.label2]
 return children
 
+ def set_clip_path(self, clippath, transform=None):
+ Artist.set_clip_path(self, clippath, transform)
+ self.tick1line.set_clip_path(clippath, transform)
+ self.tick2line.set_clip_path(clippath, transform)
+ self.gridline.set_clip_path(clippath, transform)
+ 
 def contains(self, mouseevent):
 """Test whether the mouse event occured in the Tick marks.
 
@@ -164,9 +169,12 @@
 midPoint = interval_contains_open(self.get_view_interval(), self.get_loc() )
 
 if midPoint:
- if self.gridOn: self.gridline.draw(renderer)
- if self.tick1On: self.tick1line.draw(renderer)
- if self.tick2On: self.tick2line.draw(renderer)
+ if self.gridOn:
+ self.gridline.draw(renderer)
+ if self.tick1On:
+ self.tick1line.draw(renderer)
+ if self.tick2On:
+ self.tick2line.draw(renderer)
 
 if self.label1On: self.label1.draw(renderer)
 if self.label2On: self.label2.draw(renderer)
@@ -213,8 +221,10 @@
 'return the view Interval instance for the axis tjis tick is ticking'
 raise NotImplementedError('Derived must override')
 
+ def set_view_interval(self, vmin, vmax, ignore=False):
+ raise NotImplementedError('Derived must override')
 
-
+ 
 class XTick(Tick):
 """
 Contains all the Artists needed to make an x tick - the tick line,
@@ -237,12 +247,7 @@
 xaxis=True,
 )
 
-	trans = blended_transform_factory(
-	 self.axes.transData, self.axes.transAxes)
- #offset the text downward with a post transformation
-	trans = trans + Affine2D().translate(0, -1 * self._padPixels)
- t.set_transform(trans)
-
+ t.set_transform(self.axes.get_xaxis_text1_transform(self._padPixels))
 self._set_artist_props(t)
 return t
 
@@ -262,11 +267,7 @@
 horizontalalignment='center',
 )
 
-	trans = blended_transform_factory(
-	 self.axes.transData, self.axes.transAxes)
- # offset the text upward with a post transformation
- trans = trans + Affine2D().translate(0, self._padPixels)
- t.set_transform( trans )
+ t.set_transform(self.axes.get_xaxis_text2_transform(self._padPixels))
 self._set_artist_props(t)
 return t
 
@@ -280,8 +281,7 @@
 marker = self._xtickmarkers[0],
 markersize=self._size,
 )
- l.set_transform(blended_transform_factory(
-		self.axes.transData, self.axes.transAxes) )
+ l.set_transform(self.axes.get_xaxis_transform())
 self._set_artist_props(l)
 return l
 
@@ -296,24 +296,20 @@
 markersize=self._size,
 )
 
- l.set_transform(blended_transform_factory(
-		self.axes.transData, self.axes.transAxes) )
+ l.set_transform(self.axes.get_xaxis_transform())
 self._set_artist_props(l)
 return l
 
 def _get_gridline(self, loc):
 'Get the default line2D instance'
 # x in data coords, y in axes coords
- l = Line2D( xdata=(loc, loc), ydata=(0, 1),
- color=rcParams['grid.color'],
- linestyle=rcParams['grid.linestyle'],
- linewidth=rcParams['grid.linewidth'],
- antialiased=False,
- )
- l.set_transform(
-	 blended_transform_factory(
-		self.axes.transData, self.axes.transAxes))
- l.set_clip_box(self.axes.bbox)
+ l = Line2D(xdata=(loc, loc), ydata=(0, 1.0),
+ color=rcParams['grid.color'],
+ linestyle=rcParams['grid.linestyle'],
+ linewidth=rcParams['grid.linewidth'],
+ antialiased=False,
+ )
+ l.set_transform(self.axes.get_xaxis_transform())
 self._set_artist_props(l)
 
 return l
@@ -322,7 +318,6 @@
 'Set the location of tick in data coords with scalar loc'
 x = loc
 
-
 self.tick1line.set_xdata((x,))
 self.tick2line.set_xdata((x,))
 self.gridline.set_xdata((x, ))
@@ -334,6 +329,13 @@
 'return the Interval instance for this axis view limits'
 return self.axes.viewLim.intervalx
 
+ def set_view_interval(self, vmin, vmax, ignore = False):
+ if ignore:
+ self.axes.viewLim.intervalx = vmin, vmax
+ else:
+ Vmin, Vmax = self.get_view_interval()
+ self.axes.viewLim.intervalx = min(vmin, Vmin), max(vmax, Vmax)
+ 
 def get_minpos(self):
 return self.axes.dataLim.minposx
 
@@ -363,12 +365,7 @@
 dashdirection=0,
 xaxis=False,
 )
- trans = blended_transform_factory(
-	 self.axes.transAxes, self.axes.transData)
- # offset the text leftward with a post transformation
-	trans = trans + Affine2D().translate(-1 * self._padPixels, 0)
-
- t.set_transform( trans )
+ t.set_transform(self.axes.get_yaxis_text1_transform(self._padPixels))
 #t.set_transform( self.axes.transData )
 self._set_artist_props(t)
 return t
@@ -386,11 +383,7 @@
 xaxis=False,
 horizontalalignment='left',
 )
- trans = blended_transform_factory(
-	 self.axes.transAxes, self.axes.transData)
- # offset the text rightward with a post transformation
-	trans = trans + Affine2D().translate(self._padPixels, 0)
- t.set_transform( trans )
+ t.set_transform(self.axes.get_yaxis_text2_transform(self._padPixels))
 self._set_artist_props(t)
 return t
 
@@ -404,9 +397,7 @@
 linestyle = 'None',
 markersize=self._size,
 )
- l.set_transform(
-	 blended_transform_factory(
-		self.axes.transAxes, self.axes.transData))
+ l.set_transform(self.axes.get_yaxis_transform())
 self._set_artist_props(l)
 return l
 
@@ -420,9 +411,7 @@
 markersize=self._size,
 )
 
- l.set_transform(
-	 blended_transform_factory(
-		self.axes.transAxes, self.axes.transData))
+ l.set_transform(self.axes.get_yaxis_transform())
 self._set_artist_props(l)
 return l
 
@@ -436,10 +425,7 @@
 antialiased=False,
 )
 
- l.set_transform( blended_transform_factory(
-		self.axes.transAxes, self.axes.transData) )
- l.set_clip_box(self.axes.bbox)
-
+ l.set_transform(self.axes.get_yaxis_transform())
 self._set_artist_props(l)
 return l
 
@@ -461,6 +447,13 @@
 'return the Interval instance for this axis view limits'
 return self.axes.viewLim.intervaly
 
+ def set_view_interval(self, vmin, vmax):
+ if ignore:
+ self.axes.viewLim.intervaly = vmin, vmax
+ else:
+ Vmin, Vmax = self.get_view_interval()
+ self.axes.viewLim.intervaly = min(vmin, Vmin), max(vmax, Vmax)
+ 
 def get_minpos(self):
 return self.axes.dataLim.minposy
 
@@ -530,8 +523,8 @@
 
 def get_children(self):
 children = [self.label]
- majorticks = self.get_major_ticks()
- minorticks = self.get_minor_ticks() 
+ majorticks = self.get_major_ticks(len(self.major.locator()))
+ minorticks = self.get_minor_ticks(len(self.minor.locator())) 
 
 children.extend(majorticks)
 children.extend(minorticks)
@@ -565,11 +558,20 @@
 self.units = None
 self.set_units(None)
 
-
+ def set_clip_path(self, clippath, transform=None):
+ Artist.set_clip_path(self, clippath, transform)
+ majorticks = self.get_major_ticks(len(self.major.locator()))
+ minorticks = self.get_minor_ticks(len(self.minor.locator())) 
+ for child in self.majorTicks + self.minorTicks:
+ child.set_clip_path(clippath, transform)
+ 
 def get_view_interval(self):
 'return the Interval instance for this axis view limits'
 raise NotImplementedError('Derived must override')
 
+ def set_view_interval(self, vmin, vmax, ignore=False):
+ raise NotImplementedError('Derived must override')
+ 
 def get_data_interval(self):
 'return the Interval instance for this axis data limits'
 raise NotImplementedError('Derived must override')
@@ -585,8 +587,8 @@
 ticklabelBoxes = []
 ticklabelBoxes2 = []
 
- majorTicks = self.get_major_ticks()
 majorLocs = self.major.locator()
+ majorTicks = self.get_major_ticks(len(majorLocs))
 self.major.formatter.set_locs(majorLocs)
 majorLabels = [self.major.formatter(val, i) for i, val in enumerate(majorLocs)]
 
@@ -609,8 +611,8 @@
 extent = tick.label2.get_window_extent(renderer)
 ticklabelBoxes2.append(extent)
 
- minorTicks = self.get_minor_ticks()
 minorLocs = self.minor.locator()
+ minorTicks = self.get_minor_ticks(len(minorLocs))
 self.minor.formatter.set_locs(minorLocs)
 minorLabels = [self.minor.formatter(val, i) for i, val in enumerate(minorLocs)]
 
@@ -727,11 +729,9 @@
 'Get the formatter of the minor ticker'
 return self.minor.formatter
 
- def get_major_ticks(self):
+ def get_major_ticks(self, numticks):
 'get the tick instances; grow as necessary'
 
- numticks = len(self.major.locator())
-
 if len(self.majorTicks)<numticks:
 # update the new tick label properties from the old
 protoTick = self.majorTicks[0]
@@ -746,9 +746,8 @@
 return ticks
 
 
- def get_minor_ticks(self):
+ def get_minor_ticks(self, numticks):
 'get the minor tick instances; grow as necessary'
- numticks = len(self.minor.locator())
 if len(self.minorTicks)<numticks:
 protoTick = self.minorTicks[0]
 for i in range(numticks-len(self.minorTicks)):
@@ -949,8 +948,9 @@
 ### XXX if the user changes units, the information will be lost here
 ticks = self.convert_units(ticks)
 self.set_major_locator( FixedLocator(ticks) )
- self.get_view_interval().update(ticks,0)
- return self.get_major_ticks()
+ if len(ticks):
+ self.set_view_interval(min(ticks), max(ticks))
+ return self.get_major_ticks(len(ticks))
 
 def _update_label_position(self, bboxes, bboxes2):
 """
@@ -1153,6 +1153,13 @@
 'return the Interval instance for this axis view limits'
 return self.axes.viewLim.intervalx
 
+ def set_view_interval(self, vmin, vmax, ignore=False):
+ if ignore:
+ self.axes.viewLim.intervalx = vmin, vmax
+ else:
+ Vmin, Vmax = self.get_view_interval()
+ self.axes.viewLim.intervalx = min(vmin, Vmin), max(vmax, Vmax)
+ 
 def get_minpos(self):
 return self.axes.dataLim.minposx
 
@@ -1357,6 +1364,13 @@
 'return the Interval instance for this axis view limits'
 return self.axes.viewLim.intervaly
 
+ def set_view_interval(self, vmin, vmax, ignore=False):
+ if ignore:
+ self.axes.viewLim.intervaly = vmin, vmax
+ else:
+ Vmin, Vmax = self.get_view_interval()
+ self.axes.viewLim.intervaly = min(vmin, Vmin), max(vmax, Vmax)
+ 
 def get_minpos(self):
 return self.axes.dataLim.minposy
 
Modified: branches/transforms/lib/matplotlib/backend_bases.py
===================================================================
--- branches/transforms/lib/matplotlib/backend_bases.py	2007年10月02日 08:30:29 UTC (rev 3907)
+++ branches/transforms/lib/matplotlib/backend_bases.py	2007年10月03日 12:50:04 UTC (rev 3908)
@@ -537,7 +537,9 @@
 """
 Return the clip path
 """
- return self._clippath
+ if self._clippath is not None:
+ return self._clippath.get_transformed_path_and_affine()
+ return None, None
 
 def get_dashes(self):
 """
@@ -608,7 +610,7 @@
 
 def set_clip_path(self, path):
 """
- Set the clip path
+ Set the clip path and transformation
 """
 self._clippath = path
 
@@ -758,7 +760,7 @@
 return
 
 # Find all axes containing the mouse
- axes_list = [a for a in self.canvas.figure.get_axes() if a.in_axes(x, y)]
+ axes_list = [a for a in self.canvas.figure.get_axes() if a.in_axes(self)]
 
 if len(axes_list) == 0: # None found
 self.inaxes = None
@@ -1333,7 +1335,7 @@
 if event.key!='a':
 n=int(event.key)-1
 for i, a in enumerate(self.canvas.figure.get_axes()):
- if event.x is not None and event.y is not None and a.in_axes(event.x, event.y):
+ if event.x is not None and event.y is not None and a.in_axes(event):
 if event.key=='a':
 a.set_navigate(True)
 else:
@@ -1557,7 +1559,7 @@
 
 self._xypress=[]
 for i, a in enumerate(self.canvas.figure.get_axes()):
- if x is not None and y is not None and a.in_axes(x, y) and a.get_navigate():
+ if x is not None and y is not None and a.in_axes(event) and a.get_navigate():
 self._xypress.append((x, y, a, i, a.viewLim.frozen(), a.transData.frozen()))
 self.canvas.mpl_disconnect(self._idDrag)
 self._idDrag=self.canvas.mpl_connect('motion_notify_event', self.drag_pan)
@@ -1581,7 +1583,7 @@
 
 self._xypress=[]
 for i, a in enumerate(self.canvas.figure.get_axes()):
- if x is not None and y is not None and a.in_axes(x, y) and a.get_navigate():
+ if x is not None and y is not None and a.in_axes(event) and a.get_navigate():
 self._xypress.append(( x, y, a, i, a.viewLim.frozen(), a.transData.frozen()))
 
 self.press(event)
@@ -1621,33 +1623,12 @@
 def drag_pan(self, event):
 'the drag callback in pan/zoom mode'
 
- def format_deltas(event,dx,dy):
- if event.key=='control':
- if(abs(dx)>abs(dy)):
- dy = dx
- else:
- dx = dy
- elif event.key=='x':
- dy = 0
- elif event.key=='y':
- dx = 0
- elif event.key=='shift':
- if 2*abs(dx) < abs(dy):
- dx=0
- elif 2*abs(dy) < abs(dx):
- dy=0
- elif(abs(dx)>abs(dy)):
- dy=dy/abs(dy)*abs(dx)
- else:
- dx=dx/abs(dx)*abs(dy)
- return (dx,dy)
-
 for lastx, lasty, a, ind, old_lim, old_trans in self._xypress:
 #safer to use the recorded button at the press than current button:
 #multiple button can get pressed during motion...
 dx, dy = event.x - lastx, event.y - lasty
- dx, dy = format_deltas(event, dx, dy)
- a.drag_pan(self._button_pressed, lastx + dx, lasty + dy, lastx, lasty, old_lim, old_trans)
+ a.drag_pan(self._button_pressed, event.key, lastx, lasty, dx, dy,
+ old_lim, old_trans)
 self.dynamic_update()
 
 def release_zoom(self, event):
@@ -1664,7 +1645,7 @@
 self.draw()
 return
 
- xmin, ymin, xmax, ymax = lim
+ xmin, ymin, xmax, ymax = lim.lbrt
 
 # zoom to rect
 	 inverse = a.transData.inverted()
Modified: branches/transforms/lib/matplotlib/cbook.py
===================================================================
--- branches/transforms/lib/matplotlib/cbook.py	2007年10月02日 08:30:29 UTC (rev 3907)
+++ branches/transforms/lib/matplotlib/cbook.py	2007年10月03日 12:50:04 UTC (rev 3908)
@@ -1033,7 +1033,27 @@
 	itself.
 	"""
 	return self._mapping.get(a, [a])
-		
+
+ 
+def simple_linear_interpolation(a, steps):
+ steps = npy.floor(steps)
+ new_length = ((len(a) - 1) * steps) + 1
+ new_shape = list(a.shape)
+ new_shape[0] = new_length
+ result = npy.zeros(new_shape, a.dtype)
+
+ result[0] = a[0]
+ a0 = a[0:-1]
+ a1 = a[1: ]
+ delta = ((a1 - a0) / steps)
+
+ # MGDTODO: Could use linspace here?
+ for i in range(1, int(steps)):
+ result[i::steps] = delta * i + a0
+ result[steps::steps] = a1
+ 
+ return result
+
 if __name__=='__main__':
 assert( allequal([1,1,1]) )
 assert(not allequal([1,1,0]) )
Modified: branches/transforms/lib/matplotlib/figure.py
===================================================================
--- branches/transforms/lib/matplotlib/figure.py	2007年10月02日 08:30:29 UTC (rev 3907)
+++ branches/transforms/lib/matplotlib/figure.py	2007年10月03日 12:50:04 UTC (rev 3908)
@@ -7,7 +7,7 @@
 
 import artist
 from artist import Artist
-from axes import Axes, Subplot, PolarSubplot, PolarAxes
+from axes import Axes, SubplotBase, subplot_class_factory
 from cbook import flatten, allequal, Stack, iterable, dedent
 import _image
 import colorbar as cbar
@@ -22,6 +22,8 @@
 from transforms import Affine2D, Bbox, BboxTransform, TransformedBbox
 from cm import ScalarMappable
 from contour import ContourSet
+from projections import projection_factory, get_projection_names, \
+ get_projection_class
 import warnings
 
 class SubplotParams:
@@ -449,12 +451,17 @@
 """
 Add an a axes with axes rect [left, bottom, width, height] where all
 quantities are in fractions of figure width and height. kwargs are
- legal Axes kwargs plus "polar" which sets whether to create a polar axes
-
+ legal Axes kwargs plus "projection" which sets the projection type
+ of the axes. (For backward compatibility, polar=True may also be
+ provided, which is equivalent to projection='polar').
+ Valid values for "projection" are: %s. Some of these projections
+ support additional kwargs, which may be provided to add_axes.
+ 
 rect = l,b,w,h
 add_axes(rect)
 add_axes(rect, frameon=False, axisbg='g')
 add_axes(rect, polar=True)
+ add_axes(rect, projection='polar')
 add_axes(ax) # add an Axes instance
 
 
@@ -470,10 +477,10 @@
 add_axes(rect, label='axes2')
 
 The Axes instance will be returned
-
+ 
 The following kwargs are supported:
- %(Axes)s
- """
+ %s
+ """ % (", ".join(get_projection_names()), '%(Axes)s')
 
 key = self._make_key(*args, **kwargs)
 
@@ -489,13 +496,17 @@
 else:
 rect = args[0]
 ispolar = kwargs.pop('polar', False)
-
+ projection = kwargs.pop('projection', None)
 if ispolar:
- a = PolarAxes(self, rect, **kwargs)
- else:
- a = Axes(self, rect, **kwargs)
+ if projection is not None and projection != 'polar':
+ raise ValueError(
+ "polar=True, yet projection='%s'. " +
+ "Only one of these arguments should be supplied." %
+ projection)
+ projection = 'polar'
+ 
+ a = projection_factory(projection, self, rect, **kwargs)
 
-
 self.axes.append(a)
 self._axstack.push(a)
 self.sca(a)
@@ -513,15 +524,21 @@
 add_subplot(111, polar=True) # add a polar subplot
 add_subplot(sub) # add Subplot instance sub
 
- kwargs are legal Axes kwargs plus"polar" which sets whether to create a
- polar axes. The Axes instance will be returned.
+ kwargs are legal Axes kwargs plus "projection", which chooses
+ a projection type for the axes. (For backward compatibility,
+ polar=True may also be provided, which is equivalent to
+ projection='polar'). Valid values for "projection" are: %s.
+ Some of these projections support additional kwargs, which may
+ be provided to add_axes.
 
+ The Axes instance will be returned.
+ 
 If the figure already has a subplot with key *args, *kwargs then it will
 simply make that subplot current and return it
 
 The following kwargs are supported:
- %(Axes)s
- """
+ %s
+ """ % (", ".join(get_projection_names()), "%(Axes)s")
 
 key = self._make_key(*args, **kwargs)
 if self._seen.has_key(key):
@@ -532,16 +549,22 @@
 
 if not len(args): return
 
- if isinstance(args[0], Subplot) or isinstance(args[0], PolarSubplot):
+ if isinstance(args[0], SubplotBase):
 a = args[0]
 assert(a.get_figure() is self)
 else:
 ispolar = kwargs.pop('polar', False)
+ projection = kwargs.pop('projection', None)
 if ispolar:
- a = PolarSubplot(self, *args, **kwargs)
- else:
- a = Subplot(self, *args, **kwargs)
+ if projection is not None and projection != 'polar':
+ raise ValueError(
+ "polar=True, yet projection='%s'. " +
+ "Only one of these arguments should be supplied." %
+ projection)
+ projection = 'polar'
 
+ projection_class = get_projection_class(projection)
+ a = subplot_class_factory(projection_class)(self, *args, **kwargs)
 
 self.axes.append(a)
 self._axstack.push(a)
Modified: branches/transforms/lib/matplotlib/patches.py
===================================================================
--- branches/transforms/lib/matplotlib/patches.py	2007年10月02日 08:30:29 UTC (rev 3907)
+++ branches/transforms/lib/matplotlib/patches.py	2007年10月03日 12:50:04 UTC (rev 3908)
@@ -12,6 +12,8 @@
 import matplotlib.mlab as mlab
 import matplotlib.artist as artist
 from matplotlib.path import Path
+# MGDTODO: Maybe this belongs elsewhere
+from matplotlib.backends._backend_agg import point_in_path
 
 # these are not available for the object inspector until after the
 # class is build so we define an initial set here for the init
@@ -72,6 +74,7 @@
 self._linewidth = linewidth
 self._antialiased = antialiased
 self._hatch = hatch
+ self._combined_transform = transforms.IdentityTransform()
 self.fill = fill
 	
 if len(kwargs): artist.setp(self, **kwargs)
@@ -84,19 +87,15 @@
 
 Returns T/F, {}
 """
-	# MGDTODO: This will probably need to be implemented in C++
-
+	# This is a general version of contains should work on any
+ # patch with a path. However, patches that have a faster
+ # algebraic solution to hit-testing should override this
+ # method.
 	if callable(self._contains): return self._contains(self,mouseevent)
 
- try:
- # TODO: make this consistent with patch collection algorithm
- x, y = self.get_transform().inverse_xy_tup((mouseevent.x, mouseevent.y))
- xyverts = self.get_verts()
- inside = nxutils.pnpoly(x, y, xyverts)
- #print str(self),"%g,%g is in"%(x,y),xyverts,inside
- return inside,{}
- except ValueError:
- return False,{}
+ inside = point_in_path(mouseevent.x, mouseevent.y, self.get_path(),
+ self.get_transform().frozen())
+ return inside, {}
 
 def update_from(self, other):
 artist.Artist.update_from(self, other)
@@ -109,6 +108,17 @@
 self.set_figure(other.get_figure())
 self.set_alpha(other.get_alpha())
 
+ def get_transform(self):
+ return self._combined_transform
+
+ def set_transform(self, t):
+ artist.Artist.set_transform(self, t)
+ self._combined_transform = self.get_patch_transform() + \
+ artist.Artist.get_transform(self)
+
+ def get_patch_transform(self):
+ return transforms.IdentityTransform()
+ 
 def get_antialiased(self):
 return self._antialiased
 
@@ -207,12 +217,12 @@
 
 if not self.fill or self._facecolor is None: rgbFace = None
 else: rgbFace = colors.colorConverter.to_rgb(self._facecolor)
-
+ 
 if self._hatch:
 gc.set_hatch(self._hatch )
 
 path = self.get_path()
- transform = self.get_patch_transform() + self.get_transform()
+ transform = self.get_transform()
 
 renderer.draw_path(gc, path, transform, rgbFace)
 
@@ -226,12 +236,10 @@
 
 
 def get_window_extent(self, renderer=None):
- verts = self.get_verts()
- tverts = self.get_transform().seq_xy_tups(verts)
- return transforms.bound_vertices(tverts)
+ trans_path = self.get_path().transformed(self.get_path_transform())
+ return Bbox.unit().update_from_data(trans_path.vertices)
 
 
-
 def set_lw(self, val):
 'alias for set_linewidth'
 self.set_linewidth(val)
@@ -350,6 +358,11 @@
 
 def get_patch_transform(self):
 	return self._rect_transform
+
+ def contains(self, mouseevent):
+ x, y = self.get_transform().inverted().transform_point(
+ (mouseevent.x, mouseevent.y))
+ return (x >= 0.0 and x <= 1.0 and y >= 0.0 and y <= 1.0), {}
 
 def get_x(self):
 "Return the left coord of the rectangle"
@@ -445,8 +458,8 @@
 def get_path(self):
 	return self._path
 
- def get_transform(self):
-	return self._poly_transform + self._transform
+ def get_patch_transform(self):
+	return self._poly_transform
 	
 class Polygon(Patch):
 """
@@ -467,39 +480,35 @@
 	self._path = Path(xy, closed=True)
 __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd
 
- def get_verts(self):
+ def get_path(self):
 	return self._path
-
- # MGDTODO: Convert units
- xs = self.convert_xunits(xs)
- ys = self.convert_yunits(ys)
-
-class Wedge(Polygon):
+ 
+class Wedge(Patch):
 def __str__(self):
 return "Wedge(%g,%g)"%self.xy[0]
- def __init__(self, center, r, theta1, theta2,
- dtheta=0.1, **kwargs):
+ def __init__(self, center, r, theta1, theta2, **kwargs):
 """
 Draw a wedge centered at x,y tuple center with radius r that
 sweeps theta1 to theta2 (angles)
 
- dtheta is the resolution in degrees
-
 Valid kwargs are:
 %(Patch)s
 
 """
-	# MGDTODO: Implement me
- xc, yc = center
- rads = (math.pi/180.)*npy.arange(theta1, theta2+0.1*dtheta, dtheta)
- xs = r*npy.cos(rads)+xc
- ys = r*npy.sin(rads)+yc
- ...
 
[truncated message content]
From: <ef...@us...> - 2007年10月02日 08:30:38
Revision: 3907
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3907&view=rev
Author: efiring
Date: 2007年10月02日 01:30:29 -0700 (2007年10月02日)
Log Message:
-----------
matplotlib.use() raises an exception if called too late
Modified Paths:
--------------
 trunk/matplotlib/CHANGELOG
 trunk/matplotlib/lib/matplotlib/__init__.py
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG	2007年10月01日 11:53:52 UTC (rev 3906)
+++ trunk/matplotlib/CHANGELOG	2007年10月02日 08:30:29 UTC (rev 3907)
@@ -1,3 +1,6 @@
+2007年10月01日 Made matplotlib.use() raise an exception if called after
+ backends has been imported.
+
 2007年09月30日 Modified update* methods of Bbox and Interval so they
 work with reversed axes. Prior to this, trying to
 set the ticks on a reversed axis failed with an
Modified: trunk/matplotlib/lib/matplotlib/__init__.py
===================================================================
--- trunk/matplotlib/lib/matplotlib/__init__.py	2007年10月01日 11:53:52 UTC (rev 3906)
+++ trunk/matplotlib/lib/matplotlib/__init__.py	2007年10月02日 08:30:29 UTC (rev 3907)
@@ -716,6 +716,9 @@
 except:
 from config import rcParams, rcdefaults
 
+_use_error_msg = """ matplotlib.use() must be called *before* pylab
+or matplotlib.backends is imported for the first time."""
+
 def use(arg):
 """
 Set the matplotlib backend to one of the known backends.
@@ -732,6 +735,8 @@
 for the first time; or, if you are not using pylab, it must
 be called before importing matplotlib.backends.
 """
+ if 'matplotlib.backends' in sys.modules:
+ raise RuntimeError(_use_error_msg)
 be_parts = arg.split('.')
 name = validate_backend(be_parts[0])
 rcParams['backend'] = name
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
From: <md...@us...> - 2007年10月01日 11:54:17
Revision: 3906
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3906&view=rev
Author: mdboom
Date: 2007年10月01日 04:53:52 -0700 (2007年10月01日)
Log Message:
-----------
Merged revisions 3896-3905 via svnmerge from 
http://matplotlib.svn.sf.net/svnroot/matplotlib/trunk/matplotlib
........
 r3898 | jdh2358 | 2007年09月28日 08:41:08 -0400 (2007年9月28日) | 2 lines
 
 fixed some tick accessor bugs
........
 r3899 | jouni | 2007年09月28日 11:50:01 -0400 (2007年9月28日) | 3 lines
 
 Catch UnboundLocalError in checkdep_pdftops; it is raised if
 no output line of pdftops -v contains the word "version".
........
 r3900 | jouni | 2007年09月28日 11:57:49 -0400 (2007年9月28日) | 2 lines
 
 More debugging output when using TeX with the pdf backend
........
 r3901 | jouni | 2007年09月30日 16:08:50 -0400 (2007年9月30日) | 3 lines
 
 use_tex in pdf backend: don't use AFM files, 
 which are not there in some TeX distros
........
 r3902 | efiring | 2007年09月30日 16:32:31 -0400 (2007年9月30日) | 4 lines
 
 bugfix by Zack, confirmed by Gary Ruben.
 
 http://sourceforge.net/mailarchive/forum.php?thread_name=d8cf9020703071339y43354eaerbfa1a47d272e5d26%40mail.gmail.com&forum_name=matplotlib-users
........
 r3903 | efiring | 2007年09月30日 16:47:55 -0400 (2007年9月30日) | 2 lines
 
 Apply patch by Leon Barrett, tracker #1798196
........
 r3904 | efiring | 2007年10月01日 03:06:43 -0400 (2007年10月01日) | 2 lines
 
 Fixed bug in updating dataLim when an axis is reversed
........
Modified Paths:
--------------
 branches/transforms/CHANGELOG
 branches/transforms/lib/matplotlib/__init__.py
 branches/transforms/lib/matplotlib/axes3d.py
 branches/transforms/lib/matplotlib/axis.py
 branches/transforms/lib/matplotlib/backends/backend_pdf.py
 branches/transforms/lib/matplotlib/dviread.py
 branches/transforms/lib/matplotlib/widgets.py
Property Changed:
----------------
 branches/transforms/
Property changes on: branches/transforms
___________________________________________________________________
Name: svnmerge-integrated
 - /trunk/matplotlib:1-3895
 + /trunk/matplotlib:1-3905
Modified: branches/transforms/CHANGELOG
===================================================================
--- branches/transforms/CHANGELOG	2007年10月01日 11:44:54 UTC (rev 3905)
+++ branches/transforms/CHANGELOG	2007年10月01日 11:53:52 UTC (rev 3906)
@@ -1,3 +1,10 @@
+2007年09月30日 Modified update* methods of Bbox and Interval so they
+ work with reversed axes. Prior to this, trying to
+ set the ticks on a reversed axis failed with an
+ uninformative error message. - EF
+
+2007年09月30日 Applied patches to axes3d to fix index error problem - EF
+
 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
@@ -2,3 +9,3 @@
 
-2007年09月21日 Changed cbook.reversed to yield the same result as the 
+2007年09月21日 Changed cbook.reversed to yield the same result as the
 python reversed builtin - DSD
Modified: branches/transforms/lib/matplotlib/__init__.py
===================================================================
--- branches/transforms/lib/matplotlib/__init__.py	2007年10月01日 11:44:54 UTC (rev 3905)
+++ branches/transforms/lib/matplotlib/__init__.py	2007年10月01日 11:53:52 UTC (rev 3906)
@@ -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):
Modified: branches/transforms/lib/matplotlib/axes3d.py
===================================================================
--- branches/transforms/lib/matplotlib/axes3d.py	2007年10月01日 11:44:54 UTC (rev 3905)
+++ branches/transforms/lib/matplotlib/axes3d.py	2007年10月01日 11:53:52 UTC (rev 3906)
@@ -510,16 +510,16 @@
 #
 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)]:
- 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))
Modified: branches/transforms/lib/matplotlib/axis.py
===================================================================
--- branches/transforms/lib/matplotlib/axis.py	2007年10月01日 11:44:54 UTC (rev 3905)
+++ branches/transforms/lib/matplotlib/axis.py	2007年10月01日 11:53:52 UTC (rev 3906)
@@ -530,8 +530,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):
@@ -654,7 +657,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'
@@ -670,14 +674,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)
@@ -1087,9 +1093,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
@@ -1287,8 +1294,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: branches/transforms/lib/matplotlib/backends/backend_pdf.py
===================================================================
--- branches/transforms/lib/matplotlib/backends/backend_pdf.py	2007年10月01日 11:44:54 UTC (rev 3905)
+++ branches/transforms/lib/matplotlib/backends/backend_pdf.py	2007年10月01日 11:53:52 UTC (rev 3906)
@@ -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,11 +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)
- 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: branches/transforms/lib/matplotlib/dviread.py
===================================================================
--- branches/transforms/lib/matplotlib/dviread.py	2007年10月01日 11:44:54 UTC (rev 3905)
+++ branches/transforms/lib/matplotlib/dviread.py	2007年10月01日 11:53:52 UTC (rev 3906)
@@ -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
@@ -734,6 +739,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
Modified: branches/transforms/lib/matplotlib/widgets.py
===================================================================
--- branches/transforms/lib/matplotlib/widgets.py	2007年10月01日 11:44:54 UTC (rev 3905)
+++ branches/transforms/lib/matplotlib/widgets.py	2007年10月01日 11:53:52 UTC (rev 3906)
@@ -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年10月01日 11:45:06
Revision: 3905
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3905&view=rev
Author: mdboom
Date: 2007年10月01日 04:44:54 -0700 (2007年10月01日)
Log Message:
-----------
Move ticking/formatting defaults to scale.py. Speed improvements in transforms.py
Modified Paths:
--------------
 branches/transforms/lib/matplotlib/axes.py
 branches/transforms/lib/matplotlib/axis.py
 branches/transforms/lib/matplotlib/backend_bases.py
 branches/transforms/lib/matplotlib/backends/backend_agg.py
 branches/transforms/lib/matplotlib/cbook.py
 branches/transforms/lib/matplotlib/lines.py
 branches/transforms/lib/matplotlib/path.py
 branches/transforms/lib/matplotlib/scale.py
 branches/transforms/lib/matplotlib/transforms.py
Modified: branches/transforms/lib/matplotlib/axes.py
===================================================================
--- branches/transforms/lib/matplotlib/axes.py	2007年10月01日 07:06:43 UTC (rev 3904)
+++ branches/transforms/lib/matplotlib/axes.py	2007年10月01日 11:44:54 UTC (rev 3905)
@@ -23,6 +23,7 @@
 from matplotlib import mlab
 from matplotlib import cm
 from matplotlib import patches as mpatches
+from matplotlib import path as mpath
 from matplotlib import pbox as mpbox
 from matplotlib import quiver as mquiver
 from matplotlib import scale as mscale
@@ -1461,7 +1462,7 @@
 self.axesPatch.set_facecolor(color)
 
 ### data limits, ticks, tick labels, and formatting
-
+ 
 def get_xlim(self):
 'Get the x axis range [xmin, xmax]'
 return self.viewLim.intervalx
@@ -1503,11 +1504,6 @@
 if xmin is None: xmin = old_xmin
 if xmax is None: xmax = old_xmax
 
-	# MGDTODO
-# if (self.transData.get_funcx().get_type()==mtrans.LOG10
-# and min(xmin, xmax)<=0):
-# raise ValueError('Cannot set nonpositive limits with log transform')
-
 xmin, xmax = mtransforms.nonsingular(xmin, xmax, increasing=False)
 
 	self.viewLim.intervalx = (xmin, xmax)
@@ -1516,7 +1512,7 @@
 	 # Call all of the other x-axes that are shared with this one
 	 for other in self._shared_x_axes.get_siblings(self):
 		if other is not self:
-		 other.set_xlim(self.viewLim.xmin, self.viewLim.xmax, emit=False)
+		 other.set_xlim(self.viewLim.intervalx, emit=False)
 	 
 return xmin, xmax
 
@@ -1634,7 +1630,7 @@
 'return the yaxis scale string: log or linear'
 return self.yaxis.get_scale()
 
- def set_yscale(self, value, basey=10, subsy=None):
+ def set_yscale(self, value, **kwargs):
 """
 SET_YSCALE(value, basey=10, subsy=None)
 
@@ -1652,7 +1648,7 @@
 
 ACCEPTS: ['log' | 'linear']
 """
- self.yaxis.set_scale(value, basey, subsy)
+ self.yaxis.set_scale(value, **kwargs)
 self._update_transScale()
 
 def get_yticks(self):
@@ -1788,6 +1784,32 @@
 """
 self._navigate_mode = b
 
+ def drag_pan(self, button, x, y, startx, starty, start_lim, start_trans):
+ if button == 1:
+ inverse = start_trans.inverted()
+ dx = startx - x
+ dy = starty - y
+ result = self.bbox.frozen().translated(dx, dy).transformed(inverse)
+ elif button == 3:
+ try:
+ inverse = start_trans.inverted()
+ dx = (startx - x) / float(self.bbox.width)
+ dy = (starty - y) / float(self.bbox.height)
+ xmin, ymin, xmax, ymax = start_lim.lbrt
+
+ alpha = npy.power(10.0, (dx, dy))
+ start = inverse.transform_point((startx, starty))
+ lim_points = start_lim.get_points()
+ result = start + alpha * (lim_points - start)
+ result = mtransforms.Bbox(result)
+ except OverflowError:
+ warnings.warn('Overflow while panning')
+ return
+ 
+ # MGDTODO: Could we do this with a single set_lim?
+ self.set_xlim(*result.intervalx)
+ self.set_ylim(*result.intervaly)
+ 
 def get_cursor_props(self):
 """return the cursor props as a linewidth, color tuple where
 linewidth is a float and color is an RGBA tuple"""
@@ -5658,8 +5680,253 @@
 self, fig,
 [self.figLeft, self.figBottom, self.figW, self.figH], **kwargs)
 
+######################################################################
+# New Polar Axes
+ 
+class PolarAxes(Axes):
+ class PolarTransform(mtransforms.Transform):
+ input_dims = 2
+ output_dims = 2
+ is_separable = False
 
+ def transform(self, tr):
+ xy = npy.zeros(tr.shape, npy.float_)
+ t = tr[:, 0:1]
+ r = tr[:, 1:2]
+ x = xy[:, 0:1]
+ y = xy[:, 1:2]
+ x += r * npy.cos(t)
+ y += r * npy.sin(t)
+ return xy
+ transform_non_affine = transform
 
+ def interpolate(self, a, steps):
+ steps = npy.floor(steps)
+ new_length = ((len(a) - 1) * steps) + 1
+ new_shape = list(a.shape)
+ new_shape[0] = new_length
+ result = npy.zeros(new_shape, a.dtype)
+
+ result[0] = a[0]
+ a0 = a[0:-1]
+ a1 = a[1: ]
+ delta = ((a1 - a0) / steps)
+ 
+ for i in range(1, int(steps)+1):
+ result[i::steps] = delta * i + a0
+
+ return result
+ 
+# def transform_path(self, path):
+# twopi = 2.0 * npy.pi
+# halfpi = 0.5 * npy.pi
+ 
+# vertices = path.vertices
+# t0 = vertices[0:-1, 0]
+# t1 = vertices[1: , 0]
+# td = npy.where(t1 > t0, t1 - t0, twopi - (t0 - t1))
+# maxtd = td.max()
+# interpolate = npy.ceil(maxtd / halfpi)
+# if interpolate > 1.0:
+# vertices = self.interpolate(vertices, interpolate)
+
+# vertices = self.transform(vertices)
+
+# result = npy.zeros((len(vertices) * 3 - 2, 2), npy.float_)
+# codes = mpath.Path.CURVE4 * npy.ones((len(vertices) * 3 - 2, ), mpath.Path.code_type)
+# result[0] = vertices[0]
+# codes[0] = mpath.Path.MOVETO
+
+# kappa = 4.0 * ((npy.sqrt(2.0) - 1.0) / 3.0)
+# kappa = 0.5
+ 
+# p0 = vertices[0:-1]
+# p1 = vertices[1: ]
+
+# x0 = p0[:, 0:1]
+# y0 = p0[:, 1: ]
+# b0 = ((y0 - x0) - y0) / ((x0 + y0) - x0)
+# a0 = y0 - b0*x0
+
+# x1 = p1[:, 0:1]
+# y1 = p1[:, 1: ]
+# b1 = ((y1 - x1) - y1) / ((x1 + y1) - x1)
+# a1 = y1 - b1*x1
+
+# x = -(a0-a1) / (b0-b1)
+# y = a0 + b0*x
+
+# xk = (x - x0) * kappa + x0
+# yk = (y - y0) * kappa + y0
+
+# result[1::3, 0:1] = xk
+# result[1::3, 1: ] = yk
+
+# xk = (x - x1) * kappa + x1
+# yk = (y - y1) * kappa + y1
+
+# result[2::3, 0:1] = xk
+# result[2::3, 1: ] = yk
+ 
+# result[3::3] = p1
+
+# print vertices[-2:]
+# print result[-2:]
+ 
+# return mpath.Path(result, codes)
+ 
+# twopi = 2.0 * npy.pi
+# halfpi = 0.5 * npy.pi
+ 
+# vertices = path.vertices
+# t0 = vertices[0:-1, 0]
+# t1 = vertices[1: , 0]
+# td = npy.where(t1 > t0, t1 - t0, twopi - (t0 - t1))
+# maxtd = td.max()
+# interpolate = npy.ceil(maxtd / halfpi)
+
+# print "interpolate", interpolate
+# if interpolate > 1.0:
+# vertices = self.interpolate(vertices, interpolate)
+ 
+# result = npy.zeros((len(vertices) * 3 - 2, 2), npy.float_)
+# codes = mpath.Path.CURVE4 * npy.ones((len(vertices) * 3 - 2, ), mpath.Path.code_type)
+# result[0] = vertices[0]
+# codes[0] = mpath.Path.MOVETO
+
+# kappa = 4.0 * ((npy.sqrt(2.0) - 1.0) / 3.0)
+# tkappa = npy.arctan(kappa)
+# hyp_kappa = npy.sqrt(kappa*kappa + 1.0)
+
+# t0 = vertices[0:-1, 0]
+# t1 = vertices[1: , 0]
+# r0 = vertices[0:-1, 1]
+# r1 = vertices[1: , 1]
+
+# td = npy.where(t1 > t0, t1 - t0, twopi - (t0 - t1))
+# td_scaled = td / (npy.pi * 0.5)
+# rd = r1 - r0
+# r0kappa = r0 * kappa * td_scaled
+# r1kappa = r1 * kappa * td_scaled
+# ravg_kappa = ((r1 + r0) / 2.0) * kappa * td_scaled
+
+# result[1::3, 0] = t0 + (tkappa * td_scaled)
+# result[1::3, 1] = r0*hyp_kappa
+# # result[1::3, 1] = r0 / npy.cos(tkappa * td_scaled) # npy.sqrt(r0*r0 + ravg_kappa*ravg_kappa)
+
+# result[2::3, 0] = t1 - (tkappa * td_scaled)
+# result[2::3, 1] = r1*hyp_kappa
+# # result[2::3, 1] = r1 / npy.cos(tkappa * td_scaled) # npy.sqrt(r1*r1 + ravg_kappa*ravg_kappa)
+ 
+# result[3::3, 0] = t1
+# result[3::3, 1] = r1
+
+# print vertices[:6], result[:6], t0[:6], t1[:6], td[:6], td_scaled[:6], tkappa
+# result = self.transform(result)
+# return mpath.Path(result, codes)
+# transform_path_non_affine = transform_path
+
+ def inverted(self):
+ return PolarAxes.InvertedPolarTransform()
+
+ class PolarAffine(mtransforms.Affine2DBase):
+ def __init__(self, limits):
+ mtransforms.Affine2DBase.__init__(self)
+ self._limits = limits
+ self.set_children(limits)
+ self._mtx = None
+
+ def get_matrix(self):
+ if self._invalid:
+ xmin, ymin, xmax, ymax = self._limits.lbrt
+ affine = mtransforms.Affine2D().rotate(xmin).scale(0.5 / ymax).translate(0.5, 0.5)
+ self._mtx = affine.get_matrix()
+ self._inverted = None
+ self._invalid = 0
+ return self._mtx
+ 
+ class InvertedPolarTransform(mtransforms.Transform):
+ input_dims = 2
+ output_dims = 2
+ is_separable = False
+
+ def transform(self, xy):
+ x = xy[:, 0:1]
+ y = xy[:, 1:]
+ r = npy.sqrt(x*x + y*y)
+ theta = npy.arccos(x / r)
+ theta = npy.where(y < 0, 2 * npy.pi - theta, theta)
+ return npy.concatenate((theta, r), 1)
+
+ def inverted(self):
+ return PolarAxes.PolarTransform()
+ 
+ def _set_lim_and_transforms(self):
+ """
+ set the dataLim and viewLim BBox attributes and the
+ transData and transAxes Transformation attributes
+ """
+	self.dataLim = mtransforms.Bbox.unit()
+ self.viewLim = mtransforms.Bbox.unit()
+ self.transAxes = mtransforms.BboxTransform(
+ mtransforms.Bbox.unit(), self.bbox)
+
+ # 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 = self.PolarTransform()
+
+ # An affine transformation on the data, generally to limit the
+ # range of the axes
+ self.transProjectionAffine = self.PolarAffine(self.viewLim)
+ 
+ self.transData = self.transScale + self.transProjection + \
+ self.transProjectionAffine + self.transAxes
+
+ def drag_pan(self, button, x, y, startx, starty, start_lim, start_trans):
+ if button == 1:
+ inverse = start_trans.inverted()
+ startt, startr = inverse.transform_point((startx, starty))
+ t, r = inverse.transform_point((x, y))
+
+ scale = r / startr
+ self.set_ylim(start_lim.ymin, start_lim.ymax / scale)
+
+ dt0 = t - startt
+ dt1 = startt - t
+ if abs(dt1) < abs(dt0):
+ dt = abs(dt1) * sign(dt0) * -1.0
+ else:
+ dt = dt0 * -1.0
+ self.set_xlim(start_lim.xmin - dt, start_lim.xmin - dt + npy.pi*2.0)
+ 
+ def set_rmax(self, rmax):
+ self.viewLim.maxy = rmax
+ 
+class PolarSubplot(SubplotBase, PolarAxes):
+ """
+ Create a polar subplot with
+
+ PolarSubplot(numRows, numCols, plotNum)
+
+ where plotNum=1 is the first plot number and increasing plotNums
+ fill rows first. max(plotNum)==numRows*numCols
+
+ You can leave out the commas if numRows<=numCols<=plotNum<10, as
+ in
+
+ Subplot(211) # 2 rows, 1 column, first (upper) plot
+ """
+ def __str__(self):
+ return "PolarSubplot(%gx%g)"%(self.figW,self.figH)
+ def __init__(self, fig, *args, **kwargs):
+ SubplotBase.__init__(self, fig, *args)
+ PolarAxes.__init__(
+ self, fig,
+ [self.figLeft, self.figBottom, self.figW, self.figH], **kwargs)
+ 
 martist.kwdocd['Axes'] = martist.kwdocd['Subplot'] = martist.kwdoc(Axes)
 """
 # this is some discarded code I was using to find the minimum positive
Modified: branches/transforms/lib/matplotlib/axis.py
===================================================================
--- branches/transforms/lib/matplotlib/axis.py	2007年10月01日 07:06:43 UTC (rev 3904)
+++ branches/transforms/lib/matplotlib/axis.py	2007年10月01日 11:44:54 UTC (rev 3905)
@@ -20,7 +20,7 @@
 from transforms import Affine2D, Bbox, blended_transform_factory, interval_contains, \
 interval_contains_open, IntervalTransform
 from patches import bbox_artist
-from scale import LinearScale, LogScale
+from scale import scale_factory
 
 import matplotlib.units as units
 #import pdb
@@ -514,41 +514,19 @@
 self.majorTicks = []
 self.minorTicks = []
 self.pickradius = pickradius
- self._scale = LinearScale()
 
 self.cla()
-
+ self.set_scale('linear')
+ 
 def get_transform(self):
 return self._scale.get_transform()
- 
+
 def get_scale(self):
 return self._scale.name
 
- 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')
- if value == 'linear':
- self.set_major_locator(AutoLocator())
- self.set_major_formatter(ScalarFormatter())
- self.set_minor_locator(NullLocator())
- self.set_minor_formatter(NullFormatter())
- 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._scale = LogScale()
- miny, maxy = getattr(self.axes.viewLim, 'interval' + self.axis_name)
- if min(miny, maxy)<=0:
- self.axes.autoscale_view()
+ def set_scale(self, value, **kwargs):
+ self._scale = scale_factory(value, self, **kwargs)
+ self._scale.set_default_locators_and_formatters(self)
 
 def get_children(self):
 children = [self.label]
Modified: branches/transforms/lib/matplotlib/backend_bases.py
===================================================================
--- branches/transforms/lib/matplotlib/backend_bases.py	2007年10月01日 07:06:43 UTC (rev 3904)
+++ branches/transforms/lib/matplotlib/backend_bases.py	2007年10月01日 11:44:54 UTC (rev 3905)
@@ -1483,7 +1483,7 @@
 self._lastCursor = cursors.SELECT_REGION
 if self._xypress:
 x, y = event.x, event.y
- lastx, lasty, a, ind, lim, trans= self._xypress[0]
+ lastx, lasty, a, ind, lim, trans = self._xypress[0]
 self.draw_rubberband(event, x, y, lastx, lasty)
 elif (self._active=='PAN' and
 self._lastCursor != cursors.MOVE):
@@ -1558,10 +1558,7 @@
 self._xypress=[]
 for i, a in enumerate(self.canvas.figure.get_axes()):
 if x is not None and y is not None and a.in_axes(x, y) and a.get_navigate():
- xmin, xmax = a.get_xlim()
- ymin, ymax = a.get_ylim()
- lim = xmin, xmax, ymin, ymax
- self._xypress.append((x, y, a, i, lim, copy.deepcopy(a.transData)))
+ self._xypress.append((x, y, a, i, a.viewLim.frozen(), a.transData.frozen()))
 self.canvas.mpl_disconnect(self._idDrag)
 self._idDrag=self.canvas.mpl_connect('motion_notify_event', self.drag_pan)
 
@@ -1585,10 +1582,7 @@
 self._xypress=[]
 for i, a in enumerate(self.canvas.figure.get_axes()):
 if x is not None and y is not None and a.in_axes(x, y) and a.get_navigate():
- xmin, xmax = a.get_xlim()
- ymin, ymax = a.get_ylim()
- lim = xmin, xmax, ymin, ymax
- self._xypress.append(( x, y, a, i, lim, copy.deepcopy(a.transData) ))
+ self._xypress.append(( x, y, a, i, a.viewLim.frozen(), a.transData.frozen()))
 
 self.press(event)
 
@@ -1648,38 +1642,12 @@
 dx=dx/abs(dx)*abs(dy)
 return (dx,dy)
 
- for cur_xypress in self._xypress:
- lastx, lasty, a, ind, lim, trans = cur_xypress
- xmin, xmax, ymin, ymax = lim
+ for lastx, lasty, a, ind, old_lim, old_trans in self._xypress:
 #safer to use the recorded button at the press than current button:
 #multiple button can get pressed during motion...
- if self._button_pressed==1:
-		inverse = trans.inverted()
- dx, dy = event.x - lastx, event.y - lasty
- dx, dy = format_deltas(event, dx, dy)
- delta = npy.array([[dx, dy], [dx, dy]], npy.float_)
- bbox = transforms.Bbox(a.bbox.get_points() - delta)
- result = bbox.transformed(inverse)
- elif self._button_pressed==3:
- try:
- inverse = trans.inverted()
- dx=(lastx-event.x)/float(a.bbox.width)
- dy=(lasty-event.y)/float(a.bbox.height)
- alphax = pow(10.0, dx)
- alphay = pow(10.0, dy)
- # MGDTODO: Make better use of numpy
- lastx, lasty = inverse.transform_point((lastx, lasty))
- xmin = (lastx + alphax * (xmin - lastx))
- xmax = (lastx + alphax * (xmax - lastx))
- ymin = (lasty + alphay * (ymin - lasty))
- ymax = (lasty + alphay * (ymax - lasty))
- result = transforms.Bbox.from_lbrt(xmin, ymin, xmax, ymax)
- except OverflowError:
- warnings.warn('Overflow while panning')
- return
- a.set_xlim(*result.intervalx)
- a.set_ylim(*result.intervaly)
-
+ dx, dy = event.x - lastx, event.y - lasty
+ dx, dy = format_deltas(event, dx, dy)
+ a.drag_pan(self._button_pressed, lastx + dx, lasty + dy, lastx, lasty, old_lim, old_trans)
 self.dynamic_update()
 
 def release_zoom(self, event):
Modified: branches/transforms/lib/matplotlib/backends/backend_agg.py
===================================================================
--- branches/transforms/lib/matplotlib/backends/backend_agg.py	2007年10月01日 07:06:43 UTC (rev 3904)
+++ branches/transforms/lib/matplotlib/backends/backend_agg.py	2007年10月01日 11:44:54 UTC (rev 3905)
@@ -130,16 +130,16 @@
 if __debug__: verbose.report('RendererAgg.__init__ done',
 'debug-annoying')
 
- # MGDTODO: This is a hack for now to allow for arbitrary transformations
+ # MGDTODO: Just adding helpful asserts. This can be removed in the future
 def draw_path(self, gc, path, trans, rgbFace=None):
- assert trans.is_affine()
- self._renderer.draw_path(gc, path, trans, rgbFace)
+ assert trans.is_affine
+ self._renderer.draw_path(gc, path, trans.frozen(), rgbFace)
 
- # MGDTODO: This is a hack for now to allow for arbitrary transformations
+ # MGDTODO: Just adding helpful asserts. This can be removed in the future
 def draw_markers(self, gc, marker_path, marker_trans, path, trans, rgbFace=None):
- assert marker_trans.is_affine()
- assert trans.is_affine()
- self._renderer.draw_markers(gc, marker_path, marker_trans, path, trans, rgbFace)
+ assert marker_trans.is_affine
+ assert trans.is_affine
+ self._renderer.draw_markers(gc, marker_path, marker_trans.frozen(), path, trans.frozen(), rgbFace)
 
 def draw_mathtext(self, gc, x, y, s, prop, angle):
 """
Modified: branches/transforms/lib/matplotlib/cbook.py
===================================================================
--- branches/transforms/lib/matplotlib/cbook.py	2007年10月01日 07:06:43 UTC (rev 3904)
+++ branches/transforms/lib/matplotlib/cbook.py	2007年10月01日 11:44:54 UTC (rev 3905)
@@ -7,10 +7,11 @@
 import time, datetime
 import numpy as npy
 
-try: set
+try:
+ set = set
 except NameError:
 from sets import Set as set
-
+ 
 major, minor1, minor2, s, tmp = sys.version_info
 
 
Modified: branches/transforms/lib/matplotlib/lines.py
===================================================================
--- branches/transforms/lib/matplotlib/lines.py	2007年10月01日 07:06:43 UTC (rev 3904)
+++ branches/transforms/lib/matplotlib/lines.py	2007年10月01日 11:44:54 UTC (rev 3905)
@@ -496,7 +496,7 @@
 
 funcname = self._lineStyles.get(self._linestyle, '_draw_nothing')
 lineFunc = getattr(self, funcname)
- lineFunc(renderer, gc, *self._transformed_path.get_path_and_affine())
+ lineFunc(renderer, gc, *self._transformed_path.get_transformed_path_and_affine())
 	 
 	# MGDTODO: Deal with markers
 if self._marker is not None:
@@ -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._transformed_path.get_path_and_affine())
+ markerFunc(renderer, gc, *self._transformed_path.get_transformed_path_and_affine())
 
 #renderer.close_group('line2d')
 
Modified: branches/transforms/lib/matplotlib/path.py
===================================================================
--- branches/transforms/lib/matplotlib/path.py	2007年10月01日 07:06:43 UTC (rev 3904)
+++ branches/transforms/lib/matplotlib/path.py	2007年10月01日 11:44:54 UTC (rev 3905)
@@ -1,6 +1,8 @@
 import numpy as npy
 from numpy import ma as ma
 
+KAPPA = 4.0 * (npy.sqrt(2) - 1) / 3.0
+
 class Path(object):
 # Path codes
 STOP = 0 # 1 vertex
@@ -122,7 +124,7 @@
 def unit_circle(cls):
 	# MGDTODO: Optimize?
 	if cls._unit_circle is None:
-	 offset = 4.0 * (npy.sqrt(2) - 1) / 3.0
+ offset = KAPPA
 	 vertices = npy.array(
 		[[-1.0, 0.0],
 		 
Modified: branches/transforms/lib/matplotlib/scale.py
===================================================================
--- branches/transforms/lib/matplotlib/scale.py	2007年10月01日 07:06:43 UTC (rev 3904)
+++ branches/transforms/lib/matplotlib/scale.py	2007年10月01日 11:44:54 UTC (rev 3905)
@@ -2,25 +2,38 @@
 from numpy import ma
 from numpy.linalg import inv
 
+from ticker import NullFormatter, FixedFormatter, ScalarFormatter, \
+ LogFormatter, LogFormatterMathtext
+from ticker import NullLocator, FixedLocator, LinearLocator, LogLocator, AutoLocator
 from transforms import Affine1DBase, IntervalTransform, Transform, \
 composite_transform_factory, IdentityTransform
 
 class ScaleBase(object):
- pass
+ def set_default_locators_and_formatters(self, axis):
+ raise NotImplementedError
+ 
+class LinearScale(ScaleBase):
+ name = 'linear'
+ 
+ def __init__(self, axis, **kwargs):
+ pass
 
-class LinearScale(ScaleBase):
+ def set_default_locators_and_formatters(self, axis):
+ axis.set_major_locator(AutoLocator())
+ axis.set_major_formatter(ScalarFormatter())
+ axis.set_minor_locator(NullLocator())
+ axis.set_minor_formatter(NullFormatter())
+ 
 def get_transform(self):
 return IdentityTransform()
 
 class LogScale(ScaleBase):
+ name = 'log'
+ 
 class Log10Transform(Transform):
 input_dims = 1
 output_dims = 1
- def __init__(self):
- Transform.__init__(self)
-
- def is_separable(self):
- return True
+ is_separable = True
 
 def transform(self, a):
 return ma.log10(ma.masked_where(a <= 0.0, a * 10.0))
@@ -31,11 +44,7 @@
 class InvertedLog10Transform(Transform):
 input_dims = 1
 output_dims = 1
- def __init__(self):
- Transform.__init__(self)
-
- def is_separable(self):
- return True
+ is_separable = True
 
 def transform(self, a):
 return ma.power(10.0, a) / 10.0
@@ -46,11 +55,7 @@
 class Log2Transform(Transform):
 input_dims = 1
 output_dims = 1
- def __init__(self):
- Transform.__init__(self)
-
- def is_separable(self):
- return True
+ is_separable = True
 
 def transform(self, a):
 return ma.log2(ma.masked_where(a <= 0.0, a * 2.0))
@@ -61,11 +66,7 @@
 class InvertedLog2Transform(Transform):
 input_dims = 1
 output_dims = 1
- def __init__(self):
- Transform.__init__(self)
-
- def is_separable(self):
- return True
+ is_separable = True
 
 def transform(self, a):
 return ma.power(2.0, a) / 2.0
@@ -76,12 +77,8 @@
 class NaturalLogTransform(Transform):
 input_dims = 1
 output_dims = 1
- def __init__(self):
- Transform.__init__(self)
-
- def is_separable(self):
- return True
- 
+ is_separable = True
+ 
 def transform(self, a):
 return ma.log(ma.masked_where(a <= 0.0, a * npy.e))
 
@@ -91,12 +88,8 @@
 class InvertedNaturalLogTransform(Transform):
 input_dims = 1
 output_dims = 1
- def __init__(self):
- Transform.__init__(self)
-
- def is_separable(self):
- return True
- 
+ is_separable = True
+ 
 def transform(self, a):
 return ma.power(npy.e, a) / npy.e
 
@@ -106,12 +99,11 @@
 class LogTransform(Transform):
 input_dims = 1
 output_dims = 1
+ is_separable = True
+ 
 def __init__(self, base):
 Transform.__init__(self)
 self._base = base
-
- def is_separable(self):
- return True
 
 def transform(self, a):
 return ma.log(ma.masked_where(a <= 0.0, a * self._base)) / npy.log(self._base)
@@ -122,21 +114,27 @@
 class InvertedLogTransform(Transform):
 input_dims = 1
 output_dims = 1
+ is_separable = True
+ 
 def __init__(self, base):
 Transform.__init__(self)
 self._base = base
 
- def is_separable(self):
- return True
- 
 def transform(self, a):
 return ma.power(self._base, a) / self._base
 
 def inverted(self):
 return LogScale.LogTransform(self._base)
+
 
- 
- def __init__(self, base=10):
+ def __init__(self, axis, **kwargs):
+ if axis.axis_name == 'x':
+ base = kwargs.pop('basex')
+ subs = kwargs.pop('subsx')
+ else:
+ base = kwargs.pop('basey')
+ subs = kwargs.pop('subsy')
+ 
 if base == 10.0:
 self._transform = self.Log10Transform()
 elif base == 2.0:
@@ -145,16 +143,30 @@
 self._transform = self.NaturalLogTransform()
 else:
 self._transform = self.LogTransform(base)
+
+ self._base = base
+ self._subs = subs
+
+ def set_default_locators_and_formatters(self, axis):
+ axis.set_major_locator(LogLocator(self._base))
+ axis.set_major_formatter(LogFormatterMathtext(self._base))
+ axis.set_minor_locator(LogLocator(self._base, self._subs))
+ axis.set_minor_formatter(NullFormatter())
 
 def get_transform(self):
 return self._transform
 
 
 _scale_mapping = {
- 'linear': LinearScale,
- 'log': LogScale
+ 'linear' : LinearScale,
+ 'log' : LogScale
 }
-def scale_factory(scale, viewLim, direction):
+def scale_factory(scale, axis, **kwargs):
+ scale = scale.lower()
 if scale is None:
 scale = 'linear'
- return _scale_mapping[scale](viewLim, direction)
+
+ if not _scale_mapping.has_key(scale):
+ raise ValueError("Unknown scale type '%s'" % scale)
+ 
+ return _scale_mapping[scale](axis, **kwargs)
Modified: branches/transforms/lib/matplotlib/transforms.py
===================================================================
--- branches/transforms/lib/matplotlib/transforms.py	2007年10月01日 07:06:43 UTC (rev 3904)
+++ branches/transforms/lib/matplotlib/transforms.py	2007年10月01日 11:44:54 UTC (rev 3905)
@@ -7,49 +7,57 @@
 import numpy as npy
 from numpy import ma as ma
 from numpy.linalg import inv
-from sets import Set
-from weakref import WeakKeyDictionary
 
+from copy import deepcopy
+from math import sqrt
+from weakref import ref, WeakKeyDictionary
+
+import cbook
 from path import Path
 
 DEBUG = False
 
-# MGDTODO: This creates a ton of cyclical references. We may want to
-# consider using weak references
-
 # MGDTODO: deep copying is probably incorrect wrt the parent/child
 # relationships
 
 class TransformNode(object):
 _gid = 0
+
+ is_affine = False
+ is_bbox = False
 
 def __init__(self):
- # 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._parents = WeakKeyDictionary()
 self._id = TransformNode._gid
+ TransformNode._gid += 1
+ self._invalid = 1
+ self._children = []
 
- 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:
- parent.invalidate(affine_only)
-
- def _do_invalidation(self, affine_only):
- return False
+ def invalidate(self):
+ if self._invalid:
+ return
 
- def set_children(self, children):
+ value = (self.is_affine or self.is_bbox) and 2 or 1
+ stack = [self]
+
+ while len(stack):
+ root = stack.pop()
+ if root._invalid == 0:
+ root._id = TransformNode._gid
+ TransformNode._gid += 1
+ root._invalid = value
+ stack.extend(root._parents.keys())
+
+ def set_children(self, *children):
 for child in children:
- getattr(self, child)._parents.add(self)
+ child._parents[self] = None
 self._children = children
 
+ def frozen(self):
+ return self
+ 
 def make_graphviz(self, fobj):
- seen = Set()
+ seen = cbook.set()
 
 def recurse(root):
 if root in seen:
@@ -57,30 +65,22 @@
 seen.add(root)
 fobj.write('%s [label="%s"];\n' %
 (hash(root), root.__class__.__name__))
- if root.is_affine():
+ if root.is_affine:
 fobj.write('%s [style=filled, color=".7 .7 .9"];\n' %
 hash(root))
- elif root.is_bbox():
+ 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 [label="%s"];\n' % (
+ for child in root._children:
+ fobj.write('%s -> %s;\n' % (
 hash(root),
- hash(child),
- child_name))
+ hash(child)))
 recurse(child)
 
 fobj.write("digraph G {\n")
 recurse(self)
 fobj.write("}\n")
- 
- def is_affine(self):
- return False
 
- def is_bbox(self):
- return False
-
 def get_id(self):
 return self._id
 
@@ -89,13 +89,14 @@
 '''
 This is the read-only part of a bounding-box
 '''
+ is_bbox = True
 
 def __init__(self):
 TransformNode.__init__(self)
 
- def is_bbox(self):
- return True
- 
+ def frozen(self):
+ return Bbox(self.get_points().copy())
+ 
 def __array__(self):
 return self.get_points()
 
@@ -225,7 +226,6 @@
 BboxBase.__init__(self)
 self._points = npy.asarray(points, npy.float_)
 self._minpos = npy.array([0.0000001, 0.0000001])
- self._invalid = False
 
 #@staticmethod
 def unit():
@@ -247,11 +247,6 @@
 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(
@@ -330,7 +325,7 @@
 minposy = property(_get_minposy)
 
 def get_points(self):
- self._invalid = False
+ self._invalid = 0
 return self._points
 
 def set_points(self, points):
@@ -349,6 +344,9 @@
 a = npy.array([[-deltaw, -deltah], [deltaw, deltah]])
 return Bbox(self._points + a)
 
+ def translated(self, tx, ty):
+ return Bbox(self._points + (tx, ty))
+ 
 #@staticmethod
 def union(bboxes):
 """
@@ -362,24 +360,22 @@
 return bboxes[0]
 
 bbox = bboxes[0]
- xmin = bbox.xmin
- ymin = bbox.ymin
- xmax = bbox.xmax
- ymax = bbox.ymax
+ xmin0, ymin0, xmax0, ymax0 = bbox.bounds
 
 for bbox in bboxes[1:]:
- xmin = min(xmin, bbox.xmin)
- ymin = min(ymin, bbox.ymin)
- xmax = max(xmax, bbox.xmax)
- ymax = max(ymax, bbox.ymax)
+ xmin, ymin, xmax, ymax = bbox.bounds
+ xmin0 = min(xmin0, xmin)
+ ymin0 = min(ymin0, ymin)
+ xmax0 = max(xmax0, xmax)
+ ymax0 = max(ymax0, ymax)
 
- return Bbox.from_lbrt(xmin, ymin, xmax, ymax)
+ return Bbox.from_lbrt(xmin0, ymin0, xmax0, ymax0)
 union = staticmethod(union)
 
 
 class TransformedBbox(BboxBase):
 def __init__(self, bbox, transform):
- assert bbox.is_bbox()
+ assert bbox.is_bbox
 assert isinstance(transform, Transform)
 assert transform.input_dims == 2
 assert transform.output_dims == 2
@@ -387,31 +383,26 @@
 BboxBase.__init__(self)
 self._bbox = bbox
 self._transform = transform
- self.set_children(['_bbox', '_transform'])
+ self.set_children(bbox, transform)
 self._points = None
 
 def __repr__(self):
 return "TransformedBbox(%s, %s)" % (self._bbox, self._transform)
 __str__ = __repr__
 
- 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:
+ if self._invalid:
 self._points = self._transform.transform(self._bbox.get_points())
+ self._invalid = 0
 return self._points
-
 
+ 
 class Transform(TransformNode):
+ is_separable = False
+ 
 def __init__(self):
 TransformNode.__init__(self)
 
- def is_separable(self):
- return False
- 
 def __add__(self, other):
 if isinstance(other, Transform):
 return composite_transform_factory(self, other)
@@ -428,17 +419,26 @@
 raise NotImplementedError
 
 def transform_affine(self, points):
- raise NotImplementedError
+ return points
 
 def transform_non_affine(self, points):
- raise NotImplementedError
+ return self.transform(points)
 
 def get_affine(self):
- raise NotImplementedError
+ return IdentityTransform()
 
 def transform_point(self, point):
 return self.transform(npy.asarray([point]))[0]
 
+ def transform_path(self, path):
+ return Path(self.transform(path.vertices), path.codes)
+
+ def transform_path_affine(self, path):
+ return path
+
+ def transform_path_non_affine(self, path):
+ return Path(self.transform_non_affine(path.vertices), path.codes)
+ 
 def has_inverse(self):
 raise NotImplementedError()
 
@@ -454,24 +454,35 @@
 self.input_dims = child.input_dims
 self.output_dims = child.output_dims
 self._child = child
- self.set_children(['_child'])
+ self.set_children(child)
 
 def __repr__(self):
 return "TransformWrapper(%r)" % self._child
 __str__ = __repr__
- 
+
+ def frozen(self):
+ return self._child.frozen()
+ 
 def set(self, child):
 assert child.input_dims == self.input_dims
 assert child.output_dims == self.output_dims
 self._child = child
- self.set_children(['_child'])
+ self.set_children(child)
+ self._invalid = 0
 self.invalidate()
+ self._invalid = 0
 
- def is_separable(self):
- return self._child.is_separable()
+ def _get_is_separable(self):
+ return self._child.is_separable
+ is_separable = property(_get_is_separable)
 
- def is_affine(self):
- return self._child.is_affine()
+ def _get_is_affine(self):
+ return self._child.is_affine
+ is_affine = property(_get_is_affine)
+
+ def get_matrix(self):
+ assert self._child.is_affine
+ return self._child.get_matrix()
 
 def transform(self, points):
 return self._child.transform(points)
@@ -482,6 +493,15 @@
 def transform_non_affine(self, points):
 return self._child.transform_non_affine(points)
 
+ def transform_path(self, path):
+ return self._child.transform_path(path)
+
+ def transform_path_affine(self, path):
+ return self._child.transform_path_affine(path)
+
+ def transform_path_non_affine(self, path):
+ return self._child.transform_path_non_affine(path)
+ 
 def get_affine(self):
 return self._child.get_affine()
 
@@ -490,13 +510,12 @@
 
 
 class AffineBase(Transform):
+ is_affine = True
+ 
 def __init__(self):
 Transform.__init__(self)
 self._inverted = None
 
- def is_affine(self):
- return True
- 
 def __array__(self, *args, **kwargs):
 	return self.get_matrix()
 	
@@ -507,7 +526,7 @@
 
 #@staticmethod
 def concat(a, b):
- return Affine1D(Affine1D._concat(a.get_matrix(), b.get_matrix()))
+ return Affine1D(npy.dot(b.get_matrix(), a.get_matrix()))
 concat = staticmethod(concat)
 
 def get_matrix(self):
@@ -516,6 +535,12 @@
 def transform_non_affine(self, points):
 return points
 
+ def transform_path_affine(self, path):
+ return self.transform_path(path)
+
+ def transform_path_non_affine(self, path):
+ return path
+ 
 def get_affine(self):
 return self
 
@@ -523,12 +548,13 @@
 class Affine1DBase(AffineBase):
 input_dims = 1
 output_dims = 1
+ is_separable = True
 
 def __init__(self):
 AffineBase.__init__(self)
 
- def is_separable(self):
- return True
+ def frozen(self):
+ return Affine1D(self.get_matrix().copy())
 
 def __array__(self, *args, **kwargs):
 	return self.get_matrix()
@@ -539,10 +565,7 @@
 
 #@staticmethod
 def matrix_from_values(a, b):
- affine = npy.zeros((2, 2), npy.float_)
- affine[0, :] = (a, b)
- affine[1, 1] = 1
- return affine
+ return npy.array([[a, b], [0.0, 1.0]], npy.float_)
 matrix_from_values = staticmethod(matrix_from_values)
 
 def transform(self, values):
@@ -561,15 +584,16 @@
 # 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
 
 def inverted(self):
- if self._inverted is None:
+ if self._inverted is None or self._invalid:
 mtx = self.get_matrix()
 self._inverted = Affine1D(inv(mtx))
+ self._invalid = 0
 return self._inverted
 
 
@@ -605,6 +629,7 @@
 from_values = staticmethod(from_values)
 
 def get_matrix(self):
+ self._invalid = 0
 return self._mtx
 
 def set_matrix(self, mtx):
@@ -635,37 +660,29 @@
 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):
 assert direction in ('x', 'y')
- assert bbox.is_bbox()
+ assert bbox.is_bbox
 
 Affine1DBase.__init__(self)
 self._bbox = bbox
 self._direction = "interval" + direction
- self.set_children(['_bbox'])
+ self.set_children(bbox)
 self._mtx = None
 
 def __repr__(self):
 return "IntervalTransform(%s)" % (getattr(self._bbox, self._direction))
 __str__ = __repr__
 
- def _do_invalidation(self, affine_only):
- result = self._mtx is None
- self._mtx = None
- self._inverted = None
- return result
-
 def get_matrix(self):
- if self._mtx is None:
+ if self._invalid:
 min, max = getattr(self._bbox, self._direction)
 self._mtx = inv(npy.array([[max - min, min],
 [0.0, 1.0]], npy.float_))
+ self._inverted = None
+ self._invalid = 0
 return self._mtx
 
 
@@ -676,6 +693,9 @@
 def __init__(self):
 AffineBase.__init__(self)
 
+ def frozen(self):
+ return Affine2D(self.get_matrix().copy())
+ 
 def is_separable(self):
 mtx = self.get_matrix()
 return mtx[0, 1] == 0.0 and mtx[1, 0] == 0.0
@@ -689,11 +709,7 @@
 
 #@staticmethod
 def matrix_from_values(a, b, c, d, e, f):
- affine = npy.zeros((3, 3), npy.float_)
- affine[0, ] = a, c, e
- affine[1, ] = b, d, f
- affine[2, 2] = 1
- return affine
+ return npy.array([[a, c, e], [b, d, f], [0.0, 0.0, 1.0]], npy.float_)
 matrix_from_values = staticmethod(matrix_from_values)
 
 def transform(self, points):
@@ -715,7 +731,7 @@
 # print "".join(traceback.format_stack())
 # print points
 mtx = self.get_matrix()
- if ma.isarray(points):
+ if ma.isMaskedArray(points):
 points = points.transpose()
 points = ma.dot(mtx[0:2, 0:2], points)
 points = points + mtx[0:2, 2:]
@@ -729,9 +745,10 @@
 transform_affine = transform
 
 def inverted(self):
- if self._inverted is None:
+ if self._inverted is None or self._invalid:
 mtx = self.get_matrix()
 self._inverted = Affine2D(inv(mtx))
+ self._invalid = 0
 return self._inverted
 
 
@@ -768,6 +785,7 @@
 from_values = staticmethod(from_values)
 
 def get_matrix(self):
+ self._invalid = 0
 return self._mtx
 
 def set_matrix(self, mtx):
@@ -791,8 +809,8 @@
 def rotate(self, theta):
 a = npy.cos(theta)
 b = npy.sin(theta)
- rotate_mtx = self.matrix_from_values(a, b, -b, a, 0, 0)
- self._mtx = self._concat(self._mtx, rotate_mtx)
+ rotate_mtx = npy.array([[a, -b, 0.0], [b, a, 0.0], [0.0, 0.0, 1.0]], npy.float_)
+ self._mtx = npy.dot(rotate_mtx, self._mtx)
 self.invalidate()
 return self
 
@@ -806,30 +824,33 @@
 return self.translate(-x, -y).rotate_deg(degrees).translate(x, y)
 
 def translate(self, tx, ty):
- translate_mtx = self.matrix_from_values(1., 0., 0., 1., tx, ty)
- self._mtx = self._concat(self._mtx, translate_mtx)
+ translate_mtx = npy.array([[1.0, 0.0, tx], [0.0, 1.0, ty], [0.0, 0.0, 1.0]], npy.float_)
+ self._mtx = npy.dot(translate_mtx, self._mtx)
 self.invalidate()
 return self
 
 def scale(self, sx, sy=None):
 if sy is None:
 sy = sx
- scale_mtx = self.matrix_from_values(sx, 0., 0., sy, 0., 0.)
- self._mtx = self._concat(self._mtx, scale_mtx)
+ scale_mtx = npy.array([[sx, 0.0, 0.0], [0.0, sy, 0.0], [0.0, 0.0, 1.0]], npy.float_)
+ self._mtx = npy.dot(scale_mtx, self._mtx)
 self.invalidate()
 return self
 
- def is_separable(self):
+ def _get_is_separable(self):
 mtx = self.get_matrix()
 return mtx[0, 1] == 0.0 and mtx[1, 0] == 0.0
+ is_separable = property(_get_is_separable)
 
-
 class IdentityTransform(Affine2DBase):
 """
 A special class that does the identity transform quickly.
 """
 _mtx = npy.identity(3)
 
+ def frozen(self):
+ return self
+ 
 def __repr__(self):
 return "IdentityTransform()"
 __str__ = __repr__
@@ -847,6 +868,10 @@
 return points
 transform_affine = transform_non_affine = transform
 
+ def transform_path(self, path):
+ return path
+ transform_path_affine = transform_path_non_affine = transform_path
+ 
 def get_affine(self):
 return self
 inverted = get_affine
@@ -855,33 +880,37 @@
 class BlendedGenericTransform(Transform):
 input_dims = 2
 output_dims = 2
+ is_separable = True
 
 def __init__(self, x_transform, y_transform):
 	# Here we ask: "Does it blend?"
- assert x_transform.is_separable()
- assert y_transform.is_separable()
+ # MGDTODO: Reinvoke these asserts?
+ # 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'])
+ self.set_children(x_transform, y_transform)
 
- def is_affine(self):
- return self._x.is_affine() and self._y.is_affine()
- 
- def is_separable(self):
- return True
- 
+ def _get_is_affine(self):
+ return self._x.is_affine and self._y.is_affine
+ is_affine = property(_get_is_affine)
+
+ def frozen(self):
+ return blended_transform_factory(self._x.frozen(), self._y.frozen())
+ 
 def __repr__(self):
 return "BlendedGenericTransform(%s,%s)" % (self._x, self._y)
 __str__ = __repr__
- 
+
 def transform(self, points):
 x = self._x
 y = self._y
- if x == y and x.input_dims == 2:
- return self._x.transform(points)
 
+ if x is y and x.input_dims == 2:
+ return x.transform(points)
+
 if x.input_dims == 2:
 x_points = x.transform(points)[:, 0:1]
 else:
@@ -895,11 +924,12 @@
 y_points = y_points.reshape((len(y_points), 1))
 
 return ma.concatenate((x_points, y_points), 1)
+
 transform_non_affine = transform
- 
+
 def transform_affine(self, points):
 return points
- 
+ 
 def get_affine(self):
 return IdentityTransform()
 
@@ -908,6 +938,8 @@
 
 
 class BlendedAffine1D(Affine2DBase, Transform):
+ is_separable = True
+ 
 def __init__(self, x_transform, y_transform):
 assert isinstance(x_transform, Affine1DBase)
 assert isinstance(y_transform, Affine1DBase)
@@ -915,63 +947,50 @@
 Transform.__init__(self)
 self._x = x_transform
 self._y = y_transform
- self.set_children(['_x', '_y'])
+ self.set_children(x_transform, y_transform)
 
 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, affine_only):
- result = self._mtx is None
- self._mtx = None
- self._inverted = None
-
 def get_matrix(self):
- if self._mtx is None:
+ if self._invalid:
 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]])
+ self._inverted = None
+ self._invalid = 0
 return self._mtx
 
 
 class BlendedAffine2D(Affine2DBase, Transform):
+ is_separable = True
+ 
 def __init__(self, x_transform, y_transform):
- assert x_transform.is_affine()
- assert y_transform.is_affine()
- assert x_transform.is_separable()
- assert y_transform.is_separable()
+ assert x_transform.is_affine
+ assert y_transform.is_affine
+ 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'])
+ self.set_children(x_transform, y_transform)
 
 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, affine_only):
- result = self._mtx is None
- self._mtx = None
- self._inverted = None
- return result
-
 def get_matrix(self):
- if self._mtx is None:
+ if self._invalid:
 if self._x == self._y:
 self._mtx = self._x.get_matrix()
 else:
@@ -981,6 +1000,8 @@
 # separable, though normally one would want to set b and
 # c to zero.
 self._mtx = npy.vstack((x_mtx[0], y_mtx[1], [0.0, 0.0, 1.0]))
+ self._inverted = None
+ self._invalid = 0
 return self._mtx
 
 
@@ -1001,18 +1022,31 @@
 Transform.__init__(self)
 self._a = a
 self._b = b
- self.set_children(['_a', '_b'])
+ self.set_children(a, b)
+ self._mtx = None
 
- def is_affine(self):
- return self._a.is_affine() and self._b.is_affine()
+ def frozen(self):
+ return composite_transform_factory(self._a.frozen(), self._b.frozen())
 
- def is_separable(self):
+ def _get_is_affine(self):
+ return self._a.is_affine and self._b.is_affine
+ is_affine = property(_get_is_affine)
+ 
+ def _get_is_separable(self):
 return self._a.is_separable() and self._b.is_separable()
+ is_separable = property(_get_is_separable)
 
 def __repr__(self):
 return "CompositeGenericTransform(%s, %s)" % (self._a, self._b)
 __str__ = __repr__
- 
+
+ def get_matrix(self):
+ if self._invalid:
+ assert self._a.is_affine and self._b.is_affine
+ self._mtx = npy.dot(self._b.get_matrix(), self._a.get_matrix())
+ self._invalid = 0
+ return self._mtx
+ 
 def transform(self, points):
 return self._b.transform(self._a.transform(points))
 
@@ -1022,6 +1056,15 @@
 def transform_non_affine(self, points):
 return self._b.transform_non_affine(self._a.transform_non_affine(points))
 
+ def transform_path(self, path):
+ return self._b.transform_path(self._a.transform_path(path))
+
+ def transform_path_affine(self, path):
+ return self._b.transform_path_affine(self._a.transform_path_affine(path))
+
+ def transform_path_non_affine(self, path):
+ return self._b.transform_path_non_affine(self._a.transform_path_non_affine(path))
+ 
 def get_affine(self):
 return CompositeAffine2D(self._a.get_affine(), self._b.get_affine())
 
@@ -1034,113 +1077,46 @@
 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()
+ assert a.is_affine
+ assert b.is_affine
 
 Affine2DBase.__init__(self)
 self._a = a
 self._b = b
- self.set_children(['_a', '_b'])
+ self.set_children(a, b)
 self._mtx = None
 
 def __repr__(self):
 return "CompositeAffine2D(%s, %s)" % (self._a, self._b)
 __str__ = __repr__
 
- def _do_invalidation(self, affine_only):
- result = self._mtx is None
- self._mtx = None
- self._inverted = None
- return result
- 
 def get_matrix(self):
- if self._mtx is None:
- self._mtx = self._concat(
- self._a.get_matrix(),
- self._b.get_matrix())
+ if self._invalid:
+ self._mtx = npy.dot(
+ self._b.get_matrix(),
+ self._a.get_matrix())
+ self._inverted = None
+ self._invalid = 0
 return self._mtx
 
 
 def composite_transform_factory(a, b):
-# 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)
-
-
-class TestPolarTransform(Transform):
- 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
- 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(self._limits)
 
- def is_separable(self):
- return False
-
-
-class TestInvertPolarTransform(Transform):
- 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)
- r = r * (limmax - limmin) + limmin
- return ma.concatenate((theta, r), 1)
-
- def inverted(self):
- return TestInvertPolarTransform(self._limits)
- 
- def is_separable(self):
- return False
- 
- 
 class BboxTransform(Affine2DBase):
+ is_separable = True
+
 def __init__(self, boxin, boxout):
- assert boxin.is_bbox()
- assert boxout.is_bbox()
+ assert boxin.is_bbox
+ assert boxout.is_bbox
 
 Affine2DBase.__init__(self)
 self._boxin = boxin
 self._boxout = boxout
- self.set_children(['_boxin', '_boxout'])
+ self.set_children(boxin, boxout)
 self._mtx = None
 self._inverted = None
 
@@ -1148,29 +1124,17 @@
 return "BboxTransform(%s, %s)" % (self._boxin, self._boxout)
 __str__ = __repr__
 
- def _do_invalidation(self, affine_only):
- result = self._mtx is None
- self._mtx = None
- self._inverted = None
- return result
- 
- def is_separable(self):
- return True
-
 def get_matrix(self):
- if self._mtx is None:
- boxin = self._boxin
- boxout = self._boxout
- x_scale = boxout.width / boxin.width
- y_scale = boxout.height / boxin.height
-
- # MGDTODO: Optimize
- affine = Affine2D() \
- .translate(-boxin.xmin, -boxin.ymin) \
- .scale(x_scale, y_scale) \
- .translate(boxout.xmin, boxout.ymin)
-
- self._mtx = affine._mtx
+ if self._invalid:
+ inl, inb, inw, inh = self._boxin.bounds
+ outl, outb, outw, outh = self._boxout.bounds
+ x_scale = outw / inw
+ y_scale = outh / inh
+ self._mtx = npy.array([[x_scale, 0.0 , (-inl*x_scale+outl)],
+ [0.0 , y_scale, (-inb*y_scale+outb)],
+ [0.0 , 0.0 , 1.0 ]],
+ npy.float_)
+ self._inverted = None
 return self._mtx
 
 
@@ -1181,27 +1145,20 @@
 
 self._path = path
 self._transform = transform
- self.set_children(['_transform'])
+ self.set_children(transform)
 self._transformed_path = None
 
- 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:
- vertices = self._transform.transform_non_affine(self._path.vertices)
- self._transformed_path = Path(vertices, self._path.codes)
-
+ def get_transformed_path_and_affine(self):
+ if self._invalid == 1 or self._transformed_path is None:
+ self._transformed_path = self._transform.transform_path_non_affine(self._path)
+ self._invalid = 0
 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_fully_transformed_path(self):
+ if self._invalid == 1 or self._transformed_path is None:
+ self._transformed_path = self._transform.transform_path_non_affine(self._path)
+ self._invalid = 0
+ return self._transform.transform_path_affine(self._transformed_path)
 
 def get_affine(self):
 return self._transform.get_affine()
...
 
[truncated message content]
From: <ef...@us...> - 2007年10月01日 07:06:44
Revision: 3904
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3904&view=rev
Author: efiring
Date: 2007年10月01日 00:06:43 -0700 (2007年10月01日)
Log Message:
-----------
Fixed bug in updating dataLim when an axis is reversed
Modified Paths:
--------------
 trunk/matplotlib/CHANGELOG
 trunk/matplotlib/src/_transforms.cpp
Modified: trunk/matplotlib/CHANGELOG
===================================================================
--- trunk/matplotlib/CHANGELOG	2007年09月30日 20:47:55 UTC (rev 3903)
+++ trunk/matplotlib/CHANGELOG	2007年10月01日 07:06:43 UTC (rev 3904)
@@ -1,3 +1,10 @@
+2007年09月30日 Modified update* methods of Bbox and Interval so they
+ work with reversed axes. Prior to this, trying to
+ set the ticks on a reversed axis failed with an
+ uninformative error message. - EF
+
+2007年09月30日 Applied patches to axes3d to fix index error problem - EF
+
 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
@@ -2,3 +9,3 @@
 
-2007年09月21日 Changed cbook.reversed to yield the same result as the 
+2007年09月21日 Changed cbook.reversed to yield the same result as the
 python reversed builtin - DSD
Modified: trunk/matplotlib/src/_transforms.cpp
===================================================================
--- trunk/matplotlib/src/_transforms.cpp	2007年09月30日 20:47:55 UTC (rev 3903)
+++ trunk/matplotlib/src/_transforms.cpp	2007年10月01日 07:06:43 UTC (rev 3904)
@@ -159,12 +159,19 @@
 
 double minx = _val1->val();
 double maxx = _val2->val();
+ int reversed = 0;
+ if (minx > maxx) {
+ reversed = 1;
+ double tmp = minx;
+ minx = maxx;
+ maxx = tmp;
+ }
 
 
 
 double thisval;
 thisval = Py::Float(vals[0]);
- if (ignore) { 
+ if (ignore) {
 minx = thisval;
 maxx = thisval;
 }
@@ -176,9 +183,13 @@
 _minpos->update(thisval);
 }
 
-
- _val1->set_api(minx);
- _val2->set_api(maxx);
+ if (reversed) {
+ _val1->set_api(maxx);
+ _val2->set_api(minx);
+ } else {
+ _val1->set_api(minx);
+ _val2->set_api(maxx);
+ }
 return Py::Object();
 }
 
@@ -459,8 +470,24 @@
 
 double minx = _ll->xval();
 double maxx = _ur->xval();
+ int xreversed = 0;
+ if (minx > maxx) {
+ xreversed = 1;
+ double tmp = minx;
+ minx = maxx;
+ maxx = tmp;
+ }
+
+
 double miny = _ll->yval();
 double maxy = _ur->yval();
+ int yreversed = 0;
+ if (miny > maxy) {
+ yreversed = 1;
+ double tmp = miny;
+ miny = maxy;
+ maxy = tmp;
+ }
 
 Py::Tuple tup;
 if (ignore) {
@@ -482,11 +509,22 @@
 if (y>maxy) maxy=y;
 }
 
+ if (xreversed) {
+ _ll->x_api()->set_api(maxx);
+ _ur->x_api()->set_api(minx);
+ } else {
+ _ll->x_api()->set_api(minx);
+ _ur->x_api()->set_api(maxx);
+ }
 
- _ll->x_api()->set_api(minx);
- _ll->y_api()->set_api(miny);
- _ur->x_api()->set_api(maxx);
- _ur->y_api()->set_api(maxy);
+ if (yreversed) {
+ _ll->y_api()->set_api(maxy);
+ _ur->y_api()->set_api(miny);
+ } else {
+ _ll->y_api()->set_api(miny);
+ _ur->y_api()->set_api(maxy);
+ }
+
 return Py::Object();
 }
 
@@ -519,8 +557,24 @@
 
 double minx = _ll->xval();
 double maxx = _ur->xval();
+ int xreversed = 0;
+ if (minx > maxx) {
+ xreversed = 1;
+ double tmp = minx;
+ minx = maxx;
+ maxx = tmp;
+ }
+
+
 double miny = _ll->yval();
 double maxy = _ur->yval();
+ int yreversed = 0;
+ if (miny > maxy) {
+ yreversed = 1;
+ double tmp = miny;
+ miny = maxy;
+ maxy = tmp;
+ }
 
 double thisx, thisy;
 //don't use current bounds on first update
@@ -550,10 +604,21 @@
 
 Py_XDECREF(xyin);
 if (ngood) {
- _ll->x_api()->set_api(minx);
- _ll->y_api()->set_api(miny);
- _ur->x_api()->set_api(maxx);
- _ur->y_api()->set_api(maxy);
+ if (xreversed) {
+ _ll->x_api()->set_api(maxx);
+ _ur->x_api()->set_api(minx);
+ } else {
+ _ll->x_api()->set_api(minx);
+ _ur->x_api()->set_api(maxx);
+ }
+
+ if (yreversed) {
+ _ll->y_api()->set_api(maxy);
+ _ur->y_api()->set_api(miny);
+ } else {
+ _ll->y_api()->set_api(miny);
+ _ur->y_api()->set_api(maxy);
+ }
 }
 return Py::Object();
 }
@@ -594,8 +659,24 @@
 
 double minx = _ll->xval();
 double maxx = _ur->xval();
+ int xreversed = 0;
+ if (minx > maxx) {
+ xreversed = 1;
+ double tmp = minx;
+ minx = maxx;
+ maxx = tmp;
+ }
+
+
 double miny = _ll->yval();
 double maxy = _ur->yval();
+ int yreversed = 0;
+ if (miny > maxy) {
+ yreversed = 1;
+ double tmp = miny;
+ miny = maxy;
+ maxy = tmp;
+ }
 
 double thisx, thisy;
 //don't use current bounds on first update
@@ -627,10 +708,21 @@
 Py_XDECREF(y);
 
 
- _ll->x_api()->set_api(minx);
- _ll->y_api()->set_api(miny);
- _ur->x_api()->set_api(maxx);
- _ur->y_api()->set_api(maxy);
+ if (xreversed) {
+ _ll->x_api()->set_api(maxx);
+ _ur->x_api()->set_api(minx);
+ } else {
+ _ll->x_api()->set_api(minx);
+ _ur->x_api()->set_api(maxx);
+ }
+
+ if (yreversed) {
+ _ll->y_api()->set_api(maxy);
+ _ur->y_api()->set_api(miny);
+ } else {
+ _ll->y_api()->set_api(miny);
+ _ur->y_api()->set_api(maxy);
+ }
 return Py::Object();
 }
 
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:47:58
Revision: 3903
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3903&view=rev
Author: efiring
Date: 2007年09月30日 13:47:55 -0700 (2007年9月30日)
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 (2007年9月30日)
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 (2007年9月30日)
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 (2007年9月28日)
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 (2007年9月28日)
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 (2007年9月28日)
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 (2007年9月26日)
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 (2007年9月26日)
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 (2007年9月26日) | 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 (2007年9月26日)
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 (2007年9月26日)
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.
Revision: 3893
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3893&view=rev
Author: mdboom
Date: 2007年09月26日 05:29:05 -0700 (2007年9月26日)
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 (2007年9月25日)
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 (2007年9月25日)
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 (2007年9月25日)
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 (2007年9月25日)
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 (2007年9月25日)
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.
Revision: 3887
 http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3887&view=rev
Author: jswhit
Date: 2007年09月25日 05:14:28 -0700 (2007年9月25日)
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.

Showing results of 5455

<< < 1 .. 202 203 204 205 206 .. 219 > >> (Page 204 of 219)
Want the latest updates on software, tech news, and AI?
Get latest updates about software, tech news, and AI from SourceForge directly in your inbox once a month.
Thanks for helping keep SourceForge clean.
X





Briefly describe the problem (required):
Upload screenshot of ad (required):
Select a file, or drag & drop file here.
Screenshot instructions:

Click URL instructions:
Right-click on the ad, choose "Copy Link", then paste here →
(This may not be possible with some types of ads)

More information about our ad policies

Ad destination/click URL:

AltStyle によって変換されたページ (->オリジナル) /