ginput in pylab

For those who have never used matlab, ginput is a blocking

    > call that takes one optional argument n, waits for n click
    > on the current figure, and returns the coordinates of those
    > n clicks. I have been trying to write such a function in
    > pylab and I can't find a solution.

blocking calls in pylab with gtk threading may be possible but it is
beyond my powers. I would write this with a callback, eg create a
class that takes a callback in the constructor and calls the callback
after n clicks with a list of n coords. blocking input calls may be
easier in tkagg. If there is a gtk/threading guru on hand, I'd be
interested if anyone has ideas on how to do this.

JDH

Yes this is the right way of doing this (I have been experimenting a bit
yesterday). However have a blocking call would be really nice for casual
programmers, like so many physicists, who have no idea what eventloops
and threads are.

I think that for such a blocking call to work, all we would need is a
way to start and stop the eventloop (I am talking in wx terms, the only
GUI toolkit I know). That way when a script call ginput the ginput call
adds a few callbacks to the canvas (that's the easy part) and starts the
eventloop. The callbacks stop the eventloop when the right number of
points as been acquired.

Now I have no clue if this is possible, but that would certainly make
writing small interactive scripts much easier.

Cheers,

Gaël

···

On Mon, Oct 30, 2006 at 08:21:20AM -0600, John Hunter wrote:

blocking calls in pylab with gtk threading may be possible but it is
beyond my powers. I would write this with a callback, eg create a
class that takes a callback in the constructor and calls the callback
after n clicks with a list of n coords.

Gael Varoquaux wrote:

I think that for such a blocking call to work, all we would need is a
way to start and stop the eventloop (I am talking in wx terms, the only
GUI toolkit I know).

That's a trick, because if you stop the event loop, then you don't get the mouse clicks...

However, perhaps you can take advantage of a similar feature (at least in wx) -- can you make the Frame Modal temporarily? My understanding of how model dialogs work is that they stop the main event loop, and then have their own event loop, for just that frame -- then you could catch the mouse event you want, and make it non-modal again.

What I don't know is if you can make a Frame model/non-model without hiding and showing it in the process...

I also don't know if other toolkits work similarly.

-Chris

···

--
Christopher Barker, Ph.D.
Oceanographer
                                         
NOAA/OR&R/HAZMAT (206) 526-6959 voice
7600 Sand Point Way NE (206) 526-6329 fax
Seattle, WA 98115 (206) 526-6317 main reception

Chris.Barker@...236...

I far as I have seen in ipython the execution of a script blocks the
eventloop. Now in another shell if the shell is not aware of the event
loop, calling show() will block until the windows is closed (that might be
a good blocking call for my purpose). This leaves us with the case where
the shell is a wx shell and lives in the eventloop. A wx guru would
probably give us the solution here.

Now I am probably talking nonsense, as I don't know much about gui and
event loop, but it does look like there might be a solution (and the
chances that I actually implement this are close to zero, given my
knowledge of these things).

    GaÃl

···

On Mon, Oct 30, 2006 at 10:36:09AM -0800, Christopher Barker wrote:

However, perhaps you can take advantage of a similar feature (at least
in wx) -- can you make the Frame Modal temporarily? My understanding of
how model dialogs work is that they stop the main event loop, and then
have their own event loop, for just that frame -- then you could catch
the mouse event you want, and make it non-modal again.

Jut to clarify, Gael: in ipython (with -pylab or -{g,w,q}thread), what
happens is that IPython lets the GUI toolkit run in the main thread,
and then attaches its own routines for user code execution as the
toolkit's idle timer callback and runs in a secondary thread (each
toolkit has its own way of doing this, but the basic idea is the
same).

The only blocking that you see comes from blocking code which your
scripts may call (typically extension code, C, Fortran, etc), since at
that point the Python interpreter can't switch out of this secondary
thread. But as long as your scripts do NOT call any extension
blocking code, the Python interpreter will switch out every 100
bytecodes between your user code and the main thread.

This two-thread arrangement has a big drawback: the inability to
interrupt long-running calculations (even non-blocking ones) with
Ctrl-C, because it is simply impossible in Python to toss asynchronous
signals accross threads. And yes, I've tried even using the
undocumented Python C-API for cross-thread asynchronous signals via
this recipe:

http://sebulba.wikispaces.com/recipe+thread2

I spent some time on this, unsuccessfully. I still don't understand
why it doesn't work, since what I'm trying to do seems to be exactly
what that recipe is for. If anyone ever gets this to work, *please*
send it to me. It would be a major usability improvement to get
interruptibility of long computations in the threaded Pylab
environments (GTK, QT and Wx). In fact, this is part of the reason
why I'm resisting a switch to Wx: I really hate not being able to
cleanly stop a computation that is taking longer than I meant, or
which I accidentally started.

Cheers,

f

···

On 10/30/06, Gael Varoquaux <gael.varoquaux@...427...> wrote:

On Mon, Oct 30, 2006 at 10:36:09AM -0800, Christopher Barker wrote:
> However, perhaps you can take advantage of a similar feature (at least
> in wx) -- can you make the Frame Modal temporarily? My understanding of
> how model dialogs work is that they stop the main event loop, and then
> have their own event loop, for just that frame -- then you could catch
> the mouse event you want, and make it non-modal again.

I far as I have seen in ipython the execution of a script blocks the
eventloop. Now in another shell if the shell is not aware of the event
loop, calling show() will block until the windows is closed (that might be
a good blocking call for my purpose). This leaves us with the case where
the shell is a wx shell and lives in the eventloop. A wx guru would
probably give us the solution here.

Jut to clarify, Gael: in ipython (with -pylab or -{g,w,q}thread), what
happens is that IPython lets the GUI toolkit run in the main thread,
and then attaches its own routines for user code execution as the
toolkit's idle timer callback and runs in a secondary thread (each
toolkit has its own way of doing this, but the basic idea is the
same).

OK, similar to launching a wx application and starting a thread in it
with ipython attached to this thread ? Is there a "hook" to the main
eventloop that would be accessible to the code running in ipython. Thus
a wx.CallAfter or alike in different toolkits, and other eventloop and
multi-threaded programming tricks might be useful here. Maybe this
solution would even provide the solution for blocking calls with MPL
with most multi-threaded cases.

The problem I hit in my first attempt was that the "connect" call
executed in my function did not seem to be executed until the function
returned. If I can connect a callback to the figure in the beginning of
the function, then loop waiting and checking a parameter the will be set
be the callback, then process the parameter when available.

I do not see why this could not work, but then my understanding of
multithreaded programming is quite poor.

This two-thread arrangement has a big drawback: the inability to
interrupt long-running calculations (even non-blocking ones) with
Ctrl-C, because it is simply impossible in Python to toss asynchronous
signals accross threads.

Yes :-<. Have you tried getting some help from a guru, it seems to be
worth the while.

Cheers,

GaÃl

···

On Mon, Oct 30, 2006 at 12:37:42PM -0700, Fernando Perez wrote: