Hi,
Following Gael Varoquaux's lead on adding a ginput command to matplotlib
(nice job!), I added a waitforbuttonpress function to matplotlib. The
patch is attached (generate using svn diff from the
matplotlib/trunk/matplotlib directory). waitforbuttonpress is a simple
function with a matlab equivalent that returns a list of true/false's -
true for a keyboard click and false for a mouse click. I use it in
matlab regularly as a simple yes/no question (often to decide whether or
not to save a figure).
The way I have implemented it is by adding an additional class
BlockingKeyMouseInput, which is quite similar to BlockingMouseInput, but
waits for both key and mouse events. A smarter person than I could
probably combine these two classes and make something that would serve
both functions. But I am basically new to python and don't feel
comfortable. Perhaps someone else could take a look and make
improvements/simplifications?
The other thing that I have noticed with both ginput and
waitforbuttonpress is that if you use ctrl-c to break out of either,
then the callback functions remain attached to their respective events
(e.g., try ginput(n=-1,timeout=-1,verbose=True) and hit ctrl-c). This
probably isn't a huge problem, but it would be nice if there was a way
to say "if ctrl-c is pressed, cleanup nicely". Does someone know if
that is possible?
Cheers,
David
--
**********************************
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
Assistant Researcher
UCSC / Institute of Marine Sciences
Ocean Sciences
1156 High St.
SC, CA 95064
Phone: 831-459-4789
Fax: 831-459-4882
http://pmc.ucsc.edu/~dmk/
**********************************
Index: lib/matplotlib/pyplot.py
===================================================================
--- lib/matplotlib/pyplot.py (revision 5735)
+++ lib/matplotlib/pyplot.py (working copy)
@@ -335,7 +335,21 @@
if Figure.ginput.__doc__ is not None:
ginput.__doc__ = dedent(Figure.ginput.__doc__)
+def waitforbuttonpress(*args, **kwargs):
+ """
+ Blocking call to interact with the figure.
+ This will wait for *n* key or mouse clicks from the user and
+ return a list containing True's for keyboard clicks and False's
+ for mouse clicks.
+
+ If *timeout* is negative, does not timeout.
+ """
+ return gcf().waitforbuttonpress(*args, **kwargs)
+if Figure.waitforbuttonpress.__doc__ is not None:
+ waitforbuttonpress.__doc__ = dedent(Figure.waitforbuttonpress.__doc__)
+
+
# Putting things in figures
def figtext(*args, **kwargs):
Index: lib/matplotlib/figure.py
===================================================================
--- lib/matplotlib/figure.py (revision 5735)
+++ lib/matplotlib/figure.py (working copy)
@@ -6,6 +6,9 @@
:class:`SubplotParams`
control the default spacing of the subplots
+:class:`BlockingKeyMouseInput`
+ creates a callable object to retrieve key or mouse clicks in a blocking way for interactive sessions
+
:class:`BlockingMouseInput`
creates a callable object to retrieve mouse clicks in a blocking way for interactive sessions
@@ -118,6 +121,78 @@
setattr(self, s, val)
+class BlockingKeyMouseInput(object):
+ """
+ Class that creates a callable object to retrieve key or mouse clicks in a
+ blocking way.
+ """
+ def __init__(self, fig):
+ self.fig = fig
+
+
+ def on_mouse_click(self, event):
+ """
+ Event handler that will be passed to the current figure to
+ retrieve clicks.
+ """
+ self.events.append(event)
+ self.buttons.append(event.button)
+ self.keyormouse.append(False)
+
+ if len(self.keyormouse) >= self.n:
+ self.done = True
+
+ def on_key_click(self, event):
+ """
+ Event handler that will be passed to the current figure to
+ retrieve key presses.
+ """
+ self.events.append(event)
+ self.keys.append(event.key)
+ self.keyormouse.append(True)
+
+ if len(self.keyormouse) >= self.n:
+ self.done = True
+
+ def __call__(self, n=1, timeout=-1 ):
+ """
+ Blocking call to retrieve n key or mouse events
+ """
+ self.done = False
+ self.keys = []
+ self.buttons = []
+ self.events = []
+ self.keyormouse = []
+
+ 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.callbackm = self.fig.canvas.mpl_connect('button_press_event',
+ self.on_mouse_click)
+ self.callbackk = self.fig.canvas.mpl_connect('key_press_event',
+ self.on_key_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 "Timeout reached";
+ break;
+
+ # Disconnect the event, clean the figure, and return what we have
+ self.fig.canvas.mpl_disconnect(self.callbackm)
+ self.callbackm = None
+ self.fig.canvas.mpl_disconnect(self.callbackk)
+ self.callbackk = None
+ return (self.keyormouse,self.keys,self.buttons,self.events)
+
class BlockingMouseInput(object):
"""
Class that creates a callable object to retrieve mouse clicks in a
@@ -1119,8 +1194,25 @@
return blocking_mouse_input(n=n, timeout=timeout,
verbose=verbose, show_clicks=True)
+ def waitforbuttonpress(self, n=1, timeout=-1):
+ """
+ call signature::
+ waitforbuttonpress(self, n=1, timeout=-1)
+ Blocking call to interact with the figure.
+
+ This will wait for *n* key or mouse clicks from the user and
+ return a list containing True's for keyboard clicks and
+ False's for mouse clicks.
+
+ If *timeout* is negative, does not timeout.
+ """
+
+ blocking_input = BlockingKeyMouseInput(self)
+ return blocking_input(n=n, timeout=timeout)[0]
+
+
def figaspect(arg):
"""
Create a figure with specified aspect ratio. If *arg* is a number,
-------------------------------------------------------------------------
Sponsored by: SourceForge.net Community Choice Awards: VOTE NOW!
Studies have shown that voting for your favorite open source project,
along with a healthy diet, reduces your potential for chronic lameness
and boredom. Vote Now at http://www.sourceforge.net/community/cca08
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel