Live plotting in matplotlib while taking a measurement that takes time

I would like to take a measurement and plot a graph, while the measurement is running. These measurements take quite a long time in python (it has to fetch data over a slow connection). The problem is the graph freezes when measured. The measurement consists of setting the center wavelength and then measuring some signal.

My program looks something like this:

# this is just some arbitrary library that has the functions set_wavelength and
# perform_measurement
from measurement_module import set_wavelength, perform_measurement
from pylab import *

xdata = np.linspace(600,1000,30) # this will be the x axis
ydata = np.zeros(len(xdata)) # this will be the y data. It will
for i in range(len(xdata)):
  # this call takes approx 1 s
  set_wavelength(xdata[i])
  # this takes approx 10 s
  ydata[i] = perform_measurement(xdata)
  # now I would like to plot the measured data
  plot(xdata,ydata)
  draw()

      

This will work when it is run in IPython with the -pylab module enabled, but while the measurement is in progress, the figure will freeze. How can I change the behavior to have an interactive graph when measuring?

You cannot just use pylab.ion () because python is busy while doing measurements.

Respectfully,

Dirk

+3


source to share


4 answers


Slow input and output is the ideal time to use streams and queues in Python. Themes have limitations, but this is the case when they work easily and efficiently.



A short description of how to do it:
Typically the GUI (like a matplotlib window) should be on the main thread, so collecting data on the second thread. In the data stream, check for new data (and if you do it in some type of infinite polling loop, put in .sleep for a short amount of time to release the stream sometimes). Then, when needed, let the main thread know there is some new data to process / display. Exactly how to do this depends on the details of your program and your GUI, etc. You could just use a flag on the data stream you are checking from the main stream or theading.Event or for example if you have a wx backend for matplotlib wx.CallAfter easily. I recommend looking at one of the many tutorials on Python streaming.to get an idea of ​​this as well as threading with a GUI tends to have a few issues, so just do a quick thread search with your specific backend. It sounds cumbersome as I explain it so succinctly, but it is very light and powerful, and will be smoother than reading and writing to the same file from different processes, for example.

0


source


You can, although it might be a little awkward, start collecting data as a playable process. I find Popen in a subprocess module quite handy. Then let the data collection script save what it does to disk and you use

Popen.poll()

      



To check if it's completed.

It should work.

+1


source


I recommend buffering the data in large chunks and rendering / re-rendering when the buffer is full. If you want it to be unblocked look at green trees.

from gevent.greenlet import Greenlet
import copy
def render(buffer):
    '''
    do rendering stuff
    '''
    pass

buff = ''
while not_finished:
    buff = connection.read()
    g = Greenlet(render, copy.deepcopy(buff))
    g.start()

      

+1


source


Take a look at Traits and Chaco , the Enthought system and the charting library. They provide a great abstraction for solving the problem you are facing. The Chaco conspiracy will be updated every time any of its dependencies change.

0


source







All Articles