简体   繁体   中英

Event lag in matplotlib mpl_connect when run from iPython shell

I am attempting to write a very simple little 'gui' which will allow the user to click on an image and have the position and the value printed to the screen. What I have works, but I've discovered that when running it from an iPython shell, there is a 1-event delay in the printed output.

When I run the routine, the first click doesn't do anything. The second click allows the printed output from the first click to show up. The routine exits okay when I right-click (which is what I want), but oddly enough there must be a buffer still around because if I run the routine again, the values from that last click get printed before I even do anything.

Here is the code:

import matplotlib.pyplot as plt
import numpy as np

def pickPoint(data):
    """Displays a 2D array on the screen and prints data info based upon user clicks."""

    def pickPointSelectVal(event):
        if event.button == 3:
            fig.canvas.mpl_disconnect(cid)
            plt.close(fig)
        else:
            print 'got click: ', event.x, ',', event.y, ' value: ', data[event.x,event.y]

    dims = data.shape
    dpi = 96.0
    fdims = (x/dpi for x in dims)

    fig = plt.figure(figsize=fdims, dpi=dpi)
    plt.figimage(data.transpose(),origin='lower',cmap='gray')
    cid = fig.canvas.mpl_connect('button_press_event', pickPointSelectVal)

if __name__ == "__main__":
    a = np.arange(500)
    b = np.reshape(np.repeat(a,100),(500,100))
    c = b * np.reshape(np.repeat(np.arange(100),500),(100,500)).transpose()
    pickPoint(c)

running it twice with a few clicks only on the first time yields the following output:

In [1]: pickPoint(c)
got click:  60 , 80.0  value:  4800
got click:  45 , 25.0  value:  1125
got click:
In [2]: pickPoint(c)
 267 , 76.0  value:  20292

"c" is dummy array. Note that this delay doesn't happen when I run the same routine from a normal Python shell, but it also doesn't appear to exit correctly in that case. I'd love to know what the difference is, and if there is something kooky with what I've written.

I'm running this inside Spyder 2.2.5 from an install of Anaconda 1.8 on Windows 7 64-bit.

ADD: I have tried this in iPython qtconsole and plain iPython, both using the Qt4Agg backend. The problem occurs when using qtconsole, but not when using plain iPython. Does someone know how events may be handled differently between the two?

Well, I managed to track this down - it turns out that this is an known issue with QtConsole, and the underlying cause is the same as this question (both Canopy and Spyder use ipython qtconsole in their GUIs). The issue is that the first print doesn't trigger a flush of stdout (a much better explanation from a couple years ago can be found here ), so you have to a) do it manually, as below, or b) use ipython -u for unbuffered output, which I haven't tried. Flushing manually will work fine for me, so I'll go with that for now.

If I add the following to my code it works as expected:

import sys

# (put this after the print statement)
sys.stdout.flush()

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM