Ok, here's something of a weird patch, because I don't know how to use subversion properly. It has changes to axes.py which update quiver so that it accepts arbitrary X,Y data; it doesn't demand the data be on a grid anymore.

The other changes are to collections.py; I updated LineCollection so it inherits from ScalarMappable. I did this just by copying what looked like the relevant code from PatchCollection and then I tested it with my LineCollection based version of quiver. I think I got it right, but I don't really know what I'm doing here so someone should check it over.

Jordan
Index: lib/matplotlib/axes.py
===================================================================
--- lib/matplotlib/axes.py      (revision 2421)
+++ lib/matplotlib/axes.py      (working copy)
@@ -3206,16 +3206,16 @@
         QUIVER( U, V )
         QUIVER( X, Y, U, V, S)
         QUIVER( U, V, S )
-        QUIVER( ..., color=None, width=1.0, cmap=None,norm=None )
+        QUIVER( ..., color=None, width=1.0, cmap=None, norm=None )
 
         Make a vector plot (U, V) with arrows on a grid (X, Y)
 
-        The optional arguments color and width are used to specify the color 
and width
-        of the arrow. color can be an array of colors in which case the arrows 
can be
-        colored according to another dataset.
+        If X and Y are not specified, U and V must be 2D arrays.  Equally 
spaced
+        X and Y grids are then generated using the meshgrid command.
 
-        If cmap is specified and color is 'length', the colormap is
-        used to give a color according to the vector's length.
+        color can be a color value or an array of colors, so that the arrows 
can be
+        colored according to another dataset.  If cmap is specified and color 
is 'length',
+        the colormap is used to give a color according to the vector's length.
 
         If color is a scalar field, the colormap is used to map the scalar to 
a color
         If a colormap is specified and color is an array of color triplets, 
then the
@@ -3263,10 +3263,15 @@
         assert X.shape == Y.shape
         assert U.shape == X.shape
 
+        U = ravel(U)
+        V = ravel(V)
+        X = ravel(X)
+        Y = ravel(Y)
+
         arrows = []
         N = sqrt( U**2+V**2 )
         if do_scale:
-            Nmax = maximum.reduce(maximum.reduce(N)) or 1 # account for div by 
zero
+            Nmax = maximum.reduce(N) or 1 # account for div by zero
             U = U*(S/Nmax)
             V = V*(S/Nmax)
             N = N*Nmax
@@ -3281,7 +3286,6 @@
         shading = kwargs.get('shading', 'faceted')
 
         C = None
-        I,J = U.shape
         if color == 'length' or color is True:
             if color is True:
                 warnings.warn('''Use "color='length'",
@@ -3290,12 +3294,15 @@
         elif color is None:
             color = (0,0,0,1)
         else:
-            clr = asarray(color)
+            clr = ravel(asarray(color))
             if clr.shape == U.shape:
                 C = clr
 
-        arrows = [ Arrow(X[i,j],Y[i,j],U[i,j],V[i,j],0.1*S ).get_verts()
-                   for i in xrange(I) for j in xrange(J) ]
+        I = U.shape[0]
+        arrows = []
+        for i in xrange(I):
+            arrows.append( FancyArrow(X[i],Y[i],U[i],V[i],0.1*S ).get_verts() )
+
         collection = PolyCollection(
             arrows,
             edgecolors = 'None',
@@ -3311,6 +3318,7 @@
         else:
             collection.set_facecolor(color)
         self.add_collection( collection )
+
         lims = asarray(arrows)
         _max = maximum.reduce( maximum.reduce( lims ))
         _min = minimum.reduce( minimum.reduce( lims ))
Index: lib/matplotlib/collections.py
===================================================================
--- lib/matplotlib/collections.py       (revision 2421)
+++ lib/matplotlib/collections.py       (working copy)
@@ -367,7 +367,7 @@
         raise NotImplementedError('Vertices in data coordinates are 
calculated\n'
                 + 'only with offsets and only if _transOffset == dataTrans.')
 
-class LineCollection(Collection):
+class LineCollection(Collection, ScalarMappable):
     """
     All parameters must be sequences.  The property of the ith line
     segment is the prop[i % len(props)], ie the properties cycle if
@@ -381,6 +381,8 @@
                  linestyle = 'solid',
                  offsets = None,
                  transOffset = None,#identity_transform(),
+                 norm = None,  # optional for ScalarMappable
+                 cmap = None,  # ditto
                  ):
         """
         segments is a sequence of ( line0, line1, line2), where
@@ -412,6 +414,7 @@
         """
 
         Collection.__init__(self)
+        ScalarMappable.__init__(self, norm, cmap)
 
         if linewidths is None   :
             linewidths   = (rcParams['lines.linewidth'], )
@@ -419,7 +422,7 @@
         if colors is None       :
             colors       = (rcParams['lines.color'],)
         if antialiaseds is None :
-            antialiaseds = (rcParams['lines.antialiased'], )
+                        antialiaseds = (rcParams['lines.antialiased'], )
 
         self._segments = list(segments)
         self._colors = colorConverter.to_rgba_list(colors)
@@ -453,6 +456,7 @@
         renderer.open_group('linecollection')
         self._transform.freeze()
         if self._transOffset is not None: self._transOffset.freeze()
+        self.update_scalarmappable()
         renderer.draw_line_collection(
             self._segments, self._transform, self.clipbox,
             self._colors, self._lw, self._ls, self._aa, self._offsets,
@@ -461,6 +465,7 @@
         if self._transOffset is not None: self._transOffset.thaw()
         renderer.close_group('linecollection')
 
+
     def set_linewidth(self, lw):
         """
         Set the linewidth(s) for the collection.  lw can be a scalar or a
@@ -546,10 +551,22 @@
         verts = []
         if self._offsets is None:
             for seg in self._segments:
-                verts.extend(seg)
+                verts.append(seg)
             return [tuple(xy) for xy in verts]
         if self._transOffset == dataTrans:
             return [tuple(xy) for xy in self._offsets]
         raise NotImplementedError('Vertices in data coordinates are 
calculated\n'
                 + 'with offsets only if _transOffset == dataTrans.')
 
+    def update_scalarmappable(self):
+        """
+        If the scalar mappable array is not none, update facecolors
+        from scalar data
+        """
+        if self._A is None: return
+        if len(self._A.shape)>1:
+            raise ValueError('LineCollections can only map rank 1 arrays')
+        self._colors = self.to_rgba(self._A, self._alpha)
+        #print self._A.shape, type(R), R.shape
+        #self._facecolors = [(r,g,b,a) for r,g,b,a in R]
+

Reply via email to