can't update transform for polygon animation

Hi John,

Thanks for your help on the animation with patches, and now
I'm trying to do the same idea for matplotlib.patches.Polygon
ala your method for a circle patch:

    initialize:
  xy =[[x0,y0],[x1,y1],[x2,y2]]
      poly = Polygon( xy, animated=True,lw=2,fill=False )
  add_patch(poly)
        .
        .
    in the loop:
  poly.set_xy = xy_new
  poly.update_transorm() (no such routine)

The set_xy seems to work (at least no errors), but I don't see how
to "update the transform" as for the circle.

here I am looking at:
http://matplotlib.sourceforge.net/api/artist_api.html?highlight=polygon#matp
lotlib.patches.Polygon

thanks,
john

···

-----Original Message-----
From: John Hunter [mailto:jdh2358@…287…]
Sent: Sunday, February 14, 2010 7:39 PM
To: John Jameson
Cc: matplotlib-users@lists.sourceforge.net; Michael Droettboom
Subject: Re: [Matplotlib-users] memory leak for GTKAgg animation

On Sat, Feb 13, 2010 at 2:53 PM, John Jameson <jjameson@...2972...> wrote:

HI,
I find the very basic animation below has a memory leak (my pagefile usage
number keeps growing in the Windows XP Windows Task Manager Performance
graph).I don't see this with the "animation_blit_gtk.py" example on:

http://matplotlib.sourceforge.net/examples/index.html

(which I used as a starting point for this). In "animation_blit_gtk.py"

the

set_ydata() routine is used to update the line for the animation and this
does not leak. But if you call plot again with the new y_data (instead of
using set_ydata), this leaks too. Anyone have an idea on how to stop the
leak?

This isn't a memory leak. The problem is that you keep adding new
patches to the axes when you want just one with different data. Eg,
in your loop, run this code, and you will see that the number of
patches is growing:

   x_cir = 1.0 + 0.003*update_line.cnt
   cir = CirclePolygon((x_cir, 1), 0.3, animated=True, \
                   resolution=12, lw=2 )
   ax.add_patch(cir)
   ax.draw_artist(cir)
   print 'num patches=%d, mem usage=%d'%(
       len(ax.patches), cbook.report_memory(update_line.cnt))
   canvas.blit(ax.bbox)

You should add just one patch and then manipulate the data. In this
case, you are using a CirclePolygon which derives from RegularPolygon
and so you can update the "xy" property

http://matplotlib.sourceforge.net/api/artist_api.html#matplotlib.patches.Reg
ularPolygon

But on testing this it looks like there is a bug in that the set_xy
property setter is ignored. I worked around this in the func below by
setting the private variable directly, but this looks like a bug we
need to fix (Michael, shouldn't we respect the xy passed in in
patches.RegularPolygon._set_xy ?). In the meantime, the following
workaround should work for you w/o leaking....

def update_line():
   global x, y
   print update_line.cnt
   if update_line.background is None:
       update_line.background = canvas.copy_from_bbox(ax.bbox)
   canvas.restore_region(update_line.background)

   x_cir = 1.0 + 0.003*update_line.cnt

   if update_line.cir is None:
       cir = CirclePolygon((x_cir, 1), 0.3, animated=True, \
                   resolution=12, lw=2 )
       ax.add_patch(cir)
       update_line.cir = cir
   else:
       update_line.cir._xy = x_cir, 1
       update_line.cir._update_transform()
   ax.draw_artist(update_line.cir)
   print 'num patches=%d, xy=%s, mem usage=%d'%(
       len(ax.patches), update_line.cir.xy,
cbook.report_memory(update_line.cnt))
   canvas.blit(ax.bbox)

   if update_line.direction == 0:
       update_line.cnt += 1
       if update_line.cnt > 500:
           update_line.direction = 1
   else:
       update_line.cnt -= 1
       if update_line.cnt < 100:
           update_line.direction = 0

   return update_line.cnt<100

update_line.cnt = 0
update_line.direction = 0
update_line.background = None
update_line.cir = None

Two problems here :

* There is no polygon attribute "set_xy"; it is a method, so you need
to call it like "poly.set_xy(xy_new)". In general this is True for
all matplotlib set_* methods. There is also an "xy" attribute which
you can access like "poly.xy = xy_new". These two approaches do the
same thing

* The _update_transforms call was a hack I did on CirclePolygon to
work around a broken method. it is not a method of Polygon or Patch
which is why you are not finding it. For normal usage, the methods
that start with underscores are not meant to be called or used at the
user level, but because there was breakage in the CirclePolygon set_xy
method, I had to hack around it in the example I posted for you. For
Polygon, simply setting the xy attribute should be sufficient.

JDH

···

On Tue, Feb 16, 2010 at 10:54 AM, John Jameson <jjameson@...2972...> wrote:

Hi John,

Thanks for your help on the animation with patches, and now
I'm trying to do the same idea for matplotlib.patches.Polygon
ala your method for a circle patch:

initialize:
xy =[[x0,y0],[x1,y1],[x2,y2]]
poly = Polygon( xy, animated=True,lw=2,fill=False )
add_patch(poly)
.
.
in the loop:
poly.set_xy = xy_new
poly.update_transorm() (no such routine)

The set_xy seems to work (at least no errors), but I don't see how
to "update the transform" as for the circle.