Revision: 4053
          http://matplotlib.svn.sourceforge.net/matplotlib/?rev=4053&view=rev
Author:   mdboom
Date:     2007-10-29 08:21:49 -0700 (Mon, 29 Oct 2007)

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

Modified Paths:
--------------
    branches/transforms/PASSED_DEMOS
    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/backends/backend_svg.py
    branches/transforms/lib/matplotlib/collections.py
    branches/transforms/lib/matplotlib/colors.py
    branches/transforms/lib/matplotlib/legend.py
    branches/transforms/lib/matplotlib/lines.py
    branches/transforms/lib/matplotlib/patches.py
    branches/transforms/lib/matplotlib/widgets.py

Modified: branches/transforms/PASSED_DEMOS
===================================================================
--- branches/transforms/PASSED_DEMOS    2007-10-29 15:20:13 UTC (rev 4052)
+++ branches/transforms/PASSED_DEMOS    2007-10-29 15:21:49 UTC (rev 4053)
@@ -208,3 +208,5 @@
 xcorr_demo.py          O       
 zoom_window.py         O
 zorder_demo.py         O
+
+MGDTODO: units directory
\ No newline at end of file

Modified: branches/transforms/lib/matplotlib/artist.py
===================================================================
--- branches/transforms/lib/matplotlib/artist.py        2007-10-29 15:20:13 UTC 
(rev 4052)
+++ branches/transforms/lib/matplotlib/artist.py        2007-10-29 15:21:49 UTC 
(rev 4053)
@@ -2,6 +2,7 @@
 import re, warnings
 from cbook import iterable, flatten
 from transforms import Bbox, IdentityTransform, TransformedBbox, 
TransformedPath
+from path import Path
 
 ## Note, matplotlib artists use the doc strings for set and get
 # methods to enable the introspection methods of setp and getp.  Every
@@ -285,25 +286,48 @@
 
     def set_clip_path(self, path, transform=None):
         """
-        Set the artist's clip path
+        Set the artist's clip path, which may be:
 
-        ACCEPTS: a Path instance and a Transform instance, or a Patch instance
+          a) a Patch (or subclass) instance
+
+          b) a Path instance, in which cas aoptional transform may
+             be provided, which will be applied to the path before using it
+             for clipping.
+
+          c) None, to remove the clipping path
+
+        For efficiency, if the path happens to be an axis-aligned
+        rectangle, this method will set the clipping box to the
+        corresponding rectangle and set the clipping path to None.
+             
+        ACCEPTS: a Path instance and a Transform instance, a Patch
+        instance, or None
         """
         from patches import Patch, Rectangle
+
+        success = False
         if transform is None:
             if isinstance(path, Rectangle):
                 self.clipbox = TransformedBbox(Bbox.unit(), 
path.get_transform())
+                success = True
             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:
+                success = True
+                
+        if path is None:
+            self._clippath = None
+            success = True
+        elif isinstance(path, Path):
             self._clippath = TransformedPath(path, transform)
-        self._clipon = self.clipbox is not None or path is not None
+            success = True
+            
+        if not success:
+            print type(path), type(transform)
+            raise TypeError("Invalid arguments to set_clip_path")
+
+        self._clipon = self.clipbox is not None or self._clippath is not None
         self.pchanged()
 
     def get_alpha(self):
@@ -334,6 +358,10 @@
         return self._clippath
 
     def get_transformed_clip_path_and_affine(self):
+        '''
+        Return the clip path with the non-affine part of its transformation 
applied,
+        and the remaining affine part of its transformation.
+        '''
         if self._clippath is not None:
             return self._clippath.get_transformed_path_and_affine()
         return None, None

Modified: branches/transforms/lib/matplotlib/axes.py
===================================================================
--- branches/transforms/lib/matplotlib/axes.py  2007-10-29 15:20:13 UTC (rev 
4052)
+++ branches/transforms/lib/matplotlib/axes.py  2007-10-29 15:21:49 UTC (rev 
4053)
@@ -494,9 +494,6 @@
         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()
         
@@ -553,7 +550,8 @@
     def _set_lim_and_transforms(self):
         """
         set the dataLim and viewLim BBox attributes and the
-        transData and transAxes Transformation attributes
+        transScale, transData, transLimits and transAxes
+        transformations.
         """
        self.dataLim = mtransforms.Bbox.unit()
         self.viewLim = mtransforms.Bbox.unit()
