Revision: 3859
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3859&view=rev
Author:   mdboom
Date:     2007-09-19 12:46:34 -0700 (Wed, 19 Sep 2007)

Log Message:
-----------
Lots of minor fixes

Modified Paths:
--------------
    branches/transforms/lib/matplotlib/lines.py
    branches/transforms/lib/matplotlib/patches.py
    branches/transforms/lib/matplotlib/path.py
    branches/transforms/lib/matplotlib/pbox.py
    branches/transforms/lib/matplotlib/text.py
    branches/transforms/lib/matplotlib/transforms.py

Modified: branches/transforms/lib/matplotlib/lines.py
===================================================================
--- branches/transforms/lib/matplotlib/lines.py 2007-09-19 16:18:51 UTC (rev 
3858)
+++ branches/transforms/lib/matplotlib/lines.py 2007-09-19 19:46:34 UTC (rev 
3859)
@@ -252,12 +252,9 @@
         if not is_numlike(self.pickradius):
             raise ValueError,"pick radius should be a distance"
 
-        if self._newstyle:
-            # transform in backend
-            x = self._x
-            y = self._y
-        else:
-            x, y = self._get_plottable()
+        # transform in backend
+        x = self._x
+        y = self._y
         if len(x)==0: return False,{}
 
         xt, yt = self.get_transform().numerix_x_y(x, y)
@@ -337,7 +334,6 @@
 
         ACCEPTS: (npy.array xdata, npy.array ydata)
         """
-
         if len(args)==1:
             x, y = args[0]
         else:
@@ -347,8 +343,9 @@
         self._yorig = y
         self.recache()
 
+    # MGDTODO: Masked data arrays are broken
     _masked_array_to_path_code_mapping = npy.array(
-        [Path.LINETO, Path.IGNORE, Path.MOVETO], Path.code_type)
+        [Path.LINETO, Path.MOVETO, Path.MOVETO], Path.code_type)
     def recache(self):
         #if self.axes is None: print 'recache no axes'
         #else: print 'recache units', self.axes.xaxis.units, 
self.axes.yaxis.units
@@ -387,18 +384,18 @@
         # MGDTODO: If _draw_steps is removed, remove the following line also
         self._step_path = None
         
-
     def _is_sorted(self, x):
         "return true if x is sorted"
         if len(x)<2: return 1
         return npy.alltrue(x[1:]-x[0:-1]>=0)
 
+    # MGDTODO: Remove me (seems to be used for old-style interface only)
     def _get_plottable(self):
         # If log scale is set, only pos data will be returned
 
         x, y = self._x, self._y
 
-       # MGDTODO: Deal with the log scale here
+       # MGDTODO: (log-scaling)
        
 #         try: logx = self.get_transform().get_funcx().get_type()==LOG10
 #         except RuntimeError: logx = False  # non-separable

Modified: branches/transforms/lib/matplotlib/patches.py
===================================================================
--- branches/transforms/lib/matplotlib/patches.py       2007-09-19 16:18:51 UTC 
(rev 3858)
+++ branches/transforms/lib/matplotlib/patches.py       2007-09-19 19:46:34 UTC 
(rev 3859)
@@ -319,8 +319,6 @@
         return str(self.__class__).split('.')[-1] \
             + "(%g,%g;%gx%g)"%(self.xy[0],self.xy[1],self.width,self.height)
 
-    # MGDTODO: Perhaps pass in a Bbox here instead, then the updates will
-    # happen automatically (without needing to call set_x etc.
     def __init__(self, xy, width, height, **kwargs):
         """
         xy is an x,y tuple lower, left
@@ -459,17 +457,14 @@
 
     def __init__(self, xy, **kwargs):
         """
-        xy is a sequence of (x,y) 2 tuples
+        xy is a numpy array with shape Nx2
 
         Valid kwargs are:
         %(Patch)s
         See Patch documentation for additional kwargs
         """
-       # MGDTODO: This should encourage the use of numpy arrays of shape Nx2
         Patch.__init__(self, **kwargs)
-        if not isinstance(xy, list):
-            xy = list(xy)
-       self._path = Path(xy, closed=False)
+       self._path = Path(xy, closed=True)
     __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd
 
     def get_verts(self):

Modified: branches/transforms/lib/matplotlib/path.py
===================================================================
--- branches/transforms/lib/matplotlib/path.py  2007-09-19 16:18:51 UTC (rev 
3858)
+++ branches/transforms/lib/matplotlib/path.py  2007-09-19 19:46:34 UTC (rev 
3859)
@@ -1,15 +1,13 @@
 import numpy as npy
 
-DEBUG = True
-
 class Path(object):
     # Path codes
-    IGNORE    = 0 # 1 vertex
+    STOP      = 0 # 1 vertex
     MOVETO    = 1 # 1 vertex
     LINETO    = 2 # 1 vertex
     CURVE3    = 3 # 2 vertices
     CURVE4    = 4 # 3 vertices
-    CLOSEPOLY = 5
+    CLOSEPOLY = 5 # 1 vertex
     ###
     # MGDTODO: I'm not sure these are supported by PS/PDF/SVG,
     # so if they don't, we probably shouldn't
@@ -18,38 +16,36 @@
     UBSPLINE  = 8
     ####
 
-    NUM_VERTICES = [1, 1, 1, 2, 3, 0]
+    NUM_VERTICES = [1, 1, 1, 2, 3, 1]
     
     code_type = npy.uint8
     
     def __init__(self, vertices, codes=None, closed=True):
-       self._vertices = npy.asarray(vertices, npy.float_)
-       assert self._vertices.ndim == 2
-       assert self._vertices.shape[1] == 2
-
+        vertices = npy.asarray(vertices, npy.float_)
+       assert vertices.ndim == 2
+       assert vertices.shape[1] == 2
+        
        if codes is None:
            if closed:
                codes = self.LINETO * npy.ones(
-                   self._vertices.shape[0] + 1, self.code_type)
+                   vertices.shape[0] + 1, self.code_type)
                codes[0] = self.MOVETO
-               codes[-1] = self.CLOSEPOLY
+                codes[-1] = self.CLOSEPOLY
+                vertices = npy.concatenate((vertices, [[0.0, 0.0]]))
            else:
                codes = self.LINETO * npy.ones(
-                   self._vertices.shape[0], self.code_type)
+                   vertices.shape[0], self.code_type)
                codes[0] = self.MOVETO
         else:
            codes = npy.asarray(codes, self.code_type)
-       self._codes = codes
-           
+            assert codes.ndim == 1
+            assert len(codes) == len(vertices)
+
+        self._codes = codes
+       self._vertices = vertices
+        
        assert self._codes.ndim == 1
 
-       if DEBUG:
-           i = 0
-           NUM_VERTICES = self.NUM_VERTICES
-           for code in codes:
-               i += NUM_VERTICES[code]
-           assert i == len(self.vertices)
-
     def __repr__(self):
        return "Path(%s, %s)" % (self.vertices, self.codes)
            
@@ -66,11 +62,13 @@
        NUM_VERTICES = self.NUM_VERTICES
        vertices = self.vertices
        for code in self.codes:
-           num_vertices = NUM_VERTICES[code]
-           if num_vertices >= 1:
-               i += num_vertices - 1
-               yield vertices[i]
-               i += 1
+            if code == self.CLOSEPOLY:
+                i += 1
+            else:
+                num_vertices = NUM_VERTICES[code]
+                i += num_vertices - 1
+                yield vertices[i]
+                i += 1
 
     _unit_rectangle = None
     [EMAIL PROTECTED]
@@ -118,16 +116,18 @@
                 
                 [-offset, -1.0],
                 [-1.0, -offset],
-                [-1.0, 0.0]],
-               npy.float_)
-           codes = npy.array(
-               [cls.MOVETO,
-                cls.CURVE4,
-                cls.CURVE4,
-                cls.CURVE4,
-                cls.CURVE4,
-                cls.CLOSEPOLY],
-               cls.code_type)
+                [-1.0, 0.0],
+
+                 [-1.0, 0.0]],
+                npy.float_)
+
+            codes = cls.CURVE4 + npy.ones((len(vertices)))
+           codes[0] = cls.MOVETO
+            codes[-1] = cls.CLOSEPOLY
+
            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/pbox.py
===================================================================
--- branches/transforms/lib/matplotlib/pbox.py  2007-09-19 16:18:51 UTC (rev 
3858)
+++ branches/transforms/lib/matplotlib/pbox.py  2007-09-19 19:46:34 UTC (rev 
3859)
@@ -1,5 +1,3 @@
-# MGDTODO: Just included verbatim for now
-
 class PBox(list):
     '''
     A left-bottom-width-height (lbwh) specification of a bounding box,

Modified: branches/transforms/lib/matplotlib/text.py
===================================================================
--- branches/transforms/lib/matplotlib/text.py  2007-09-19 16:18:51 UTC (rev 
3858)
+++ branches/transforms/lib/matplotlib/text.py  2007-09-19 19:46:34 UTC (rev 
3859)
@@ -231,7 +231,7 @@
 
         # now rotate the bbox
 
-        cornersRotated = M(cornersHoriz)
+        cornersRotated = M.transform(cornersHoriz)
 
         txs = cornersRotated[:, 0]
         tys = cornersRotated[:, 1]
@@ -269,7 +269,7 @@
        
 
         # now rotate the positions around the first x,y position
-        xys = M(offsetLayout)
+        xys = M.transform(offsetLayout)
        tx = xys[:, 0]
        ty = xys[:, 1]
        tx += offsetx
@@ -277,7 +277,7 @@
 
         # now inverse transform back to data coords
        inverse_transform = self.get_transform().inverted()
-        xys = inverse_transform(xys)
+        xys = inverse_transform.transform(xys)
 
         xs, ys = zip(*xys)
 
@@ -407,7 +407,7 @@
         return (x, y, self._text, self._color,
                 self._verticalalignment, self._horizontalalignment,
                 hash(self._fontproperties), self._rotation,
-                self.get_transform().to_values(),
+                self.get_transform(),
                 )
 
     def get_text(self):

Modified: branches/transforms/lib/matplotlib/transforms.py
===================================================================
--- branches/transforms/lib/matplotlib/transforms.py    2007-09-19 16:18:51 UTC 
(rev 3858)
+++ branches/transforms/lib/matplotlib/transforms.py    2007-09-19 19:46:34 UTC 
(rev 3859)
@@ -32,7 +32,8 @@
         for child in children:
             getattr(self, child)._parents.add(self)
         self._children = children
-            
+
+        
 class BboxBase(TransformNode):
     '''
     This is the read-only part of a bounding-box
@@ -293,6 +294,7 @@
         return Bbox.from_lbrt(xmin, ymin, xmax, ymax)
     union = staticmethod(union)
 
+    
 class TransformedBbox(BboxBase):
     def __init__(self, bbox, transform):
         assert isinstance(bbox, Bbox)
@@ -313,16 +315,20 @@
 
     def get_points(self):
         if self._points is None:
-            self._points = self.transform(self.bbox.get_points())
+            self._points = self.transform.transform(self.bbox.get_points())
         return self._points
+
     
 class Transform(TransformNode):
     def __init__(self):
         TransformNode.__init__(self)
     
-    def __call__(self, points):
+    def transform(self, points):
         raise NotImplementedError()
 
+    def transform_without_affine(self, points):
+        return self.transform(points), IDENTITY
+    
     def __add__(self, other):
         if isinstance(other, Transform):
             return composite_transform_factory(self, other)
@@ -336,7 +342,7 @@
             "Can not add Transform to object of type '%s'" % type(other))
 
     def transform_point(self, point):
-        return self.__call__(npy.asarray([point]))[0]
+        return self.transform(npy.asarray([point]))[0]
     
     def has_inverse(self):
         raise NotImplementedError()
@@ -350,6 +356,7 @@
     def is_affine(self):
         return False
 
+    
 class Affine2DBase(Transform):
     input_dims = 2
     output_dims = 2
@@ -390,7 +397,7 @@
     def get_matrix(self):
         raise NotImplementedError()
     
-    def __call__(self, points):
+    def transform(self, points):
         """
         Applies the transformation to an array of 2D points and
         returns the result.
@@ -414,6 +421,11 @@
         points = npy.dot(mtx[0:2, 0:2], points)
         points = points + mtx[0:2, 2:]
         return points.transpose()
+
+    def transform_without_affine(self, points):
+        # MGDTODO: Should we copy the points here?  I'd like to avoid it,
+        # if possible
+        return points, self
     
     def inverted(self):
         if self._inverted is None:
@@ -430,9 +442,6 @@
 
         
 class Affine2D(Affine2DBase):
-    input_dims = 2
-    output_dims = 2
-    
     def __init__(self, matrix = None):
         """
         Initialize an Affine transform from a 3x3 numpy float array.
@@ -535,40 +544,82 @@
 
     def is_affine(self):
         return True
+
+IDENTITY = Affine2D()
     
 class BlendedGenericTransform(Transform):
+    input_dims = 2
+    output_dims = 2
+
     def __init__(self, x_transform, y_transform):
        # Here we ask: "Does it blend?"
         assert x_transform.is_separable()
         assert y_transform.is_separable()
-
+        assert x_transform.input_dims == x_transform.output_dims == 2
+        assert y_transform.input_dims == y_transform.output_dims == 2
+        
         Transform.__init__(self)
         self._x = x_transform
         self._y = y_transform
         self.set_children(['_x', '_y'])
 
-    def __call__(self, points):
-        if self._x == self._y:
+    def transform(self, points):
+        # MGDTODO: Optimize the case where one of these is
+        # an affine
+        x = self._x
+        y = self._y
+        if x == y and x.input_dims == 2:
             return self._x(points)
