discuss-gnuradio
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Discuss-gnuradio] matplotlib runtime error


From: Marcus Müller
Subject: Re: [Discuss-gnuradio] matplotlib runtime error
Date: Sun, 18 May 2014 15:00:11 +0200
User-agent: K-9 Mail for Android

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


On May 18, 2014 2:25:00 PM CEST, Activecat <address@hidden> wrote:
On Fri, May 2, 2014 at 8:56 PM, Tom Rondeau <address@hidden> wrote:
On Fri, May 2, 2014 at 8:49 AM, Marcus Müller <address@hidden> wrote:
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

Tim's written a number of blocks like this:

Tom



The examples (https://github.com/osh/gr-pyqt) are using Qt and Qwt to plot graphs, not matplotlib.
(When all the "import pylab" are removed, everything still work as usual, except for pylab.fftshift ).

In order to stick to matplotlib, I created a custom block, register a message handler, and use the message passing interface to get data out from the flowgraph into the custom block. (Everything is as described by Marcus as above, except I do not use QT.)
For this flowgraph, Generate-Option="No GUI"

When I put "self.axes1.figure.canvas.draw()"  or  "pyplot.draw()"  in the message handler, the same error still happens:
ERROR: handler caught exception: main thread is not in main loop

Question: 
How to get rid of this error?
Or, does this mean plotting using matplotlib is not an option ..?

My objective is to plot graphs in realtime using matplotlib.
I try to stick to Matplotlib because it is the tool I that I am using for numerical analysis.



The custom block is coded as:

        #!/usr/bin/env python
        # -*- coding: utf-8 -*-

        import numpy
        from gnuradio import gr

        import pmt
        from matplotlib import pyplot


        class matplotlib4(gr.sync_block):

            def __init__(self):
                gr.sync_block.__init__(self,
                    name="matplotlib4",
                    in_sig=None,
                    out_sig=None)

                pyplot.ion()
                self.fig1 = pyplot.figure()
                self.ax1 = self.fig1.add_subplot(2,1,1)
                self.ax1.set_ylabel('Real')
                self.ax1.set_xlabel('time')
                self.ax1.set_ylim(-1.2, 1.2)
                self.ax1.grid(True)       
                self.line1, = self.ax1.plot( [0.3]*1000 )       
                self.line2, = self.ax1.plot( [0.3]*1000 )       
                self.axes1 = pyplot.gca()
                pyplot.draw()   # no error of "main thread is not in main loop"
                pyplot.show()   # no error of "main thread is not in main loop"

                self.message_port_register_in( pmt.intern("cpdus"))
                self.set_msg_handler(pmt.intern("cpdus"), self.handler4)


            def handler4( self, msg ):
                samples = pmt.cdr(msg)
                data = "" pmt.c32vector_elements(samples), dtype=numpy.complex64 )

                self.line1.set_ydata( data.real )
                self.line2.set_ydata( data.imag )
                #self.fig1.canvas.draw()           # handler caught exception: main thread is not in main loop
                #pyplot.draw()                     # handler caught exception: main thread is not in main loop
                #self.axes1.figure.canvas.draw()   # handler caught exception: main thread is not in main loop
                print "handler4(): x.size={}".format( data.size )


            def work(self, input_items, output_items):
                print "matplotlib4.work():  *** This should not be invoked*** "
                return len(input_items[0])
     



Flowgraph being used for this test:








Discuss-gnuradio mailing list
address@hidden
https://lists.gnu.org/mailman/listinfo/discuss-gnuradio

--
Sent from my Android device with K-9 Mail. Please excuse my brevity.
reply via email to

[Prev in Thread] Current Thread [Next in Thread]