Skip to content

Instantly share code, notes, and snippets.

@cycomanic
Created April 16, 2016 14:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save cycomanic/ec0145bb67d96ad9a0f27079779c3abc to your computer and use it in GitHub Desktop.
Save cycomanic/ec0145bb67d96ad9a0f27079779c3abc to your computer and use it in GitHub Desktop.
interactive figure issues matplotlib notebook backend
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"%matplotlib notebook\n",
"import matplotlib.pylab as plt\n",
"from ipywidgets.widgets.interaction import interact\n",
"import ipywidgets.widgets as widgets\n",
"\n",
"def plotsin(f, fig, ax):\n",
" x = plt.linspace(-10,10, 2**10)\n",
" s = plt.sin(f*x)\n",
" if len(ax.lines):\n",
" ax.lines[0].set_ydata(s)\n",
" else:\n",
" ax.plot(x,s)\n",
" fig.canvas.draw()\n",
"\n",
"\n",
"def plot_interactive():\n",
" fig,ax = plt.subplots(1,1)\n",
" def pls(f):\n",
" plotsin(f, fig, ax)\n",
" ww = widgets.FloatSlider(description='frequency', min=1, max=100)\n",
" interact(pls, f=ww)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"plot_interactive()"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
"application/javascript": [
"/* Put everything inside the global mpl namespace */\n",
"window.mpl = {};\n",
"\n",
"mpl.get_websocket_type = function() {\n",
" if (typeof(WebSocket) !== 'undefined') {\n",
" return WebSocket;\n",
" } else if (typeof(MozWebSocket) !== 'undefined') {\n",
" return MozWebSocket;\n",
" } else {\n",
" alert('Your browser does not have WebSocket support.' +\n",
" 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
" 'Firefox 4 and 5 are also supported but you ' +\n",
" 'have to enable WebSockets in about:config.');\n",
" };\n",
"}\n",
"\n",
"mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
" this.id = figure_id;\n",
"\n",
" this.ws = websocket;\n",
"\n",
" this.supports_binary = (this.ws.binaryType != undefined);\n",
"\n",
" if (!this.supports_binary) {\n",
" var warnings = document.getElementById(\"mpl-warnings\");\n",
" if (warnings) {\n",
" warnings.style.display = 'block';\n",
" warnings.textContent = (\n",
" \"This browser does not support binary websocket messages. \" +\n",
" \"Performance may be slow.\");\n",
" }\n",
" }\n",
"\n",
" this.imageObj = new Image();\n",
"\n",
" this.context = undefined;\n",
" this.message = undefined;\n",
" this.canvas = undefined;\n",
" this.rubberband_canvas = undefined;\n",
" this.rubberband_context = undefined;\n",
" this.format_dropdown = undefined;\n",
"\n",
" this.image_mode = 'full';\n",
"\n",
" this.root = $('<div/>');\n",
" this._root_extra_style(this.root)\n",
" this.root.attr('style', 'display: inline-block');\n",
"\n",
" $(parent_element).append(this.root);\n",
"\n",
" this._init_header(this);\n",
" this._init_canvas(this);\n",
" this._init_toolbar(this);\n",
"\n",
" var fig = this;\n",
"\n",
" this.waiting = false;\n",
"\n",
" this.ws.onopen = function () {\n",
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
" fig.send_message(\"send_image_mode\", {});\n",
" fig.send_message(\"refresh\", {});\n",
" }\n",
"\n",
" this.imageObj.onload = function() {\n",
" if (fig.image_mode == 'full') {\n",
" // Full images could contain transparency (where diff images\n",
" // almost always do), so we need to clear the canvas so that\n",
" // there is no ghosting.\n",
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
" }\n",
" fig.context.drawImage(fig.imageObj, 0, 0);\n",
" };\n",
"\n",
" this.imageObj.onunload = function() {\n",
" this.ws.close();\n",
" }\n",
"\n",
" this.ws.onmessage = this._make_on_message_function(this);\n",
"\n",
" this.ondownload = ondownload;\n",
"}\n",
"\n",
"mpl.figure.prototype._init_header = function() {\n",
" var titlebar = $(\n",
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
" 'ui-helper-clearfix\"/>');\n",
" var titletext = $(\n",
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
" 'text-align: center; padding: 3px;\"/>');\n",
" titlebar.append(titletext)\n",
" this.root.append(titlebar);\n",
" this.header = titletext[0];\n",
"}\n",
"\n",
"\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
"\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._init_canvas = function() {\n",
" var fig = this;\n",
"\n",
" var canvas_div = $('<div/>');\n",
"\n",
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
"\n",
" function canvas_keyboard_event(event) {\n",
" return fig.key_event(event, event['data']);\n",
" }\n",
"\n",
" canvas_div.keydown('key_press', canvas_keyboard_event);\n",
" canvas_div.keyup('key_release', canvas_keyboard_event);\n",
" this.canvas_div = canvas_div\n",
" this._canvas_extra_style(canvas_div)\n",
" this.root.append(canvas_div);\n",
"\n",
" var canvas = $('<canvas/>');\n",
" canvas.addClass('mpl-canvas');\n",
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
"\n",
" this.canvas = canvas[0];\n",
" this.context = canvas[0].getContext(\"2d\");\n",
"\n",
" var rubberband = $('<canvas/>');\n",
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
"\n",
" var pass_mouse_events = true;\n",
"\n",
" canvas_div.resizable({\n",
" start: function(event, ui) {\n",
" pass_mouse_events = false;\n",
" },\n",
" resize: function(event, ui) {\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" stop: function(event, ui) {\n",
" pass_mouse_events = true;\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" });\n",
"\n",
" function mouse_event_fn(event) {\n",
" if (pass_mouse_events)\n",
" return fig.mouse_event(event, event['data']);\n",
" }\n",
"\n",
" rubberband.mousedown('button_press', mouse_event_fn);\n",
" rubberband.mouseup('button_release', mouse_event_fn);\n",
" // Throttle sequential mouse events to 1 every 20ms.\n",
" rubberband.mousemove('motion_notify', mouse_event_fn);\n",
"\n",
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
"\n",
" canvas_div.on(\"wheel\", function (event) {\n",
" event = event.originalEvent;\n",
" event['data'] = 'scroll'\n",
" if (event.deltaY < 0) {\n",
" event.step = 1;\n",
" } else {\n",
" event.step = -1;\n",
" }\n",
" mouse_event_fn(event);\n",
" });\n",
"\n",
" canvas_div.append(canvas);\n",
" canvas_div.append(rubberband);\n",
"\n",
" this.rubberband = rubberband;\n",
" this.rubberband_canvas = rubberband[0];\n",
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
" this.rubberband_context.strokeStyle = \"#000000\";\n",
"\n",
" this._resize_canvas = function(width, height) {\n",
" // Keep the size of the canvas, canvas container, and rubber band\n",
" // canvas in synch.\n",
" canvas_div.css('width', width)\n",
" canvas_div.css('height', height)\n",
"\n",
" canvas.attr('width', width);\n",
" canvas.attr('height', height);\n",
"\n",
" rubberband.attr('width', width);\n",
" rubberband.attr('height', height);\n",
" }\n",
"\n",
" // Set the figure to an initial 600x600px, this will subsequently be updated\n",
" // upon first draw.\n",
" this._resize_canvas(600, 600);\n",
"\n",
" // Disable right mouse context menu.\n",
" $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
" return false;\n",
" });\n",
"\n",
" function set_focus () {\n",
" canvas.focus();\n",
" canvas_div.focus();\n",
" }\n",
"\n",
" window.setTimeout(set_focus, 100);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items) {\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) {\n",
" // put a spacer in here.\n",
" continue;\n",
" }\n",
" var button = $('<button/>');\n",
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
" 'ui-button-icon-only');\n",
" button.attr('role', 'button');\n",
" button.attr('aria-disabled', 'false');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
"\n",
" var icon_img = $('<span/>');\n",
" icon_img.addClass('ui-button-icon-primary ui-icon');\n",
" icon_img.addClass(image);\n",
" icon_img.addClass('ui-corner-all');\n",
"\n",
" var tooltip_span = $('<span/>');\n",
" tooltip_span.addClass('ui-button-text');\n",
" tooltip_span.html(tooltip);\n",
"\n",
" button.append(icon_img);\n",
" button.append(tooltip_span);\n",
"\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" var fmt_picker_span = $('<span/>');\n",
"\n",
" var fmt_picker = $('<select/>');\n",
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
" fmt_picker_span.append(fmt_picker);\n",
" nav_element.append(fmt_picker_span);\n",
" this.format_dropdown = fmt_picker[0];\n",
"\n",
" for (var ind in mpl.extensions) {\n",
" var fmt = mpl.extensions[ind];\n",
" var option = $(\n",
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
" fmt_picker.append(option)\n",
" }\n",
"\n",
" // Add hover states to the ui-buttons\n",
" $( \".ui-button\" ).hover(\n",
" function() { $(this).addClass(\"ui-state-hover\");},\n",
" function() { $(this).removeClass(\"ui-state-hover\");}\n",
" );\n",
"\n",
" var status_bar = $('<span class=\"mpl-message\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"}\n",
"\n",
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
" // which will in turn request a refresh of the image.\n",
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
"}\n",
"\n",
"mpl.figure.prototype.send_message = function(type, properties) {\n",
" properties['type'] = type;\n",
" properties['figure_id'] = this.id;\n",
" this.ws.send(JSON.stringify(properties));\n",
"}\n",
"\n",
"mpl.figure.prototype.send_draw_message = function() {\n",
" if (!this.waiting) {\n",
" this.waiting = true;\n",
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
" }\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" var format_dropdown = fig.format_dropdown;\n",
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
" fig.ondownload(fig, format);\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
" var size = msg['size'];\n",
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
" fig._resize_canvas(size[0], size[1]);\n",
" fig.send_message(\"refresh\", {});\n",
" };\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
" var x0 = msg['x0'];\n",
" var y0 = fig.canvas.height - msg['y0'];\n",
" var x1 = msg['x1'];\n",
" var y1 = fig.canvas.height - msg['y1'];\n",
" x0 = Math.floor(x0) + 0.5;\n",
" y0 = Math.floor(y0) + 0.5;\n",
" x1 = Math.floor(x1) + 0.5;\n",
" y1 = Math.floor(y1) + 0.5;\n",
" var min_x = Math.min(x0, x1);\n",
" var min_y = Math.min(y0, y1);\n",
" var width = Math.abs(x1 - x0);\n",
" var height = Math.abs(y1 - y0);\n",
"\n",
" fig.rubberband_context.clearRect(\n",
" 0, 0, fig.canvas.width, fig.canvas.height);\n",
"\n",
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
" // Updates the figure title.\n",
" fig.header.textContent = msg['label'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
" var cursor = msg['cursor'];\n",
" switch(cursor)\n",
" {\n",
" case 0:\n",
" cursor = 'pointer';\n",
" break;\n",
" case 1:\n",
" cursor = 'default';\n",
" break;\n",
" case 2:\n",
" cursor = 'crosshair';\n",
" break;\n",
" case 3:\n",
" cursor = 'move';\n",
" break;\n",
" }\n",
" fig.rubberband_canvas.style.cursor = cursor;\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_message = function(fig, msg) {\n",
" fig.message.textContent = msg['message'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
" // Request the server to send over a new figure.\n",
" fig.send_draw_message();\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
" fig.image_mode = msg['mode'];\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Called whenever the canvas gets updated.\n",
" this.send_message(\"ack\", {});\n",
"}\n",
"\n",
"// A function to construct a web socket function for onmessage handling.\n",
"// Called in the figure constructor.\n",
"mpl.figure.prototype._make_on_message_function = function(fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
" /* FIXME: We get \"Resource interpreted as Image but\n",
" * transferred with MIME type text/plain:\" errors on\n",
" * Chrome. But how to set the MIME type? It doesn't seem\n",
" * to be part of the websocket stream */\n",
" evt.data.type = \"image/png\";\n",
"\n",
" /* Free the memory for the previous frames */\n",
" if (fig.imageObj.src) {\n",
" (window.URL || window.webkitURL).revokeObjectURL(\n",
" fig.imageObj.src);\n",
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
" evt.data);\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
" fig.imageObj.src = evt.data;\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
"\n",
" var msg = JSON.parse(evt.data);\n",
" var msg_type = msg['type'];\n",
"\n",
" // Call the \"handle_{type}\" callback, which takes\n",
" // the figure and JSON message as its only arguments.\n",
" try {\n",
" var callback = fig[\"handle_\" + msg_type];\n",
" } catch (e) {\n",
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
" return;\n",
" }\n",
"\n",
" if (callback) {\n",
" try {\n",
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
" callback(fig, msg);\n",
" } catch (e) {\n",
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
" }\n",
" }\n",
" };\n",
"}\n",
"\n",
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
"mpl.findpos = function(e) {\n",
" //this section is from http://www.quirksmode.org/js/events_properties.html\n",
" var targ;\n",
" if (!e)\n",
" e = window.event;\n",
" if (e.target)\n",
" targ = e.target;\n",
" else if (e.srcElement)\n",
" targ = e.srcElement;\n",
" if (targ.nodeType == 3) // defeat Safari bug\n",
" targ = targ.parentNode;\n",
"\n",
" // jQuery normalizes the pageX and pageY\n",
" // pageX,Y are the mouse positions relative to the document\n",
" // offset() returns the position of the element relative to the document\n",
" var x = e.pageX - $(targ).offset().left;\n",
" var y = e.pageY - $(targ).offset().top;\n",
"\n",
" return {\"x\": x, \"y\": y};\n",
"};\n",
"\n",
"/*\n",
" * return a copy of an object with only non-object keys\n",
" * we need this to avoid circular references\n",
" * http://stackoverflow.com/a/24161582/3208463\n",
" */\n",
"function simpleKeys (original) {\n",
" return Object.keys(original).reduce(function (obj, key) {\n",
" if (typeof original[key] !== 'object')\n",
" obj[key] = original[key]\n",
" return obj;\n",
" }, {});\n",
"}\n",
"\n",
"mpl.figure.prototype.mouse_event = function(event, name) {\n",
" var canvas_pos = mpl.findpos(event)\n",
"\n",
" if (name === 'button_press')\n",
" {\n",
" this.canvas.focus();\n",
" this.canvas_div.focus();\n",
" }\n",
"\n",
" var x = canvas_pos.x;\n",
" var y = canvas_pos.y;\n",
"\n",
" this.send_message(name, {x: x, y: y, button: event.button,\n",
" step: event.step,\n",
" guiEvent: simpleKeys(event)});\n",
"\n",
" /* This prevents the web browser from automatically changing to\n",
" * the text insertion cursor when the button is pressed. We want\n",
" * to control all of the cursor setting manually through the\n",
" * 'cursor' event from matplotlib */\n",
" event.preventDefault();\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" // Handle any extra behaviour associated with a key event\n",
"}\n",
"\n",
"mpl.figure.prototype.key_event = function(event, name) {\n",
"\n",
" // Prevent repeat events\n",
" if (name == 'key_press')\n",
" {\n",
" if (event.which === this._key)\n",
" return;\n",
" else\n",
" this._key = event.which;\n",
" }\n",
" if (name == 'key_release')\n",
" this._key = null;\n",
"\n",
" var value = '';\n",
" if (event.ctrlKey && event.which != 17)\n",
" value += \"ctrl+\";\n",
" if (event.altKey && event.which != 18)\n",
" value += \"alt+\";\n",
" if (event.shiftKey && event.which != 16)\n",
" value += \"shift+\";\n",
"\n",
" value += 'k';\n",
" value += event.which.toString();\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
" this.send_message(name, {key: value,\n",
" guiEvent: simpleKeys(event)});\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
" if (name == 'download') {\n",
" this.handle_save(this, null);\n",
" } else {\n",
" this.send_message(\"toolbar_button\", {name: name});\n",
" }\n",
"};\n",
"\n",
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
" this.message.textContent = tooltip;\n",
"};\n",
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
"\n",
"mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n",
"\n",
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
" // Create a \"websocket\"-like object which calls the given IPython comm\n",
" // object with the appropriate methods. Currently this is a non binary\n",
" // socket, so there is still some room for performance tuning.\n",
" var ws = {};\n",
"\n",
" ws.close = function() {\n",
" comm.close()\n",
" };\n",
" ws.send = function(m) {\n",
" //console.log('sending', m);\n",
" comm.send(m);\n",
" };\n",
" // Register the callback with on_msg.\n",
" comm.on_msg(function(msg) {\n",
" //console.log('receiving', msg['content']['data'], msg);\n",
" // Pass the mpl event to the overriden (by mpl) onmessage function.\n",
" ws.onmessage(msg['content']['data'])\n",
" });\n",
" return ws;\n",
"}\n",
"\n",
"mpl.mpl_figure_comm = function(comm, msg) {\n",
" // This is the function which gets called when the mpl process\n",
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
"\n",
" var id = msg.content.data.id;\n",
" // Get hold of the div created by the display call when the Comm\n",
" // socket was opened in Python.\n",
" var element = $(\"#\" + id);\n",
" var ws_proxy = comm_websocket_adapter(comm)\n",
"\n",
" function ondownload(figure, format) {\n",
" window.open(figure.imageObj.src);\n",
" }\n",
"\n",
" var fig = new mpl.figure(id, ws_proxy,\n",
" ondownload,\n",
" element.get(0));\n",
"\n",
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
" // web socket which is closed, not our websocket->open comm proxy.\n",
" ws_proxy.onopen();\n",
"\n",
" fig.parent_element = element.get(0);\n",
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
" if (!fig.cell_info) {\n",
" console.error(\"Failed to find cell for figure\", id, fig);\n",
" return;\n",
" }\n",
"\n",
" var output_index = fig.cell_info[2]\n",
" var cell = fig.cell_info[0];\n",
"\n",
"};\n",
"\n",
"mpl.figure.prototype.handle_close = function(fig, msg) {\n",
" fig.root.unbind('remove')\n",
"\n",
" // Update the output cell to use the data from the current canvas.\n",
" fig.push_to_output();\n",
" var dataURL = fig.canvas.toDataURL();\n",
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
" // the notebook keyboard shortcuts fail.\n",
" IPython.keyboard_manager.enable()\n",
" $(fig.parent_element).html('<img src=\"' + dataURL + '\">');\n",
" fig.close_ws(fig, msg);\n",
"}\n",
"\n",
"mpl.figure.prototype.close_ws = function(fig, msg){\n",
" fig.send_message('closing', msg);\n",
" // fig.ws.close()\n",
"}\n",
"\n",
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
" // Turn the data on the canvas into data in the output cell.\n",
" var dataURL = this.canvas.toDataURL();\n",
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Tell IPython that the notebook contents must change.\n",
" IPython.notebook.set_dirty(true);\n",
" this.send_message(\"ack\", {});\n",
" var fig = this;\n",
" // Wait a second, then push the new image to the DOM so\n",
" // that it is saved nicely (might be nice to debounce this).\n",
" setTimeout(function () { fig.push_to_output() }, 1000);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items){\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) { continue; };\n",
"\n",
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" // Add the status bar.\n",
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"\n",
" // Add the close button to the window.\n",
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
" buttongrp.append(button);\n",
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
" titlebar.prepend(buttongrp);\n",
"}\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(el){\n",
" var fig = this\n",
" el.on(\"remove\", function(){\n",
"\tfig.close_ws(fig, {});\n",
" });\n",
"}\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(el){\n",
" // this is important to make the div 'focusable\n",
" el.attr('tabindex', 0)\n",
" // reach out to IPython and tell the keyboard manager to turn it's self\n",
" // off when our div gets focus\n",
"\n",
" // location in version 3\n",
" if (IPython.notebook.keyboard_manager) {\n",
" IPython.notebook.keyboard_manager.register_events(el);\n",
" }\n",
" else {\n",
" // location in version 2\n",
" IPython.keyboard_manager.register_events(el);\n",
" }\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" var manager = IPython.notebook.keyboard_manager;\n",
" if (!manager)\n",
" manager = IPython.keyboard_manager;\n",
"\n",
" // Check for shift+enter\n",
" if (event.shiftKey && event.which == 13) {\n",
" this.canvas_div.blur();\n",
" event.shiftKey = false;\n",
" // Send a \"J\" for go to next cell\n",
" event.which = 74;\n",
" event.keyCode = 74;\n",
" manager.command_mode();\n",
" manager.handle_keydown(event);\n",
" }\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" fig.ondownload(fig, null);\n",
"}\n",
"\n",
"\n",
"mpl.find_output_cell = function(html_output) {\n",
" // Return the cell and output element which can be found *uniquely* in the notebook.\n",
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
" // IPython event is triggered only after the cells have been serialised, which for\n",
" // our purposes (turning an active figure into a static one), is too late.\n",
" var cells = IPython.notebook.get_cells();\n",
" var ncells = cells.length;\n",
" for (var i=0; i<ncells; i++) {\n",
" var cell = cells[i];\n",
" if (cell.cell_type === 'code'){\n",
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
" var data = cell.output_area.outputs[j];\n",
" if (data.data) {\n",
" // IPython >= 3 moved mimebundle to data attribute of output\n",
" data = data.data;\n",
" }\n",
" if (data['text/html'] == html_output) {\n",
" return [cell, data, j];\n",
" }\n",
" }\n",
" }\n",
" }\n",
"}\n",
"\n",
"// Register the function which deals with the matplotlib target/channel.\n",
"// The kernel may be null if the page has been refreshed.\n",
"if (IPython.notebook.kernel != null) {\n",
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
"}\n"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<img src=\"data:image/png;base64,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\">"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig,ax = plt.subplots(1,1)\n",
"def plot_interactive2():\n",
" def pls2(f):\n",
" plotsin(f, fig, ax)\n",
" ww = widgets.FloatSlider(description='frequency', min=1, max=100)\n",
" interact(pls2, f=ww)"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
"plot_interactive2()"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.5.1"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment