Hi All, I put a small test case together based on
> wxcursor_demo. When clicking the button1 it should show a
> new plot, but it does not.
It does for me...
Do you mean a new plot window, or just redraw in the current figure?
You may not see that it has redrawn the figure unless you somehow
change the plot (ed pan/zoom). I modified your example so that each
time you redraw the frequency of the sine wave changes to make it more
apparent.
> I think my memory issue has to do with this as I created a
> new self.canvas each time, instead of doing a clear, but
> the big question is what do I need to call to show the new
> plot.
For one thing, add a gc.collect after you call clear to trigger the
garbage collector.
I added a memory report function and noticed something surprising. If
I just plotted the same sine wave over and over, memory usage was
flat. If I changed the sine wave frequency (still creating arrays of
the same size though) memory usage increased with each plot.
matplotlib does cache some information, mainly text and font stuff)
between draws which can cause memory to grow, but usually this is a
small amount. I'll explore further.
Here is my lightly modified version of your test script. The
report_memory function only works on unix like systems.
JDH
#!/usr/bin/env python
"""
Show how to have wx draw a cursor over an axes that moves with the
mouse and reports the data coords
"""
from matplotlib.numerix import arange, sin, pi
import matplotlib
matplotlib.use('WXAgg')
from matplotlib.backends.backend_wxagg import FigureCanvasWxAgg as FigureCanvas
from matplotlib.backends.backend_wx import NavigationToolbar2Wx
from matplotlib.figure import Figure
import wx
import os, sys, time, gc
def report_memory(i):
pid = os.getpid()
a2 = os.popen('ps -p %d -o rss,sz' % pid).readlines()
print i, ' ', a2[1],
return int(a2[1].split()[1])
class CanvasFrame(wx.Frame):
def __init__(self):
wx.Frame.__init__(self,None,-1,
'CanvasFrame',size=(550,350))
self.SetBackgroundColour(wx.NamedColor("WHITE"))
self.figure = Figure()
self.axes = self.figure.add_subplot(111)
t = arange(0.0,3.0,0.01)
s = sin(2*pi*t)
self.axes.plot(t,s)
self.axes.set_xlabel('Time (s)')
self.axes.set_ylabel('Price ($)')
self.canvas = FigureCanvas(self, -1, self.figure)
self.canvas.mpl_connect('motion_notify_event', self.mouse_move)
self.sizer =wx.BoxSizer(wx.VERTICAL)
self.sizer.Add(self.canvas, 1, wx.LEFT | wx.TOP | wx.GROW)
buttonId = wx.NewId()
self.button1 = wx.Button(id=buttonId, label='Clear and do figure again',
parent=self)
self.button1.Bind(wx.EVT_BUTTON, self.OnButton1Button, id=buttonId)
self.sizer.Add(self.button1, 0, wx.LEFT | wx.TOP)
self.SetSizer(self.sizer)
self.Fit()
self.statusBar =wx.StatusBar(self, -1)
self.statusBar.SetFieldsCount(1)
self.SetStatusBar(self.statusBar)
self.add_toolbar() # comment this out for no toolbar
if wx.VERSION_STRING >= '2.5':
self.Bind(wx.EVT_PAINT, self.OnPaint)
else:
wx.EVT_PAINT(self, self.OnPaint)
self.cnt = 0
def OnButton1Button(self, event):
print 'done it'
self.figure.clear()
self.axes = self.figure.add_subplot(111)
t = arange(0.0,4.0,0.01)
s = sin(2*pi*t*(self.cnt+1))
#s = sin(2*pi*t)
self.axes.plot(t,s)
self.axes.set_xlabel('Time 2 (s)')
self.axes.set_ylabel('Price 2 ($)')
report_memory(self.cnt)
self.cnt+=1
gc.collect()
def mouse_move(self, event):
self.draw_cursor(event)
def add_toolbar(self):
self.toolbar = NavigationToolbar2Wx(self.canvas)
self.toolbar.Realize()
tw, th = self.toolbar.GetSizeTuple()
fw, fh = self.canvas.GetSizeTuple()
self.toolbar.SetSize(wx.Size(fw, th))
self.sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
# update the axes menu on the toolbar
self.toolbar.update()
def OnPaint(self, event):
self.erase_cursor()
try: del self.lastInfo
except AttributeError: pass
self.canvas.draw()
event.Skip()
def draw_cursor(self, event):
'event is a MplEvent. Draw a cursor over the axes'
if event.inaxes is None:
self.erase_cursor()
try: del self.lastInfo
except AttributeError: pass
return
canvas = self.canvas
figheight = canvas.figure.bbox.height()
ax = event.inaxes
left,bottom,width,height = ax.bbox.get_bounds()
bottom = figheight-bottom
top = bottom - height
right = left + width
x, y = event.x, event.y
y = figheight-y
dc =wx.ClientDC(canvas)
dc.SetLogicalFunction(wx.XOR)
wbrush =wx.Brush(wx.Colour(255,255,255), wx.TRANSPARENT)
wpen =wx.Pen(wx.Colour(200, 200, 200), 1, wx.SOLID)
dc.SetBrush(wbrush)
dc.SetPen(wpen)
dc.ResetBoundingBox()
dc.BeginDrawing()
x, y, left, right, bottom, top = [int(val) for val in x, y, left, right, bottom, top]
self.erase_cursor()
line1 = (x, bottom, x, top)
line2 = (left, y, right, y)
self.lastInfo = line1, line2, ax, dc
dc.DrawLine(*line1) # draw new
dc.DrawLine(*line2) # draw new
dc.EndDrawing()
time, price = event.xdata, event.ydata
self.statusBar.SetStatusText("Time=%f Price=%f"% (time, price), 0)
def erase_cursor(self):
try: lastline1, lastline2, lastax, lastdc = self.lastInfo
except AttributeError: pass
else:
lastdc.DrawLine(*lastline1) # erase old
lastdc.DrawLine(*lastline2) # erase old
class App(wx.App):
def OnInit(self):
'Create the main window and insert the custom frame'
frame = CanvasFrame()
frame.Show(True)
return True
app = App(0)
app.MainLoop()