Matplotlib runtime error

Gurus,

I try to transfer an image file via a pair of USRPs.
At the receiver side, the data is fed into a custom block, where it
plots
the image in realtime using matplotlib’s pyplot.imshow().
Unfortunately, in the work() function, the pyplot.draw() causes below
runtime error.

handler caught exception: main thread is not in main loop
Traceback (most recent call last):
File “/usr/local/lib/python2.7/dist-packages/gnuradio/gr/gateway.py”,
line 55, in eval
try: self._callback()
File “/usr/local/lib/python2.7/dist-packages/gnuradio/gr/gateway.py”,
line 160, in __gr_block_handle
) for i in self.__out_indexes],
File
“/usr/local/lib/python2.7/dist-packages/activecat/image_sink1.py”,
line 72, in work
self.axes1.figure.canvas.draw() #pyplot.draw()
File
“/usr/lib/pymodules/python2.7/matplotlib/backends/backend_tkagg.py”,
line 349, in draw
tkagg.blit(self._tkphoto, self.renderer._renderer, colormode=2)
File “/usr/lib/pymodules/python2.7/matplotlib/backends/tkagg.py”, line
13, in blit
tk.call(“PyAggImagePhoto”, photoimage, id(aggimage), colormode,
id(bbox_array))
RuntimeError: main thread is not in main loop
thread[thread-per-block[1]: <block image_sink1 (2)>]: caught
unrecognized
exception

The custom block (perform plotting) is written in Python, as below:

#!/usr/bin/env python

-- coding: utf-8 --

import numpy
from gnuradio import gr
from matplotlib import image, pyplot

class image_sink1(gr.sync_block):

def __init__(self):
    gr.sync_block.__init__( self, name="image_sink1",
        in_sig=[ numpy.complex64 ],
        out_sig=None)

    pyplot.figure()
    pyplot.ion()
    pyplot.show()

    self.axes1 = pyplot.gca()
    #self.win   = self.axes1.figure.canvas.manager.window
    #self.win.after(100,animate)

    self.completed = False
    self.img2 = numpy.zeros( (150,150,4), numpy.uint8 )

    self.coordinate = self.coordinate_stream()


def coordinate_stream(self):
    for y in range(150):
        for x in range( 0, 150, 2 ):
            yield y,x

def work(self, input_items, output_items):
    in0 = input_items[0]

    if self.completed:
        return -1

    for sample1 in in0:
        try:
            y,x = next( self.coordinate )

            if sample1.real > 0:
                self.img2[y,x] = numpy.array([255,255,255,255])
            else:
                self.img2[y,x] = numpy.array([0,0,0,255])

            if sample1.imag > 0:
                self.img2[y,x+1] = numpy.array([255,255,255,255])
            else:
                self.img2[y,x+1] = numpy.array([0,0,0,255])

        except StopIteration:
            print "Receiver side completed!"
            self.complete = True

    self.axes1.imshow( self.img2 )

    self.axes1.figure.canvas.draw()   # or, pyplot.draw(), both 

gives
error !!!

    return in0.size

Please advise,
thanks in advance.

On Fri, May 2, 2014 at 8:49 AM, Marcus Müller
[email protected]wrote:

out of your flow graph into your GUI.

Greetings,
Marcus

Tim’s written a number of blocks like this:

Tom

Hi Activecat,

typical GUI problem; background is that X applications are inherently
hard
to multithread, which basically requires graphical toolkits to run in a
main loop. This conflicts with every block being run in its own thread.

The easiest solution nowadays should be that you generate a QT flow
graph
in GRC, use PyQT to generate your GUI, register a message handler and
integrate matplotlib (there are examples out there, just don’t have one
at
my fingertips right now), and use the message passing interface to get
data
out of your flow graph into your GUI.

Greetings,
Marcus

On Fri, May 2, 2014 at 8:56 PM, Tom R. [email protected] wrote:

integrate matplotlib (there are examples out there, just don’t have one at

Tom

I am now learning Qt in order to use it with gnuradio.
Q1: In gnuradio we use Qt Widgets, but not Qt Quick at all. Is this
correct?
Q2: In roadmap when will gnuradio start to use Qt5, gnuradio v3.8 …?


Discuss-gnuradio mailing list
[email protected]
https://lists.gnu.org/mailman/listinfo/discuss-gnuradio

On Thu, May 8, 2014 at 3:30 AM, Activecat [email protected] wrote:

Tim’s written a number of blocks like this:

GitHub - osh/gr-pyqt: pyqt based plotters intended for plotting bursted events in gnu radio

Tom

I am now learning Qt in order to use it with gnuradio.
Q1: In gnuradio we use Qt Widgets, but not Qt Quick at all. Is this
correct?

Correct.

Q2: In roadmap when will gnuradio start to use Qt5, gnuradio v3.8 …?

Uncertain. I haven’t spent enough time, yet, with QT5 to know for sure
and
determine what we get (features) and what we lose (older distro
support).
More likely, this will be a 3.9 thing.

Tom

On Sun, May 18, 2014 at 9:00 AM, Marcus Müller
[email protected]wrote:

As I explained, you’ll have a hard time getting GUI to run in a block,
Marcus

I agree with Marcus. Don’t try and use/abuse matplotlib for this
purpose. I
pointed to Tim’s repo of PyQT/QWT blocks to show you how to use those
tools
to build GUIs in Python blocks.

Tom

On Mon, May 19, 2014 at 12:52 AM, Tom R. [email protected] wrote:

about your approach.

Greetings,
Marcus

I agree with Marcus. Don’t try and use/abuse matplotlib for this purpose.
I pointed to Tim’s repo of PyQT/QWT blocks to show you how to use those
tools to build GUIs in Python blocks.

Tom

Thank you very much.

Hi,
I think real-time and matplotlib kind of contradict in the first place -
really, matplotlib’s performance is terrible. As a rule, it’s Assisi
generally a bad idea to let your data file update your GUI. Usually, you
want something like a check every tenth of a second, if data has
arrived, and then updating your GUI accordingly. Otherwise, you will
either end up with refresh rates that are unnecessarily high (e.g.
200fps) or a GUI not reacting to events (e.g. resizing) by redrawing. So
that’s two things bad about your approach.

As I explained, you’ll have a hard time getting GUI to run in a block,
since by principle, GR blocks can not run in the main thread, and things
like Tim’s qwt plot go through death, wind, fire and message passing to
get data out of the blocks’ threads and into the GUI thread.

Anyway, with matplotlib and pyqt to wrap the canvas in a qt application
and a little googling you can hack together guis that should work with
the qt generate option - no guarantee though. I’d rather get used to qwt
in most cases than stick with matplotlib…

Greetings,
Marcus