«

»

Print this Post

Realtime Data Plotting in Python

Notice

If you’re looking to plot PCM audio or FFT frequency-domain audio data, you might find my next post more interesting. I use a PC microphone as input, and graph the data in real time.

http://www.swharden.com/blog/2013-05-09-realtime-fft-audio-visualization-with-python/

I love using python for handing data. Displaying it isn’t always as easy. Python fast to write, and numpy, scipy, and matplotlib are an incredible combination. I love matplotlib for displaying data and use it all the time, but when it comes to realtime data visualization, matplotlib (admittedly) falls behind. Imagine trying to plot sound waves in real time. Matplotlib simply can’t handle it. I’ve recently been making progress toward this end with PyQwt with the Python X,Y distribution. It is a cross-platform solution which should perform identically on Windows, Linux, and MacOS. Here’s an example of what it looks like plotting some dummy data (a sine wave) being transformed with numpy.roll().

How did I do it? Easy. First, I made the GUI with QtDesigner (which comes with Python x,y). I saved the GUI as a .ui file. I then used the pyuic4 command to generate a python script from the .ui file. In reality, I use a little helper script I wrote designed to build .py files from .ui files and start a little “ui.py” file which imports all of the ui classes. It’s overkill for this, but I’ll put it in the ZIP anyway.  Here’s what the GUI looks like in QtDesigner:

 

After that, I tie everything together in a little script which updates the plot in real time. It takes inputs from button click events and tells a clock (QTimer) how often to update/replot the data. Replotting it involves just rolling it with numpy.roll().  Check it out:

import ui_plot #this was generated by pyuic4 command
import sys
import numpy
from PyQt4 import QtCore, QtGui
import PyQt4.Qwt5 as Qwt

numPoints=1000
xs=numpy.arange(numPoints)
ys=numpy.sin(3.14159*xs*10/numPoints) #this is our data

def plotSomething():
    global ys
    ys=numpy.roll(ys,-1)
    c.setData(xs, ys)
    uiplot.qwtPlot.replot()   

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    win_plot = ui_plot.QtGui.QMainWindow()
    uiplot = ui_plot.Ui_win_plot()
    uiplot.setupUi(win_plot)

    # tell buttons what to do when clicked
    uiplot.btnA.clicked.connect(plotSomething)
    uiplot.btnB.clicked.connect(lambda: uiplot.timer.setInterval(100.0))
    uiplot.btnC.clicked.connect(lambda: uiplot.timer.setInterval(10.0))
    uiplot.btnD.clicked.connect(lambda: uiplot.timer.setInterval(1.0))

    # set up the QwtPlot (pay attention!)
    c=Qwt.QwtPlotCurve()  #make a curve
    c.attach(uiplot.qwtPlot) #attach it to the qwtPlot object
    uiplot.timer = QtCore.QTimer() #start a timer (to call replot events)
    uiplot.timer.start(100.0) #set the interval (in ms)
    win_plot.connect(uiplot.timer, QtCore.SIGNAL('timeout()'), plotSomething)

    # show the main window
    win_plot.show()
    sys.exit(app.exec_())

I’ll put all the files in a ZIP to help out anyone interested in giving this a shot. Clicking different buttons updates the graph at different speeds. If you make something cool with this concept, let me know! I’d love to see it.

DOWNLOAD PROJECT: realtime_python_graph.zip

About the author

Scott W Harden

Scott Harden has had a lifelong passion for computer programming and electrical engineering, and recently has become interested in its relationship with biomolecular sciences. He has run a personal website since he was 15, which has changed names from HardenTechnologies.com, to KnightHacker.com, to ScottIsHot.com, to its current SWHarden.com. Scott has been in college for 10 years, with 3 more years to go. He has an AA in Biology (Valencia College), BS in Cell Biology (Union University), MS in Molecular Biology and Microbiology (University of Central Florida), and is currently in a combined DMD (doctor of dental medicine) / PhD (neuroscience) program through the collaboration of the College of Dentistry and College of Medicine (Interdisciplinary Program in Biomedical Science, IDP) at the University of Florida in Gainesville, Florida. In his spare time Scott builds small electrical devices (with an emphasis on radio frequency) and enjoys writing cross-platform open-source software.

Permanent link to this article: http://www.SWHarden.com/blog/2013-05-08-realtime-data-plotting-in-python/