@@ -579,27 +577,105 @@
                 self.axes.transAxes, self.axes.transData)
 
     def get_xaxis_transform(self):
+        """
+        Get the transformation used for drawing x-axis labels, ticks
+        and gridlines.  The x-direction is in data coordinates and the
+        y-direction is in axis coordinates.
+
+        This transformation is primarily used by the Axis class, and
+        is meant to be overridden by new kinds of projections that may
+        need to place axis elements in different locations.
+        """
         return self._xaxis_transform
 
     def get_xaxis_text1_transform(self, pad_pixels):
+        """
+        Get the transformation used for drawing x-axis labels, which
+        will add the given number of pad_pixels between the axes and
+        the label.  The x-direction is in data coordinates and the
+        y-direction is in axis coordinates.  Returns a 3-tuple of the
+        form:
+
+          (transform, valign, halign)
+
+        where valign and halign are requested alignments for the text.
+
+        This transformation is primarily used by the Axis class, and
+        is meant to be overridden by new kinds of projections that may
+        need to place axis elements in different locations.
+        """
         return (self._xaxis_transform +
                 mtransforms.Affine2D().translate(0, -1 * pad_pixels),
                 "top", "center")
 
     def get_xaxis_text2_transform(self, pad_pixels):
+        """
+        Get the transformation used for drawing the secondary x-axis
+        labels, which will add the given number of pad_pixels between
+        the axes and the label.  The x-direction is in data
+        coordinates and the y-direction is in axis coordinates.
+        Returns a 3-tuple of the form:
+
+          (transform, valign, halign)
+
+        where valign and halign are requested alignments for the text.
+
+        This transformation is primarily used by the Axis class, and
+        is meant to be overridden by new kinds of projections that may
+        need to place axis elements in different locations.
+        """
         return (self._xaxis_transform +
                 mtransforms.Affine2D().translate(0, pad_pixels),
                 "bottom", "center")
 
     def get_yaxis_transform(self):
+        """
+        Get the transformation used for drawing y-axis labels, ticks
+        and gridlines.  The x-direction is in axis coordinates and the
+        y-direction is in data coordinates.
+
+        This transformation is primarily used by the Axis class, and
+        is meant to be overridden by new kinds of projections that may
+        need to place axis elements in different locations.
+        """
         return self._yaxis_transform
 
     def get_yaxis_text1_transform(self, pad_pixels):
+        """
+        Get the transformation used for drawing y-axis labels, which
+        will add the given number of pad_pixels between the axes and
+        the label.  The x-direction is in axis coordinates and the
+        y-direction is in data coordinates.  Returns a 3-tuple of the
+        form:
+
+          (transform, valign, halign)
+
+        where valign and halign are requested alignments for the text.
+
+        This transformation is primarily used by the Axis class, and
+        is meant to be overridden by new kinds of projections that may
+        need to place axis elements in different locations.
+        """
         return (self._yaxis_transform +
                 mtransforms.Affine2D().translate(-1 * pad_pixels, 0),
                 "center", "right")
 
     def get_yaxis_text2_transform(self, pad_pixels):
+        """
+        Get the transformation used for drawing the secondary y-axis
+        labels, which will add the given number of pad_pixels between
+        the axes and the label.  The x-direction is in axis
+        coordinates and the y-direction is in data coordinates.
+        Returns a 3-tuple of the form:
+
+          (transform, valign, halign)
+
+        where valign and halign are requested alignments for the text.
+
+        This transformation is primarily used by the Axis class, and
+        is meant to be overridden by new kinds of projections that may
+        need to place axis elements in different locations.
+        """
         return (self._yaxis_transform +
                 mtransforms.Affine2D().translate(pad_pixels, 0),
                 "center", "left")
@@ -610,11 +686,11 @@
                 self.xaxis.get_transform(), self.yaxis.get_transform()))
         
     def get_position(self, original=False):
-        'Return the axes rectangle left, bottom, width, height'
+        'Return the a copy of the axes rectangle as a Bbox'
         if original:
-            return self._originalPosition
+            return self._originalPosition.frozen()
         else:
