Skip to content

Nbagg enhancements #3552

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

Merged
merged 4 commits into from
Sep 24, 2014
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Fixed the webagg backend to handle figures with transparency.
  • Loading branch information
pelson committed Sep 24, 2014
commit aa583e4a114cb5883bf43d9d8d63c5323a898800
21 changes: 6 additions & 15 deletions lib/matplotlib/backends/backend_nbagg.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
"""Interactive figures in the IPython notebook"""
# Note: There is a notebook in
# lib/matplotlib/backends/web_backend/nbagg_uat.ipynb to help verify
# that changes made maintain expected behaviour.

from base64 import b64encode
from contextlib import contextmanager
import json
Expand Down Expand Up @@ -33,8 +37,8 @@ def __call__(self, block=None):
for manager in managers:
manager.show()

if not is_interactive() and manager in Gcf._activeQue:
Gcf._activeQue.remove(manager)
if not is_interactive() and manager in Gcf._activeQue:
Gcf._activeQue.remove(manager)


show = Show()
Expand Down Expand Up @@ -189,19 +193,6 @@ def start_event_loop(self, timeout):
def stop_event_loop(self):
FigureCanvasBase.stop_event_loop_default(self)

def draw(self):
renderer = self.get_renderer()

self._png_is_old = True

backend_agg.RendererAgg.lock.acquire()
try:
self.figure.draw(renderer)
finally:
backend_agg.RendererAgg.lock.release()
# Swap the frames
self.manager.refresh_all()


def new_figure_manager(num, *args, **kwargs):
"""
Expand Down
33 changes: 20 additions & 13 deletions lib/matplotlib/backends/backend_webagg_core.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ def show(self):
show()

def draw(self):
renderer = self.get_renderer()
renderer = self.get_renderer(cleared=True)

self._png_is_old = True

Expand All @@ -91,21 +91,25 @@ def get_diff_image(self):
# The buffer is created as type uint32 so that entire
# pixels can be compared in one numpy call, rather than
# needing to compare each plane separately.
buff = np.frombuffer(
self.get_renderer().buffer_rgba(), dtype=np.uint32)
buff.shape = (
self._renderer.height, self._renderer.width)
renderer = self.get_renderer()
buff = np.frombuffer(renderer.buffer_rgba(), dtype=np.uint32)

if not self._force_full:
last_buffer = np.frombuffer(
self._last_renderer.buffer_rgba(), dtype=np.uint32)
last_buffer.shape = (
self._renderer.height, self._renderer.width)
buff.shape = (renderer.height, renderer.width)

# If any pixels have transparency, we need to force a full draw
# as we cannot overlay new on top of old.
pixels = buff.view(dtype=np.uint8).reshape(buff.shape + (4,))
some_transparency = np.any(pixels[:, :, 3] != 255)

output = buff

if not self._force_full and not some_transparency:
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This has been raised as a concern by @mdboom in #5419.

last_buffer = np.frombuffer(self._last_renderer.buffer_rgba(),
dtype=np.uint32)
last_buffer.shape = (renderer.height, renderer.width)

diff = buff != last_buffer
output = np.where(diff, buff, 0)
else:
output = buff

# Clear out the PNG data buffer rather than recreating it
# each time. This reduces the number of memory
Expand All @@ -122,7 +126,7 @@ def get_diff_image(self):

# Swap the renderer frames
self._renderer, self._last_renderer = (
self._last_renderer, self._renderer)
self._last_renderer, renderer)
self._force_full = False
self._png_is_old = False
return self._png_buffer.getvalue()
Expand All @@ -147,6 +151,9 @@ def get_renderer(self, cleared=None):
w, h, self.figure.dpi)
self._lastKey = key

elif cleared:
self._renderer.clear()

return self._renderer

def handle_event(self, event):
Expand Down
2 changes: 2 additions & 0 deletions lib/matplotlib/backends/web_backend/mpl.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ mpl.figure = function(figure_id, websocket, ondownload, parent_element) {
}

this.imageObj.onload = function() {
fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);
fig.context.drawImage(fig.imageObj, 0, 0);
fig.waiting = false;
};
Expand Down Expand Up @@ -322,6 +323,7 @@ mpl.figure.prototype._make_on_message_function = function(fig) {
(window.URL || window.webkitURL).revokeObjectURL(
fig.imageObj.src);
}

fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(
evt.data);
fig.updated_canvas_event();
Expand Down
14 changes: 4 additions & 10 deletions lib/matplotlib/backends/web_backend/nbagg_uat.ipynb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"metadata": {
"name": "",
"signature": "sha256:34c3a5a9d82d5a3c433f0c03f0717d43e1d14eaf78f88a64f094d104fa636ddc"
"signature": "sha256:1d491e506b54b126f6971897d3249a9e6f96f9d50bf4e4ba8d179c6b7b1aefa8"
},
"nbformat": 3,
"nbformat_minor": 0,
Expand All @@ -24,7 +24,6 @@
"import matplotlib\n",
"reload(matplotlib)\n",
"\n",
"\n",
"matplotlib.use('nbagg')\n",
"\n",
"import matplotlib.backends.backend_nbagg\n",
Expand All @@ -47,6 +46,9 @@
"cell_type": "code",
"collapsed": false,
"input": [
"import matplotlib.backends.backend_webagg_core\n",
"reload(matplotlib.backends.backend_webagg_core)\n",
"\n",
"import matplotlib.pyplot as plt\n",
"plt.interactive(False)\n",
"\n",
Expand Down Expand Up @@ -382,14 +384,6 @@
"language": "python",
"metadata": {},
"outputs": []
},
{
"cell_type": "code",
"collapsed": false,
"input": [],
"language": "python",
"metadata": {},
"outputs": []
}
],
"metadata": {}
Expand Down