Hi,

Yes, I have fixed the problem in my version of matplotlib, but I haven't
had the time to look over all of my changes and commit them to SVN.
Next week things should get better.  If you are really in a hurry, you
can try applying the attached patch set to SVN, but better to wait and
let me make sure it is all kosher.

Cheers,
David


On Fri, 2008-09-12 at 11:29 +0200, Mark Bakker wrote:
> Hello David -
> 
> Sorry for the late reply. I am back from vacation.
> 
> Any luck on solving the problem of the disappearing contour lines when
> labelling? It works fine when you don't use the 'inline', but the
> picture is of course not as nice, as the labels are not in-line
> anymore. Maybe that gives a clue to what goes wrong?
> 
> Thanks, Mark
> 
> On Wed, Sep 3, 2008 at 12:47 PM, David M. Kaplan <[EMAIL PROTECTED]>
> wrote:
>         Hi,
>         
>         Back from vacation.  The problem with not being able to end
>         point
>         selection is easy to fix - allow keyboard clicks to also
>         select points
>         and enter to also exit (this is the solution matlab uses).
>          This is easy
>         to add and I will try to work on it sometime over the next
>         couple of
>         weeks.
>         
>         I will try your example sometime soon and see what happens.
>          It sounds
>         like the problem has something to do with what happens when
>         the label
>         covers the entire contour - currently the contour gets deleted
>         entirely,
>         but this seems to be doing something strange in your case.
>         
>         Cheers,
>         David
>         
>         
>         
>         On Thu, 2008-08-21 at 16:02 +0200, Mark Bakker wrote:
>         > David -
>         >
>         > Enjoy your vacation.
>         >
>         > I tried the contour_label_demo and it works fine, but my
>         problem
>         > remains.
>         >
>         > I suggest you try the example I provided below, and notice
>         the
>         > difference between labeling with inline=True and
>         inline=False. When
>         > inline=True the contours in the middle part (which don't get
>         labeled,
>         > presumably because there isn't enough room) get erased.
>         >
>         > I figured out the manual input problem. The trick is that
>         you require
>         > to press the middle button to end (I'll do a post to the
>         user's list).
>         > Many laptops don't have a middle button. Although
>         suggestions are
>         > found on the web that pushing both buttons simultaneously
>         works, I
>         > have never seen it work. What you have to do is configure
>         your
>         > touchpad such that a corner acts as the middle button. Once
>         I figured
>         > that out, I could end manually selecting the labels. Very
>         nice. If I
>         > may, I strongly recommend you change the code such that
>         pushing the
>         > right button ends the manual input. Is there any reason not
>         to use the
>         > right button for that?
>         >
>         > I hope you can fix the inline problem. Thanks for all the
>         other new
>         > cool features,
>         >
>         > Mark
>         >
>         > On Tue, Aug 19, 2008 at 4:06 PM, <[EMAIL PROTECTED]> wrote:
>         >         Hi,
>         >
>         >         I am currently on vacation, so I can´t be of much
>         help - back
>         >         beginning of next month.  It would be useful if
>         >         you could try the clabel and ginput demo scripts and
>         send
>         >         images of the resulting figures so that we can
>         determine
>         >         exactly what things work and don´t work.
>         >
>         >         Thanks,
>         >         David
>         >
>         >
>         >
>         >         Mark Bakker <[EMAIL PROTECTED]> ha escrito:
>         >
>         >
>         >
>         >                 Hello David and the developers list-
>         >
>         >                 I have had little luck on the mailing list,
>         so sorry
>         >                 for writing you
>         >                 directly (David may be on vacation).
>         >
>         >                 I have two problems labeling contour lines
>         in 0.98.3.
>         >
>         >                 First, when I call clabel, it removes all
>         contours
>         >                 that are not labeled
>         >                 (because the label doesn't fit on the
>         section of
>         >                 contour, I presume).
>         >                 This seems like a bug to me (or a really odd
>         feature).
>         >                 It doesn't do this
>         >                 when inline = False, but I don't think it
>         should do it
>         >                 either when inline =
>         >                 True
>         >                 Easy example:
>         >
>         >                                         x,y =
>         >
>         meshgrid( linspace(-10,10,50),
>         >
>         linspace(-10,10,50) )
>         >                                         z = log(x**2 + y**2)
>         >                                         cobj =
>         contour(x,y,z) # Note
>         >                                         that there are 8
>         contours
>         >                                         levels (11
>         >                 contour sections in all)
>         >                                         cobj.clabel()
>         >                 <a list of 8 text.Text objects>
>         >                                         draw()  # Now only 5
>         contours
>         >                                         are drawn; the ones
>         in the
>         >                                         middle are
>         >                 removed.
>         >
>         >                 Second, when using the new manual labeling
>         of contour
>         >                 labels (which is
>         >                 pretty neat!), how do I end this feature?
>         >                 The doc string says: right click, or
>         potentially click
>         >                 both mouse buttons
>         >                 together (which already worries me).
>         >                 Neither works for me on win32, mpl 0.98.3,
>         TkAgg
>         >                 backend, interactive mode.
>         >                 Does anybody have a solution?
>         >
>         >                 Thanks, Mark
>         >
>         >
>         >
>         >
>         >
>         >
>         ----------------------------------------------------------------
>         >         This message was sent using IMP, the Internet
>         Messaging
>         >         Program.
>         >
>         >
>         >
>         
>         --
>         **********************************
>         David M. Kaplan
>         Charge de Recherche 1
>         Institut de Recherche pour le Developpement
>         Centre de Recherche Halieutique Mediterraneenne et Tropicale
>         av. Jean Monnet
>         B.P. 171
>         34203 Sete cedex
>         France
>         
>         Phone: +33 (0)4 99 57 32 27
>         Fax: +33 (0)4 99 57 32 95
>         http://www.ur097.ird.fr/team/dkaplan/index.html
>         **********************************
>         
>         
> 
> 
-- 
**********************************
David M. Kaplan
Charge de Recherche 1
Institut de Recherche pour le Developpement
Centre de Recherche Halieutique Mediterraneenne et Tropicale
av. Jean Monnet
B.P. 171
34203 Sete cedex
France

Phone: +33 (0)4 99 57 32 27
Fax: +33 (0)4 99 57 32 95
http://www.ur097.ird.fr/team/dkaplan/index.html
**********************************
Index: CHANGELOG
===================================================================
--- CHANGELOG	(revision 6074)
+++ CHANGELOG	(working copy)
@@ -1,3 +1,13 @@
+<<<<<<< .mine
+<<<<<<< .mine
+<<<<<<< .mine
+2008-07-26 Reorganized cbook and mlab methods related to numerical
+	   calculations that have little to do with the goals of those two
+	   modules into a separate module numerical_methods.py - DMK
+
+=======
+=======
+=======
 2008-09-07 Changed full arrows slightly to avoid an xpdf rendering
            problem reported by Friedrich Hagedorn. - JKS
 
@@ -10,6 +20,7 @@
 
 2008-09-03 Fix log with base 2 - MGD
 
+>>>>>>> .r6074
 2008-09-01 Added support for bilinear interpolation in
            NonUniformImage; patch by Gregory Lielens. - EF
 
@@ -28,6 +39,7 @@
 
 2008-08-18 improve interactive pan/zoom in qt4 backend on windows - DSD
 
+>>>>>>> .r6060
 2008-08-11 Fix more bugs in NaN/inf handling.  In particular, path simplification
            (which does not handle NaNs or infs) will be turned off automatically
            when infs or NaNs are present.  Also masked arrays are now converted
@@ -46,6 +58,7 @@
 	   of C based on the x,y coordinates and display in hexagonal
 	   bins. - ADS
 
+>>>>>>> .r6036
 2008-07-24 Deprecated (raise NotImplementedError) all the mlab2
            functions from matplotlib.mlab out of concern that some of
            them were not clean room implementations. JDH
Index: lib/matplotlib/cbook.py
===================================================================
--- lib/matplotlib/cbook.py	(revision 6074)
+++ lib/matplotlib/cbook.py	(working copy)
@@ -1157,47 +1157,6 @@
 
     return result
 
-def less_simple_linear_interpolation( x, y, xi, extrap=False ):
-    """
-    This function provides simple (but somewhat less so than
-    simple_linear_interpolation) linear interpolation.
-    simple_linear_interpolation will give a list of point between a
-    start and an end, while this does true linear interpolation at an
-    arbitrary set of points.
-
-    This is very inefficient linear interpolation meant to be used
-    only for a small number of points in relatively non-intensive use
-    cases.
-    """
-    if is_scalar(xi): xi = [xi]
-
-    x = np.asarray(x)
-    y = np.asarray(y)
-    xi = np.asarray(xi)
-
-    s = list(y.shape)
-    s[0] = len(xi)
-    yi = np.tile( np.nan, s )
-
-    for ii,xx in enumerate(xi):
-        bb = x == xx
-        if np.any(bb):
-            jj, = np.nonzero(bb)
-            yi[ii] = y[jj[0]]
-        elif xx<x[0]:
-            if extrap:
-                yi[ii] = y[0]
-        elif xx>x[-1]:
-            if extrap:
-                yi[ii] = y[-1]
-        else:
-            jj, = np.nonzero(x<xx)
-            jj = max(jj)
-
-            yi[ii] = y[jj] + (xx-x[jj])/(x[jj+1]-x[jj]) * (y[jj+1]-y[jj])
-
-    return yi
-
 def recursive_remove(path):
     if os.path.isdir(path):
         for fname in glob.glob(os.path.join(path, '*')) + glob.glob(os.path.join(path, '.*')):
@@ -1336,60 +1295,6 @@
     ic1 = breakpoints
     return np.concatenate((ic0[:, np.newaxis], ic1[:, np.newaxis]), axis=1)
 
-def isvector(X):
-    """
-    Like the Matlab (TM) function with the same name, returns true if
-    the supplied numpy array or matrix looks like a vector, meaning it
-    has a one non-singleton axis (i.e., it can have multiple axes, but
-    all must have length 1, except for one of them).
-
-    If you just want to see if the array has 1 axis, use X.ndim==1
-
-    """
-    return np.prod(X.shape)==np.max(X.shape)
-
-def vector_lengths( X, P=2., axis=None ):
-    """
-    Finds the length of a set of vectors in n dimensions.  This is
-    like the numpy norm function for vectors, but has the ability to
-    work over a particular axis of the supplied array or matrix.
-
-    Computes (sum((x_i)^P))^(1/P) for each {x_i} being the elements of X along
-    the given axis.  If *axis* is *None*, compute over all elements of X.
-    """
-    X = np.asarray(X)
-    return (np.sum(X**(P),axis=axis))**(1./P)
-
-def distances_along_curve( X ):
-    """
-    Computes the distance between a set of successive points in N dimensions.
-
-    where X is an MxN array or matrix.  The distances between successive rows
-    is computed.  Distance is the standard Euclidean distance.
-    """
-    X = np.diff( X, axis=0 )
-    return vector_lengths(X,axis=1)
-
-def path_length(X):
-    """
-    Computes the distance travelled along a polygonal curve in N dimensions.
-
-
-    where X is an MxN array or matrix.  Returns an array of length M consisting
-    of the distance along the curve at each point (i.e., the rows of X).
-    """
-    X = distances_along_curve(X)
-    return np.concatenate( (np.zeros(1), np.cumsum(X)) )
-
-def is_closed_polygon(X):
-    """
-    Tests whether first and last object in a sequence are the same.  These are
-    presumably coordinates on a polygonal curve, in which case this function
-    tests if that curve is closed.
-
-    """
-    return np.all(X[0] == X[-1])
-
 def quad2cubic(q0x, q0y, q1x, q1y, q2x, q2y):
     """
     Converts a quadratic Bezier curve to a cubic approximation.
Index: lib/matplotlib/numerical_methods.py
===================================================================
--- lib/matplotlib/numerical_methods.py	(revision 0)
+++ lib/matplotlib/numerical_methods.py	(revision 0)
@@ -0,0 +1,285 @@
+"""
+A collection of utility functions that do various numerical or geometrical
+manipulations.  
+"""
+import numpy as np
+from numpy import ma
+import matplotlib.cbook as cbook
+
+##################################################
+# Linear interpolation algorithms
+##################################################
+def less_simple_linear_interpolation( x, y, xi, extrap=False ):
+    """
+    This function provides simple (but somewhat less so than
+    cbook.simple_linear_interpolation) linear interpolation.
+    simple_linear_interpolation will give a list of point between a
+    start and an end, while this does true linear interpolation at an
+    arbitrary set of points.
+
+    This is very inefficient linear interpolation meant to be used
+    only for a small number of points in relatively non-intensive use
+    cases.  For real linear interpolation, use scipy.
+    """
+    if cbook.is_scalar(xi): xi = [xi]
+
+    x = np.asarray(x)
+    y = np.asarray(y)
+    xi = np.asarray(xi)
+
+    s = list(y.shape)
+    s[0] = len(xi)
+    yi = np.tile( np.nan, s )
+
+    for ii,xx in enumerate(xi):
+        bb = x == xx
+        if np.any(bb):
+            jj, = np.nonzero(bb)
+            yi[ii] = y[jj[0]]
+        elif xx<x[0]:
+            if extrap:
+                yi[ii] = y[0]
+        elif xx>x[-1]:
+            if extrap:
+                yi[ii] = y[-1]
+        else:
+            jj, = np.nonzero(x<xx)
+            jj = max(jj)
+
+            yi[ii] = y[jj] + (xx-x[jj])/(x[jj+1]-x[jj]) * (y[jj+1]-y[jj])
+
+    return yi
+
+def slopes(x,y):
+    """
+    SLOPES calculate the slope y'(x) Given data vectors X and Y SLOPES
+    calculates Y'(X), i.e the slope of a curve Y(X). The slope is
+    estimated using the slope obtained from that of a parabola through
+    any three consecutive points.
+
+    This method should be superior to that described in the appendix
+    of A CONSISTENTLY WELL BEHAVED METHOD OF INTERPOLATION by Russel
+    W. Stineman (Creative Computing July 1980) in at least one aspect:
+
+    Circles for interpolation demand a known aspect ratio between x-
+    and y-values.  For many functions, however, the abscissa are given
+    in different dimensions, so an aspect ratio is completely
+    arbitrary.
+
+    The parabola method gives very similar results to the circle
+    method for most regular cases but behaves much better in special
+    cases
+
+    Norbert Nemec, Institute of Theoretical Physics, University or
+    Regensburg, April 2006 Norbert.Nemec at physik.uni-regensburg.de
+
+    (inspired by a original implementation by Halldor Bjornsson,
+    Icelandic Meteorological Office, March 2006 halldor at vedur.is)
+    """
+    # Cast key variables as float.
+    x=np.asarray(x, np.float_)
+    y=np.asarray(y, np.float_)
+
+    yp=np.zeros(y.shape, np.float_)
+
+    dx=x[1:] - x[:-1]
+    dy=y[1:] - y[:-1]
+    dydx = dy/dx
+    yp[1:-1] = (dydx[:-1] * dx[1:] + dydx[1:] * dx[:-1])/(dx[1:] + dx[:-1])
+    yp[0] = 2.0 * dy[0]/dx[0] - yp[1]
+    yp[-1] = 2.0 * dy[-1]/dx[-1] - yp[-2]
+    return yp
+
+
+def stineman_interp(xi,x,y,yp=None):
+    """
+    STINEMAN_INTERP Well behaved data interpolation.  Given data
+    vectors X and Y, the slope vector YP and a new abscissa vector XI
+    the function stineman_interp(xi,x,y,yp) uses Stineman
+    interpolation to calculate a vector YI corresponding to XI.
+
+    Here's an example that generates a coarse sine curve, then
+    interpolates over a finer abscissa:
+
+      x = linspace(0,2*pi,20);  y = sin(x); yp = cos(x)
+      xi = linspace(0,2*pi,40);
+      yi = stineman_interp(xi,x,y,yp);
+      plot(x,y,'o',xi,yi)
+
+    The interpolation method is described in the article A
+    CONSISTENTLY WELL BEHAVED METHOD OF INTERPOLATION by Russell
+    W. Stineman. The article appeared in the July 1980 issue of
+    Creative Computing with a note from the editor stating that while
+    they were
+
+      not an academic journal but once in a while something serious
+      and original comes in adding that this was
+      "apparently a real solution" to a well known problem.
+
+    For yp=None, the routine automatically determines the slopes using
+    the "slopes" routine.
+
+    X is assumed to be sorted in increasing order
+
+    For values xi[j] < x[0] or xi[j] > x[-1], the routine tries a
+    extrapolation.  The relevance of the data obtained from this, of
+    course, questionable...
+
+    original implementation by Halldor Bjornsson, Icelandic
+    Meteorolocial Office, March 2006 halldor at vedur.is
+
+    completely reworked and optimized for Python by Norbert Nemec,
+    Institute of Theoretical Physics, University or Regensburg, April
+    2006 Norbert.Nemec at physik.uni-regensburg.de
+
+    """
+
+    # Cast key variables as float.
+    x=np.asarray(x, np.float_)
+    y=np.asarray(y, np.float_)
+    assert x.shape == y.shape
+    N=len(y)
+
+    if yp is None:
+        yp = slopes(x,y)
+    else:
+        yp=np.asarray(yp, np.float_)
+
+    xi=np.asarray(xi, np.float_)
+    yi=np.zeros(xi.shape, np.float_)
+
+    # calculate linear slopes
+    dx = x[1:] - x[:-1]
+    dy = y[1:] - y[:-1]
+    s = dy/dx  #note length of s is N-1 so last element is #N-2
+
+    # find the segment each xi is in
+    # this line actually is the key to the efficiency of this implementation
+    idx = np.searchsorted(x[1:-1], xi)
+
+    # now we have generally: x[idx[j]] <= xi[j] <= x[idx[j]+1]
+    # except at the boundaries, where it may be that xi[j] < x[0] or xi[j] > x[-1]
+
+    # the y-values that would come out from a linear interpolation:
+    sidx = s.take(idx)
+    xidx = x.take(idx)
+    yidx = y.take(idx)
+    xidxp1 = x.take(idx+1)
+    yo = yidx + sidx * (xi - xidx)
+
+    # the difference that comes when using the slopes given in yp
+    dy1 = (yp.take(idx)- sidx) * (xi - xidx)       # using the yp slope of the left point
+    dy2 = (yp.take(idx+1)-sidx) * (xi - xidxp1) # using the yp slope of the right point
+
+    dy1dy2 = dy1*dy2
+    # The following is optimized for Python. The solution actually
+    # does more calculations than necessary but exploiting the power
+    # of numpy, this is far more efficient than coding a loop by hand
+    # in Python
+    yi = yo + dy1dy2 * np.choose(np.array(np.sign(dy1dy2), np.int32)+1,
+                                 ((2*xi-xidx-xidxp1)/((dy1-dy2)*(xidxp1-xidx)),
+                                  0.0,
+                                  1/(dy1+dy2),))
+    return yi
+
+##################################################
+# Code related to things in and around polygons
+##################################################
+def inside_poly(points, verts):
+    """
+    points is a sequence of x,y points
+    verts is a sequence of x,y vertices of a poygon
+
+    return value is a sequence of indices into points for the points
+    that are inside the polygon
+    """
+    res, =  np.nonzero(nxutils.points_inside_poly(points, verts))
+    return res
+
+def poly_below(xmin, xs, ys):
+    """
+    given a sequence of xs and ys, return the vertices of a polygon
+    that has a horzontal base at xmin and an upper bound at the ys.
+    xmin is a scalar.
+
+    intended for use with Axes.fill, eg
+    xv, yv = poly_below(0, x, y)
+    ax.fill(xv, yv)
+    """
+    xs = np.asarray(xs)
+    ys = np.asarray(ys)
+    Nx = len(xs)
+    Ny = len(ys)
+    assert(Nx==Ny)
+    x = xmin*np.ones(2*Nx)
+    y = np.ones(2*Nx)
+    x[:Nx] = xs
+    y[:Nx] = ys
+    y[Nx:] = ys[::-1]
+    return x, y
+
+
+def poly_between(x, ylower, yupper):
+    """
+    given a sequence of x, ylower and yupper, return the polygon that
+    fills the regions between them.  ylower or yupper can be scalar or
+    iterable.  If they are iterable, they must be equal in length to x
+
+    return value is x, y arrays for use with Axes.fill
+    """
+    Nx = len(x)
+    if not cbook.iterable(ylower):
+        ylower = ylower*np.ones(Nx)
+
+    if not cbook.iterable(yupper):
+        yupper = yupper*np.ones(Nx)
+
+    x = np.concatenate( (x, x[::-1]) )
+    y = np.concatenate( (yupper, ylower[::-1]) )
+    return x,y
+
+def is_closed_polygon(X):
+    """
+    Tests whether first and last object in a sequence are the same.  These are
+    presumably coordinates on a polygonal curve, in which case this function
+    tests if that curve is closed.
+
+    """
+    return np.all(X[0] == X[-1])
+
+##################################################
+# Vector and path length geometry calculations
+##################################################
+def vector_lengths( X, P=2., axis=None ):
+    """
+    Finds the length of a set of vectors in n dimensions.  This is
+    like the numpy norm function for vectors, but has the ability to
+    work over a particular axis of the supplied array or matrix.
+
+    Computes (sum((x_i)^P))^(1/P) for each {x_i} being the elements of X along
+    the given axis.  If *axis* is *None*, compute over all elements of X.
+    """
+    X = np.asarray(X)
+    return (np.sum(X**(P),axis=axis))**(1./P)
+
+def distances_along_curve( X ):
+    """
+    Computes the distance between a set of successive points in N dimensions.
+
+    where X is an MxN array or matrix.  The distances between successive rows
+    is computed.  Distance is the standard Euclidean distance.
+    """
+    X = np.diff( X, axis=0 )
+    return vector_lengths(X,axis=1)
+
+def path_length(X):
+    """
+    Computes the distance travelled along a polygonal curve in N dimensions.
+
+
+    where X is an MxN array or matrix.  Returns an array of length M consisting
+    of the distance along the curve at each point (i.e., the rows of X).
+    """
+    X = distances_along_curve(X)
+    return np.concatenate( (np.zeros(1), np.cumsum(X)) )
+
Index: lib/matplotlib/contour.py
===================================================================
--- lib/matplotlib/contour.py	(revision 6074)
+++ lib/matplotlib/contour.py	(working copy)
@@ -16,6 +16,7 @@
 import matplotlib.font_manager as font_manager
 import matplotlib.text as text
 import matplotlib.cbook as cbook
+import matplotlib.numerical_methods as numerical_methods
 
 # Import needed for adding manual selection capability to clabel
 from matplotlib.blocking_input import BlockingContourLabeler
@@ -87,7 +88,10 @@
             add a label, click the second button (or potentially both
             mouse buttons at once) to finish adding labels.  The third
             button can be used to remove the last label added, but
-            only if labels are not inline.
+            only if labels are not inline.  Alternatively, the keyboard
+            can be used to select label locations (enter to end label
+            placement, delete or backspace act like the third mouse button,
+            and any other key will select a label location).
 
         """
 
@@ -96,17 +100,9 @@
 
         clabel basically takes the input arguments and uses them to
         add a list of "label specific" attributes to the ContourSet
-        object.  These attributes currently include: label_indices,
-        label_levels, label_cvalues, fp (font properties), fslist
-        (fontsize list), label_mappable, cl (list of text objects of
-        labels), cl_xy (coordinates of labels), cl_cvalues (color
-        values of the actual labels).
+        object.  These attributes are all of the form label* and names
+        should be fairly self explanatory.
 
-        Note that these property names do not conform to the standards
-        set for coding matplotlib and I (DMK) eventually plan on
-        changing them so that they are clearer and conform to
-        standards.
-
         Once these attributes are set, clabel passes control to the
         labels method (case of automatic label placement) or
         BlockingContourLabeler (case of manual label placement).
@@ -181,7 +177,7 @@
             self.labels(inline,inline_spacing)
 
         # Hold on to some old attribute names.  These are depricated and will
-        # be moved in the near future (sometime after 2008-08-01), but keeping
+        # be removed in the near future (sometime after 2008-08-01), but keeping
         # for now for backwards compatibility
         self.cl = self.labelTexts
         self.cl_xy = self.labelXYs
@@ -339,7 +335,7 @@
         not empty (lc defaults to the empty list if None).  *spacing*
         is the space around the label in pixels to leave empty.
 
-        Do both of these tasks at once to avoid calling cbook.path_length
+        Do both of these tasks at once to avoid calling numerical_methods.path_length
         multiple times, which is relatively costly.
 
         The method used here involves calculating the path length
@@ -353,7 +349,7 @@
         hlw = lw/2.0
 
         # Check if closed and, if so, rotate contour so label is at edge
-        closed = cbook.is_closed_polygon(slc)
+        closed = numerical_methods.is_closed_polygon(slc)
         if closed:
             slc = np.r_[ slc[ind:-1], slc[:ind+1] ]
 
@@ -363,7 +359,7 @@
             ind = 0
 
         # Path length in pixel space
-        pl = cbook.path_length(slc)
+        pl = numerical_methods.path_length(slc)
         pl = pl-pl[ind]
 
         # Use linear interpolation to get points around label
@@ -373,7 +369,7 @@
         else:
             dp = np.zeros_like(xi)
 
-        ll = cbook.less_simple_linear_interpolation( pl, slc, dp+xi,
+        ll = numerical_methods.less_simple_linear_interpolation( pl, slc, dp+xi,
                                                      extrap=True )
 
         # get vector in pixel space coordinates from one point to other
@@ -399,16 +395,16 @@
             xi = dp + xi + np.array([-spacing,spacing])
 
             # Get indices near points of interest
-            I = cbook.less_simple_linear_interpolation(
+            I = numerical_methods.less_simple_linear_interpolation(
                 pl, np.arange(len(pl)), xi, extrap=False )
 
             # If those indices aren't beyond contour edge, find x,y
             if (not np.isnan(I[0])) and int(I[0])<>I[0]:
-                xy1 = cbook.less_simple_linear_interpolation(
+                xy1 = numerical_methods.less_simple_linear_interpolation(
                     pl, lc, [ xi[0] ] )
 
             if (not np.isnan(I[1])) and int(I[1])<>I[1]:
-                xy2 = cbook.less_simple_linear_interpolation(
+                xy2 = numerical_methods.less_simple_linear_interpolation(
                     pl, lc, [ xi[1] ] )
 
             # Make integer
@@ -476,12 +472,12 @@
                 # zero in print_label and locate_label.  Other than these
                 # functions, this is not necessary and should probably be
                 # eventually removed.
-                if cbook.is_closed_polygon( lc ):
+                if numerical_methods.is_closed_polygon( lc ):
                     slc = np.r_[ slc0, slc0[1:2,:] ]
                 else:
                     slc = slc0
 
-                if self.print_label(slc,lw):
+                if self.print_label(slc,lw): # Check if long enough for a label
                     x,y,ind  = self.locate_label(slc, lw)
 
                     if inline: lcarg = lc
@@ -498,6 +494,8 @@
                         for n in new:
                             # Add path if not empty or single point
                             if len(n)>1: additions.append( path.Path(n) )
+                else: # If not adding label, keep old path
+                    additions.append(linepath)
 
             # After looping over all segments on a contour, remove old
             # paths and add new ones if inlining
Index: lib/matplotlib/pylab.py
===================================================================
--- lib/matplotlib/pylab.py	(revision 6074)
+++ lib/matplotlib/pylab.py	(working copy)
@@ -225,8 +225,12 @@
         sqrtm, prctile, center_matrix, rk4, exp_safe, amap,\
         sum_flat, mean_flat, rms_flat, l1norm, l2norm, norm, frange,\
         diagonal_matrix, base_repr, binary_repr, log2, ispower2,\
-        bivariate_normal, load, save, stineman_interp
+        bivariate_normal, load, save
 
+from matplotlib.numerical_methods import stineman_interp, slopes, \
+    stineman_interp, inside_poly, poly_below, poly_between, \
+    is_closed_polygon, path_length, distances_along_curve, vector_lengths
+
 from numpy import *
 from numpy.fft import *
 from numpy.random import *
@@ -237,10 +241,10 @@
      find, longest_contiguous_ones, longest_ones, prepca, prctile, prctile_rank, \
      center_matrix, rk4, bivariate_normal, get_xyz_where, get_sparse_matrix, dist, \
      dist_point_to_segment, segments_intersect, fftsurr, liaupunov, movavg, \
-     save, load, slopes, stineman_interp, inside_poly, poly_below, poly_between, exp_safe, \
+     save, load, exp_safe, \
      amap, rms_flat, l1norm, l2norm, norm_flat, frange, diagonal_matrix, identity, \
      base_repr, binary_repr, log2, ispower2, fromfunction_kw, rem, norm, orth, rank, sqrtm,\
-     mfuncC, approx_real, rec_append_field, rec_drop_fields, rec_join, csv2rec, rec2csv
+     mfuncC, approx_real, rec_append_field, rec_drop_fields, rec_join, csv2rec, rec2csv, isvector
 
 
 
Index: lib/matplotlib/blocking_input.py
===================================================================
--- lib/matplotlib/blocking_input.py	(revision 6074)
+++ lib/matplotlib/blocking_input.py	(working copy)
@@ -113,10 +113,15 @@
     """
     Class that creates a callable object to retrieve mouse clicks in a
     blocking way.
+
+    This class will also retrieve keyboard clicks and treat them like 
+    appropriate mouse clicks (delete and backspace are like mouse button 3,
+    enter is like mouse button 2 and all others are like mouse button 1).
     """
     def __init__(self, fig):
         BlockingInput.__init__(self, fig=fig,
-                               eventslist=('button_press_event',) )
+                               eventslist=('button_press_event',
+                                           'key_press_event') )
 
     def post_event(self):
         """
@@ -124,17 +129,17 @@
         """
         assert len(self.events)>0, "No events yet"
 
+        if self.events[-1].name == 'key_press_event':
+            self.key_event()
+        else:
+            self.mouse_event()
+            
+    def mouse_event(self):
+        '''Process a mouse click event'''
+
         event = self.events[-1]
         button = event.button
 
-        # Using additional methods for each button is a bit overkill
-        # for this class, but it allows for easy overloading.  Also,
-        # this would make it easy to attach other type of non-mouse
-        # events to these "mouse" actions.  For example, the matlab
-        # version of ginput also allows you to add points with
-        # keyboard clicks.  This could easily be added to this class
-        # with relatively minor modification to post_event and
-        # __init__.
         if button == 3:
             self.button3(event)
         elif button == 2:
@@ -142,6 +147,22 @@
         else:
             self.button1(event)
 
+    def key_event(self):
+        '''
+        Process a key click event.  This maps certain keys to appropriate
+        mouse click events.
+        '''
+        
+        event = self.events[-1]
+        key = event.key
+
+        if key == 'backspace' or key == 'delete':
+            self.button3(event)
+        elif key == 'enter':
+            self.button2(event)
+        else:
+            self.button1(event)
+
     def button1( self, event ):
         """
         Will be called for any event involving a button other than
@@ -240,8 +261,8 @@
 
 class BlockingContourLabeler( BlockingMouseInput ):
     """
-    Class that creates a callable object that uses mouse clicks on a
-    figure window to place contour labels.
+    Class that creates a callable object that uses mouse clicks or key
+    clicks on a figure window to place contour labels.
     """
     def __init__(self,cs):
         self.cs = cs
Index: lib/matplotlib/mlab.py
===================================================================
--- lib/matplotlib/mlab.py	(revision 6074)
+++ lib/matplotlib/mlab.py	(working copy)
@@ -1292,191 +1292,6 @@
     else: return X
 
 
-def slopes(x,y):
-    """
-    SLOPES calculate the slope y'(x) Given data vectors X and Y SLOPES
-    calculates Y'(X), i.e the slope of a curve Y(X). The slope is
-    estimated using the slope obtained from that of a parabola through
-    any three consecutive points.
-
-    This method should be superior to that described in the appendix
-    of A CONSISTENTLY WELL BEHAVED METHOD OF INTERPOLATION by Russel
-    W. Stineman (Creative Computing July 1980) in at least one aspect:
-
-    Circles for interpolation demand a known aspect ratio between x-
-    and y-values.  For many functions, however, the abscissa are given
-    in different dimensions, so an aspect ratio is completely
-    arbitrary.
-
-    The parabola method gives very similar results to the circle
-    method for most regular cases but behaves much better in special
-    cases
-
-    Norbert Nemec, Institute of Theoretical Physics, University or
-    Regensburg, April 2006 Norbert.Nemec at physik.uni-regensburg.de
-
-    (inspired by a original implementation by Halldor Bjornsson,
-    Icelandic Meteorological Office, March 2006 halldor at vedur.is)
-    """
-    # Cast key variables as float.
-    x=np.asarray(x, np.float_)
-    y=np.asarray(y, np.float_)
-
-    yp=np.zeros(y.shape, np.float_)
-
-    dx=x[1:] - x[:-1]
-    dy=y[1:] - y[:-1]
-    dydx = dy/dx
-    yp[1:-1] = (dydx[:-1] * dx[1:] + dydx[1:] * dx[:-1])/(dx[1:] + dx[:-1])
-    yp[0] = 2.0 * dy[0]/dx[0] - yp[1]
-    yp[-1] = 2.0 * dy[-1]/dx[-1] - yp[-2]
-    return yp
-
-
-def stineman_interp(xi,x,y,yp=None):
-    """
-    STINEMAN_INTERP Well behaved data interpolation.  Given data
-    vectors X and Y, the slope vector YP and a new abscissa vector XI
-    the function stineman_interp(xi,x,y,yp) uses Stineman
-    interpolation to calculate a vector YI corresponding to XI.
-
-    Here's an example that generates a coarse sine curve, then
-    interpolates over a finer abscissa:
-
-      x = linspace(0,2*pi,20);  y = sin(x); yp = cos(x)
-      xi = linspace(0,2*pi,40);
-      yi = stineman_interp(xi,x,y,yp);
-      plot(x,y,'o',xi,yi)
-
-    The interpolation method is described in the article A
-    CONSISTENTLY WELL BEHAVED METHOD OF INTERPOLATION by Russell
-    W. Stineman. The article appeared in the July 1980 issue of
-    Creative Computing with a note from the editor stating that while
-    they were
-
-      not an academic journal but once in a while something serious
-      and original comes in adding that this was
-      "apparently a real solution" to a well known problem.
-
-    For yp=None, the routine automatically determines the slopes using
-    the "slopes" routine.
-
-    X is assumed to be sorted in increasing order
-
-    For values xi[j] < x[0] or xi[j] > x[-1], the routine tries a
-    extrapolation.  The relevance of the data obtained from this, of
-    course, questionable...
-
-    original implementation by Halldor Bjornsson, Icelandic
-    Meteorolocial Office, March 2006 halldor at vedur.is
-
-    completely reworked and optimized for Python by Norbert Nemec,
-    Institute of Theoretical Physics, University or Regensburg, April
-    2006 Norbert.Nemec at physik.uni-regensburg.de
-
-    """
-
-    # Cast key variables as float.
-    x=np.asarray(x, np.float_)
-    y=np.asarray(y, np.float_)
-    assert x.shape == y.shape
-    N=len(y)
-
-    if yp is None:
-        yp = slopes(x,y)
-    else:
-        yp=np.asarray(yp, np.float_)
-
-    xi=np.asarray(xi, np.float_)
-    yi=np.zeros(xi.shape, np.float_)
-
-    # calculate linear slopes
-    dx = x[1:] - x[:-1]
-    dy = y[1:] - y[:-1]
-    s = dy/dx  #note length of s is N-1 so last element is #N-2
-
-    # find the segment each xi is in
-    # this line actually is the key to the efficiency of this implementation
-    idx = np.searchsorted(x[1:-1], xi)
-
-    # now we have generally: x[idx[j]] <= xi[j] <= x[idx[j]+1]
-    # except at the boundaries, where it may be that xi[j] < x[0] or xi[j] > x[-1]
-
-    # the y-values that would come out from a linear interpolation:
-    sidx = s.take(idx)
-    xidx = x.take(idx)
-    yidx = y.take(idx)
-    xidxp1 = x.take(idx+1)
-    yo = yidx + sidx * (xi - xidx)
-
-    # the difference that comes when using the slopes given in yp
-    dy1 = (yp.take(idx)- sidx) * (xi - xidx)       # using the yp slope of the left point
-    dy2 = (yp.take(idx+1)-sidx) * (xi - xidxp1) # using the yp slope of the right point
-
-    dy1dy2 = dy1*dy2
-    # The following is optimized for Python. The solution actually
-    # does more calculations than necessary but exploiting the power
-    # of numpy, this is far more efficient than coding a loop by hand
-    # in Python
-    yi = yo + dy1dy2 * np.choose(np.array(np.sign(dy1dy2), np.int32)+1,
-                                 ((2*xi-xidx-xidxp1)/((dy1-dy2)*(xidxp1-xidx)),
-                                  0.0,
-                                  1/(dy1+dy2),))
-    return yi
-
-def inside_poly(points, verts):
-    """
-    points is a sequence of x,y points
-    verts is a sequence of x,y vertices of a poygon
-
-    return value is a sequence of indices into points for the points
-    that are inside the polygon
-    """
-    res, =  np.nonzero(nxutils.points_inside_poly(points, verts))
-    return res
-
-def poly_below(xmin, xs, ys):
-    """
-    given a sequence of xs and ys, return the vertices of a polygon
-    that has a horzontal base at xmin and an upper bound at the ys.
-    xmin is a scalar.
-
-    intended for use with Axes.fill, eg
-    xv, yv = poly_below(0, x, y)
-    ax.fill(xv, yv)
-    """
-    xs = np.asarray(xs)
-    ys = np.asarray(ys)
-    Nx = len(xs)
-    Ny = len(ys)
-    assert(Nx==Ny)
-    x = xmin*np.ones(2*Nx)
-    y = np.ones(2*Nx)
-    x[:Nx] = xs
-    y[:Nx] = ys
-    y[Nx:] = ys[::-1]
-    return x, y
-
-
-def poly_between(x, ylower, yupper):
-    """
-    given a sequence of x, ylower and yupper, return the polygon that
-    fills the regions between them.  ylower or yupper can be scalar or
-    iterable.  If they are iterable, they must be equal in length to x
-
-    return value is x, y arrays for use with Axes.fill
-    """
-    Nx = len(x)
-    if not cbook.iterable(ylower):
-        ylower = ylower*np.ones(Nx)
-
-    if not cbook.iterable(yupper):
-        yupper = yupper*np.ones(Nx)
-
-    x = np.concatenate( (x, x[::-1]) )
-    y = np.concatenate( (yupper, ylower[::-1]) )
-    return x,y
-
 ### the following code was written and submitted by Fernando Perez
 ### from the ipython numutils package under a BSD license
 # begin fperez functions
@@ -1755,6 +1570,18 @@
     else:
         return len(bin_n)
 
+def isvector(X):
+    """
+    Like the Matlab (TM) function with the same name, returns true if
+    the supplied numpy array or matrix looks like a vector, meaning it
+    has a one non-singleton axis (i.e., it can have multiple axes, but
+    all must have length 1, except for one of them).
+
+    If you just want to see if the array has 1 axis, use X.ndim==1
+
+    """
+    return np.prod(X.shape)==np.max(X.shape)
+
 #from numpy import fromfunction as fromfunction_kw
 def fromfunction_kw(function, dimensions, **kwargs):
     """Drop-in replacement for fromfunction() from numpy
Index: lib/matplotlib/figure.py
===================================================================
--- lib/matplotlib/figure.py	(revision 6074)
+++ lib/matplotlib/figure.py	(working copy)
@@ -1028,12 +1028,18 @@
         This will wait for *n* clicks from the user and return a list of the
         coordinates of each click.
 
-        If *timeout* is negative, does not timeout.
+        If *timeout* is zero negative, does not timeout.
 
-        If *n* is negative, accumulate clicks until a middle click
-        terminates the input.
+        If *n* is zero or negative, accumulate clicks until a middle click
+        (or potentially both mouse buttons at once) terminates the input.
 
         Right clicking cancels last input.
+
+        The keyboard can also be used to select points in case your mouse
+        does not have one or more of the buttons.  The delete and backspace
+        keys act like right clicking (i.e., remove last point), the enter key
+        terminates input and any other key (not already used by the window
+        manager) selects a point.
         """
 
         blocking_mouse_input = BlockingMouseInput(self)
Index: API_CHANGES
===================================================================
--- API_CHANGES	(revision 6074)
+++ API_CHANGES	(working copy)
@@ -19,6 +19,10 @@
   maintained for the moment (in addition to their renamed versions), but they
   are depricated and will eventually be removed.
 
+* Moved several function in mlab.py into a separate module 
+  numerical_methods.py because they were unrelated to the initial purpose of
+  mlab and appeared more coherent elsewhere.
+
 Changes for 0.98.1
 ==================
 
Index: examples/pylab_examples/interp_demo.py
===================================================================
--- examples/pylab_examples/interp_demo.py	(revision 6074)
+++ examples/pylab_examples/interp_demo.py	(working copy)
@@ -1,6 +1,6 @@
 from matplotlib.pyplot import figure, show
 from numpy import pi, sin, linspace
-from matplotlib.mlab import stineman_interp
+from matplotlib.numerical_methods import stineman_interp
 
 x = linspace(0,2*pi,20);
 y = sin(x); yp = None
Index: examples/pylab_examples/fill_between.py
===================================================================
--- examples/pylab_examples/fill_between.py	(revision 6074)
+++ examples/pylab_examples/fill_between.py	(working copy)
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-import matplotlib.mlab as mlab
+import matplotlib.numerical_methods as numerical_methods
 from pylab import figure, show
 import numpy as np
 
@@ -13,15 +13,15 @@
 ax3 = fig.add_subplot(313)
 
 
-xs, ys = mlab.poly_between(x, 0, y1)
+xs, ys = numerical_methods.poly_between(x, 0, y1)
 ax.fill(xs, ys)
 ax.set_ylabel('between y1 and 0')
 
-xs, ys = mlab.poly_between(x, y1, 1)
+xs, ys = numerical_methods.poly_between(x, y1, 1)
 ax2.fill(xs, ys)
 ax2.set_ylabel('between y1 and 1')
 
-xs, ys = mlab.poly_between(x, y1, y2)
+xs, ys = numerical_methods.poly_between(x, y1, y2)
 ax3.fill(xs, ys)
 ax3.set_ylabel('between y1 and y2')
 ax3.set_xlabel('x')
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

Reply via email to