Help with blitting bug with subplots and markers

Hi,

I've been debugging this for hours now and could really use the help
of someone smarter than me. In working on blitting with animations,
I've run into a problem when trying to use blitting + multiple
subplots + lines with markers. It's an esoteric combination to be
sure, but I have a script (attached) that demonstrates my problem. As
far as I can tell, the addition of a marker to a line object causes to
canvas.restore_region() to no longer function (I've paused the
animation, after a blit to flush the draw, after every stage). The
data in the region saved from copy_from_bbox is fine, but calling
restore_region() with it has no effect. Removing marker from the line
specification causes the problem to disappear. The net effect of the
problem is that the other subplot (than the one with the marker) does
not have the previous draw cleared, resulting in a smearing effect.

Anybody have a clue?

Ryan

blit_bug.py (1.47 KB)

···

--
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma

Alright, before I go to bed, I found the following line in
src/_backend_agg.cpp at line 709 (in draw_markers()) makes all the
difference:

set_clipbox(gc.cliprect, rendererBase);

Commenting out this line fixes my problem. I'm not sure why it's a
problem, (maybe a missing restore to previous state somewhere?). I'll
look into this tomorrow, but it would probably be a lot easier with
someone familiar with the code.

Ryan

···

On Sat, Jul 3, 2010 at 12:33 AM, Ryan May <rmay31@...149...> wrote:

Hi,

I've been debugging this for hours now and could really use the help
of someone smarter than me. In working on blitting with animations,
I've run into a problem when trying to use blitting + multiple
subplots + lines with markers. It's an esoteric combination to be
sure, but I have a script (attached) that demonstrates my problem. As
far as I can tell, the addition of a marker to a line object causes to
canvas.restore_region() to no longer function (I've paused the
animation, after a blit to flush the draw, after every stage). The
data in the region saved from copy_from_bbox is fine, but calling
restore_region() with it has no effect. Removing marker from the line
specification causes the problem to disappear. The net effect of the
problem is that the other subplot (than the one with the marker) does
not have the previous draw cleared, resulting in a smearing effect.

Anybody have a clue?

Ryan

--
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma

--
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma

Following up again, it seems like the problem is that draw_marker is
calling set_clipbox() on the rendererBase instead of theRasterizer,
which is done at 7 other places in the code (as opposed to only one
other location for rendererBase). Since rendererBase is used for
restore_region, this makes sense as to why it would fix my problem. I
can confirm making the change fixes my problem and doesn't cause any
other issues in my (admittedly brief so far) testing.

(If this isn't the proper fix, an alternative is to call
rendererBase.reset_clipping(true), but I really think this is working
around the issue).

Can someone more familiar with the agg backend weigh in here? I'm
pretty comfortable with the fix, but don't want to be responsible for
breaking pretty much all of matplotlib.

Ryan

···

On Sat, Jul 3, 2010 at 1:11 AM, Ryan May <rmay31@...149...> wrote:

Alright, before I go to bed, I found the following line in
src/_backend_agg.cpp at line 709 (in draw_markers()) makes all the
difference:

set_clipbox(gc.cliprect, rendererBase);

Commenting out this line fixes my problem. I'm not sure why it's a
problem, (maybe a missing restore to previous state somewhere?). I'll
look into this tomorrow, but it would probably be a lot easier with
someone familiar with the code.

--
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma

Does marker clipping still work with the proposed change?

The only thing that is special about marker drawing is we use cached
marker rasters to make drawing many of them efficient, but I don't
recall anymore whether this required special clipping treatment.

JDH

···

On Sat, Jul 3, 2010 at 11:53 AM, Ryan May <rmay31@...149...> wrote:

On Sat, Jul 3, 2010 at 1:11 AM, Ryan May <rmay31@...149...> wrote:

Alright, before I go to bed, I found the following line in
src/_backend_agg.cpp at line 709 (in draw_markers()) makes all the
difference:

set_clipbox(gc.cliprect, rendererBase);

Commenting out this line fixes my problem. I'm not sure why it's a
problem, (maybe a missing restore to previous state somewhere?). I'll
look into this tomorrow, but it would probably be a lot easier with
someone familiar with the code.

Following up again, it seems like the problem is that draw_marker is
calling set_clipbox() on the rendererBase instead of theRasterizer,
which is done at 7 other places in the code (as opposed to only one
other location for rendererBase). Since rendererBase is used for
restore_region, this makes sense as to why it would fix my problem. I
can confirm making the change fixes my problem and doesn't cause any
other issues in my (admittedly brief so far) testing.

(If this isn't the proper fix, an alternative is to call
rendererBase.reset_clipping(true), but I really think this is working
around the issue).

