From bedc614e20b87b783c8420132afc8fd8e478c4bd Mon Sep 17 00:00:00 2001 From: jaseg Date: Sun, 13 May 2018 20:58:55 +0200 Subject: Move to new run capture arch --- firmware/Spectrum Measurement.ipynb | 688 ++++++++++++++++++++++-------------- firmware/measure_spectrum.py | 29 +- firmware/results.sqlite3 | Bin 102400 -> 0 bytes firmware/spectra.sqlite3 | Bin 294912 -> 12288 bytes firmware/stepper_test.py | 1 - 5 files changed, 442 insertions(+), 276 deletions(-) delete mode 100644 firmware/results.sqlite3 (limited to 'firmware') diff --git a/firmware/Spectrum Measurement.ipynb b/firmware/Spectrum Measurement.ipynb index c77709a..66818a9 100644 --- a/firmware/Spectrum Measurement.ipynb +++ b/firmware/Spectrum Measurement.ipynb @@ -2,9 +2,9 @@ "cells": [ { "cell_type": "code", - "execution_count": 277, + "execution_count": 6, "metadata": { - "collapsed": false + "collapsed": true }, "outputs": [], "source": [ @@ -22,9 +22,9 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 7, "metadata": { - "collapsed": false + "collapsed": true }, "outputs": [], "source": [ @@ -33,9 +33,9 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 8, "metadata": { - "collapsed": false + "collapsed": true }, "outputs": [], "source": [ @@ -46,7 +46,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 9, "metadata": { "collapsed": true }, @@ -64,9 +64,9 @@ }, { "cell_type": "code", - "execution_count": 12, + "execution_count": 10, "metadata": { - "collapsed": false + "collapsed": true }, "outputs": [], "source": [ @@ -83,10 +83,8 @@ }, { "cell_type": "code", - "execution_count": 15, - "metadata": { - "collapsed": false - }, + "execution_count": 11, + "metadata": {}, "outputs": [ { "data": { @@ -94,6 +92,7 @@ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", + "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", @@ -152,6 +151,9 @@ " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", + " if (mpl.ratio != 1) {\n", + " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", + " }\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", @@ -221,6 +223,15 @@ " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", + " var backingStore = this.context.backingStorePixelRatio ||\n", + "\tthis.context.webkitBackingStorePixelRatio ||\n", + "\tthis.context.mozBackingStorePixelRatio ||\n", + "\tthis.context.msBackingStorePixelRatio ||\n", + "\tthis.context.oBackingStorePixelRatio ||\n", + "\tthis.context.backingStorePixelRatio || 1;\n", + "\n", + " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", + "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", @@ -277,8 +288,9 @@ " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", - " canvas.attr('width', width);\n", - " canvas.attr('height', height);\n", + " canvas.attr('width', width * mpl.ratio);\n", + " canvas.attr('height', height * mpl.ratio);\n", + " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", @@ -411,10 +423,10 @@ "}\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", + " var x0 = msg['x0'] / mpl.ratio;\n", + " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n", + " var x1 = msg['x1'] / mpl.ratio;\n", + " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n", " x0 = Math.floor(x0) + 0.5;\n", " y0 = Math.floor(y0) + 0.5;\n", " x1 = Math.floor(x1) + 0.5;\n", @@ -570,8 +582,8 @@ " this.canvas_div.focus();\n", " }\n", "\n", - " var x = canvas_pos.x;\n", - " var y = canvas_pos.y;\n", + " var x = canvas_pos.x * mpl.ratio;\n", + " var y = canvas_pos.y * mpl.ratio;\n", "\n", " this.send_message(name, {x: x, y: y, button: event.button,\n", " step: event.step,\n", @@ -692,6 +704,7 @@ "};\n", "\n", "mpl.figure.prototype.handle_close = function(fig, msg) {\n", + " var width = fig.canvas.width/mpl.ratio\n", " fig.root.unbind('remove')\n", "\n", " // Update the output cell to use the data from the current canvas.\n", @@ -700,7 +713,7 @@ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", " // the notebook keyboard shortcuts fail.\n", " IPython.keyboard_manager.enable()\n", - " $(fig.parent_element).html('');\n", + " $(fig.parent_element).html('');\n", " fig.close_ws(fig, msg);\n", "}\n", "\n", @@ -711,8 +724,9 @@ "\n", "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", " // Turn the data on the canvas into data in the output cell.\n", + " var width = this.canvas.width/mpl.ratio\n", " var dataURL = this.canvas.toDataURL();\n", - " this.cell_info[1]['text/html'] = '';\n", + " this.cell_info[1]['text/html'] = '';\n", "}\n", "\n", "mpl.figure.prototype.updated_canvas_event = function() {\n", @@ -801,12 +815,9 @@ " // 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", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", " }\n", "}\n", "\n", @@ -855,7 +866,7 @@ { "data": { "text/html": [ - "" + "
" ], "text/plain": [ "" @@ -863,6 +874,19 @@ }, "metadata": {}, "output_type": "display_data" + }, + { + "ename": "OperationalError", + "evalue": "no such column: run_id", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mOperationalError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mplot_rgb\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m10\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m9\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m12\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m\u001b[0m in \u001b[0;36mplot_rgb\u001b[0;34m(id_r, id_g, id_b, loader)\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mfig\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msuptitle\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'Runs {}, {}, {} at {:%y-%m-%d %H:%M:%S}'\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mformat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mid_r\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mid_g\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mid_b\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mdatetime\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnow\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mrun_id\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcolor\u001b[0m \u001b[0;32min\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mid_g\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'green'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mid_r\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'red'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mid_b\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'blue'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0msteps\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstdev\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mloader\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrun_id\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 6\u001b[0m \u001b[0max\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0merrorbar\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0msteps\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mvalues\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0myerr\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mstdev\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mcolor\u001b[0m\u001b[0;34m=\u001b[0m\u001b[0mcolor\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 7\u001b[0m \u001b[0;31m#ax.set_ylim([2.2, 5])\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mload_run\u001b[0;34m(run_id)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mload_run\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrun_id\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mdata\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mdb\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mexecute\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'SELECT step, voltage, voltage_stdev FROM measurements WHERE run_id = ? AND led_on = 1 ORDER BY step ASC'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0mrun_id\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mfetchall\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mzip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0mdata\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mOperationalError\u001b[0m: no such column: run_id" + ] } ], "source": [ @@ -871,9 +895,9 @@ }, { "cell_type": "code", - "execution_count": 16, + "execution_count": null, "metadata": { - "collapsed": false + "collapsed": true }, "outputs": [], "source": [ @@ -892,9 +916,74 @@ }, { "cell_type": "code", - "execution_count": 18, + "execution_count": null, "metadata": { - "collapsed": false + "collapsed": true + }, + "outputs": [], + "source": [ + "#live_plot_rgb(14, 15, 13, loader=load_run_zero_cal)" + ] + }, + { + "cell_type": "code", + "execution_count": 116, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def live_plot_rgb_splines(id_r, id_g, id_b, id_w=None,\n", + " max_stdev=0.05, spline_s=1, interval=1,\n", + " live=True, show_title=True, save_svg=None):\n", + " fig, ax = plt.subplots(1, 1)\n", + " if show_title:\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,0,0.2)),\n", + " # ((0,1,0), (0,1,0,0.2)),\n", + " # ((0,0,1), (0,0,1,0.2)),\n", + " # ((0,0,0), (0,0,0,0.2))\n", + " #]\n", + " colors = [\n", + " (('#fe3ea0', '#ffd2e9')) #ff99cc\n", + " ]*4\n", + " runs = [id_r, id_g, id_b] if id_w is None else [id_r, id_g, id_b, id_w]\n", + " for run_id, (color_dark, color_bright) in zip(runs, colors):\n", + " steps, values, stdev = load_run_zero_cal(run_id, max_stdev)\n", + " ax.errorbar(steps, values, yerr=stdev, color=color_bright, zorder=1)\n", + " ax.spines['top'].set_visible(False)\n", + " ax.spines['right'].set_visible(False)\n", + " ax.spines['bottom'].set_color('#08bdf9')\n", + " ax.spines['left'].set_color('#08bdf9')\n", + " ax.tick_params(axis='x', colors='#01769D')\n", + " ax.tick_params(axis='y', colors='#01769D')\n", + " ax.xaxis.label.set_color('#01769D')\n", + " ax.yaxis.label.set_color('#01769D')\n", + " ax.set_xlabel('x [steps]')\n", + " ax.set_ylabel('Vpd [V]')\n", + " ax.grid(color='#08bdf9', linestyle=':')\n", + " try:\n", + " spline = inter.UnivariateSpline(steps, values, s=spline_s)\n", + " ax.plot(steps, spline(steps), color=color_dark, zorder=2)\n", + " except:\n", + " pass\n", + " fig.canvas.draw()\n", + " if save_svg:\n", + " fig.savefig(save_svg)\n", + " if save_svg or not live:\n", + " break\n", + " time.sleep(1)" + ] + }, + { + "cell_type": "code", + "execution_count": 117, + "metadata": { + "scrolled": false }, "outputs": [ { @@ -903,6 +992,7 @@ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", + "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", @@ -961,6 +1051,9 @@ " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", + " if (mpl.ratio != 1) {\n", + " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", + " }\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", @@ -1030,6 +1123,15 @@ " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", + " var backingStore = this.context.backingStorePixelRatio ||\n", + "\tthis.context.webkitBackingStorePixelRatio ||\n", + "\tthis.context.mozBackingStorePixelRatio ||\n", + "\tthis.context.msBackingStorePixelRatio ||\n", + "\tthis.context.oBackingStorePixelRatio ||\n", + "\tthis.context.backingStorePixelRatio || 1;\n", + "\n", + " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", + "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", @@ -1086,8 +1188,9 @@ " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", - " canvas.attr('width', width);\n", - " canvas.attr('height', height);\n", + " canvas.attr('width', width * mpl.ratio);\n", + " canvas.attr('height', height * mpl.ratio);\n", + " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", @@ -1220,10 +1323,10 @@ "}\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", + " var x0 = msg['x0'] / mpl.ratio;\n", + " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n", + " var x1 = msg['x1'] / mpl.ratio;\n", + " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n", " x0 = Math.floor(x0) + 0.5;\n", " y0 = Math.floor(y0) + 0.5;\n", " x1 = Math.floor(x1) + 0.5;\n", @@ -1379,8 +1482,8 @@ " this.canvas_div.focus();\n", " }\n", "\n", - " var x = canvas_pos.x;\n", - " var y = canvas_pos.y;\n", + " var x = canvas_pos.x * mpl.ratio;\n", + " var y = canvas_pos.y * mpl.ratio;\n", "\n", " this.send_message(name, {x: x, y: y, button: event.button,\n", " step: event.step,\n", @@ -1501,6 +1604,7 @@ "};\n", "\n", "mpl.figure.prototype.handle_close = function(fig, msg) {\n", + " var width = fig.canvas.width/mpl.ratio\n", " fig.root.unbind('remove')\n", "\n", " // Update the output cell to use the data from the current canvas.\n", @@ -1509,7 +1613,7 @@ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", " // the notebook keyboard shortcuts fail.\n", " IPython.keyboard_manager.enable()\n", - " $(fig.parent_element).html('');\n", + " $(fig.parent_element).html('');\n", " fig.close_ws(fig, msg);\n", "}\n", "\n", @@ -1520,8 +1624,9 @@ "\n", "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", " // Turn the data on the canvas into data in the output cell.\n", + " var width = this.canvas.width/mpl.ratio\n", " var dataURL = this.canvas.toDataURL();\n", - " this.cell_info[1]['text/html'] = '';\n", + " this.cell_info[1]['text/html'] = '';\n", "}\n", "\n", "mpl.figure.prototype.updated_canvas_event = function() {\n", @@ -1610,12 +1715,9 @@ " // 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", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", " }\n", "}\n", "\n", @@ -1664,7 +1766,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -1672,63 +1774,27 @@ }, "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\u001b[0m in \u001b[0;36m\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\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)" + "#live_plot_rgb_splines(14, 15, 13, live=False, show_title=False)\n", + "live_plot_rgb_splines(45, 46, 44, spline_s=0.08, max_stdev=1.0, live=False, show_title=False, save_svg='/tmp/raw_plot_cheap_rgb.svg')" ] }, { - "cell_type": "code", - "execution_count": 72, - "metadata": { - "collapsed": false - }, - "outputs": [], + "cell_type": "markdown", + "metadata": {}, "source": [ - "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.8,0.8)),\n", - " ((0,1,0), (0.8,1,0.8)),\n", - " ((0,0,1), (0.8,0.8,1))\n", - " ]\n", - " for run_id, (color_dark, color_bright) in zip([id_r, id_g, id_b], colors):\n", - " steps, values, stdev = load_run_zero_cal(run_id, max_stdev)\n", - " ax.errorbar(steps, values, yerr=stdev, color=color_bright)\n", - " try:\n", - " spline = inter.UnivariateSpline(steps, values, s=spline_s)\n", - " ax.plot(steps, spline(steps), color=color_dark)\n", - " except:\n", - " pass\n", - " fig.canvas.draw()\n", - " if not live:\n", - " break\n", - " time.sleep(1)" + "* Go further than step 250 to capture some zeros beyond the red band to allow the spline fitter to do its job more properly\n", + "* Move the entire screen further down and further increase range to properly capture blue rolloff\n", + "* Decrease amplification to avoid clipping. Maybe change amplification midway for green channel. Currenlty set to 5GOhm using 10M transimp feedback R with 1:10 T feedback and ~1:50 gain voltage amp stage. Maybe go back to plain transimp amp with 10M gain, for a total gain of 500M\n", + "* Decrease VGND bias to allow for more headroom" ] }, { "cell_type": "code", - "execution_count": 40, - "metadata": { - "collapsed": false - }, + "execution_count": 118, + "metadata": {}, "outputs": [ { "data": { @@ -1736,6 +1802,7 @@ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", + "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", @@ -1794,6 +1861,9 @@ " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", + " if (mpl.ratio != 1) {\n", + " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", + " }\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", @@ -1863,6 +1933,15 @@ " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", + " var backingStore = this.context.backingStorePixelRatio ||\n", + "\tthis.context.webkitBackingStorePixelRatio ||\n", + "\tthis.context.mozBackingStorePixelRatio ||\n", + "\tthis.context.msBackingStorePixelRatio ||\n", + "\tthis.context.oBackingStorePixelRatio ||\n", + "\tthis.context.backingStorePixelRatio || 1;\n", + "\n", + " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", + "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", @@ -1919,8 +1998,9 @@ " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", - " canvas.attr('width', width);\n", - " canvas.attr('height', height);\n", + " canvas.attr('width', width * mpl.ratio);\n", + " canvas.attr('height', height * mpl.ratio);\n", + " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", @@ -2053,10 +2133,10 @@ "}\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", + " var x0 = msg['x0'] / mpl.ratio;\n", + " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n", + " var x1 = msg['x1'] / mpl.ratio;\n", + " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n", " x0 = Math.floor(x0) + 0.5;\n", " y0 = Math.floor(y0) + 0.5;\n", " x1 = Math.floor(x1) + 0.5;\n", @@ -2212,8 +2292,8 @@ " this.canvas_div.focus();\n", " }\n", "\n", - " var x = canvas_pos.x;\n", - " var y = canvas_pos.y;\n", + " var x = canvas_pos.x * mpl.ratio;\n", + " var y = canvas_pos.y * mpl.ratio;\n", "\n", " this.send_message(name, {x: x, y: y, button: event.button,\n", " step: event.step,\n", @@ -2334,6 +2414,7 @@ "};\n", "\n", "mpl.figure.prototype.handle_close = function(fig, msg) {\n", + " var width = fig.canvas.width/mpl.ratio\n", " fig.root.unbind('remove')\n", "\n", " // Update the output cell to use the data from the current canvas.\n", @@ -2342,7 +2423,7 @@ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", " // the notebook keyboard shortcuts fail.\n", " IPython.keyboard_manager.enable()\n", - " $(fig.parent_element).html('');\n", + " $(fig.parent_element).html('');\n", " fig.close_ws(fig, msg);\n", "}\n", "\n", @@ -2353,8 +2434,9 @@ "\n", "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", " // Turn the data on the canvas into data in the output cell.\n", + " var width = this.canvas.width/mpl.ratio\n", " var dataURL = this.canvas.toDataURL();\n", - " this.cell_info[1]['text/html'] = '';\n", + " this.cell_info[1]['text/html'] = '';\n", "}\n", "\n", "mpl.figure.prototype.updated_canvas_event = function() {\n", @@ -2443,12 +2525,9 @@ " // 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", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", " }\n", "}\n", "\n", @@ -2497,7 +2576,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -2508,24 +2587,14 @@ } ], "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" + "live_plot_rgb_splines(42, 43, 40, spline_s=0.01, max_stdev=1.0, live=False)" ] }, { "cell_type": "code", - "execution_count": 96, + "execution_count": 119, "metadata": { - "collapsed": false + "scrolled": false }, "outputs": [ { @@ -2534,6 +2603,7 @@ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", + "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", @@ -2592,6 +2662,9 @@ " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", + " if (mpl.ratio != 1) {\n", + " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", + " }\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", @@ -2661,6 +2734,15 @@ " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", + " var backingStore = this.context.backingStorePixelRatio ||\n", + "\tthis.context.webkitBackingStorePixelRatio ||\n", + "\tthis.context.mozBackingStorePixelRatio ||\n", + "\tthis.context.msBackingStorePixelRatio ||\n", + "\tthis.context.oBackingStorePixelRatio ||\n", + "\tthis.context.backingStorePixelRatio || 1;\n", + "\n", + " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", + "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", @@ -2717,8 +2799,9 @@ " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", - " canvas.attr('width', width);\n", - " canvas.attr('height', height);\n", + " canvas.attr('width', width * mpl.ratio);\n", + " canvas.attr('height', height * mpl.ratio);\n", + " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", @@ -2851,10 +2934,10 @@ "}\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", + " var x0 = msg['x0'] / mpl.ratio;\n", + " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n", + " var x1 = msg['x1'] / mpl.ratio;\n", + " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n", " x0 = Math.floor(x0) + 0.5;\n", " y0 = Math.floor(y0) + 0.5;\n", " x1 = Math.floor(x1) + 0.5;\n", @@ -3010,8 +3093,8 @@ " this.canvas_div.focus();\n", " }\n", "\n", - " var x = canvas_pos.x;\n", - " var y = canvas_pos.y;\n", + " var x = canvas_pos.x * mpl.ratio;\n", + " var y = canvas_pos.y * mpl.ratio;\n", "\n", " this.send_message(name, {x: x, y: y, button: event.button,\n", " step: event.step,\n", @@ -3132,6 +3215,7 @@ "};\n", "\n", "mpl.figure.prototype.handle_close = function(fig, msg) {\n", + " var width = fig.canvas.width/mpl.ratio\n", " fig.root.unbind('remove')\n", "\n", " // Update the output cell to use the data from the current canvas.\n", @@ -3140,7 +3224,7 @@ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", " // the notebook keyboard shortcuts fail.\n", " IPython.keyboard_manager.enable()\n", - " $(fig.parent_element).html('');\n", + " $(fig.parent_element).html('');\n", " fig.close_ws(fig, msg);\n", "}\n", "\n", @@ -3151,8 +3235,9 @@ "\n", "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", " // Turn the data on the canvas into data in the output cell.\n", + " var width = this.canvas.width/mpl.ratio\n", " var dataURL = this.canvas.toDataURL();\n", - " this.cell_info[1]['text/html'] = '';\n", + " this.cell_info[1]['text/html'] = '';\n", "}\n", "\n", "mpl.figure.prototype.updated_canvas_event = function() {\n", @@ -3241,12 +3326,9 @@ " // 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", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", " }\n", "}\n", "\n", @@ -3295,7 +3377,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -3306,16 +3388,13 @@ } ], "source": [ - "live_plot_rgb_splines(42, 43, 40, spline_s=0.01, max_stdev=1.0, live=False)" + "live_plot_rgb_splines(45, 46, 44, spline_s=0.08, max_stdev=1.0, live=False)" ] }, { "cell_type": "code", - "execution_count": 104, - "metadata": { - "collapsed": false, - "scrolled": false - }, + "execution_count": 120, + "metadata": {}, "outputs": [ { "data": { @@ -3323,6 +3402,7 @@ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", + "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", @@ -3381,6 +3461,9 @@ " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", + " if (mpl.ratio != 1) {\n", + " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", + " }\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", @@ -3450,6 +3533,15 @@ " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", + " var backingStore = this.context.backingStorePixelRatio ||\n", + "\tthis.context.webkitBackingStorePixelRatio ||\n", + "\tthis.context.mozBackingStorePixelRatio ||\n", + "\tthis.context.msBackingStorePixelRatio ||\n", + "\tthis.context.oBackingStorePixelRatio ||\n", + "\tthis.context.backingStorePixelRatio || 1;\n", + "\n", + " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", + "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", @@ -3506,8 +3598,9 @@ " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", - " canvas.attr('width', width);\n", - " canvas.attr('height', height);\n", + " canvas.attr('width', width * mpl.ratio);\n", + " canvas.attr('height', height * mpl.ratio);\n", + " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", @@ -3640,10 +3733,10 @@ "}\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", + " var x0 = msg['x0'] / mpl.ratio;\n", + " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n", + " var x1 = msg['x1'] / mpl.ratio;\n", + " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n", " x0 = Math.floor(x0) + 0.5;\n", " y0 = Math.floor(y0) + 0.5;\n", " x1 = Math.floor(x1) + 0.5;\n", @@ -3799,8 +3892,8 @@ " this.canvas_div.focus();\n", " }\n", "\n", - " var x = canvas_pos.x;\n", - " var y = canvas_pos.y;\n", + " var x = canvas_pos.x * mpl.ratio;\n", + " var y = canvas_pos.y * mpl.ratio;\n", "\n", " this.send_message(name, {x: x, y: y, button: event.button,\n", " step: event.step,\n", @@ -3921,6 +4014,7 @@ "};\n", "\n", "mpl.figure.prototype.handle_close = function(fig, msg) {\n", + " var width = fig.canvas.width/mpl.ratio\n", " fig.root.unbind('remove')\n", "\n", " // Update the output cell to use the data from the current canvas.\n", @@ -3929,7 +4023,7 @@ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", " // the notebook keyboard shortcuts fail.\n", " IPython.keyboard_manager.enable()\n", - " $(fig.parent_element).html('');\n", + " $(fig.parent_element).html('');\n", " fig.close_ws(fig, msg);\n", "}\n", "\n", @@ -3940,8 +4034,9 @@ "\n", "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", " // Turn the data on the canvas into data in the output cell.\n", + " var width = this.canvas.width/mpl.ratio\n", " var dataURL = this.canvas.toDataURL();\n", - " this.cell_info[1]['text/html'] = '';\n", + " this.cell_info[1]['text/html'] = '';\n", "}\n", "\n", "mpl.figure.prototype.updated_canvas_event = function() {\n", @@ -4030,12 +4125,9 @@ " // 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", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", " }\n", "}\n", "\n", @@ -4084,7 +4176,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -4095,12 +4187,12 @@ } ], "source": [ - "live_plot_rgb_splines(45, 46, 44, spline_s=0.08, max_stdev=1.0, live=False)" + "live_plot_rgb_splines(51, 54, 55, 61, spline_s=0.05, max_stdev=1.0, live=False)" ] }, { "cell_type": "code", - "execution_count": 169, + "execution_count": 121, "metadata": { "collapsed": true }, @@ -4124,10 +4216,8 @@ }, { "cell_type": "code", - "execution_count": 171, - "metadata": { - "collapsed": false - }, + "execution_count": 122, + "metadata": {}, "outputs": [ { "name": "stdout", @@ -4147,6 +4237,7 @@ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", + "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", @@ -4205,6 +4296,9 @@ " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", + " if (mpl.ratio != 1) {\n", + " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", + " }\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", @@ -4274,6 +4368,15 @@ " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", + " var backingStore = this.context.backingStorePixelRatio ||\n", + "\tthis.context.webkitBackingStorePixelRatio ||\n", + "\tthis.context.mozBackingStorePixelRatio ||\n", + "\tthis.context.msBackingStorePixelRatio ||\n", + "\tthis.context.oBackingStorePixelRatio ||\n", + "\tthis.context.backingStorePixelRatio || 1;\n", + "\n", + " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", + "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", @@ -4330,8 +4433,9 @@ " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", - " canvas.attr('width', width);\n", - " canvas.attr('height', height);\n", + " canvas.attr('width', width * mpl.ratio);\n", + " canvas.attr('height', height * mpl.ratio);\n", + " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", @@ -4464,10 +4568,10 @@ "}\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", + " var x0 = msg['x0'] / mpl.ratio;\n", + " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n", + " var x1 = msg['x1'] / mpl.ratio;\n", + " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n", " x0 = Math.floor(x0) + 0.5;\n", " y0 = Math.floor(y0) + 0.5;\n", " x1 = Math.floor(x1) + 0.5;\n", @@ -4623,8 +4727,8 @@ " this.canvas_div.focus();\n", " }\n", "\n", - " var x = canvas_pos.x;\n", - " var y = canvas_pos.y;\n", + " var x = canvas_pos.x * mpl.ratio;\n", + " var y = canvas_pos.y * mpl.ratio;\n", "\n", " this.send_message(name, {x: x, y: y, button: event.button,\n", " step: event.step,\n", @@ -4745,6 +4849,7 @@ "};\n", "\n", "mpl.figure.prototype.handle_close = function(fig, msg) {\n", + " var width = fig.canvas.width/mpl.ratio\n", " fig.root.unbind('remove')\n", "\n", " // Update the output cell to use the data from the current canvas.\n", @@ -4753,7 +4858,7 @@ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", " // the notebook keyboard shortcuts fail.\n", " IPython.keyboard_manager.enable()\n", - " $(fig.parent_element).html('');\n", + " $(fig.parent_element).html('');\n", " fig.close_ws(fig, msg);\n", "}\n", "\n", @@ -4764,8 +4869,9 @@ "\n", "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", " // Turn the data on the canvas into data in the output cell.\n", + " var width = this.canvas.width/mpl.ratio\n", " var dataURL = this.canvas.toDataURL();\n", - " this.cell_info[1]['text/html'] = '';\n", + " this.cell_info[1]['text/html'] = '';\n", "}\n", "\n", "mpl.figure.prototype.updated_canvas_event = function() {\n", @@ -4854,12 +4960,9 @@ " // 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", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", " }\n", "}\n", "\n", @@ -4908,7 +5011,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -4946,38 +5049,55 @@ }, { "cell_type": "code", - "execution_count": 238, + "execution_count": 166, "metadata": { "collapsed": true }, "outputs": [], "source": [ - "def plot_rgb_bar(data_rgb, ids_rgb, spline_s=1):\n", + "def plot_rgb_bar(data_rgb, ids_rgb, spline_s=1, show_label=True, save_svg=None):\n", " fig, ax = plt.subplots(1, 1)\n", - " fig.suptitle('Runs {}(R), {}(G), {}(B) at {:%y-%m-%d %H:%M:%S}'.format(*ids_rgb, datetime.now()))\n", + " if show_label:\n", + " fig.suptitle('Runs {}(R), {}(G), {}(B) at {:%y-%m-%d %H:%M:%S}'.format(*ids_rgb, datetime.now()))\n", "\n", + " #colors = [\n", + " # ((1,0,0), (1,0.8,0.8)),\n", + " # ((0,1,0), (0.8,1,0.8)),\n", + " # ((0,0,1), (0.8,0.8,1))\n", + " #]\n", " colors = [\n", - " ((1,0,0), (1,0.8,0.8)),\n", - " ((0,1,0), (0.8,1,0.8)),\n", - " ((0,0,1), (0.8,0.8,1))\n", - " ]\n", + " (('#fe3ea0', '#ffd2e9')) #ff99cc\n", + " ] * 4\n", + " print('spline_s', spline_s)\n", + "\n", " for (steps, values, stdev), (color_dark, color_bright) in zip(data_rgb, colors):\n", - " ax.errorbar(steps, values, yerr=stdev, color=color_bright)\n", + " ax.errorbar(steps, values, yerr=stdev, color=color_bright, zorder=1)\n", " \n", " spline = inter.UnivariateSpline(steps, values, s=spline_s)\n", - " ax.plot(steps, spline(steps), color=color_dark)\n", + " ax.plot(steps, spline(steps), color=color_dark, zorder=2)\n", + " \n", + " ax.spines['top'].set_visible(False)\n", + " ax.spines['right'].set_visible(False)\n", + " ax.spines['bottom'].set_color('#08bdf9')\n", + " ax.spines['left'].set_color('#08bdf9')\n", + " ax.tick_params(axis='x', colors='#01769D')\n", + " ax.tick_params(axis='y', colors='#01769D')\n", + " ax.xaxis.label.set_color('#01769D')\n", + " ax.yaxis.label.set_color('#01769D')\n", + " ax.grid(color='#08bdf9', linestyle=':')\n", " \n", " ax.set_xlim([380, 720])\n", - " ax.set_xlabel('$\\lambda [nm]$')\n", - " ax.set_ylabel('normalized amplitude')" + " ax.set_xlabel('$\\lambda\\;[nm]$')\n", + " ax.set_ylabel('$I_{pd}\\;[nA]$')\n", + " \n", + " if save_svg:\n", + " fig.savefig(save_svg)" ] }, { "cell_type": "code", - "execution_count": 226, - "metadata": { - "collapsed": false - }, + "execution_count": 124, + "metadata": {}, "outputs": [ { "data": { @@ -4985,6 +5105,7 @@ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", + "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", @@ -5043,6 +5164,9 @@ " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", + " if (mpl.ratio != 1) {\n", + " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", + " }\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", @@ -5112,6 +5236,15 @@ " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", + " var backingStore = this.context.backingStorePixelRatio ||\n", + "\tthis.context.webkitBackingStorePixelRatio ||\n", + "\tthis.context.mozBackingStorePixelRatio ||\n", + "\tthis.context.msBackingStorePixelRatio ||\n", + "\tthis.context.oBackingStorePixelRatio ||\n", + "\tthis.context.backingStorePixelRatio || 1;\n", + "\n", + " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", + "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", @@ -5168,8 +5301,9 @@ " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", - " canvas.attr('width', width);\n", - " canvas.attr('height', height);\n", + " canvas.attr('width', width * mpl.ratio);\n", + " canvas.attr('height', height * mpl.ratio);\n", + " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", @@ -5302,10 +5436,10 @@ "}\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", + " var x0 = msg['x0'] / mpl.ratio;\n", + " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n", + " var x1 = msg['x1'] / mpl.ratio;\n", + " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n", " x0 = Math.floor(x0) + 0.5;\n", " y0 = Math.floor(y0) + 0.5;\n", " x1 = Math.floor(x1) + 0.5;\n", @@ -5461,8 +5595,8 @@ " this.canvas_div.focus();\n", " }\n", "\n", - " var x = canvas_pos.x;\n", - " var y = canvas_pos.y;\n", + " var x = canvas_pos.x * mpl.ratio;\n", + " var y = canvas_pos.y * mpl.ratio;\n", "\n", " this.send_message(name, {x: x, y: y, button: event.button,\n", " step: event.step,\n", @@ -5583,6 +5717,7 @@ "};\n", "\n", "mpl.figure.prototype.handle_close = function(fig, msg) {\n", + " var width = fig.canvas.width/mpl.ratio\n", " fig.root.unbind('remove')\n", "\n", " // Update the output cell to use the data from the current canvas.\n", @@ -5591,7 +5726,7 @@ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", " // the notebook keyboard shortcuts fail.\n", " IPython.keyboard_manager.enable()\n", - " $(fig.parent_element).html('');\n", + " $(fig.parent_element).html('');\n", " fig.close_ws(fig, msg);\n", "}\n", "\n", @@ -5602,8 +5737,9 @@ "\n", "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", " // Turn the data on the canvas into data in the output cell.\n", + " var width = this.canvas.width/mpl.ratio\n", " var dataURL = this.canvas.toDataURL();\n", - " this.cell_info[1]['text/html'] = '';\n", + " this.cell_info[1]['text/html'] = '';\n", "}\n", "\n", "mpl.figure.prototype.updated_canvas_event = function() {\n", @@ -5692,12 +5828,9 @@ " // 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", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", " }\n", "}\n", "\n", @@ -5746,7 +5879,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -5761,7 +5894,7 @@ "(380, 720)" ] }, - "execution_count": 226, + "execution_count": 124, "metadata": {}, "output_type": "execute_result" } @@ -5778,9 +5911,8 @@ }, { "cell_type": "code", - "execution_count": 261, + "execution_count": 168, "metadata": { - "collapsed": false, "scrolled": false }, "outputs": [ @@ -5806,6 +5938,7 @@ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", + "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", @@ -5864,6 +5997,9 @@ " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", + " if (mpl.ratio != 1) {\n", + " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n", + " }\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", @@ -5933,6 +6069,15 @@ " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", + " var backingStore = this.context.backingStorePixelRatio ||\n", + "\tthis.context.webkitBackingStorePixelRatio ||\n", + "\tthis.context.mozBackingStorePixelRatio ||\n", + "\tthis.context.msBackingStorePixelRatio ||\n", + "\tthis.context.oBackingStorePixelRatio ||\n", + "\tthis.context.backingStorePixelRatio || 1;\n", + "\n", + " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n", + "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", @@ -5989,8 +6134,9 @@ " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", - " canvas.attr('width', width);\n", - " canvas.attr('height', height);\n", + " canvas.attr('width', width * mpl.ratio);\n", + " canvas.attr('height', height * mpl.ratio);\n", + " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", @@ -6123,10 +6269,10 @@ "}\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", + " var x0 = msg['x0'] / mpl.ratio;\n", + " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n", + " var x1 = msg['x1'] / mpl.ratio;\n", + " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n", " x0 = Math.floor(x0) + 0.5;\n", " y0 = Math.floor(y0) + 0.5;\n", " x1 = Math.floor(x1) + 0.5;\n", @@ -6282,8 +6428,8 @@ " this.canvas_div.focus();\n", " }\n", "\n", - " var x = canvas_pos.x;\n", - " var y = canvas_pos.y;\n", + " var x = canvas_pos.x * mpl.ratio;\n", + " var y = canvas_pos.y * mpl.ratio;\n", "\n", " this.send_message(name, {x: x, y: y, button: event.button,\n", " step: event.step,\n", @@ -6404,6 +6550,7 @@ "};\n", "\n", "mpl.figure.prototype.handle_close = function(fig, msg) {\n", + " var width = fig.canvas.width/mpl.ratio\n", " fig.root.unbind('remove')\n", "\n", " // Update the output cell to use the data from the current canvas.\n", @@ -6412,7 +6559,7 @@ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n", " // the notebook keyboard shortcuts fail.\n", " IPython.keyboard_manager.enable()\n", - " $(fig.parent_element).html('');\n", + " $(fig.parent_element).html('');\n", " fig.close_ws(fig, msg);\n", "}\n", "\n", @@ -6423,8 +6570,9 @@ "\n", "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", " // Turn the data on the canvas into data in the output cell.\n", + " var width = this.canvas.width/mpl.ratio\n", " var dataURL = this.canvas.toDataURL();\n", - " this.cell_info[1]['text/html'] = '';\n", + " this.cell_info[1]['text/html'] = '';\n", "}\n", "\n", "mpl.figure.prototype.updated_canvas_event = function() {\n", @@ -6513,12 +6661,9 @@ " // 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", + " // select the cell after this one\n", + " var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n", + " IPython.notebook.select(index + 1);\n", " }\n", "}\n", "\n", @@ -6567,7 +6712,7 @@ { "data": { "text/html": [ - "" + "" ], "text/plain": [ "" @@ -6575,6 +6720,13 @@ }, "metadata": {}, "output_type": "display_data" + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "spline_s 0.5\n" + ] } ], "source": [ @@ -6588,6 +6740,7 @@ "λ_led = [623, 518, 466] # [nm] Assumed wavelengths of R, G and B spectral peaks.\n", "λ_be = 400 # [nm] Approximate short-λ edge of blue band\n", "y_edge_min = 0.5\n", + "transimpedance = 630e6 # Ohms.\n", "\n", "poly_degree = 2 # degree of polynomial for stray light and offset correction. Should be 1 or 2.\n", "\n", @@ -6645,21 +6798,24 @@ "data_rgb = [ (λ[λ > 380], y[λ > 380], σ2[λ > 380]) for λ, y, σ2 in data_rgb ]\n", "\n", "# Normalize amplitude data to brightest channel for ease of reading\n", - "max_val = max(np.max(y) for λ, y, σ2 in data_rgb)\n", - "data_rgb = [ (λ, y/max_val, σ2/max_val) for λ, y, σ2 in data_rgb ]\n", + "#max_val = max(np.max(y) for λ, y, σ2 in data_rgb)\n", + "#data_rgb = [ (λ, y/max_val, σ2/max_val) for λ, y, σ2 in data_rgb ]\n", + "\n", + "# Convert amplitude data to current in nanoampère\n", + "data_rgb = [ (λ, y/transimpedance / 1e-9, σ2/transimpedance / 1e-9) for λ, y, σ2 in data_rgb ]\n", "\n", - "plot_rgb_bar(data_rgb, ids, spline_s=0.005)" + "plot_rgb_bar(data_rgb, ids, spline_s=0.5, show_label=False, save_svg='/tmp/processed_plot_cheap_rgb.svg')" ] }, { "cell_type": "code", - "execution_count": 271, + "execution_count": 58, "metadata": { - "collapsed": false + "collapsed": true }, "outputs": [], "source": [ - "# CIE XYZ Color matching functions\n", + "# CIE XYZ Color matching functions from http://cvrl.ioo.ucl.ac.uk/\n", "# rows are: λ[nm], x, y, z\n", "CMFs = { fn[:-4]: np.genfromtxt(fn, delimiter=',')\n", " for fn in ['cie_xyz_1931.csv', 'cie_xyz_judd_1951.csv', 'cie_xyz_judd_vos_1978.csv'] }\n", @@ -6669,7 +6825,7 @@ }, { "cell_type": "code", - "execution_count": 285, + "execution_count": 59, "metadata": { "collapsed": true }, @@ -6688,10 +6844,8 @@ }, { "cell_type": "code", - "execution_count": 289, - "metadata": { - "collapsed": false - }, + "execution_count": 60, + "metadata": {}, "outputs": [ { "data": { @@ -6701,7 +6855,7 @@ " [ 1.75128165e-01, 2.49230694e-01, 9.78488855e-01]])" ] }, - "execution_count": 289, + "execution_count": 60, "metadata": {}, "output_type": "execute_result" } @@ -6713,9 +6867,9 @@ }, { "cell_type": "code", - "execution_count": 330, + "execution_count": 61, "metadata": { - "collapsed": false + "collapsed": true }, "outputs": [], "source": [ @@ -6728,10 +6882,8 @@ }, { "cell_type": "code", - "execution_count": 332, - "metadata": { - "collapsed": false - }, + "execution_count": 62, + "metadata": {}, "outputs": [ { "data": { @@ -6739,7 +6891,7 @@ "array([ 0.72869072, 0.1386238 , 0.20139265])" ] }, - "execution_count": 332, + "execution_count": 62, "metadata": {}, "output_type": "execute_result" } @@ -6754,8 +6906,20 @@ "display_name": "Python 3", "language": "python", "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.6.5" } }, "nbformat": 4, - "nbformat_minor": 0 + "nbformat_minor": 1 } diff --git a/firmware/measure_spectrum.py b/firmware/measure_spectrum.py index 471d1a8..47df7b3 100644 --- a/firmware/measure_spectrum.py +++ b/firmware/measure_spectrum.py @@ -3,7 +3,6 @@ import time import statistics import sqlite3 -from olsndot import Olsndot, Driver from datetime import datetime from pyBusPirateLite import BitBang @@ -12,34 +11,38 @@ 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=400, help='Steps to run through') parser.add_argument('-k', '--skip', type=int, nargs='?', default=2, help='Steps skip between measurements for shorter runtime') parser.add_argument('-d', '--database', default='spectra.sqlite3', help='sqlite3 database file to store results in') parser.add_argument('-w', '--wait', type=float, default=2.0, help='time to wait between samples in seconds') parser.add_argument('-o', '--oversample', type=int, default=32, help='oversampling ratio') + parser.add_argument('-g', '--gain', type=float, default=None, help='Transimpedance gain of amplifier in MOhm') parser.add_argument('-c', '--comment', help='run comment') + parser.add_argument('-p', '--port', default='/dev/serial/by-id/usb-FTDI_FT232R_USB_UART_AD01W1RF-if00-port0', help='Serial port device of the control buspirate') + parser.add_argument('run_name', nargs='?', default='auto') + parser.add_argument('color', help='Captured color channel') args = parser.parse_args() db = sqlite3.connect(args.database) db.execute(""" CREATE TABLE IF NOT EXISTS runs ( - run_id INTEGER PRIMARY KEY, + capture_id INTEGER PRIMARY KEY, name TEXT, comment TEXT, + color TEXT, -- Captured color channel + gain REAL, -- Preamplifier transimpedance in Ohms timestamp REAL -- unix timestamp in fractional seconds )""") db.execute(""" CREATE TABLE IF NOT EXISTS measurements ( measurement_id INTEGER PRIMARY KEY, - run_id INTEGER, + capture_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)""") + FOREIGN KEY (capture_id) REFERENCES runs)""") class BPState: def __init__(self, port): @@ -72,7 +75,7 @@ if __name__ == '__main__': self.reinit() return [ self.bp.adc_value for _ in range(oversampling) ] - bp = BPState(args.buspirate_port) + bp = BPState(args.port) run_name = args.run_name if not str.isnumeric(args.run_name[-1]): @@ -82,11 +85,11 @@ if __name__ == '__main__': run_name += str(1+max(int(n) if str.isnumeric(n) else 0 for n in names)) with db: cur = db.cursor() - cur.execute('INSERT INTO runs(name, comment, timestamp) VALUES (?, ?, ?)', - (run_name, args.comment, time.time())) - run_id = cur.lastrowid + cur.execute('INSERT INTO runs(name, comment, color, gain, timestamp) VALUES (?, ?, ?, ?, ?)', + (run_name, args.comment, args.color, args.gain*1e6, time.time())) + capture_id = cur.lastrowid - print('Starting run {} "{}" at {:%y-%m-%d %H:%M:%S:%f}'.format(run_id, run_name, datetime.now())) + print('Starting run {} "{}" at {:%y-%m-%d %H:%M:%S:%f}'.format(capture_id, run_name, datetime.now())) print('[measurement id] " " [step number] " " [reading (V)]') bp.stepper_direction('down') @@ -107,9 +110,9 @@ if __name__ == '__main__': cur = db.cursor() cur.execute(''' INSERT INTO measurements ( - run_id, led_on, step, voltage, voltage_stdev, timestamp + capture_id, led_on, step, voltage, voltage_stdev, timestamp ) VALUES (?, ?, ?, ?, ?, ?)''', - (run_id, led_val, step, mean, stdev, time.time())) + (capture_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: diff --git a/firmware/results.sqlite3 b/firmware/results.sqlite3 deleted file mode 100644 index d0ede6a..0000000 Binary files a/firmware/results.sqlite3 and /dev/null differ diff --git a/firmware/spectra.sqlite3 b/firmware/spectra.sqlite3 index 09e23c2..fe9be41 100644 Binary files a/firmware/spectra.sqlite3 and b/firmware/spectra.sqlite3 differ diff --git a/firmware/stepper_test.py b/firmware/stepper_test.py index 23486fb..95a4e2a 100644 --- a/firmware/stepper_test.py +++ b/firmware/stepper_test.py @@ -3,7 +3,6 @@ import time import statistics import sqlite3 -from olsndot import Olsndot, Driver from datetime import datetime from pyBusPirateLite import BitBang -- cgit