summaryrefslogtreecommitdiff
path: root/tools/BER Plots.ipynb
diff options
context:
space:
mode:
Diffstat (limited to 'tools/BER Plots.ipynb')
-rw-r--r--tools/BER Plots.ipynb1215
1 files changed, 1215 insertions, 0 deletions
diff --git a/tools/BER Plots.ipynb b/tools/BER Plots.ipynb
new file mode 100644
index 0000000..794872b
--- /dev/null
+++ b/tools/BER Plots.ipynb
@@ -0,0 +1,1215 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 105,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import math\n",
+ "import statistics\n",
+ "import json\n",
+ "\n",
+ "import numpy as np\n",
+ "from matplotlib import pyplot as plt\n",
+ "import matplotlib as mpl\n",
+ "import tqdm"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%matplotlib notebook"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#from math import nan, inf\n",
+ "#data = {'dec_proto_am_ber_top.py': ([1.0, 1.2, 1.5, 1.8, 2.2, 2.7, 3.3, 3.9, 4.7, 5.6, 6.8, 8.2, 10.0, 12.0, 15.0, 18.0, 22.0, 27.0, 33.0, 39.0, 47.0, 56.0, 68.0, 82.0, 100.0, 120.0, 150.0, 180.0, 220.00000000000003, 270.0, 330.0, 390.0, 470.0, 560.0, 680.0, 819.9999999999999], [-1.1706362050026655, -1.193387892562896, -1.2494141100905836, -1.273546683602035, -1.3226867043413222, -1.3284842972643673, -1.4249085476621985, -2.4881654670462012, -2.9280282892286777, -1.8337596086785197, -3.4516299068927765, -3.6739503433927894, -3.85142894461751, -4.2109690103679895, -4.841764334589243, -5.121118910610676, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf, -inf], [0.000562024584446438, 0.002583366143280799, 0.003536123538459578, 0.0060136203314800725, 0.0017120634851061035, 0.01202664019209608, 0.009352711681458127, 0.010626429313400118, 0.0031605552412962345, 0.07580074150906693, 0.008303067934118849, 0.010968003992851543, 0.010921403354231309, 0.014436211616218221, 0.045257276108434545, 0.05063300417965297, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan, nan]), 'dec_proto_am_dc_ber_top.py': ([1.0, 1.2, 1.5, 1.8, 2.2, 2.7, 3.3, 3.9, 4.7, 5.6, 6.8, 8.2, 10.0, 12.0, 15.0, 18.0, 22.0, 27.0, 33.0, 39.0, 47.0, 56.0, 68.0, 82.0, 100.0, 120.0, 150.0, 180.0, 220.00000000000003, 270.0, 330.0, 390.0, 470.0, 560.0, 680.0, 819.9999999999999], [-1.208226392045617, -1.2001309534534812, -1.2082590111531317, -1.2057580375112593, -1.214704089694553, -1.231758143831406, -1.2328452042170934, -1.2342556988606688, -1.2555496906861663, -1.2633800823241472, -1.2801077286712825, -1.292429564986378, -1.2502315024699062, -1.2731027859982436, -1.3264964096914462, -1.350060076963517, -1.402916835230801, -1.6361557068303227, -1.3996004345826805, -2.025891115888953, -2.2259163050377957, -2.403329889470167, -2.5532801901852644, -2.6723825335502625, -2.7451475376985512, -2.7838943274880226, -2.7973828878928355, -2.8114503007382154, -2.7500487601808214, -2.7576294792325875, -2.7531131004032336, -2.771351588479543, -2.763352069271704, -2.7856492625232554, -2.8089246354122395, -2.805404500961304], [0.0006223969511333752, 0.001109700896962153, 0.00210398864758181, 0.0009171589283670842, 0.01005799259051457, 0.01198940071540007, 0.013730311872618627, 0.020358273695306007, 0.019376830251761356, 0.02698367824924875, 0.03015560422449139, 0.04189253434399468, 0.04626542022859063, 0.07217384274518368, 0.08584595043975161, 0.12539079396237413, 0.09791907379447246, 0.10581626829587948, 0.18250650933422224, 0.07591527055792387, 0.20120497031325296, 0.2529568393261202, 0.3140587593946733, 0.3626712973758648, 0.39454531783086805, 0.40694947364033235, 0.4101018950589088, 0.38136874448954844, 0.4108311426740005, 0.40839715897167816, 0.4083367927775933, 0.40823628264400785, 0.4080951641200549, 0.40959607776701595, 0.40969886669408834, 0.4099477409126599]), 'dec_proto_fm_ber_top.py': ([1.0, 1.2, 1.5, 1.8, 2.2, 2.7, 3.3, 3.9, 4.7, 5.6, 6.8, 8.2, 10.0, 12.0, 15.0, 18.0, 22.0, 27.0, 33.0, 39.0, 47.0, 56.0, 68.0, 82.0, 100.0, 120.0, 150.0, 180.0, 220.00000000000003, 270.0, 330.0, 390.0, 470.0, 560.0, 680.0, 819.9999999999999], [-1.3057961403392255, -1.3484294968657196, -1.4667961434461176, -2.8690875116735697, -1.6547222812660038, -1.3891625558026135, -3.5982019547373056, -3.771391890011728, -4.029223203659058, -4.187133187428117, -4.5257152915000916, -4.8291374538093805, -4.9882102105766535, -4.988903861492872, -4.977243402972817, -4.991583617404103, -4.978662932291627, -4.995597720146179, -4.980234434828162, -4.898328188806772, -4.886065758764744, -4.892892232164741, -4.887955756857991, -4.894121825695038, -4.874834077432752, -4.881909834221005, -4.885749246925116, -4.879474958404899, -4.893610496073961, -4.893589161336422, -4.900892127305269, -4.89244575984776, -4.886744260787964, -4.895636919885874, -4.909515650942922, -4.8994301706552505], [0.014213245118859085, 0.001330722343276248, 0.013951488821076687, 0.0041134580502828425, 0.038365233682153145, 0.030733212747131068, 0.0091992661239188, 0.010529797577944408, 0.014647350039240111, 0.014036738695564741, 0.0201667482688038, 0.03195929762792339, 0.050554225347760565, 0.05155121488079693, 0.05696637316379902, 0.05194819962648275, 0.04815391425232906, 0.04198674248536032, 0.0531488148233794, 0.043095657257340825, 0.05140641385191975, 0.047935496094956176, 0.05329373773860191, 0.05040869503181174, 0.05644083328947176, 0.053389328604204575, 0.05074839526504205, 0.053625197798602975, 0.047252304573416753, 0.051310379811370974, 0.046438087027853785, 0.05365724267638675, 0.0534321058650641, 0.04956836848859283, 0.04218369035098332, 0.05032427561533336])}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 54,
+ "metadata": {
+ "scrolled": true
+ },
+ "outputs": [
+ {
+ "data": {
+ "application/vnd.jupyter.widget-view+json": {
+ "model_id": "75ad09f7b6df4c1aa68ef78b1e4ceb0a",
+ "version_major": 2,
+ "version_minor": 0
+ },
+ "text/plain": [
+ "HBox(children=(IntProgress(value=0, max=380), HTML(value='')))"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "name": "stdout",
+ "output_type": "stream",
+ "text": [
+ "Will launch 450 simulation jobs in 38 batches of 12\n",
+ "Starting batch 1/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 2/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 3/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 4/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 5/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 6/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 7/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 8/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 9/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 10/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 11/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 12/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 13/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 14/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 15/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 16/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 17/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 18/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 19/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 20/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 21/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 22/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 23/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 24/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 25/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 26/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 27/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 28/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 29/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 30/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 31/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 32/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 33/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 34/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 35/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 36/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 37/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "Starting batch 38/38...\n",
+ "done.\n",
+ "Waiting for simulation:\n",
+ "Terminating processes...\n",
+ "done.\n",
+ "Processing simulation results\n",
+ "\n"
+ ]
+ }
+ ],
+ "source": [
+ "import sweep_gr_sims\n",
+ "data = sweep_gr_sims.run_simulation(\n",
+ " amplitudes = [10**x for x in np.linspace(0, 2.5, 30)],\n",
+ " #simulations=['dec_proto_am_ber_top.py'],\n",
+ " duration=10.0,\n",
+ " forklimit=12,\n",
+ " repeat_runs=5,\n",
+ " tqdm=tqdm.tqdm_notebook)"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 76,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "#with open('gr_sweep_results2.json', 'w') as f:\n",
+ "# f.write(json.dumps(data))"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 148,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "with open('results_digitalocean2.json') as f:\n",
+ " data = json.loads(f.read())\n",
+ " for sim in list(data):\n",
+ " data[sim] = {\n",
+ " float(a): entry for a, entry in data[sim].items()\n",
+ " }"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 73,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "labels = {\n",
+ " 'dec_proto_am_dc_ber_top.py': '\"DC\"',\n",
+ " 'dec_proto_am_ber_top.py': 'ASK',\n",
+ " 'dec_proto_fm_ber_top.py': 'FSK'\n",
+ "}"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 150,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "data": {
+ "application/javascript": [
+ "/* Put everything inside the global mpl namespace */\n",
+ "window.mpl = {};\n",
+ "\n",
+ "\n",
+ "mpl.get_websocket_type = function() {\n",
+ " if (typeof(WebSocket) !== 'undefined') {\n",
+ " return WebSocket;\n",
+ " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
+ " return MozWebSocket;\n",
+ " } else {\n",
+ " alert('Your browser does not have WebSocket support.' +\n",
+ " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
+ " 'Firefox 4 and 5 are also supported but you ' +\n",
+ " 'have to enable WebSockets in about:config.');\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
+ " this.id = figure_id;\n",
+ "\n",
+ " this.ws = websocket;\n",
+ "\n",
+ " this.supports_binary = (this.ws.binaryType != undefined);\n",
+ "\n",
+ " if (!this.supports_binary) {\n",
+ " var warnings = document.getElementById(\"mpl-warnings\");\n",
+ " if (warnings) {\n",
+ " warnings.style.display = 'block';\n",
+ " warnings.textContent = (\n",
+ " \"This browser does not support binary websocket messages. \" +\n",
+ " \"Performance may be slow.\");\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " this.imageObj = new Image();\n",
+ "\n",
+ " this.context = undefined;\n",
+ " this.message = undefined;\n",
+ " this.canvas = undefined;\n",
+ " this.rubberband_canvas = undefined;\n",
+ " this.rubberband_context = undefined;\n",
+ " this.format_dropdown = undefined;\n",
+ "\n",
+ " this.image_mode = 'full';\n",
+ "\n",
+ " this.root = $('<div/>');\n",
+ " this._root_extra_style(this.root)\n",
+ " this.root.attr('style', 'display: inline-block');\n",
+ "\n",
+ " $(parent_element).append(this.root);\n",
+ "\n",
+ " this._init_header(this);\n",
+ " this._init_canvas(this);\n",
+ " this._init_toolbar(this);\n",
+ "\n",
+ " var fig = this;\n",
+ "\n",
+ " this.waiting = false;\n",
+ "\n",
+ " this.ws.onopen = function () {\n",
+ " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
+ " fig.send_message(\"send_image_mode\", {});\n",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " }\n",
+ "\n",
+ " this.imageObj.onload = function() {\n",
+ " if (fig.image_mode == 'full') {\n",
+ " // Full images could contain transparency (where diff images\n",
+ " // almost always do), so we need to clear the canvas so that\n",
+ " // there is no ghosting.\n",
+ " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
+ " }\n",
+ " fig.context.drawImage(fig.imageObj, 0, 0);\n",
+ " };\n",
+ "\n",
+ " this.imageObj.onunload = function() {\n",
+ " fig.ws.close();\n",
+ " }\n",
+ "\n",
+ " this.ws.onmessage = this._make_on_message_function(this);\n",
+ "\n",
+ " this.ondownload = ondownload;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_header = function() {\n",
+ " var titlebar = $(\n",
+ " '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
+ " 'ui-helper-clearfix\"/>');\n",
+ " var titletext = $(\n",
+ " '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
+ " 'text-align: center; padding: 3px;\"/>');\n",
+ " titlebar.append(titletext)\n",
+ " this.root.append(titlebar);\n",
+ " this.header = titletext[0];\n",
+ "}\n",
+ "\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
+ "\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
+ "\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_canvas = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var canvas_div = $('<div/>');\n",
+ "\n",
+ " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
+ "\n",
+ " function canvas_keyboard_event(event) {\n",
+ " return fig.key_event(event, event['data']);\n",
+ " }\n",
+ "\n",
+ " canvas_div.keydown('key_press', canvas_keyboard_event);\n",
+ " canvas_div.keyup('key_release', canvas_keyboard_event);\n",
+ " this.canvas_div = canvas_div\n",
+ " this._canvas_extra_style(canvas_div)\n",
+ " this.root.append(canvas_div);\n",
+ "\n",
+ " var canvas = $('<canvas/>');\n",
+ " canvas.addClass('mpl-canvas');\n",
+ " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
+ "\n",
+ " this.canvas = canvas[0];\n",
+ " this.context = canvas[0].getContext(\"2d\");\n",
+ "\n",
+ " var backingStore = this.context.backingStorePixelRatio ||\n",
+ "\tthis.context.webkitBackingStorePixelRatio ||\n",
+ "\tthis.context.mozBackingStorePixelRatio ||\n",
+ "\tthis.context.msBackingStorePixelRatio ||\n",
+ "\tthis.context.oBackingStorePixelRatio ||\n",
+ "\tthis.context.backingStorePixelRatio || 1;\n",
+ "\n",
+ " mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
+ "\n",
+ " var rubberband = $('<canvas/>');\n",
+ " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
+ "\n",
+ " var pass_mouse_events = true;\n",
+ "\n",
+ " canvas_div.resizable({\n",
+ " start: function(event, ui) {\n",
+ " pass_mouse_events = false;\n",
+ " },\n",
+ " resize: function(event, ui) {\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " stop: function(event, ui) {\n",
+ " pass_mouse_events = true;\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " });\n",
+ "\n",
+ " function mouse_event_fn(event) {\n",
+ " if (pass_mouse_events)\n",
+ " return fig.mouse_event(event, event['data']);\n",
+ " }\n",
+ "\n",
+ " rubberband.mousedown('button_press', mouse_event_fn);\n",
+ " rubberband.mouseup('button_release', mouse_event_fn);\n",
+ " // Throttle sequential mouse events to 1 every 20ms.\n",
+ " rubberband.mousemove('motion_notify', mouse_event_fn);\n",
+ "\n",
+ " rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
+ " rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
+ "\n",
+ " canvas_div.on(\"wheel\", function (event) {\n",
+ " event = event.originalEvent;\n",
+ " event['data'] = 'scroll'\n",
+ " if (event.deltaY < 0) {\n",
+ " event.step = 1;\n",
+ " } else {\n",
+ " event.step = -1;\n",
+ " }\n",
+ " mouse_event_fn(event);\n",
+ " });\n",
+ "\n",
+ " canvas_div.append(canvas);\n",
+ " canvas_div.append(rubberband);\n",
+ "\n",
+ " this.rubberband = rubberband;\n",
+ " this.rubberband_canvas = rubberband[0];\n",
+ " this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
+ " this.rubberband_context.strokeStyle = \"#000000\";\n",
+ "\n",
+ " this._resize_canvas = function(width, height) {\n",
+ " // Keep the size of the canvas, canvas container, and rubber band\n",
+ " // canvas in synch.\n",
+ " canvas_div.css('width', width)\n",
+ " canvas_div.css('height', height)\n",
+ "\n",
+ " canvas.attr('width', width * mpl.ratio);\n",
+ " canvas.attr('height', height * mpl.ratio);\n",
+ " canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
+ "\n",
+ " rubberband.attr('width', width);\n",
+ " rubberband.attr('height', height);\n",
+ " }\n",
+ "\n",
+ " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
+ " // upon first draw.\n",
+ " this._resize_canvas(600, 600);\n",
+ "\n",
+ " // Disable right mouse context menu.\n",
+ " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
+ " return false;\n",
+ " });\n",
+ "\n",
+ " function set_focus () {\n",
+ " canvas.focus();\n",
+ " canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " window.setTimeout(set_focus, 100);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_toolbar = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var nav_element = $('<div/>')\n",
+ " nav_element.attr('style', 'width: 100%');\n",
+ " this.root.append(nav_element);\n",
+ "\n",
+ " // Define a callback function for later on.\n",
+ " function toolbar_event(event) {\n",
+ " return fig.toolbar_button_onclick(event['data']);\n",
+ " }\n",
+ " function toolbar_mouse_event(event) {\n",
+ " return fig.toolbar_button_onmouseover(event['data']);\n",
+ " }\n",
+ "\n",
+ " for(var toolbar_ind in mpl.toolbar_items) {\n",
+ " var name = mpl.toolbar_items[toolbar_ind][0];\n",
+ " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
+ " var image = mpl.toolbar_items[toolbar_ind][2];\n",
+ " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
+ "\n",
+ " if (!name) {\n",
+ " // put a spacer in here.\n",
+ " continue;\n",
+ " }\n",
+ " var button = $('<button/>');\n",
+ " button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
+ " 'ui-button-icon-only');\n",
+ " button.attr('role', 'button');\n",
+ " button.attr('aria-disabled', 'false');\n",
+ " button.click(method_name, toolbar_event);\n",
+ " button.mouseover(tooltip, toolbar_mouse_event);\n",
+ "\n",
+ " var icon_img = $('<span/>');\n",
+ " icon_img.addClass('ui-button-icon-primary ui-icon');\n",
+ " icon_img.addClass(image);\n",
+ " icon_img.addClass('ui-corner-all');\n",
+ "\n",
+ " var tooltip_span = $('<span/>');\n",
+ " tooltip_span.addClass('ui-button-text');\n",
+ " tooltip_span.html(tooltip);\n",
+ "\n",
+ " button.append(icon_img);\n",
+ " button.append(tooltip_span);\n",
+ "\n",
+ " nav_element.append(button);\n",
+ " }\n",
+ "\n",
+ " var fmt_picker_span = $('<span/>');\n",
+ "\n",
+ " var fmt_picker = $('<select/>');\n",
+ " fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
+ " fmt_picker_span.append(fmt_picker);\n",
+ " nav_element.append(fmt_picker_span);\n",
+ " this.format_dropdown = fmt_picker[0];\n",
+ "\n",
+ " for (var ind in mpl.extensions) {\n",
+ " var fmt = mpl.extensions[ind];\n",
+ " var option = $(\n",
+ " '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
+ " fmt_picker.append(option)\n",
+ " }\n",
+ "\n",
+ " // Add hover states to the ui-buttons\n",
+ " $( \".ui-button\" ).hover(\n",
+ " function() { $(this).addClass(\"ui-state-hover\");},\n",
+ " function() { $(this).removeClass(\"ui-state-hover\");}\n",
+ " );\n",
+ "\n",
+ " var status_bar = $('<span class=\"mpl-message\"/>');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
+ " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
+ " // which will in turn request a refresh of the image.\n",
+ " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_message = function(type, properties) {\n",
+ " properties['type'] = type;\n",
+ " properties['figure_id'] = this.id;\n",
+ " this.ws.send(JSON.stringify(properties));\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_draw_message = function() {\n",
+ " if (!this.waiting) {\n",
+ " this.waiting = true;\n",
+ " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " var format_dropdown = fig.format_dropdown;\n",
+ " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
+ " fig.ondownload(fig, format);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
+ " var size = msg['size'];\n",
+ " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
+ " fig._resize_canvas(size[0], size[1]);\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
+ " var x0 = msg['x0'] / mpl.ratio;\n",
+ " var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
+ " var x1 = msg['x1'] / mpl.ratio;\n",
+ " var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
+ " x0 = Math.floor(x0) + 0.5;\n",
+ " y0 = Math.floor(y0) + 0.5;\n",
+ " x1 = Math.floor(x1) + 0.5;\n",
+ " y1 = Math.floor(y1) + 0.5;\n",
+ " var min_x = Math.min(x0, x1);\n",
+ " var min_y = Math.min(y0, y1);\n",
+ " var width = Math.abs(x1 - x0);\n",
+ " var height = Math.abs(y1 - y0);\n",
+ "\n",
+ " fig.rubberband_context.clearRect(\n",
+ " 0, 0, fig.canvas.width, fig.canvas.height);\n",
+ "\n",
+ " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
+ " // Updates the figure title.\n",
+ " fig.header.textContent = msg['label'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
+ " var cursor = msg['cursor'];\n",
+ " switch(cursor)\n",
+ " {\n",
+ " case 0:\n",
+ " cursor = 'pointer';\n",
+ " break;\n",
+ " case 1:\n",
+ " cursor = 'default';\n",
+ " break;\n",
+ " case 2:\n",
+ " cursor = 'crosshair';\n",
+ " break;\n",
+ " case 3:\n",
+ " cursor = 'move';\n",
+ " break;\n",
+ " }\n",
+ " fig.rubberband_canvas.style.cursor = cursor;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
+ " fig.message.textContent = msg['message'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
+ " // Request the server to send over a new figure.\n",
+ " fig.send_draw_message();\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
+ " fig.image_mode = msg['mode'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.updated_canvas_event = function() {\n",
+ " // Called whenever the canvas gets updated.\n",
+ " this.send_message(\"ack\", {});\n",
+ "}\n",
+ "\n",
+ "// A function to construct a web socket function for onmessage handling.\n",
+ "// Called in the figure constructor.\n",
+ "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
+ " return function socket_on_message(evt) {\n",
+ " if (evt.data instanceof Blob) {\n",
+ " /* FIXME: We get \"Resource interpreted as Image but\n",
+ " * transferred with MIME type text/plain:\" errors on\n",
+ " * Chrome. But how to set the MIME type? It doesn't seem\n",
+ " * to be part of the websocket stream */\n",
+ " evt.data.type = \"image/png\";\n",
+ "\n",
+ " /* Free the memory for the previous frames */\n",
+ " if (fig.imageObj.src) {\n",
+ " (window.URL || window.webkitURL).revokeObjectURL(\n",
+ " fig.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
+ " evt.data);\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
+ " fig.imageObj.src = evt.data;\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var msg = JSON.parse(evt.data);\n",
+ " var msg_type = msg['type'];\n",
+ "\n",
+ " // Call the \"handle_{type}\" callback, which takes\n",
+ " // the figure and JSON message as its only arguments.\n",
+ " try {\n",
+ " var callback = fig[\"handle_\" + msg_type];\n",
+ " } catch (e) {\n",
+ " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " if (callback) {\n",
+ " try {\n",
+ " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
+ " callback(fig, msg);\n",
+ " } catch (e) {\n",
+ " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
+ " }\n",
+ " }\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
+ "mpl.findpos = function(e) {\n",
+ " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
+ " var targ;\n",
+ " if (!e)\n",
+ " e = window.event;\n",
+ " if (e.target)\n",
+ " targ = e.target;\n",
+ " else if (e.srcElement)\n",
+ " targ = e.srcElement;\n",
+ " if (targ.nodeType == 3) // defeat Safari bug\n",
+ " targ = targ.parentNode;\n",
+ "\n",
+ " // jQuery normalizes the pageX and pageY\n",
+ " // pageX,Y are the mouse positions relative to the document\n",
+ " // offset() returns the position of the element relative to the document\n",
+ " var x = e.pageX - $(targ).offset().left;\n",
+ " var y = e.pageY - $(targ).offset().top;\n",
+ "\n",
+ " return {\"x\": x, \"y\": y};\n",
+ "};\n",
+ "\n",
+ "/*\n",
+ " * return a copy of an object with only non-object keys\n",
+ " * we need this to avoid circular references\n",
+ " * http://stackoverflow.com/a/24161582/3208463\n",
+ " */\n",
+ "function simpleKeys (original) {\n",
+ " return Object.keys(original).reduce(function (obj, key) {\n",
+ " if (typeof original[key] !== 'object')\n",
+ " obj[key] = original[key]\n",
+ " return obj;\n",
+ " }, {});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.mouse_event = function(event, name) {\n",
+ " var canvas_pos = mpl.findpos(event)\n",
+ "\n",
+ " if (name === 'button_press')\n",
+ " {\n",
+ " this.canvas.focus();\n",
+ " this.canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " var x = canvas_pos.x * mpl.ratio;\n",
+ " var y = canvas_pos.y * mpl.ratio;\n",
+ "\n",
+ " this.send_message(name, {x: x, y: y, button: event.button,\n",
+ " step: event.step,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ "\n",
+ " /* This prevents the web browser from automatically changing to\n",
+ " * the text insertion cursor when the button is pressed. We want\n",
+ " * to control all of the cursor setting manually through the\n",
+ " * 'cursor' event from matplotlib */\n",
+ " event.preventDefault();\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " // Handle any extra behaviour associated with a key event\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.key_event = function(event, name) {\n",
+ "\n",
+ " // Prevent repeat events\n",
+ " if (name == 'key_press')\n",
+ " {\n",
+ " if (event.which === this._key)\n",
+ " return;\n",
+ " else\n",
+ " this._key = event.which;\n",
+ " }\n",
+ " if (name == 'key_release')\n",
+ " this._key = null;\n",
+ "\n",
+ " var value = '';\n",
+ " if (event.ctrlKey && event.which != 17)\n",
+ " value += \"ctrl+\";\n",
+ " if (event.altKey && event.which != 18)\n",
+ " value += \"alt+\";\n",
+ " if (event.shiftKey && event.which != 16)\n",
+ " value += \"shift+\";\n",
+ "\n",
+ " value += 'k';\n",
+ " value += event.which.toString();\n",
+ "\n",
+ " this._key_event_extra(event, name);\n",
+ "\n",
+ " this.send_message(name, {key: value,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
+ " if (name == 'download') {\n",
+ " this.handle_save(this, null);\n",
+ " } else {\n",
+ " this.send_message(\"toolbar_button\", {name: name});\n",
+ " }\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
+ " this.message.textContent = tooltip;\n",
+ "};\n",
+ "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
+ "\n",
+ "mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
+ "\n",
+ "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
+ " // Create a \"websocket\"-like object which calls the given IPython comm\n",
+ " // object with the appropriate methods. Currently this is a non binary\n",
+ " // socket, so there is still some room for performance tuning.\n",
+ " var ws = {};\n",
+ "\n",
+ " ws.close = function() {\n",
+ " comm.close()\n",
+ " };\n",
+ " ws.send = function(m) {\n",
+ " //console.log('sending', m);\n",
+ " comm.send(m);\n",
+ " };\n",
+ " // Register the callback with on_msg.\n",
+ " comm.on_msg(function(msg) {\n",
+ " //console.log('receiving', msg['content']['data'], msg);\n",
+ " // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
+ " ws.onmessage(msg['content']['data'])\n",
+ " });\n",
+ " return ws;\n",
+ "}\n",
+ "\n",
+ "mpl.mpl_figure_comm = function(comm, msg) {\n",
+ " // This is the function which gets called when the mpl process\n",
+ " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
+ "\n",
+ " var id = msg.content.data.id;\n",
+ " // Get hold of the div created by the display call when the Comm\n",
+ " // socket was opened in Python.\n",
+ " var element = $(\"#\" + id);\n",
+ " var ws_proxy = comm_websocket_adapter(comm)\n",
+ "\n",
+ " function ondownload(figure, format) {\n",
+ " window.open(figure.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " var fig = new mpl.figure(id, ws_proxy,\n",
+ " ondownload,\n",
+ " element.get(0));\n",
+ "\n",
+ " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
+ " // web socket which is closed, not our websocket->open comm proxy.\n",
+ " ws_proxy.onopen();\n",
+ "\n",
+ " fig.parent_element = element.get(0);\n",
+ " fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
+ " if (!fig.cell_info) {\n",
+ " console.error(\"Failed to find cell for figure\", id, fig);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var output_index = fig.cell_info[2]\n",
+ " var cell = fig.cell_info[0];\n",
+ "\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.handle_close = function(fig, msg) {\n",
+ " var width = fig.canvas.width/mpl.ratio\n",
+ " fig.root.unbind('remove')\n",
+ "\n",
+ " // Update the output cell to use the data from the current canvas.\n",
+ " fig.push_to_output();\n",
+ " var dataURL = fig.canvas.toDataURL();\n",
+ " // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
+ " // the notebook keyboard shortcuts fail.\n",
+ " IPython.keyboard_manager.enable()\n",
+ " $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
+ " fig.close_ws(fig, msg);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.close_ws = function(fig, msg){\n",
+ " fig.send_message('closing', msg);\n",
+ " // fig.ws.close()\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
+ " // Turn the data on the canvas into data in the output cell.\n",
+ " var width = this.canvas.width/mpl.ratio\n",
+ " var dataURL = this.canvas.toDataURL();\n",
+ " this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.updated_canvas_event = function() {\n",
+ " // Tell IPython that the notebook contents must change.\n",
+ " IPython.notebook.set_dirty(true);\n",
+ " this.send_message(\"ack\", {});\n",
+ " var fig = this;\n",
+ " // Wait a second, then push the new image to the DOM so\n",
+ " // that it is saved nicely (might be nice to debounce this).\n",
+ " setTimeout(function () { fig.push_to_output() }, 1000);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_toolbar = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var nav_element = $('<div/>')\n",
+ " nav_element.attr('style', 'width: 100%');\n",
+ " this.root.append(nav_element);\n",
+ "\n",
+ " // Define a callback function for later on.\n",
+ " function toolbar_event(event) {\n",
+ " return fig.toolbar_button_onclick(event['data']);\n",
+ " }\n",
+ " function toolbar_mouse_event(event) {\n",
+ " return fig.toolbar_button_onmouseover(event['data']);\n",
+ " }\n",
+ "\n",
+ " for(var toolbar_ind in mpl.toolbar_items){\n",
+ " var name = mpl.toolbar_items[toolbar_ind][0];\n",
+ " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
+ " var image = mpl.toolbar_items[toolbar_ind][2];\n",
+ " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
+ "\n",
+ " if (!name) { continue; };\n",
+ "\n",
+ " var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
+ " button.click(method_name, toolbar_event);\n",
+ " button.mouseover(tooltip, toolbar_mouse_event);\n",
+ " nav_element.append(button);\n",
+ " }\n",
+ "\n",
+ " // Add the status bar.\n",
+ " var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "\n",
+ " // Add the close button to the window.\n",
+ " var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
+ " var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
+ " button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
+ " button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
+ " buttongrp.append(button);\n",
+ " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
+ " titlebar.prepend(buttongrp);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._root_extra_style = function(el){\n",
+ " var fig = this\n",
+ " el.on(\"remove\", function(){\n",
+ "\tfig.close_ws(fig, {});\n",
+ " });\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._canvas_extra_style = function(el){\n",
+ " // this is important to make the div 'focusable\n",
+ " el.attr('tabindex', 0)\n",
+ " // reach out to IPython and tell the keyboard manager to turn it's self\n",
+ " // off when our div gets focus\n",
+ "\n",
+ " // location in version 3\n",
+ " if (IPython.notebook.keyboard_manager) {\n",
+ " IPython.notebook.keyboard_manager.register_events(el);\n",
+ " }\n",
+ " else {\n",
+ " // location in version 2\n",
+ " IPython.keyboard_manager.register_events(el);\n",
+ " }\n",
+ "\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " var manager = IPython.notebook.keyboard_manager;\n",
+ " if (!manager)\n",
+ " manager = IPython.keyboard_manager;\n",
+ "\n",
+ " // Check for shift+enter\n",
+ " if (event.shiftKey && event.which == 13) {\n",
+ " this.canvas_div.blur();\n",
+ " 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,iVBORw0KGgoAAAANSUhEUgAAA4QAAAH0CAYAAABl8+PTAAAgAElEQVR4nOzdd3xTZfsG8OOgiCC49ZUfBBQFJLJFERGZDgQXIuiLA3xFFBAQ3jDfguwhyF4KaQtlQynp3pS20JYW6KSD0plOuuhuev3+CA2EtmHY5uQk1/fzef4w3Dl50vauuXqecx4BREREREREZJEEsSdARERERERE4mAgJCIiIiIislAMhERERERERBaKgZCIiIiIiMhCMRASERERERFZKAZCIiIiIiIiC8VASEREREREZKEYCImIiIiIiCwUAyEREREREZGFYiAkIiIiIiKyUAyEREREREREFoqBkIiIiIiIyEIxEBIREREREVkoBkIiIiIiIiILxUBIRERERERkoRgIiYiIiIiILBQDIRERERERkYViICQiIiIiIrJQDIREREREREQWioGQiIiIiIjIQjEQEhERERERWSgGQiIiIiIiIgvFQEhERERERGShGAiJiIiIiIgsFAMhERERERGRhWIgJCIiIiIislAMhERERERERBaKgZCIiIiIiMhCMRASERERERFZKAZCIiIiIiIiC8VASEREREREZKEYCImIiIiIiCwUAyEREREREZGFYiAkIiIiIiKyUAyEREREREREFoqBkIiIiIiIyEIxEBIREREREVkoBkIiIiIiIiILxUBIRERERERkoRgIiYjqsXfvXgiCoDeefvppDBo0CKdOnapTf3vtrePbb7/V1VlbW+v928MPP4x27drhhx9+gFqtbrT55+Xl4csvv8QzzzwDQRDw8ccfN9qx6yOTyTBy5MgmfY3bJSUlQRAE7N2716iv21QGDRqEQYMG3ddzv/32W8hksvt67v79+7Fhw4Z6/00QBFhbW9/Xcf+JgIAAWFtbIz8/3+ivTURkaRgIiYjqURsI9+7di6CgIAQGBuL48eMYMmQIBEGAo6OjXr0gCBgzZgyCgoLqjISEBF1dbSB0dXVFUFAQPDw8MGfOHDz44IN49dVXUVlZ2SjznzFjBqysrLBv3z4EBQXh8uXLjXLchogRCMvLyxEUFITs7Gyjvm5TESsQjhw5ssHnBgUFITU19b6O+0+sXbsWgiAgKSnJ6K9NRGRpGAiJiOpRGwhDQkL0Hi8tLUXz5s0xfvx4vccFQcAvv/xyx+PWBsKcnBy9x7///nsIggBvb+9/PnkA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goKCYGNjg0ceeQS//vprg3UMhEREd4eBkIiIiCRDEAQ8+uijGDNmjN5G9PXVMRASEd0ZAyEREREREZGFYiA0AVu3btXdYKF37944ffq02FMiIiIiIiILwEAosoMHD6JZs2bYvXs3oqOj8euvv6Jly5ZITk4We2pERERERGTmGAhF1q9fP/z00096j3Xp0gVz584VaUZERERERGQpGAhFVFFRgYceegjHjx/Xe3z69Ol455136n1OeXk5CgsLUVhYiIKCAqSkpCAxMREFBQW6xzk4ODg4ODg4ODikPAoKCpCamgqNRmOMj+UWjYFQROnp6RAEAQEBAXqPL1++HK+88kq9z6ndvJmDg4ODg4ODg4PD3EdqaqoxPpZbNAZCEdUGwsDAQL3Hly1bhs6dO9f7nNvPEEZHR0MQBCQlJSE3N9eoQ61Ww97eHmq12uivzcHBIc5g33NwWNZgz3OINZKSkiAIAgoKCozxsdyiMRCK6H6WjN6usLAQgiCgsLCwKaZoUGVlJRwcHFBZWWn01yYicbDviSwLe57EIuZnXEvDQCiyfv36YcqUKXqPde3a9a5vKsNASETGxL4nsizseRILA6HxMBCKrHbbib///hvR0dGYMWMGWrZsiatXr97V8xkIiciY2PdEloU9T2JhIDQeBkITsHXrVshkMlhZWaF3797w8/O76+cyEBKRMbHviSwLe57EwkBoPAyEEsdASETGxL4nsizseRILA6HxMBBKHAMhERkT+57IsrDnSSwMhMbDQChxDIREZEzseyLLwp4nsTAQGg8DocQxEBKRMbHviSwLe57EwkBoPAyEEsdASETGxL4nsizseRILA6HxMBBKHAMhERkT+57IsrDnSSwMhMbDQChxDIREZEzseyLLYgk9r1arERMTwxETA7VaLfa3Q4eB0HgYCCWOgZCIjIl9T2RZzL3n1Wo1evTogfbt23O0b48ePXqYTChkIDQeBkKJYyAkImNi3xNZFnPv+ZiYGLRv3x6dOnVCt27dLHp06tQJ7du3R0xMjNjfFgAMhMbEQChxDIREZEzseyLLYu49XxsIu3Xrhj59+lj06NatGwOhhWIglDgGQiIyJvY9kWUx955nIGQgJAZCyWMgJCJjYt8TWRZz7/n6AqGjo6NeTX5+PgICAvDll1/qahoyb9489OnTBz/++GOdYwQHB2PixIn/OLjt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\" width=\"900\">"
+ ],
+ "text/plain": [
+ "<IPython.core.display.HTML object>"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "# Note on this plot: For the ASK trial, above a certain level no further errors were detected,\n",
+ "# thus the BER could not be calculated. The ASK line stops at this point.\n",
+ "\n",
+ "# Another note: The wobbliness of the plotted lines despite the low standard deviation of measurements\n",
+ "# lets us conclude there are some serious systematic errors in this simulation. Since we're only interested\n",
+ "# in a ballpark measurement here, this is not a significant issue.\n",
+ "\n",
+ "# A BER of 0.5 in dB\n",
+ "ber05 = 10*math.log10(0.5)\n",
+ "\n",
+ "fig, ax = plt.subplots(figsize=(9, 5))\n",
+ "ax.set_title('BERs for basic modulation types')\n",
+ "if data.keys() - labels.keys():\n",
+ " raise ValueError(f'Unmatched simulation labels: {data.keys() - labels.keys()}')\n",
+ "for sim, label in labels.items():\n",
+ " d = data[sim]\n",
+ " ampls = np.array(sorted(list(d.keys())))\n",
+ " filter_inf = lambda l: [ x for x in l if math.isfinite(x) ] or [-math.inf]\n",
+ " filter_nan = lambda l: [ x for x in l if math.isfinite(x) ] or [math.nan]\n",
+ " bers = np.array([ statistics.mean(filter_inf(d[a][0])) for a in ampls ])\n",
+ " #stdevs = np.array([statistics.stdev(filter_inf(d[a][0])) if len(filter_inf(d[a][0]))>1 else 0 for a in ampls])\n",
+ " #stdevs = np.array([math.sqrt(statistics.mean([x**2 for x in filter_nan(d[a][1])] + [0])) for a in ampls])\n",
+ " stdevs = np.array([statistics.stdev((np.array(filter_inf(d[a][0])) + math.log10(8))*10) if len(filter_inf(d[a][0]))>1 else 0 for a in ampls])\n",
+ " \n",
+ " # The Gnuradio BER block calculates bit error rate over whole bytes, but we only feed in bits casted\n",
+ " # to bytes. We correct for this by adding log10(8).\n",
+ " # Also convert log10 values to dB.\n",
+ " bers = (bers + math.log10(8))*10\n",
+ " #stdevs = (stdevs + math.log10(8)) *10\n",
+ " #ax.errorbar(ampls, bers, yerr=stdevs, label=label)\n",
+ " p, = ax.plot(ampls, bers, label=label)\n",
+ " \n",
+ " ax.fill_between(ampls, bers-stdevs, np.clip(bers+stdevs, a_min=None, a_max=ber05),\n",
+ " alpha=0.3, facecolor=p.get_color(), linewidth=0)\n",
+ "ax.grid()\n",
+ "ax.legend()\n",
+ "ax.set_xscale('log')\n",
+ "ax.set_xlabel('Amplitude Δf [mHz]')\n",
+ "ax.set_ylabel('BER [dB]')\n",
+ "ax.set_ylim([-50, 0])\n",
+ "ax.axhline(ber05, linestyle='--', color='red')\n",
+ "bbox = {'facecolor': 'black', 'alpha': 0.8, 'pad': 2}\n",
+ "xform = mpl.transforms.blended_transform_factory(ax.transAxes, ax.transData)\n",
+ "ax.text(0.9, ber05, f'BER=0.5', transform=xform, color='white', bbox=bbox, ha='center', va='center')\n",
+ "\n",
+ "None"
+ ]
+ }
+ ],
+ "metadata": {
+ "kernelspec": {
+ "display_name": "Python 3",
+ "language": "python",
+ "name": "python3"
+ },
+ "language_info": {
+ "codemirror_mode": {
+ "name": "ipython",
+ "version": 3
+ },
+ "file_extension": ".py",
+ "mimetype": "text/x-python",
+ "name": "python",
+ "nbconvert_exporter": "python",
+ "pygments_lexer": "ipython3",
+ "version": "3.7.6"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}