Can someone more familiar with the agg backend weigh in here? I'm
pretty comfortable with the fix, but don't want to be responsible for
breaking pretty much all of matplotlib.

   

Alright, before I go to bed, I found the following line in
src/_backend_agg.cpp at line 709 (in draw_markers()) makes all the
difference:

set_clipbox(gc.cliprect, rendererBase);

Commenting out this line fixes my problem. I'm not sure why it's a
problem, (maybe a missing restore to previous state somewhere?). I'll
look into this tomorrow, but it would probably be a lot easier with
someone familiar with the code.
       

Following up again, it seems like the problem is that draw_marker is
calling set_clipbox() on the rendererBase instead of theRasterizer,
which is done at 7 other places in the code (as opposed to only one
other location for rendererBase). Since rendererBase is used for
restore_region, this makes sense as to why it would fix my problem. I
can confirm making the change fixes my problem and doesn't cause any
other issues in my (admittedly brief so far) testing.

(If this isn't the proper fix, an alternative is to call
rendererBase.reset_clipping(true), but I really think this is working
around the issue).

Can someone more familiar with the agg backend weigh in here? I'm
pretty comfortable with the fix, but don't want to be responsible for
breaking pretty much all of matplotlib.
     

Does marker clipping still work with the proposed change?
   

Unfortunately, not.

Ryan's suggestion to call rendererBase.reset_clipping(true) upon exit of draw_markers does seem to work both for the blitting and clipping, however. I don't think this is working around the issue -- I think it's probably the correct solution. The clipping state really should probably be reset around every backend call -- but this is the first instance we've seen where the stickiness is a problem, so I think I'll only fix it here (and not reset all the clipping calls to theRasterizer).

I've committed this change to 8515.

Mike

···

On 07/04/2010 09:32 PM, John Hunter wrote:

On Sat, Jul 3, 2010 at 11:53 AM, Ryan May<rmay31@...149...> wrote:

On Sat, Jul 3, 2010 at 1:11 AM, Ryan May<rmay31@...149...> wrote:

The only thing that is special about marker drawing is we use cached
marker rasters to make drawing many of them efficient, but I don't
recall anymore whether this required special clipping treatment.

JDH

------------------------------------------------------------------------------
This SF.net email is sponsored by Sprint
What will you do first with EVO, the first 4G phone?
Visit sprint.com/first -- http://p.sf.net/sfu/sprint-com-first
_______________________________________________
Matplotlib-devel mailing list
Matplotlib-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-devel
   
--
Michael Droettboom
Science Software Branch
Space Telescope Science Institute
Baltimore, Maryland, USA

Did this make it into 1.0.0? I didn't see it in the merges you did
earlier? If not, can we get it into the stable branch for the next
bugfix release? I'd love to only require the latest release (and not
trunk) when I finally put out my animation stuff for wider testing.

Ryan

···

On Tue, Jul 6, 2010 at 10:19 AM, Michael Droettboom <mdroe@...31...> wrote:

On 07/04/2010 09:32 PM, John Hunter wrote:

On Sat, Jul 3, 2010 at 11:53 AM, Ryan May<rmay31@...149...> wrote:

On Sat, Jul 3, 2010 at 1:11 AM, Ryan May<rmay31@...149...> wrote:

Alright, before I go to bed, I found the following line in
src/_backend_agg.cpp at line 709 (in draw_markers()) makes all the
difference:

set_clipbox(gc.cliprect, rendererBase);

Commenting out this line fixes my problem. I'm not sure why it's a
problem, (maybe a missing restore to previous state somewhere?). I'll
look into this tomorrow, but it would probably be a lot easier with
someone familiar with the code.

Following up again, it seems like the problem is that draw_marker is
calling set_clipbox() on the rendererBase instead of theRasterizer,
which is done at 7 other places in the code (as opposed to only one
other location for rendererBase). Since rendererBase is used for
restore_region, this makes sense as to why it would fix my problem. I
can confirm making the change fixes my problem and doesn't cause any
other issues in my (admittedly brief so far) testing.

(If this isn't the proper fix, an alternative is to call
rendererBase.reset_clipping(true), but I really think this is working
around the issue).

Can someone more familiar with the agg backend weigh in here? I'm
pretty comfortable with the fix, but don't want to be responsible for
breaking pretty much all of matplotlib.

Does marker clipping still work with the proposed change?

Unfortunately, not.

Ryan's suggestion to call rendererBase.reset_clipping(true) upon exit of
draw_markers does seem to work both for the blitting and clipping,
however. I don't think this is working around the issue -- I think it's
probably the correct solution. The clipping state really should
probably be reset around every backend call -- but this is the first
instance we've seen where the stickiness is a problem, so I think I'll
only fix it here (and not reset all the clipping calls to theRasterizer).

I've committed this change to 8515.

Mike

--
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma