Dynamically updating plot in matplotlib


I am making an application in Python which collects data from a serial port and plots a graph of the collected data against arrival time. The time of arrival for the data is uncertain. I want the plot to be updated when data is received. I searched on how to do this and found two methods:

  1. Clear the plot and re-draw the plot with all the points again.
  2. Animate the plot by changing it after a particular interval.

I do not prefer the first one as the program runs and collects data for a long time (a day for example), and redrawing the plot will be pretty slow. The second one is also not preferable as time of arrival of data is uncertain and I want the plot to update only when the data is received.

Is there a way in which I can update the plot just by adding more points to it only when the data is received?

6/8/2012 9:05:34 AM

Accepted Answer

Is there a way in which I can update the plot just by adding more point[s] to it...

There are a number of ways of animating data in matplotlib, depending on the version you have. Have you seen the matplotlib cookbook examples? Also, check out the more modern animation examples in the matplotlib documentation. Finally, the animation API defines a function FuncAnimation which animates a function in time. This function could just be the function you use to acquire your data.

Each method basically sets the data property of the object being drawn, so doesn't require clearing the screen or figure. The data property can simply be extended, so you can keep the previous points and just keep adding to your line (or image or whatever you are drawing).

Given that you say that your data arrival time is uncertain your best bet is probably just to do something like:

import matplotlib.pyplot as plt
import numpy

hl, = plt.plot([], [])

def update_line(hl, new_data):
    hl.set_xdata(numpy.append(hl.get_xdata(), new_data))
    hl.set_ydata(numpy.append(hl.get_ydata(), new_data))

Then when you receive data from the serial port just call update_line.

10/5/2012 5:14:53 PM

In order to do this without FuncAnimation (eg you want to execute other parts of the code while the plot is been produced or you want to be updating several plots at the same time), calling draw alone does not produce the plot (at least with the qt backend).

The following works for me:

import matplotlib.pyplot as plt
class DynamicUpdate():
    #Suppose we know the x range
    min_x = 0
    max_x = 10

    def on_launch(self):
        #Set up plot
        self.figure, self.ax = plt.subplots()
        self.lines, = self.ax.plot([],[], 'o')
        #Autoscale on unknown axis and known lims on the other
        self.ax.set_xlim(self.min_x, self.max_x)
        #Other stuff

    def on_running(self, xdata, ydata):
        #Update data (with the new _and_ the old points)
        #Need both of these in order to rescale
        #We need to draw *and* flush

    def __call__(self):
        import numpy as np
        import time
        xdata = []
        ydata = []
        for x in np.arange(0,10,0.5):
            self.on_running(xdata, ydata)
        return xdata, ydata

d = DynamicUpdate()

Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow