Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

animation blitting is no longer working #4947

Closed
jrevans opened this issue Aug 17, 2015 · 6 comments · Fixed by #4951
Closed

animation blitting is no longer working #4947

jrevans opened this issue Aug 17, 2015 · 6 comments · Fixed by #4951
Assignees
Milestone

Comments

@jrevans
Copy link

jrevans commented Aug 17, 2015

This is mentioned in #4897.

I currently do not have a solution for this one, but I do have a script that demonstrates the problem. I am using the current devel branch and a Qt5Agg backend.

The following is in reference to the attached script.

The line 'bg = fig.canvas.copy_from_bbox( fig.bbox )' will in fact save the current Agg buffer state as appropriate. The later calls to 'fig.canvas.restore_region( bg, fig.bbox )' however do not seem to actually restore the Agg buffers to the saved state, because in the subsequent call to 'fig.canvas.blit( fig.bbox )' the Agg buffers are still in the same state as before the call to 'restore_region'. The result is the red ellipse gets drawn multiple times to the Agg backend.

At the end of the script a new call to the canvas 'draw' method causes the entire figure to redraw (and the Agg backend), and the plot then is updated to look as expected.

======================================================================
#   blit.py
======================================================================
#!/bin/env python

import pylab as p
from matplotlib.patches import Ellipse
import math, time

p.ion()
fig, ax = p.subplots()
ax.set_xlim( [ -3, 3 ] )
ax.set_ylim( [ -3, 3 ] )

e1 = Ellipse( [ 0, 0 ], 1, 2, 0 )
ax.add_patch( e1 )

e2 = Ellipse( [ 2, 0 ], 1, 3, 0 )
ax.add_patch( e2 )

raw_input( "Press return to start blit" )

bg = fig.canvas.copy_from_bbox( fig.bbox )

e0 = Ellipse( [1,0], 1, 1, 0, facecolor="red" )
ax.add_patch( e0 )

t0 = time.time()
num = 0
while True:
   dt = time.time() - t0
   if dt > 1:
      print "%d frames in %g sec (%g frames/sec)" % ( num, dt, num/dt )
      break

   fig.canvas.restore_region( bg, fig.bbox )

   x = num / 10.0
   e0.center = [ math.cos( x ), math.sin( x ) ]

   ax.draw_artist( e0 )
   fig.canvas.blit( fig.bbox )

   num += 1


print "================="
print "Qt5 bug: red ellipse is not removed each time."
raw_input( "Press return to remove red ellipse" )

e0.remove()
fig.canvas.restore_region( bg, fig.bbox )
fig.canvas.blit( fig.bbox )

print "================="
print "The red ellipse should be gone - if it's still there, try to resize"
print "the screen.  In some cases an extra 'draw' happens here which "
print "causes the entire plot to redraw and look correct.  In Qt5agg, "
print "this shows the bug..."
print
raw_input( "Press return to exit" )
@tacaswell
Copy link
Member

I ended up modifying your script a bit (mostly style + python3 compatibility as I only have qt5 + python3 set up to test with) and can not reproduce this issue with either pyqt4 or pyqt5 in python3 @ 3520e94

from __future__ import print_function
import matplotlib.pyplot as plt
from matplotlib.patches import Ellipse
import math
import time

plt.ion()
fig, ax = plt.subplots()
ax.set_xlim([-3, 3])
ax.set_ylim([-3, 3])

e1 = Ellipse([0, 0], 1, 2, 0)
ax.add_patch(e1)

e2 = Ellipse([2, 0], 1, 3, 0)
ax.add_patch(e2)

input("Press return to start blit")

bg = fig.canvas.copy_from_bbox(fig.bbox)

e0 = Ellipse([1, 0], 1, 1, 0, facecolor="red")
ax.add_patch(e0)

t0 = time.time()
num = 0
while True:
    dt = time.time() - t0
    if dt > 1:
        print("%d frames in %g sec (%g frames/sec)" % (num, dt, num/dt))
        break

    fig.canvas.restore_region(bg, fig.bbox)

    x = num / 10.0
    e0.center = [math.cos(x), math.sin(x)]

    ax.draw_artist(e0)
    fig.canvas.blit(fig.bbox)

    num += 1


print("=================")
print("Qt5 bug: red ellipse is not removed each time.")
input("Press return to remove red ellipse")

e0.remove()
fig.canvas.restore_region(bg, fig.bbox)
fig.canvas.blit(fig.bbox)

print("=================")
print("The red ellipse should be gone - if it's still there, try to resize")
print("the screen.  In some cases an extra 'draw' happens here which ")
print("causes the entire plot to redraw and look correct.  In Qt5agg, ")
print("this shows the bug...")

input("Press return to exit")

@mdehoon
Copy link
Contributor

mdehoon commented Aug 18, 2015

With the current master (latest commit 512b5d7), the animation doesn't run at all with qt5agg. With tkagg, the animation runs, but the red ellipse gets drawn multiple times as described by @jrevans .

@tacaswell
Copy link
Member

ah, I now see what is going on, in 512b5d7 I am getting a bunch of extra draws so it looks like the animation is working, but is running much slower than it should be. I do see the overlapped circles with tkagg and if I merge the two qt PRs into master.

@tacaswell
Copy link
Member

The problem seems to be this code path https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/backends/backend_agg.py#L347

If you change

fig.canvas.restore_region(bg)

then it works as expected.

This looks like fall out from the cxx conversion.

tacaswell added a commit to tacaswell/matplotlib that referenced this issue Aug 18, 2015
In ba40160 Remove use of PyCXX in core C++ extensions the order
of the arguments into the `restore_region` that takes off sets
was swapped.  The order should be (x1, x2, y1, y2, offset_x, offset_y)
which was the order of `restore_region2` (a function removed as part
of the refactor in favor of simple dispatch in the wrapper code +
c++ function overloading) and the order of the arguments passed
out of the python layer, but at the c++ layer they were being mapped
to (offset_x, offset_y, x1, x2, y1, y2) which was causing a region
not of interest to be restored.

closes matplotlib#4947
@tacaswell tacaswell added this to the next point release milestone Aug 18, 2015
@tacaswell tacaswell self-assigned this Aug 18, 2015
@tacaswell
Copy link
Member

@mdehoon @jrevans Thanks! Can you check if #4951 fixes this for you?

Sorry I was being cranky.

@mdehoon
Copy link
Contributor

mdehoon commented Aug 18, 2015

@tacaswell #4951 fixes the problem for tkagg.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants