Dynamically updating plot in matplotlib Dynamically updating plot in matplotlib python python

Dynamically updating plot in matplotlib


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 pltimport numpyhl, = 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))    plt.draw()

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


In order to do this without FuncAnimation (eg you want to execute other parts of the code while the plot is being 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 pltplt.ion()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_autoscaley_on(True)        self.ax.set_xlim(self.min_x, self.max_x)        #Other stuff        self.ax.grid()        ...    def on_running(self, xdata, ydata):        #Update data (with the new _and_ the old points)        self.lines.set_xdata(xdata)        self.lines.set_ydata(ydata)        #Need both of these in order to rescale        self.ax.relim()        self.ax.autoscale_view()        #We need to draw *and* flush        self.figure.canvas.draw()        self.figure.canvas.flush_events()    #Example    def __call__(self):        import numpy as np        import time        self.on_launch()        xdata = []        ydata = []        for x in np.arange(0,10,0.5):            xdata.append(x)            ydata.append(np.exp(-x**2)+10*np.exp(-(x-7)**2))            self.on_running(xdata, ydata)            time.sleep(1)        return xdata, ydatad = DynamicUpdate()d()


Here is a way which allows to remove points after a certain number of points plotted:

import matplotlib.pyplot as plt# generate axes objectax = plt.axes()# set limitsplt.xlim(0,10) plt.ylim(0,10)for i in range(10):             # add something to axes         ax.scatter([i], [i])      ax.plot([i], [i+1], 'rx')     # draw the plot     plt.draw()      plt.pause(0.01) #is necessary for the plot to update for some reason     # start removing points if you don't want all shown     if i>2:         ax.lines[0].remove()         ax.collections[0].remove()