summaryrefslogtreecommitdiff
path: root/doc/Spectrum Measurement.ipynb
diff options
context:
space:
mode:
Diffstat (limited to 'doc/Spectrum Measurement.ipynb')
-rw-r--r--doc/Spectrum Measurement.ipynb3667
1 files changed, 3667 insertions, 0 deletions
diff --git a/doc/Spectrum Measurement.ipynb b/doc/Spectrum Measurement.ipynb
new file mode 100644
index 0000000..516321b
--- /dev/null
+++ b/doc/Spectrum Measurement.ipynb
@@ -0,0 +1,3667 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "import sqlite3\n",
+ "import time\n",
+ "from IPython import display\n",
+ "from datetime import datetime\n",
+ "import scipy.interpolate as inter\n",
+ "from scipy import integrate\n",
+ "\n",
+ "import numpy as np\n",
+ "from matplotlib import pyplot as plt\n",
+ "%matplotlib notebook"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "db = sqlite3.connect('spectra.sqlite3')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 71,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "def load_run(capture_id, gain, zero_cal=False):\n",
+ " if zero_cal:\n",
+ " data = db.execute('SELECT a.step, a.voltage, a.voltage_stdev, b.voltage, b.voltage_stdev '\n",
+ " 'FROM measurements a JOIN measurements b USING (step) '\n",
+ " 'WHERE a.capture_id = ?1 AND a.led_on = 1 AND b.capture_id = ?1 AND b.led_on = 0 '\n",
+ " 'ORDER BY step ASC', (capture_id,)).fetchall()\n",
+ " steps, voltages, voltage_stdevs, zero_voltages, zero_stdevs = map(np.array, zip(*data))\n",
+ " else:\n",
+ " data = db.execute('SELECT step, voltage, voltage_stdev '\n",
+ " 'FROM measurements '\n",
+ " 'WHERE capture_id = ? AND led_on = 1 '\n",
+ " 'ORDER BY step ASC', (capture_id,)).fetchall()\n",
+ " steps, voltages, voltage_stdevs = map(np.array, zip(*data))\n",
+ " zero_voltages = zero_stdevs = np.zeros(len(steps))\n",
+ " \n",
+ " return (steps,\n",
+ " (voltages-zero_voltages)/gain*1e9, # nanoamps\n",
+ " np.sqrt(np.square(voltage_stdevs) + np.square(zero_stdevs))/gain*1e9) #nanoamps"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 94,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "def find_captures(name):\n",
+ " # Get the newest capture for each color\n",
+ " captures = db.execute(\n",
+ " 'SELECT capture_id, color, gain FROM runs WHERE (name, color, timestamp) IN '\n",
+ " '(SELECT name, color, MAX(timestamp) FROM runs '\n",
+ " 'WHERE name=? GROUP BY color ORDER BY timestamp)', (name,)).fetchall()\n",
+ " \n",
+ " if not captures:\n",
+ " raise ValueError('Run not found')\n",
+ " return captures"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 95,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "def live_plot(name,\n",
+ " spline_s=1, interval=1,\n",
+ " live=True, save_svg=None):\n",
+ " captures = find_captures(name)\n",
+ " \n",
+ " fig, ax = plt.subplots(1, 1)\n",
+ " \n",
+ " colors = {\n",
+ "\n",
+ " }\n",
+ " \n",
+ " while True:\n",
+ " ax.clear()\n",
+ " ax.spines['top'].set_visible(False)\n",
+ " ax.spines['right'].set_visible(False)\n",
+ " ax.spines['bottom'].set_color('#08bdf9')\n",
+ " ax.spines['left'].set_color('#08bdf9')\n",
+ " ax.tick_params(axis='x', colors='#01769D')\n",
+ " ax.tick_params(axis='y', colors='#01769D')\n",
+ " ax.xaxis.label.set_color('#01769D')\n",
+ " ax.yaxis.label.set_color('#01769D')\n",
+ " ax.set_xlabel('$x\\;[step]$')\n",
+ " ax.set_ylabel('$I_{pd}\\;[nA]$')\n",
+ " ax.grid(color='#08bdf9', linestyle=':')\n",
+ " \n",
+ " for capture_id, color, gain in captures:\n",
+ " color_dark, color_bright = colors.get(color, ('#fe3ea0', '#ffd2e9'))\n",
+ " steps, values, stdev = load_run(capture_id, gain)\n",
+ " \n",
+ " ax.errorbar(steps, values, yerr=stdev, color=color_bright, zorder=1)\n",
+ " try:\n",
+ " spline = inter.UnivariateSpline(steps, values, s=spline_s)\n",
+ " ax.plot(steps, spline(steps), color=color_dark, zorder=2)\n",
+ " except:\n",
+ " pass\n",
+ " fig.canvas.draw()\n",
+ " if save_svg:\n",
+ " fig.savefig(save_svg)\n",
+ " if save_svg or not live:\n",
+ " break\n",
+ " time.sleep(1)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 113,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "application/javascript": [
+ "/* Put everything inside the global mpl namespace */\n",
+ "window.mpl = {};\n",
+ "\n",
+ "\n",
+ "mpl.get_websocket_type = function() {\n",
+ " if (typeof(WebSocket) !== 'undefined') {\n",
+ " return WebSocket;\n",
+ " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
+ " return MozWebSocket;\n",
+ " } else {\n",
+ " alert('Your browser does not have WebSocket support.' +\n",
+ " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
+ " 'Firefox 4 and 5 are also supported but you ' +\n",
+ " 'have to enable WebSockets in about:config.');\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
+ " this.id = figure_id;\n",
+ "\n",
+ " this.ws = websocket;\n",
+ "\n",
+ " this.supports_binary = (this.ws.binaryType != undefined);\n",
+ "\n",
+ " if (!this.supports_binary) {\n",
+ " var warnings = document.getElementById(\"mpl-warnings\");\n",
+ " if (warnings) {\n",
+ " warnings.style.display = 'block';\n",
+ " warnings.textContent = (\n",
+ " \"This browser does not support binary websocket messages. \" +\n",
+ " \"Performance may be slow.\");\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " this.imageObj = new Image();\n",
+ "\n",
+ " this.context = undefined;\n",
+ " this.message = undefined;\n",
+ " this.canvas = undefined;\n",
+ " this.rubberband_canvas = undefined;\n",
+ " this.rubberband_context = undefined;\n",
+ " this.format_dropdown = undefined;\n",
+ "\n",
+ " this.image_mode = 'full';\n",
+ "\n",
+ " this.root = $('<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",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " }\n",
+ "\n",
+ " this.imageObj.onload = function() {\n",
+ " if (fig.image_mode == 'full') {\n",
+ " // Full images could contain transparency (where diff images\n",
+ " // almost always do), so we need to clear the canvas so that\n",
+ " // there is no ghosting.\n",
+ " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
+ " }\n",
+ " fig.context.drawImage(fig.imageObj, 0, 0);\n",
+ " };\n",
+ "\n",
+ " this.imageObj.onunload = function() {\n",
+ " this.ws.close();\n",
+ " }\n",
+ "\n",
+ " this.ws.onmessage = this._make_on_message_function(this);\n",
+ "\n",
+ " this.ondownload = ondownload;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_header = function() {\n",
+ " var titlebar = $(\n",
+ " '<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 backingStore = this.context.backingStorePixelRatio ||\n",
+ "\tthis.context.webkitBackingStorePixelRatio ||\n",
+ "\tthis.context.mozBackingStorePixelRatio ||\n",
+ "\tthis.context.msBackingStorePixelRatio ||\n",
+ "\tthis.context.oBackingStorePixelRatio ||\n",
+ "\tthis.context.backingStorePixelRatio || 1;\n",
+ "\n",
+ " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
+ "\n",
+ " var rubberband = $('<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 * mpl.ratio);\n",
+ " canvas.attr('height', height * mpl.ratio);\n",
+ " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
+ "\n",
+ " rubberband.attr('width', width);\n",
+ " rubberband.attr('height', height);\n",
+ " }\n",
+ "\n",
+ " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
+ " // upon first draw.\n",
+ " this._resize_canvas(600, 600);\n",
+ "\n",
+ " // Disable right mouse context menu.\n",
+ " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
+ " return false;\n",
+ " });\n",
+ "\n",
+ " function set_focus () {\n",
+ " canvas.focus();\n",
+ " canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " window.setTimeout(set_focus, 100);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_toolbar = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var nav_element = $('<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'] / mpl.ratio;\n",
+ " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
+ " var x1 = msg['x1'] / mpl.ratio;\n",
+ " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
+ " x0 = Math.floor(x0) + 0.5;\n",
+ " y0 = Math.floor(y0) + 0.5;\n",
+ " x1 = Math.floor(x1) + 0.5;\n",
+ " y1 = Math.floor(y1) + 0.5;\n",
+ " var min_x = Math.min(x0, x1);\n",
+ " var min_y = Math.min(y0, y1);\n",
+ " var width = Math.abs(x1 - x0);\n",
+ " var height = Math.abs(y1 - y0);\n",
+ "\n",
+ " fig.rubberband_context.clearRect(\n",
+ " 0, 0, fig.canvas.width, fig.canvas.height);\n",
+ "\n",
+ " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
+ " // Updates the figure title.\n",
+ " fig.header.textContent = msg['label'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
+ " var cursor = msg['cursor'];\n",
+ " switch(cursor)\n",
+ " {\n",
+ " case 0:\n",
+ " cursor = 'pointer';\n",
+ " break;\n",
+ " case 1:\n",
+ " cursor = 'default';\n",
+ " break;\n",
+ " case 2:\n",
+ " cursor = 'crosshair';\n",
+ " break;\n",
+ " case 3:\n",
+ " cursor = 'move';\n",
+ " break;\n",
+ " }\n",
+ " fig.rubberband_canvas.style.cursor = cursor;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
+ " fig.message.textContent = msg['message'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
+ " // Request the server to send over a new figure.\n",
+ " fig.send_draw_message();\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
+ " fig.image_mode = msg['mode'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.updated_canvas_event = function() {\n",
+ " // Called whenever the canvas gets updated.\n",
+ " this.send_message(\"ack\", {});\n",
+ "}\n",
+ "\n",
+ "// A function to construct a web socket function for onmessage handling.\n",
+ "// Called in the figure constructor.\n",
+ "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
+ " return function socket_on_message(evt) {\n",
+ " if (evt.data instanceof Blob) {\n",
+ " /* FIXME: We get \"Resource interpreted as Image but\n",
+ " * transferred with MIME type text/plain:\" errors on\n",
+ " * Chrome. But how to set the MIME type? It doesn't seem\n",
+ " * to be part of the websocket stream */\n",
+ " evt.data.type = \"image/png\";\n",
+ "\n",
+ " /* Free the memory for the previous frames */\n",
+ " if (fig.imageObj.src) {\n",
+ " (window.URL || window.webkitURL).revokeObjectURL(\n",
+ " fig.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
+ " evt.data);\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
+ " fig.imageObj.src = evt.data;\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var msg = JSON.parse(evt.data);\n",
+ " var msg_type = msg['type'];\n",
+ "\n",
+ " // Call the \"handle_{type}\" callback, which takes\n",
+ " // the figure and JSON message as its only arguments.\n",
+ " try {\n",
+ " var callback = fig[\"handle_\" + msg_type];\n",
+ " } catch (e) {\n",
+ " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " if (callback) {\n",
+ " try {\n",
+ " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
+ " callback(fig, msg);\n",
+ " } catch (e) {\n",
+ " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
+ " }\n",
+ " }\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
+ "mpl.findpos = function(e) {\n",
+ " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
+ " var targ;\n",
+ " if (!e)\n",
+ " e = window.event;\n",
+ " if (e.target)\n",
+ " targ = e.target;\n",
+ " else if (e.srcElement)\n",
+ " targ = e.srcElement;\n",
+ " if (targ.nodeType == 3) // defeat Safari bug\n",
+ " targ = targ.parentNode;\n",
+ "\n",
+ " // jQuery normalizes the pageX and pageY\n",
+ " // pageX,Y are the mouse positions relative to the document\n",
+ " // offset() returns the position of the element relative to the document\n",
+ " var x = e.pageX - $(targ).offset().left;\n",
+ " var y = e.pageY - $(targ).offset().top;\n",
+ "\n",
+ " return {\"x\": x, \"y\": y};\n",
+ "};\n",
+ "\n",
+ "/*\n",
+ " * return a copy of an object with only non-object keys\n",
+ " * we need this to avoid circular references\n",
+ " * http://stackoverflow.com/a/24161582/3208463\n",
+ " */\n",
+ "function simpleKeys (original) {\n",
+ " return Object.keys(original).reduce(function (obj, key) {\n",
+ " if (typeof original[key] !== 'object')\n",
+ " obj[key] = original[key]\n",
+ " return obj;\n",
+ " }, {});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.mouse_event = function(event, name) {\n",
+ " var canvas_pos = mpl.findpos(event)\n",
+ "\n",
+ " if (name === 'button_press')\n",
+ " {\n",
+ " this.canvas.focus();\n",
+ " this.canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " var x = canvas_pos.x * mpl.ratio;\n",
+ " var y = canvas_pos.y * mpl.ratio;\n",
+ "\n",
+ " this.send_message(name, {x: x, y: y, button: event.button,\n",
+ " step: event.step,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ "\n",
+ " /* This prevents the web browser from automatically changing to\n",
+ " * the text insertion cursor when the button is pressed. We want\n",
+ " * to control all of the cursor setting manually through the\n",
+ " * 'cursor' event from matplotlib */\n",
+ " event.preventDefault();\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " // Handle any extra behaviour associated with a key event\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.key_event = function(event, name) {\n",
+ "\n",
+ " // Prevent repeat events\n",
+ " if (name == 'key_press')\n",
+ " {\n",
+ " if (event.which === this._key)\n",
+ " return;\n",
+ " else\n",
+ " this._key = event.which;\n",
+ " }\n",
+ " if (name == 'key_release')\n",
+ " this._key = null;\n",
+ "\n",
+ " var value = '';\n",
+ " if (event.ctrlKey && event.which != 17)\n",
+ " value += \"ctrl+\";\n",
+ " if (event.altKey && event.which != 18)\n",
+ " value += \"alt+\";\n",
+ " if (event.shiftKey && event.which != 16)\n",
+ " value += \"shift+\";\n",
+ "\n",
+ " value += 'k';\n",
+ " value += event.which.toString();\n",
+ "\n",
+ " this._key_event_extra(event, name);\n",
+ "\n",
+ " this.send_message(name, {key: value,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
+ " if (name == 'download') {\n",
+ " this.handle_save(this, null);\n",
+ " } else {\n",
+ " this.send_message(\"toolbar_button\", {name: name});\n",
+ " }\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
+ " this.message.textContent = tooltip;\n",
+ "};\n",
+ "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
+ "\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "\n",
+ "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
+ " // Create a \"websocket\"-like object which calls the given IPython comm\n",
+ " // object with the appropriate methods. Currently this is a non binary\n",
+ " // socket, so there is still some room for performance tuning.\n",
+ " var ws = {};\n",
+ "\n",
+ " ws.close = function() {\n",
+ " comm.close()\n",
+ " };\n",
+ " ws.send = function(m) {\n",
+ " //console.log('sending', m);\n",
+ " comm.send(m);\n",
+ " };\n",
+ " // Register the callback with on_msg.\n",
+ " comm.on_msg(function(msg) {\n",
+ " //console.log('receiving', msg['content']['data'], msg);\n",
+ " // Pass the mpl event to the overriden (by mpl) onmessage function.\n",
+ " ws.onmessage(msg['content']['data'])\n",
+ " });\n",
+ " return ws;\n",
+ "}\n",
+ "\n",
+ "mpl.mpl_figure_comm = function(comm, msg) {\n",
+ " // This is the function which gets called when the mpl process\n",
+ " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
+ "\n",
+ " var id = msg.content.data.id;\n",
+ " // Get hold of the div created by the display call when the Comm\n",
+ " // socket was opened in Python.\n",
+ " var element = $(\"#\" + id);\n",
+ " var ws_proxy = comm_websocket_adapter(comm)\n",
+ "\n",
+ " function ondownload(figure, format) {\n",
+ " window.open(figure.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " var fig = new mpl.figure(id, ws_proxy,\n",
+ " ondownload,\n",
+ " element.get(0));\n",
+ "\n",
+ " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
+ " // web socket which is closed, not our websocket->open comm proxy.\n",
+ " ws_proxy.onopen();\n",
+ "\n",
+ " fig.parent_element = element.get(0);\n",
+ " fig.cell_info = mpl.find_output_cell(\"<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",
+ " var width = fig.canvas.width/mpl.ratio\n",
+ " fig.root.unbind('remove')\n",
+ "\n",
+ " // Update the output cell to use the data from the current canvas.\n",
+ " fig.push_to_output();\n",
+ " var dataURL = fig.canvas.toDataURL();\n",
+ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
+ " // the notebook keyboard shortcuts fail.\n",
+ " IPython.keyboard_manager.enable()\n",
+ " $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
+ " fig.close_ws(fig, msg);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.close_ws = function(fig, msg){\n",
+ " fig.send_message('closing', msg);\n",
+ " // fig.ws.close()\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
+ " // Turn the data on the canvas into data in the output cell.\n",
+ " var width = this.canvas.width/mpl.ratio\n",
+ " var dataURL = this.canvas.toDataURL();\n",
+ " this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\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",
+ " // select the cell after this one\n",
+ " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
+ " IPython.notebook.select(index + 1);\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " fig.ondownload(fig, null);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.find_output_cell = function(html_output) {\n",
+ " // Return the cell and output element which can be found *uniquely* in the notebook.\n",
+ " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
+ " // IPython event is triggered only after the cells have been serialised, which for\n",
+ " // our purposes (turning an active figure into a static one), is too late.\n",
+ " var cells = IPython.notebook.get_cells();\n",
+ " var ncells = cells.length;\n",
+ " for (var i=0; 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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\" width=\"640\">"
+ ],
+ "text/plain": [
+ "<IPython.core.display.HTML object>"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "live_plot('cheap_rgb', spline_s=0.001, live=False, save_svg='/tmp/raw_plot_cheap_rgb.svg')"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "* Go further than step 250 to capture some zeros beyond the red band to allow the spline fitter to do its job more properly\n",
+ "* Move the entire screen further down and further increase range to properly capture blue rolloff\n",
+ "* 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": 121,
+ "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": 122,
+ "metadata": {},
+ "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",
+ "\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",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " }\n",
+ "\n",
+ " this.imageObj.onload = function() {\n",
+ " if (fig.image_mode == 'full') {\n",
+ " // Full images could contain transparency (where diff images\n",
+ " // almost always do), so we need to clear the canvas so that\n",
+ " // there is no ghosting.\n",
+ " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
+ " }\n",
+ " fig.context.drawImage(fig.imageObj, 0, 0);\n",
+ " };\n",
+ "\n",
+ " this.imageObj.onunload = function() {\n",
+ " this.ws.close();\n",
+ " }\n",
+ "\n",
+ " this.ws.onmessage = this._make_on_message_function(this);\n",
+ "\n",
+ " this.ondownload = ondownload;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_header = function() {\n",
+ " var titlebar = $(\n",
+ " '<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 backingStore = this.context.backingStorePixelRatio ||\n",
+ "\tthis.context.webkitBackingStorePixelRatio ||\n",
+ "\tthis.context.mozBackingStorePixelRatio ||\n",
+ "\tthis.context.msBackingStorePixelRatio ||\n",
+ "\tthis.context.oBackingStorePixelRatio ||\n",
+ "\tthis.context.backingStorePixelRatio || 1;\n",
+ "\n",
+ " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
+ "\n",
+ " var rubberband = $('<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 * mpl.ratio);\n",
+ " canvas.attr('height', height * mpl.ratio);\n",
+ " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
+ "\n",
+ " rubberband.attr('width', width);\n",
+ " rubberband.attr('height', height);\n",
+ " }\n",
+ "\n",
+ " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
+ " // upon first draw.\n",
+ " this._resize_canvas(600, 600);\n",
+ "\n",
+ " // Disable right mouse context menu.\n",
+ " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
+ " return false;\n",
+ " });\n",
+ "\n",
+ " function set_focus () {\n",
+ " canvas.focus();\n",
+ " canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " window.setTimeout(set_focus, 100);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_toolbar = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var nav_element = $('<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'] / mpl.ratio;\n",
+ " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
+ " var x1 = msg['x1'] / mpl.ratio;\n",
+ " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
+ " x0 = Math.floor(x0) + 0.5;\n",
+ " y0 = Math.floor(y0) + 0.5;\n",
+ " x1 = Math.floor(x1) + 0.5;\n",
+ " y1 = Math.floor(y1) + 0.5;\n",
+ " var min_x = Math.min(x0, x1);\n",
+ " var min_y = Math.min(y0, y1);\n",
+ " var width = Math.abs(x1 - x0);\n",
+ " var height = Math.abs(y1 - y0);\n",
+ "\n",
+ " fig.rubberband_context.clearRect(\n",
+ " 0, 0, fig.canvas.width, fig.canvas.height);\n",
+ "\n",
+ " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
+ " // Updates the figure title.\n",
+ " fig.header.textContent = msg['label'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
+ " var cursor = msg['cursor'];\n",
+ " switch(cursor)\n",
+ " {\n",
+ " case 0:\n",
+ " cursor = 'pointer';\n",
+ " break;\n",
+ " case 1:\n",
+ " cursor = 'default';\n",
+ " break;\n",
+ " case 2:\n",
+ " cursor = 'crosshair';\n",
+ " break;\n",
+ " case 3:\n",
+ " cursor = 'move';\n",
+ " break;\n",
+ " }\n",
+ " fig.rubberband_canvas.style.cursor = cursor;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
+ " fig.message.textContent = msg['message'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
+ " // Request the server to send over a new figure.\n",
+ " fig.send_draw_message();\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
+ " fig.image_mode = msg['mode'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.updated_canvas_event = function() {\n",
+ " // Called whenever the canvas gets updated.\n",
+ " this.send_message(\"ack\", {});\n",
+ "}\n",
+ "\n",
+ "// A function to construct a web socket function for onmessage handling.\n",
+ "// Called in the figure constructor.\n",
+ "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
+ " return function socket_on_message(evt) {\n",
+ " if (evt.data instanceof Blob) {\n",
+ " /* FIXME: We get \"Resource interpreted as Image but\n",
+ " * transferred with MIME type text/plain:\" errors on\n",
+ " * Chrome. But how to set the MIME type? It doesn't seem\n",
+ " * to be part of the websocket stream */\n",
+ " evt.data.type = \"image/png\";\n",
+ "\n",
+ " /* Free the memory for the previous frames */\n",
+ " if (fig.imageObj.src) {\n",
+ " (window.URL || window.webkitURL).revokeObjectURL(\n",
+ " fig.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
+ " evt.data);\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
+ " fig.imageObj.src = evt.data;\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var msg = JSON.parse(evt.data);\n",
+ " var msg_type = msg['type'];\n",
+ "\n",
+ " // Call the \"handle_{type}\" callback, which takes\n",
+ " // the figure and JSON message as its only arguments.\n",
+ " try {\n",
+ " var callback = fig[\"handle_\" + msg_type];\n",
+ " } catch (e) {\n",
+ " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " if (callback) {\n",
+ " try {\n",
+ " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
+ " callback(fig, msg);\n",
+ " } catch (e) {\n",
+ " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
+ " }\n",
+ " }\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
+ "mpl.findpos = function(e) {\n",
+ " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
+ " var targ;\n",
+ " if (!e)\n",
+ " e = window.event;\n",
+ " if (e.target)\n",
+ " targ = e.target;\n",
+ " else if (e.srcElement)\n",
+ " targ = e.srcElement;\n",
+ " if (targ.nodeType == 3) // defeat Safari bug\n",
+ " targ = targ.parentNode;\n",
+ "\n",
+ " // jQuery normalizes the pageX and pageY\n",
+ " // pageX,Y are the mouse positions relative to the document\n",
+ " // offset() returns the position of the element relative to the document\n",
+ " var x = e.pageX - $(targ).offset().left;\n",
+ " var y = e.pageY - $(targ).offset().top;\n",
+ "\n",
+ " return {\"x\": x, \"y\": y};\n",
+ "};\n",
+ "\n",
+ "/*\n",
+ " * return a copy of an object with only non-object keys\n",
+ " * we need this to avoid circular references\n",
+ " * http://stackoverflow.com/a/24161582/3208463\n",
+ " */\n",
+ "function simpleKeys (original) {\n",
+ " return Object.keys(original).reduce(function (obj, key) {\n",
+ " if (typeof original[key] !== 'object')\n",
+ " obj[key] = original[key]\n",
+ " return obj;\n",
+ " }, {});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.mouse_event = function(event, name) {\n",
+ " var canvas_pos = mpl.findpos(event)\n",
+ "\n",
+ " if (name === 'button_press')\n",
+ " {\n",
+ " this.canvas.focus();\n",
+ " this.canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " var x = canvas_pos.x * mpl.ratio;\n",
+ " var y = canvas_pos.y * mpl.ratio;\n",
+ "\n",
+ " this.send_message(name, {x: x, y: y, button: event.button,\n",
+ " step: event.step,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ "\n",
+ " /* This prevents the web browser from automatically changing to\n",
+ " * the text insertion cursor when the button is pressed. We want\n",
+ " * to control all of the cursor setting manually through the\n",
+ " * 'cursor' event from matplotlib */\n",
+ " event.preventDefault();\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " // Handle any extra behaviour associated with a key event\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.key_event = function(event, name) {\n",
+ "\n",
+ " // Prevent repeat events\n",
+ " if (name == 'key_press')\n",
+ " {\n",
+ " if (event.which === this._key)\n",
+ " return;\n",
+ " else\n",
+ " this._key = event.which;\n",
+ " }\n",
+ " if (name == 'key_release')\n",
+ " this._key = null;\n",
+ "\n",
+ " var value = '';\n",
+ " if (event.ctrlKey && event.which != 17)\n",
+ " value += \"ctrl+\";\n",
+ " if (event.altKey && event.which != 18)\n",
+ " value += \"alt+\";\n",
+ " if (event.shiftKey && event.which != 16)\n",
+ " value += \"shift+\";\n",
+ "\n",
+ " value += 'k';\n",
+ " value += event.which.toString();\n",
+ "\n",
+ " this._key_event_extra(event, name);\n",
+ "\n",
+ " this.send_message(name, {key: value,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
+ " if (name == 'download') {\n",
+ " this.handle_save(this, null);\n",
+ " } else {\n",
+ " this.send_message(\"toolbar_button\", {name: name});\n",
+ " }\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
+ " this.message.textContent = tooltip;\n",
+ "};\n",
+ "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
+ "\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "\n",
+ "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
+ " // Create a \"websocket\"-like object which calls the given IPython comm\n",
+ " // object with the appropriate methods. Currently this is a non binary\n",
+ " // socket, so there is still some room for performance tuning.\n",
+ " var ws = {};\n",
+ "\n",
+ " ws.close = function() {\n",
+ " comm.close()\n",
+ " };\n",
+ " ws.send = function(m) {\n",
+ " //console.log('sending', m);\n",
+ " comm.send(m);\n",
+ " };\n",
+ " // Register the callback with on_msg.\n",
+ " comm.on_msg(function(msg) {\n",
+ " //console.log('receiving', msg['content']['data'], msg);\n",
+ " // Pass the mpl event to the overriden (by mpl) onmessage function.\n",
+ " ws.onmessage(msg['content']['data'])\n",
+ " });\n",
+ " return ws;\n",
+ "}\n",
+ "\n",
+ "mpl.mpl_figure_comm = function(comm, msg) {\n",
+ " // This is the function which gets called when the mpl process\n",
+ " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
+ "\n",
+ " var id = msg.content.data.id;\n",
+ " // Get hold of the div created by the display call when the Comm\n",
+ " // socket was opened in Python.\n",
+ " var element = $(\"#\" + id);\n",
+ " var ws_proxy = comm_websocket_adapter(comm)\n",
+ "\n",
+ " function ondownload(figure, format) {\n",
+ " window.open(figure.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " var fig = new mpl.figure(id, ws_proxy,\n",
+ " ondownload,\n",
+ " element.get(0));\n",
+ "\n",
+ " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
+ " // web socket which is closed, not our websocket->open comm proxy.\n",
+ " ws_proxy.onopen();\n",
+ "\n",
+ " fig.parent_element = element.get(0);\n",
+ " fig.cell_info = mpl.find_output_cell(\"<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",
+ " var width = fig.canvas.width/mpl.ratio\n",
+ " fig.root.unbind('remove')\n",
+ "\n",
+ " // Update the output cell to use the data from the current canvas.\n",
+ " fig.push_to_output();\n",
+ " var dataURL = fig.canvas.toDataURL();\n",
+ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
+ " // the notebook keyboard shortcuts fail.\n",
+ " IPython.keyboard_manager.enable()\n",
+ " $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
+ " fig.close_ws(fig, msg);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.close_ws = function(fig, msg){\n",
+ " fig.send_message('closing', msg);\n",
+ " // fig.ws.close()\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
+ " // Turn the data on the canvas into data in the output cell.\n",
+ " var width = this.canvas.width/mpl.ratio\n",
+ " var dataURL = this.canvas.toDataURL();\n",
+ " this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\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",
+ " // select the cell after this one\n",
+ " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
+ " IPython.notebook.select(index + 1);\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " fig.ondownload(fig, null);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.find_output_cell = function(html_output) {\n",
+ " // Return the cell and output element which can be found *uniquely* in the notebook.\n",
+ " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
+ " // IPython event is triggered only after the cells have been serialised, which for\n",
+ " // our purposes (turning an active figure into a static one), is too late.\n",
+ " var cells = IPython.notebook.get_cells();\n",
+ " var ncells = cells.length;\n",
+ " for (var i=0; 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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\" width=\"640\">"
+ ],
+ "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": 97,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "def plot_rgb_calibrated(data_rgb, spline_s=1, save_svg=None):\n",
+ " fig, ax = plt.subplots(1, 1)\n",
+ "\n",
+ " for steps, values, stdev in data_rgb:\n",
+ " ax.errorbar(steps, values, yerr=stdev, color='#ffd2e9', zorder=1)\n",
+ " \n",
+ " spline = inter.UnivariateSpline(steps, values, s=spline_s)\n",
+ " ax.plot(steps, spline(steps), color='#fe3ea0', zorder=2)\n",
+ " \n",
+ " ax.spines['top'].set_visible(False)\n",
+ " ax.spines['right'].set_visible(False)\n",
+ " ax.spines['bottom'].set_color('#08bdf9')\n",
+ " ax.spines['left'].set_color('#08bdf9')\n",
+ " ax.tick_params(axis='x', colors='#01769D')\n",
+ " ax.tick_params(axis='y', colors='#01769D')\n",
+ " ax.xaxis.label.set_color('#01769D')\n",
+ " ax.yaxis.label.set_color('#01769D')\n",
+ " ax.grid(color='#08bdf9', linestyle=':')\n",
+ " \n",
+ " ax.set_xlim([380, 720])\n",
+ " ax.set_xlabel('$\\lambda\\;[nm]$')\n",
+ " ax.set_ylabel('$I_{pd}\\;[nA]$')\n",
+ " \n",
+ " if save_svg:\n",
+ " fig.savefig(save_svg)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 127,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "application/javascript": [
+ "/* Put everything inside the global mpl namespace */\n",
+ "window.mpl = {};\n",
+ "\n",
+ "\n",
+ "mpl.get_websocket_type = function() {\n",
+ " if (typeof(WebSocket) !== 'undefined') {\n",
+ " return WebSocket;\n",
+ " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
+ " return MozWebSocket;\n",
+ " } else {\n",
+ " alert('Your browser does not have WebSocket support.' +\n",
+ " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
+ " 'Firefox 4 and 5 are also supported but you ' +\n",
+ " 'have to enable WebSockets in about:config.');\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
+ " this.id = figure_id;\n",
+ "\n",
+ " this.ws = websocket;\n",
+ "\n",
+ " this.supports_binary = (this.ws.binaryType != undefined);\n",
+ "\n",
+ " if (!this.supports_binary) {\n",
+ " var warnings = document.getElementById(\"mpl-warnings\");\n",
+ " if (warnings) {\n",
+ " warnings.style.display = 'block';\n",
+ " warnings.textContent = (\n",
+ " \"This browser does not support binary websocket messages. \" +\n",
+ " \"Performance may be slow.\");\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " this.imageObj = new Image();\n",
+ "\n",
+ " this.context = undefined;\n",
+ " this.message = undefined;\n",
+ " this.canvas = undefined;\n",
+ " this.rubberband_canvas = undefined;\n",
+ " this.rubberband_context = undefined;\n",
+ " this.format_dropdown = undefined;\n",
+ "\n",
+ " this.image_mode = 'full';\n",
+ "\n",
+ " this.root = $('<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",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " }\n",
+ "\n",
+ " this.imageObj.onload = function() {\n",
+ " if (fig.image_mode == 'full') {\n",
+ " // Full images could contain transparency (where diff images\n",
+ " // almost always do), so we need to clear the canvas so that\n",
+ " // there is no ghosting.\n",
+ " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
+ " }\n",
+ " fig.context.drawImage(fig.imageObj, 0, 0);\n",
+ " };\n",
+ "\n",
+ " this.imageObj.onunload = function() {\n",
+ " this.ws.close();\n",
+ " }\n",
+ "\n",
+ " this.ws.onmessage = this._make_on_message_function(this);\n",
+ "\n",
+ " this.ondownload = ondownload;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_header = function() {\n",
+ " var titlebar = $(\n",
+ " '<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 backingStore = this.context.backingStorePixelRatio ||\n",
+ "\tthis.context.webkitBackingStorePixelRatio ||\n",
+ "\tthis.context.mozBackingStorePixelRatio ||\n",
+ "\tthis.context.msBackingStorePixelRatio ||\n",
+ "\tthis.context.oBackingStorePixelRatio ||\n",
+ "\tthis.context.backingStorePixelRatio || 1;\n",
+ "\n",
+ " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
+ "\n",
+ " var rubberband = $('<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 * mpl.ratio);\n",
+ " canvas.attr('height', height * mpl.ratio);\n",
+ " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
+ "\n",
+ " rubberband.attr('width', width);\n",
+ " rubberband.attr('height', height);\n",
+ " }\n",
+ "\n",
+ " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
+ " // upon first draw.\n",
+ " this._resize_canvas(600, 600);\n",
+ "\n",
+ " // Disable right mouse context menu.\n",
+ " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
+ " return false;\n",
+ " });\n",
+ "\n",
+ " function set_focus () {\n",
+ " canvas.focus();\n",
+ " canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " window.setTimeout(set_focus, 100);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_toolbar = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var nav_element = $('<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'] / mpl.ratio;\n",
+ " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
+ " var x1 = msg['x1'] / mpl.ratio;\n",
+ " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
+ " x0 = Math.floor(x0) + 0.5;\n",
+ " y0 = Math.floor(y0) + 0.5;\n",
+ " x1 = Math.floor(x1) + 0.5;\n",
+ " y1 = Math.floor(y1) + 0.5;\n",
+ " var min_x = Math.min(x0, x1);\n",
+ " var min_y = Math.min(y0, y1);\n",
+ " var width = Math.abs(x1 - x0);\n",
+ " var height = Math.abs(y1 - y0);\n",
+ "\n",
+ " fig.rubberband_context.clearRect(\n",
+ " 0, 0, fig.canvas.width, fig.canvas.height);\n",
+ "\n",
+ " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
+ " // Updates the figure title.\n",
+ " fig.header.textContent = msg['label'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
+ " var cursor = msg['cursor'];\n",
+ " switch(cursor)\n",
+ " {\n",
+ " case 0:\n",
+ " cursor = 'pointer';\n",
+ " break;\n",
+ " case 1:\n",
+ " cursor = 'default';\n",
+ " break;\n",
+ " case 2:\n",
+ " cursor = 'crosshair';\n",
+ " break;\n",
+ " case 3:\n",
+ " cursor = 'move';\n",
+ " break;\n",
+ " }\n",
+ " fig.rubberband_canvas.style.cursor = cursor;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
+ " fig.message.textContent = msg['message'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
+ " // Request the server to send over a new figure.\n",
+ " fig.send_draw_message();\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
+ " fig.image_mode = msg['mode'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.updated_canvas_event = function() {\n",
+ " // Called whenever the canvas gets updated.\n",
+ " this.send_message(\"ack\", {});\n",
+ "}\n",
+ "\n",
+ "// A function to construct a web socket function for onmessage handling.\n",
+ "// Called in the figure constructor.\n",
+ "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
+ " return function socket_on_message(evt) {\n",
+ " if (evt.data instanceof Blob) {\n",
+ " /* FIXME: We get \"Resource interpreted as Image but\n",
+ " * transferred with MIME type text/plain:\" errors on\n",
+ " * Chrome. But how to set the MIME type? It doesn't seem\n",
+ " * to be part of the websocket stream */\n",
+ " evt.data.type = \"image/png\";\n",
+ "\n",
+ " /* Free the memory for the previous frames */\n",
+ " if (fig.imageObj.src) {\n",
+ " (window.URL || window.webkitURL).revokeObjectURL(\n",
+ " fig.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
+ " evt.data);\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
+ " fig.imageObj.src = evt.data;\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var msg = JSON.parse(evt.data);\n",
+ " var msg_type = msg['type'];\n",
+ "\n",
+ " // Call the \"handle_{type}\" callback, which takes\n",
+ " // the figure and JSON message as its only arguments.\n",
+ " try {\n",
+ " var callback = fig[\"handle_\" + msg_type];\n",
+ " } catch (e) {\n",
+ " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " if (callback) {\n",
+ " try {\n",
+ " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
+ " callback(fig, msg);\n",
+ " } catch (e) {\n",
+ " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
+ " }\n",
+ " }\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
+ "mpl.findpos = function(e) {\n",
+ " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
+ " var targ;\n",
+ " if (!e)\n",
+ " e = window.event;\n",
+ " if (e.target)\n",
+ " targ = e.target;\n",
+ " else if (e.srcElement)\n",
+ " targ = e.srcElement;\n",
+ " if (targ.nodeType == 3) // defeat Safari bug\n",
+ " targ = targ.parentNode;\n",
+ "\n",
+ " // jQuery normalizes the pageX and pageY\n",
+ " // pageX,Y are the mouse positions relative to the document\n",
+ " // offset() returns the position of the element relative to the document\n",
+ " var x = e.pageX - $(targ).offset().left;\n",
+ " var y = e.pageY - $(targ).offset().top;\n",
+ "\n",
+ " return {\"x\": x, \"y\": y};\n",
+ "};\n",
+ "\n",
+ "/*\n",
+ " * return a copy of an object with only non-object keys\n",
+ " * we need this to avoid circular references\n",
+ " * http://stackoverflow.com/a/24161582/3208463\n",
+ " */\n",
+ "function simpleKeys (original) {\n",
+ " return Object.keys(original).reduce(function (obj, key) {\n",
+ " if (typeof original[key] !== 'object')\n",
+ " obj[key] = original[key]\n",
+ " return obj;\n",
+ " }, {});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.mouse_event = function(event, name) {\n",
+ " var canvas_pos = mpl.findpos(event)\n",
+ "\n",
+ " if (name === 'button_press')\n",
+ " {\n",
+ " this.canvas.focus();\n",
+ " this.canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " var x = canvas_pos.x * mpl.ratio;\n",
+ " var y = canvas_pos.y * mpl.ratio;\n",
+ "\n",
+ " this.send_message(name, {x: x, y: y, button: event.button,\n",
+ " step: event.step,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ "\n",
+ " /* This prevents the web browser from automatically changing to\n",
+ " * the text insertion cursor when the button is pressed. We want\n",
+ " * to control all of the cursor setting manually through the\n",
+ " * 'cursor' event from matplotlib */\n",
+ " event.preventDefault();\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " // Handle any extra behaviour associated with a key event\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.key_event = function(event, name) {\n",
+ "\n",
+ " // Prevent repeat events\n",
+ " if (name == 'key_press')\n",
+ " {\n",
+ " if (event.which === this._key)\n",
+ " return;\n",
+ " else\n",
+ " this._key = event.which;\n",
+ " }\n",
+ " if (name == 'key_release')\n",
+ " this._key = null;\n",
+ "\n",
+ " var value = '';\n",
+ " if (event.ctrlKey && event.which != 17)\n",
+ " value += \"ctrl+\";\n",
+ " if (event.altKey && event.which != 18)\n",
+ " value += \"alt+\";\n",
+ " if (event.shiftKey && event.which != 16)\n",
+ " value += \"shift+\";\n",
+ "\n",
+ " value += 'k';\n",
+ " value += event.which.toString();\n",
+ "\n",
+ " this._key_event_extra(event, name);\n",
+ "\n",
+ " this.send_message(name, {key: value,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
+ " if (name == 'download') {\n",
+ " this.handle_save(this, null);\n",
+ " } else {\n",
+ " this.send_message(\"toolbar_button\", {name: name});\n",
+ " }\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
+ " this.message.textContent = tooltip;\n",
+ "};\n",
+ "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
+ "\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "\n",
+ "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
+ " // Create a \"websocket\"-like object which calls the given IPython comm\n",
+ " // object with the appropriate methods. Currently this is a non binary\n",
+ " // socket, so there is still some room for performance tuning.\n",
+ " var ws = {};\n",
+ "\n",
+ " ws.close = function() {\n",
+ " comm.close()\n",
+ " };\n",
+ " ws.send = function(m) {\n",
+ " //console.log('sending', m);\n",
+ " comm.send(m);\n",
+ " };\n",
+ " // Register the callback with on_msg.\n",
+ " comm.on_msg(function(msg) {\n",
+ " //console.log('receiving', msg['content']['data'], msg);\n",
+ " // Pass the mpl event to the overriden (by mpl) onmessage function.\n",
+ " ws.onmessage(msg['content']['data'])\n",
+ " });\n",
+ " return ws;\n",
+ "}\n",
+ "\n",
+ "mpl.mpl_figure_comm = function(comm, msg) {\n",
+ " // This is the function which gets called when the mpl process\n",
+ " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
+ "\n",
+ " var id = msg.content.data.id;\n",
+ " // Get hold of the div created by the display call when the Comm\n",
+ " // socket was opened in Python.\n",
+ " var element = $(\"#\" + id);\n",
+ " var ws_proxy = comm_websocket_adapter(comm)\n",
+ "\n",
+ " function ondownload(figure, format) {\n",
+ " window.open(figure.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " var fig = new mpl.figure(id, ws_proxy,\n",
+ " ondownload,\n",
+ " element.get(0));\n",
+ "\n",
+ " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
+ " // web socket which is closed, not our websocket->open comm proxy.\n",
+ " ws_proxy.onopen();\n",
+ "\n",
+ " fig.parent_element = element.get(0);\n",
+ " fig.cell_info = mpl.find_output_cell(\"<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",
+ " var width = fig.canvas.width/mpl.ratio\n",
+ " fig.root.unbind('remove')\n",
+ "\n",
+ " // Update the output cell to use the data from the current canvas.\n",
+ " fig.push_to_output();\n",
+ " var dataURL = fig.canvas.toDataURL();\n",
+ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
+ " // the notebook keyboard shortcuts fail.\n",
+ " IPython.keyboard_manager.enable()\n",
+ " $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
+ " fig.close_ws(fig, msg);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.close_ws = function(fig, msg){\n",
+ " fig.send_message('closing', msg);\n",
+ " // fig.ws.close()\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
+ " // Turn the data on the canvas into data in the output cell.\n",
+ " var width = this.canvas.width/mpl.ratio\n",
+ " var dataURL = this.canvas.toDataURL();\n",
+ " this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\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",
+ " // select the cell after this one\n",
+ " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
+ " IPython.notebook.select(index + 1);\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " fig.ondownload(fig, null);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.find_output_cell = function(html_output) {\n",
+ " // Return the cell and output element which can be found *uniquely* in the notebook.\n",
+ " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
+ " // IPython event is triggered only after the cells have been serialised, which for\n",
+ " // our purposes (turning an active figure into a static one), is too late.\n",
+ " var cells = IPython.notebook.get_cells();\n",
+ " var ncells = cells.length;\n",
+ " for (var i=0; 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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\" width=\"640\">"
+ ],
+ "text/plain": [
+ "<IPython.core.display.HTML object>"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "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), color='#fe3ea0')\n",
+ "ax.set_xlim([380, 720])\n",
+ "\n",
+ "ax.spines['top'].set_visible(False)\n",
+ "ax.spines['right'].set_visible(False)\n",
+ "ax.spines['bottom'].set_color('#08bdf9')\n",
+ "ax.spines['left'].set_color('#08bdf9')\n",
+ "ax.tick_params(axis='x', colors='#01769D')\n",
+ "ax.tick_params(axis='y', colors='#01769D')\n",
+ "ax.xaxis.label.set_color('#01769D')\n",
+ "ax.yaxis.label.set_color('#01769D')\n",
+ "ax.grid(color='#08bdf9', linestyle=':')\n",
+ "\n",
+ "ax.set_xlim([380, 720])\n",
+ "ax.set_xlabel('$\\lambda\\;[nm]$')\n",
+ "ax.set_ylabel('$S_{rel,820nm}\\;[1]$')\n",
+ "fig.savefig('/tmp/photodiode_sensitivity.svg')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 112,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Poly for red channel\n",
+ " \n",
+ "-0.0001301 x + 0.4955\n",
+ "Poly for green channel\n",
+ " \n",
+ "-3.846e-05 x + 0.4401\n",
+ "Poly for blue channel\n",
+ " \n",
+ "-0.000189 x + 0.5092\n"
+ ]
+ },
+ {
+ "data": {
+ "application/javascript": [
+ "/* Put everything inside the global mpl namespace */\n",
+ "window.mpl = {};\n",
+ "\n",
+ "\n",
+ "mpl.get_websocket_type = function() {\n",
+ " if (typeof(WebSocket) !== 'undefined') {\n",
+ " return WebSocket;\n",
+ " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
+ " return MozWebSocket;\n",
+ " } else {\n",
+ " alert('Your browser does not have WebSocket support.' +\n",
+ " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
+ " 'Firefox 4 and 5 are also supported but you ' +\n",
+ " 'have to enable WebSockets in about:config.');\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
+ " this.id = figure_id;\n",
+ "\n",
+ " this.ws = websocket;\n",
+ "\n",
+ " this.supports_binary = (this.ws.binaryType != undefined);\n",
+ "\n",
+ " if (!this.supports_binary) {\n",
+ " var warnings = document.getElementById(\"mpl-warnings\");\n",
+ " if (warnings) {\n",
+ " warnings.style.display = 'block';\n",
+ " warnings.textContent = (\n",
+ " \"This browser does not support binary websocket messages. \" +\n",
+ " \"Performance may be slow.\");\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " this.imageObj = new Image();\n",
+ "\n",
+ " this.context = undefined;\n",
+ " this.message = undefined;\n",
+ " this.canvas = undefined;\n",
+ " this.rubberband_canvas = undefined;\n",
+ " this.rubberband_context = undefined;\n",
+ " this.format_dropdown = undefined;\n",
+ "\n",
+ " this.image_mode = 'full';\n",
+ "\n",
+ " this.root = $('<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",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " }\n",
+ "\n",
+ " this.imageObj.onload = function() {\n",
+ " if (fig.image_mode == 'full') {\n",
+ " // Full images could contain transparency (where diff images\n",
+ " // almost always do), so we need to clear the canvas so that\n",
+ " // there is no ghosting.\n",
+ " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
+ " }\n",
+ " fig.context.drawImage(fig.imageObj, 0, 0);\n",
+ " };\n",
+ "\n",
+ " this.imageObj.onunload = function() {\n",
+ " this.ws.close();\n",
+ " }\n",
+ "\n",
+ " this.ws.onmessage = this._make_on_message_function(this);\n",
+ "\n",
+ " this.ondownload = ondownload;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_header = function() {\n",
+ " var titlebar = $(\n",
+ " '<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 backingStore = this.context.backingStorePixelRatio ||\n",
+ "\tthis.context.webkitBackingStorePixelRatio ||\n",
+ "\tthis.context.mozBackingStorePixelRatio ||\n",
+ "\tthis.context.msBackingStorePixelRatio ||\n",
+ "\tthis.context.oBackingStorePixelRatio ||\n",
+ "\tthis.context.backingStorePixelRatio || 1;\n",
+ "\n",
+ " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
+ "\n",
+ " var rubberband = $('<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 * mpl.ratio);\n",
+ " canvas.attr('height', height * mpl.ratio);\n",
+ " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
+ "\n",
+ " rubberband.attr('width', width);\n",
+ " rubberband.attr('height', height);\n",
+ " }\n",
+ "\n",
+ " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
+ " // upon first draw.\n",
+ " this._resize_canvas(600, 600);\n",
+ "\n",
+ " // Disable right mouse context menu.\n",
+ " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
+ " return false;\n",
+ " });\n",
+ "\n",
+ " function set_focus () {\n",
+ " canvas.focus();\n",
+ " canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " window.setTimeout(set_focus, 100);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_toolbar = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var nav_element = $('<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'] / mpl.ratio;\n",
+ " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
+ " var x1 = msg['x1'] / mpl.ratio;\n",
+ " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
+ " x0 = Math.floor(x0) + 0.5;\n",
+ " y0 = Math.floor(y0) + 0.5;\n",
+ " x1 = Math.floor(x1) + 0.5;\n",
+ " y1 = Math.floor(y1) + 0.5;\n",
+ " var min_x = Math.min(x0, x1);\n",
+ " var min_y = Math.min(y0, y1);\n",
+ " var width = Math.abs(x1 - x0);\n",
+ " var height = Math.abs(y1 - y0);\n",
+ "\n",
+ " fig.rubberband_context.clearRect(\n",
+ " 0, 0, fig.canvas.width, fig.canvas.height);\n",
+ "\n",
+ " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
+ " // Updates the figure title.\n",
+ " fig.header.textContent = msg['label'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
+ " var cursor = msg['cursor'];\n",
+ " switch(cursor)\n",
+ " {\n",
+ " case 0:\n",
+ " cursor = 'pointer';\n",
+ " break;\n",
+ " case 1:\n",
+ " cursor = 'default';\n",
+ " break;\n",
+ " case 2:\n",
+ " cursor = 'crosshair';\n",
+ " break;\n",
+ " case 3:\n",
+ " cursor = 'move';\n",
+ " break;\n",
+ " }\n",
+ " fig.rubberband_canvas.style.cursor = cursor;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
+ " fig.message.textContent = msg['message'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
+ " // Request the server to send over a new figure.\n",
+ " fig.send_draw_message();\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
+ " fig.image_mode = msg['mode'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.updated_canvas_event = function() {\n",
+ " // Called whenever the canvas gets updated.\n",
+ " this.send_message(\"ack\", {});\n",
+ "}\n",
+ "\n",
+ "// A function to construct a web socket function for onmessage handling.\n",
+ "// Called in the figure constructor.\n",
+ "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
+ " return function socket_on_message(evt) {\n",
+ " if (evt.data instanceof Blob) {\n",
+ " /* FIXME: We get \"Resource interpreted as Image but\n",
+ " * transferred with MIME type text/plain:\" errors on\n",
+ " * Chrome. But how to set the MIME type? It doesn't seem\n",
+ " * to be part of the websocket stream */\n",
+ " evt.data.type = \"image/png\";\n",
+ "\n",
+ " /* Free the memory for the previous frames */\n",
+ " if (fig.imageObj.src) {\n",
+ " (window.URL || window.webkitURL).revokeObjectURL(\n",
+ " fig.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
+ " evt.data);\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
+ " fig.imageObj.src = evt.data;\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var msg = JSON.parse(evt.data);\n",
+ " var msg_type = msg['type'];\n",
+ "\n",
+ " // Call the \"handle_{type}\" callback, which takes\n",
+ " // the figure and JSON message as its only arguments.\n",
+ " try {\n",
+ " var callback = fig[\"handle_\" + msg_type];\n",
+ " } catch (e) {\n",
+ " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " if (callback) {\n",
+ " try {\n",
+ " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
+ " callback(fig, msg);\n",
+ " } catch (e) {\n",
+ " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
+ " }\n",
+ " }\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
+ "mpl.findpos = function(e) {\n",
+ " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
+ " var targ;\n",
+ " if (!e)\n",
+ " e = window.event;\n",
+ " if (e.target)\n",
+ " targ = e.target;\n",
+ " else if (e.srcElement)\n",
+ " targ = e.srcElement;\n",
+ " if (targ.nodeType == 3) // defeat Safari bug\n",
+ " targ = targ.parentNode;\n",
+ "\n",
+ " // jQuery normalizes the pageX and pageY\n",
+ " // pageX,Y are the mouse positions relative to the document\n",
+ " // offset() returns the position of the element relative to the document\n",
+ " var x = e.pageX - $(targ).offset().left;\n",
+ " var y = e.pageY - $(targ).offset().top;\n",
+ "\n",
+ " return {\"x\": x, \"y\": y};\n",
+ "};\n",
+ "\n",
+ "/*\n",
+ " * return a copy of an object with only non-object keys\n",
+ " * we need this to avoid circular references\n",
+ " * http://stackoverflow.com/a/24161582/3208463\n",
+ " */\n",
+ "function simpleKeys (original) {\n",
+ " return Object.keys(original).reduce(function (obj, key) {\n",
+ " if (typeof original[key] !== 'object')\n",
+ " obj[key] = original[key]\n",
+ " return obj;\n",
+ " }, {});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.mouse_event = function(event, name) {\n",
+ " var canvas_pos = mpl.findpos(event)\n",
+ "\n",
+ " if (name === 'button_press')\n",
+ " {\n",
+ " this.canvas.focus();\n",
+ " this.canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " var x = canvas_pos.x * mpl.ratio;\n",
+ " var y = canvas_pos.y * mpl.ratio;\n",
+ "\n",
+ " this.send_message(name, {x: x, y: y, button: event.button,\n",
+ " step: event.step,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ "\n",
+ " /* This prevents the web browser from automatically changing to\n",
+ " * the text insertion cursor when the button is pressed. We want\n",
+ " * to control all of the cursor setting manually through the\n",
+ " * 'cursor' event from matplotlib */\n",
+ " event.preventDefault();\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " // Handle any extra behaviour associated with a key event\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.key_event = function(event, name) {\n",
+ "\n",
+ " // Prevent repeat events\n",
+ " if (name == 'key_press')\n",
+ " {\n",
+ " if (event.which === this._key)\n",
+ " return;\n",
+ " else\n",
+ " this._key = event.which;\n",
+ " }\n",
+ " if (name == 'key_release')\n",
+ " this._key = null;\n",
+ "\n",
+ " var value = '';\n",
+ " if (event.ctrlKey && event.which != 17)\n",
+ " value += \"ctrl+\";\n",
+ " if (event.altKey && event.which != 18)\n",
+ " value += \"alt+\";\n",
+ " if (event.shiftKey && event.which != 16)\n",
+ " value += \"shift+\";\n",
+ "\n",
+ " value += 'k';\n",
+ " value += event.which.toString();\n",
+ "\n",
+ " this._key_event_extra(event, name);\n",
+ "\n",
+ " this.send_message(name, {key: value,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
+ " if (name == 'download') {\n",
+ " this.handle_save(this, null);\n",
+ " } else {\n",
+ " this.send_message(\"toolbar_button\", {name: name});\n",
+ " }\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
+ " this.message.textContent = tooltip;\n",
+ "};\n",
+ "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
+ "\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "\n",
+ "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
+ " // Create a \"websocket\"-like object which calls the given IPython comm\n",
+ " // object with the appropriate methods. Currently this is a non binary\n",
+ " // socket, so there is still some room for performance tuning.\n",
+ " var ws = {};\n",
+ "\n",
+ " ws.close = function() {\n",
+ " comm.close()\n",
+ " };\n",
+ " ws.send = function(m) {\n",
+ " //console.log('sending', m);\n",
+ " comm.send(m);\n",
+ " };\n",
+ " // Register the callback with on_msg.\n",
+ " comm.on_msg(function(msg) {\n",
+ " //console.log('receiving', msg['content']['data'], msg);\n",
+ " // Pass the mpl event to the overriden (by mpl) onmessage function.\n",
+ " ws.onmessage(msg['content']['data'])\n",
+ " });\n",
+ " return ws;\n",
+ "}\n",
+ "\n",
+ "mpl.mpl_figure_comm = function(comm, msg) {\n",
+ " // This is the function which gets called when the mpl process\n",
+ " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
+ "\n",
+ " var id = msg.content.data.id;\n",
+ " // Get hold of the div created by the display call when the Comm\n",
+ " // socket was opened in Python.\n",
+ " var element = $(\"#\" + id);\n",
+ " var ws_proxy = comm_websocket_adapter(comm)\n",
+ "\n",
+ " function ondownload(figure, format) {\n",
+ " window.open(figure.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " var fig = new mpl.figure(id, ws_proxy,\n",
+ " ondownload,\n",
+ " element.get(0));\n",
+ "\n",
+ " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
+ " // web socket which is closed, not our websocket->open comm proxy.\n",
+ " ws_proxy.onopen();\n",
+ "\n",
+ " fig.parent_element = element.get(0);\n",
+ " fig.cell_info = mpl.find_output_cell(\"<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",
+ " var width = fig.canvas.width/mpl.ratio\n",
+ " fig.root.unbind('remove')\n",
+ "\n",
+ " // Update the output cell to use the data from the current canvas.\n",
+ " fig.push_to_output();\n",
+ " var dataURL = fig.canvas.toDataURL();\n",
+ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
+ " // the notebook keyboard shortcuts fail.\n",
+ " IPython.keyboard_manager.enable()\n",
+ " $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
+ " fig.close_ws(fig, msg);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.close_ws = function(fig, msg){\n",
+ " fig.send_message('closing', msg);\n",
+ " // fig.ws.close()\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
+ " // Turn the data on the canvas into data in the output cell.\n",
+ " var width = this.canvas.width/mpl.ratio\n",
+ " var dataURL = this.canvas.toDataURL();\n",
+ " this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\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",
+ " // select the cell after this one\n",
+ " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
+ " IPython.notebook.select(index + 1);\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " fig.ondownload(fig, null);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.find_output_cell = function(html_output) {\n",
+ " // Return the cell and output element which can be found *uniquely* in the notebook.\n",
+ " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
+ " // IPython event is triggered only after the cells have been serialised, which for\n",
+ " // our purposes (turning an active figure into a static one), is too late.\n",
+ " var cells = IPython.notebook.get_cells();\n",
+ " var ncells = cells.length;\n",
+ " for (var i=0; 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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\" width=\"640\">"
+ ],
+ "text/plain": [
+ "<IPython.core.display.HTML object>"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "captures = find_captures('cheap_rgb')\n",
+ "\n",
+ "# Approximate bands of interest for R, G and B channelsfor offset and stray light correction.\n",
+ "bands = {\n",
+ " 'red': (260,410), # [step]\n",
+ " 'green': (150,330),\n",
+ " 'blue': (100,260)\n",
+ "}\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 = {'red': 623, 'green': 518, 'blue': 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",
+ "transimpedance = 630e6 # Ohms.\n",
+ "\n",
+ "poly_degree = 1 # degree of polynomial for stray light and offset correction. Should be 1 or 2.\n",
+ "\n",
+ "#remove_thresh = 10.0 # [V] standard deviation delta threshold for outlier removal\n",
+ "\n",
+ "# ---\n",
+ "data_rgb = {}\n",
+ "for capture_id, color, gain in captures:\n",
+ " # Load this channel from the database\n",
+ " steps, values, stdev = load_run(capture_id, gain)\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",
+ " l, r = bands[color]\n",
+ " idxs = (steps < l) | (steps > r)\n",
+ " poly = np.poly1d(np.polyfit(steps[idxs], values[idxs], poly_degree))\n",
+ " print('Poly for', color, 'channel')\n",
+ " print(poly)\n",
+ " values -= poly(steps)\n",
+ " \n",
+ " data_rgb[color] = (steps, values, stdev)\n",
+ "\n",
+ "\n",
+ "# Produce a first estimate for wavelength scaling. Use the short-wavelength edge of the blue band and the red peak\n",
+ "# for this, as both can be assumed to remain stable even after photodiode response compensation. Then apply photodiode\n",
+ "# response compensation and do another, second round of wavelength scaling estimation but this time using all three\n",
+ "# peaks and a proper least-squares fit.\n",
+ "peaks = { color: x[np.argmax(y)] for color, (x, y, σ2) in data_rgb.items() }\n",
+ "edgesl = { color: x[np.argmax(y > y_edge_min)] for color, (x, y, σ2) in data_rgb.items() }\n",
+ "\n",
+ "Λ_est = np.poly1d(np.polyfit([edgesl['blue'], peaks['red']], [λ_be, λ_led['red']], 1))\n",
+ "\n",
+ "data_tmp = { color: (x, Λ_est(x), y, σ2) for color, (x, y, σ2) in data_rgb.items() }\n",
+ "data_tmp = { color: (x, λ, y/Λ_sfh2701(λ), σ2) for color, (x, λ, y, σ2) in data_tmp.items() }\n",
+ "# Limit wavelength range\n",
+ "data_tmp = { color: (x[λ > 380], λ[λ > 380], y[λ > 380], σ2[λ > 380]) for color, (x, λ, y, σ2) in data_tmp.items() }\n",
+ "\n",
+ "# Calibrate wavelength axis using assumed peaks for r, g and b. Use least-squares polyfit for getting coefficients.\n",
+ "peaks = { color: x[np.argmax(y)] for color, (x, λ, y, σ2) in data_tmp.items() }\n",
+ "Λ = np.poly1d(np.polyfit(\n",
+ " [peaks['red'], peaks['green'], peaks['blue']],\n",
+ " [λ_led['red'], λ_led['green'], λ_led['blue']], 1))\n",
+ "\n",
+ "data_rgb = { color: (Λ(x), y, σ2) for color, (x, y, σ2) in data_rgb.items() }\n",
+ "data_rgb = { color: (λ, y/Λ_sfh2701(λ), σ2) for color, (λ, y, σ2) in data_rgb.items() }\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 = { color: (λ[λ > 380], y[λ > 380], σ2[λ > 380]) for color, (λ, y, σ2) in data_rgb.items() }\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",
+ "# Convert amplitude data to current in nanoampère\n",
+ "data_rgb = { color: (λ, y/transimpedance / 1e-9, σ2/transimpedance / 1e-9) for color, (λ, y, σ2) in data_rgb.items() }\n",
+ "\n",
+ "plot_rgb_calibrated(data_rgb.values(), spline_s=0.005, save_svg='/tmp/processed_plot_cheap_rgb.svg')"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 114,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "# CIE XYZ Color matching functions from http://cvrl.ioo.ucl.ac.uk/\n",
+ "# rows are: λ[nm], x, y, z\n",
+ "CMFs = { fn[:-4]: np.genfromtxt(fn, delimiter=',')\n",
+ " for fn in ['cie_xyz_1931.csv', 'cie_xyz_judd_1951.csv', 'cie_xyz_judd_vos_1978.csv'] }\n",
+ "CMFs = { name: np.hstack([inter.interp1d(d[:,0], d[:,i]) for i in range(1,4)])\n",
+ " for name, d in CMFs.items() }"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 119,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "def integrate_tristimulus_response(data, channels=('red', 'green', 'blue'), colorspace='cie_xyz_1931'):\n",
+ " a = np.array([[\n",
+ " integrate.simps(\n",
+ " np.multiply(CMFs[colorspace][j](data[color][0]), data[color][1]), data[color][0])\n",
+ " for j in range(3) ]\n",
+ " for color in channels ])\n",
+ " # normalize by largest component\n",
+ " return a / np.max(np.sum(a, axis=0))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 120,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "array([[ 0.06995882, 0.02007191, -0.0260505 ],\n",
+ " [ 0.05310356, 0.0995779 , 0.03458726],\n",
+ " [ 0.16122952, 0.16639874, 0.99146324]])"
+ ]
+ },
+ "execution_count": 120,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "tristimulus_data = integrate_tristimulus_response(data_rgb)\n",
+ "tristimulus_data\n",
+ "#array([[ 3.46142003e-01, 1.73335974e-01, -7.18827590e-05],\n",
+ "# [ 9.01721797e-02, 1.69512416e-01, 2.15830281e-02],\n",
+ "# [ 1.75128165e-01, 2.49230694e-01, 9.78488855e-01]])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 121,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": [
+ "def led_setpoint_from_xyz(x, y, z):\n",
+ " # returns [r, g, b] array.\n",
+ " # Note that many xyz tristimulus values cannot be produced because one component is outside [0, 1]\n",
+ " #return np.linalg.solve(tristimulus_data.T, np.array([x, y, z]))\n",
+ " return np.dot(np.linalg.inv(tristimulus_data.T), np.array([x, y, z]))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 122,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "array([ 2.96363627, 1.00231926, 0.24462504])"
+ ]
+ },
+ "execution_count": 122,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "led_setpoint_from_xyz(0.3, 0.2, 0.2)"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.6.5"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 1
+}