Skip to content

Instantly share code, notes, and snippets.

@jeremytrimble
Created May 7, 2012 20:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jeremytrimble/2630258 to your computer and use it in GitHub Desktop.
Save jeremytrimble/2630258 to your computer and use it in GitHub Desktop.
Trying to write a fast plot in matplotlib.
# Copyright 2012 Jeremy Trimble
import wx
from matplotlib.figure import Figure
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
import numpy as np
from math import sqrt
import time
import types
class AnimatedPlotPanel(wx.Panel):
def __init__(self, parent, *args, **kwargs):
wx.Panel.__init__(self, parent)
self.background = None
self.backgroundValid = False
self.midground = None
self.midElements = []
self.midgroundValid = False
self.foreElements = []
self.createUI()
self.canvas.mpl_connect('resize_event', self.onResize)
def createUI(self):
self.fig = Figure( (6,4), 100 )
self.canvas = FigureCanvas( self, wx.ID_ANY, self.fig )
self.ax = self.fig.add_subplot(111)
self.ax.set_rasterized(True)
self.ax.set_autoscale_on(False)
self.ax.set_xticks([])
self.ax.set_yticks([])
self.ax.grid(True)
(self.trace,) = self.ax.plot(np.arange(5), np.arange(5), animated=True)
self.midElements.append( (None, self.trace) )
self.canvas.draw()
sizer = wx.FlexGridSizer(cols=1)
sizer.AddGrowableRow(0); sizer.AddGrowableCol(0);
sizer.Add( self.canvas, flag=wx.EXPAND )
self.SetSizer(sizer)
def onResize(self, event):
self.backgroundValid = False
self.midgroundValid = False
def onMouseMove(self, event):
if event.xdata is not None:
xpoints = self.trace.get_xdata()
xClosestIdx = np.abs(xpoints-event.xdata).argmin()
def setXBounds(self, xbounds):
assert( len(xbounds) == 2 )
self.ax.set_xlim( xbounds )
self.backgroundValid = False
def setYBounds(self, ybounds):
assert( len(ybounds) == 2 )
self.ax.set_ylim( ybounds )
def setXTicks(self, xticks):
self.ax.set_xticks(xticks)
self.backgroundValid = False
def setYTicks(self, yticks):
self.ax.set_yticks(yticks)
self.backgroundValid = False
def setTraceData(self, newData):
self.trace.set_xdata(np.arange(len(newData)))
self.trace.set_ydata(newData)
self.midgroundValid = False
def drawBackground(self):
if self.backgroundValid:
self.canvas.restore_region(self.background)
return
else:
self.canvas.draw()
self.background = self.canvas.copy_from_bbox(self.ax.bbox)
self.backgroundValid = True
def drawMidground(self):
self.drawBackground()
if self.midgroundValid:
self.canvas.restore_region(self.midground)
return
else:
for (setupFunc, element) in self.midElements:
if setupFunc:
setupFunc(element)
self.ax.draw_artist(element)
self.canvas.blit(self.ax.bbox)
self.midground = self.canvas.copy_from_bbox(self.ax.bbox)
self.midgroundValid = True
def drawAll(self):
self.drawMidground()
for (setupFunc, element) in self.foreElements:
if setupFunc:
setupFunc(element)
self.ax.draw_artist(element)
self.canvas.blit(self.ax.bbox)
class TestFrame(wx.Frame):
instance = None
def __init__(self, *args, **kwargs):
wx.Frame.__init__(self, title="Test Frame", *args, **kwargs)
self.createUI()
REFRESH_FPS = 45 # Reduce this if performance is poor
self.TIMER_INTERVAL = 1000.0/REFRESH_FPS
self.frameDecCounter = 0
self.fpsPeriodBegin = time.time()
self.fpsFramesInPeriod = 0
timerId = wx.NewId()
self.timer = wx.Timer(self, timerId)
self.Bind(wx.EVT_TIMER, self.onTimer, id=timerId)
self.timer.Start(self.TIMER_INTERVAL, wx.TIMER_ONE_SHOT)
self.apf.setXTicks( np.arange(0,501, 100) )
self.apf.setYTicks( np.arange(-6,6.1,0.5) )
def createUI(self):
panel = self
self.apf = AnimatedPlotPanel(panel, -1)
sizer = wx.FlexGridSizer(cols=1)
sizer.AddGrowableRow(0); sizer.AddGrowableCol(0);
sizer.Add( self.apf, flag=wx.EXPAND )
self.SetSizer(sizer)
def onTimer(self, evt):
self.apf.setTraceData( np.random.randn(500) )
self.apf.drawAll()
self.fpsFramesInPeriod += 1
curTime = time.time()
if curTime > self.fpsPeriodBegin+3:
deltaT = (curTime - self.fpsPeriodBegin)
fps = self.fpsFramesInPeriod / float(deltaT)
self.fpsPeriodBegin = time.time()
self.fpsFramesInPeriod = 0
print "FPS: %f" % fps
self.timer.Start(self.TIMER_INTERVAL, wx.TIMER_ONE_SHOT)
if __name__ == '__main__':
app = wx.PySimpleApp()
frame = TestFrame(None, size=(900,500))
app.SetTopWindow(frame)
frame.Show()
app.MainLoop()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment