1

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: How to update a plot in matplotlib?). Here's the code I'm using:

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, "&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&xit\tCtrl-X", "Exit")
        self.Bind(wx.EVT_MENU, self.on_exit, m_exit)
        self.menubar.Append(menu_file, "&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

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?

Thanks for your help, -B

Community
  • 1
  • 1
user1352331
  • 91
  • 1
  • 7

0 Answers0