1

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?

Ajean
  • 5,528
  • 14
  • 46
  • 69
  • please [edit] your question to list your imports, so we can run your program as well. Also, have you tried running this from the IPython console, notebook, or qtconsole to see if it works there? The buffering very well could be a Spyder thing... – MattDMo Jan 27 '14 at 21:03
  • I've updated the code with imports ... I'll try the qtconsole to see what happens... – Ajean Jan 27 '14 at 21:39
  • I tried it in the iPython qtconsole and got the same thing, but then tried it in a "normal" iPython console outside of Spyder and got it to work right. Hmmm. – Ajean Jan 27 '14 at 22:53

1 Answers1

1

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()
Community
  • 1
  • 1
Ajean
  • 5,528
  • 14
  • 46
  • 69