Skip to content

Instantly share code, notes, and snippets.

@enakai00
Created June 18, 2016 12:33
Show Gist options
  • Save enakai00/43701ac5071fec85f3524fd4bbcee732 to your computer and use it in GitHub Desktop.
Save enakai00/43701ac5071fec85f3524fd4bbcee732 to your computer and use it in GitHub Desktop.
Math animation
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import numpy as np\n",
"import matplotlib.pyplot as plt\n",
"import matplotlib.animation as animation"
]
},
{
"cell_type": "code",
"execution_count": 4,
"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\", \"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(\"<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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HyxenMs//jFEAExqDAJgNvcOlT2jFcjPhyZNoF8/uOiiXHr1EgCTK1wAzOguoMJlswL/8z9gDx59/DEUFAiAbm1BAMzmHqKyZ6wChYXQvLlz2WmfPpCbKwAKgBnb3FUwKbCjAtOnw2WXOSc/dt1VACyufcgDVM+RAhmmgHl/J50EnTrBLbc4hZMH6F7JAmCGNX4VRwq88Qacdx588QXUtn0UAmCxjUIAVH/xVODOO+/kySefxHbuH3vssYwaNYo//elPxcY755xzWLRoEZs2bWKXXXbhpJNOYujQoRx88MG/x3nppZfo378/a9as4cADD+Tuu+/mPOu1wA8//MBNN93E3Llz+fHHH6lbty4XXnghAwYMoHr16jGbv//97zz33HNUquQ04cLCQjZv3sy1117L/fffH/s3P/koytCDDz7I9ddfz+23386gQYM8NSnPBmecASeeCAMHbs+lPEB5gOW5zZKXl/d75y5PGR02bBgjR45kxowZNG7cmIEDB/Lss8/y4YcfsqtNLrmEZcuWcdhhh8WOTm3YsIGrr746Brr58+fHrBcsWMCpp57KCy+8QKdOnZgyZQqXXHIJb731Fs2bN+ezzz5j4sSJdO3alYMOOohPP/00BsfTTz+dESNGFPvNo48+mnfffZdj7MZPwCsfRQmtXr2av/zlL9SqVYuzzz67QgNwwQIwANrc3957C4BefUkeoJdCIX/+yCOP8Oijj8Y6/m677cYZZ5wR80z2jrdKA8nrr79OmzZteOqpp9hzzz354IMPYsC45ZZbYsAxj+b444/n4YcfjoHAgnlO9957bwwKdkNHy5YtMe/FvKhUBPPa+vbtSx9bSgTy8/OpX79+DEQXX3yx5yfXr18fi2vxJkyYELPv0aNHrJwvJ9zL1Llz55g2TzzxhGuaVsaxY8fy3nvvuf7cILt06VLetgcvXIJbPsysoKCAVq1aceutt8bq5+STT67QALR5vyOOsJMfO4ogD1AeoGdnjdJg8uTJNG3alEMOOYQvv/ySCy64IDYEHD9+fOwzBsB77rkHG17acM86Ys2aNWNAbNiwYQx65mHdcccdTJ06lffffx+7lug///kP9erVi6X9008/cfnll8eGiUXelVsZDK42VLRhYlEo+v/2X4O1DTGTgw1599hjjxhUDMRFoW3btrHvDx8+vFjJDCjmORrEW7duzWuv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\">"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"%matplotlib nbagg\n",
"\n",
"def f(x):\n",
" y = x ** 2\n",
" return y\n",
"\n",
"fig = plt.figure(figsize=(4,4))\n",
"images = []\n",
"step = 0.5\n",
"for _ in range(12):\n",
" subplot = fig.add_subplot(1,1,1)\n",
" subplot.set_xlim(0,1.1)\n",
" subplot.set_ylim(0)\n",
" linex = np.linspace(0,1,100)\n",
" subimages = []\n",
"\n",
" im, = subplot.plot(linex, f(linex), color='blue')\n",
" subimages.append(im)\n",
"\n",
" area = 0\n",
" for x0 in np.arange(0,1,step):\n",
" rect = plt.Rectangle((x0,0),step,f(x0),alpha=0.5)\n",
" im = subplot.add_patch(rect)\n",
" subimages.append(im)\n",
" area += step * f(x0)\n",
" im = subplot.text(0.2, 0.8, ('area = %f' % area))\n",
" subimages.append(im)\n",
" images.append(subimages)\n",
" if step > 0.002:\n",
" step *= 0.5\n",
"ani = animation.ArtistAnimation(fig, images, interval=1000, repeat_delay=1000)\n",
"ani.save('integral.gif', writer='imagemagick', fps=1);\n",
"plt.show()"
]
},
{
"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\", \"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(\"<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": [
"%matplotlib nbagg\n",
"\n",
"x0 = 1.0\n",
"\n",
"def f(x):\n",
" return x**2\n",
"\n",
"fig = plt.figure(figsize=(4,4))\n",
"\n",
"images = []\n",
"for i, dx in enumerate(\n",
" np.hstack((np.arange(1.5,0,-0.02), np.array([10**(-10)]*50)))):\n",
" subplot = fig.add_subplot(1,1,1)\n",
" subplot.set_xlim(0,3)\n",
" subplot.set_ylim(0,10)\n",
" slope = (f(x0+dx)-f(x0)) / dx\n",
" linex = np.linspace(0,3,100)\n",
" image0 = subplot.text(0.5, 8, ('slope = %f' % slope))\n",
" image1, = subplot.plot(linex, f(linex), color='blue')\n",
" image2 = subplot.scatter([x0,x0+dx],[f(x0),f(x0+dx)])\n",
"\n",
" def g(x):\n",
" return f(x0) + slope * (x-x0)\n",
" \n",
" image3, = subplot.plot([0,3],[g(0),g(3)], linewidth=1, color='red')\n",
" images.append([image0, image1, image2, image3])\n",
"\n",
"ani = animation.ArtistAnimation(fig, images, interval=20, repeat_delay=80)\n",
"ani.save('differencial.gif', writer='imagemagick', fps=20);\n",
"plt.show()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 2",
"language": "python",
"name": "python2"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 2
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
"version": "2.7.5"
}
},
"nbformat": 4,
"nbformat_minor": 0
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment