Revision: 3947
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=3947&view=rev
Author:   mdboom
Date:     2007-10-15 06:49:25 -0700 (Mon, 15 Oct 2007)

Log Message:
-----------
Significant speed improvement in text layout.  Reverted to fix bug in
ticklabels.  Lots of other minor things.

Modified Paths:
--------------
    branches/transforms/lib/matplotlib/axes.py
    branches/transforms/lib/matplotlib/axis.py
    branches/transforms/lib/matplotlib/collections.py
    branches/transforms/lib/matplotlib/lines.py
    branches/transforms/lib/matplotlib/path.py
    branches/transforms/lib/matplotlib/text.py
    branches/transforms/lib/matplotlib/transforms.py

Modified: branches/transforms/lib/matplotlib/axes.py
===================================================================
--- branches/transforms/lib/matplotlib/axes.py  2007-10-14 21:14:18 UTC (rev 
3946)
+++ branches/transforms/lib/matplotlib/axes.py  2007-10-15 13:49:25 UTC (rev 
3947)
@@ -1037,6 +1037,7 @@
         a.set_axes(self)
         self.artists.append(a)
         self._set_artist_props(a)
+        a.set_clip_path(self.axesPatch)
         a._remove_method = lambda h: self.artists.remove(h)
 
     def add_collection(self, collection, autolim=False):
@@ -1091,6 +1092,7 @@
         'Add a table instance to the list of axes tables'
         self._set_artist_props(tab)
         self.tables.append(tab)
+        tab.set_clip_path(self.axesPatch)
         tab._remove_method = lambda h: self.tables.remove(h)
 
     def relim(self):

Modified: branches/transforms/lib/matplotlib/axis.py
===================================================================
--- branches/transforms/lib/matplotlib/axis.py  2007-10-14 21:14:18 UTC (rev 
3946)
+++ branches/transforms/lib/matplotlib/axis.py  2007-10-15 13:49:25 UTC (rev 
3947)
@@ -91,7 +91,6 @@
         self._size = size
 
         self._padPixels = self.figure.dpi * self._pad * (1/72.0)
-        self._locTransform = Affine2D()
         
         self.tick1line = self._get_tick1line()
         self.tick2line = self._get_tick2line()
@@ -286,7 +285,7 @@
                        markersize=self._size,
                        )
 
-        l.set_transform(self._locTransform + self.axes.get_xaxis_transform())
+        l.set_transform(self.axes.get_xaxis_transform())
         self._set_artist_props(l)
         return l
 
@@ -298,16 +297,20 @@
                    linestyle=rcParams['grid.linestyle'],
                    linewidth=rcParams['grid.linewidth'],
                    )
-        l.set_transform(self._locTransform + self.axes.get_xaxis_transform())
+        l.set_transform(self.axes.get_xaxis_transform())
         self._set_artist_props(l)
 
         return l
 
     def update_position(self, loc):
         'Set the location of tick in data coords with scalar loc'
-        self._locTransform.clear().translate(loc, 0.0)
-        self.label1.set_x(loc)
-        self.label2.set_x(loc)
+        x = loc
+
+        self.tick1line.set_xdata((x,))
+        self.tick2line.set_xdata((x,))
+        self.gridline.set_xdata((x, ))
+        self.label1.set_x(x)
+        self.label2.set_x(x)
         self._loc = loc
 
     def get_view_interval(self):
@@ -385,7 +388,7 @@
                     linestyle = 'None',
                     markersize=self._size,
                        )
-        l.set_transform(self._locTransform + self.axes.get_yaxis_transform())
+        l.set_transform(self.axes.get_yaxis_transform())
         self._set_artist_props(l)
         return l
 
@@ -398,7 +401,7 @@
                     markersize=self._size,
                     )
 
-        l.set_transform(self._locTransform + self.axes.get_yaxis_transform())
+        l.set_transform(self.axes.get_yaxis_transform())
         self._set_artist_props(l)
         return l
 
@@ -411,19 +414,24 @@
                     linewidth=rcParams['grid.linewidth'],
                     )
 
-        l.set_transform(self._locTransform + self.axes.get_yaxis_transform())
+        l.set_transform(self.axes.get_yaxis_transform())
         self._set_artist_props(l)
         return l
 
 
     def update_position(self, loc):
         'Set the location of tick in data coords with scalar loc'
-        self._locTransform.clear().translate(0.0, loc)
-        self.label1.set_y(loc)
-        self.label2.set_y(loc)
+        y = loc
+        self.tick1line.set_ydata((y,))
+        self.tick2line.set_ydata((y,))
+        self.gridline.set_ydata((y, ))
+
+        self.label1.set_y( y )
+        self.label2.set_y( y )
+
         self._loc = loc
 
-
+        
     def get_view_interval(self):
         'return the Interval instance for this axis view limits'
         return self.axes.viewLim.intervaly
@@ -751,7 +759,7 @@
         if len(self.minorTicks) < numticks:
             # update the new tick label properties from the old
             for i in range(numticks - len(self.minorTicks)):
-                tick = self._get_tick(minor=True)
+                tick = self._get_tick(major=False)
                 self.minorTicks.append(tick)
             
         if self._lastNumMinorTicks < numticks:

Modified: branches/transforms/lib/matplotlib/collections.py
===================================================================
--- branches/transforms/lib/matplotlib/collections.py   2007-10-14 21:14:18 UTC 
(rev 3946)
+++ branches/transforms/lib/matplotlib/collections.py   2007-10-15 13:49:25 UTC 
(rev 3947)
@@ -43,7 +43,7 @@
           linewidths=None,
           antialiaseds = None,
           offsets = None,
-          transOffset = transforms.identity_transform(),
+          transOffset = transforms.IdentityTransform(),
           norm = None,  # optional for cm.ScalarMappable
           cmap = None,  # ditto
 
@@ -376,7 +376,7 @@
       linewidths=None,
       antialiaseds = None,
       offsets = None,
-      transOffset = transforms.identity_transform(),
+      transOffset = transforms.IdentityTransform(),
       norm = None,  # optional for cm.ScalarMappable
       cmap = None,  # ditto
 

Modified: branches/transforms/lib/matplotlib/lines.py
===================================================================
--- branches/transforms/lib/matplotlib/lines.py 2007-10-14 21:14:18 UTC (rev 
3946)
+++ branches/transforms/lib/matplotlib/lines.py 2007-10-15 13:49:25 UTC (rev 
3947)
@@ -455,8 +455,10 @@
         gc.set_capstyle(cap)
 
         funcname = self._lineStyles.get(self._linestyle, '_draw_nothing')
-        lineFunc = getattr(self, funcname)
-        lineFunc(renderer, gc, 
*self._transformed_path.get_transformed_path_and_affine())
+        if funcname != '_draw_nothing':
+            tpath, affine = 
self._transformed_path.get_transformed_path_and_affine()
+            lineFunc = getattr(self, funcname)
+            lineFunc(renderer, gc, tpath, affine)
            
         if self._marker is not None:
             gc = renderer.new_gc()
@@ -465,8 +467,10 @@
             gc.set_linewidth(self._markeredgewidth)
             gc.set_alpha(self._alpha)
             funcname = self._markers.get(self._marker, '_draw_nothing')
-            markerFunc = getattr(self, funcname)
-            markerFunc(renderer, gc, 
*self._transformed_path.get_transformed_path_and_affine())
+            if funcname != '_draw_nothing':
+                tpath, affine = 
self._transformed_path.get_transformed_path_and_affine()
+                markerFunc = getattr(self, funcname)
+                markerFunc(renderer, gc, tpath, affine)
 
         renderer.close_group('line2d')
 
@@ -621,11 +625,9 @@
 
         ACCEPTS: npy.array
         """
-        try: del self._xsorted
-        except AttributeError: pass
+        self._xorig = x
+        self.recache()
 
-        self.set_data(x, self.get_ydata())
-
     def set_ydata(self, y):
         """
         Set the data npy.array for y
@@ -633,9 +635,9 @@
         ACCEPTS: npy.array
         """
 
-        self.set_data(self.get_xdata(), y)
+        self._yorig = y
+        self.recache()
 
-
     def set_dashes(self, seq):
         """
         Set the dash sequence, sequence of dashes with on off ink in

Modified: branches/transforms/lib/matplotlib/path.py
===================================================================
--- branches/transforms/lib/matplotlib/path.py  2007-10-14 21:14:18 UTC (rev 
3946)
+++ branches/transforms/lib/matplotlib/path.py  2007-10-15 13:49:25 UTC (rev 
3947)
@@ -84,7 +84,8 @@
         resulting path will be compressed, with MOVETO codes inserted
         in the correct places to jump over the masked regions.
         """
-        vertices = ma.asarray(vertices, npy.float_)
+        if not ma.isMaskedArray(vertices):
+            vertices = ma.asarray(vertices, npy.float_)
 
        if codes is None:
             if len(vertices) == 0:

Modified: branches/transforms/lib/matplotlib/text.py
===================================================================
--- branches/transforms/lib/matplotlib/text.py  2007-10-14 21:14:18 UTC (rev 
3946)
+++ branches/transforms/lib/matplotlib/text.py  2007-10-15 13:49:25 UTC (rev 
3947)
@@ -172,24 +172,18 @@
         self._linespacing = other._linespacing
 
     def _get_layout(self, renderer):
-        # layout the xylocs in display coords as if angle = zero and
-        # then rotate them around self._x, self._y
-        #return _unit_box
         key = self.get_prop_tup()
         if self.cached.has_key(key): return self.cached[key]
+
         horizLayout = []
-        transform = self.get_transform()
-        x, y = self.get_position()
-        thisx, thisy = transform.transform_point((x, y))
-        tx, ty = thisx, thisy
 
-        width = 0
-        height = 0
-
-        xmin, ymin = thisx, thisy
+        thisx, thisy  = 0.0, 0.0
+        xmin, ymin    = 0.0, 0.0
+        width, height = 0.0, 0.0
         lines = self._text.split('\n')
 
-        whs = []
+        whs = npy.zeros((len(lines), 2))
+        horizLayout = npy.zeros((len(lines), 4))
         # Find full vertical extent of font,
         # including ascenders and descenders:
         tmp, heightt, bl = renderer.get_text_width_height_descent(
@@ -197,43 +191,39 @@
         offsety = heightt * self._linespacing
 
         baseline = None
-        for line in lines:
+        for i, line in enumerate(lines):
             w, h, d = renderer.get_text_width_height_descent(
                 line, self._fontproperties, ismath=self.is_math_text(line))
             if baseline is None:
                 baseline = h - d
-            whs.append( (w,h) )
-            horizLayout.append((line, thisx, thisy, w, h))
+            whs[i] = w, h
+            horizLayout[i] = thisx, thisy, w, h
             thisy -= offsety
             width = max(width, w)
 
-        ymin = horizLayout[-1][2]
-        ymax = horizLayout[0][2] + horizLayout[0][-1]
+        ymin = horizLayout[-1][1]
+        ymax = horizLayout[0][1] + horizLayout[0][3]
         height = ymax-ymin
-
         xmax = xmin + width
+
         # get the rotation matrix
-        M = self.get_rotation_matrix(xmin, ymin)
+        M = Affine2D().rotate_deg(self.get_rotation())
 
-        # the corners of the unrotated bounding box
-        cornersHoriz = npy.array(
-           [(xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin)],
-           npy.float_)
         offsetLayout = npy.zeros((len(lines), 2))
+        offsetLayout[:] = horizLayout[:, 0:2]
         # now offset the individual text lines within the box
         if len(lines)>1: # do the multiline aligment
             malign = self._get_multialignment()
-            for i, (line, thisx, thisy, w, h) in enumerate(horizLayout):
-                if malign=='center': offsetx = width/2.0-w/2.0
-                elif malign=='right': offsetx = width-w
-                else: offsetx = 0
-                thisx += offsetx
-               offsetLayout[i] = (thisx, thisy)
-        else: # no additional layout needed
-            offsetLayout[0] = horizLayout[0][1:3]
+            if malign == 'center':
+                offsetLayout[:, 0] += width/2.0 - horizLayout[:, 2] / 2.0
+            elif malign == 'right':
+                offsetLayout[:, 0] += width - horizLayout[:, 2]
 
+        # the corners of the unrotated bounding box
+        cornersHoriz = npy.array(
+           [(xmin, ymin), (xmin, ymax), (xmax, ymax), (xmax, ymin)],
+           npy.float_)
         # now rotate the bbox
-
         cornersRotated = M.transform(cornersHoriz)
 
         txs = cornersRotated[:, 0]
@@ -251,37 +241,30 @@
 
         # compute the text location in display coords and the offsets
         # necessary to align the bbox with that location
-        tx, ty = self._get_xy_display()
+        if halign=='center':  offsetx = (xmin + width/2.0)
+        elif halign=='right': offsetx = (xmin + width)
+        else: offsetx = xmin
 
-        if halign=='center':  offsetx = tx - (xmin + width/2.0)
-        elif halign=='right': offsetx = tx - (xmin + width)
-        else: offsetx = tx - xmin
+        if valign=='center': offsety = (ymin + height/2.0)
+        elif valign=='top': offsety  = (ymin + height)
+        elif valign=='baseline': offsety = (ymin + height) + baseline
+        else: offsety = ymin
 
-        if valign=='center': offsety = ty - (ymin + height/2.0)
-        elif valign=='top': offsety  = ty - (ymin + height)
-        elif valign=='baseline': offsety = ty - (ymin + height) + baseline
-        else: offsety = ty - ymin
+        xmin -= offsetx
+        ymin -= offsety
 
-        xmin += offsetx
-        ymin += offsety
-
         bbox = Bbox.from_lbwh(xmin, ymin, width, height)
 
         # now rotate the positions around the first x,y position
         xys = M.transform(offsetLayout)
-        xys += (offsetx, offsety)
+        xys -= (offsetx, offsety)
 
-        # now inverse transform back to data coords
-       inverse_transform = transform.inverted()
-        xys = inverse_transform.transform(xys)
-
         xs, ys = xys[:, 0], xys[:, 1]
         
         ret = bbox, zip(lines, whs, xs, ys)
         self.cached[key] = ret
         return ret
 
-
     def set_bbox(self, rectprops):
         """
         Draw a bounding box around self.  rect props are any settable
