On Thu, Jan 31, 2008 at 04:41:41PM +0100, Gael Varoquaux wrote:
> > If this seems like a good organization to you, I'll wait for a new
> > patch and then contribute that.
> Give me a few days, but it will come.
Here is the new patch. I added visual feedback when accumulating points.
I hope the docstrings are clear.
Cheers,
Gaƫl
Index: backend_bases.py
===================================================================
--- backend_bases.py (revision 4908)
+++ backend_bases.py (working copy)
@@ -1151,7 +1151,13 @@
"""
return self.callbacks.disconnect(cid)
+ def flush_events(self):
+ """ Flush the GUI events for the figure. Implemented only for
+ backends with GUIs.
+ """
+ raise NotImplementedError
+
class FigureManagerBase:
"""
Helper class for matlab mode, wraps everything up into a neat bundle
Index: pyplot.py
===================================================================
--- pyplot.py (revision 4908)
+++ pyplot.py (working copy)
@@ -272,6 +272,20 @@
if Figure.savefig.__doc__ is not None:
savefig.__doc__ = dedent(Figure.savefig.__doc__)
+def ginput(*args, **kwargs):
+ """
+ Blocking call to interact with the figure.
+
+ 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.
+ """
+ return gcf().ginput(*args, **kwargs)
+if Figure.ginput.__doc__ is not None:
+ ginput.__doc__ = dedent(Figure.ginput.__doc__)
+
+
# Putting things in figures
def figtext(*args, **kwargs):
Index: figure.py
===================================================================
--- figure.py (revision 4908)
+++ figure.py (working copy)
@@ -2,6 +2,7 @@
Figure class -- add docstring here!
"""
import numpy as npy
+import time
import artist
from artist import Artist
@@ -96,6 +97,83 @@
setattr(self, s, val)
+class BlockingMouseInput(object):
+ """ Class that creates a callable object to retrieve mouse clicks in a
+ blocking way.
+ """
+ def __init__(self, fig):
+ self.fig = fig
+
+
+ def on_click(self, event):
+ """ Event handler that will be passed to the current figure to
+ retrieve clicks.
+ """
+ if event.button == 3:
+ # If it's a right click, pop the last coordinates.
+ if len(self.clicks) > 0:
+ self.clicks.pop()
+ if self.show_clicks:
+ mark = self.marks.pop()
+ mark.remove()
+ self.fig.canvas.draw()
+ elif event.button == 2 and self.n < 0:
+ # If it's a middle click, and we are in infinite mode, finish
+ self.done = True
+ elif event.inaxes:
+ # If it's a valid click, append the coordinates to the list
+ self.clicks.append((event.xdata, event.ydata))
+ if self.verbose:
+ print "input %i: %f,%f" % (len(self.clicks),
+ event.xdata, event.ydata)
+ if self.show_clicks:
+ self.marks.extend(
+ event.inaxes.plot([event.xdata,], [event.ydata,], 'r+') )
+ self.fig.canvas.draw()
+ if self.n > 0 and len(self.clicks) >= self.n:
+ self.done = True
+
+
+ def __call__(self, n=1, timeout=30, verbose=False, show_clicks=True):
+ """ Blocking call to retrieve n coordinate pairs through mouse
+ clicks.
+ """
+ self.verbose = verbose
+ self.done = False
+ self.clicks = []
+ self.show_clicks = True
+ self.marks = []
+
+ assert isinstance(n, int), "Requires an integer argument"
+ self.n = n
+
+ # Ensure that the figure is shown
+ self.fig.show()
+ # connect the click events to the on_click function call
+ self.callback = self.fig.canvas.mpl_connect('button_press_event',
+ self.on_click)
+ # wait for n clicks
+ counter = 0
+ while not self.done:
+ self.fig.canvas.flush_events()
+ time.sleep(0.01)
+
+ # check for a timeout
+ counter += 1
+ if timeout > 0 and counter > timeout/0.01:
+ print "ginput timeout";
+ break;
+
+ # Disconnect the event, clean the figure, and return what we have
+ self.fig.canvas.mpl_disconnect(self.callback)
+ self.callback = None
+ if self.show_clicks:
+ for mark in self.marks:
+ mark.remove()
+ self.fig.canvas.draw()
+ return self.clicks
+
+
class Figure(Artist):
def __str__(self):
@@ -892,8 +970,24 @@
ax.update_params()
ax.set_position(ax.figbox)
+ def ginput(self, n=1, timeout=30, verbose=False, show_clicks=True):
+ """
+ ginput(self, n=1, timeout=30, verbose=False, show_clicks=True)
+
+ Blocking call to interact with the figure.
+ 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 n is negative, accumulate clicks until a middle
+ click terminates the input. Right clicking cancels last input.
+ """
+ blocking_mouse_input = BlockingMouseInput(self)
+ return blocking_mouse_input(n=n, timeout=timeout,
+ verbose=verbose, show_clicks=True)
+
+
+
def figaspect(arg):
"""
Create a figure with specified aspect ratio. If arg is a number,
Index: backends/backend_qt.py
===================================================================
--- backends/backend_qt.py (revision 4908)
+++ backends/backend_qt.py (working copy)
@@ -175,6 +175,9 @@
return key
+ def flush_events(self):
+ qt.qApp.processEvents()
+
class FigureManagerQT( FigureManagerBase ):
"""
Public attributes
Index: backends/backend_gtk.py
===================================================================
--- backends/backend_gtk.py (revision 4908)
+++ backends/backend_gtk.py (working copy)
@@ -386,6 +386,13 @@
def get_default_filetype(self):
return 'png'
+ def flush_events(self):
+ gtk.gdk.threads_enter()
+ while gtk.events_pending():
+ gtk.main_iteration(True)
+ gtk.gdk.flush()
+ gtk.gdk.threads_leave()
+
class FigureManagerGTK(FigureManagerBase):
"""
Index: backends/backend_tkagg.py
===================================================================
--- backends/backend_tkagg.py (revision 4908)
+++ backends/backend_tkagg.py (working copy)
@@ -269,8 +269,9 @@
key = self._get_key(event)
FigureCanvasBase.key_release_event(self, key, guiEvent=event)
+ def flush_events(self):
+ self._master.update()
-
class FigureManagerTkAgg(FigureManagerBase):
"""
Public attributes
Index: backends/backend_wx.py
===================================================================
--- backends/backend_wx.py (revision 4908)
+++ backends/backend_wx.py (working copy)
@@ -1301,6 +1301,9 @@
wxapp.Yield()
return True
+ def flush_events(self):
+ wx.Yield()
+
class FigureManagerWx(FigureManagerBase):
"""
This class contains the FigureCanvas and GUI frame
Index: backends/backend_qt4.py
===================================================================
--- backends/backend_qt4.py (revision 4908)
+++ backends/backend_qt4.py (working copy)
@@ -13,7 +13,7 @@
from matplotlib.mathtext import MathTextParser
from matplotlib.widgets import SubplotTool
-from PyQt4 import QtCore, QtGui
+from PyQt4 import QtCore, QtGui, Qt
backend_version = "0.9.1"
def fn_name(): return sys._getframe(1).f_code.co_name
@@ -174,6 +174,9 @@
return key
+ def flush_events(self):
+ Qt.qApp.processEvents()
+
class FigureManagerQT( FigureManagerBase ):
"""
Public attributes
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel