{ "cells": [ { "cell_type": "code", "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2017-11-27T22:05:53.048619Z", "start_time": "2017-11-27T22:05:48.068618Z" } }, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\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 = $('
');\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", " if (mpl.ratio != 1) {\n", " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", " }\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", " '');\n", " var titletext = $(\n", " '');\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 = $('');\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 = $('');\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 backingStore = this.context.backingStorePixelRatio ||\n", "\tthis.context.webkitBackingStorePixelRatio ||\n", "\tthis.context.mozBackingStorePixelRatio ||\n", "\tthis.context.msBackingStorePixelRatio ||\n", "\tthis.context.oBackingStorePixelRatio ||\n", "\tthis.context.backingStorePixelRatio || 1;\n", "\n", " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", "\n", " var rubberband = $('');\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 * mpl.ratio);\n", " canvas.attr('height', height * mpl.ratio);\n", " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\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 = $('')\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 = $('');\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 = $('');\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 = $('');\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 = $('');\n", "\n", " var fmt_picker = $('');\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", " '', {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 = $('');\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'] / mpl.ratio;\n", " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n", " var x1 = msg['x1'] / mpl.ratio;\n", " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\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 * mpl.ratio;\n", " var y = canvas_pos.y * mpl.ratio;\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\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\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(\"\");\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", " var width = fig.canvas.width/mpl.ratio\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('');\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 width = this.canvas.width/mpl.ratio\n", " var dataURL = this.canvas.toDataURL();\n", " this.cell_info[1]['text/html'] = '';\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 = $('')\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 = $('');\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 = $('');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "\n", " // Add the close button to the window.\n", " var buttongrp = $('');\n", " var 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", " // select the cell after this one\n", " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", " IPython.notebook.select(index + 1);\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; iFailed to display Jupyter Widget of type interactive
.
\n", " If you're reading this message in the Jupyter Notebook or JupyterLab Notebook, it may mean\n", " that the widgets JavaScript is still loading. If this message persists, it\n", " likely means that the widgets JavaScript library is either not installed or\n", " not enabled. See the Jupyter\n", " Widgets Documentation for setup instructions.\n", "
\n", "\n", " If you're reading this message in another frontend (for example, a static\n", " rendering on GitHub or NBViewer),\n", " it may mean that your frontend doesn't currently support widgets.\n", "
\n" ], "text/plain": [ "interactive(children=(FloatSlider(value=0.0, description='x_0', max=3.0, min=-3.0), FloatSlider(value=0.0, description='y_0', max=3.0, min=-3.0), FloatSlider(value=2.5, description='a', max=5.0), Output(layout=Layout(height='350px'))), _dom_classes=('widget-interact',))" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "image/png": "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\nBjcREZGE/H9lqQiYJQyHSQAAAABJRU5ErkJggg==\n", "text/plain": [ "