a memory + CPU problem when using mpl_connect?

Hi, thanks for this useful and quick answer. I am (always)

    > using GTKAgg (hope it is a good choice). I understand the 40
    > Mb part then, but not the 150-200 Mb... (this happens when I
    > move the cursor within the figure window only and things get
    > worse when I reload the data with a new imshow).

    > Two things from what you say:

    > * first : should I do something before redoing another
    > imshow? (when I cycle many times through the 3 commands,
    > connect, disconnect, imshow, the mouse event updating gets
    > really slow, and in fact it seems only the "imshow" really
    > makes things worse..). Maybe I need to "flush" the old
    > data/image/imshow ?

If you are doing multiple imshows and not clearing the axes in between
then you may be overplotting multiple images. Make sure you clear
your axes before plotting a new image

  ax.cla()

    > * second: I tried to understand what you mentioned in your
    > email about the blit thing. I understand the "principle",
    > reading the wiki, and going into mpl examples, but I didn"t
    > manage to implement it in practice (see my pathetic attempt
    > below). I guess the main reason is that I am not sure what
    > should be the "background" in the case of a figtext... (not
    > ax.bbox I guess but then what?)

You would want to pick a rectangle large enough to hold any text you
may want to plot to an area, and the copy and blit just that region.

Here are two examples: the first redraws the entire figure as you are
doing but reports memory. I find that memory grows for a while but
them stabilizes, and if you throw in a gc.collect() it is rock solid.
Uncomment gc.collect to compare

The second script uses the blitting technique -- you'll appreciate the
performance boost!

### script one, draw the whole thing every time
import os, sys, time, gc
import matplotlib
#matplotlib.interactive(True)
#matplotlib.use('Cairo')
matplotlib.use('GTKAgg')
import matplotlib.transforms
from pylab import figure, show, nx

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])

fig = figure()
ax = fig.add_subplot(111)
X = nx.mlab.randn(100,100)
ax.imshow(X)
t = ax.text(20,20,'test: 0')

def onmove(event):
    mem = report_memory(onmove.cnt)
    t.set_text('test: %d mem=%d'%(onmove.cnt, mem))
    fig.canvas.draw_idle()
    onmove.cnt +=1
    #gc.collect()
onmove.cnt = 0

fig.canvas.mpl_connect('motion_notify_event', onmove)
show()

### script two, just blit the text region
import os, sys, time
import matplotlib
#matplotlib.interactive(True)
#matplotlib.use('Cairo')
matplotlib.use('GTKAgg')
import matplotlib.transforms
from pylab import figure, show, nx

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])

fig = figure()
ax = fig.add_subplot(111)
X = nx.mlab.randn(100,100)
ax.imshow(X)
t = ax.text(20,20,'test: 0', animated=True)

def ondraw(event):
    l,b,w,h = t.get_window_extent(event.renderer).get_bounds()

    figw, figh = fig.figwidth.get(), fig.figheight.get()
    # expand the rectangle to account for larger text; coords are pixel space
    ondraw.bbox = matplotlib.transforms.lbwh_to_bbox(
        l-10, b-10, w+200, h+20)
    ondraw.background = fig.canvas.copy_from_bbox(ondraw.bbox)
ondraw.background = None
ondraw.bbox = None

def onmove(event):
    mem = report_memory(onmove.cnt)
    t.set_text('test: %d mem=%d'%(onmove.cnt, mem))
    if ondraw.background is not None:
        fig.canvas.restore_region(ondraw.background)
        ax.draw_artist(t)
        fig.canvas.blit(ondraw.bbox)

    onmove.cnt +=1
onmove.cnt = 0

fig.canvas.mpl_connect('motion_notify_event', onmove)
fig.canvas.mpl_connect('draw_event', ondraw)
show()

JDH

great! but one question though: I need to put the text with figtext and
thus use figure coordinates (instead of pixel coord).
So how would I replace the :

matplotlib.transforms.lbwh_to_bbox

?

thanks

Eric
John Hunter wrote

···

def ondraw(event):
    l,b,w,h = t.get_window_extent(event.renderer).get_bounds()

    figw, figh = fig.figwidth.get(), fig.figheight.get()
    # expand the rectangle to account for larger text; coords are pixel space
    ondraw.bbox = matplotlib.transforms.lbwh_to_bbox(
        l-10, b-10, w+200, h+20)
    ondraw.background = fig.canvas.copy_from_bbox(ondraw.bbox)
ondraw.background = None
ondraw.bbox = None