title: Quickly and Efficiently update Matplotlib Axes (Plot)
body: <p>I've run into some performance issues with a GUI that I'm working on.  Specificially I'm using wxPython as the backend for several matplotlib figures which I've embedded in the canvas.  I've gotten the basic functionality working with a simple self.axes.clear() and self.axes.plot() command, but I can't seem to get any sort of reasonable frame rates using this method.  After performing a search it seems that if I were using a plot object that I I could reset the xdata and ydata then redraw the figure to obtain a faster refresh rate.  Unfortunately, the layout that I'm using precludes the use of the plot object, so I've implemented the code using the axes() object.  As far as I can tell the axes() object does not  have any equivalent methods for setting the xdata and ydata (see this post: <a href="https://stackoverflow.com/questions/4098131/matplotlib-update-a-plot">How to update a plot in matplotlib?</a>).  Here's the code I'm using:</p>
  
  <pre><code>import sys,os,csv
  import numpy as np
  import wx
  import matplotlib
  import pylab
  from matplotlib.figure import Figure
  from matplotlib.backends.backend_wxagg import \
      FigureCanvasWxAgg as FigCanvas, \
      NavigationToolbar2WxAgg as NavigationToolbar
  class UltrasoundDemoGUI(wx.Frame):
      title = ' Ultrasound Demo '
      def __init__(self):
          wx.Frame.__init__(self, None, -1, self.title)
          self.create_menu()
          self.statusbar = self.CreateStatusBar()
          self.create_main_panel()
          self.dataMon = pylab.randn(100,1);
          self.dataBi = pylab.randn(100,1);
          self.dataLoc = pylab.randn(100,1);
  
          self.redraw_timer = wx.Timer(self)
          self.Bind(wx.EVT_TIMER, self.on_redraw_timer, self.redraw_timer)        
          self.redraw_timer.Start(300)
  
      def create_menu(self):
          self.menubar = wx.MenuBar()
          menu_file = wx.Menu()
          m_expt = menu_file.Append(-1, "&amp;Save plot\tCtrl-S", "Save plot to file")
          self.Bind(wx.EVT_MENU, self.on_save_plot, m_expt)
          menu_file.AppendSeparator()
          m_exit = menu_file.Append(-1, "E&amp;xit\tCtrl-X", "Exit")
          self.Bind(wx.EVT_MENU, self.on_exit, m_exit)
          self.menubar.Append(menu_file, "&amp;File")
          self.SetMenuBar(self.menubar)
      def create_main_panel(self):
          self.panel = wx.Panel(self)
  #        self.init_plot()
          self.dpi = 100
          self.figSignals = Figure((12, 5.0), dpi=self.dpi)
          self.canvas = FigCanvas(self.panel, -1, self.figSignals)
  
          rectSubplotMono = .1, .55, .4, .4
          self.axesMono = self.figSignals.add_axes(rectSubplotMono)
          rectSubplotBi = .1, .05, .4, .4
          self.axesBi = self.figSignals.add_axes(rectSubplotBi)
          rectSubplotLoc = .55, .05, .4, .9
          self.axesLoc = self.figSignals.add_axes(rectSubplotLoc)
  
          self.axesMono.set_axis_bgcolor('white')
          self.axesBi.set_axis_bgcolor('white')
          self.axesLoc.set_axis_bgcolor('white')      
          self.axesMono.set_title('Raw Ultrasound Signal', size=12)
  
          pylab.setp(self.axesMono.get_xticklabels(), fontsize=8)
          pylab.setp(self.axesMono.get_yticklabels(), fontsize=8)
  
          pylab.setp(self.axesBi.get_xticklabels(), fontsize=8)
          pylab.setp(self.axesBi.get_yticklabels(), fontsize=8)
  
          pylab.setp(self.axesLoc.get_xticklabels(), fontsize=8)
          pylab.setp(self.axesLoc.get_yticklabels(), fontsize=8)
  
          # plot the data as a line series, and save the reference 
          # to the plotted line series
          #
          self.dataMono = pylab.randn(100,1)
          self.dataBi = pylab.randn(100,1)
          self.dataLoc = pylab.randn(100,1)
          self.plot_dataMono = self.axesMono.plot(
              self.dataMono, 
              linewidth=1,
              color=(1, 1, 0),
              )[0]
          self.plot_dataBi = self.axesBi.plot(
              self.dataBi, 
              linewidth=1,
              color=(1, 1, 0),
              )[0]
          self.plot_dataLoc = self.axesLoc.plot(
              self.dataLoc, 
              linewidth=1,
              color=(1, 1, 0),
              )[0]
  
          self.toolbar = NavigationToolbar(self.canvas)
          self.vbox = wx.BoxSizer(wx.VERTICAL)
          self.vbox.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
          self.vbox.AddSpacer(10)
          self.hbox = wx.BoxSizer(wx.HORIZONTAL)
          flags = wx.ALIGN_LEFT | wx.ALL | wx.ALIGN_CENTER_VERTICAL
          self.panel.SetSizer(self.vbox)
          self.vbox.Fit(self)
  
      def init_plot(self):
          rectSubplotMono = .1, .55, .4, .4
          self.axesMono = self.figSignals.add_axes(rectSubplotMono)
          rectSubplotBi = .1, .05, .4, .4
          self.axesBi = self.figSignals.add_axes(rectSubplotBi)
          rectSubplotLoc = .55, .05, .4, .9
          self.axesLoc = self.figSignals.add_axes(rectSubplotLoc)
  
          self.axesMono.set_axis_bgcolor('white')
          self.axesBi.set_axis_bgcolor('white')
          self.axesLoc.set_axis_bgcolor('white')      
          self.axesMono.set_title('Raw Ultrasound Signal', size=12)
  
          pylab.setp(self.axesMono.get_xticklabels(), fontsize=8)
          pylab.setp(self.axesMono.get_yticklabels(), fontsize=8)
  
          pylab.setp(self.axesBi.get_xticklabels(), fontsize=8)
          pylab.setp(self.axesBi.get_yticklabels(), fontsize=8)
  
          pylab.setp(self.axesLoc.get_xticklabels(), fontsize=8)
          pylab.setp(self.axesLoc.get_yticklabels(), fontsize=8)
  
  
      def on_redraw_timer(self, event):
          self.draw_plot()
  
      def draw_plot(self):
          self.axesMono.clear()
          self.axesBi.clear()
          self.axesLoc.clear()
          i = np.arange(1,100)
          w = i;
          x = pylab.randn(100,1);
          y = pylab.randn(100, 1);
          z = pylab.randn(100, 1);        
  
  #        self.axesMono.set_xdata(np.arange(len(x)))
  #        self.axesMono.set_ydata(np.array(x))
  
          self.axesMono.plot(x, 'red')
          self.axesBi.plot(x,'yellow')
          self.axesLoc.plot(x, z, 'black')
          self.canvas.draw()
  
      def on_save_plot(self, event): 
          file_choices = "PNG (*.png)|*.png"
          dlg = wx.FileDialog(
              self, 
              message="Save plot as...",
              defaultDir=os.getcwd(),
              defaultFile="plot.png",
              wildcard=file_choices,
              style=wx.SAVE)
  
          if dlg.ShowModal() == wx.ID_OK:
              path = dlg.GetPath()
              self.canvas.print_figure(path, dpi=self.dpi)
              self.flash_status_message("Saved to %s" % path)
  
      def on_exit(self, event):
          self.Destroy()
  if __name__ == '__main__':
      app = wx.PySimpleApp()
      app.frame = UltrasoundDemoGUI()
      app.frame.Show()
      app.frame.draw_plot()
      app.MainLoop()
      del app
  </code></pre>
  
  <p>I appear to be limited to a refresh rate of approximate 3Hz.  Ideally I'd like to visualize the data at a frame rate of 10Hz or higher.  Does anyone have any idea how I can efficiently (quickly) update the plots using the axes object?  </p>
  
  <p>Thanks for your help, 
  -B</p>