Skip to content

nbagg blit support #4288

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

Closed
azjps opened this issue Mar 27, 2015 · 17 comments · Fixed by #19059
Closed

nbagg blit support #4288

azjps opened this issue Mar 27, 2015 · 17 comments · Fixed by #19059

Comments

@azjps
Copy link
Contributor

azjps commented Mar 27, 2015

Hi, on the nbagg backend, blit doesn't seem to update without re-drawing. Here's a simple example:

import matplotlib.pyplot as plt

prev_artist = None
cur_y = 0.1

def onclick_handle(event):
  """Should draw elevating green line on each mouse click"""
  global ax, bg, prev_artist, cur_y
  ax.figure.canvas.restore_region(bg)
  if prev_artist:
    prev_artist.remove()
  cur_y += 0.1
  prev_artist = ax.plot([0, 1], [cur_y, cur_y], 'g')[0]
  ax.draw_artist(prev_artist)
  ax.figure.canvas.blit(ax.bbox)
  print "Drew line"

ax = plt.gca()
ax.plot([0, 1], [0, 1], 'r')
# ax.figure.canvas.draw()
bg = ax.figure.canvas.copy_from_bbox(ax.bbox)
ax.figure.canvas.mpl_connect('button_press_event', onclick_handle)

With %matplotlib nbagg, clicking on the plot doesn't cause any updates until the plot is re-drawn. With other backends (say qt) the plot updates immediately on clicking.

An unrelated oddity, if I uncomment the draw command and try re-drawing the figure just disappears (edit - on 1.4.3; seems fixed on 1.5.1dev1).

If it helps, IPython version is 2.3.0 and matplotlib is 1.4.3/1.5.1dev1; occurs on both chrome and firefox. UAT including animation example more or less run fine.

(Coincidental to the other nbagg animation issue just posted. Google led to this post also.)

@tacaswell
Copy link
Member

Part of the problem with blitting is that nothing is triggering the python -> js communication is never getting triggered.

If you add a

  ax.figure.canvas.draw_idle()

line inside your call back it behaves as expected.

@tacaswell tacaswell added this to the Color overhaul milestone Mar 28, 2015
@azjps
Copy link
Contributor Author

azjps commented Mar 28, 2015

Right, although my applications were using blit precisely to be faster than re-drawing. Just curious do animation.FuncAnimation(.., blit=True), etc also do the same thing for nbagg? I'm more than happy to add a check for nbagg backend and call draw_idle() for now though.

Edit - oh ok didn't realize that draw_idle might not do a full re-draw.

@tacaswell
Copy link
Member

Digging into this a bit more, I don't think draw_idle is doing what I think (and is in fact triggering a full re-draw after all)

%matplotlib notebook
import matplotlib.pyplot as plt

prev_artist = None
cur_y = 0.1

def onclick_handle(event):
  """Should draw elevating green line on each mouse click"""
  global ax, bg, prev_artist, cur_y
  ax.figure.canvas.restore_region(bg)
  if prev_artist:
    prev_artist.remove()
  cur_y += 0.1
  prev_artist = ax.plot([0, 1], [cur_y, cur_y], 'g')[0]
  ax.draw_artist(prev_artist)
  ax.figure.canvas.blit(ax.bbox)
  ax.figure.canvas._force_full = True
  ax.figure.canvas._png_is_old = True
  ax.figure.canvas.manager.refresh_all()
  print ("Drew line")

ax = plt.gca()
ax.plot([0, 1], [0, 1], 'r')
plt.draw()
bg = ax.figure.canvas.copy_from_bbox(ax.bbox)
ax.figure.canvas.mpl_connect('button_press_event', onclick_handle)