@@ -307,18 +290,20 @@
         if self.get_clip_on():
             gc.set_clip_rectangle(self.clipbox)
 
-
-
         if self._bbox:
             bbox_artist(self, renderer, self._bbox)
         angle = self.get_rotation()
 
         bbox, info = self._get_layout(renderer)
         trans = self.get_transform()
+        posx, posy = self.get_position()
+        posx, posy = trans.transform_point((posx, posy))
+        canvasw, canvash = renderer.get_canvas_width_height()
+        
         if rcParams['text.usetex']:
-            canvasw, canvash = renderer.get_canvas_width_height()
             for line, wh, x, y in info:
-                x, y = trans.transform_point((x, y))
+                x = x + posx
+                y = y + posy
                 if renderer.flipy():
                     y = canvash-y
 
@@ -326,9 +311,9 @@
                                   self._fontproperties, angle)
             return
 
-        canvasw, canvash = renderer.get_canvas_width_height()
         for line, wh, x, y in info:
-            x, y = trans.transform_point((x, y))
+            x = x + posx
+            y = y + posy
             if renderer.flipy():
                 y = canvash-y
                 
@@ -402,8 +387,7 @@
         x, y = self.get_position()
         return (x, y, self._text, self._color,
                 self._verticalalignment, self._horizontalalignment,
-                hash(self._fontproperties), self._rotation,
-                self.get_transform().id
+                hash(self._fontproperties), self._rotation
                 )
 
     def get_text(self):
@@ -432,11 +416,11 @@
 
         angle = self.get_rotation()
         bbox, info = self._get_layout(self._renderer)
+        x, y = self.get_position()
+        x, y = self.get_transform().transform_point((x, y))
+        bbox = bbox.translated(x, y)
         return bbox
 
-    def get_rotation_matrix(self, x0, y0):
-       return Affine2D().rotate_deg_around(x0, y0, self.get_rotation())
-
     def set_backgroundcolor(self, color):
         """
         Set the background color of the text by updating the bbox (see 
set_bbox for more info)

Modified: branches/transforms/lib/matplotlib/transforms.py
===================================================================
--- branches/transforms/lib/matplotlib/transforms.py    2007-10-14 21:14:18 UTC 
(rev 3946)
+++ branches/transforms/lib/matplotlib/transforms.py    2007-10-15 13:49:25 UTC 
(rev 3947)
@@ -34,8 +34,6 @@
 
 DEBUG = False
 
-# MGDTODO: Cache get_affine???
-
 class TransformNode(object):
     """
     TransformNode is the base class for anything that participates in
@@ -51,7 +49,7 @@
     # INVALID_AFFINE_ONLY
     INVALID_NON_AFFINE = 1
     INVALID_AFFINE     = 2
-    INVALID            = INVALID_NON_AFFINE & INVALID_AFFINE
+    INVALID            = INVALID_NON_AFFINE | INVALID_AFFINE
     
     # Some metadata about the transform, used to determine whether an
     # invalidation is affine-only
@@ -71,11 +69,6 @@
         # them alive.
         self._parents = WeakKeyDictionary()
 
-        # id is an arbitrary integer that is updated every time the node
-        # is invalidated.
-        self.id = TransformNode._gid
-        TransformNode._gid += 1
-
         # TransformNodes start out as invalid until their values are
         # computed for the first time.
         self._invalid = 1
@@ -105,15 +98,14 @@
         value = ((self.is_affine or self.is_bbox)
                  and self.INVALID_AFFINE
                  or self.INVALID)
-
+        
         # Invalidate all ancestors of self using pseudo-recursion.
+        parent = None
         stack = [self]
         while len(stack):
             root = stack.pop()
             # Stop at subtrees that have already been invalidated
             if root._invalid == 0 or root.pass_through:
-                root.id = TransformNode._gid
-                TransformNode._gid += 1
                 root._invalid = value
                 stack.extend(root._parents.keys())
 
@@ -466,8 +458,7 @@
 
         count = 0
         for bbox in bboxes:
-            # bx1, by1, bx2, by2 = bbox._get_lbrt()
-            # The above, inlined...
+            # bx1, by1, bx2, by2 = bbox._get_lbrt() ... inlined...
             bx1, by1, bx2, by2 = bbox.get_points().flatten()
             if bx2 < bx1:
                 bx2, bx1 = bx1, bx2
@@ -497,6 +488,26 @@
         """
         return Bbox(self._points + (tx, ty))
 
+    def corners(self):
+        """
+        Return an array of points which are the four corners of this
+        rectangle.
+        """
+        l, b, r, t = self.get_points().flatten()
+        return npy.array([[l, b], [l, t], [r, b], [r, t]])
+    
+    def rotated(self, radians):
+        """
+        Return a new bounding box that bounds a rotated version of this
+        bounding box.  The new bounding box is still aligned with the
+        axes, of course.
+        """
+        corners = self.corners()
+        corners_rotated = Affine2D().rotate(radians).transform(corners)
+        bbox = Bbox.unit()
+        bbox.update_from_data(corners_rotated, ignore=True)
+        return bbox
+    
     [EMAIL PROTECTED]
     def union(bboxes):
         """
@@ -965,7 +976,6 @@
         self.transform_path_non_affine = child.transform_path_non_affine
         self.get_affine                = child.get_affine
         self.inverted                  = child.inverted
-        # self.get_matrix                = child.get_matrix
     
     def set(self, child):
         """
@@ -1609,7 +1619,8 @@
         self._x = x_transform
         self._y = y_transform
         self.set_children(x_transform, y_transform)
-
+        self._affine = None
+        
     def _get_is_affine(self):
         return self._x.is_affine and self._y.is_affine
     is_affine = property(_get_is_affine)
@@ -1648,9 +1659,7 @@
     transform.__doc__ = Transform.transform.__doc__
 
     def transform_affine(self, points):
-        if self._x.is_affine and self._y.is_affine:
-            return self.transform(points)
-        return points
+        return self.get_affine().transform(points)
     transform_affine.__doc__ = Transform.transform_affine.__doc__
 
     def transform_non_affine(self, points):
@@ -1664,18 +1673,22 @@
     inverted.__doc__ = Transform.inverted.__doc__
 
     def get_affine(self):
-        if self._x.is_affine and self._y.is_affine:
-            if self._x == self._y:
-                return self._x.get_affine()
+        if self._invalid or self._affine is None:
+            if self._x.is_affine and self._y.is_affine:
+                if self._x == self._y:
+                    self._affine = self._x.get_affine()
+                else:
+                    x_mtx = self._x.get_affine().get_matrix()
+                    y_mtx = self._y.get_affine().get_matrix()
+                    # This works because we already know the transforms are
+                    # separable, though normally one would want to set b and
+                    # c to zero.
+                    mtx = npy.vstack((x_mtx[0], y_mtx[1], [0.0, 0.0, 1.0]))
+                    self._affine = Affine2D(mtx)
             else:
-                x_mtx = self._x.get_affine().get_matrix()
-                y_mtx = self._y.get_affine().get_matrix()
-                # This works because we already know the transforms are
-                # separable, though normally one would want to set b and
-                # c to zero.
-                mtx = npy.vstack((x_mtx[0], y_mtx[1], [0.0, 0.0, 1.0]))
-                return Affine2D(mtx)
-        return IdentityTransform()
+                self._affine = IdentityTransform()
+            self._invalid = 0
+        return self._affine
     get_affine.__doc__ = Transform.get_affine.__doc__
 
 
@@ -1830,6 +1843,7 @@
         self._b = b
         self.set_children(a, b)
         self._mtx = None
+        self._affine = None
 
     def frozen(self):
         self._invalid = 0
@@ -1857,8 +1871,7 @@
     transform.__doc__ = Transform.transform.__doc__
     
     def transform_affine(self, points):
-        return self._b.transform_affine(
-            self._a.transform(points))
+        return self.get_affine().transform(points)
     transform_affine.__doc__ = Transform.transform_affine.__doc__
 
     def transform_non_affine(self, points):
@@ -1886,10 +1899,14 @@
     transform_path_non_affine.__doc__ = 
Transform.transform_path_non_affine.__doc__
     
     def get_affine(self):
-        if self._a.is_affine and self._b.is_affine:
-            return Affine2D(npy.dot(self._b.get_affine().get_matrix(),
-                                    self._a.get_affine().get_matrix()))
-        return self._b.get_affine()
+        if self._invalid or self._affine is None:
+            if self._a.is_affine and self._b.is_affine:
+                self._affine = 
Affine2D(npy.dot(self._b.get_affine().get_matrix(),
+                                                
self._a.get_affine().get_matrix()))
+            else:
+                self._affine = self._b.get_affine()
+            self._invalid = 0
+        return self._affine
     get_affine.__doc__ = Transform.get_affine.__doc__
     
     def inverted(self):
@@ -2023,6 +2040,7 @@
         self._transform = transform
         self.set_children(transform)
         self._transformed_path = None
+        self.get_affine = self._transform.get_affine
 
     def get_transformed_path_and_affine(self):
         """
@@ -2035,7 +2053,7 @@
             self._transformed_path = \
                 self._transform.transform_path_non_affine(self._path)
         self._invalid = 0
-        return self._transformed_path, self._transform.get_affine()
+        return self._transformed_path, self.get_affine()
 
     def get_fully_transformed_path(self):
         """
@@ -2047,12 +2065,6 @@
                 self._transform.transform_path_non_affine(self._path)
         self._invalid = 0
         return self._transform.transform_path_affine(self._transformed_path)
-
-    def get_affine(self):
-        """
-        Get the affine part of the child transform.
-        """
-        return self._transform.get_affine()
     
     
 def nonsingular(vmin, vmax, expander=0.001, tiny=1e-15, increasing=True):


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: Splunk Inc.
Still grepping through log files to find problems?  Stop.
Now Search log events and configuration files using AJAX and a browser.
Download your FREE copy of Splunk now >> http://get.splunk.com/
_______________________________________________
Matplotlib-checkins mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to