animation -- ATTN backend maintainers

I wrote once before
(http://sourceforge.net/mailarchive/message.php?msg_id=12093643) about
some new methods for animation that can enable fast animations in
matplotlib, which can support everything from dynamically updating
your data to strip charts to real time cursoring to a widget like
canvas.

So far, only GTKAgg has complete support for the required methods. I
think it would be nice to have these in the major mpl GUI backends,
since it would make the animation interface much simpler and cleaner
if we could rely on them in the frontend, eg in the Axes class.

I just posted an entry on the wiki about matplotlib animations. It
starts with regular "pylab" animations, and then discusses GUI
animations using timers and event handlers, and finally the newfangled
methods to support per-artist animations.

As it turns out, for the *Agg backends, only one new method needs to
be added, which is

  canvas.blit(bbox)

This method transfers the agg canvas within the bounding box onto the
GUI canvas. I realize that I need to add something like

  aggcanvas.as_rgba_str(bbox)

to support this for Qt and WX which are currently using string methods
to blit to canvas. I'm happy to do this in the next couple of days if
I know that someone is interested in actually implementing
canvas.blit(bbox) for their respective backend.

To see the utility of the new methods, run examples/widgets/cursor.py
and examples/widgets/span_selector.py modified to set useblit=True,
and compare the performance of anim.py with examples/animation_blit.py
which animate the same data. All of the above should be run done with
the GTKAgg backend.

As noted on the wiki entry, with these methods in place, users who
want to do per artist animation could write code like

    line, = ax.plot(something, animated=True)
    canvas.draw()

    def callback(*args):
        line.set_ydata(somedata)
        ax.draw_animated()

This *doesn't* work now, because I am hesitant to put methods into
Axes which would break most backends. The equivalent in
animation_blit.py is considerably more complicated.

Perhaps someone at STScI could sign up for implementing
canvas.blit(bbox) for TkAgg, and someone at JPL for the Qt backend? I
might take a crack at WX, if noone else wants it :slight_smile: Steve, Gregory
and Charles, if you are interested in animation for your respective
backends, I encourage you to take a look at this too. Those of you
using the agg buffer in extension code (eg tkagg) may want to look at
src/_gtkagg.cpp to see how the bbox and the agg buffer are used to
implement blit, which defaults to blitting the entire canvas if
blit=None.
All of this is discussed in more depth at
http://www.scipy.org/wikis/topical_software/Animations

Thanks!
JDH

example/animation_blit.py works fine on my laptop, but for some reason not obvious to me it is not working on my desktop. Here is the error:

Traceback (most recent call last):
   File "animation_blit.py", line 30, in update_line
     ax.draw_artist(line)
   File "/usr/local/lib/python2.4/site-packages/matplotlib/axes.py", line 1336, in draw_artist
     assert self._cachedRenderer is not None
AssertionError

Both machines are up-to-date with cvs. Any clues?

Thanks,
  Charlie

John Hunter wrote:

···

I wrote once before
(http://sourceforge.net/mailarchive/message.php?msg_id=12093643) about
some new methods for animation that can enable fast animations in
matplotlib, which can support everything from dynamically updating
your data to strip charts to real time cursoring to a widget like
canvas.

So far, only GTKAgg has complete support for the required methods. I
think it would be nice to have these in the major mpl GUI backends,
since it would make the animation interface much simpler and cleaner
if we could rely on them in the frontend, eg in the Axes class.

I just posted an entry on the wiki about matplotlib animations. It
starts with regular "pylab" animations, and then discusses GUI
animations using timers and event handlers, and finally the newfangled
methods to support per-artist animations.

As it turns out, for the *Agg backends, only one new method needs to
be added, which is

  canvas.blit(bbox)

This method transfers the agg canvas within the bounding box onto the
GUI canvas. I realize that I need to add something like

  aggcanvas.as_rgba_str(bbox)

to support this for Qt and WX which are currently using string methods
to blit to canvas. I'm happy to do this in the next couple of days if
I know that someone is interested in actually implementing
canvas.blit(bbox) for their respective backend.

To see the utility of the new methods, run examples/widgets/cursor.py
and examples/widgets/span_selector.py modified to set useblit=True,
and compare the performance of anim.py with examples/animation_blit.py
which animate the same data. All of the above should be run done with
the GTKAgg backend.

As noted on the wiki entry, with these methods in place, users who
want to do per artist animation could write code like

    line, = ax.plot(something, animated=True)
    canvas.draw()

    def callback(*args):
        line.set_ydata(somedata)
        ax.draw_animated()

This *doesn't* work now, because I am hesitant to put methods into
Axes which would break most backends. The equivalent in
animation_blit.py is considerably more complicated.

Perhaps someone at STScI could sign up for implementing
canvas.blit(bbox) for TkAgg, and someone at JPL for the Qt backend? I
might take a crack at WX, if noone else wants it :slight_smile: Steve, Gregory
and Charles, if you are interested in animation for your respective
backends, I encourage you to take a look at this too. Those of you
using the agg buffer in extension code (eg tkagg) may want to look at
src/_gtkagg.cpp to see how the bbox and the agg buffer are used to
implement blit, which defaults to blitting the entire canvas if
blit=None. All of this is discussed in more depth at
http://www.scipy.org/wikis/topical_software/Animations

Thanks!
JDH

-------------------------------------------------------
SF.Net email is sponsored by: Discover Easy Linux Migration Strategies
from IBM. Find simple to follow Roadmaps, straightforward articles,
informative Webcasts and more! Get everything you need to get up to
speed, fast. http://ads.osdn.com/?ad_id=7477&alloc_id=16492&op=click
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel

Hi John, Hi the list,

I almost have finished updating the fltkAgg, to add the new subplot
formatter and the blit method for fast animation. Everything seems to
work fine, but I still need to do some code clean-up, and before
commiting the changes I have to ask what you think about the method I
used:

Instead of writing a special method taking account of the bbox for
bliting, similar to the agg_to_gtk_drawable, or a aggcanvas->str
conversion like the proposed aggcanvas.as_rgba_str(bbox), I just changed
the method that I introduced for normal draw in fltkAdd, that rely on
pytho buffer objects to transfer the agg buffer to the fltk library.

The old method of the Agg backend that was used to get the buffer object
was:

Py::Object
RendererAgg::buffer_rgba(const Py::Tuple& args) {
  //"expose the rendered buffer as Python buffer object";
  
  _VERBOSE("RendererAgg::buffer_rgba");
  
  args.verify_length(0);
  int row_len = width*4;
  return Py::asObject(PyBuffer_FromMemory( pixBuffer, row_len*height));
}

and I just extended it to use only part of the buffer:

Py::Object
RendererAgg::buffer_rgba(const Py::Tuple& args) {
  //"expose the rendered buffer as Python buffer object, starting from
postion x,y";
  
  _VERBOSE("RendererAgg::buffer_rgba");
  
  args.verify_length(2);
  int startw = Py::Int(args[0]);
  int starth = Py::Int(args[1]);
  int row_len = width*4;
  int start=row_len*starth+startw*4;
  return Py::asObject(PyBuffer_FromMemory( pixBuffer+start,
row_len*height-start));
}

As fltkAgg is able to use an image source with a pixel stride (skipping
the a of the rgba quatuor) and a line stride (taking a part of wide w1
from an image of wide w2), no copy or special method is needed with the
new version of RendererAgg::buffer_rgba...

The draw code calls

Fltk.fl_draw_image(self._source.buffer_rgba(0,0),0,0,int(w),int(h),4,0)

and the blit code

Fltk.fl_draw_image(self._source.buffer_rgba(x,y),x,y,int(w),int(h),4,int(wo)*4)

Now I checked and other backends (qtagg, cocoaagg) now use
RendererAgg::buffer_rgba. If this is ok, I will update all the calls to
pass (0,0) instead of no arguments, but I wonder if the new methods
could not simplify things for those backends too...

Another remarks is that the animation code seems quite fragile for the
moment: if one do a resize of the output window, the background copy is
not updated correctly and one have a very interresting effect :wink: Well,
at leat I observe that under fltkAgg (my local version supporting blit)
and GTKAgg. tkagg does not do this..because it is not possible to resize
the window during animation (well, window is resizable but the size of
the inside canvas does not change during this resize...).

I think some extra steps should be performed to make resize and anim
play nicely together (like freezing the anim during resize, and
restarting afterwards with the correct background...)

Regards,

Greg.