|
From: <md...@us...> - 2007-09-12 13:36:31
|
Revision: 3835
http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3835&view=rev
Author: mdboom
Date: 2007-09-12 06:36:25 -0700 (Wed, 12 Sep 2007)
Log Message:
-----------
Second pass, using a stateful transform tree.
Modified Paths:
--------------
branches/transforms/lib/matplotlib/affine.py
branches/transforms/lib/matplotlib/artist.py
branches/transforms/lib/matplotlib/axes.py
branches/transforms/lib/matplotlib/axis.py
branches/transforms/lib/matplotlib/backends/backend_agg.py
branches/transforms/lib/matplotlib/backends/backend_tkagg.py
branches/transforms/lib/matplotlib/figure.py
branches/transforms/lib/matplotlib/legend.py
branches/transforms/lib/matplotlib/lines.py
branches/transforms/lib/matplotlib/table.py
branches/transforms/lib/matplotlib/text.py
branches/transforms/lib/matplotlib/ticker.py
Removed Paths:
-------------
branches/transforms/lib/matplotlib/bbox.py
Modified: branches/transforms/lib/matplotlib/affine.py
===================================================================
--- branches/transforms/lib/matplotlib/affine.py 2007-09-12 07:04:38 UTC (rev 3834)
+++ branches/transforms/lib/matplotlib/affine.py 2007-09-12 13:36:25 UTC (rev 3835)
@@ -6,19 +6,203 @@
import numpy as N
from numpy.linalg import inv
+from sets import Set
-class Transform(object):
+# MGDTODO: This creates a ton of cyclical references. We may want to
+# consider using weak references
+
+class TransformNode(object):
+ def __init__(self):
+ self._parents = Set()
+
+ def invalidate(self):
+ if not self._do_invalidation():
+ for parent in self._parents:
+ parent.invalidate()
+
+ def _do_invalidation(self):
+ return False
+
+ def add_children(self, children):
+ for child in children:
+ child._parents.add(self)
+
+class Bbox(TransformNode):
+ def __init__(self, points):
+ TransformNode.__init__(self)
+ self._points = N.asarray(points, N.float_)
+ self.track = False
+
+ def __del__(self):
+ if self.track:
+ print "Bbox::__del__"
+
+ #@staticmethod
+ def unit():
+ return Bbox([[0,0], [1,1]])
+ unit = staticmethod(unit)
+
+ #@staticmethod
+ def from_lbwh(left, bottom, width, height):
+ return Bbox([[left, bottom], [left + width, bottom + height]])
+ from_lbwh = staticmethod(from_lbwh)
+
+ #@staticmethod
+ def from_lbrt(left, bottom, right, top):
+ return Bbox([[left, bottom], [right, top]])
+ from_lbrt = staticmethod(from_lbrt)
+
+ def update_from_data(self, x, y):
+ self._points = N.array([[x.min(), y.min()], [x.max(), y.max()]], N.float_)
+ self.invalidate()
+ if self.track:
+ print "Bbox::update_from_data", self._points
+
+ def copy(self):
+ if self.track:
+ print "Bbox::copy"
+ return Bbox(self._points.copy())
+
+ def __repr__(self):
+ return 'Bbox(%s)' % repr(self._points)
+ __str__ = __repr__
+
+ def __cmp__(self, other):
+ # MGDTODO: Totally suboptimal
+ if isinstance(other, Bbox):
+ return (self._points == other._points).all()
+ return -1
+
+ # MGDTODO: Probably a more efficient ways to do this...
+ def _get_xmin(self):
+ if self.track:
+ print "Bbox::_get_xmin"
+ return self._points[0, 0]
+ def _set_xmin(self, val):
+ print "Bbox::_set_xmin"
+ self._points[0, 0] = val
+ self.invalidate()
+ xmin = property(_get_xmin, _set_xmin)
+
+ def _get_ymin(self):
+ return self._points[0, 1]
+ def _set_ymin(self, val):
+ self._points[0, 1] = val
+ self.invalidate()
+ ymin = property(_get_ymin, _set_ymin)
+
+ def _get_xmax(self):
+ return self._points[1, 0]
+ def _set_xmax(self, val):
+ self._points[1, 0] = val
+ self.invalidate()
+ xmax = property(_get_xmax, _set_xmax)
+
+ def _get_ymax(self):
+ return self._points[1, 1]
+ def _set_ymax(self, val):
+ self._points[1, 1] = val
+ self.invalidate()
+ ymax = property(_get_ymax, _set_ymax)
+
+ def _get_min(self):
+ return self._points[0]
+ def _set_min(self, val):
+ self._points[0] = val
+ self.invalidate()
+ min = property(_get_min, _set_min)
+
+ def _get_max(self):
+ return self._points[1]
+ def _set_max(self, val):
+ self._points[1] = val
+ self.invalidate()
+ max = property(_get_max, _set_max)
+
+ def _get_intervalx(self):
+ return self._points[:,0]
+ def _set_intervalx(self, interval):
+ self._points[:,0] = interval
+ self.invalidate()
+ intervalx = property(_get_intervalx, _set_intervalx)
+
+ def _get_intervaly(self):
+ return self._points[:,1]
+ def _set_intervaly(self, interval):
+ self._points[:,1] = interval
+ self.invalidate()
+ intervaly = property(_get_intervaly, _set_intervaly)
+
+ def _get_width(self):
+ return self.xmax - self.xmin
+ width = property(_get_width)
+
+ def _get_height(self):
+ return self.ymax - self.ymin
+ height = property(_get_height)
+
+ def transformed(self, transform):
+ return Bbox(self.transform(self._points))
+
+ def inverse_transformed(self, transform):
+ return Bbox(self.transform.inverted()(self._points))
+
+ def get_bounds(self):
+ return (self.xmin, self.ymin,
+ self.xmax - self.xmin, self.ymax - self.ymin)
+
+ def expanded(self, sw, sh):
+ width = self.width()
+ height = self.height()
+ deltaw = (sw * width - width) / 2.0
+ deltah = (sh * height - height) / 2.0
+ a = N.array([[-deltaw, -deltah], [deltaw, deltah]])
+ return Bbox(self._points + a)
+
+ def contains(self, x, y):
+ return (x >= self.xmin and x <= self.xmax and
+ y >= self.ymin and y <= self.ymax)
+
+ #@staticmethod
+ def union(bboxes):
+ """
+ Return the Bbox that bounds all bboxes
+ """
+ assert(len(bboxes))
+
+ if len(bboxes) == 1:
+ return bboxes[0]
+
+ bbox = bboxes[0]
+ xmin = bbox.xmin
+ ymin = bbox.ymin
+ xmax = bbox.xmax
+ ymax = bbox.ymax
+
+ 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)
+
+ return Bbox.from_lbrt(xmin, ymin, xmax, ymax)
+ union = staticmethod(union)
+
+class Transform(TransformNode):
+ def __init__(self):
+ TransformNode.__init__(self)
+
def __call__(self, points):
raise NotImplementedError()
def __add__(self, other):
if isinstance(other, Transform):
- return CompositeTransform(self, other)
+ return composite_transform_factory(self, other)
raise TypeError("Can not add Transform to object of type '%s'" % type(other))
def __radd__(self, other):
if isinstance(other, Transform):
- return CompositeTransform(other, self)
+ return composite_transform_factory(other, self)
raise TypeError("Can not add Transform to object of type '%s'" % type(other))
def has_inverse(self):
@@ -30,15 +214,9 @@
def is_separable(self):
return False
-class CompositeTransform(Transform):
- def __init__(self, a, b):
- assert a.output_dims == b.input_dims
- self.a = a
- self.b = b
-
- def __call__(self, points):
- return self.b(self.a(points))
-
+ def is_affine(self):
+ return False
+
class Affine2D(Transform):
input_dims = 2
output_dims = 2
@@ -51,15 +229,22 @@
b d f
0 0 1
"""
+ Transform.__init__(self)
if matrix is None:
matrix = N.identity(3)
else:
assert matrix.shape == (3, 3)
- self.mtx = matrix
+ self._mtx = matrix
+ self._inverted = None
def __repr__(self):
- return "Affine2D(%s)" % repr(self.mtx)
+ return "Affine2D(%s)" % repr(self._mtx)
__str__ = __repr__
+
+ def _do_invalidation(self):
+ result = self._inverted is None
+ self._inverted = None
+ return result
#@staticmethod
def from_values(a, b, c, d, e, f):
@@ -67,7 +252,8 @@
from_values = staticmethod(from_values)
def to_values(self):
- return tuple(self.mtx[:2].swapaxes(0, 1).flatten())
+ mtx = self.get_matrix()
+ return tuple(mtx[:2].swapaxes(0, 1).flatten())
#@staticmethod
def matrix_from_values(a, b, c, d, e, f):
@@ -78,6 +264,9 @@
return affine
matrix_from_values = staticmethod(matrix_from_values)
+ def get_matrix(self):
+ return self._mtx
+
def __call__(self, points):
"""
Applies the transformation to a set of 2D points and
@@ -91,13 +280,14 @@
# to separate the matrix out into the translation and scale components
# and apply each separately (which is still sub-optimal)
- # This is nicer for now, however, since we can just keep a
+ # This is easier for now, however, since we can just keep a
# regular affine matrix around
# MGDTODO: Trap cases where this isn't an array and fix there
- points = N.array(points, N.float_)
+ mtx = self.get_matrix()
+ points = N.asarray(points, N.float_)
new_points = points.swapaxes(0, 1)
new_points = N.vstack((new_points, N.ones((1, points.shape[0]))))
- result = N.dot(self.mtx, new_points)[:2]
+ result = N.dot(mtx, new_points)[:2]
return result.swapaxes(0, 1)
#@staticmethod
@@ -105,8 +295,9 @@
return N.dot(b, a)
_concat = staticmethod(_concat)
+ #@staticmethod
def concat(a, b):
- return Affine2D(Affine2D._concat(a.mtx, b.mtx))
+ return Affine2D(Affine2D._concat(a._mtx, b._mtx))
concat = staticmethod(concat)
#@staticmethod
@@ -114,100 +305,246 @@
return Affine2D(N.identity(3))
identity = staticmethod(identity)
- def __add__(self, other):
- if isinstance(other, Affine2D):
- return Affine2D.concat(self, other)
- return Transform.__add__(self, other)
-
- def __radd__(self, other):
- if isinstance(other, Affine2D):
- return Affine2D.concat(other, self)
- return Transform.__radd__(self, other)
-
- def rotated(self, theta):
+ def rotate(self, theta):
a = N.cos(theta)
b = N.sin(theta)
rotate_mtx = self.matrix_from_values(a, b, -b, a, 0, 0)
- return Affine2D(self._concat(self.mtx, rotate_mtx))
+ self._mtx = self._concat(self._mtx, rotate_mtx)
+ self.invalidate()
+ return self
- def rotated_deg(self, degrees):
- return self.rotated(degrees*N.pi/180.)
+ def rotate_deg(self, degrees):
+ return self.rotate(degrees*N.pi/180.)
- def translated(self, tx, ty):
+ def translate(self, tx, ty):
translate_mtx = self.matrix_from_values(1., 0., 0., 1., tx, ty)
- return Affine2D(self._concat(self.mtx, translate_mtx))
+ self._mtx = self._concat(self._mtx, translate_mtx)
+ self.invalidate()
+ return self
- def scaled(self, sx, sy=None):
+ def scale(self, sx, sy=None):
if sy is None:
sy = sx
scale_mtx = self.matrix_from_values(sx, 0., 0., sy, 0., 0.)
- return Affine2D(self._concat(self.mtx, scale_mtx))
+ self._mtx = self._concat(self._mtx, scale_mtx)
+ self.invalidate()
+ return self
def inverted(self):
- # MGDTODO: We may want to optimize by storing the inverse
- # of the transform with every transform
- return Affine2D(inv(self.mtx))
+ if self._inverted is None:
+ mtx = self.get_matrix()
+ self._inverted = Affine2D(inv(mtx))
+ return self._inverted
def is_separable(self):
- mtx = self.mtx
+ mtx = self.get_matrix()
return mtx[0, 1] == 0.0 and mtx[1, 0] == 0.0
+ def is_affine(self):
+ return True
+
class BlendedAffine2D(Affine2D):
def __init__(self, x_transform, y_transform):
-# assert isinstance(x_transform, Affine2D)
-# assert isinstance(y_transform, Affine2D)
+ assert x_transform.is_affine()
+ assert y_transform.is_affine()
assert x_transform.is_separable()
assert y_transform.is_separable()
- x_mtx = x_transform.mtx
- y_mtx = y_transform.mtx
- self.mtx = self.matrix_from_values(
- x_mtx[0,0], 0.0, 0.0, y_mtx[1,1], x_mtx[0,2], y_mtx[1,2])
-# This is a placeholder since eventually we may need to handle the
-# more general case of two transforms that aren't affines
-BlendedTransform = BlendedAffine2D
+ Transform.__init__(self)
+ self.add_children([x_transform, y_transform])
+ self._x = x_transform
+ self._y = y_transform
+ self._mtx = None
+ self._inverted = None
-def blend_xy_sep_transform(x_transform, y_transform):
- return BlendedAffine2D(x_transform, y_transform)
+ def __repr__(self):
+ return "BlendedAffine2D(%s,%s)" % (self._x, self._y)
+ __str__ = __repr__
+
+ def _do_invalidation(self):
+ if self._mtx is not None:
+ self._mtx = None
+ Affine2D._do_invalidation(self)
+ return False
+ return True
-def get_bbox_transform(boxin, boxout):
- x_scale = boxout.width() / boxin.width()
- y_scale = boxout.height() / boxin.height()
+ def _make__mtx(self):
+ if self._mtx is None:
+ x_mtx = self._x.get_matrix()
+ y_mtx = self._y.get_matrix()
+ self._mtx = N.vstack([x_mtx[0], y_mtx[1], [0.0, 0.0, 1.0]])
+# self._mtx = self.matrix_from_values(
+# x_mtx[0,0], 0.0, 0.0, y_mtx[1,1], x_mtx[0,2], y_mtx[1,2])
+ print "Blended", x_mtx, y_mtx, self._mtx
+
+ def is_separable(self):
+ return True
+
+ def get_matrix(self):
+ self._make__mtx()
+ return self._mtx
- # MGDTODO: Optimize
- return Affine2D() \
- .translated(-boxin.xmin(), -boxin.ymin()) \
- .scaled(x_scale, y_scale) \
- .translated(boxout.xmin(), boxout.ymin())
+class BlendedTransform(Transform):
+ def __init__(self, x_transform, y_transform):
+ assert x_transform.is_separable()
+ assert y_transform.is_separable()
+
+ Transform.__init__(self)
+ self.add_children([x_transform, y_transform])
+ self._x = x_transform
+ self._y = y_transform
+
+ def __call__(self, points):
+ # MGDTODO: Implement me
+ pass
+
+class CompositeAffine2D(Affine2D):
+ def __init__(self, a, b):
+ assert a.is_affine()
+ assert b.is_affine()
+
+ Transform.__init__(self)
+ self.add_children([a, b])
+ self._a = a
+ self._b = b
+ self._mtx = None
+ self._inverted = None
+
+ def __repr__(self):
+ return "CompositeAffine2D(%s, %s)" % (self._a, self._b)
+ __str__ = __repr__
+
+ def _do_invalidation(self):
+ self._mtx = None
+ Affine2D._do_invalidation(self)
-if __name__ == '__main__':
- print Affine2D.from_values(1., 0, 0, 1, 0, 0)
-
- print "translated", Affine2D.identity().translated(5, 4)
- print "rotated", Affine2D.identity().rotated_deg(30)
- print "scaled", Affine2D.identity().scaled(5, 4)
-
- transform = Affine2D.identity().rotated_deg(30).translated(5, 4)
+ def _make__mtx(self):
+ if self._mtx is None:
+ self._mtx = self._concat(
+ self._b.get_matrix(),
+ self._a.get_matrix())
- points = N.array([[1, 2], [3, 4], [5, 6]])
+ def get_matrix(self):
+ self._make__mtx()
+ return self._mtx
+
+class CompositeTransform(Transform):
+ def __init__(self, a, b):
+ assert a.output_dims == b.input_dims
- print inv(transform.mtx)
+ Transform.__init__(self)
+ self.add_children([a, b])
+ self._a = a
+ self._b = b
+
+ def __call__(self, points):
+ # MGDTODO: Optimize here by concatenating affines if possible
+ return self._b(self._a(points))
+
+class BboxTransform(Affine2D):
+ def __init__(self, boxin, boxout):
+ assert isinstance(boxin, Bbox)
+ assert isinstance(boxout, Bbox)
+
+ Transform.__init__(self)
+ self.add_children([boxin, boxout])
+ self._boxin = boxin
+ self._boxout = boxout
+ self._mtx = None
+ self._inverted = None
+
+ def __repr__(self):
+ return "BboxTransform(%s, %s)" % (self._boxin, self._boxout)
+ __str__ = __repr__
+
+ def _do_invalidation(self):
+ if self._mtx is not None:
+ self._mtx = None
+ Affine2D._do_invalidation(self)
+ return False
+ return True
+
+ def _make__mtx(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
+
+ def __call__(self, points):
+ self._make__mtx()
+ return Affine2D.__call__(self, points)
+
+ def inverted(self):
+ self._make__mtx()
+ return Affine2D.inverted(self)
+
+ def is_separable(self):
+ return True
+
+ def get_matrix(self):
+ self._make__mtx()
+ return self._mtx
- print transform(points)
+def blend_xy_sep_transform(x_transform, y_transform):
+ if x_transform.is_affine() and y_transform.is_affine():
+ return BlendedAffine2D(x_transform, y_transform)
+ return BlendedTransform(x_transform, y_transform)
- transform = Affine2D.identity().scaled(5., 1.).translated(10, 0)
- print transform
- print transform.inverted()
+def composite_transform_factory(a, b):
+ if a.is_affine() and b.is_affine():
+ return CompositeAffine2D(a, b)
+ return CompositeTransform(a, b)
- from bbox import Bbox
- print "BBOX"
- boxin = Bbox([[10, 10], [320, 240]])
- boxout = Bbox([[25, 25], [640, 400]])
- print boxin._points, boxin.xmin(), boxin.ymin(), boxin.xmax(), boxin.ymax()
- print boxout._points, boxout.xmin(), boxout.ymin(), boxout.xmax(), boxout.ymax()
- trans = get_bbox_transform(boxin, boxout)
- print trans
- print trans(N.array([[10, 10], [320, 240]]))
- print trans([[10, 10]])
+# MGDTODO: There's probably a better place for this
+def nonsingular(vmin, vmax, expander=0.001, tiny=1e-15, increasing=True):
+ '''
+ Ensure the endpoints of a range are not too close together.
+
+ "too close" means the interval is smaller than 'tiny' times
+ the maximum absolute value.
+
+ If they are too close, each will be moved by the 'expander'.
+ If 'increasing' is True and vmin > vmax, they will be swapped,
+ regardless of whether they are too close.
+ '''
+ swapped = False
+ if vmax < vmin:
+ vmin, vmax = vmax, vmin
+ swapped = True
+ if vmax - vmin <= max(abs(vmin), abs(vmax)) * tiny:
+ if vmin==0.0:
+ vmin = -expander
+ vmax = expander
+ else:
+ vmin -= expander*abs(vmin)
+ vmax += expander*abs(vmax)
+ if swapped and not increasing:
+ vmin, vmax = vmax, vmin
+ return vmin, vmax
+
+# MGDTODO: Optimize
+def interval_contains(interval, val):
+ return interval[0] <= val and interval[1] >= val
+
+def interval_contains_open(interval, val):
+ return interval[0] < val and interval[1] > val
+if __name__ == '__main__':
+ bbox1 = Bbox([[10., 15.], [20., 25.]])
+ bbox2 = Bbox([[30., 35.], [40., 45.]])
+ trans = BboxTransform(bbox1, bbox2)
+ print trans(bbox1._points)
+
+ bbox2.intervalx = 50, 55
+ print trans(bbox1._points)
+
__all__ = ['Transform', 'Affine2D']
Modified: branches/transforms/lib/matplotlib/artist.py
===================================================================
--- branches/transforms/lib/matplotlib/artist.py 2007-09-12 07:04:38 UTC (rev 3834)
+++ branches/transforms/lib/matplotlib/artist.py 2007-09-12 13:36:25 UTC (rev 3835)
@@ -138,7 +138,6 @@
ACCEPTS: a matplotlib.transform transformation instance
"""
- print "set_transform", t
self._transform = t
self._transformSet = True
self.pchanged()
Modified: branches/transforms/lib/matplotlib/axes.py
===================================================================
--- branches/transforms/lib/matplotlib/axes.py 2007-09-12 07:04:38 UTC (rev 3834)
+++ branches/transforms/lib/matplotlib/axes.py 2007-09-12 13:36:25 UTC (rev 3835)
@@ -12,7 +12,6 @@
from matplotlib import affine as maffine
from matplotlib import agg
from matplotlib import axis as maxis
-from matplotlib import bbox as mbbox
from matplotlib import cbook
from matplotlib import collections as mcoll
from matplotlib import colors as mcolors
@@ -33,7 +32,6 @@
iterable = cbook.iterable
is_string_like = cbook.is_string_like
-Wrapper = cbook.Wrapper
def delete_masked_points(*args):
@@ -484,8 +482,8 @@
"""
martist.Artist.__init__(self)
- self._position = rect
- self._originalPosition = rect
+ self._position = maffine.Bbox.from_lbwh(*rect)
+ self._originalPosition = self._position.copy()
self.set_axes(self)
self.set_aspect('auto')
self.set_adjustable('box')
@@ -615,11 +613,11 @@
"""
martist.Artist.set_figure(self, fig)
- l, b, w, h = self._position
- xmin = fig.bbox.xmin()
- xmax = fig.bbox.xmax()
- ymin = fig.bbox.ymin()
- ymax = fig.bbox.ymax()
+ l, b, w, h = self._position.get_bounds()
+ xmin = fig.bbox.xmin
+ xmax = fig.bbox.xmax
+ ymin = fig.bbox.ymin
+ ymax = fig.bbox.ymax
figw = xmax-xmin
figh = ymax-ymin
self.left = l*figw
@@ -627,7 +625,7 @@
self.right = (l+w)*figw
self.top = (b+h)*figh
- self.bbox = mbbox.Bbox.from_lbrt(
+ self.bbox = maffine.Bbox.from_lbrt(
self.left, self.bottom,
self.right, self.top,
)
@@ -639,7 +637,7 @@
set the dataLim and viewLim BBox attributes and the
transData and transAxes Transformation attributes
"""
- Bbox = mbbox.Bbox
+ Bbox = maffine.Bbox
if self._sharex is not None:
left = self._sharex.viewLim.xmin()
right = self._sharex.viewLim.xmax()
@@ -655,11 +653,12 @@
self.viewLim = Bbox.from_lbrt(left, bottom, right, top)
self.dataLim = Bbox.unit()
+ self.dataLim.track = True
- self.transData = maffine.get_bbox_transform(
+ self.transData = maffine.BboxTransform(
self.viewLim, self.bbox)
- self.transAxes = maffine.get_bbox_transform(
- self.dataLim, self.bbox)
+ self.transAxes = maffine.BboxTransform(
+ Bbox.unit(), self.bbox)
print "_set_lim_and_transforms", self.viewLim, self.transData, self.dataLim, self.transAxes, self.bbox
@@ -1184,9 +1183,8 @@
# MGDTODO
## self.dataLim.update_numerix(x, y, -1)
print "update_datalim_numerix", self.dataLim,
- self.dataLim = mbbox.Bbox.from_data(x, y)
+ self.dataLim.update_from_data(x, y)
print self.dataLim
- # MGDTODO side-effects
def _get_verts_in_data_coords(self, trans, xys):
if trans == self.transData:
@@ -1247,7 +1245,7 @@
axis direction reversal that has already been done.
"""
# if image data only just use the datalim
- print "autoscale_view"
+ print "autoscale_view", self._autoscaleon, scalex, scaley
if not self._autoscaleon: return
if (tight or (len(self.images)>0 and
@@ -1504,7 +1502,7 @@
def get_xlim(self):
'Get the x axis range [xmin, xmax]'
- return self.viewLim.intervalx().get_bounds()
+ return self.viewLim.intervalx
def set_xlim(self, xmin=None, xmax=None, emit=True, **kwargs):
@@ -1549,12 +1547,10 @@
# and min(xmin, xmax)<=0):
# raise ValueError('Cannot set nonpositive limits with log transform')
- xmin, xmax = mbbox.nonsingular(xmin, xmax, increasing=False)
+ xmin, xmax = maffine.nonsingular(xmin, xmax, increasing=False)
- # MGDTODO: This is fairly cumbersome
- # MGDTODO: side-effects on x-bounds should propagate
- self.viewLim = mbbox.Bbox.from_lbrt(xmin, self.viewLim.ymin(), xmax, self.viewLim.ymax())
- print 'set_xlim', self.viewLim
+ self.viewLim.intervalx = (xmin, xmax)
+ print 'set_xlim', self.viewLim, xmin, xmax
return xmin, xmax
@@ -1634,7 +1630,7 @@
def get_ylim(self):
'Get the y axis range [ymin, ymax]'
- return self.viewLim.intervaly().get_bounds()
+ return self.viewLim.intervaly
def set_ylim(self, ymin=None, ymax=None, emit=True, **kwargs):
"""
@@ -1677,9 +1673,8 @@
# and min(ymin, ymax)<=0):
# raise ValueError('Cannot set nonpositive limits with log transform')
- ymin, ymax = mbbox.nonsingular(ymin, ymax, increasing=False)
- # MGDTODO: side-effects on y-bounds should propagate
- self.viewLim = mbbox.Bbox.from_lbrt(self.viewLim.xmin(), ymin, self.viewLim.xmax(), ymax)
+ ymin, ymax = maffine.nonsingular(ymin, ymax, increasing=False)
+ self.viewLim.intervaly = (ymin, ymax)
if emit: self.callbacks.process('ylim_changed', self)
print "set_ylim", self.viewLim
Modified: branches/transforms/lib/matplotlib/axis.py
===================================================================
--- branches/transforms/lib/matplotlib/axis.py 2007-09-12 07:04:38 UTC (rev 3834)
+++ branches/transforms/lib/matplotlib/axis.py 2007-09-12 13:36:25 UTC (rev 3835)
@@ -15,8 +15,8 @@
from ticker import NullFormatter, FixedFormatter, ScalarFormatter, LogFormatter
from ticker import NullLocator, FixedLocator, LinearLocator, LogLocator, AutoLocator
-from affine import Affine2D, blend_xy_sep_transform
-from bbox import bbox_union
+from affine import Affine2D, Bbox, blend_xy_sep_transform, interval_contains, \
+ interval_contains_open
from font_manager import FontProperties
from text import Text, TextWithDash, _process_text_args
from patches import bbox_artist
@@ -160,7 +160,7 @@
def draw(self, renderer):
if not self.get_visible(): return
renderer.open_group(self.__name__)
- midPoint = self.get_view_interval().contains_open( self.get_loc() )
+ midPoint = interval_contains_open(self.get_view_interval(), self.get_loc() )
if midPoint:
if self.gridOn: self.gridline.draw(renderer)
@@ -239,7 +239,7 @@
trans = blend_xy_sep_transform(
self.axes.transData, self.axes.transAxes)
#offset the text downward with a post transformation
- trans = trans + Affine2D().translated(0, -1 * self._padPixels)
+ trans = trans + Affine2D().translate(0, -1 * self._padPixels)
t.set_transform(trans)
self._set_artist_props(t)
@@ -264,7 +264,7 @@
trans = blend_xy_sep_transform(
self.axes.transData, self.axes.transAxes)
# offset the text upward with a post transformation
- trans = trans + Affine2D().translated(0, self._padPixels)
+ trans = trans + Affine2D().translate(0, self._padPixels)
t.set_transform( trans )
self._set_artist_props(t)
return t
@@ -331,11 +331,11 @@
def get_view_interval(self):
'return the Interval instance for this axis view limits'
- return self.axes.viewLim.intervalx()
+ return self.axes.viewLim.intervalx
def get_data_interval(self):
'return the Interval instance for this axis data limits'
- return self.axes.dataLim.intervalx()
+ return self.axes.dataLim.intervalx
class YTick(Tick):
@@ -362,7 +362,7 @@
trans = blend_xy_sep_transform(
self.axes.transAxes, self.axes.transData)
# offset the text leftward with a post transformation
- trans = trans + Affine2D().translated(-1 * self._padPixels, 0)
+ trans = trans + Affine2D().translate(-1 * self._padPixels, 0)
t.set_transform( trans )
#t.set_transform( self.axes.transData )
@@ -385,7 +385,7 @@
trans = blend_xy_sep_transform(
self.axes.transAxes, self.axes.transData)
# offset the text rightward with a post transformation
- trans = trans + Affine2D().translated(self._padPixels, 0)
+ trans = trans + Affine2D().translate(self._padPixels, 0)
t.set_transform( trans )
self._set_artist_props(t)
return t
@@ -455,11 +455,11 @@
def get_view_interval(self):
'return the Interval instance for this axis view limits'
- return self.axes.viewLim.intervaly()
+ return self.axes.viewLim.intervaly
def get_data_interval(self):
'return the Interval instance for this axis data limits'
- return self.axes.dataLim.intervaly()
+ return self.axes.dataLim.intervaly
class Ticker:
@@ -575,7 +575,7 @@
interval = self.get_view_interval()
for tick, loc, label in zip(majorTicks, majorLocs, majorLabels):
if tick is None: continue
- if not interval.contains(loc): continue
+ if not interval_contains(interval, loc): continue
seen[loc] = 1
tick.update_position(loc)
tick.set_label1(label)
@@ -1034,19 +1034,19 @@
bottom = self.axes.bbox.ymin()
else:
- bbox = bbox_union(bboxes)
- bottom = bbox.ymin()
+ bbox = Bbox.union(bboxes)
+ bottom = bbox.ymin
self.label.set_position( (x, bottom-self.LABELPAD*self.figure.dpi/72.0))
# self.label.set_position( (x, bottom-self.LABELPAD*self.figure.dpi.get()/72.0)) MGDTODO
else:
if not len(bboxes2):
- top = self.axes.bbox.ymax()
+ top = self.axes.bbox.ymax
else:
bbox = bbox_union(bboxes2)
- top = bbox.ymax()
+ top = bbox.ymax
self.label.set_position( (x, top+self.LABELPAD*self.figure.dpi.get()/72.0))
@@ -1059,8 +1059,8 @@
if not len(bboxes):
bottom = self.axes.bbox.ymin()
else:
- bbox = bbox_union(bboxes)
- bottom = bbox.ymin()
+ bbox = Bbox.union(bboxes)
+ bottom = bbox.ymin
self.offsetText.set_position((x, bottom-self.OFFSETTEXTPAD*self.figure.dpi/72.0))
# self.offsetText.set_position((x, bottom-self.OFFSETTEXTPAD*self.figure.dpi.get()/72.0)) MGDTODO
@@ -1133,11 +1133,11 @@
def get_view_interval(self):
'return the Interval instance for this axis view limits'
- return self.axes.viewLim.intervalx()
+ return self.axes.viewLim.intervalx
def get_data_interval(self):
'return the Interval instance for this axis data limits'
- return self.axes.dataLim.intervalx()
+ return self.axes.dataLim.intervalx
class YAxis(Axis):
@@ -1223,11 +1223,11 @@
x,y = self.label.get_position()
if self.label_position == 'left':
if not len(bboxes):
- left = self.axes.bbox.xmin()
+ left = self.axes.bbox.xmin
else:
- bbox = bbox_union(bboxes)
- left = bbox.xmin()
+ bbox = Bbox.union(bboxes)
+ left = bbox.xmin
self.label.set_position( (left-self.LABELPAD*self.figure.dpi/72.0, y))
# self.label.set_position( (left-self.LABELPAD*self.figure.dpi.get()/72.0, y)) MGDTODO
@@ -1248,7 +1248,7 @@
boxes of all the ticklabels
"""
x,y = self.offsetText.get_position()
- top = self.axes.bbox.ymax()
+ top = self.axes.bbox.ymax
self.offsetText.set_position((x, top+self.OFFSETTEXTPAD*self.figure.dpi/72.0))
# self.offsetText.set_position((x, top+self.OFFSETTEXTPAD*self.figure.dpi.get()/72.0)) MGDTODO
@@ -1335,11 +1335,11 @@
def get_view_interval(self):
'return the Interval instance for this axis view limits'
- return self.axes.viewLim.intervaly()
+ return self.axes.viewLim.intervaly
def get_data_interval(self):
'return the Interval instance for this axis data limits'
- return self.axes.dataLim.intervaly()
+ return self.axes.dataLim.intervaly
Modified: branches/transforms/lib/matplotlib/backends/backend_agg.py
===================================================================
--- branches/transforms/lib/matplotlib/backends/backend_agg.py 2007-09-12 07:04:38 UTC (rev 3834)
+++ branches/transforms/lib/matplotlib/backends/backend_agg.py 2007-09-12 13:36:25 UTC (rev 3835)
@@ -84,7 +84,7 @@
from matplotlib.font_manager import findfont
from matplotlib.ft2font import FT2Font, LOAD_DEFAULT
from matplotlib.mathtext import MathTextParser
-from matplotlib.bbox import Bbox
+from matplotlib.affine import Bbox
from _backend_agg import RendererAgg as _RendererAgg
Modified: branches/transforms/lib/matplotlib/backends/backend_tkagg.py
===================================================================
--- branches/transforms/lib/matplotlib/backends/backend_tkagg.py 2007-09-12 07:04:38 UTC (rev 3834)
+++ branches/transforms/lib/matplotlib/backends/backend_tkagg.py 2007-09-12 13:36:25 UTC (rev 3835)
@@ -219,13 +219,13 @@
def motion_notify_event(self, event):
x = event.x
# flipy so y=0 is bottom of canvas
- y = self.figure.bbox.height() - event.y
+ y = self.figure.bbox.height - event.y
FigureCanvasBase.motion_notify_event(self, x, y, guiEvent=event)
def button_press_event(self, event):
x = event.x
# flipy so y=0 is bottom of canvas
- y = self.figure.bbox.height() - event.y
+ y = self.figure.bbox.height - event.y
num = getattr(event, 'num', None)
if sys.platform=='darwin':
@@ -239,7 +239,7 @@
def button_release_event(self, event):
x = event.x
# flipy so y=0 is bottom of canvas
- y = self.figure.bbox.height() - event.y
+ y = self.figure.bbox.height - event.y
num = getattr(event, 'num', None)
@@ -609,7 +609,7 @@
return b
def _init_toolbar(self):
- xmin, xmax = self.canvas.figure.bbox.intervalx().get_bounds()
+ xmin, xmax = self.canvas.figure.bbox.intervalx
height, width = 50, xmax-xmin
Tk.Frame.__init__(self, master=self.window,
width=width, height=height,
Deleted: branches/transforms/lib/matplotlib/bbox.py
===================================================================
--- branches/transforms/lib/matplotlib/bbox.py 2007-09-12 07:04:38 UTC (rev 3834)
+++ branches/transforms/lib/matplotlib/bbox.py 2007-09-12 13:36:25 UTC (rev 3835)
@@ -1,161 +0,0 @@
-"""
-A convenience class for handling bounding boxes
-
-2007 Michael Droettboom
-"""
-
-import numpy as N
-
-class Interval:
- def __init__(self, bounds):
- self._bounds = N.array(bounds, N.float_)
-
- def contains(self, value):
- bounds = self._bounds
- return value >= bounds[0] and value <= bounds[1]
-
- def contains_open(self, value):
- bounds = self._bounds
- return value > bounds[0] and value < bounds[1]
-
- def get_bounds(self):
- return self._bounds
-
- def span(self):
- bounds = self._bounds
- return bounds[1] - bounds[0]
-
-class Bbox:
- def __init__(self, points):
- self._points = N.array(points, N.float_)
-
- #@staticmethod
- def unit():
- return Bbox([[0,0], [1,1]])
- unit = staticmethod(unit)
-
- #@staticmethod
- def from_lbwh(left, bottom, width, height):
- return Bbox([[left, bottom], [left + width, bottom + height]])
- from_lbwh = staticmethod(from_lbwh)
-
- #@staticmethod
- def from_lbrt(left, bottom, right, top):
- return Bbox([[left, bottom], [right, top]])
- from_lbrt = staticmethod(from_lbrt)
-
- #@staticmethod
- def from_data(x, y):
- return Bbox([[x.min(), y.min()], [x.max(), y.max()]])
- from_data = staticmethod(from_data)
-
- def copy(self):
- return Bbox(self._points.copy())
-
- def __repr__(self):
- return 'Bbox(%s)' % repr(self._points)
- __str__ = __repr__
-
- def __cmp__(self, other):
- # MGDTODO: Totally suboptimal
- if isinstance(other, Bbox):
- return (self._points == other._points).all()
- return -1
-
- # MGDTODO: Probably a more efficient ways to do this...
- def xmin(self):
- return self._points[0,0]
-
- def ymin(self):
- return self._points[0,1]
-
- def xmax(self):
- return self._points[1,0]
-
- def ymax(self):
- return self._points[1,1]
-
- def width(self):
- return self.xmax() - self.xmin()
-
- def height(self):
- return self.ymax() - self.ymin()
-
- def transform(self, transform):
- return Bbox(transform(self._points))
-
- def inverse_transform(self, transform):
- return Bbox(transform.inverted()(self._points))
-
- def get_bounds(self):
- return (self.xmin(), self.ymin(),
- self.xmax() - self.xmin(), self.ymax() - self.ymin())
-
- # MGDTODO: This is an inefficient way to do this
- def intervalx(self):
- return Interval(self._points[0])
-
- def intervaly(self):
- return Interval(self._points[1])
-
- def scaled(self, sw, sh):
- width = self.width()
- height = self.height()
- deltaw = (sw * width - width) / 2.0
- deltah = (sh * height - height) / 2.0
- a = N.array([[-deltaw, -deltah], [deltaw, deltah]])
- return Bbox(self._points + a)
-
- def contains(self, x, y):
- return (x >= self.xmin() and x <= self.xmax() and
- y >= self.ymin() and y <= self.ymax())
-
-def bbox_union(bboxes):
- """
- Return the Bbox that bounds all bboxes
- """
- assert(len(bboxes))
-
- if len(bboxes) == 1:
- return bboxes[0]
-
- bbox = bboxes[0]
- xmin = bbox.xmin()
- ymin = bbox.ymin()
- xmax = bbox.xmax()
- ymax = bbox.ymax()
-
- 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())
-
- return Bbox.from_lbrt(xmin, ymin, xmax, ymax)
-
-# MGDTODO: There's probably a better place for this
-def nonsingular(vmin, vmax, expander=0.001, tiny=1e-15, increasing=True):
- '''
- Ensure the endpoints of a range are not too close together.
-
- "too close" means the interval is smaller than 'tiny' times
- the maximum absolute value.
-
- If they are too close, each will be moved by the 'expander'.
- If 'increasing' is True and vmin > vmax, they will be swapped,
- regardless of whether they are too close.
- '''
- swapped = False
- if vmax < vmin:
- vmin, vmax = vmax, vmin
- swapped = True
- if vmax - vmin <= max(abs(vmin), abs(vmax)) * tiny:
- if vmin==0.0:
- vmin = -expander
- vmax = expander
- else:
- vmin -= expander*abs(vmin)
- vmax += expander*abs(vmax)
- if swapped and not increasing:
- vmin, vmax = vmax, vmin
- return vmin, vmax
Modified: branches/transforms/lib/matplotlib/figure.py
===================================================================
--- branches/transforms/lib/matplotlib/figure.py 2007-09-12 07:04:38 UTC (rev 3834)
+++ branches/transforms/lib/matplotlib/figure.py 2007-09-12 13:36:25 UTC (rev 3835)
@@ -18,8 +18,7 @@
from text import Text, _process_text_args
from legend import Legend
-from affine import get_bbox_transform
-from bbox import Bbox
+from affine import Bbox, BboxTransform
from ticker import FormatStrFormatter
from cm import ScalarMappable
from contour import ContourSet
@@ -105,7 +104,7 @@
class Figure(Artist):
def __str__(self):
- return "Figure(%gx%g)"%(self.figwidth, self.figheight)
+ return "Figure(%gx%g)"%(self.bbox.max)
# return "Figure(%gx%g)"%(self.figwidth.get(),self.figheight.get())
def __init__(self,
@@ -130,13 +129,13 @@
if edgecolor is None: edgecolor = rcParams['figure.edgecolor']
self.dpi = dpi
- self.figwidth = figsize[0] * dpi
- self.figheight = figsize[1] * dpi
- self.bbox = Bbox.from_lbwh(0, 0, self.figwidth, self.figheight)
+ figwidth = figsize[0] * dpi
+ figheight = figsize[1] * dpi
+ self.bbox = Bbox.from_lbwh(0, 0, figwidth, figheight)
self.frameon = frameon
- self.transFigure = get_bbox_transform( Bbox.unit(), self.bbox)
+ self.transFigure = BboxTransform( Bbox.unit(), self.bbox)
@@ -325,9 +324,9 @@
else:
w,h = args
-
- self.figwidth = w
- self.figheight = h
+ dpival = self.dpi
+ self.bbox.max = w * dpival, h * dpival
+ print self.bbox
# self.figwidth.set(w) MGDTODO
# self.figheight.set(h)
@@ -341,7 +340,7 @@
manager.resize(int(canvasw), int(canvash))
def get_size_inches(self):
- return self.figwidth, self.figheight
+ return self.bbox.max
# return self.figwidth.get(), self.figheight.get() MGDTODO
def get_edgecolor(self):
@@ -354,12 +353,12 @@
def get_figwidth(self):
'Return the figwidth as a float'
- return self.figwidth
+ return self.bbox.xmax
# return self.figwidth.get() MGDTODO
def get_figheight(self):
'Return the figheight as a float'
- return self.figheight.get()
+ return self.bbox.ymax
def get_dpi(self):
'Return the dpi as a float'
@@ -402,7 +401,7 @@
ACCEPTS: float
"""
# self.figwidth.set(val) MGDTODO
- self.figwidth = val
+ self.bbox.xmax = val
def set_figheight(self, val):
"""
@@ -411,7 +410,7 @@
ACCEPTS: float
"""
# MGDTODO (set())
- self.figheight = val
+ self.bbox.ymax = val
def set_frameon(self, b):
"""
Modified: branches/transforms/lib/matplotlib/legend.py
===================================================================
--- branches/transforms/lib/matplotlib/legend.py 2007-09-12 07:04:38 UTC (rev 3834)
+++ branches/transforms/lib/matplotlib/legend.py 2007-09-12 13:36:25 UTC (rev 3835)
@@ -34,8 +34,7 @@
from patches import Patch, Rectangle, RegularPolygon, Shadow, bbox_artist, draw_bbox
from collections import LineCollection, RegularPolyCollection, PatchCollection
from text import Text
-from affine import get_bbox_transform
-from bbox import Bbox, bbox_union
+from affine import Bbox, BboxTransform
def line_cuts_bbox(line, bbox):
""" Return True if and only if line cuts bbox. """
@@ -165,7 +164,7 @@
else:
raise TypeError("Legend needs either Axes or Figure as parent")
self.parent = parent
- self.set_transform( get_bbox_transform( Bbox.unit(), parent.bbox) )
+ self.set_transform( BboxTransform( Bbox.unit(), parent.bbox) )
if loc is None:
loc = rcParams["legend.loc"]
@@ -260,10 +259,10 @@
bboxesAll = bboxesText
bboxesAll.extend(bboxesHandles)
- bbox = bbox_union(bboxesAll)
+ bbox = Bbox.union(bboxesAll)
self.save = bbox
- ibox = bbox.inverse_transform(self.get_transform())
+ ibox = bbox.inverse_transformed(self.get_transform())
self.ibox = ibox
return ibox
@@ -531,7 +530,7 @@
if not len(self.legendHandles) and not len(self.texts): return
def get_tbounds(text): #get text bounds in axes coords
bbox = text.get_window_extent(renderer)
- bboxa = bbox.inverse_transform(self.get_transform())
+ bboxa = bbox.inverse_transformed(self.get_transform())
return bboxa.get_bounds()
hpos = []
Modified: branches/transforms/lib/matplotlib/lines.py
===================================================================
--- branches/transforms/lib/matplotlib/lines.py 2007-09-12 07:04:38 UTC (rev 3834)
+++ branches/transforms/lib/matplotlib/lines.py 2007-09-12 13:36:25 UTC (rev 3835)
@@ -14,11 +14,11 @@
import numerix.ma as ma
from matplotlib import verbose
import artist
+from affine import Bbox
from artist import Artist, setp
from cbook import iterable, is_string_like, is_numlike
from colors import colorConverter
-from bbox import Bbox
from matplotlib import rcParams
# special-purpose marker identifiers:
Modified: branches/transforms/lib/matplotlib/table.py
===================================================================
--- branches/transforms/lib/matplotlib/table.py 2007-09-12 07:04:38 UTC (rev 3834)
+++ branches/transforms/lib/matplotlib/table.py 2007-09-12 13:36:25 UTC (rev 3835)
@@ -29,7 +29,7 @@
from patches import Rectangle
from cbook import enumerate, is_string_like, flatten
from text import Text
-from bbox import Bbox, bbox_union
+from affine import Bbox
@@ -130,7 +130,7 @@
def get_text_bounds(self, renderer):
""" Get text bounds in axes co-ordinates. """
bbox = self._text.get_window_extent(renderer)
- bbox.inverse_transform(self.get_transform())
+ bboxa = bbox.inverse_transformed(self.get_transform())
return bboxa.get_bounds()
def get_required_width(self, renderer):
Modified: branches/transforms/lib/matplotlib/text.py
===================================================================
--- branches/transforms/lib/matplotlib/text.py 2007-09-12 07:04:38 UTC (rev 3834)
+++ branches/transforms/lib/matplotlib/text.py 2007-09-12 13:36:25 UTC (rev 3835)
@@ -15,7 +15,7 @@
from cbook import enumerate, is_string_like, maxdict, is_numlike
from font_manager import FontProperties
from patches import bbox_artist, YAArrow
-from bbox import Bbox, bbox_union
+from affine import Bbox
from lines import Line2D
import matplotlib.nxutils as nxutils
Modified: branches/transforms/lib/matplotlib/ticker.py
===================================================================
--- branches/transforms/lib/matplotlib/ticker.py 2007-09-12 07:04:38 UTC (rev 3834)
+++ branches/transforms/lib/matplotlib/ticker.py 2007-09-12 13:36:25 UTC (rev 3835)
@@ -115,7 +115,7 @@
import matplotlib as mpl
from matplotlib import verbose, rcParams
from matplotlib import cbook
-from matplotlib import bbox as mbbox
+from matplotlib import affine as maffine
@@ -148,8 +148,9 @@
cases where the Intervals do not need to be updated
automatically.
'''
- self.dataInterval = mbbox.Interval([vmin, vmax])
- self.viewInterval = mbbox.Interval([vmin, vmax])
+ # MGDTODO: Interval no longer exists
+ self.dataInterval = maffine.Interval([vmin, vmax])
+ self.viewInterval = maffine.Interval([vmin, vmax])
class Formatter(TickHelper):
"""
@@ -341,7 +342,8 @@
self.locs = locs
if len(self.locs) > 0:
self.verify_intervals()
- d = abs(self.viewInterval.span())
+ vmin, vmax = self.viewInterval
+ d = abs(vmax - vmin)
if self._useOffset: self._set_offset(d)
self._set_orderOfMagnitude(d)
self._set_format()
@@ -571,7 +573,7 @@
def autoscale(self):
'autoscale the view limits'
self.verify_intervals()
- return mbbox.nonsingular(*self.dataInterval.get_bounds())
+ return maffine.nonsingular(*self.dataInterval.get_bounds())
def pan(self, numsteps):
'Pan numticks (can be positive or negative)'
@@ -713,7 +715,7 @@
vmin = math.floor(scale*vmin)/scale
vmax = math.ceil(scale*vmax)/scale
- return mbbox.nonsingular(vmin, vmax)
+ return maffine.nonsingular(vmin, vmax)
def closeto(x,y):
@@ -797,7 +799,7 @@
vmin -=1
vmax +=1
- return mbbox.nonsingular(vmin, vmax)
+ return maffine.nonsingular(vmin, vmax)
def scale_range(vmin, vmax, n = 1, threshold=100):
dv = abs(vmax - vmin)
@@ -864,14 +866,14 @@
def __call__(self):
self.verify_intervals()
- vmin, vmax = self.viewInterval.get_bounds()
- vmin, vmax = mbbox.nonsingular(vmin, vmax, expander = 0.05)
+ vmin, vmax = self.viewInterval
+ vmin, vmax = maffine.nonsingular(vmin, vmax, expander = 0.05)
return self.bin_boundaries(vmin, vmax)
def autoscale(self):
self.verify_intervals()
- dmin, dmax = self.dataInterval.get_bounds()
- dmin, dmax = mbbox.nonsingular(dmin, dmax, expander = 0.05)
+ dmin, dmax = self.dataInterval
+ dmin, dmax = maffine.nonsingular(dmin, dmax, expander = 0.05)
return npy.take(self.bin_boundaries(dmin, dmax), [0,-1])
@@ -972,7 +974,7 @@
if vmin==vmax:
vmin = decade_down(vmin,self._base)
vmax = decade_up(vmax,self._base)
- return mbbox.nonsingular(vmin, vmax)
+ return maffine.nonsingular(vmin, vmax)
class AutoLocator(MaxNLocator):
def __init__(self):
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|