-        
-        x_points = self._x(points)
-        y_points = self._y(points)
-        # This works because we already know the transforms are
-        # separable
-        return npy.hstack((x_points[:, 0:1], y_points[:, 1:2]))
 
-#     def set_x_transform(self, x_transform):
-#         self.replace_child(0, x_transform)
+        if x.input_dims == 2:
+            x_points = x.transform(points)[:, 0]
+        else:
+            x_points = x.transform(points[:, 0])
 
-#     def set_y_transform(self, y_transform):
-#         self.replace_child(1, y_transform)
+        if y.input_dims == 2:
+            y_points = y.transform(points)[:, 1]
+        else:
+            y_points = y.transform(points[:, 1])
 
+        return npy.vstack((x_points, y_points)).transpose()
+
+    def inverted(self):
+        return BlendedGenericTransform(self._x.inverted(), self._y.inverted())
     
-class BlendedAffine2D(Affine2DBase, BlendedGenericTransform):
+    def is_separable(self):
+        return True
+    
+    
+class BlendedSeparableTransform(Transform):
+    input_dims = 2
+    output_dims = 2
+
     def __init__(self, x_transform, y_transform):
+       # Here we ask: "Does it blend?"
+        assert x_transform.is_separable()
+        assert y_transform.is_separable()
+        assert x_transform.input_dims == x.transform.output_dims == 1
+        assert y_transform.input_dims == y.transform.output_dims == 1
+        
+        Transform.__init__(self)
+        self._x = x_transform
+        self._y = y_transform
+        self.set_children(['_x', '_y'])
+
+    def transform(self, points):
+        x_points = self._x(points[:, 0])
+        y_points = self._y(points[:, 1])
+        return npy.vstack((x_points[:, 0:1], y_points[:, 1:2])).transpose()
+    
+    
+class BlendedAffine2D(Affine2DBase, Transform):
+    def __init__(self, x_transform, y_transform):
         assert x_transform.is_affine()
         assert y_transform.is_affine()
-        BlendedGenericTransform.__init__(self, x_transform, y_transform)
+        Transform.__init__(self)
+        self._x = x_transform
+        self._y = y_transform
+        self.set_children(['_x', '_y'])
         
         Affine2DBase.__init__(self)
         self._mtx = None
@@ -597,12 +648,14 @@
                 # c to zero.
                 self._mtx = npy.vstack((x_mtx[0], y_mtx[1], [0.0, 0.0, 1.0]))
         return self._mtx
-        
+
+    
 def blended_transform_factory(x_transform, y_transform):
     if x_transform.is_affine() and y_transform.is_affine():
         return BlendedAffine2D(x_transform, y_transform)
     return BlendedGenericTransform(x_transform, y_transform)
 
+
 class CompositeGenericTransform(Transform):
     def __init__(self, a, b):
         assert a.output_dims == b.input_dims
@@ -614,9 +667,17 @@
         self._b = b
         self.set_children(['_a', '_b'])
         
-    def __call__(self, points):
-        return self._b(self._a(points))
+    def transform(self, points):
+        return self._b.transform(self._a.transform(points))
+
+    def inverted(self):
+        return CompositeGenericTransform(self._b.inverted(), 
self._a.inverted())
     
+    def is_separable(self):
+        return True
+        return self._a.is_separable() and self._b.is_separable()
+
+    
 class CompositeAffine2D(Affine2DBase):
     def __init__(self, a, b):
         assert a.is_affine()
@@ -643,11 +704,32 @@
                 self._b.get_matrix())
         return self._mtx
 
+    
 def composite_transform_factory(a, b):
     if a.is_affine() and b.is_affine():
         return CompositeAffine2D(a, b)
     return CompositeGenericTransform(a, b)
+
+
+class LogTransform(Transform):
+    input_dims = 1
+    output_dims = 1
     
+    def transform(self, a):
+        m = npy.ma.masked_where(a < 0, a)
+        return npy.log10(m)
+
+
+class TestLogTransform(Transform):
+    input_dims = 2
+    output_dims = 2
+    def transform(self, xy):
+        return xy * 2
+
+    def inverted(self):
+        return self
+
+    
 class BboxTransform(Affine2DBase):
     def __init__(self, boxin, boxout):
         assert isinstance(boxin, BboxBase)
@@ -688,6 +770,7 @@
             self._mtx = affine._mtx
         return self._mtx
 
+    
 def nonsingular(vmin, vmax, expander=0.001, tiny=1e-15, increasing=True):
     '''
     Ensure the endpoints of a range are not too close together.


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2005.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Matplotlib-checkins mailing list
Matplotlib-checkins@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to