diff options
author | jaseg <git@jaseg.net> | 2018-05-05 11:56:54 +0200 |
---|---|---|
committer | jaseg <git@jaseg.net> | 2018-05-05 11:56:54 +0200 |
commit | c95e8296bf08b39f1198a8075b651e0da24934d1 (patch) | |
tree | 18d6f1ced22f81c95bdb1fd48db95fdd060164bd /firmware | |
parent | c641bbc090721d11dae9f4cf412320a37b1170ec (diff) | |
download | olsndot-c95e8296bf08b39f1198a8075b651e0da24934d1.tar.gz olsndot-c95e8296bf08b39f1198a8075b651e0da24934d1.tar.bz2 olsndot-c95e8296bf08b39f1198a8075b651e0da24934d1.zip |
Add spectrum measurement stuff
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/Spectrum Measurement.ipynb | 2531 | ||||
-rw-r--r-- | firmware/calc_framerate.py | 38 | ||||
-rw-r--r-- | firmware/measure_spectrum.py | 122 | ||||
-rw-r--r-- | firmware/offset_test.py | 1 | ||||
-rw-r--r-- | firmware/results.sqlite3 | bin | 102400 -> 102400 bytes | |||
-rw-r--r-- | firmware/spectra.sqlite3 | bin | 0 -> 208896 bytes | |||
-rw-r--r-- | firmware/spectrum_progress.py | 32 | ||||
-rw-r--r-- | firmware/stepper_test.py | 56 |
8 files changed, 2780 insertions, 0 deletions
diff --git a/firmware/Spectrum Measurement.ipynb b/firmware/Spectrum Measurement.ipynb new file mode 100644 index 0000000..57d4339 --- /dev/null +++ b/firmware/Spectrum Measurement.ipynb @@ -0,0 +1,2531 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import sqlite3\n", + "import time\n", + "from IPython import display\n", + "from datetime import datetime\n", + "\n", + "import numpy as np\n", + "from matplotlib import pyplot as plt\n", + "%matplotlib notebook" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "db = sqlite3.connect('spectra.sqlite3')" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def load_run(run_id):\n", + " data = db.execute('SELECT step, voltage, voltage_stdev FROM measurements WHERE run_id = ? AND led_on = 1 ORDER BY step ASC', (run_id,)).fetchall()\n", + " return zip(*data)" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def load_run_zero_cal(run_id, max_stdev=1e10):\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.run_id = ?1 AND a.led_on = 1 AND b.run_id = ?1 AND b.led_on = 0 '\n", + " 'AND a.voltage_stdev < ?2 AND b.voltage_stdev < ?2'\n", + " 'ORDER BY step ASC', (run_id, max_stdev)).fetchall()\n", + " steps, voltages, voltage_stdevs, zero_voltages, zero_stdevs = map(np.array, zip(*data))\n", + " return steps, voltages-zero_voltages, np.sqrt(np.square(voltage_stdevs) + np.square(zero_stdevs))" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def plot_rgb(id_r, id_g, id_b, loader=load_run):\n", + " fig, ax = plt.subplots(1, 1)\n", + " fig.suptitle('Runs {}, {}, {} at {:%y-%m-%d %H:%M:%S}'.format(id_r, id_g, id_b, datetime.now()))\n", + " for run_id, color in [(id_g, 'green'), (id_r, 'red'), (id_b, 'blue')]:\n", + " steps, values, stdev = loader(run_id)\n", + " ax.errorbar(steps, values, yerr=stdev, color=color)\n", + " #ax.set_ylim([2.2, 5])\n", + " #plt.close(fig)\n", + " #return fig" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "window.mpl = {};\n", + "\n", + "mpl.get_websocket_type = function() {\n", + " if (typeof(WebSocket) !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof(MozWebSocket) !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert('Your browser does not have WebSocket support.' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.');\n", + " };\n", + "}\n", + "\n", + "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = (this.ws.binaryType != undefined);\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById(\"mpl-warnings\");\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent = (\n", + " \"This browser does not support binary websocket messages. \" +\n", + " \"Performance may be slow.\");\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = $('<div/>');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " this.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n", + " 'ui-helper-clearfix\"/>');\n", + " var titletext = $(\n", + " '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n", + " 'text-align: center; padding: 3px;\"/>');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('<div/>');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('<canvas/>');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var rubberband = $('<canvas/>');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width);\n", + " canvas.attr('height', height);\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('<div/>')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('<button/>');\n", + " button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n", + " 'ui-button-icon-only');\n", + " button.attr('role', 'button');\n", + " button.attr('aria-disabled', 'false');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + "\n", + " var icon_img = $('<span/>');\n", + " icon_img.addClass('ui-button-icon-primary ui-icon');\n", + " icon_img.addClass(image);\n", + " icon_img.addClass('ui-corner-all');\n", + "\n", + " var tooltip_span = $('<span/>');\n", + " tooltip_span.addClass('ui-button-text');\n", + " tooltip_span.html(tooltip);\n", + "\n", + " button.append(icon_img);\n", + " button.append(tooltip_span);\n", + "\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " var fmt_picker_span = $('<span/>');\n", + "\n", + " var fmt_picker = $('<select/>');\n", + " fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n", + " fmt_picker_span.append(fmt_picker);\n", + " nav_element.append(fmt_picker_span);\n", + " this.format_dropdown = fmt_picker[0];\n", + "\n", + " for (var ind in mpl.extensions) {\n", + " var fmt = mpl.extensions[ind];\n", + " var option = $(\n", + " '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n", + " fmt_picker.append(option)\n", + " }\n", + "\n", + " // Add hover states to the ui-buttons\n", + " $( \".ui-button\" ).hover(\n", + " function() { $(this).addClass(\"ui-state-hover\");},\n", + " function() { $(this).removeClass(\"ui-state-hover\");}\n", + " );\n", + "\n", + " var status_bar = $('<span class=\"mpl-message\"/>');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "}\n", + "\n", + "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n", + " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", + " // which will in turn request a refresh of the image.\n", + " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n", + "}\n", + "\n", + "mpl.figure.prototype.send_message = function(type, properties) {\n", + " properties['type'] = type;\n", + " properties['figure_id'] = this.id;\n", + " this.ws.send(JSON.stringify(properties));\n", + "}\n", + "\n", + "mpl.figure.prototype.send_draw_message = function() {\n", + " if (!this.waiting) {\n", + " this.waiting = true;\n", + " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n", + " }\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " var format_dropdown = fig.format_dropdown;\n", + " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", + " fig.ondownload(fig, format);\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype.handle_resize = function(fig, msg) {\n", + " var size = msg['size'];\n", + " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n", + " fig._resize_canvas(size[0], size[1]);\n", + " fig.send_message(\"refresh\", {});\n", + " };\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n", + " var x0 = msg['x0'];\n", + " var y0 = fig.canvas.height - msg['y0'];\n", + " var x1 = msg['x1'];\n", + " var y1 = fig.canvas.height - msg['y1'];\n", + " x0 = Math.floor(x0) + 0.5;\n", + " y0 = Math.floor(y0) + 0.5;\n", + " x1 = Math.floor(x1) + 0.5;\n", + " y1 = Math.floor(y1) + 0.5;\n", + " var min_x = Math.min(x0, x1);\n", + " var min_y = Math.min(y0, y1);\n", + " var width = Math.abs(x1 - x0);\n", + " var height = Math.abs(y1 - y0);\n", + "\n", + " fig.rubberband_context.clearRect(\n", + " 0, 0, fig.canvas.width, fig.canvas.height);\n", + "\n", + " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n", + " // Updates the figure title.\n", + " fig.header.textContent = msg['label'];\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n", + " var cursor = msg['cursor'];\n", + " switch(cursor)\n", + " {\n", + " case 0:\n", + " cursor = 'pointer';\n", + " break;\n", + " case 1:\n", + " cursor = 'default';\n", + " break;\n", + " case 2:\n", + " cursor = 'crosshair';\n", + " break;\n", + " case 3:\n", + " cursor = 'move';\n", + " break;\n", + " }\n", + " fig.rubberband_canvas.style.cursor = cursor;\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_message = function(fig, msg) {\n", + " fig.message.textContent = msg['message'];\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_draw = function(fig, msg) {\n", + " // Request the server to send over a new figure.\n", + " fig.send_draw_message();\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n", + " fig.image_mode = msg['mode'];\n", + "}\n", + "\n", + "mpl.figure.prototype.updated_canvas_event = function() {\n", + " // Called whenever the canvas gets updated.\n", + " this.send_message(\"ack\", {});\n", + "}\n", + "\n", + "// A function to construct a web socket function for onmessage handling.\n", + "// Called in the figure constructor.\n", + "mpl.figure.prototype._make_on_message_function = function(fig) {\n", + " return function socket_on_message(evt) {\n", + " if (evt.data instanceof Blob) {\n", + " /* FIXME: We get \"Resource interpreted as Image but\n", + " * transferred with MIME type text/plain:\" errors on\n", + " * Chrome. But how to set the MIME type? It doesn't seem\n", + " * to be part of the websocket stream */\n", + " evt.data.type = \"image/png\";\n", + "\n", + " /* Free the memory for the previous frames */\n", + " if (fig.imageObj.src) {\n", + " (window.URL || window.webkitURL).revokeObjectURL(\n", + " fig.imageObj.src);\n", + " }\n", + "\n", + " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", + " evt.data);\n", + " fig.updated_canvas_event();\n", + " fig.waiting = false;\n", + " return;\n", + " }\n", + " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n", + " fig.imageObj.src = evt.data;\n", + " fig.updated_canvas_event();\n", + " fig.waiting = false;\n", + " return;\n", + " }\n", + "\n", + " var msg = JSON.parse(evt.data);\n", + " var msg_type = msg['type'];\n", + "\n", + " // Call the \"handle_{type}\" callback, which takes\n", + " // the figure and JSON message as its only arguments.\n", + " try {\n", + " var callback = fig[\"handle_\" + msg_type];\n", + " } catch (e) {\n", + " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n", + " return;\n", + " }\n", + "\n", + " if (callback) {\n", + " try {\n", + " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", + " callback(fig, msg);\n", + " } catch (e) {\n", + " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n", + " }\n", + " }\n", + " };\n", + "}\n", + "\n", + "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", + "mpl.findpos = function(e) {\n", + " //this section is from http://www.quirksmode.org/js/events_properties.html\n", + " var targ;\n", + " if (!e)\n", + " e = window.event;\n", + " if (e.target)\n", + " targ = e.target;\n", + " else if (e.srcElement)\n", + " targ = e.srcElement;\n", + " if (targ.nodeType == 3) // defeat Safari bug\n", + " targ = targ.parentNode;\n", + "\n", + " // jQuery normalizes the pageX and pageY\n", + " // pageX,Y are the mouse positions relative to the document\n", + " // offset() returns the position of the element relative to the document\n", + " var x = e.pageX - $(targ).offset().left;\n", + " var y = e.pageY - $(targ).offset().top;\n", + "\n", + " return {\"x\": x, \"y\": y};\n", + "};\n", + "\n", + "/*\n", + " * return a copy of an object with only non-object keys\n", + " * we need this to avoid circular references\n", + " * http://stackoverflow.com/a/24161582/3208463\n", + " */\n", + "function simpleKeys (original) {\n", + " return Object.keys(original).reduce(function (obj, key) {\n", + " if (typeof original[key] !== 'object')\n", + " obj[key] = original[key]\n", + " return obj;\n", + " }, {});\n", + "}\n", + "\n", + "mpl.figure.prototype.mouse_event = function(event, name) {\n", + " var canvas_pos = mpl.findpos(event)\n", + "\n", + " if (name === 'button_press')\n", + " {\n", + " this.canvas.focus();\n", + " this.canvas_div.focus();\n", + " }\n", + "\n", + " var x = canvas_pos.x;\n", + " var y = canvas_pos.y;\n", + "\n", + " this.send_message(name, {x: x, y: y, button: event.button,\n", + " step: event.step,\n", + " guiEvent: simpleKeys(event)});\n", + "\n", + " /* This prevents the web browser from automatically changing to\n", + " * the text insertion cursor when the button is pressed. We want\n", + " * to control all of the cursor setting manually through the\n", + " * 'cursor' event from matplotlib */\n", + " event.preventDefault();\n", + " return false;\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " // Handle any extra behaviour associated with a key event\n", + "}\n", + "\n", + "mpl.figure.prototype.key_event = function(event, name) {\n", + "\n", + " // Prevent repeat events\n", + " if (name == 'key_press')\n", + " {\n", + " if (event.which === this._key)\n", + " return;\n", + " else\n", + " this._key = event.which;\n", + " }\n", + " if (name == 'key_release')\n", + " this._key = null;\n", + "\n", + " var value = '';\n", + " if (event.ctrlKey && event.which != 17)\n", + " value += \"ctrl+\";\n", + " if (event.altKey && event.which != 18)\n", + " value += \"alt+\";\n", + " if (event.shiftKey && event.which != 16)\n", + " value += \"shift+\";\n", + "\n", + " value += 'k';\n", + " value += event.which.toString();\n", + "\n", + " this._key_event_extra(event, name);\n", + "\n", + " this.send_message(name, {key: value,\n", + " guiEvent: simpleKeys(event)});\n", + " return false;\n", + "}\n", + "\n", + "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n", + " if (name == 'download') {\n", + " this.handle_save(this, null);\n", + " } else {\n", + " this.send_message(\"toolbar_button\", {name: name});\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", + " this.message.textContent = tooltip;\n", + "};\n", + "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", + "\n", + "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n", + "\n", + "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n", + " // Create a \"websocket\"-like object which calls the given IPython comm\n", + " // object with the appropriate methods. Currently this is a non binary\n", + " // socket, so there is still some room for performance tuning.\n", + " var ws = {};\n", + "\n", + " ws.close = function() {\n", + " comm.close()\n", + " };\n", + " ws.send = function(m) {\n", + " //console.log('sending', m);\n", + " comm.send(m);\n", + " };\n", + " // Register the callback with on_msg.\n", + " comm.on_msg(function(msg) {\n", + " //console.log('receiving', msg['content']['data'], msg);\n", + " // Pass the mpl event to the overriden (by mpl) onmessage function.\n", + " ws.onmessage(msg['content']['data'])\n", + " });\n", + " return ws;\n", + "}\n", + "\n", + "mpl.mpl_figure_comm = function(comm, msg) {\n", + " // This is the function which gets called when the mpl process\n", + " // starts-up an IPython Comm through the \"matplotlib\" channel.\n", + "\n", + " var id = msg.content.data.id;\n", + " // Get hold of the div created by the display call when the Comm\n", + " // socket was opened in Python.\n", + " var element = $(\"#\" + id);\n", + " var ws_proxy = comm_websocket_adapter(comm)\n", + "\n", + " function ondownload(figure, format) {\n", + " window.open(figure.imageObj.src);\n", + " }\n", + "\n", + " var fig = new mpl.figure(id, ws_proxy,\n", + " ondownload,\n", + " element.get(0));\n", + "\n", + " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", + " // web socket which is closed, not our websocket->open comm proxy.\n", + " ws_proxy.onopen();\n", + "\n", + " fig.parent_element = element.get(0);\n", + " fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n", + " if (!fig.cell_info) {\n", + " console.error(\"Failed to find cell for figure\", id, fig);\n", + " return;\n", + " }\n", + "\n", + " var output_index = fig.cell_info[2]\n", + " var cell = fig.cell_info[0];\n", + "\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_close = function(fig, msg) {\n", + " fig.root.unbind('remove')\n", + "\n", + " // Update the output cell to use the data from the current canvas.\n", + " fig.push_to_output();\n", + " var dataURL = fig.canvas.toDataURL();\n", + " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", + " // the notebook keyboard shortcuts fail.\n", + " IPython.keyboard_manager.enable()\n", + " $(fig.parent_element).html('<img src=\"' + dataURL + '\">');\n", + " fig.close_ws(fig, msg);\n", + "}\n", + "\n", + "mpl.figure.prototype.close_ws = function(fig, msg){\n", + " fig.send_message('closing', msg);\n", + " // fig.ws.close()\n", + "}\n", + "\n", + "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", + " // Turn the data on the canvas into data in the output cell.\n", + " var dataURL = this.canvas.toDataURL();\n", + " this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n", + "}\n", + "\n", + "mpl.figure.prototype.updated_canvas_event = function() {\n", + " // Tell IPython that the notebook contents must change.\n", + " IPython.notebook.set_dirty(true);\n", + " this.send_message(\"ack\", {});\n", + " var fig = this;\n", + " // Wait a second, then push the new image to the DOM so\n", + " // that it is saved nicely (might be nice to debounce this).\n", + " setTimeout(function () { fig.push_to_output() }, 1000);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('<div/>')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items){\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) { continue; };\n", + "\n", + " var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", + " var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", + " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", + " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", + " buttongrp.append(button);\n", + " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", + " titlebar.prepend(buttongrp);\n", + "}\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(el){\n", + " var fig = this\n", + " el.on(\"remove\", function(){\n", + "\tfig.close_ws(fig, {});\n", + " });\n", + "}\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(el){\n", + " // this is important to make the div 'focusable\n", + " el.attr('tabindex', 0)\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " }\n", + " else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager)\n", + " manager = IPython.keyboard_manager;\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which == 13) {\n", + " this.canvas_div.blur();\n", + " event.shiftKey = false;\n", + " // Send a \"J\" for go to next cell\n", + " event.which = 74;\n", + " event.keyCode = 74;\n", + " manager.command_mode();\n", + " manager.handle_keydown(event);\n", + " }\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " fig.ondownload(fig, null);\n", + "}\n", + "\n", + "\n", + "mpl.find_output_cell = function(html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i=0; i<ncells; i++) {\n", + " var cell = cells[i];\n", + " if (cell.cell_type === 'code'){\n", + " for (var j=0; j<cell.output_area.outputs.length; j++) {\n", + " var data = cell.output_area.outputs[j];\n", + " if (data.data) {\n", + " // IPython >= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] == html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel != null) {\n", + " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", + "}\n" + ], + "text/plain": [ + "<IPython.core.display.Javascript object>" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "<img src=\"data:image/png;base64,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\">" + ], + "text/plain": [ + "<IPython.core.display.HTML object>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "plot_rgb(10, 9, 12)" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "def live_plot_rgb(id_r, id_g, id_b, interval=1, loader=load_run):\n", + " fig, ax = plt.subplots(1, 1)\n", + " fig.suptitle('Runs {}, {}, {} at {:%y-%m-%d %H:%M:%S}'.format(id_r, id_g, id_b, datetime.now()))\n", + " \n", + " while True:\n", + " ax.clear()\n", + " for run_id, color in [(id_g, 'green'), (id_r, 'red'), (id_b, 'blue')]:\n", + " steps, values, stdev = loader(run_id)\n", + " ax.errorbar(steps, values, yerr=stdev, color=color)\n", + " fig.canvas.draw()\n", + " time.sleep(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "window.mpl = {};\n", + "\n", + "mpl.get_websocket_type = function() {\n", + " if (typeof(WebSocket) !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof(MozWebSocket) !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert('Your browser does not have WebSocket support.' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.');\n", + " };\n", + "}\n", + "\n", + "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = (this.ws.binaryType != undefined);\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById(\"mpl-warnings\");\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent = (\n", + " \"This browser does not support binary websocket messages. \" +\n", + " \"Performance may be slow.\");\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = $('<div/>');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " this.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n", + " 'ui-helper-clearfix\"/>');\n", + " var titletext = $(\n", + " '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n", + " 'text-align: center; padding: 3px;\"/>');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('<div/>');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('<canvas/>');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var rubberband = $('<canvas/>');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width);\n", + " canvas.attr('height', height);\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('<div/>')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('<button/>');\n", + " button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n", + " 'ui-button-icon-only');\n", + " button.attr('role', 'button');\n", + " button.attr('aria-disabled', 'false');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + "\n", + " var icon_img = $('<span/>');\n", + " icon_img.addClass('ui-button-icon-primary ui-icon');\n", + " icon_img.addClass(image);\n", + " icon_img.addClass('ui-corner-all');\n", + "\n", + " var tooltip_span = $('<span/>');\n", + " tooltip_span.addClass('ui-button-text');\n", + " tooltip_span.html(tooltip);\n", + "\n", + " button.append(icon_img);\n", + " button.append(tooltip_span);\n", + "\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " var fmt_picker_span = $('<span/>');\n", + "\n", + " var fmt_picker = $('<select/>');\n", + " fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n", + " fmt_picker_span.append(fmt_picker);\n", + " nav_element.append(fmt_picker_span);\n", + " this.format_dropdown = fmt_picker[0];\n", + "\n", + " for (var ind in mpl.extensions) {\n", + " var fmt = mpl.extensions[ind];\n", + " var option = $(\n", + " '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n", + " fmt_picker.append(option)\n", + " }\n", + "\n", + " // Add hover states to the ui-buttons\n", + " $( \".ui-button\" ).hover(\n", + " function() { $(this).addClass(\"ui-state-hover\");},\n", + " function() { $(this).removeClass(\"ui-state-hover\");}\n", + " );\n", + "\n", + " var status_bar = $('<span class=\"mpl-message\"/>');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "}\n", + "\n", + "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n", + " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", + " // which will in turn request a refresh of the image.\n", + " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n", + "}\n", + "\n", + "mpl.figure.prototype.send_message = function(type, properties) {\n", + " properties['type'] = type;\n", + " properties['figure_id'] = this.id;\n", + " this.ws.send(JSON.stringify(properties));\n", + "}\n", + "\n", + "mpl.figure.prototype.send_draw_message = function() {\n", + " if (!this.waiting) {\n", + " this.waiting = true;\n", + " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n", + " }\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " var format_dropdown = fig.format_dropdown;\n", + " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", + " fig.ondownload(fig, format);\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype.handle_resize = function(fig, msg) {\n", + " var size = msg['size'];\n", + " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n", + " fig._resize_canvas(size[0], size[1]);\n", + " fig.send_message(\"refresh\", {});\n", + " };\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n", + " var x0 = msg['x0'];\n", + " var y0 = fig.canvas.height - msg['y0'];\n", + " var x1 = msg['x1'];\n", + " var y1 = fig.canvas.height - msg['y1'];\n", + " x0 = Math.floor(x0) + 0.5;\n", + " y0 = Math.floor(y0) + 0.5;\n", + " x1 = Math.floor(x1) + 0.5;\n", + " y1 = Math.floor(y1) + 0.5;\n", + " var min_x = Math.min(x0, x1);\n", + " var min_y = Math.min(y0, y1);\n", + " var width = Math.abs(x1 - x0);\n", + " var height = Math.abs(y1 - y0);\n", + "\n", + " fig.rubberband_context.clearRect(\n", + " 0, 0, fig.canvas.width, fig.canvas.height);\n", + "\n", + " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n", + " // Updates the figure title.\n", + " fig.header.textContent = msg['label'];\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n", + " var cursor = msg['cursor'];\n", + " switch(cursor)\n", + " {\n", + " case 0:\n", + " cursor = 'pointer';\n", + " break;\n", + " case 1:\n", + " cursor = 'default';\n", + " break;\n", + " case 2:\n", + " cursor = 'crosshair';\n", + " break;\n", + " case 3:\n", + " cursor = 'move';\n", + " break;\n", + " }\n", + " fig.rubberband_canvas.style.cursor = cursor;\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_message = function(fig, msg) {\n", + " fig.message.textContent = msg['message'];\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_draw = function(fig, msg) {\n", + " // Request the server to send over a new figure.\n", + " fig.send_draw_message();\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n", + " fig.image_mode = msg['mode'];\n", + "}\n", + "\n", + "mpl.figure.prototype.updated_canvas_event = function() {\n", + " // Called whenever the canvas gets updated.\n", + " this.send_message(\"ack\", {});\n", + "}\n", + "\n", + "// A function to construct a web socket function for onmessage handling.\n", + "// Called in the figure constructor.\n", + "mpl.figure.prototype._make_on_message_function = function(fig) {\n", + " return function socket_on_message(evt) {\n", + " if (evt.data instanceof Blob) {\n", + " /* FIXME: We get \"Resource interpreted as Image but\n", + " * transferred with MIME type text/plain:\" errors on\n", + " * Chrome. But how to set the MIME type? It doesn't seem\n", + " * to be part of the websocket stream */\n", + " evt.data.type = \"image/png\";\n", + "\n", + " /* Free the memory for the previous frames */\n", + " if (fig.imageObj.src) {\n", + " (window.URL || window.webkitURL).revokeObjectURL(\n", + " fig.imageObj.src);\n", + " }\n", + "\n", + " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", + " evt.data);\n", + " fig.updated_canvas_event();\n", + " fig.waiting = false;\n", + " return;\n", + " }\n", + " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n", + " fig.imageObj.src = evt.data;\n", + " fig.updated_canvas_event();\n", + " fig.waiting = false;\n", + " return;\n", + " }\n", + "\n", + " var msg = JSON.parse(evt.data);\n", + " var msg_type = msg['type'];\n", + "\n", + " // Call the \"handle_{type}\" callback, which takes\n", + " // the figure and JSON message as its only arguments.\n", + " try {\n", + " var callback = fig[\"handle_\" + msg_type];\n", + " } catch (e) {\n", + " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n", + " return;\n", + " }\n", + "\n", + " if (callback) {\n", + " try {\n", + " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", + " callback(fig, msg);\n", + " } catch (e) {\n", + " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n", + " }\n", + " }\n", + " };\n", + "}\n", + "\n", + "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", + "mpl.findpos = function(e) {\n", + " //this section is from http://www.quirksmode.org/js/events_properties.html\n", + " var targ;\n", + " if (!e)\n", + " e = window.event;\n", + " if (e.target)\n", + " targ = e.target;\n", + " else if (e.srcElement)\n", + " targ = e.srcElement;\n", + " if (targ.nodeType == 3) // defeat Safari bug\n", + " targ = targ.parentNode;\n", + "\n", + " // jQuery normalizes the pageX and pageY\n", + " // pageX,Y are the mouse positions relative to the document\n", + " // offset() returns the position of the element relative to the document\n", + " var x = e.pageX - $(targ).offset().left;\n", + " var y = e.pageY - $(targ).offset().top;\n", + "\n", + " return {\"x\": x, \"y\": y};\n", + "};\n", + "\n", + "/*\n", + " * return a copy of an object with only non-object keys\n", + " * we need this to avoid circular references\n", + " * http://stackoverflow.com/a/24161582/3208463\n", + " */\n", + "function simpleKeys (original) {\n", + " return Object.keys(original).reduce(function (obj, key) {\n", + " if (typeof original[key] !== 'object')\n", + " obj[key] = original[key]\n", + " return obj;\n", + " }, {});\n", + "}\n", + "\n", + "mpl.figure.prototype.mouse_event = function(event, name) {\n", + " var canvas_pos = mpl.findpos(event)\n", + "\n", + " if (name === 'button_press')\n", + " {\n", + " this.canvas.focus();\n", + " this.canvas_div.focus();\n", + " }\n", + "\n", + " var x = canvas_pos.x;\n", + " var y = canvas_pos.y;\n", + "\n", + " this.send_message(name, {x: x, y: y, button: event.button,\n", + " step: event.step,\n", + " guiEvent: simpleKeys(event)});\n", + "\n", + " /* This prevents the web browser from automatically changing to\n", + " * the text insertion cursor when the button is pressed. We want\n", + " * to control all of the cursor setting manually through the\n", + " * 'cursor' event from matplotlib */\n", + " event.preventDefault();\n", + " return false;\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " // Handle any extra behaviour associated with a key event\n", + "}\n", + "\n", + "mpl.figure.prototype.key_event = function(event, name) {\n", + "\n", + " // Prevent repeat events\n", + " if (name == 'key_press')\n", + " {\n", + " if (event.which === this._key)\n", + " return;\n", + " else\n", + " this._key = event.which;\n", + " }\n", + " if (name == 'key_release')\n", + " this._key = null;\n", + "\n", + " var value = '';\n", + " if (event.ctrlKey && event.which != 17)\n", + " value += \"ctrl+\";\n", + " if (event.altKey && event.which != 18)\n", + " value += \"alt+\";\n", + " if (event.shiftKey && event.which != 16)\n", + " value += \"shift+\";\n", + "\n", + " value += 'k';\n", + " value += event.which.toString();\n", + "\n", + " this._key_event_extra(event, name);\n", + "\n", + " this.send_message(name, {key: value,\n", + " guiEvent: simpleKeys(event)});\n", + " return false;\n", + "}\n", + "\n", + "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n", + " if (name == 'download') {\n", + " this.handle_save(this, null);\n", + " } else {\n", + " this.send_message(\"toolbar_button\", {name: name});\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", + " this.message.textContent = tooltip;\n", + "};\n", + "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", + "\n", + "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n", + "\n", + "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n", + " // Create a \"websocket\"-like object which calls the given IPython comm\n", + " // object with the appropriate methods. Currently this is a non binary\n", + " // socket, so there is still some room for performance tuning.\n", + " var ws = {};\n", + "\n", + " ws.close = function() {\n", + " comm.close()\n", + " };\n", + " ws.send = function(m) {\n", + " //console.log('sending', m);\n", + " comm.send(m);\n", + " };\n", + " // Register the callback with on_msg.\n", + " comm.on_msg(function(msg) {\n", + " //console.log('receiving', msg['content']['data'], msg);\n", + " // Pass the mpl event to the overriden (by mpl) onmessage function.\n", + " ws.onmessage(msg['content']['data'])\n", + " });\n", + " return ws;\n", + "}\n", + "\n", + "mpl.mpl_figure_comm = function(comm, msg) {\n", + " // This is the function which gets called when the mpl process\n", + " // starts-up an IPython Comm through the \"matplotlib\" channel.\n", + "\n", + " var id = msg.content.data.id;\n", + " // Get hold of the div created by the display call when the Comm\n", + " // socket was opened in Python.\n", + " var element = $(\"#\" + id);\n", + " var ws_proxy = comm_websocket_adapter(comm)\n", + "\n", + " function ondownload(figure, format) {\n", + " window.open(figure.imageObj.src);\n", + " }\n", + "\n", + " var fig = new mpl.figure(id, ws_proxy,\n", + " ondownload,\n", + " element.get(0));\n", + "\n", + " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", + " // web socket which is closed, not our websocket->open comm proxy.\n", + " ws_proxy.onopen();\n", + "\n", + " fig.parent_element = element.get(0);\n", + " fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n", + " if (!fig.cell_info) {\n", + " console.error(\"Failed to find cell for figure\", id, fig);\n", + " return;\n", + " }\n", + "\n", + " var output_index = fig.cell_info[2]\n", + " var cell = fig.cell_info[0];\n", + "\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_close = function(fig, msg) {\n", + " fig.root.unbind('remove')\n", + "\n", + " // Update the output cell to use the data from the current canvas.\n", + " fig.push_to_output();\n", + " var dataURL = fig.canvas.toDataURL();\n", + " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", + " // the notebook keyboard shortcuts fail.\n", + " IPython.keyboard_manager.enable()\n", + " $(fig.parent_element).html('<img src=\"' + dataURL + '\">');\n", + " fig.close_ws(fig, msg);\n", + "}\n", + "\n", + "mpl.figure.prototype.close_ws = function(fig, msg){\n", + " fig.send_message('closing', msg);\n", + " // fig.ws.close()\n", + "}\n", + "\n", + "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", + " // Turn the data on the canvas into data in the output cell.\n", + " var dataURL = this.canvas.toDataURL();\n", + " this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n", + "}\n", + "\n", + "mpl.figure.prototype.updated_canvas_event = function() {\n", + " // Tell IPython that the notebook contents must change.\n", + " IPython.notebook.set_dirty(true);\n", + " this.send_message(\"ack\", {});\n", + " var fig = this;\n", + " // Wait a second, then push the new image to the DOM so\n", + " // that it is saved nicely (might be nice to debounce this).\n", + " setTimeout(function () { fig.push_to_output() }, 1000);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('<div/>')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items){\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) { continue; };\n", + "\n", + " var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", + " var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", + " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", + " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", + " buttongrp.append(button);\n", + " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", + " titlebar.prepend(buttongrp);\n", + "}\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(el){\n", + " var fig = this\n", + " el.on(\"remove\", function(){\n", + "\tfig.close_ws(fig, {});\n", + " });\n", + "}\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(el){\n", + " // this is important to make the div 'focusable\n", + " el.attr('tabindex', 0)\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " }\n", + " else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager)\n", + " manager = IPython.keyboard_manager;\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which == 13) {\n", + " this.canvas_div.blur();\n", + " event.shiftKey = false;\n", + " // Send a \"J\" for go to next cell\n", + " event.which = 74;\n", + " event.keyCode = 74;\n", + " manager.command_mode();\n", + " manager.handle_keydown(event);\n", + " }\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " fig.ondownload(fig, null);\n", + "}\n", + "\n", + "\n", + "mpl.find_output_cell = function(html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i=0; i<ncells; i++) {\n", + " var cell = cells[i];\n", + " if (cell.cell_type === 'code'){\n", + " for (var j=0; j<cell.output_area.outputs.length; j++) {\n", + " var data = cell.output_area.outputs[j];\n", + " if (data.data) {\n", + " // IPython >= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] == html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel != null) {\n", + " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", + "}\n" + ], + "text/plain": [ + "<IPython.core.display.Javascript object>" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "<img src=\"data:image/png;base64,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AHOInm4blvr3NaItTmfEfkD7WbxvASwlOmr1T9ED1E8i8mQGZTID5VWnn5c9PN5da2M30SCV0WnhrU7Pk5L6ukxTRKfRuJC6XCcaXtP7WTJubTGDqPNr6Zp6/x0i8oVoS9tZ0ffmddFg50kd0VPEF0RbmPqL4+chIvJsaplPiQYyd7x5n5uKjug+JRqmtokGuIzEig4cMT/v9SJSNt39PUVPI59Pfcynoq2NmSkvIu+KvSVskthHAIt493k5e0Vct4Gr4vjFwd17lD70vyg6f6b48D/pudt/yqe+Tk+tpu62+Z9Fg3/6eRDPiQZsIiKibGGBBL8l5AbR/oxEREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREROStl0XkoIicEZETIvKeiNQIaYmIiIiIKKgqiUih1N9zicjTInJMRGJCViIiIiIiyjJ5ROQpEbkqIsVCXBYiIiIiCqJWInJaRFJE5IqIjAltcYiIiIgoqxQWkSdFpH2oC0JEREREWSdGdEBINQ/3lRWRgvzhD3/4wx/+8CeifsoK+/dTBnKJyEURecDNfWVFBPzhD3/4wx/+8Ccif8oKUapBIlIy9fcSIjJDRE6JSLybxxYUESQnJ+Ps2bP8CfFP//79Q14G/vCzCMcffh7h88PPIjx+kpOTzQBYMEuSBUWE9SLyh4icF5GjIrJGRGp5eGxBEcHZs2dBoZeUlBTqIlAqfhbhhZ9H+OBnER7Onj3LAEiWMACGEVas4YOfRXjh5xE++FmEBwZAsooBMIzYbLZQF4FS8bMIL/w8wgc/i/DAAEhWMQASERFFGAZAsooBkIiIKMIwAJJVDIBEREQRhgGQrGIAJCIiijAMgGQVAyARUbSw2YCkJGDQICAxUZdJSXo7RRUGQLKKAZCIKNqcPQuI6JKiEgMgWcUASEQUbRgAox4DIFnFABiheKaHiDxiAIx6DIBkFQNghGM9T0QuWDFEPQZAsooBMMKxniciF6wYoh4DIFnFABjhWM8TkQtWDFGPAZCsYgCMcKznicgFK4aoxwBIVjEARjjW80TkghVD1GMAJKsYACMc63kicsGKIeoxAJJVDIARjvU8Eblg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O2Ab3QB8F7FOedjboFba9d9h1+imNwLAzJwo4GkkclsA9nljF4A9sGtm/wN3c7y2hWTpbNg773kRt08FMDL3i3NaqQm7CQWwD6Jvwq5ligcwGsCUiPVrwD5BnpVbBTwNZBY6Yr332mdyRrQAeDnspt28AK6FfVLrknaftkXOuQr2F9SW6W57HsDnEeudCXsbXJR2/W8ArSLW6Q1gfg6U8XSR2bYA7P58hWDvMxfBDoTpf/RB20KypG/QJ4/8sDv0XgXVAOYW1QCePKIFwEgvAliS9re2Rc64HnbfsTYRt2dVA2gG3qjWyV/RtkVm7oLd/9XQtpCYMutD8wvUhya35Yc92rElgDuhPoC5IbPQkZ33XvuM/7IbAP8H4LN017Ut/HUb7MBxVSb3XQLgCDLvA5g/7fpCZAzfK6F+Zyciq22RmTthjxg2tC0kpidhDye/AEBB2KOPtkKj6HJaBwCl0v4uB+AN2CezQrBrmrYDeAl2E0st2CMdNQrYH2fAbla8GnboiE+7HofsvffaZ/yT1ba4EEB92AMM8qSt8xvsqS0MbQv/PAI7cDSPcn8cgNUAxsLeT86BPTI1/Sjg9lYoSckAAAFkSURBVLBrnlrA3m4PwZ6eRCNPj0+sbVEN9nts9pWmADYA6JtuHW0LyRYLwE7YcwV9DM2jlRvmwK6pOAj7hDUJQNV099eCPUr4EOxO8C/kdgFD7C7YzVb/pF3M35ek3Z+d996C9hk/ZLUtrgewDnYN0++ww8b9mTyHBW0LP6TCHuW7H+655dKHkIoA5qXd9yuAgTg2Ath4GHYoPwR74E6LnCx0SMXaFo1gh/EUAPsAfAvgadhflNLTthAREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREREZFc8P8L+ylJX+++RQAAAABJRU5ErkJggg==\">" + ], + "text/plain": [ + "<IPython.core.display.HTML object>" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[1;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[1;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[1;32m<ipython-input-18-5741f6ed4af4>\u001b[0m in \u001b[0;36m<module>\u001b[1;34m()\u001b[0m\n\u001b[1;32m----> 1\u001b[1;33m \u001b[0mlive_plot_rgb\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m14\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m15\u001b[0m\u001b[1;33m,\u001b[0m \u001b[1;36m13\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mloader\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mload_run_zero_cal\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[1;32m<ipython-input-16-f9d194801c7a>\u001b[0m in \u001b[0;36mlive_plot_rgb\u001b[1;34m(id_r, id_g, id_b, interval, loader)\u001b[0m\n\u001b[0;32m 9\u001b[0m \u001b[0max\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0merrorbar\u001b[0m\u001b[1;33m(\u001b[0m\u001b[0msteps\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mvalues\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0myerr\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mstdev\u001b[0m\u001b[1;33m,\u001b[0m \u001b[0mcolor\u001b[0m\u001b[1;33m=\u001b[0m\u001b[0mcolor\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0;32m 10\u001b[0m \u001b[0mfig\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mcanvas\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0mdraw\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[1;32m---> 11\u001b[1;33m \u001b[0mtime\u001b[0m\u001b[1;33m.\u001b[0m\u001b[0msleep\u001b[0m\u001b[1;33m(\u001b[0m\u001b[1;36m1\u001b[0m\u001b[1;33m)\u001b[0m\u001b[1;33m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[1;31mKeyboardInterrupt\u001b[0m: " + ] + } + ], + "source": [ + "#live_plot_rgb(14, 15, 13, loader=load_run_zero_cal)" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import scipy.interpolate as inter\n", + "\n", + "def live_plot_rgb_splines(id_r, id_g, id_b, max_stdev=0.05, spline_s=1, interval=1, live=True):\n", + " fig, ax = plt.subplots(1, 1)\n", + " fig.suptitle('Runs {}, {}, {} at {:%y-%m-%d %H:%M:%S}'.format(id_r, id_g, id_b, datetime.now()))\n", + " \n", + " while True:\n", + " ax.clear()\n", + " colors = [\n", + " ((1,0,0), (1,0.5,0.5)),\n", + " ((0,1,0), (0.5,1,0.5)),\n", + " ((0,0,1), (0.5,0.5,1))\n", + " ]\n", + " for run_id, (color_dark, color_bright) in zip([id_r, id_g, id_b], colors):\n", + " steps, values, stdev = load_run_zero_cal(run_id, max_stdev)\n", + " spline = inter.UnivariateSpline(steps, values, s=spline_s)\n", + " ax.errorbar(steps, values, yerr=stdev, color=color_bright)\n", + " ax.plot(steps, spline(steps), color=color_dark)\n", + " fig.canvas.draw()\n", + " if not live:\n", + " break\n", + " time.sleep(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "application/javascript": [ + "/* Put everything inside the global mpl namespace */\n", + "window.mpl = {};\n", + "\n", + "mpl.get_websocket_type = function() {\n", + " if (typeof(WebSocket) !== 'undefined') {\n", + " return WebSocket;\n", + " } else if (typeof(MozWebSocket) !== 'undefined') {\n", + " return MozWebSocket;\n", + " } else {\n", + " alert('Your browser does not have WebSocket support.' +\n", + " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", + " 'Firefox 4 and 5 are also supported but you ' +\n", + " 'have to enable WebSockets in about:config.');\n", + " };\n", + "}\n", + "\n", + "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", + " this.id = figure_id;\n", + "\n", + " this.ws = websocket;\n", + "\n", + " this.supports_binary = (this.ws.binaryType != undefined);\n", + "\n", + " if (!this.supports_binary) {\n", + " var warnings = document.getElementById(\"mpl-warnings\");\n", + " if (warnings) {\n", + " warnings.style.display = 'block';\n", + " warnings.textContent = (\n", + " \"This browser does not support binary websocket messages. \" +\n", + " \"Performance may be slow.\");\n", + " }\n", + " }\n", + "\n", + " this.imageObj = new Image();\n", + "\n", + " this.context = undefined;\n", + " this.message = undefined;\n", + " this.canvas = undefined;\n", + " this.rubberband_canvas = undefined;\n", + " this.rubberband_context = undefined;\n", + " this.format_dropdown = undefined;\n", + "\n", + " this.image_mode = 'full';\n", + "\n", + " this.root = $('<div/>');\n", + " this._root_extra_style(this.root)\n", + " this.root.attr('style', 'display: inline-block');\n", + "\n", + " $(parent_element).append(this.root);\n", + "\n", + " this._init_header(this);\n", + " this._init_canvas(this);\n", + " this._init_toolbar(this);\n", + "\n", + " var fig = this;\n", + "\n", + " this.waiting = false;\n", + "\n", + " this.ws.onopen = function () {\n", + " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", + " fig.send_message(\"send_image_mode\", {});\n", + " fig.send_message(\"refresh\", {});\n", + " }\n", + "\n", + " this.imageObj.onload = function() {\n", + " if (fig.image_mode == 'full') {\n", + " // Full images could contain transparency (where diff images\n", + " // almost always do), so we need to clear the canvas so that\n", + " // there is no ghosting.\n", + " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", + " }\n", + " fig.context.drawImage(fig.imageObj, 0, 0);\n", + " };\n", + "\n", + " this.imageObj.onunload = function() {\n", + " this.ws.close();\n", + " }\n", + "\n", + " this.ws.onmessage = this._make_on_message_function(this);\n", + "\n", + " this.ondownload = ondownload;\n", + "}\n", + "\n", + "mpl.figure.prototype._init_header = function() {\n", + " var titlebar = $(\n", + " '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n", + " 'ui-helper-clearfix\"/>');\n", + " var titletext = $(\n", + " '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n", + " 'text-align: center; padding: 3px;\"/>');\n", + " titlebar.append(titletext)\n", + " this.root.append(titlebar);\n", + " this.header = titletext[0];\n", + "}\n", + "\n", + "\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._init_canvas = function() {\n", + " var fig = this;\n", + "\n", + " var canvas_div = $('<div/>');\n", + "\n", + " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", + "\n", + " function canvas_keyboard_event(event) {\n", + " return fig.key_event(event, event['data']);\n", + " }\n", + "\n", + " canvas_div.keydown('key_press', canvas_keyboard_event);\n", + " canvas_div.keyup('key_release', canvas_keyboard_event);\n", + " this.canvas_div = canvas_div\n", + " this._canvas_extra_style(canvas_div)\n", + " this.root.append(canvas_div);\n", + "\n", + " var canvas = $('<canvas/>');\n", + " canvas.addClass('mpl-canvas');\n", + " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", + "\n", + " this.canvas = canvas[0];\n", + " this.context = canvas[0].getContext(\"2d\");\n", + "\n", + " var rubberband = $('<canvas/>');\n", + " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", + "\n", + " var pass_mouse_events = true;\n", + "\n", + " canvas_div.resizable({\n", + " start: function(event, ui) {\n", + " pass_mouse_events = false;\n", + " },\n", + " resize: function(event, ui) {\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " stop: function(event, ui) {\n", + " pass_mouse_events = true;\n", + " fig.request_resize(ui.size.width, ui.size.height);\n", + " },\n", + " });\n", + "\n", + " function mouse_event_fn(event) {\n", + " if (pass_mouse_events)\n", + " return fig.mouse_event(event, event['data']);\n", + " }\n", + "\n", + " rubberband.mousedown('button_press', mouse_event_fn);\n", + " rubberband.mouseup('button_release', mouse_event_fn);\n", + " // Throttle sequential mouse events to 1 every 20ms.\n", + " rubberband.mousemove('motion_notify', mouse_event_fn);\n", + "\n", + " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", + " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", + "\n", + " canvas_div.on(\"wheel\", function (event) {\n", + " event = event.originalEvent;\n", + " event['data'] = 'scroll'\n", + " if (event.deltaY < 0) {\n", + " event.step = 1;\n", + " } else {\n", + " event.step = -1;\n", + " }\n", + " mouse_event_fn(event);\n", + " });\n", + "\n", + " canvas_div.append(canvas);\n", + " canvas_div.append(rubberband);\n", + "\n", + " this.rubberband = rubberband;\n", + " this.rubberband_canvas = rubberband[0];\n", + " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", + " this.rubberband_context.strokeStyle = \"#000000\";\n", + "\n", + " this._resize_canvas = function(width, height) {\n", + " // Keep the size of the canvas, canvas container, and rubber band\n", + " // canvas in synch.\n", + " canvas_div.css('width', width)\n", + " canvas_div.css('height', height)\n", + "\n", + " canvas.attr('width', width);\n", + " canvas.attr('height', height);\n", + "\n", + " rubberband.attr('width', width);\n", + " rubberband.attr('height', height);\n", + " }\n", + "\n", + " // Set the figure to an initial 600x600px, this will subsequently be updated\n", + " // upon first draw.\n", + " this._resize_canvas(600, 600);\n", + "\n", + " // Disable right mouse context menu.\n", + " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", + " return false;\n", + " });\n", + "\n", + " function set_focus () {\n", + " canvas.focus();\n", + " canvas_div.focus();\n", + " }\n", + "\n", + " window.setTimeout(set_focus, 100);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('<div/>')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items) {\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) {\n", + " // put a spacer in here.\n", + " continue;\n", + " }\n", + " var button = $('<button/>');\n", + " button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n", + " 'ui-button-icon-only');\n", + " button.attr('role', 'button');\n", + " button.attr('aria-disabled', 'false');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + "\n", + " var icon_img = $('<span/>');\n", + " icon_img.addClass('ui-button-icon-primary ui-icon');\n", + " icon_img.addClass(image);\n", + " icon_img.addClass('ui-corner-all');\n", + "\n", + " var tooltip_span = $('<span/>');\n", + " tooltip_span.addClass('ui-button-text');\n", + " tooltip_span.html(tooltip);\n", + "\n", + " button.append(icon_img);\n", + " button.append(tooltip_span);\n", + "\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " var fmt_picker_span = $('<span/>');\n", + "\n", + " var fmt_picker = $('<select/>');\n", + " fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n", + " fmt_picker_span.append(fmt_picker);\n", + " nav_element.append(fmt_picker_span);\n", + " this.format_dropdown = fmt_picker[0];\n", + "\n", + " for (var ind in mpl.extensions) {\n", + " var fmt = mpl.extensions[ind];\n", + " var option = $(\n", + " '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n", + " fmt_picker.append(option)\n", + " }\n", + "\n", + " // Add hover states to the ui-buttons\n", + " $( \".ui-button\" ).hover(\n", + " function() { $(this).addClass(\"ui-state-hover\");},\n", + " function() { $(this).removeClass(\"ui-state-hover\");}\n", + " );\n", + "\n", + " var status_bar = $('<span class=\"mpl-message\"/>');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "}\n", + "\n", + "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n", + " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", + " // which will in turn request a refresh of the image.\n", + " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n", + "}\n", + "\n", + "mpl.figure.prototype.send_message = function(type, properties) {\n", + " properties['type'] = type;\n", + " properties['figure_id'] = this.id;\n", + " this.ws.send(JSON.stringify(properties));\n", + "}\n", + "\n", + "mpl.figure.prototype.send_draw_message = function() {\n", + " if (!this.waiting) {\n", + " this.waiting = true;\n", + " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n", + " }\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " var format_dropdown = fig.format_dropdown;\n", + " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", + " fig.ondownload(fig, format);\n", + "}\n", + "\n", + "\n", + "mpl.figure.prototype.handle_resize = function(fig, msg) {\n", + " var size = msg['size'];\n", + " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n", + " fig._resize_canvas(size[0], size[1]);\n", + " fig.send_message(\"refresh\", {});\n", + " };\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n", + " var x0 = msg['x0'];\n", + " var y0 = fig.canvas.height - msg['y0'];\n", + " var x1 = msg['x1'];\n", + " var y1 = fig.canvas.height - msg['y1'];\n", + " x0 = Math.floor(x0) + 0.5;\n", + " y0 = Math.floor(y0) + 0.5;\n", + " x1 = Math.floor(x1) + 0.5;\n", + " y1 = Math.floor(y1) + 0.5;\n", + " var min_x = Math.min(x0, x1);\n", + " var min_y = Math.min(y0, y1);\n", + " var width = Math.abs(x1 - x0);\n", + " var height = Math.abs(y1 - y0);\n", + "\n", + " fig.rubberband_context.clearRect(\n", + " 0, 0, fig.canvas.width, fig.canvas.height);\n", + "\n", + " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n", + " // Updates the figure title.\n", + " fig.header.textContent = msg['label'];\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n", + " var cursor = msg['cursor'];\n", + " switch(cursor)\n", + " {\n", + " case 0:\n", + " cursor = 'pointer';\n", + " break;\n", + " case 1:\n", + " cursor = 'default';\n", + " break;\n", + " case 2:\n", + " cursor = 'crosshair';\n", + " break;\n", + " case 3:\n", + " cursor = 'move';\n", + " break;\n", + " }\n", + " fig.rubberband_canvas.style.cursor = cursor;\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_message = function(fig, msg) {\n", + " fig.message.textContent = msg['message'];\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_draw = function(fig, msg) {\n", + " // Request the server to send over a new figure.\n", + " fig.send_draw_message();\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n", + " fig.image_mode = msg['mode'];\n", + "}\n", + "\n", + "mpl.figure.prototype.updated_canvas_event = function() {\n", + " // Called whenever the canvas gets updated.\n", + " this.send_message(\"ack\", {});\n", + "}\n", + "\n", + "// A function to construct a web socket function for onmessage handling.\n", + "// Called in the figure constructor.\n", + "mpl.figure.prototype._make_on_message_function = function(fig) {\n", + " return function socket_on_message(evt) {\n", + " if (evt.data instanceof Blob) {\n", + " /* FIXME: We get \"Resource interpreted as Image but\n", + " * transferred with MIME type text/plain:\" errors on\n", + " * Chrome. But how to set the MIME type? It doesn't seem\n", + " * to be part of the websocket stream */\n", + " evt.data.type = \"image/png\";\n", + "\n", + " /* Free the memory for the previous frames */\n", + " if (fig.imageObj.src) {\n", + " (window.URL || window.webkitURL).revokeObjectURL(\n", + " fig.imageObj.src);\n", + " }\n", + "\n", + " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", + " evt.data);\n", + " fig.updated_canvas_event();\n", + " fig.waiting = false;\n", + " return;\n", + " }\n", + " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n", + " fig.imageObj.src = evt.data;\n", + " fig.updated_canvas_event();\n", + " fig.waiting = false;\n", + " return;\n", + " }\n", + "\n", + " var msg = JSON.parse(evt.data);\n", + " var msg_type = msg['type'];\n", + "\n", + " // Call the \"handle_{type}\" callback, which takes\n", + " // the figure and JSON message as its only arguments.\n", + " try {\n", + " var callback = fig[\"handle_\" + msg_type];\n", + " } catch (e) {\n", + " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n", + " return;\n", + " }\n", + "\n", + " if (callback) {\n", + " try {\n", + " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", + " callback(fig, msg);\n", + " } catch (e) {\n", + " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n", + " }\n", + " }\n", + " };\n", + "}\n", + "\n", + "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", + "mpl.findpos = function(e) {\n", + " //this section is from http://www.quirksmode.org/js/events_properties.html\n", + " var targ;\n", + " if (!e)\n", + " e = window.event;\n", + " if (e.target)\n", + " targ = e.target;\n", + " else if (e.srcElement)\n", + " targ = e.srcElement;\n", + " if (targ.nodeType == 3) // defeat Safari bug\n", + " targ = targ.parentNode;\n", + "\n", + " // jQuery normalizes the pageX and pageY\n", + " // pageX,Y are the mouse positions relative to the document\n", + " // offset() returns the position of the element relative to the document\n", + " var x = e.pageX - $(targ).offset().left;\n", + " var y = e.pageY - $(targ).offset().top;\n", + "\n", + " return {\"x\": x, \"y\": y};\n", + "};\n", + "\n", + "/*\n", + " * return a copy of an object with only non-object keys\n", + " * we need this to avoid circular references\n", + " * http://stackoverflow.com/a/24161582/3208463\n", + " */\n", + "function simpleKeys (original) {\n", + " return Object.keys(original).reduce(function (obj, key) {\n", + " if (typeof original[key] !== 'object')\n", + " obj[key] = original[key]\n", + " return obj;\n", + " }, {});\n", + "}\n", + "\n", + "mpl.figure.prototype.mouse_event = function(event, name) {\n", + " var canvas_pos = mpl.findpos(event)\n", + "\n", + " if (name === 'button_press')\n", + " {\n", + " this.canvas.focus();\n", + " this.canvas_div.focus();\n", + " }\n", + "\n", + " var x = canvas_pos.x;\n", + " var y = canvas_pos.y;\n", + "\n", + " this.send_message(name, {x: x, y: y, button: event.button,\n", + " step: event.step,\n", + " guiEvent: simpleKeys(event)});\n", + "\n", + " /* This prevents the web browser from automatically changing to\n", + " * the text insertion cursor when the button is pressed. We want\n", + " * to control all of the cursor setting manually through the\n", + " * 'cursor' event from matplotlib */\n", + " event.preventDefault();\n", + " return false;\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " // Handle any extra behaviour associated with a key event\n", + "}\n", + "\n", + "mpl.figure.prototype.key_event = function(event, name) {\n", + "\n", + " // Prevent repeat events\n", + " if (name == 'key_press')\n", + " {\n", + " if (event.which === this._key)\n", + " return;\n", + " else\n", + " this._key = event.which;\n", + " }\n", + " if (name == 'key_release')\n", + " this._key = null;\n", + "\n", + " var value = '';\n", + " if (event.ctrlKey && event.which != 17)\n", + " value += \"ctrl+\";\n", + " if (event.altKey && event.which != 18)\n", + " value += \"alt+\";\n", + " if (event.shiftKey && event.which != 16)\n", + " value += \"shift+\";\n", + "\n", + " value += 'k';\n", + " value += event.which.toString();\n", + "\n", + " this._key_event_extra(event, name);\n", + "\n", + " this.send_message(name, {key: value,\n", + " guiEvent: simpleKeys(event)});\n", + " return false;\n", + "}\n", + "\n", + "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n", + " if (name == 'download') {\n", + " this.handle_save(this, null);\n", + " } else {\n", + " this.send_message(\"toolbar_button\", {name: name});\n", + " }\n", + "};\n", + "\n", + "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", + " this.message.textContent = tooltip;\n", + "};\n", + "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", + "\n", + "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n", + "\n", + "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n", + " // Create a \"websocket\"-like object which calls the given IPython comm\n", + " // object with the appropriate methods. Currently this is a non binary\n", + " // socket, so there is still some room for performance tuning.\n", + " var ws = {};\n", + "\n", + " ws.close = function() {\n", + " comm.close()\n", + " };\n", + " ws.send = function(m) {\n", + " //console.log('sending', m);\n", + " comm.send(m);\n", + " };\n", + " // Register the callback with on_msg.\n", + " comm.on_msg(function(msg) {\n", + " //console.log('receiving', msg['content']['data'], msg);\n", + " // Pass the mpl event to the overriden (by mpl) onmessage function.\n", + " ws.onmessage(msg['content']['data'])\n", + " });\n", + " return ws;\n", + "}\n", + "\n", + "mpl.mpl_figure_comm = function(comm, msg) {\n", + " // This is the function which gets called when the mpl process\n", + " // starts-up an IPython Comm through the \"matplotlib\" channel.\n", + "\n", + " var id = msg.content.data.id;\n", + " // Get hold of the div created by the display call when the Comm\n", + " // socket was opened in Python.\n", + " var element = $(\"#\" + id);\n", + " var ws_proxy = comm_websocket_adapter(comm)\n", + "\n", + " function ondownload(figure, format) {\n", + " window.open(figure.imageObj.src);\n", + " }\n", + "\n", + " var fig = new mpl.figure(id, ws_proxy,\n", + " ondownload,\n", + " element.get(0));\n", + "\n", + " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", + " // web socket which is closed, not our websocket->open comm proxy.\n", + " ws_proxy.onopen();\n", + "\n", + " fig.parent_element = element.get(0);\n", + " fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n", + " if (!fig.cell_info) {\n", + " console.error(\"Failed to find cell for figure\", id, fig);\n", + " return;\n", + " }\n", + "\n", + " var output_index = fig.cell_info[2]\n", + " var cell = fig.cell_info[0];\n", + "\n", + "};\n", + "\n", + "mpl.figure.prototype.handle_close = function(fig, msg) {\n", + " fig.root.unbind('remove')\n", + "\n", + " // Update the output cell to use the data from the current canvas.\n", + " fig.push_to_output();\n", + " var dataURL = fig.canvas.toDataURL();\n", + " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", + " // the notebook keyboard shortcuts fail.\n", + " IPython.keyboard_manager.enable()\n", + " $(fig.parent_element).html('<img src=\"' + dataURL + '\">');\n", + " fig.close_ws(fig, msg);\n", + "}\n", + "\n", + "mpl.figure.prototype.close_ws = function(fig, msg){\n", + " fig.send_message('closing', msg);\n", + " // fig.ws.close()\n", + "}\n", + "\n", + "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", + " // Turn the data on the canvas into data in the output cell.\n", + " var dataURL = this.canvas.toDataURL();\n", + " this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n", + "}\n", + "\n", + "mpl.figure.prototype.updated_canvas_event = function() {\n", + " // Tell IPython that the notebook contents must change.\n", + " IPython.notebook.set_dirty(true);\n", + " this.send_message(\"ack\", {});\n", + " var fig = this;\n", + " // Wait a second, then push the new image to the DOM so\n", + " // that it is saved nicely (might be nice to debounce this).\n", + " setTimeout(function () { fig.push_to_output() }, 1000);\n", + "}\n", + "\n", + "mpl.figure.prototype._init_toolbar = function() {\n", + " var fig = this;\n", + "\n", + " var nav_element = $('<div/>')\n", + " nav_element.attr('style', 'width: 100%');\n", + " this.root.append(nav_element);\n", + "\n", + " // Define a callback function for later on.\n", + " function toolbar_event(event) {\n", + " return fig.toolbar_button_onclick(event['data']);\n", + " }\n", + " function toolbar_mouse_event(event) {\n", + " return fig.toolbar_button_onmouseover(event['data']);\n", + " }\n", + "\n", + " for(var toolbar_ind in mpl.toolbar_items){\n", + " var name = mpl.toolbar_items[toolbar_ind][0];\n", + " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", + " var image = mpl.toolbar_items[toolbar_ind][2];\n", + " var method_name = mpl.toolbar_items[toolbar_ind][3];\n", + "\n", + " if (!name) { continue; };\n", + "\n", + " var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", + " button.click(method_name, toolbar_event);\n", + " button.mouseover(tooltip, toolbar_mouse_event);\n", + " nav_element.append(button);\n", + " }\n", + "\n", + " // Add the status bar.\n", + " var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", + " nav_element.append(status_bar);\n", + " this.message = status_bar[0];\n", + "\n", + " // Add the close button to the window.\n", + " var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", + " var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", + " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", + " button.mouseover('Stop Interaction', toolbar_mouse_event);\n", + " buttongrp.append(button);\n", + " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", + " titlebar.prepend(buttongrp);\n", + "}\n", + "\n", + "mpl.figure.prototype._root_extra_style = function(el){\n", + " var fig = this\n", + " el.on(\"remove\", function(){\n", + "\tfig.close_ws(fig, {});\n", + " });\n", + "}\n", + "\n", + "mpl.figure.prototype._canvas_extra_style = function(el){\n", + " // this is important to make the div 'focusable\n", + " el.attr('tabindex', 0)\n", + " // reach out to IPython and tell the keyboard manager to turn it's self\n", + " // off when our div gets focus\n", + "\n", + " // location in version 3\n", + " if (IPython.notebook.keyboard_manager) {\n", + " IPython.notebook.keyboard_manager.register_events(el);\n", + " }\n", + " else {\n", + " // location in version 2\n", + " IPython.keyboard_manager.register_events(el);\n", + " }\n", + "\n", + "}\n", + "\n", + "mpl.figure.prototype._key_event_extra = function(event, name) {\n", + " var manager = IPython.notebook.keyboard_manager;\n", + " if (!manager)\n", + " manager = IPython.keyboard_manager;\n", + "\n", + " // Check for shift+enter\n", + " if (event.shiftKey && event.which == 13) {\n", + " this.canvas_div.blur();\n", + " event.shiftKey = false;\n", + " // Send a \"J\" for go to next cell\n", + " event.which = 74;\n", + " event.keyCode = 74;\n", + " manager.command_mode();\n", + " manager.handle_keydown(event);\n", + " }\n", + "}\n", + "\n", + "mpl.figure.prototype.handle_save = function(fig, msg) {\n", + " fig.ondownload(fig, null);\n", + "}\n", + "\n", + "\n", + "mpl.find_output_cell = function(html_output) {\n", + " // Return the cell and output element which can be found *uniquely* in the notebook.\n", + " // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", + " // IPython event is triggered only after the cells have been serialised, which for\n", + " // our purposes (turning an active figure into a static one), is too late.\n", + " var cells = IPython.notebook.get_cells();\n", + " var ncells = cells.length;\n", + " for (var i=0; i<ncells; i++) {\n", + " var cell = cells[i];\n", + " if (cell.cell_type === 'code'){\n", + " for (var j=0; j<cell.output_area.outputs.length; j++) {\n", + " var data = cell.output_area.outputs[j];\n", + " if (data.data) {\n", + " // IPython >= 3 moved mimebundle to data attribute of output\n", + " data = data.data;\n", + " }\n", + " if (data['text/html'] == html_output) {\n", + " return [cell, data, j];\n", + " }\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + "// Register the function which deals with the matplotlib target/channel.\n", + "// The kernel may be null if the page has been refreshed.\n", + "if (IPython.notebook.kernel != null) {\n", + " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", + "}\n" + ], + "text/plain": [ + "<IPython.core.display.Javascript object>" + ] + }, + "metadata": {}, + "output_type": "display_data" + }, + { + "data": { + "text/html": [ + "<img src=\"data:image/png;base64,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\">" + ], + "text/plain": [ + "<IPython.core.display.HTML object>" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "live_plot_rgb_splines(14, 15, 13, live=False)" + ] + }, + { + "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" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + } + }, + "nbformat": 4, + "nbformat_minor": 0 +} diff --git a/firmware/calc_framerate.py b/firmware/calc_framerate.py new file mode 100644 index 0000000..aaedc4d --- /dev/null +++ b/firmware/calc_framerate.py @@ -0,0 +1,38 @@ +#!/usr/bin/env python3 + +TIMER_FREQ = 30e6 # MHz + + +with open('main.c') as f: + lines = f.readlines() + +defs = {} +for line in lines: + if line.startswith('#define'): + _pragma, name, val, *_comment = line.split() + val = defs.get(val, val) + defs[name] = val + +print('Bit cycle timings:') +timings_total = 0 +in_array = False +for line in lines: + if not in_array: + if line.startswith('static uint16_t timer_period_lookup'): + in_array = True + else: + if '}' in line: + break + if ',' not in line: + continue + val, *_comment = line.split(',') + for name, defval in defs.items(): + val = val.replace(name, defval) + duration = eval(val) + print(duration) + timings_total += duration + int(defs['RESET_PERIOD_LENGTH']) + +total_len = timings_total/TIMER_FREQ +print('Total cycles:', timings_total) +print('Total cycle length: {:.3f}ms'.format(total_len*1e3)) +print('Frame rate: {:.3f}Hz'.format(1/total_len)) diff --git a/firmware/measure_spectrum.py b/firmware/measure_spectrum.py new file mode 100644 index 0000000..0e7dc22 --- /dev/null +++ b/firmware/measure_spectrum.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python3 + +import time +import statistics +import sqlite3 +from olsndot import Olsndot, Driver +from datetime import datetime + +from pyBusPirateLite import BitBang + +if __name__ == '__main__': + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument('run_name', nargs='?', default='auto') + parser.add_argument('buspirate_port', nargs='?', default='/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AD01W1RF-if00-port0') + parser.add_argument('-s', '--steps', type=int, nargs='?', default=100, help='Steps to run through') + parser.add_argument('-d', '--database', default='spectra.sqlite3', help='sqlite3 database file to store results in') + parser.add_argument('-w', '--wait', type=float, default=0.1, help='time to wait between samples in seconds') + parser.add_argument('-o', '--oversample', type=int, default=16, help='oversampling ratio') + args = parser.parse_args() + + db = sqlite3.connect(args.database) + db.execute(""" + CREATE TABLE IF NOT EXISTS runs ( + run_id INTEGER PRIMARY KEY, + name TEXT, + comment TEXT, + timestamp REAL -- unix timestamp in fractional seconds + )""") + db.execute(""" + CREATE TABLE IF NOT EXISTS measurements ( + measurement_id INTEGER PRIMARY KEY, + run_id INTEGER, + led_on INTEGER, + step INTEGER, + voltage REAL, -- volts + voltage_stdev REAL, -- volts + timestamp REAL, -- unix timestamp in fractional seconds + FOREIGN KEY (run_id) REFERENCES runs)""") + + class BPState: + def __init__(self, port): + self.bp = BitBang(port) + self._led = 0 + self._stepper_dir = 'down' + self.reinit() + + def reinit(self): + self.bp.enter_bb() + self.led(self._led) + self.stepper_direction(self._stepper_dir) + self.bp.cs = 0 + + def led(self, st): + self._led = st + self.bp.mosi = st + + def stepper_direction(self, direction): + self._stepper_dir = direction + self.bp.aux = 0 if direction == 'down' else 1 + + def step(self): + self.bp.cs = 1 + time.sleep(0.005) + self.bp.cs = 0 + time.sleep(0.005) + + def adc(self, oversampling): + self.reinit() + return [ self.bp.adc_value for _ in range(oversampling) ] + + bp = BPState(args.buspirate_port) + + run_name = args.run_name + if not str.isnumeric(args.run_name[-1]): + names = [ n[len(run_name):] for n, in db.execute( + 'SELECT name FROM runs WHERE name LIKE ?||"%"', (run_name,)).fetchall() ] + names.append('0') # in case we get no results + run_name += str(1+max(int(n) if str.isnumeric(n) else 0 for n in names)) + with db: + cur = db.cursor() + cur.execute('INSERT INTO runs(name, timestamp) VALUES (?, ?)', + (run_name, time.time())) + run_id = cur.lastrowid + + print('Starting run {} "{}" at {:%y-%m-%d %H:%M:%S:%f}'.format(run_id, run_name, datetime.now())) + print('[measurement id] " " [step number] " " [reading (V)]') + + bp.stepper_direction('down') + for _ in range(10): + bp.step() + + bp.stepper_direction('up') + for step in range(args.steps): + bp.step() + for led_val in [0, 1]: + try: + bp.led(led_val) + time.sleep(args.wait) + + readings = bp.adc(args.oversample) + mean, stdev = statistics.mean(readings), statistics.stdev(readings) + + with db: + cur = db.cursor() + cur.execute(''' + INSERT INTO measurements ( + run_id, led_on, step, voltage, voltage_stdev, timestamp + ) VALUES (?, ?, ?, ?, ?, ?)''', + (run_id, led_val, step, mean, stdev, time.time())) + print('{:08d} {:03} {}: {:5.4f} stdev {:5.4f}'.format( + cur.lastrowid, step, led_val, mean, stdev)) + except KeyboardInterrupt: + raise + except TypeError as e: + print('Buspirate hiccup, ignoring:', e) + + bp.stepper_direction('down') + for _ in range(args.steps): + bp.step() + diff --git a/firmware/offset_test.py b/firmware/offset_test.py index ca308a6..f2b8b2f 100644 --- a/firmware/offset_test.py +++ b/firmware/offset_test.py @@ -1,3 +1,4 @@ +#!/usr/bin/env python3 import time import statistics diff --git a/firmware/results.sqlite3 b/firmware/results.sqlite3 Binary files differindex 25115c7..d0ede6a 100644 --- a/firmware/results.sqlite3 +++ b/firmware/results.sqlite3 diff --git a/firmware/spectra.sqlite3 b/firmware/spectra.sqlite3 Binary files differnew file mode 100644 index 0000000..c82c2fe --- /dev/null +++ b/firmware/spectra.sqlite3 diff --git a/firmware/spectrum_progress.py b/firmware/spectrum_progress.py new file mode 100644 index 0000000..a4eb4b2 --- /dev/null +++ b/firmware/spectrum_progress.py @@ -0,0 +1,32 @@ +#!/usr/bin/env python3 +import sqlite3 +import argparse +import time + +import tqdm + +if __name__ == '__main__': + parser = argparse.ArgumentParser() + parser.add_argument('-d', '--database', nargs='?', default='spectra.sqlite3') + parser.add_argument('-u', '--update-delay', nargs='?', type=float, default=1.0) + parser.add_argument('max_step', nargs='?', type=int, default=250) + args = parser.parse_args() + + db = sqlite3.connect(args.database) + def current_step(): + step, = db.execute( + 'SELECT MAX(step) FROM measurements WHERE run_id = (SELECT MAX(run_id) FROM runs)' + ).fetchone() + return int(step)+1 + + def step_gen(): + while True: + step = current_step() + yield step + if step >= args.max_step: + break + time.sleep(args.update_delay) + + bar = tqdm.tqdm(total=args.max_step) + for step in step_gen(): + bar.update(step - bar.n) diff --git a/firmware/stepper_test.py b/firmware/stepper_test.py new file mode 100644 index 0000000..919fc02 --- /dev/null +++ b/firmware/stepper_test.py @@ -0,0 +1,56 @@ +#!/usr/bin/env python3 + +import time +import statistics +import sqlite3 +from olsndot import Olsndot, Driver +from datetime import datetime + +from pyBusPirateLite import BitBang + +if __name__ == '__main__': + import argparse + + parser = argparse.ArgumentParser() + parser.add_argument('buspirate_port', nargs='?', default='/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AD01W1RF-if00-port0') + args = parser.parse_args() + + bp = BitBang(args.buspirate_port) + bp.enter_bb() + bp.mosi = 1 + + def stepper_direction_down(): + bp.aux = 0 + + def stepper_direction_up(): + bp.aux = 1 + + def stepper_step(): + bp.cs = 1 + time.sleep(0.005) + bp.cs = 0 + time.sleep(0.005) + + import curses + screen = curses.initscr() + curses.noecho() + curses.cbreak() + screen.keypad(True) + try: + while True: + key = screen.getch() + if key == ord('q'): + break + + if key == curses.KEY_DOWN: + stepper_direction_down() + stepper_step() + elif key == curses.KEY_UP: + stepper_direction_up() + stepper_step() + + finally: + curses.nocbreak() + screen.keypad(0) + curses.echo() + curses.endwin() |