Sort of works, (but does not look like the restore is working correctly...

@tacaswell
Copy link
Member

The blit implementation on the webagg canavas is a no-op the private magic I am poking at is what should be in blit and it now seems to work half the time...

@tacaswell
Copy link
Member

And it looks like webagg keeps two Agg renderers around (so that it can do diffs).

%matplotlib notebook
import matplotlib.pyplot as plt

prev_artist = None
cur_y = 0.1

def onclick_handle(event):
    """Should draw elevating green line on each mouse click"""
    global ax, bg, prev_artist, cur_y
    ax.figure.canvas._png_is_old = True
    ax.figure.canvas._force_full = True
    ax.figure.canvas._renderer.restore_region(bg, None, None)
    if prev_artist:
        prev_artist.remove()
    cur_y += 0.1
    prev_artist, = ax.plot([0, 1], [cur_y, cur_y], 'g', lw=5)
    prev_artist.draw(ax.figure.canvas._renderer)
    ax.figure.canvas.manager.refresh_all()

    print ("Drew line")

ax = plt.gca()
ax.plot([0, 1], [0, 1], 'r')
plt.draw()

bg = ax.figure.canvas._last_renderer.copy_from_bbox(ax.bbox)
ax.figure.canvas.mpl_connect('button_press_event', onclick_handle)

Works correctly (well, until you run out of the y-range and it starts auto-scaling with out properly updating your bg).

@pelson The flip-flopping renderers break the assumptions of the _cachedRender attribute on all of the artists (half of the time). Think it is worth updating that every time through refresh_all?

@tacaswell
Copy link
Member

🐑 turns out that _cachedRenderer is only a thing an Axes and Figure objects so fixing that up is a no-brainer.

tacaswell added a commit to tacaswell/matplotlib that referenced this issue Mar 28, 2015
@tacaswell tacaswell self-assigned this Mar 28, 2015
@tacaswell
Copy link
Member

@azjps Thank you for kicking the tires of nbagg and providing feed back 😄 .

I don't know if that has been coming through in my other comments.

@azjps
Copy link
Contributor Author

azjps commented Mar 30, 2015

I had been excited for the pending introduction of a notebook backend for a while, but only a couple of days ago did I find out that nbagg has already been around for a year 😆. Your comments as always have been really helpful in poking around.

By the way, not sure if its been pointed out before, but with or without closing the figure (and even if you explicitly call plt.close), if you run UAT 13 multiple times, the animation goes haywire, and the only way to stop it from stuttering seems to be to restart the kernel.

[edit: misremembered something.]

@tacaswell tacaswell modified the milestones: Color overhaul, next major release (2.0) Oct 26, 2015
blink1073 pushed a commit to blink1073/matplotlib that referenced this issue Dec 27, 2015
@tacaswell tacaswell modified the milestones: 2.0 (style change major release), 2.1 (next point release) Mar 21, 2016
@mbewley
Copy link

mbewley commented Sep 8, 2017

Eagerly waiting for this one! My use case is that I've built a user interface in Jupyter, using ipywidgets and interactive matplotlib. Updates are very slow without blitting! (Just want to render a little circle on top of a large image most of the time).

@mbewley
Copy link

mbewley commented Sep 18, 2017

I tried making the modifications from blink1073's backend_webagg_core.py file on top of the matplotlib 2.0.2 code (pretty straightforward to do). Blitting works well for me in a notebook now, both in Windows 10 and Ubuntu. I've never committed to the matplotlib codebase before though, so hopefully someone who knows what they're doing can pick this up for 2.1. Happy to help in any way I can.

@tacaswell
Copy link
Member

@mbewley can you open a PR with the changes? See https://matplotlib.org/devdocs/devel/contributing.html for some details, if that isn't clear drop into our gitter room (https://gitter.im/matplotlib/matplotlib) for help!

@mbewley
Copy link

mbewley commented Sep 25, 2017

Alright, I'll give it a shot. I emailed blink1073 - he's not interested in developing this any more, so is happy for others to take on his blitting work.

@mbewley
Copy link

mbewley commented Sep 27, 2017

Pull request done - I've made a minimal example notebook for tsting, but wasn't sure where the best place to put it is?

@mbewley
Copy link

mbewley commented Sep 28, 2017

Code for minimal example added to pull request.

@tacaswell tacaswell modified the milestones: 2.1 (next point release), 2.2 (next next feature release) Oct 3, 2017
@mbewley
Copy link

mbewley commented Jan 3, 2018

Hey, anything I can do to help get this into the 2.2 release? (and is that realistically going to happen on 30th Jan?).

@tacaswell
Copy link
Member

You are doing the right thing to make sure this gets in and we are going to try to have an RC by Jan 30 (but this being mostly a volunteer effort deadlines are flexible).

@mbewley
Copy link

mbewley commented Jan 4, 2018

Cool, thanks - see comments in #9240

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.

5 participants