14 comments

  1. Jon Mohrbacher

    Hi Scott, I live in Gainesville too (although I’m not a student), and I’m currently learning python. Are there any good resources / meetup groups for programmers that I should look into? Thanks.

    1. Scott Harden

      Hey Jon, glad to hear from a fellow pythoner! I still haven’t been, but I hear a lot about the Gainesville Hackerspace – http://skillhouse.org/ – they meet frequently, and I hear it’s a cool way to meet people and see neat things. It’s on my to-do list to go one day soon.

  2. laMarmotte

    Hi Scott, very cool post, very useful. Many packages I have seen (Pyopencv, pyODE) seem to recommand pygame for fast plotting, but it is a pain to display mathematical stuff in a pygame window (everything must be converted into pixels). On my computer, I manage to display with Matplotlib in quasi-real time the stream of my webcam using imshow(), but certainly on less powerfull machines your solution will be preferable.

    1. Scott Harden

      One of the other advantages is that the speed of PyQwt is far greater than matplotlib, so if you’re looking for high-famerate, low CPU load plotting, it’s something to look into!

  3. bc

    Qwt is not your only option and in fact probably not the best one. The fact it is quite fast is more-or-less its only advantage. For more flexible real-time data display, I recommend Traits + Chaco + Enaml (all by enthought, at https://github.com/enthought). I have recently built a waveform analysis application with these (w/ real-time display) and can really recommend them. Note, Enaml (the new GUI design declarative language and library) can also embed matplotlib figures but matplotlib seems to throttle its update rate so it’s difficult to get very responsive plots. Enaml uses either wxPython or PyQt as it’s GUI backend so it can easily integrate with existing PyQt stuff.

    I wrote a chaco example to mirror your Qwt example. It will happily process events at ~ 50/second while the rest of the GUI remains fully responsive. I’m trying to find somewhere to post it…

    1. Andy

      I also use Traits and highly recommend it for its ease-of-use and flexibility. I’ve written a fully interactive tool for spectral analysis that has sped up work which used to take weeks into minutes. There are definitely a few GUI modules available now for Python, and they’re getting better and better!

    2. Andy

      Also @bc: Are you sure it was matplotlib throttling the updates? Creating the figure/axes is what takes the longest amount of time, but if you just update an existing plot with: scat = ax.scatter(…);scat.set_offsets(x, y), or similarly use set_data for plots, then you cut out a lot of the refresh lag than if you were re-building the figure and axes canvas every time.

      1. bc

        Some time back, I benchmarked the drawing speed of matplotlib and found it surprisingly fast (esp for large datasets where it uses decimation to speed up rendering). However, when I tried a quick test with MPL + Enaml today, I found a rather slow update rate compared with Chaco. I didn’t investigate this further but assumed there is something in MPL which is limiting the redrawing rate (to avoid saturating CPU etc.). I.e. I think the slow update is by design, knowing that the core drawing calls can be much faster. In my test, I was not re-creating the figure or axes; just calling set_data(…) on the line artist.

  4. jithin

    Thanks man. Big help. :)

    Although, If you manage to integrate Chako with Qt Designer, Please do put it up. I can’t seem to find any resources in that direction.

  5. Benjamin

    Hello !!

    I would like to know how can i open a python script to plot the data in the realtime. the data as follows:

    EXemple;

    0 0.217413641411 0

    0.001 0.202640969807 0

    0.002 0.13284039654 0

    0.003 0.111942324101 0

    0.004 0.0806826346525 0
    .
    .

    This data is being sent from a C file as an output.

    In python, i would like read each line and update it in the graph realtime. can you help me as how do i go about this

  6. Felipe Moreira

    Dear Scott,

    I’m part of a research group trying to make a python program for us research. We are from Rio de Janeiro (Brazil) and we are trying to run your code but this is a common problem when we try:

    {
    Traceback (most recent call last):
    File “realtimePlot.py”, line 1, in
    import ui_plot
    File “/home/moreiras/Documentos/ProjetoIC/qwtplot-example-python/ui_plot.py”, line 10, in
    from PyQt4 import QtCore, QtGui
    RuntimeError: the sip module implements API v10.0 to v10.1 but the PyQt4.QtCore module requires API v9.2
    }

    If possible, please help us.

    Regards,

    Felipe Moreira.

  7. milad

    Hey man I want to plot SIN on LCD in real time not showing immedaitly,can u help me?

  8. Jerry

    Scott;
    I’m an old HAM radio hardware guy, but I Think I can make a 0-30 MHz Spectrum analyzer with this if I can get it to work.
    I installed Python 3.4 but the PyQwt apparently wont work with it.
    I keep getting this:
    Traceback (most recent call last):
    File “C:\Users\Jerry\Desktop\SWH\realTimeAudio.py”, line 1, in
    import ui_plot
    File “C:\Users\Jerry\Desktop\SWH\ui_plot.py”, line 56, in
    from PyQt4 import Qwt5
    ImportError: cannot import name ‘Qwt5′
    I assume I have a too new version of python ??
    What version should I use ??
    As you can tell programming is not my thing.
    Thanks.

  9. Peter Farrell

    This is an absolutely fascinating project! I’m psyched to get it working but I get the same error message as Jerry: “Cannot import name ‘Qwt5′”

    Any help would be appreciated.

    Peter

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>