-            return self._position
+            return self._position.frozen()
 
        
     def set_position(self, pos, which='both'):
@@ -639,7 +715,6 @@
         if which in ('both', 'original'):
             self._originalPosition.set(pos)
 
-           
     def _set_artist_props(self, a):
         'set the boilerplate props for artists added to axes'
         a.set_figure(self.figure)
@@ -648,6 +723,16 @@
         a.axes = self
 
     def get_axes_patch(self):
+        """
+        Returns the patch used to draw the background of the axes.  It
+        is also used as the clipping path for any data elements on the
+        axes.
+
+        In the standard axes, this is a rectangle, but in other
+        projections it may not be.
+
+        Intended to be overridden by new projection types.
+        """
         return mpatches.Rectangle((0.0, 0.0), 1.0, 1.0)
         
     def cla(self):
@@ -806,6 +891,12 @@
                                 ', '.join(mtransforms.BBox.coefs.keys()))
 
     def get_data_ratio(self):
+        """
+        Returns the aspect ratio of the raw data.
+
+        This method is intended to be overridden by new projection
+        types.
+        """
         xmin,xmax = self.get_xbound()
         xsize = max(math.fabs(xmax-xmin), 1e-30)
         ymin,ymax = self.get_ybound()
@@ -1032,6 +1123,7 @@
         a.set_axes(self)
         self.artists.append(a)
         self._set_artist_props(a)
+        # MGDTODO: We may not want to do this -- the old trunk didn't
         a.set_clip_path(self.axesPatch)
         a._remove_method = lambda h: self.artists.remove(h)
 
@@ -1074,19 +1166,20 @@
         self._update_patch_limits(p)
         self.patches.append(p)
         p._remove_method = lambda h: self.patches.remove(h)
-
+        
     def _update_patch_limits(self, p):
         'update the datalimits for patch p'
-        xys = self._get_verts_in_data_coords(
-            p.get_data_transform(),
-            p.get_patch_transform().transform(p.get_path().vertices))
-        self.update_datalim(xys)
+        vertices = p.get_patch_transform().transform(p.get_path().vertices)
+        if p.get_data_transform() != self.transData:
+            transform = p.get_data_transform() + self.transData.inverted()
+            xys = transform.transform(vertices)
+        self.update_datalim(vertices)
 
-
     def add_table(self, tab):
         'Add a table instance to the list of axes tables'
         self._set_artist_props(tab)
         self.tables.append(tab)
+        # MGDTODO: We may not want to do this (the old version in trunk didn't)
         tab.set_clip_path(self.axesPatch)
         tab._remove_method = lambda h: self.tables.remove(h)
 
@@ -1105,8 +1198,6 @@
         # limits and set the bound to be the bounds of the xydata.
         # Otherwise, it will compute the bounds of it's current data
         # and the data in xydata
-        # MGDTODO: This isn't always the most efficient way to do this... in
-        # some cases things should use update_datalim_bounds
         if not ma.isMaskedArray(xys):
             xys = npy.asarray(xys)
         self.update_datalim_numerix(xys[:, 0], xys[:, 1])
@@ -1117,7 +1208,6 @@
         # limits and set the bound to be the bounds of the xydata.
         # Otherwise, it will compute the bounds of it's current data
         # and the data in xydata
-        ## self.dataLim.update_numerix(x, y, -1)
        self.dataLim.update_from_data(x, y, self.ignore_existing_data_limits)
        self.ignore_existing_data_limits = False
 
@@ -1125,16 +1215,6 @@
         'Update the datalim to include the given Bbox'
         self.dataLim.set(Bbox.union([self.dataLim, bounds]))
         
-    def _get_verts_in_data_coords(self, trans, xys):
-        if trans == self.transData:
-            return xys
-        # data is not in axis data units.  We must transform it to
-        # 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.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'
 
@@ -1162,7 +1242,7 @@
                 self.yaxis.set_units(yunits)
 
     def in_axes(self, mouseevent):
-        'return True is the point xwin, ywin (display coords) are in the Axes'
+        'return True if the given mouseevent (in display coords) is in the 
Axes'
         return self.axesPatch.contains(mouseevent)[0]
 
     def get_autoscale_on(self):
@@ -1268,11 +1348,11 @@
         if self.axison and self._frameon:
             artists.append(self.axesFrame)
 
-       dsu = [ (a.zorder, a) for a in artists
+       dsu = [ (a.zorder, i, a) for i, a in enumerate(artists)
                if not a.get_animated() ]
         dsu.sort()
 
-        for zorder, a in dsu:
+        for zorder, i, a in dsu:
             a.draw(renderer)
 
         renderer.close_group('axes')
@@ -1474,16 +1554,10 @@
                 self.set_xlim(upper, lower)
 
     def get_xlim(self):
-        """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
-        if ( self._invertedx ):
-            return bound2, bound1
-        else:
-            return bound1, bound2
+        Get the x-axis range [xmin, xmax]
+        """
+        return self.viewLim.intervalx
 
     def set_xlim(self, xmin=None, xmax=None, emit=True, **kwargs):
         """
@@ -1637,16 +1711,10 @@
                 self.set_ylim(upper, lower)
 
     def get_ylim(self):
-        """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
-        if ( self._invertedy ):
-            return bound2, bound1
-        else:
-            return bound1, bound2
+        Get the y-axis range [xmin, xmax]
+        """
+        return self.viewLim.intervaly
 
     def set_ylim(self, ymin=None, ymax=None, emit=True, **kwargs):
         """
@@ -1812,8 +1880,10 @@
 
     def format_coord(self, x, y):
         'return a format string formatting the x, y coord'
-        if x is None or y is None:
-            return ''
+        if x is None:
+            x = '???'
+        if y is None:
+            y = '???'
         xs = self.format_xdata(x)
         ys = self.format_ydata(y)
         return  'x=%s, y=%s'%(xs,ys)
@@ -1855,6 +1925,17 @@
         self._navigate_mode = b
 
     def start_pan(self, x, y, button):
+        """
+        Called when a pan operation has started.
+
+        x, y are the mouse coordinates in display coords.
+        button is the mouse button number:
+           1: LEFT
+           2: MIDDLE
+           3: RIGHT
+        
+        Intended to be overridden by new projection types.
+        """
         self._pan_start = cbook.Bunch(
             lim           = self.viewLim.frozen(),
             trans         = self.transData.frozen(),
@@ -1864,9 +1945,29 @@
             )
 
     def end_pan(self):
+        """
+        Called when a pan operation completes (when the mouse button
+        is up.)
+
+        Intended to be overridden by new projection types.
+        """
         del self._pan_start
         
     def drag_pan(self, button, key, x, y):
+        """
+        Called when the mouse moves during a pan operation.
+
+        button is the mouse button number:
+           1: LEFT
+           2: MIDDLE
+           3: RIGHT
+
+        key is a "shift" key
+
+        x, y are the mouse coordinates in display coords.
+
+        Intended to be overridden by new projection types.
+        """
         def format_deltas(key, dx, dy):
             if key=='control':
                 if(abs(dx)>abs(dy)):
@@ -2223,7 +2324,7 @@
         %(Annotation)s
         """
         a = mtext.Annotation(*args, **kwargs)
-        a.set_transform(mtransforms.Affine2D())
+        a.set_transform(mtransforms.IdentityTransform())
         self._set_artist_props(a)
         if kwargs.has_key('clip_on'):  a.set_clip_path(self.axesPatch)
         self.texts.append(a)
@@ -4035,9 +4136,9 @@
             if len(sh) == 1 and sh[0] == len(x):
                 colors = None  # use cmap, norm after collection is created
             else:
-                colors = mcolors.colorConverter.to_rgba_list(c, alpha)
+                colors = mcolors.colorConverter.to_rgba_array(c, alpha)
         else:
-            colors = mcolors.colorConverter.to_rgba_list(c, alpha)
+            colors = mcolors.colorConverter.to_rgba_array(c, alpha)
 
         if not iterable(s):
             scales = (s,)
@@ -4137,7 +4238,7 @@
                 offsets = zip(x,y),
                 transOffset = self.transData,
                 )
-            collection.set_transform(mtransforms.Affine2D())
+            collection.set_transform(mtransforms.IdentityTransform())
         collection.set_alpha(alpha)
         collection.update(kwargs)
 
@@ -4198,6 +4299,9 @@
     quiverkey.__doc__ = mquiver.QuiverKey.quiverkey_doc
 
     def quiver(self, *args, **kw):
+        """
+        MGDTODO: Document me
+        """
         q = mquiver.Quiver(self, *args, **kw)
         self.add_collection(q, False)
         self.update_datalim_numerix(q.X, q.Y)

Modified: branches/transforms/lib/matplotlib/axis.py
===================================================================
--- branches/transforms/lib/matplotlib/axis.py  2007-10-29 15:20:13 UTC (rev 
4052)
+++ branches/transforms/lib/matplotlib/axis.py  2007-10-29 15:21:49 UTC (rev 
4053)
@@ -14,7 +14,7 @@
 from font_manager import FontProperties
 from text import Text, TextWithDash
 from transforms import Affine2D, Bbox, blended_transform_factory, \
-    interval_contains
+    IdentityTransform, interval_contains
 from patches import bbox_artist
 from scale import scale_factory
 
@@ -113,6 +113,7 @@
         self.tick1line.set_clip_path(clippath, transform)
         self.tick2line.set_clip_path(clippath, transform)
         self.gridline.set_clip_path(clippath, transform)
+    set_clip_path.__doc__ = Artist.set_clip_path.__doc__
     
     def contains(self, mouseevent):
         """Test whether the mouse event occured in the Tick marks.
@@ -1015,7 +1016,7 @@
             horizontalalignment='center',
             )
         label.set_transform( blended_transform_factory(
-               self.axes.transAxes, Affine2D() ))
+               self.axes.transAxes, IdentityTransform() ))
 
         self._set_artist_props(label)
         self.label_position='bottom'
@@ -1030,7 +1031,7 @@
             horizontalalignment='right',
             )
         offsetText.set_transform( blended_transform_factory(
-               self.axes.transAxes, Affine2D() ))
+               self.axes.transAxes, IdentityTransform() ))
         self._set_artist_props(offsetText)
         self.offset_text_position='bottom'
         return offsetText
@@ -1092,11 +1093,11 @@
        
     def set_ticks_position(self, position):
         """
-        Set the ticks position (top, bottom, both or default)
-        both sets the ticks to appear on both positions, but
-        does not change the tick labels.
-        default resets the tick positions to the default:
-        ticks on both positions, labels at bottom.
+        Set the ticks position (top, bottom, both, default or none)
+        both sets the ticks to appear on both positions, but does not
+        change the tick labels.  default resets the tick positions to
+        the default: ticks on both positions, labels at bottom.  none
+        can be used if you don't want any ticks.
 
         ACCEPTS: [ 'top' | 'bottom' | 'both' | 'default' | 'none' ]
         """
@@ -1225,7 +1226,7 @@
             rotation='vertical',
             )
         label.set_transform( blended_transform_factory(
-               Affine2D(), self.axes.transAxes) )
+               IdentityTransform(), self.axes.transAxes) )
 
         self._set_artist_props(label)
         self.label_position='left'
@@ -1240,7 +1241,7 @@
             horizontalalignment = 'left',
             )
         offsetText.set_transform(blended_transform_factory(
-               self.axes.transAxes, Affine2D()) )
+               self.axes.transAxes, IdentityTransform()) )
         self._set_artist_props(offsetText)
         self.offset_text_position='left'
         return offsetText

Modified: branches/transforms/lib/matplotlib/backend_bases.py
===================================================================
--- branches/transforms/lib/matplotlib/backend_bases.py 2007-10-29 15:20:13 UTC 
(rev 4052)
+++ branches/transforms/lib/matplotlib/backend_bases.py 2007-10-29 15:21:49 UTC 
(rev 4053)
@@ -73,7 +73,7 @@
             offsets, offsetTrans, facecolors, edgecolors,
             linewidths, linestyles, antialiaseds):
             path, transform = path_id
-            transform = transform.frozen().translate(xo, yo)
+            transform = 
transforms.Affine2D(transform.get_matrix()).translate(xo, yo)
             self.draw_path(gc, path, transform, rgbFace)
             
     def _iter_collection_raw_paths(self, master_transform, paths, 
all_transforms):
@@ -200,6 +200,27 @@
         """
         return False
 
+    def draw_tex(self, gc, x, y, s, prop, angle, ismath='TeX!'):
+        raise NotImplementedError
+
+    def draw_text(self, gc, x, y, s, prop, angle, ismath=False):
+        """
+        Draw the text.Text instance s at x,y (display coords) with font
+        properties instance prop at angle in degrees, using GraphicsContext gc
+
+        **backend implementers note**
+
+        When you are trying to determine if you have gotten your bounding box
+        right (which is what enables the text layout/alignment to work
+        properly), it helps to change the line in text.py
+
+                  if 0: bbox_artist(self, renderer)
+
+        to if 1, and then the actual bounding box will be blotted along with
+        your text.
+        """
+        raise NotImplementedError
+    
     def flipy(self):
         """return true if y small numbers are top for renderer
         Is used for drawing text (text.py) and images (image.py) only
@@ -386,7 +407,8 @@
 
     def set_clip_path(self, path):
         """
-        Set the clip path and transformation
+        Set the clip path and transformation.  Path should be a
+        transforms.TransformedPath instance.
         """
         assert path is None or isinstance(path, transforms.TransformedPath)
         self._clippath = path

Modified: branches/transforms/lib/matplotlib/backends/backend_svg.py
===================================================================
--- branches/transforms/lib/matplotlib/backends/backend_svg.py  2007-10-29 
15:20:13 UTC (rev 4052)
+++ branches/transforms/lib/matplotlib/backends/backend_svg.py  2007-10-29 
15:21:49 UTC (rev 4053)
@@ -205,7 +205,7 @@
         for i, (path, transform) in enumerate(self._iter_collection_raw_paths(
             master_transform, paths, all_transforms)):
             name = 'coll%x_%x' % (self._path_collection_id, i)
-            transform = transform.frozen().scale(1.0, -1.0)
+            transform = Affine2D(transform.get_matrix()).scale(1.0, -1.0)
             d = self._convert_path(path, transform)
             write('<path id="%s" d="%s"/>\n' % (name, d))
             path_codes.append(name)

Modified: branches/transforms/lib/matplotlib/collections.py
===================================================================
--- branches/transforms/lib/matplotlib/collections.py   2007-10-29 15:20:13 UTC 
(rev 4052)
+++ branches/transforms/lib/matplotlib/collections.py   2007-10-29 15:21:49 UTC 
(rev 4053)
@@ -83,12 +83,12 @@
         if antialiaseds is None: antialiaseds = 
(mpl.rcParams['patch.antialiased'],)
         self.set_linestyles(linestyles)
         
-        self._facecolors  = _colors.colorConverter.to_rgba_list(facecolors)
+        self._facecolors  = _colors.colorConverter.to_rgba_array(facecolors)
         if edgecolors == 'None':
             self._edgecolors = self._facecolors
             linewidths = (0,)
         else:
-            self._edgecolors = _colors.colorConverter.to_rgba_list(edgecolors)
+            self._edgecolors = _colors.colorConverter.to_rgba_array(edgecolors)
         self._linewidths  = self._get_value(linewidths)
         self._antialiaseds = self._get_value(antialiaseds)
 
@@ -268,7 +268,7 @@
 
         ACCEPTS: matplotlib color arg or sequence of rgba tuples
         """
-        self._facecolors = _colors.colorConverter.to_rgba_list(c, self._alpha)
+        self._facecolors = _colors.colorConverter.to_rgba_array(c, self._alpha)
 
     set_facecolors = set_facecolor
 
@@ -284,7 +284,7 @@
             self._linewidths = (0.0,)
             self._edgecolors = npy.array([])
         else:
-            self._edgecolors = _colors.colorConverter.to_rgba_list(c)
+            self._edgecolors = _colors.colorConverter.to_rgba_array(c)
     set_edgecolors = set_edgecolor
 
     def set_alpha(self, alpha):
@@ -581,7 +581,7 @@
         if antialiaseds is None: antialiaseds = 
(mpl.rcParams['lines.antialiased'],)
         self.set_linestyles(linestyles)
 
-        colors = _colors.colorConverter.to_rgba_list(colors)
+        colors = _colors.colorConverter.to_rgba_array(colors)
         
         Collection.__init__(
             self,
@@ -633,7 +633,7 @@
 
         ACCEPTS: matplotlib color arg or sequence of rgba tuples
         """
-        self._edgecolors = _colors.colorConverter.to_rgba_list(c)
+        self._edgecolors = _colors.colorConverter.to_rgba_array(c)
 
     def color(self, c):
         """

Modified: branches/transforms/lib/matplotlib/colors.py
===================================================================
--- branches/transforms/lib/matplotlib/colors.py        2007-10-29 15:20:13 UTC 
(rev 4052)
+++ branches/transforms/lib/matplotlib/colors.py        2007-10-29 15:21:49 UTC 
(rev 4053)
@@ -307,12 +307,13 @@
         except (TypeError, ValueError), exc:
             raise ValueError('to_rgba: Invalid rgba arg "%s"\n%s' % (str(arg), 
exc))
 
-    def to_rgba_list(self, c, alpha=None):
+    def to_rgba_array(self, c, alpha=None):
         """
-        Returns a list of rgba tuples.
+        Returns an Numpy array of rgba tuples.
 
         Accepts a single mpl color spec or a sequence of specs.
-        If the sequence is a list, the list items are changed in place.
+        If the sequence is a list or array, the items are changed in place,
+        but an array copy is still returned.
         """
         try:
             result = [self.to_rgba(c, alpha)]
@@ -320,7 +321,7 @@
             # If c is a list it must be maintained as the same list
             # with modified items so that items can be appended to
             # it. This is needed for examples/dynamic_collections.py.
-            if not isinstance(c, list): # specific; don't need duck-typing
+            if not isinstance(c, (list, npy.ndarray)): # specific; don't need 
duck-typing
                 c = list(c)
             for i, cc in enumerate(c):
                 c[i] = self.to_rgba(cc, alpha)  # change in place

Modified: branches/transforms/lib/matplotlib/legend.py
===================================================================
--- branches/transforms/lib/matplotlib/legend.py        2007-10-29 15:20:13 UTC 
(rev 4052)
+++ branches/transforms/lib/matplotlib/legend.py        2007-10-29 15:21:49 UTC 
(rev 4053)
@@ -363,15 +363,6 @@
             bbox.update_from_data_xy(averts, True)
             bboxes.append(bbox)
 
-        for handle in ax.collections:
-            if isinstance(handle, LineCollection):
-                hlines = handle.get_lines()
-                trans = handle.get_transform()
-                for line in hlines:
-                    tline = trans.seq_xy_tups(line)
-                    aline = [inv(v) for v in tline]
-                    lines.append(aline)
-
         return [vertices, bboxes, lines]
 
     def draw_frame(self, b):

Modified: branches/transforms/lib/matplotlib/lines.py
===================================================================
--- branches/transforms/lib/matplotlib/lines.py 2007-10-29 15:20:13 UTC (rev 
4052)
+++ branches/transforms/lib/matplotlib/lines.py 2007-10-29 15:21:49 UTC (rev 
4053)
@@ -71,6 +71,45 @@
     ic1 = breakpoints
     return npy.concatenate((ic0[:, npy.newaxis], ic1[:, npy.newaxis]), axis=1)
 
+def segment_hits(cx,cy,x,y,radius):
+    """Determine if any line segments are within radius of a point. Returns
+    the list of line segments that are within that radius.
+    """
+    # Process single points specially
+    if len(x) < 2:
+        res, = npy.nonzero( (cx - x)**2 + (cy - y)**2 <= radius**2 )
+        return res
+
+    # We need to lop the last element off a lot.
+    xr,yr = x[:-1],y[:-1]
+
+    # Only look at line segments whose nearest point to C on the line
+    # lies within the segment.
+    dx,dy = x[1:]-xr, y[1:]-yr
+    Lnorm_sq = dx**2+dy**2    # Possibly want to eliminate Lnorm==0
+    u = ( (cx-xr)*dx + (cy-yr)*dy )/Lnorm_sq
+    candidates = (u>=0) & (u<=1)
+    #if any(candidates): print "candidates",xr[candidates]
+
+    # Note that there is a little area near one side of each point
+    # which will be near neither segment, and another which will
+    # be near both, depending on the angle of the lines.  The
+    # following radius test eliminates these ambiguities.
+    point_hits = (cx - x)**2 + (cy - y)**2 <= radius**2
+    #if any(point_hits): print "points",xr[candidates]
+    candidates = candidates & ~point_hits[:-1] & ~point_hits[1:]
+
+    # For those candidates which remain, determine how far they lie away
+    # from the line.
+    px,py = xr+u*dx,yr+u*dy
+    line_hits = (cx-px)**2 + (cy-py)**2 <= radius**2
+    #if any(line_hits): print "lines",xr[candidates]
+    line_hits = line_hits & candidates
+    points, = point_hits.ravel().nonzero()
+    lines, = line_hits.ravel().nonzero()
+    #print points,lines
+    return npy.concatenate((points,lines))
+
 class Line2D(Artist):
     lineStyles = _lineStyles =  { # hidden names deprecated
         '-'          : '_draw_solid',
@@ -276,7 +315,6 @@
         else:
             pixels = self.figure.dpi/72. * self.pickradius
             
-        path, transform = 
self._transformed_path.get_transformed_path_and_affine()
         if self._linestyle == 'None':
             # If no line, return the nearby point(s)
             d = npy.sqrt((xt-mouseevent.x)**2 + (yt-mouseevent.y)**2)
@@ -320,7 +358,7 @@
         # correct for marker size, if any
         if self._marker is not None:
             ms = (self._markersize / 72.0 * self.figure.dpi) * 0.5
-            bbox = Bbox(bbox.get_points() + [[-ms, -ms], [ms, ms]])
+            bbox = bbox.padded(ms)
         return bbox
 
     def set_axes(self, ax):
@@ -399,7 +437,7 @@
         """
         set the Transformation instance used by this artist
 
-        ACCEPTS: a matplotlib.transform transformation instance
+        ACCEPTS: a matplotlib.transforms.Transform instance
         """
         Artist.set_transform(self, t)
         self._transformed_path = TransformedPath(self._path, 
self.get_transform())

Modified: branches/transforms/lib/matplotlib/patches.py
===================================================================
--- branches/transforms/lib/matplotlib/patches.py       2007-10-29 15:20:13 UTC 
(rev 4052)
+++ branches/transforms/lib/matplotlib/patches.py       2007-10-29 15:21:49 UTC 
(rev 4053)
@@ -82,7 +82,7 @@
 
         Returns T/F, {}
         """
-       # This is a general version of contains should work on any
+       # This is a general version of contains that should work on any
         # patch with a path.  However, patches that have a faster
         # algebraic solution to hit-testing should override this
         # method.
@@ -290,8 +290,8 @@
         Patch.__init__(self)
         self.patch = patch
         self.props = props
-       self.ox, self.oy = ox, oy
-       self._shadow_transform = transforms.Affine2D().translate(self.ox, 
self.oy)
+       self._ox, self._oy = ox, oy
+        self._update_transform()
         self._update()
     __init__.__doc__ = cbook.dedent(__init__.__doc__) % artist.kwdocd
 
@@ -308,7 +308,22 @@
 
             self.set_facecolor((r,g,b,0.5))
             self.set_edgecolor((r,g,b,0.5))
-           
+
+    def _update_transform(self):
+        self._shadow_transform = transforms.Affine2D().translate(self._ox, 
self._oy)
+            
+    def _get_ox(self):
+        return self._ox
+    def _set_ox(self, ox):
+        self._ox = ox
+        self._update_transform()
+    
+    def _get_oy(self):
+        return self._oy
+    def _set_oy(self, oy):
+        self._oy = oy
+        self._update_transform()
+        
     def get_path(self):
         return self.patch.get_path()
 

Modified: branches/transforms/lib/matplotlib/widgets.py
===================================================================
--- branches/transforms/lib/matplotlib/widgets.py       2007-10-29 15:20:13 UTC 
(rev 4052)
+++ branches/transforms/lib/matplotlib/widgets.py       2007-10-29 15:21:49 UTC 
(rev 4053)
@@ -849,7 +849,7 @@
         self.prev = (0, 0)
 
         if self.direction == 'horizontal':
-            trans = (self.ax.transData, self.ax.transAxes)
+            trans = blended_transform_factory(self.ax.transData, 
self.ax.transAxes)
             w,h = 0,1
         else:
             trans = blended_transform_factory(self.ax.transAxes, 
self.ax.transData)


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
Matplotlib-checkins@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-checkins

Reply via email to