summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjaseg <git@jaseg.net>2018-05-05 19:34:01 +0200
committerjaseg <git@jaseg.net>2018-05-05 19:34:01 +0200
commitea10cdd1ed836191e7ad4adca65594527b0b922e (patch)
treef2d263b39d30a23faa313c3fb85a1c6224a35a4d
parente3bb458580588aec8eb294db96e4f7e8f56e62ae (diff)
downloadolsndot-ea10cdd1ed836191e7ad4adca65594527b0b922e.tar.gz
olsndot-ea10cdd1ed836191e7ad4adca65594527b0b922e.tar.bz2
olsndot-ea10cdd1ed836191e7ad4adca65594527b0b922e.zip
Nice spectrum plot looking as it should, including photodiode response compensation.
-rw-r--r--firmware/Spectrum Measurement.ipynb4928
-rw-r--r--firmware/measure_spectrum.py19
-rw-r--r--firmware/spectra.sqlite3bin208896 -> 294912 bytes
-rw-r--r--firmware/spectrum_progress.py10
-rw-r--r--firmware/stepper_test.py9
5 files changed, 4945 insertions, 21 deletions
diff --git a/firmware/Spectrum Measurement.ipynb b/firmware/Spectrum Measurement.ipynb
index 57d4339..5d76e1d 100644
--- a/firmware/Spectrum Measurement.ipynb
+++ b/firmware/Spectrum Measurement.ipynb
@@ -12,6 +12,7 @@
"import time\n",
"from IPython import display\n",
"from datetime import datetime\n",
+ "import scipy.interpolate as inter\n",
"\n",
"import numpy as np\n",
"from matplotlib import pyplot as plt\n",
@@ -1690,14 +1691,12 @@
},
{
"cell_type": "code",
- "execution_count": 39,
+ "execution_count": 72,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
- "import scipy.interpolate as inter\n",
- "\n",
"def live_plot_rgb_splines(id_r, id_g, id_b, max_stdev=0.05, spline_s=1, interval=1, live=True):\n",
" fig, ax = plt.subplots(1, 1)\n",
" fig.suptitle('Runs {}, {}, {} at {:%y-%m-%d %H:%M:%S}'.format(id_r, id_g, id_b, datetime.now()))\n",
@@ -1705,15 +1704,18 @@
" while True:\n",
" ax.clear()\n",
" colors = [\n",
- " ((1,0,0), (1,0.5,0.5)),\n",
- " ((0,1,0), (0.5,1,0.5)),\n",
- " ((0,0,1), (0.5,0.5,1))\n",
+ " ((1,0,0), (1,0.8,0.8)),\n",
+ " ((0,1,0), (0.8,1,0.8)),\n",
+ " ((0,0,1), (0.8,0.8,1))\n",
" ]\n",
" for run_id, (color_dark, color_bright) in zip([id_r, id_g, id_b], colors):\n",
" steps, values, stdev = load_run_zero_cal(run_id, max_stdev)\n",
- " spline = inter.UnivariateSpline(steps, values, s=spline_s)\n",
" ax.errorbar(steps, values, yerr=stdev, color=color_bright)\n",
- " ax.plot(steps, spline(steps), color=color_dark)\n",
+ " try:\n",
+ " spline = inter.UnivariateSpline(steps, values, s=spline_s)\n",
+ " ax.plot(steps, spline(steps), color=color_dark)\n",
+ " except:\n",
+ " pass\n",
" fig.canvas.draw()\n",
" if not live:\n",
" break\n",
@@ -2517,6 +2519,4916 @@
"* Decrease amplification to avoid clipping. Maybe change amplification midway for green channel. Currenlty set to 5GOhm using 10M transimp feedback R with 1:10 T feedback and ~1:50 gain voltage amp stage. Maybe go back to plain transimp amp with 10M gain, for a total gain of 500M\n",
"* Decrease VGND bias to allow for more headroom"
]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 96,
+ "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": [
+ "live_plot_rgb_splines(42, 43, 40, spline_s=0.01, max_stdev=1.0, live=False)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 104,
+ "metadata": {
+ "collapsed": false,
+ "scrolled": 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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w0THbH4c4zVFNHx2EF225knR9x8ZvNuI9qRFDo2w42SfJ1qvyfpMEBERNflOWgbAbUXXWzPHJe0oImNFe8yWi64TuFSc9wDuJiKTRU//louO27IGgkTL+GfR2cZljWWaJ3p6sI1lm+tF5LeI+2KJ1gt2f+P9ZaKnG/tZHmsvGkpOdfg3RKIvA2Nycgr4PtFgWia6LuGt0jwAdhYdg7ZJdGzniVFeZ6hoOKlv/DFvm6F5W9FlVZaI7reVokMEurR4peZ6ivZAVjaW8+GIx/8nevp6i+j4xzHS/NiJ5jLR43Kr6CQP6ynRvUWDcKmEjzEnk0CWSfj9mz/fRWxjLjmzi9grFB1SEE3kPndSryNE5MsYr9mazwQREVHWe080MKTS2eJsUgARERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERFRFnhERH4XkVIRWS8iX4vIkXGes5OIjBGRzSJSIiLviUiXFJaRiIiIiJLoAAmHt7YicpeIrBWRbWI850sR+UZEdhaRXURkkoh8msIyEhEREVGKtBeRO0WkXkS6RtlmbxFpEJGelvuOaLxvz5SWjoiIiIiS5nzR07kNImKIyHMxtr1IRKps7q8WkX7JLxoRERERpdJOInKHiFwWY5trRGSNzf1rRWSAzf3biEh3EenMH/7whz/84Q9/Muqnu8QeEkZZZBvRCSGHR3n8IhHZanN/tB7A7iIC/vCHP/zhD3/4k5E/3YUCoa2IVIrIpVEe31t0jGDkGMB6sR8D2FlEsGLFCpSVlWXdz+DBgz0vA98b31tQ3lu2vz++t8z8ydb3tmLFCjMAdk5exCA/uV1Edm28/UcRGSW6tEu3GM/5XERyRSeK/EFEJorIhCjbdhYRlJWVIRvl5OR4XYSU4XvLTNn83oDsfn98b5kpW99bWVkZA2CW+1x0TF+FiKwSXc6ll+XxvRofO8ly304i8r7oqeLNIvKuRD9AGAAzFN9bZsrm9wZk9/vje8tM2freGADJrawOgLm5uV4XIWX43jJTNr83ILvfH99bZsrW98YASG5ldQAkIiLKRgyA5BYDIBERUYZhACS3GACJiIgyDAMgucUA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\">"
+ ],
+ "text/plain": [
+ "<IPython.core.display.HTML object>"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "live_plot_rgb_splines(45, 46, 44, spline_s=0.08, max_stdev=1.0, live=False)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 169,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "def plot_rgb_foo(data_rgb, ids_rgb, spline_s=1):\n",
+ " fig, ax = plt.subplots(1, 1)\n",
+ " fig.suptitle('Runs {}(R), {}(G), {}(B) at {:%y-%m-%d %H:%M:%S}'.format(*ids_rgb, datetime.now()))\n",
+ "\n",
+ " colors = [\n",
+ " ((1,0,0), (1,0.8,0.8)),\n",
+ " ((0,1,0), (0.8,1,0.8)),\n",
+ " ((0,0,1), (0.8,0.8,1))\n",
+ " ]\n",
+ " for (steps, values, stdev), (color_dark, color_bright) in zip(data_rgb, colors):\n",
+ " ax.errorbar(steps, values, yerr=stdev, color=color_bright)\n",
+ " \n",
+ " spline = inter.UnivariateSpline(steps, values, s=spline_s)\n",
+ " ax.plot(steps, spline(steps), color=color_dark)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 171,
+ "metadata": {
+ "collapsed": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Poly for run 45: 2\n",
+ "2.282e-06 x - 0.001576 x + 0.4019\n",
+ "Poly for run 46: 2\n",
+ "6.886e-07 x - 0.0005388 x + 0.1561\n",
+ "Poly for run 44: 2\n",
+ "1.258e-06 x - 0.001514 x + 0.5252\n"
+ ]
+ },
+ {
+ "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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9I8tQ7/Q+zCHt2j1+oZone4M/f9L0T8CzSZL7WV1K+Gfp4a8fyIiyhDdJf6VQHpK/Uuuh4uOlUuFvqKNWbwOEu1h3Mf0WCvRwB7P+2+ohpR7oNTeKU5ERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERk4/9EZJWIFIvIVhH5n4gcH+U17UVkjIgUiUihiHwkIu2SWEYiIiIiSqAjpDa8NRGRB0Rks4jsFeE1k0Rkioh0EJF9ROQbEZmQxDISERERUZI0F5H7RaRaRDrabHOwiNSIyLGmx34feqxLUktHRERERAlzkejl3BoRCYrI8xG2HSAi5RaP7xaRSxJfNCIiIiJKpvYicp+IXBFhm7+IyCaLxzeLyJ8tHt9LRDqLSFt+8Ytf/OIXv/jlq6/OEnlIGKWRvURvCDnO5vkBIrLL4nG7HsDOIgJ+8Ytf/OIXv/jly6/OQhmhiYiUicjlNs8fLDpGMHwMYLVYjwFsKyJYt24dduzYkXZfWVlZrpeB743vLVPeW7q/P743f36l63tbt26dEQDbJi5ikJfcKyL7h77fT0RGik7t0inCayaKSI7ojSL7isjXIjLeZtu2IoIdO3YgHWVnZ7tdhKThe/OndH5vQHq/P743f0rX97Zjxw4GwDQ3UXRMX6mIbBCdzqWn6fmuoef6mh5rLyKjRS8VF4nIh2J/gjAA+hTfmz+l83sD0vv98b35U7q+NwZAciqtA2BOTo7bRUgavjd/Suf3BqT3++N786d0fW8MgORUWgdAIiKidMQASE4xABIREfkMAyA5xQBIRETkMwyA5BQDIBERkc8wAJJTDIBEREQ+wwBITjEAEhER+QwDIDnFAEhEROQzDIDkFAMgERGRzzAAklMMgERERD7DAEhOMQASERH5DAMgOcUASERE5DMMgOQUAyAREZHPMACSUwyAREREPsMASE4xABIREfkMAyA5xQBIRETkMwyA5BQDIBERkc8wAJJTDIBEREQ+wwBITjEAEhER+QwDIDnFAEhEROQzDIDkFAMgERGRzzAAklMMgERERD7DAEhOMQASERH5DAMgOcUASERE5DMMgOQUAyAREZHP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\">"
+ ],
+ "text/plain": [
+ "<IPython.core.display.HTML object>"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "ids = (45, 46, 44)\n",
+ "bands = [(260,410), (150,330), (100,260)]\n",
+ "poly_degree = 2\n",
+ "max_stdev = 1.0\n",
+ "remove_thresh = 0.05\n",
+ "\n",
+ "data_rgb = []\n",
+ "for run_id, (l, r) in zip(ids, bands):\n",
+ " steps, values, stdev = load_run_zero_cal(run_id, max_stdev)\n",
+ " \n",
+ " idxs = (np.abs(stdev[1:-1] - stdev[0:-2]) < remove_thresh) |\\\n",
+ " (np.abs(stdev[1:-1] - stdev[2:]) < remove_thresh)\n",
+ " idxs = np.hstack([np.array([True]), idxs, np.array([True])])\n",
+ " steps, values, stdev = steps[idxs], values[idxs], stdev[idxs]\n",
+ " \n",
+ " idxs = (steps < l) | (steps > r)\n",
+ " poly = np.poly1d(np.polyfit(steps[idxs], values[idxs], poly_degree))\n",
+ " print('Poly for run {}: {}'.format(run_id, str(poly).strip()))\n",
+ " \n",
+ " values -= poly(steps)\n",
+ " data_rgb.append((steps, values, stdev))\n",
+ "\n",
+ "plot_rgb_foo(data_rgb, ids, spline_s=0.05)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 238,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "def plot_rgb_bar(data_rgb, ids_rgb, spline_s=1):\n",
+ " fig, ax = plt.subplots(1, 1)\n",
+ " fig.suptitle('Runs {}(R), {}(G), {}(B) at {:%y-%m-%d %H:%M:%S}'.format(*ids_rgb, datetime.now()))\n",
+ "\n",
+ " colors = [\n",
+ " ((1,0,0), (1,0.8,0.8)),\n",
+ " ((0,1,0), (0.8,1,0.8)),\n",
+ " ((0,0,1), (0.8,0.8,1))\n",
+ " ]\n",
+ " for (steps, values, stdev), (color_dark, color_bright) in zip(data_rgb, colors):\n",
+ " ax.errorbar(steps, values, yerr=stdev, color=color_bright)\n",
+ " \n",
+ " spline = inter.UnivariateSpline(steps, values, s=spline_s)\n",
+ " ax.plot(steps, spline(steps), color=color_dark)\n",
+ " \n",
+ " ax.set_xlim([380, 720])\n",
+ " ax.set_xlabel('$\\lambda [nm]$')\n",
+ " ax.set_ylabel('normalized amplitude')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 226,
+ "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"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "(380, 720)"
+ ]
+ },
+ "execution_count": 226,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "λ_sfh2701 = [ 300, 400, 500, 600, 700, 800, 900, 1000, 1100]\n",
+ "S_sfh2701 = [0.00, 0.20, 0.57, 0.76, 0.90, 1.00, 0.85, 0.37, 0.00]\n",
+ "Λ_sfh2701 = np.poly1d(np.polyfit(λ_sfh2701, S_sfh2701, 5))\n",
+ "r = np.arange(380, 720)\n",
+ "fig, ax = plt.subplots(1, 1)\n",
+ "ax.plot(r, Λ_sfh2701(r))\n",
+ "ax.set_xlim([380, 720])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 257,
+ "metadata": {
+ "collapsed": false,
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Poly for run 45:\n",
+ " 2\n",
+ "2.282e-06 x - 0.001576 x + 0.4019\n",
+ "Poly for run 46:\n",
+ " 2\n",
+ "6.886e-07 x - 0.0005388 x + 0.1561\n",
+ "Poly for run 44:\n",
+ " 2\n",
+ "1.258e-06 x - 0.001514 x + 0.5252\n",
+ "[297, 228, 117] [339, 270, 210]\n",
+ "[330, 228, 159]\n"
+ ]
+ },
+ {
+ "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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//1Sly7+sY+77ur37Z12klq18pcv3HCD/z55/XXp1VelggI/9uCCBWXvK8uXS7NmZX7wuWwZB5NHehGAyGST9wCuXl3yn+s///F3mE6Z4pfz8vxUmUMPlTbfXLrttspvM326v26o2L/+Jf3sZ76nccAA34PwyCP+MXGl5zJzpj/NVK+e/8EotnKlH6y2Wzdp662lefPKrm/KFKl/f38X44aaPVu66aaNexrr88+lk06Sbr5Z+v57X1ZYKD3zjL97snZtP5bak096TD/0kNSsme8l6d3b/zDWqiUdeKA0eLC/uH7BAo/qLbaQ+vThDx1y05w50qRJ0htvSH/9q4fe7bf7YWXatPE43H13f6Zh++39AWKjRv6Ap2FDv1x8+vnP/WPq9trLP+2mePl220m/+pV04YXS2WdLxx/vl7t3l3r18t9bl1wi9eghtW8vNW3qB7g+7DDp//7P53LiiX79CSf4IZV++1t/7fNvfuO36d7d3wDTu7ePdeGFftuOHX1OXbv6ui691K8//3y/7Smn+Nd17+4P5Irnc9VVfpujj5b23lvaf3+/zemn+9d16+Zz3Xlnv+7Xv/bbn3aaz7tNG/++deggHXusdPLJvs177OHfj5Yt/ffJMcf4PLt39yDv2NHnevzxvl1du/p6mjWTmjf3rz/oIKlzZ1/vHnv4z2jffX1OvXr596pLF9850Latz+23v5Wuv14691ypUyf/Hrdq5XM980z/uXTr5rffYQef/yGH+Peka1f/+3HAAT7nzp19vkcf7ef32Uf65S/9+9Spk3/NkUf6bVu39u9Dp07+PbjgAv9+77efz2H33X29F14o9etX8v1r397n0qaNb2PxOK1a+fJDD/VxTj3V57fPPiUPYIrnsb43PCaNAERlMr0G8Fur5DWAeXl5OuaYfG22Wb62375Axx3nd/7ST8++8II/PZvpqdY1azwW27f3CKrMK6/4naxYYaH/sh892j+Efvp0D7+dd5Yef7zkdr17+y+Qe+6RWrSQfvjBlw8Z4n8MVq4s+SVebOpU/wPSsaOvY9gwv92SJf406u9/7welLt7zVljolxs29D8+bdr43rdi8+f7L7n/+z//+jVr/GtGjPBtv+gi/wVcv77f7uijpW23lf78Z2nxYn9qfMcd/fqddvJP6yj9vZw1y78Pp55a8setWzf/ngBpsWSJ7zGfNMn/7y9Y4C+BmD9fev996amnpOeekz780K9btMj3HP75z/4yiSFD/BmE0aOlkSN9L/uVV/qhp+6+27/27bell17yB2K33+4PWv/wB78vDx/uY1x+uYfa1Vf7bUaO9K+/6SZ/sHr11f4148b5A71Ro/x33+WX+/WDB/tthw71r/vTn3yMW2/16/v0kQYNku67Txo/3rdr5EgfY8gQPz9+vIfzU0/53AYN8u158EHpxRf9JTOPPeZvvBs61Lfn5Zf9+/TGG/6A8957/fsxcqQHyyOP+Pfqj3/07Ro1ytfz1lt+evll/907Zoz09NMe7K+/XrKNt97q2z1mjM9hwgQfq39/D71Bg/y6t97yPbujR/v2XHedfw9eeMEfmL/8ss/lvvt83Icf9u186ilp7Fhfdv/9vnz8eP/bMWGCf83Ikb4NTz7p8yso8HXecYf/Xr/rLh/n7bf9ezRypP+8Lrus5Pv33HM+/5de8q+fONHnO2mSz3HsWN+uW2/1uTz7rPTmm379+PH+c582rervHwUFBcrPz1d+fr7y8vIIQGR0hZn9x/zQL1ua2U1mNscqeRfwrFmL1aSJ30EnTfLDtFx+uT9lW2zZMv8M39JRVOyzzzzgig/wXJmHHvJHjqV16eLjDhxYsuyuu/zRYGGhH+Zkyy09kAoLPaxOP1369FNf/ve/+9fMn+97CJ580uez7bYlT0dPmuSP+Js08T1tLVv6L6t27TzIzjnHH0U3bep3/uKPVWvUyH+R3HGHn+/Rw+fZtKnHXMeO/u8bb5TM/f33/ftw6aUV99qtWuVvgPnpp3Xfydes8b2eNfl1jQCATcceQKzLdWb2tZkts/UcB/DCCxera9f1B0fXrplfnzd2rD99e9550rXXVv71t9ziTyGU1r+/P8VQ+qOmli71p3QnT/bd/ZdfXnLd11973DVv7o/sSxs3ziOveXN/JFja6tX+KHLWrJJlhYXSBx94rF18ccVge/xxf9q5XTuPyNJjjR/vT3lwKBYAQFUjABGqoZlpiy0Wb9CxvO6804OsvH79PKIuvNDf1FCZvn09+Er7/nvpv/+teNuBA/31Fo0ald0TKflTAZ06Vfx80sJCD8z+/ePtPVu61PfIAQBQXRCACNXQzHTVVRv2SSCffeZvSigfXp06+Ws9Lr5Y+t3vKv/6k0/2p1M3xLx5fsiYW27ZsNsDAJAWBCBCNTQzffvthgVgYaG/gaH0seiK3wAyfbrvBSz/tGxpHTv607Qbatq09X+2MAAAaUMAItRGfxbwRRf5U77Fit+MsXq1L8/Pr/xrd9ml7GFcAADAxiMAEWqjA3DSJD9UytSpfnnMGH8DiORv1ujbN/PXFRb608czZgT+rwcAIOUIQITa6ACU/PAq227rrwns29ePeyf5oVMqO1j0Dz/4se02clUAAKAcAhChNikAJT/gZ7NmfgT1hx7yZQMH+lPEmXz2mR9ShWPbAQAQhgBEqE0OwMJC3/NnVvJpFYMG+UfxZDJpkh/vDwAAhCEAEWqTA1Dyj2h65ZWSvXrXXeefBZnJ2LH++YoAACAMAYhQQQFY3g03+EesZXL77f45ugAAIAwBiFBRA/CWW/xzejO57LKyh48BAACbhgBEqKgBePvt0qmnZr7u1FOl226LshoAAFKNAESoqAE4bJh00kmZr+vc2Y8ZCAAAwhCACBU1AO+6SzrhhMzX7bab9OqrUVYDAECqEYAIFTUAR4yQevTIfF39+v6xcQAAIAwBiFBRA/C++6Sjj664fMkSP17g999HWQ0AAKlGACJU1AAcNUrq1q3i8jlzPAD5FBAAAMIRgAgVNQAffFA6/PCKy7/6SqpVK8oqAABIPQIQoaIG4JgxUpcuFZd/+aVUp06UVQAAkHoEIEJFDcBx46ROnSounzFDqlcvyioAAEg9AhChogbgY49JHTpUXP7JJ1LDhlFWAQBA6hGACBU1AJ96SjrggIrLp02TttkmyioAAEg9AhChogbgs89K++5bcfnUqdJ220VZBQAAqUcAIlTUAJwwQWrXruLy996TmjaNsgoAAFKPAESoqAH40kvSnntWXP7WW1KLFlFWAQBA6hGACBU1ACdOlFq3rrj8zTelnXeOsgoAAFKPAESoqAE4aZK0224Vl7/2WublAABg4xGACBU1ACdPllq2rLj8lVcy7xkEAAAbjwBEqKgB+Le/STvuWHF5Za8NBAAAG48ARKioAfj221KzZhWXT5ggtW8fZRUAAKQeAYhQUQPw73+Xtt++4vJnn5X22y/KKgAASD0CEKGiBuAHH0jbbltx+ZNPSgcdFGUVAACkHgGIUFEDcNo0aeutKy5/9FHpkEOirAIAgNQjABEqagB+8onUoEHF5WPHSp07R1kFAACpRwAiVNQAnDFD2nLLissfekg6/PAoqwAAIPUIQISKGoBffinVqVNx+QMPSF27RlkFAACpRwAiVNQAnDlTqlWr4vL775eOPjrKKgAASD0CEKGiBuCsWZKZVFhYdvk990g9ekRZBQAAqUcAIlTUAJw71wNwzZqyy++6S+rZM8oqAABIPQIQoaIG4DffeACuXFl2+bBh0sknR1kFAACpRwAiVNQAXLDAA3D58rLLb7tNOu20KKsAACD1CECEihqAP/zgAbhkSdnlN98s9e4dZRUAAKQeAYhQUQNwyRIPwB9+KLt8yBDp7LOjrAIAgNQjABEqagAuX+4BuGBB2eWDB0vnnx9lFQAApB4BiFBRA3DlSg/Ab74pu/z3v5cuuijKKgAASD0CEKGiBuCaNR6Ac+eWXX7VVVJeXpRVAACQegQgQkUNwMJCD8BZs8ouv/xyqW/fKKsAACD1CECEihqAkn8U3MyZZZf16yf17x9tFQAApBoBiFDRA7BOHemLL8ouu/RSacCAaKsAACDVCECEih6AW24pzZhRdlmfPtLAgdFWAQBAqhGACBU9ABs0kD75pOyyCy6QBg2KtgoAAFKNAESo6AG49dbStGlll517rnT99dFWAQBAqhGACBU9ALfdVvrgg7LLzjxTuummaKsAACDVCECEih6A228v/f3vZZf16iXdemu0VQAAkGoEIEJFD8BmzaS33y677JRTpKFDo60CAIBUIwARKnoA7rij9Le/lV124onS8OHRVgEAQKoRgAgVPQBbtpQmTy677LjjpLvvjrYKAABSjQBEqOgBuNtu0qRJZZcdc4x0333RVgEAQKoRgAgVPQBbt5YmTiy7rHt3adSoaKsAACDVCECEih6Ae+4pvfRS2WVHHCGNHh1tFQAApBoBiFDRA7BdO2nChLLLunSRxoyJtgoAAFKNAESo6AG4777Ss8+WXdaxo/TII9FWAQBAqhGACBU9AA84QHrqqbLLOnSQnngi2ioAAEg1AhChogdghw7SY4+VXbb//tLTT0dbBQAAqUYAIlT0AOzUSRo3ruyyvfeWnnsu2ioAAEg1AhChogdgly7SX/5Sdtlee0kvvhhtFQAApBoBiFDRA/CII6QHHyy7bI89Kh4bEAAAbBoCEKGiB2C3bhUP+tyqVcVPBwEAAJuGAER5Xcys0MyWFJ2Wmtnsddw+egAefXTFj33L9PnAAABg0xCAKK+Lma01s8028PbRA7BHD2nEiLLLdtxRmjIl2ioAAEg1AhDlFQdgrQ28ffQAPOEE6a67yi5r1kx6551oqwAAINUIQJRXHICzzOwbM3vVzDqv4/bRA/Ckk6Rhw8oua9JEev/9aKsAACDVCMD0GG3+2r61Rf+WP71edLvtzWwvM9vczOqb2eVm9pOZtatk3OgBeOqp0u23l132859LH30UbRUAAKQaAZge9cys8TpODdbxtW+Y2Y2VXBc9AE8/XbrllrLLGjWSpk+PtgoAAFKNAMSGeM3MbqrkuoZmpry8POXn5ys/P18FBQVB/ynPPFO64Yayy+rXlz77LGhYAABSraCg4H9/q/Py8ghAlNHNzHY2fxfwlmbWz/wp4H0ruX30PYDnnitdd13ZZXXrSl98EW0VAACkGnsAUd415m8AWWZm8833/nVZx+2jB+AFF0iDBpVdVru2NHNmtFUAAJBqBCBCRQ/Aiy6SBg4suVxYKJlJs2ZFWwUAAKlGACJU9ADMy5MGDCi5vGaNB+DcudFWAQBAqhGACBU9APv2lfr3L7m8YoUH4LffRlsFAACpRgAiVPQAzM+X+vUrubx8uQfgwoXRVgEAQKoRgAgVPQCvvFK69NLS/0k9ABctirYKAABSjQBEqOgB+LvfSX36lFxeuNADcNmyaKsAACDVCECEih6A11wjXXhhyeX58z0AV6yItgoAAFKNAESo6AF47bXSeeeVXJ43zwNw9epoqwAAINUIQISKHoBDhkhnnVVyefZsD8DCwmirAAAg1QhAhIoegDffLJ1xRsnlmTOlWrWiDQ8AQOoRgAgVPQBvu0067bSSy19+6Z8FDAAA4iAAESp6AA4dKp18csnlGTOkevWiDQ8AQOoRgAgVPQCHD5d69iy5PH261LBhtOEBAEg9AhChogfg3XdLxx1XcnnaNKlx42jDAwCQegQgQkUPwHvvlY45puTy1KnSdttFGx4AgNQjABEqegD+6U9S9+4ll999V2raNNrwAACkHgGIUNED8M9/lo48suTylClSixbRhgcAIPUIQISKHoAPPST96lcll998U2rZMtrwAACkHgGIUNED8OGHpUMPLbn82mvSbrtFGx4AgNQjABEqegA++qh08MEllydOlFq3jjY8AACpRwAiVPQAfOIJ6cADSy6/9JLUtm204QEASD0CEKGiB+Azz0j77VdyecIEqX37aMMDAJB6BCBCRQ/A554rG3zlgxAAAIQhABEqegC++GLZp3yfeEI66KBowwMAkHoEIEJFD8CCAmmPPUouP/qo1LFjtOEBAEg9AhChogfgq69KrVqVXB47VurcOdrwAACkHgGIUNED8I03pF12Kbk8erR0+OHRhgcAIPUIQISKHoB//au0004ll/Ngn7UAABiVSURBVB94QOrWLdrwAACkHgGIUNED8K23pObNSy7ff7909NHRhgcAIPUIQISKHoDvvSf94hcll0eMkHr0iDY8AACpRwAiVPQAnDpV2m67ksvDh0s9e0YbHgCA1CMAESp6AH70kbTNNiWXhw2TTjkl2vAAAKQeAYhQ0QNw+nSpYcOSy7fdJp12WrThAQBIPQIQoaIH4GefSfXqlVy+6Sapd+9owwMAkHoEIEJFD8B//lOqW7fk8pAh0jnnRBseAIDUIwARKnoA/vvfUu3aJZcHD5bOPz/a8AAApB4BiFDRA/A//5HMSi5ffbV00UXRhgcAIPUIQISKHoBz5ngArl3rlwcMkPLyog0PAEDqEYAIFT0Av/7aA3DVKr98+eVSv37RhgcAIPUIQISKHoDz53sA/vijX+7XT+rfP9rwAACkHgGIUNED8PvvPQCXLvXLeXn+NDAAAIiDAESo6AG4eLEH4KJFfrlPH38jCAAAiIMARKjoAbhsmQfgd9/55QsukAYNijY8AACpRwAiVPQAXLHCA/Dbb/3yOedI118fbXgAAFKPAESo6AG4erUH4Lx5frl3b/84OAAAEAcBiFDRA7Cw0ANw9my/3KuXdNtt0YYHACD1CECEih6AkrT55tJXX/n5U06Rhg6NOjwAAKlGACJUIgH4s59J//qXn+/ZUxo+POrwAACkGgGIUIkE4BZbSJ9/7uePO04aMSLq8AAApBoBiFCJBOBWW0mffurnjzlGuu++qMMDAJBqBCBCJRKAjRpJH3/s57t1k0aNijo8AACpRgAiVCIB2Lix9OGHfv7ww6XRo6MODwBAqhGACJVIADZpIr3/vp/v0kUaOzbq8AAApBoBiFCJBGDTptI77/j5jh2lRx6JOjwAAKlGACJUIgG4ww7SlCl+/qCDpCeeiDo8AACpRgAiVCIBuPPO0ptv+vn995eeeSbq8AAApBoBiFCJBOCuu0qvvebn995beu65qMMDAJBqBCBCJRKAv/yl9Morfr5tW+nFF6MODwBAqhGACJVIALZpI738sp9v3VqaODHq8AAApBoBiFCJBOBee0nPP+/nW7UqeToYAACEIwARKpEA3Gcfafx4P9+ypTR5ctThAQBINQIQoRIJwP33l55+2s+3aFFySBgAABCOAESoRALwoIOkxx/3882aSe++G3V4AABSjQBEqEQCsPSnf5T+WDgAABCOAESoRAKwc2dpzBg/37ix9NFHUYcHACDVCECESiQADztMGj3azzdsKE2fHnV4AABSjQBEqEQCsGtX6YEH/Hz9+tKMGVGHBwAg1QhAhEokAI86Srr/fj9ft670xRdRhwcAINUIwPRpZ2Yvmdk8Mys0s8Mz3GZrMxtnZj+Y2fdmNtbMGlUyXiIBeOyx0j33+PlataSZM6MODwBAqhGA6dPazM43s/3MbK1lDsAXzewVM9vGzBqb2atmNr6S8RIJwOOPl/74R6mwUDKTZs+OOjwAAKlGAKZbpj2AOxYtb1tqWbuiZTtkGCORADzxROnOO6U1azwA586NOjwAAKlGAKZbpgA8zsx+ynDbFWb26wzLEwnAU06R7rhDWrHCA/Dbb6MODwBAqhGANcdo86BbW/Rv+dPrGb4mUwD2NrOvM9z2GzM7PcPyRAKwVy/p1lulZcs8ABcujDo8AACpRgDWHPXMX69X2alBhq+pbA/gjxluu849gHl5ecrPz1d+fr4KCgqC/2P27i3deKO0eLEHYOS+BAAgdQoKCv73tzovL48ATLHKXgO41iq+BnCtVeFrAM85R7r+et/zZ+Z7AgEAQBzsAUynuma2hXkAdi+6XKvU9c+bWYGZ/dzMtjWziWb2bCVjJRKA558vDR7sr/0z89cCAgCAOAjA9NnJSl4rWPo0uNRttjazh81skfmxAMdY5f9BEgnA3/xGuvpqad48D8A1a6IODwBAqhGACJVIAF5yiXTVVX78PzM/HiAAAIiDAESoRALwt7+VrrjCPwGkVq2oQwMAkHoEIEIlEoCXXeanL77wzwIGAADxEIAIlUgAXnGF7wWcMUOqXz/q0AAApB4BiFCJBOBVV0kXXyxNny41bBh1aAAAUo8ARKhEAvDqq/2dwB99JDVuHHVoAABSjwBEqEQCcPBgPxbg++9LTZpEHRoAgNQjABEqkQC8/nrp7LOld9+VmjaNOjQAAKlHACJUIgF4443+ecBTpkgtWkQdGgCA1CMAESqRALz1VqlXL2nyZKlly6hDAwCQegQgQiUSgHfcIZ1yivTaa1KrVlGHBgAg9QhAhEokAO+8UzrxRGniRKl166hDAwCQegQgQiUSgH/8o3T88dKLL0pt20YdGgCA1CMAESqRALznHunYY6XnnpP23jvq0AAApB4BiFCJBODIkdJRR0nPPCPtt1/UoQEASD0CEKESCcAHHpC6dpWeeEI66KCoQwMAkHoEIEIlEoCjR0uHHSY98ojUsWPUoQEASD0CEKESCcCxY6XOnf3fLl2iDg0AQOoRgAiVSAA+8oh0yCG+J/Dww6MODQBA6hGACJVIAD7+uL/2b9QoqVu3qEMDAJB6BCBCJRKATz8t7b+/dN990jHHRB0aAIDUIwARKpEAHD/ej/83YoTUo0fUoQEASD0CEKESCcDnn5f22ksaPlzq2TPq0AAApB4BiFCJBODLL0tt2khDh0qnnBJ1aAAAUo8ARKhEAvCVV6Tdd5duu03q1Svq0AAApB4BiFCJBOBrr0m77irddJPUu3fUoQEASD0CEKESCcA335R23lm6/nrpnHOiDg0AQOoRgAiVSABOmSLtsIM0aJB0wQVRhwYAIPUIQIRKJADfeUdq2lS6+mqpT5+oQwMAkHoEIEIlEoDvvy81aSINGCDl5UUdGgCA1CMAESqRAPzwQ6lxY6l/f6lfv6hDAwCQegQgQiUSgP/4h9Sokcff5ZdHHRoAgNQjABEqkQD89FNpq6386d8BA6IODQBA6hGACJVIAH7+ubTFFtJFF/kbQQAAQDwEIEIlEoD/+pf0s59J558vDR4cdWgAAFKPAESoRALwq6+kzTbzg0APGRJ1aAAAUo8ARKhEAnD2bMlMOuMM/zg4AAAQDwGIUIkE4Lx5HoAnnyzddlvUoQEASD0CEKESCcBvv/UA7NFDGjYs6tAAAKQeAYhQiQTgd995AHbrJg0fHnVoAABSjwBEqEQCcNEiD8AuXaQRI6IODQBA6hGACJVIAC5d6gHYoYN0//1RhwYAIPUIQIRKJAB//NEDcJ99pAceiDo0AACpRwAiVCIBuGqVB2CbNtLo0VGHBgAg9QhAhEokANeu9QDcdVdp7NioQwMAkHoEIEIlEoCSB+AOO0iPPhp9aAAAUo0ARKjEArB2bWm77aQnnog+NAAAqUYAIlRiAVi3rtSggfTMM9GHBgAg1QhAhEosAOvXl+rUkSZMiD40AACpRgAiVGIB2LChvw7wpZeiDw0AQKoRgAiVWABus40H4MSJ0YcGACDVCECESiwAt9vOA/C116IPDQBAqhGACJVYAP7iFx6Ab74ZfWgAAFKNAESoxAKweXMPwClTog8NAECqEYAIlVgA7rSTB+C770YfGgCAVCMAESqxANxlFw/AqVOjDw0AQKoRgAiVWAC2auUBOG1a9KEBAEg1AhChEgvAPfbwAJw+PfrQAACkGgGIUIkFYNu2HoAzZkQfGgCAVCMAESqxAGzf3gPwyy+jDw0AQKoRgAiVWADut58H4MyZ0YcGACDVCECESiwADzzQA3D27OhDAwCQagQgQiUWgAcf7AE4b170oQEASDUCEKESC8BDD/UAnD8/+tAAAKQaAYhQiQXgr37lAbhwYfShAQBINQIQoRILwCOP9ABMYGgAAFKNAESoxAKwe3cPwOXLow8NAECqEYAIlVgAHnOMB+CKFdGHBgAg1QjA9GlnZi+Z2TwzKzSzwzPcZrKZrTSzJWa2tOjfPpWMl1gAHnecB+CaNdGHBgAg1QjA9GltZueb2X5mttYyB+AbZnb9Bo6XWAD27OkBWFgYfWgAAFKNAEy3yvYAvmFmQzZwjMQC8OSTpdq1ow8LAEDqEYDptq4AXGBmC83sMzO7xczqVzJGYgF42mlS3brRhwUAIPUIwJpjtHnQrS36t/zp9QxfU1kAdjCzrYvO72VmH5rZo5WsN7EAPOMMqX796MMCAJB6BGDNUc/MGq/j1CDD11QWgOV1MbNVZlY3w3UNzUx5eXnKz89Xfn6+CgoKovznPOssqVGjKEMBAJB6BQUF//tbnZeXRwCm2IYGYGfzANwiw3WJ7QE87zypcePowwIAkHrsAUynuuYxV2hm3Ysu1yq6rknRsnpFl/c0s/fN7MlKxkosAC+8UGrSJPqwAACkHgGYPjtZyWsFS58GF12/o5m9Z2aLzI//94Vl6U0gffpIzZpFHxYAgNQjABEqsQC89FJpxx2jDwsAQOoRgAiVWAD26ye1bBl9WAAAUo8ARKjEAvDyy6VWraIPCwBA6hGACJVYAA4YIO2xR/RhAQBIPQIQoRILwIEDpbZtow8LAEDqEYAIlVgADhok7b139GEBAEg9AhChEgvA666T9t8/+rAAAKQeAYhQiQXgDTdIHTpEHxYAgNQjABEqsQC85RapY8fowwIAkHoEIEIlFoC33y516RJ9WAAAUo8ARKjEAnDYMOmII6IPCwBA6hGACJVYAN51l9StW/RhAQBIPQIQoRILwHvvlY49NvqwAACkHgGIUIkF4MKF0qefRh8WAIDUIwARKrEABAAAySAAEYoABAAgxxCACEUAAgCQYwhAhCIAAQDIMQQgQhGAAADkGAIQoQhAAAByDAGIUAQgAAA5hgBEKAIQAIAcQwAiFAEIAECOIQARigAEACDHEIAIRQACAJBjCECEIgABAMgxBCBCEYAAAOQYAhChCEAAAHIMAYhQBCAAADmGAEQoAhAAgBxDACIUAQgAQI4hABGKAAQAIMcQgAhFAAIAkGMIQIQiAAEAyDEEIEIRgAAA5BgCEKEIQAAAcgwBiFAEIAAAOYYARCgCEACAHEMAIhQBCABAjiEAEYoABAAgxxCACEUAAgCQYwhAhCIAAQDIMQQgQhGAAADkGAIQoQhAAAByDAGIUAQgAAA5hgBEKAIQAIAcQwAiFAEIAECOIQARigAEACDHEIAIRQACAJBjCECEIgABAMgxBCBCEYAAAOQYAhChCEAAAHIMAYhQBCAAADmGAEQoAhAAgBxDACIUAQgAQI4hABGKAAQAIMcQgAhFAAIAkGMIQIQiAAEAyDEEIEIRgAAA5BgCEKEIQAAAcgwBiFAEIAAAOYYARCgCEACAHEMAIhQBCABAjiEAEYoABAAgxxCACEUAAgCQYwhAhCIAAQDIMQQgQhGAAADkGAIwfc40sylmttDMFpjZ62Z2SLnb1DGze4quX2xmE8xsh0rGIwABAMgxBGD6XGxmXc2svpnVMrN+ZrbEzJqVus09ZjbNPPq2MrO/mNmHlYxHAAIAkGMIQJiZ/WBmxxedr2tmy83s16Wu/7mZrTKzjhm+tkYHYEFBQbankBi2LTfV5G2Tavb2sW25qaZuGwGIg8zjbueiy+3MbK2ZbV/udv80s0szfH2NDsD8/PxsTyExbFtuqsnbJtXs7WPbclNN3TYCsOYYbWaF5vFWmOH0eoavaWFmX5nZ9aWWdSoao265275rZldnGIMAzFFsW26qydsm1eztY9tyU03dNgKw5qhnZo3XcWpQ7va7mdlMM7ul3PJN2gM4Z84cLV68uMad8vLysj4Hto1tS8u21fTtY9ty81RTt23OnDkEYAq1M7N5lnmPXqbXAG5rZist82sAm5v/B+LEiRMnTpw45d6puSEVDjE/BEzfddxmhPm7fluY7zn8i5l9UMltNzP/z9OQEydOnDhx4pRTp+bmf8eRAq+b2RrzQ78sLTotMbPflbpNHTO728y+K7rueeMRAgAAAAAAAAAAAACkwPVmNtf8qeTJZrZnVmezaa61sk+LLzGzcaWub2dmb5rZMjP7b9Htq6tTzeyv5h/ht9bMNi93/YZsS3X9ma5v2wrN7Ecr+3MsP/fqum23mNk/zLdtrpk9YhU/frGF+csxlpjZfPOXadQud5s880M7LTOzqWZ2aHJT3mAbsm3/MbOfrOzP7phyt6mO2zbYzP5lZovMfyYvm1n7crfJ1fvchmxbLt/nSnvWfFsOL7XsV+avfV9uZv82sz7lvmZjPjI1m8pv205Fl4t/XsX/lj5SSK5sG7LoSjObZWZtzN89fLP5L7h62ZzUJrjWPCwy2cr8HdM3mt8p2prZHPOP0KuOupqH0rlWMZI2ZFuq8890Xdtm5r/UDlvH11fnbbvJzPYxD7qG5g9APip1/WbmETXa/GMcW5jZx2b2h1K3OcX8U306FY1zifkv92y/fnd922bmYXfuOsaortvWyswaFZ2vbWb9zewbK3lRfS7f59a3bWa5fZ8rdpaZTTT/nVI6kpaZR19tM+tsHsLHl/q6jfnI1GypbNvWmlnLdXxdLmwbsmymlT02YC3zR4pnZGc6m2xdAXi2+S+90rHR18y+THpSgbpYxUjakG3JhZ9ppm0zq/gIvrxc2LZi7c23sfgPcBfzQzFtU+o2x5lH0M+KLr9uZsPKjfOhmf0+uWlukvLbZuYBeN46viYXtq2umV1mvm0/L1pWU+5zmbbNLPfvczuY733ewcpuy2CreOSLO83s1aLzG/uRqdlQ2bYV7wHctZKvy4VtQ5Y1NP9PdFC55RPNbGjVTyfIteZ/SL81/0M0zko+Gu9O86c+SjvY/BfhVlU0v02RKZLWty258jNdVwDOM3/aYqqZXVDqulzZtmIDzP94FutrZjPK3aap+Ta1Lbr8vfke0tJGmtlTSUwwQPltM/P73TfmRx74h/meo9JPb1fnbTvGfO9koflLSe4odV2u3+fWtW1muX+fm2hm5xedLx1Jz5jZfeVu28v8/6dZyYOYDf3AhGyobNuK9wDOMf+5TTGzE0p9XTur/tuGLCt+VPHLcssfM7M/Vf10grQxf0rNzP+oPmz+CL2emT1gZo+Wu31r8ztIs6qa4CbIFEnr25Zc+ZlWFoCHmT96rW1mR5tHw0VF1+XKtpmZHWn+gKRrqWXXmNk75W63hfk2HVJ0eY2ZdS93m1vN7JUE5ripMm2bmb+er775z/QQ8yAs/SlFubBtW5s/tXtSqWU15T6XadvMcvs+d4l5JBUr/XT2JKv4KVlHme8FM9v4j0ytapm2rTgA65tHeW3z+fc2sxXm22dW/bcN1UAuPLrbVHXMX5B+pLEH0Kz6/UwrC8DyrjV/dGuWO9v2a/M9LseVW76uPYDFL6qvznvJzCrftkzONn+tWLHqvm3FNjN/rdheRZdryn3OrOK2ZZIr97ldzPdctii1bGP2AFbnvWTr27ZMRpvv+DCr3tuGaiTT6zu+terz+o5NVcf8nW1dzV9EW1NeA7gh25ILP9MNDcDBZvZWqcvVfdvOMA+kIzNc19n8UXqm1wDWKbr8ulX8w/qBVY/Xya1r2zI5y/ydo8Wq87aVVtv89VMnFl2uKfc5s4rblkmu3OfONr8/zTd/GnSBeST9YGb3m9kg2/jXAK7rI1Or0vq2LZM/W8mRL6rztqEaucL8RaZ7mtmW5u/2m2PV6x1eG+IUK3lh8/ZmNsb8F1d980fpc83sBvOn3Nqav6utur4LeHPzO3A380iqV3R5M9uwbanOP9N1bds+Zrav+RsiahXdZqH5oUOKVedtu9T8F3Rlv2A3M39X3oPmP8cdzd9JW/pdwCeb7ynrZP59uNj88A7Zfqfs+rZtN/M5F/8sO5gfdqP0682q67b1NbMmRee3M39q83sr2XuSy/e59W1bLt/ntjB/Cr70qdD8b8HW5vevZeZPZ//M/CUKP1jZdwFvzEemVqX1bVsn85chbG6+bb3Md3iUDr7qum2oZq4zs6/N7yyTrXoe42l9njN/VLrM/JfTOPPd6MXamr9LeLn5rvVBVT3BjXC2+Z19bdGp+Hznous3ZFuus+r5M13Xtv3azD4z3yP2vXkcXZhhjOusem5bofkj7CVW9thcpaOphZm9UHTdAjO7y0reAVzsEvM/uMvNX5TfKclJb6D1bdsB5nG72Pwpxk/N7CrzqCitOm7b8+b/n5aah9548ygqLVfvc+vbtly/z5VX+lApZv575UPzn9tMK3ltY7Fc+sjU0tt2vvnxHZeaz/1tq7hXN5e2DQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADnt/wEYofCQl99VlgAAAABJRU5ErkJggg==\">"
+ ],
+ "text/plain": [
+ "<IPython.core.display.HTML object>"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/usr/lib64/python3.5/site-packages/matplotlib/pyplot.py:516: RuntimeWarning: More than 20 figures have been opened. Figures created through the pyplot interface (`matplotlib.pyplot.figure`) are retained until explicitly closed and may consume too much memory. (To control this warning, see the rcParam `figure.max_open_warning`).\n",
+ " max_open_warning, RuntimeWarning)\n"
+ ]
+ },
+ {
+ "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": [
+ "ids = (45, 46, 44) # Run IDs of runs for R, G and B channel\n",
+ "\n",
+ "# Approximate bands of interest for R, G and B channelsfor offset and stray light correction.\n",
+ "bands = [(260,410), (150,330), (100,260)] # [step]\n",
+ "\n",
+ "# The wavelengths are from a random RGB LED datasheet and are just preliminary starting values.\n",
+ "# https://www.sparkfun.com/datasheets/Components/YSL-R596CR3G4B5C-C10.pdf\n",
+ "λ_led = [623, 518, 466] # [nm] Assumed wavelengths of R, G and B spectral peaks.\n",
+ "λ_be = 400 # [nm] Approximate short-λ edge of blue band\n",
+ "y_edge_min = 0.5\n",
+ "\n",
+ "poly_degree = 2 # degree of polynomial for stray light and offset correction. Should be 1 or 2.\n",
+ "\n",
+ "max_stdev = 1.0 # [V] Nerved value that has been used for outlier removal in earlier tries\n",
+ "\n",
+ "remove_thresh = 0.05 # [V] standard deviation delta threshold for outlier removal\n",
+ "\n",
+ "# ---\n",
+ "data_rgb = []\n",
+ "for run_id, (l, r) in zip(ids, bands):\n",
+ " # Load this channel from the database\n",
+ " steps, values, stdev = load_run_zero_cal(run_id, max_stdev)\n",
+ " \n",
+ " # Remove outlier values whose standard deviation is much larger than that of their right and left neighbors\n",
+ " idxs = (np.abs(stdev[1:-1] - stdev[0:-2]) < remove_thresh) |\\\n",
+ " (np.abs(stdev[1:-1] - stdev[2:]) < remove_thresh)\n",
+ " idxs = np.hstack([np.array([True]), idxs, np.array([True])])\n",
+ " steps, values, stdev = steps[idxs], values[idxs], stdev[idxs]\n",
+ " \n",
+ " # Remove offset and stray light by fitting a second-order polynomial over the parts of the curve\n",
+ " # that are clearly *not* part of the primary peak.\n",
+ " idxs = (steps < l) | (steps > r)\n",
+ " poly = np.poly1d(np.polyfit(steps[idxs], values[idxs], poly_degree))\n",
+ " print('Poly for run {}:'.format(run_id))\n",
+ " print(poly)\n",
+ " values -= poly(steps)\n",
+ " \n",
+ " data_rgb.append((steps, values, stdev))\n",
+ "\n",
+ "\n",
+ "# Calibrate wavelength axis using assumed peaks for r, g and b. Use least-squares polyfit for getting coefficients.\n",
+ "peaks = [ x[np.argmax(y)] for x, y, σ2 in data_rgb ]\n",
+ "edgesl = [ x[np.argmax(y > y_edge_min)] for x, y, σ2 in data_rgb ]\n",
+ "print(edgesl, peaks)\n",
+ "\n",
+ "Λ_est = np.poly1d(np.polyfit([edgesl[2], peaks[0]], [λ_be, λ_led[0]], 1))\n",
+ "\n",
+ "data_tmp = [ (x, Λ_est(x), y, σ2) for x, y, σ2 in data_rgb ]\n",
+ "data_tmp = [ (x, λ, y/Λ_sfh2701(λ), σ2) for x, λ, y, σ2 in data_tmp ]\n",
+ "# Limit wavelength range\n",
+ "data_tmp = [ (x[λ > 380], λ[λ > 380], y[λ > 380], σ2[λ > 380]) for x, λ, y, σ2 in data_tmp ]\n",
+ "peaks = [ x[np.argmax(y)] for x, λ, y, σ2 in data_tmp ]\n",
+ "Λ = np.poly1d(np.polyfit(peaks, λ_led, 1))\n",
+ "\n",
+ "data_rgb = [ (Λ(x), y, σ2) for x, y, σ2 in data_rgb ]\n",
+ "data_rgb = [ (λ, y/Λ_sfh2701(λ), σ2) for λ, y, σ2 in data_rgb ]\n",
+ "\n",
+ "# Limit wavelength range to slightly-larger-than visible range. We're getting improbably large values in the\n",
+ "# utraviolet region that are probably caused by stray light.\n",
+ "data_rgb = [ (λ[λ > 380], y[λ > 380], σ2[λ > 380]) for λ, y, σ2 in data_rgb ]\n",
+ "\n",
+ "# Normalize amplitude data to brightest channel for ease of reading\n",
+ "max_val = max(np.max(y) for λ, y, σ2 in data_rgb)\n",
+ "data_rgb = [ (λ, y/max_val, σ2/max_val) for λ, y, σ2 in data_rgb ]\n",
+ "\n",
+ "plot_rgb_bar(data_rgb, ids, spline_s=0.005)"
+ ]
}
],
"metadata": {
diff --git a/firmware/measure_spectrum.py b/firmware/measure_spectrum.py
index 0e7dc22..471d1a8 100644
--- a/firmware/measure_spectrum.py
+++ b/firmware/measure_spectrum.py
@@ -14,10 +14,12 @@ if __name__ == '__main__':
parser = argparse.ArgumentParser()
parser.add_argument('run_name', nargs='?', default='auto')
parser.add_argument('buspirate_port', nargs='?', default='/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AD01W1RF-if00-port0')
- parser.add_argument('-s', '--steps', type=int, nargs='?', default=100, help='Steps to run through')
+ parser.add_argument('-s', '--steps', type=int, nargs='?', default=400, help='Steps to run through')
+ parser.add_argument('-k', '--skip', type=int, nargs='?', default=2, help='Steps skip between measurements for shorter runtime')
parser.add_argument('-d', '--database', default='spectra.sqlite3', help='sqlite3 database file to store results in')
- parser.add_argument('-w', '--wait', type=float, default=0.1, help='time to wait between samples in seconds')
- parser.add_argument('-o', '--oversample', type=int, default=16, help='oversampling ratio')
+ parser.add_argument('-w', '--wait', type=float, default=2.0, help='time to wait between samples in seconds')
+ parser.add_argument('-o', '--oversample', type=int, default=32, help='oversampling ratio')
+ parser.add_argument('-c', '--comment', help='run comment')
args = parser.parse_args()
db = sqlite3.connect(args.database)
@@ -80,8 +82,8 @@ if __name__ == '__main__':
run_name += str(1+max(int(n) if str.isnumeric(n) else 0 for n in names))
with db:
cur = db.cursor()
- cur.execute('INSERT INTO runs(name, timestamp) VALUES (?, ?)',
- (run_name, time.time()))
+ cur.execute('INSERT INTO runs(name, comment, timestamp) VALUES (?, ?, ?)',
+ (run_name, args.comment, time.time()))
run_id = cur.lastrowid
print('Starting run {} "{}" at {:%y-%m-%d %H:%M:%S:%f}'.format(run_id, run_name, datetime.now()))
@@ -92,8 +94,7 @@ if __name__ == '__main__':
bp.step()
bp.stepper_direction('up')
- for step in range(args.steps):
- bp.step()
+ for step in range(0, args.steps+args.skip, args.skip): # Run one skip past end to capture both interval boundaries
for led_val in [0, 1]:
try:
bp.led(led_val)
@@ -115,8 +116,10 @@ if __name__ == '__main__':
raise
except TypeError as e:
print('Buspirate hiccup, ignoring:', e)
+ for _ in range(args.skip):
+ bp.step()
bp.stepper_direction('down')
- for _ in range(args.steps):
+ for _ in range(args.steps+args.skip):
bp.step()
diff --git a/firmware/spectra.sqlite3 b/firmware/spectra.sqlite3
index c82c2fe..09e23c2 100644
--- a/firmware/spectra.sqlite3
+++ b/firmware/spectra.sqlite3
Binary files differ
diff --git a/firmware/spectrum_progress.py b/firmware/spectrum_progress.py
index a4eb4b2..35a9d65 100644
--- a/firmware/spectrum_progress.py
+++ b/firmware/spectrum_progress.py
@@ -17,7 +17,7 @@ if __name__ == '__main__':
step, = db.execute(
'SELECT MAX(step) FROM measurements WHERE run_id = (SELECT MAX(run_id) FROM runs)'
).fetchone()
- return int(step)+1
+ return int(step)
def step_gen():
while True:
@@ -28,5 +28,9 @@ if __name__ == '__main__':
time.sleep(args.update_delay)
bar = tqdm.tqdm(total=args.max_step)
- for step in step_gen():
- bar.update(step - bar.n)
+ while True:
+ try:
+ for step in step_gen():
+ bar.update(step - bar.n)
+ except:
+ time.sleep(args.update_delay)
diff --git a/firmware/stepper_test.py b/firmware/stepper_test.py
index 919fc02..23486fb 100644
--- a/firmware/stepper_test.py
+++ b/firmware/stepper_test.py
@@ -27,27 +27,32 @@ if __name__ == '__main__':
def stepper_step():
bp.cs = 1
- time.sleep(0.005)
+ #time.sleep(0.005)
bp.cs = 0
- time.sleep(0.005)
+ #time.sleep(0.005)
import curses
screen = curses.initscr()
curses.noecho()
curses.cbreak()
screen.keypad(True)
+ i = 0
try:
while True:
key = screen.getch()
if key == ord('q'):
break
+ screen.addstr('{: 4}'.format(i))
+
if key == curses.KEY_DOWN:
stepper_direction_down()
stepper_step()
+ i -= 1
elif key == curses.KEY_UP:
stepper_direction_up()
stepper_step()
+ i += 1
finally:
curses.nocbreak()