tkagg animation

I added the blit method to the tkagg, but I don't know

    > what needs to be done to take the bbox into account.
    > Even as it stands I get 141 fps in animation_blit.py
    > compared to gtk's 350 fps. Whoever is the tk expert, any
    > clue on how to account for the bbox on blit updates?

Todd wrote this, but I can point you to the relevant section of code.

  tkagg.blit(self._tkphoto, self.renderer._renderer, 2)

calls backends.tkagg.blit

def blit(photoimage, aggimage, colormode=1):
    tk = photoimage.tk
    try:
        tk.call("PyAggImagePhoto", photoimage, id(aggimage), colormode)
    except Tk.TclError, v:
        try:
            try:
                _tkagg.tkinit(tk.interpaddr(), 1)
            except AttributeError:
                _tkagg.tkinit(id(tk), 0)
            tk.call("PyAggImagePhoto", photoimage, id(aggimage), colormode)
        except (ImportError, AttributeError, Tk.TclError):
            raise

and PyAggImagePhoto is the relevant function which is defined in
src/_tkagg.cpp

static int
PyAggImagePhoto(ClientData clientdata, Tcl_Interp* interp,
               int argc, char **argv)
{
    Tk_PhotoHandle photo;
    Tk_PhotoImageBlock block;
    PyObject* aggo;
    //...snip....

    block.width = aggRenderer->get_width();
    block.height = aggRenderer->get_height();
    //std::cout << "w,h: " << block.width << " " << block.height << std::endl;
    block.pitch = block.width * nval;
    block.pixelPtr = aggRenderer->pixBuffer;
    /* Clear current contents */
    Tk_PhotoBlank(photo);
    /* Copy opaque block to photo image, and leave the rest to TK */
    Tk_PhotoPutBlock(photo, &block, 0, 0, block.width, block.height);

I assume the 0, 0 are the x and y offsets and block.width,
block.height are the sizes of the rect to be transferred. By
following the example of src/_gtkagg.cpp, you should be able to
substitute in the information from the bbox where appropriate.

BTW, I am getting 51 FPS with Tkagg using your blit. My test script
is below:

import matplotlib
matplotlib.use('TkAgg')
import sys
import gtk, gobject
import pylab as p
import matplotlib.numerix as nx
import time

ax = p.subplot(111)
canvas = ax.figure.canvas

# create the initial line
x = nx.arange(0,2*nx.pi,0.01)
line, = p.plot(x, nx.sin(x), animated=True)

def run(*args):
    background = canvas.copy_from_bbox(ax.bbox)
    # for profiling
    tstart = time.time()

    while 1:
        # restore the clean slate background
        canvas.restore_region(background)
        # update the data
        line.set_ydata(nx.sin(x+run.cnt/10.0))
        # just draw the animated artist
        ax.draw_artist(line)
        # just redraw the axes rectangle
        canvas.blit(ax.bbox)

        if run.cnt==200:
            # print the timing info and quit
            print 'FPS:' , 200/(time.time()-tstart)
            sys.exit()

        run.cnt += 1
run.cnt = 0

manager = p.get_current_fig_manager()
manager.window.after(100, run)

p.show()

I am really close on having blit work for the tkagg. I committed my changes. There is one problem left I was hoping you could help on. I blit the axes in the right place, but it is blitting the upper-left of the whole figure. Running your test script below, this is easily seen. How do I pass in just the pixmap of the area of interest?

- Charlie

John Hunter wrote:

···

"Charles" == Charles Moad <cmoad@...209...> writes:

    > I added the blit method to the tkagg, but I don't know
    > what needs to be done to take the bbox into account.
    > Even as it stands I get 141 fps in animation_blit.py
    > compared to gtk's 350 fps. Whoever is the tk expert, any
    > clue on how to account for the bbox on blit updates?

Todd wrote this, but I can point you to the relevant section of code.

  tkagg.blit(self._tkphoto, self.renderer._renderer, 2)

calls backends.tkagg.blit

def blit(photoimage, aggimage, colormode=1):
    tk = photoimage.tk
    try:
        tk.call("PyAggImagePhoto", photoimage, id(aggimage), colormode)
    except Tk.TclError, v:
        try:
            try:
                _tkagg.tkinit(tk.interpaddr(), 1)
            except AttributeError:
                _tkagg.tkinit(id(tk), 0)
            tk.call("PyAggImagePhoto", photoimage, id(aggimage), colormode)
        except (ImportError, AttributeError, Tk.TclError):
            raise

and PyAggImagePhoto is the relevant function which is defined in
src/_tkagg.cpp

static int
PyAggImagePhoto(ClientData clientdata, Tcl_Interp* interp,
               int argc, char **argv)
{
    Tk_PhotoHandle photo;
    Tk_PhotoImageBlock block;
    PyObject* aggo;
    //...snip....

    block.width = aggRenderer->get_width();
    block.height = aggRenderer->get_height();
    //std::cout << "w,h: " << block.width << " " << block.height << std::endl;
    block.pitch = block.width * nval;
    block.pixelPtr = aggRenderer->pixBuffer;
    /* Clear current contents */
    Tk_PhotoBlank(photo);
    /* Copy opaque block to photo image, and leave the rest to TK */
    Tk_PhotoPutBlock(photo, &block, 0, 0, block.width, block.height);

I assume the 0, 0 are the x and y offsets and block.width,
block.height are the sizes of the rect to be transferred. By
following the example of src/_gtkagg.cpp, you should be able to
substitute in the information from the bbox where appropriate.

BTW, I am getting 51 FPS with Tkagg using your blit. My test script
is below:

import matplotlib
matplotlib.use('TkAgg')
import sys
import gtk, gobject
import pylab as p
import matplotlib.numerix as nx
import time

ax = p.subplot(111)
canvas = ax.figure.canvas

# create the initial line
x = nx.arange(0,2*nx.pi,0.01)
line, = p.plot(x, nx.sin(x), animated=True)

def run(*args):
    background = canvas.copy_from_bbox(ax.bbox)
    # for profiling
    tstart = time.time()

    while 1:
        # restore the clean slate background
        canvas.restore_region(background)
        # update the data
        line.set_ydata(nx.sin(x+run.cnt/10.0)) # just draw the animated artist
        ax.draw_artist(line)
        # just redraw the axes rectangle
        canvas.blit(ax.bbox)

        if run.cnt==200:
            # print the timing info and quit
            print 'FPS:' , 200/(time.time()-tstart)
            sys.exit()

        run.cnt += 1
run.cnt = 0

manager = p.get_current_fig_manager()
manager.window.after(100, run)

p.show()