summaryrefslogtreecommitdiff
path: root/grid_frequency_spectra.ipynb
diff options
context:
space:
mode:
authorjaseg <git@jaseg.net>2020-01-12 18:24:21 +0100
committerjaseg <git@jaseg.net>2020-01-12 18:24:21 +0100
commit269279d55a6c8459c06d9c7cfc426fa0dda0ce3a (patch)
tree215217ce1c7d81fc26c65e4c779bd8e5e0399512 /grid_frequency_spectra.ipynb
parent5cf7f77cc4e5e6cf06e4264eb8f116880508f628 (diff)
downloadmaster-thesis-269279d55a6c8459c06d9c7cfc426fa0dda0ce3a.tar.gz
master-thesis-269279d55a6c8459c06d9c7cfc426fa0dda0ce3a.tar.bz2
master-thesis-269279d55a6c8459c06d9c7cfc426fa0dda0ce3a.zip
notebooks: Add notebooks
Diffstat (limited to 'grid_frequency_spectra.ipynb')
-rw-r--r--grid_frequency_spectra.ipynb4205
1 files changed, 4205 insertions, 0 deletions
diff --git a/grid_frequency_spectra.ipynb b/grid_frequency_spectra.ipynb
new file mode 100644
index 0000000..c861490
--- /dev/null
+++ b/grid_frequency_spectra.ipynb
@@ -0,0 +1,4205 @@
+{
+ "cells": [
+ {
+ "cell_type": "code",
+ "execution_count": 1,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "import csv\n",
+ "\n",
+ "import numpy as np\n",
+ "from matplotlib import pyplot as plt\n",
+ "import scipy.fftpack"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 2,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "%matplotlib notebook"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 3,
+ "metadata": {},
+ "outputs": [],
+ "source": [
+ "data = np.genfromtxt('Netzfrequenz_Sekundenwerte_2012_KW37.csv', delimiter=',')[1:,1:]"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 4,
+ "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,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAgAElEQVR4nOzdeXhU5dk/8LnqBSj8kOuyXi+LbQ9a2SouL1q3ty9URLEVaYu11Grt2yoWW0Ra257IYkR2ZVExAkZkUdlBxUMSCJAFEsKWkATClgRCCGFJIAkJmUlmzvf3x5lzkiEzyUzOzJw5Z76f65o/nPWOPMlzz3me575tICIiIqKoYjM6ACIiIiIKLyaARERERFGGCSARERFRlGECSERERBRlmAASERERRRkmgERERERRhgkgERERUZRhAkhEREQUZZgAEhEREUUZJoBEREREUYYJIBEREVGUYQJIREREFGWYABIRERFFGSaARERERFGGCSARERFRlGECSERERBRlmAASERERRRkmgERERERRhgkgERERUZRhAkhEREQUZZgAEhEREUUZJoBEREREUYYJIBEREVGUYQJIREREFGWYABIRERFFGSaARERERFGGCSARERFRlGECSERERBRlmAASERERRRkmgERERERRhgkgERERUZRhAkhEREQUZZgAEhEREUUZJoBEREREUYYJIBEREVGUYQJIREREFGWYABIRERFFGSaARERERFGGCSARERFRlGECSERERBRlmAASERERRRkmgERERERRhgkgERERUZRhAkhEREQUZZgAEhEREUUZJoBEREREUYYJIBEREVGUYQJIREREFGWYABIRERFFGSaARERERFGGCSARERFRlGECSERERBRlmAASERERRRkmgERERERRhgkgERERUZRhAkhEREQUZZgA6uByuVBaWoqqqipUV1fzxhtvvPHGG28muFVVVaG0tBQul8voVMIwTAB1KC0thc1m44033njjjTfeTHgrLS01OpUwDBNAHaqqqrQBZPS3Gd5444033njjzb+begGnqqrK6FTCMEwAdaiurobNZkN1dbXRoRAREZGfOH8zAdSFA4iIiMh8OH8zAdSFA4iIiMh8OH8zAdSFA4iIiMh8OH8zAdSFA4iIiMh8OH8zAdSFA4iIiMh8OH8zAdSFA4iIiMh8OH8zAdSFA4iIiMh8OH8zAdSFA4iIiMh8OH8zAdSFA4iIiMh8OH8zAdSFA4iIiMh8OH8zAdSFA4iIiMh8OH8zAdSFA4iIiMh8OH8zAdSFA4iIiMh8OH8zAdSFA4iIiMh8OH8zAdSF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\" width=\"640\">"
+ ],
+ "text/plain": [
+ "<IPython.core.display.HTML object>"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/plain": [
+ "[<matplotlib.lines.Line2D at 0x79510ce19a90>]"
+ ]
+ },
+ "execution_count": 4,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "plt.plot(data[:3600*24, 0])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 5,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "0.02051102806199375"
+ ]
+ },
+ "execution_count": 5,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "np.std(data[:,0])"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 6,
+ "metadata": {
+ "scrolled": false
+ },
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/usr/lib/python3.7/site-packages/ipykernel_launcher.py:7: DeprecationWarning: object of type <class 'float'> cannot be safely interpreted as an integer.\n",
+ " import sys\n"
+ ]
+ },
+ {
+ "data": {
+ "application/javascript": [
+ "/* Put everything inside the global mpl namespace */\n",
+ "window.mpl = {};\n",
+ "\n",
+ "\n",
+ "mpl.get_websocket_type = function() {\n",
+ " if (typeof(WebSocket) !== 'undefined') {\n",
+ " return WebSocket;\n",
+ " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
+ " return MozWebSocket;\n",
+ " } else {\n",
+ " alert('Your browser does not have WebSocket support.' +\n",
+ " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
+ " 'Firefox 4 and 5 are also supported but you ' +\n",
+ " 'have to enable WebSockets in about:config.');\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
+ " this.id = figure_id;\n",
+ "\n",
+ " this.ws = websocket;\n",
+ "\n",
+ " this.supports_binary = (this.ws.binaryType != undefined);\n",
+ "\n",
+ " if (!this.supports_binary) {\n",
+ " var warnings = document.getElementById(\"mpl-warnings\");\n",
+ " if (warnings) {\n",
+ " warnings.style.display = 'block';\n",
+ " warnings.textContent = (\n",
+ " \"This browser does not support binary websocket messages. \" +\n",
+ " \"Performance may be slow.\");\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " this.imageObj = new Image();\n",
+ "\n",
+ " this.context = undefined;\n",
+ " this.message = undefined;\n",
+ " this.canvas = undefined;\n",
+ " this.rubberband_canvas = undefined;\n",
+ " this.rubberband_context = undefined;\n",
+ " this.format_dropdown = undefined;\n",
+ "\n",
+ " this.image_mode = 'full';\n",
+ "\n",
+ " this.root = $('<div/>');\n",
+ " this._root_extra_style(this.root)\n",
+ " this.root.attr('style', 'display: inline-block');\n",
+ "\n",
+ " $(parent_element).append(this.root);\n",
+ "\n",
+ " this._init_header(this);\n",
+ " this._init_canvas(this);\n",
+ " this._init_toolbar(this);\n",
+ "\n",
+ " var fig = this;\n",
+ "\n",
+ " this.waiting = false;\n",
+ "\n",
+ " this.ws.onopen = function () {\n",
+ " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
+ " fig.send_message(\"send_image_mode\", {});\n",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " }\n",
+ "\n",
+ " this.imageObj.onload = function() {\n",
+ " if (fig.image_mode == 'full') {\n",
+ " // Full images could contain transparency (where diff images\n",
+ " // almost always do), so we need to clear the canvas so that\n",
+ " // there is no ghosting.\n",
+ " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
+ " }\n",
+ " fig.context.drawImage(fig.imageObj, 0, 0);\n",
+ " };\n",
+ "\n",
+ " this.imageObj.onunload = function() {\n",
+ " 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,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8WIdOHBAixcv1qc//Wlt3bp1wH0/fvy4PvvZz2revHkqLi5Wamqqxo4dq/fee8/E31D0iZTntK+uri5NnTpV1113nQoLC7V+/Xp96Utf0j333GP+L2GUGY7nNJjZs2fry1/+stavX6/CwkJdd911mjZtmrq6uix5nHZixnPaV3p6usaOHavU1FQVFxdr3rx5iomJUWlpqdUPBzZGAI4Cff8R8vl8+uIXv6glS5b417W1tenSSy/Viy++KEkqLi6Ww+EICLWCggI5HA4dPHhQkvT888/r0ksvDbh21aOPPqovfelL/leM/vM//1M33XRTwP7ceOONuu222wbc3z/+8Y+aPHlywLq7775b3/72t0N96KPWSD6nfWVlZelTn/qUKisr/euWLVum8ePHc2HbEFj1nPZVX1+vsWPHKj093b+usrJSn/rUp7RmzRqzH5athfOcBjN9+nTNnj07YN3kyZOVkJBg/k4DnyAAR4G+/wgdO3ZMDodDhYWFAdvdfPPN+uUvfylJSktL06WXXtpvrEsvvVSvvvqqJOkXv/iFbr755oCfFxYWyuFw6Pjx45Kkv/u7v1NSUlLANklJSbr88ssH3N9rr71Wc+fODViXmZmpT3/60+ro6LjQw7WFkXxO+3rwwQd1zTXXBKyrra2Vw+HQxo0bQ39wNmXVc9rXxx9/LIfDodra2oD111xzjR566CGjDwO9hPOc9tXe3q4xY8b0++jM3LlzNWPGDPN3GvgEATgK9P1HKC8vTw6HI+AVG0m66667dMMNN0iSFi1apKuuuqrfWFdddZUWL14sSbr++ut11113Bfy8srJSDodD+fn5kqSxY8fq7bffDtjm7bff1rhx4wbc36uuukqLFi0KWNezz1VVVRd6uLYwks9pX3fddZeuv/76fuvHjRund955J7QHZmNWPad9DfT37/rrr9evf/1rIw8BfYTznPbV8/cvLy8vYP2iRYsUGxtr/k4DnyAAR4GB/hHqG1O/+tWvdOONN0oa+B+XK6+8Uo8++qik4AeMiooKORwOFRQUSOoOwL4R8NZbb2n8+PED7m+wg9eWLVvkcDh08uTJCz1cWxjJ57SvgQ5eY8eO1bJly0J7YDZm1XPa10AB+K//+q+6++67jTwE9BHOc9rXQP8HbOHChZo0aZL5Ow18ggAcBXgLePThLeDRh7eARx/eAkY0IwBHgYE+iPzYY4/517W3twf9cPm2bdv822zdurXfCQOf+9znAi73sWTJkn4ngfzwhz8M2J+bbrrpgieBxMXFBaybPXs2J4H0MpLPaV89J4H0flUjPT2dk0BCZNVz2lfPSSDvvvuuf11VVRUngVggnOc0mOnTp2vOnDkB6+Li4jgJBJYiAKNUU1OTPB6PPB6PHA6HkpKS5PF4/JcNWLJkiS699FJlZmaqqKhIt99+e9DLS1xzzTUqKChQQUGBrr766oDLS9TX1+sLX/iCbr/9dhUVFSkzM1OXXHJJwCVD8vLyNGbMGC1ZskQHDhzQkiVL+l0GJiEhQb/4xS/8f+65DMy9996r4uJipaWlcRkYRc5zmpmZGfDWU89lYH7wgx+osLBQGzZs0Fe+8hUuAzMEw/GcVlRUaNKkSQGROHv2bH3lK1/Rhg0bVFhYqO9///tcBsYkZjyn3//+9/Xcc8/5/9xzGZi0tDQVFxdr/vz5iomJUUlJybA/PtgHARilsrOz5XA4+i2zZs2SdP5ipF/84hc1fvx4zZgxQ0VFRQFj1NTU6Oc//7kuvvhiXXzxxfr5z38e9KLB1157rcaPH68vfvGL+vOf/9zvlaIVK1Zo0qRJGjt2rCZPnqyMjIyAn8+aNUvf/e53A9Zt2rRJ3/jGNzRu3DhNnDiRC0Ercp7T1157TQ5H4D8NpaWl+tGPfqSLLrpIn//853XPPfcEXEoGwQ3Hc3rixAk5HA5lZ2f717W2tuqee+7R5z//eV100UWaOXOmysrKhuMhj3pmPKdOp1OJiYkB61JSUuR0OjVu3DjFx8crJydnmB4R7IoABAAAsBkCEAAAwGYIQAAAAJshAAEAAGyGAAQAALAZAhAAAMBmCEAAAACbIQABAABshgAEAACwGQIQAADAZghAAAAAmyEAAQAAbIYABAAAsBkCEAAAwGYIQAAAAJshAAEAAGyGAAQAALAZAhAAAMBmCEAAAACbIQABAABshgAEAACwGQIQAADAZghAAAAAmyEAAQAAbIYABAAAsBkCEAAAwGYIQAAAAJshAAEAAGyGAAQAALAZAhAAAMBmCEAAAACbIQABAABs5v8DBJ3IALshXCYAAAAASUVORK5CYII=\" width=\"640\">"
+ ],
+ "text/plain": [
+ "<IPython.core.display.HTML object>"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "ys = scipy.fftpack.fft(data[:,0])\n",
+ "ys = 2.0/len(data) * np.abs(ys[:len(data)//2])\n",
+ "s = 60\n",
+ "\n",
+ "ys = np.convolve(ys, np.ones((s,))/s, mode='valid')\n",
+ "\n",
+ "xs = np.linspace(0, 1.0/2.0, len(data)/2)\n",
+ "#xs = np.linspace(len(data)/2, 1, len(data)/2)\n",
+ "\n",
+ "fig, ax = plt.subplots()\n",
+ "ax.loglog(xs[s//2:-s//2+1], ys)\n",
+ "ax.xaxis.set_major_formatter(plt.FuncFormatter(lambda x, _pos: 1/x))\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 7,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/usr/lib/python3.7/site-packages/ipykernel_launcher.py:7: DeprecationWarning: object of type <class 'float'> cannot be safely interpreted as an integer.\n",
+ " import sys\n"
+ ]
+ },
+ {
+ "data": {
+ "application/javascript": [
+ "/* Put everything inside the global mpl namespace */\n",
+ "window.mpl = {};\n",
+ "\n",
+ "\n",
+ "mpl.get_websocket_type = function() {\n",
+ " if (typeof(WebSocket) !== 'undefined') {\n",
+ " return WebSocket;\n",
+ " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
+ " return MozWebSocket;\n",
+ " } else {\n",
+ " alert('Your browser does not have WebSocket support.' +\n",
+ " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
+ " 'Firefox 4 and 5 are also supported but you ' +\n",
+ " 'have to enable WebSockets in about:config.');\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
+ " this.id = figure_id;\n",
+ "\n",
+ " this.ws = websocket;\n",
+ "\n",
+ " this.supports_binary = (this.ws.binaryType != undefined);\n",
+ "\n",
+ " if (!this.supports_binary) {\n",
+ " var warnings = document.getElementById(\"mpl-warnings\");\n",
+ " if (warnings) {\n",
+ " warnings.style.display = 'block';\n",
+ " warnings.textContent = (\n",
+ " \"This browser does not support binary websocket messages. \" +\n",
+ " \"Performance may be slow.\");\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " this.imageObj = new Image();\n",
+ "\n",
+ " this.context = undefined;\n",
+ " this.message = undefined;\n",
+ " this.canvas = undefined;\n",
+ " this.rubberband_canvas = undefined;\n",
+ " this.rubberband_context = undefined;\n",
+ " this.format_dropdown = undefined;\n",
+ "\n",
+ " this.image_mode = 'full';\n",
+ "\n",
+ " this.root = $('<div/>');\n",
+ " this._root_extra_style(this.root)\n",
+ " this.root.attr('style', 'display: inline-block');\n",
+ "\n",
+ " $(parent_element).append(this.root);\n",
+ "\n",
+ " this._init_header(this);\n",
+ " this._init_canvas(this);\n",
+ " this._init_toolbar(this);\n",
+ "\n",
+ " var fig = this;\n",
+ "\n",
+ " this.waiting = false;\n",
+ "\n",
+ " this.ws.onopen = function () {\n",
+ " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
+ " fig.send_message(\"send_image_mode\", {});\n",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " }\n",
+ "\n",
+ " this.imageObj.onload = function() {\n",
+ " if (fig.image_mode == 'full') {\n",
+ " // Full images could contain transparency (where diff images\n",
+ " // almost always do), so we need to clear the canvas so that\n",
+ " // there is no ghosting.\n",
+ " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
+ " }\n",
+ " fig.context.drawImage(fig.imageObj, 0, 0);\n",
+ " };\n",
+ "\n",
+ " this.imageObj.onunload = function() {\n",
+ " 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,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tLRULpdLFRUViY4SCUMAtMEoIAaDwWAwGM4bpaWliY4SCUMAtKGlpUWlpaW68sorg/6roiPPCvbt27fD3xttvUivh3otlmXW3zvjc7TzWfI5du7naOezjHV5pM822T/Htry3oz/HaJ8t/x/Jv+1k+BwrKipUWlqqlpaWREeJhCEAxkFaWpr5c2Vlx3+vwLq/jnpvtPUivR7qtViWdfbnGO644vk+Psf4va+9n2WsyyN9tsn+ObblvR39OYZaxv9HRn8tGT/HcMcVz/cl+nNMZQTAOJg0aZL5c2f8o7Tur6PeG229SK+Hei2WZZ39OYY7rni+j88xfu9r72cZ6/JIn22yf45teW9Hf46hlvH/kdFfS8bPMdxxxfN9if4cUxkBMM466x9lV8fnGB98jvHB5xg/fJbxwecIuwiAcVZfX68xY8aovr4+0YfiaHyO8cHnGB98jvHDZxkffI6wiwAIAACQYgiAAAAAKYYACAAAkGIIgAAAACmGAAgAAJBiukQAzMnJ0eDBg9W7d2+5XC7NmzfP73Wv16sxY8aod+/eOv/883Xbbbdpx44dfuucOXNG9957ry666CJddNFFuvfee1VeXu63zvbt2zVo0CCdf/75+sIXvqAnnnhCXq/Xb50PPvhAaWlp6tGjh9LS0jR37tyIx/L1r39d9957ry699FKdf/75uvnmm7Vs2TLzWD796U/r8ssv1yWXXKJPfepTuvPOO7V3716/be7fv19DhgzR+eefr0984hPq1q2bvv3tb/s94mbz5s365je/qYsvvlif+cxn9Lvf/U7V1dV+21m2bJluvvlmffrTn9Yll1yiv/3tb2pqaor42e/fv1/f//739bnPfU4XXnih7r77bh07dsxvnXjte9asWbruuuv0qU99SpdeeqkmTJgQdDyTJk1Sv379dP7556tv3756++23/V5vbGzUE088ocsvv1w9e/bUtddeq4ULF/qtU1VVpREjRvj9nWzYsMFvnWPHjmno0KHq3bt3xL+XcJ+NUbOf+9zn5HK5dMEFF/h9NtY66dGjhy666CJ96lOf8vtsOqtmQ1m1apXS09PVs2dPXXbZZZoyZUrU93SWZPr/g0DFxcUaPHiwLrjgAn32s5/VQw89pIaGhvj8wTtYZ32ugerr6/Xggw/qs5/9rC644AJ973vf63KP74rHZxvK5MmT1adPH/Xs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bn5+Pux2O0wmE9LS0nDw4MGgOM6bNw82mw0xMTGYOXMmTp8+Lb3f1tYWtCtYLdtoNCIpKQk7d+4Mikkkyu7u7sasWbMQFxeH2NhYzJ8/P+isuubmZrzyyiuwWCywWq1YunRp0MzCxYsXkZqaCrPZjOeffx75+flBi6uPHz+OxMREqU3u378vXVNZWQmXyyW1S+CBvo+LTbg+q+749e8n6npFk8kkxWa4+uzKlSu1HdD+cXz11VdhMpkwceLEEXUQ9EgZDw4cOAAh5CH2zp07WLx4MSwWC+x2O9avXy/tFB/JhiOuocaYhw8fYv369bDb7bBYLFiyZIk0to0GkYit2+3WThhQff7553C73TCZTEhPT8e33347THdEz4JRkQASERER0ZNjAkhERESkM0wAiYiIiHSGCSARERGRzjABJCIiItIZJoBEREREOsMEkIiIiEhnmAASERER6QwTQCIiIiKdYQJIREREpDNMAImIiIh0hgkgERERkc4wASQiIiLSGSaARERERDrDBJCIiIhIZ5gAEhEREekME0AiIiIinWECSERERKQzTACJiIiIdIYJIBEREZHOMAEkIiIi0hkmgEREREQ6wwSQiIiISGeYABIRERHpDBNAIiIiIp1hAkhERESkM0wAiYiIiHSGCSARERGRzjABJCIiItIZJoBEREREOsMEkIiIiEhnmAASERER6cz/APkJ3inyrTN5AAAAAElFTkSuQmCC\" width=\"640\">"
+ ],
+ "text/plain": [
+ "<IPython.core.display.HTML object>"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "ys = scipy.fftpack.fft(data[:,0])\n",
+ "ys = 2.0/len(data) * np.abs(ys[:len(data)//2])\n",
+ "s = 1\n",
+ "\n",
+ "ys = np.convolve(ys, np.ones((s,))/s, mode='valid')\n",
+ "\n",
+ "xs = np.linspace(0, 1.0/2.0, len(data)/2)\n",
+ "#xs = np.linspace(len(data)/2, 1, len(data)/2)\n",
+ "\n",
+ "fig, ax = plt.subplots()\n",
+ "ax.loglog(xs[s//2:-s//2+1 if s > 1 else None], ys)\n",
+ "ax.xaxis.set_major_formatter(plt.FuncFormatter(lambda x, _pos: 1/x))\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 8,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/usr/lib/python3.7/site-packages/ipykernel_launcher.py:7: DeprecationWarning: object of type <class 'float'> cannot be safely interpreted as an integer.\n",
+ " import sys\n"
+ ]
+ },
+ {
+ "data": {
+ "application/javascript": [
+ "/* Put everything inside the global mpl namespace */\n",
+ "window.mpl = {};\n",
+ "\n",
+ "\n",
+ "mpl.get_websocket_type = function() {\n",
+ " if (typeof(WebSocket) !== 'undefined') {\n",
+ " return WebSocket;\n",
+ " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
+ " return MozWebSocket;\n",
+ " } else {\n",
+ " alert('Your browser does not have WebSocket support.' +\n",
+ " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
+ " 'Firefox 4 and 5 are also supported but you ' +\n",
+ " 'have to enable WebSockets in about:config.');\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
+ " this.id = figure_id;\n",
+ "\n",
+ " this.ws = websocket;\n",
+ "\n",
+ " this.supports_binary = (this.ws.binaryType != undefined);\n",
+ "\n",
+ " if (!this.supports_binary) {\n",
+ " var warnings = document.getElementById(\"mpl-warnings\");\n",
+ " if (warnings) {\n",
+ " warnings.style.display = 'block';\n",
+ " warnings.textContent = (\n",
+ " \"This browser does not support binary websocket messages. \" +\n",
+ " \"Performance may be slow.\");\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " this.imageObj = new Image();\n",
+ "\n",
+ " this.context = undefined;\n",
+ " this.message = undefined;\n",
+ " this.canvas = undefined;\n",
+ " this.rubberband_canvas = undefined;\n",
+ " this.rubberband_context = undefined;\n",
+ " this.format_dropdown = undefined;\n",
+ "\n",
+ " this.image_mode = 'full';\n",
+ "\n",
+ " this.root = $('<div/>');\n",
+ " this._root_extra_style(this.root)\n",
+ " this.root.attr('style', 'display: inline-block');\n",
+ "\n",
+ " $(parent_element).append(this.root);\n",
+ "\n",
+ " this._init_header(this);\n",
+ " this._init_canvas(this);\n",
+ " this._init_toolbar(this);\n",
+ "\n",
+ " var fig = this;\n",
+ "\n",
+ " this.waiting = false;\n",
+ "\n",
+ " this.ws.onopen = function () {\n",
+ " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
+ " fig.send_message(\"send_image_mode\", {});\n",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " }\n",
+ "\n",
+ " this.imageObj.onload = function() {\n",
+ " if (fig.image_mode == 'full') {\n",
+ " // Full images could contain transparency (where diff images\n",
+ " // almost always do), so we need to clear the canvas so that\n",
+ " // there is no ghosting.\n",
+ " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
+ " }\n",
+ " fig.context.drawImage(fig.imageObj, 0, 0);\n",
+ " };\n",
+ "\n",
+ " this.imageObj.onunload = function() {\n",
+ " 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,iVBORw0KGgoAAAANSUhEUgAAAoAAAAHgCAYAAAA10dzkAAAgAElEQVR4nOydeXBUVdr/U2WpbxX1vlXvO2+9VVa9P5txRhRhXOIyozPj6DjqzLyMzoYzo87ojKOjzozKbM2OIougxIWExQAqogIKQWiSkEA2SEJIIJAVspCdkJWsZO1+fn90zu1zb9/bfbvv2t3fT9VT0nc96RzP+eTec54TRwAAAAAAIKaIs7oAAAAAAADAXCCAAAAAAAAxBgQQAAAAACDGgAACAAAAAMQYEEAAAAAAgBgDAggAAAAAEGNAAAEAAAAAYgwIIAAAAABAjAEBBAAAAACIMSCAAAAAAAAxBgQQAAAAACDGgAACAAAAAMQYEEAAAAAAgBgDAggAAAAAEGNAAAEAAAAAYgwIIAAAAABAjAEBBAAAAACIMSCAAAAAAAAxBgQQAAAAACDGgAACAAAAAMQYEEAAAAAAgBgDAggAAAAAEGNAAAEAAAAAYgwIIAAAAABAjAEBBAAAAACIMSCAAAAAAAAxBgQQAAAAACDGgAACAAAAAMQYEEAAAAAAgBgDAggAAAAAEGNAAAEAAAAAYgwIIAAAAABAjAEBBAAAAACIMSCAAAAAAAAxBgQQAAAAACDGgAACAAAAAMQYEEAAAAAAgBgDAggAAAAAEGNAAAEAAAAAYgwIIAAAAABAjAEBBAAAAACIMSCAAAAAAAAxBgQQAAAAACDGgAACAAAAAMQYEEAAAAAAgBgDAggAAAAAEGNAAAEAAAAAYgwIIAAAAABAjAEBBAAAAACIMSCAAAAAAAAxBgQQAAAAACDGgAACAAAAAMQYEEAAAAAAgBgDAggAAAAAEGNAAAEAAAAAYgwIIAAAAABAjAEB1IDb7aaWlhbq6+uj/v5+BAKBQCAQERB9fX3U0tJCbrfbapWwDAigBlpaWiguLg6BQCAQCEQERktLi9UqYRkQQA309fUJFcjqv2YQCAQCgUCoC/YAp6+vz2qVsAwIoAb6+/spLi6O+vv7rS4KAAAAAFSC/hsCqAlUIAAAACDyQP8NAdQEKhAAAAAQeaD/hgBqAhUIAAAAiDzQf0MANYEKBAAAAEQe6L8hgGGRmJhIM2fOpBkzZsR8BQIAAAAiDQggBFATqEAAAABA5IH+GwKoCVQgAAAAIPJA/w0B1AQqEAAAABB5oP+GAGoCFQgAAACIPNB/QwA1gQoEAAAARB7ovyGAmkAFAgAAACIP9N8QQE2gAgEAAACRB/pvCKAmUIEAAMAath07T/tPt1ldDBChoP+GAGoCFQgAAMyntmOAHE4XOZwuq4sCIhT03xBATaACAQCA+Ryv74YAAk2g/4YAagIVCAAAzAcCCLSC/hsCqAlUIAAAMB8IINAK+m8IoCZQgQAAwHwggPqyKrWKfv/BCZp0e6wuimmg/4YAagIVCAAAzAcCqC/suzxW22V1UUwD/TcEkIiIhoeH6dprr6W///3vIZ2HCgQAAOYDAdQX9l1mn+2wuiimgf4bAkhERAsXLqS5c+dCAAEAIAKAAOoLBDA2iXkBrKmpoZ///Of0wQcfQAABACACgADqCwQwNrG1AObm5tKcOXPommuuobi4OEpJSfE7JikpiaZPn05XX301xcfHU15eXkj3eOSRR+jcuXMQQAAAiBAggPoCAYxNbC2AqamptGjRItqzZ4+sAO7cuZOuvPJKSk5OpqqqKnr55Zdp2rRp1NTUJBwTHx9Ps2bN8ou2tjbat28f/eMf/yAiggACAECEAAHUFwhgbGJrAeSRE8C77rqLnn/+edG2G2+8kebPn6/qmvPnz6f//d//JYfDQV/5ylfoP/7jP+i1115TPH50dJT6+/uFaGlpifkKBAAAZgMB1BcIYGwSsQI4NjZGV1xxBe3du1d03EsvvUT33ntvyNdX8wRw2bJlFBcX5xexXIEAAMBsCiGAugIBjE0iVgDb2tooLi6O8vPzRcetXLmSZsyYEfL11QggngACAID1QAD1hX2XOec6rS6KaUAAo0AACwoKRMetWLGCbrjhBlPKhAoEAADmAwHUFwhgbBKxAqj3K+BQSExMpJkzZ9KMGTNivgIBAIDZQAD1BQIYm0SsABJ5J4G88MILom0zZ85UPQlEK6hAAABgPhBAfYEAxia2FsDBwUEqLS2l0tJSiouLo4SEBCotLRXSvLA0MFu3bqWqqip65ZVXaNq0adTY2GhK+VCBAADAfCCA+nGw7AIEMEaxtQBmZ2fLzrp96qmnhGOSkpLI4XDQVVddRfHx8ZSbm2ta+VCBAADAfCCA+sG+Rwhg7GFrAbQrGAMIAADWAQHUDwhg7PbfEEANoAIBAID5QAC1MT7pFv4NAYzd/hsCqAFUIAAAMB8IYPisyzhHDqeLylr6iEgsgLkQwJgCAhgGeAUMAADWAQEMH/a9zd1UIPoMAYw9IIAaQAUCAADzgQCGDwTQC/pvCKAmUIEAAMB8CuoggOECAfSC/hsCqAlUIAAAMB+7CGDf5XHamFNHrZcuh3zuiYYeOlx10YBSBQYC6AX9NwRQE6hAAABgPnYRwBd2lJDD6aJvrjwc8rms/G1hyKMWIIBe0H9DAMMCk0AAAMA67CKAs5elh10Odl5p8yUDShb8vnM3QgBjvf+GAGoAFQgAAMwHAhg+gQQwrwYCGEtAADWACgQAAOYDAQwfCKAX9N8QQE2gAgEAgPnYRQC/oYMAnmrqNaBkwe8LAUT/DQHUACoQAACYDwQwfAIJ4NGaLlPLYiXovyGAYYFJIAAAYB12EcCbXz0UsQL4y435os8QwNgDAqgBVCAAADCfaBLAkxBAS0D/DQHUBCoQAACYDwQwfAIJ4HPbi00ti5Wg/4YAagIVCAAAzMcuAnjLa9ElgA6nizoGRkwtj1Wg/4YAagIVCAAAzCe/ritqBLCk0V4C2Ng9ZGp5rAL9NwRQE6hAAABgPnYRwFvDFMBVqVWcAPYYUrbB0QkanZj02w4B9IL+GwKoCVQgAAAwH7UCODQ6QW63x7By3LY8IywB5IXLCAEcHJ0gh9NFt752SLQ9vaIdAjgF+m8IYFggDQwAAFiHGgFsu3SZHE4X/XpzoWHlsKsAHquV/374+5ohgMNjE7S7uJl6hsZ0u6ZeQAAhgJpABQIAAPNRI4CJWbWGvyaO10EAixv0F8C3M8/ZQgD/vvs0OZwu+vG7eWGdPzHppvLWPkOe4qL/hgBqAhUIAADMBwIYmIQMewjgzCVpmn4HTCDXHTqrW5kY6L8hgJpABQIAAPOBAAZGjQA6nC4aGBm3tQCyc786X//fIfpvCKAmUIEAAMB81AhgUrbxAnj76/YUwOc/LlElgGvSqv22NXUP61YOCKC9gQBqABUIAADMJ5oE8IQBAvirzQWqBHDB3jJDBfAmCKCtgQBqABUIAADMJ5oEsOi8/QQw+2wH/eXTU3RpWNvsXS0C2DkwCgE0GAigBlCBAADAfNQI4IbsOhMEMDMqBZD9e/6eMk3l0CKAP9+QDwE0GAigBlCBAADAfKJJAI/Xd+terl9vLpS9vlT2FsoIYG3HoPDvp7cVaSrHrKXpYf8O+DJBAI0BAhgGSAQNAADWYRcBvGOF/QWQL5saAXwoIVc3AZwNAbQ1EEANoAIBAID55CusdMGzMcd4AbzTpgLIvwIOVQD5gABGNxBADaACAQCA+ZglgMFWoLCrAGp5AggBjB0ggBpABQIAAPNRI4BKEyHUUt85SLe8dogSs2oVj7lrpXYBLLRQABelGCyAyyCAdgYCqAFUIACAEUy6PTR3UwHN21VqdVFsybEgAlhzcUBWgELhDx+cCHq+XQVQ7SvgxSnlAQXw9x+cEF13aHSCPi5spI7+EVXlgADaGwigBlCBAABGcKqp1/Dxa5FMMAHkl4FzOF10UYWwdA+O0m/eL6R9pa1EpE4Av7nysOEC2N43QimnWml80q36+kYJIFub93trs1SVAwJobyCAGkAFAgAYQUkjBDAQwQTw95y8OZwuum7BwaDX/Ofnp4Xj3848R99dk2ULAWSpVAK9ipai9hXwkn2hCeCtrx0K6ef9BgTQ1kAANYAKBAAwgmgWwNGJSc3XkBNAj8dDtR2D9GF+g6zMBOOPHxUripASvABmne1QXX7+2gV1gQWQHffYpgK/fRmVF+lH7+TRuYsDou0QwOCg/4YAagIVCAB74nZ7aNmXFfRFSYvVRQkLqwQwv66LqtuNa8/OtFwih9NFq1KrNF1HTgDfSKsOKDMnm3r9RIknHAH81qrDqo6Twp+TX9el6lg5AWT7HliXI9qupwBuyK6jJ5KP08j4ZEABlBP7m1/1Hd85MEqXx9TLPwTQeCCAGkAFAsCeZFZejOgnaFYIIL8EmFH85v1CXe4hJ4CBREZOhqQy8syH+glgWnk7rXBVKqaR0VsA71qZKdqupwDyn6Vj+mo7BuiRxGPk/OIMOZwu2l7YKCrHLZwwOpwumr00PeDPqvQdQQCNAQKoAVQgAOzJruJmCGCIZJ/tiBkBZN/vsi8rhPP1FED2+cvTbbLniQSwVp0A/mqz/gK4NIgA/kEigNJrPpiQ47e9sL6bNmTXkdvt8RPAUH7vEEDjgQBqABUIAHuyO8IFMK38AgSQo7y1j7oHR4XPWgWQnyU7MemmX27MD3oOEdHJpl5aebCKhscmiIjo7iACuOXoedmfR60A9g2PGyqAy76sCPhzS58ASq/JJ8KWxoEzbboJoJpJPKGC/hsCGBZYCxgAe5Jf10W1HYMRL4BfX3jQ9PJn2VQA2bhB/hxeAJmMqRVAj8dDP343T/icc65T1Tn8PVanVpPb7VGUG70E8NHEY8Jxv95cqHgdqQCqTQOjRQDHJ90Bz03MqhWNGYQA2g8IoAZQgQCwD7UdvuS/kS6A4XSYWrFaAN1uD61OraaDZRdE2zdk+y/pdrSmS/QdeTz+MqYU+0pb6Q7uydWNi9OCnvOtVYdpdap4ksmWo+eDCuBWFQKYV9Op+H3xx9lNAPnfi9EC+MKOEtXnqQX9NwRQE6hAANgH1xnfa9NoEsD+kXFT7mm1AB6qaJfdp0YARycmVQvgc9uLRQIYbgR6vRmKADqcLlWTRX7zvnoBNOMV8FPbikwTwPvfylZ9nlrQf0MANYEKBIB94AXw85IWw2SmuKGHnv2omJp7hnW/NoPv/F7dXxH8BB3IqjZOANv7RuhZSZoVKTuON8ru25gTXACr2/tNF0C5YLDP246pE8DeobGgx0WiAN62PAMCaGMggBpABQLAPpglgOy6P006pvu1pfdwOF307EfFht2Hx0gBfFpGFngSs2pFM2p5NqkQwJUHq1RLmlREI0UAH0/WXwBf3R9YAAPNApb7nUoFMB4CaGsggBpABQLAPpgtgA6ni14/UKn79aX3MEsAj1Srz524MaeOfr25kEbG1SX2fSghV1EEBkcnAkrC5lx/ATxcddHvHDvE5tw6ujzmex39QRgCWNLYK+QG5I95Ivm44nWiXQC/DwE0BAigBlCBALAPvADy67rqTbgdGmN3cTMt2VeuOO5Leg+zBJCXqmCw47YXNKi6diABvDQ8FvA7fT+3XrS9Y2DEctFTG6EKID+zuHdI/L2EIoD8WEujBDDQ6+FwBHBgZJwWpZRR0fkev7JCAI0BAqgBVCAA7AMvgFoELRhar8/Oy6y8qOoeoQrgl6fb6M4VmXSqqTek88IRwPdz61VdW04AB0e96VvkBHBswi2cywvgY5sKZH/Hdo0P8xsCfn9SAZzgUqvUdw6Kjnlyi/5PAF/bXxm2AAbaxwTw9tfVCyCflLqld1h0DgTQGCCAGkAFAsA+RJoAfh5gnWL++s9tD00A2Xl3rMgMfjCHkQIot2LEDYtTiUheAG9cnCacm5xXL/t7jYT4aOoJad/wOD38di4lZtWKvj+jBFCaBiarukP2vssPhC+Az3yorwD+dqvvlTK/Eg4E0DgggBpABQLAPkSCAJ5q8nVsRgtgqGULZf3kUAVQSRKIyO9Vp7QMkSyATFzWpvtyCMp9H1lnvYI2btATQKX7BhPAQJJnpADy35fD6aIH1uWoqmehgP4bAqgJVCAA7EMkCCB/HgTQRf/3Xh7N21kqu+/vu08TEdGTW45bLnJagojodU60+OXdpMfxAni+a0i0P5AASn9n0ieAbL90m/EC6J9uRwleAKUBATQGCKAGUIEAsA/RKoChjgEMt2x6CmBxQw+9nXmOsqo7QlqlQxqnmy+Ffa5d4rblGaIxkA+s838dzr5zLQKYVt4ubFcrgPy4O7kIJHmzl6YHPDcxq1Y236ISEEDzgQBqABUIAPugVQDz67ro3MUB+vMnJwM+2Qr3+tJztQigx+OhpfvKZfPMKZWt6HwPVbf72qq+y+P0ys5SyjnnXYosIwwB3JxbR2fbB2iFq5J6uFQmfBm+PN1muYRFQhAFFsDfbi0K+Lt+aptvv9pXwItTAgtgsIkegSJUAfxdAAH8AQTQECCAGkAFAsA+aBFAfh3hYOeFc325c7/Q8Aq4pLFH8f5yZWvvG/Hbxj/9IVJeii1Q+fgcfc9/XOK3n4mJ1XIVCUFENDahLIC/izABXH+khu6EANqamBfAK664gm655Ra65ZZb6JlnngnpXFQgAOyDFgGUO1eJcK4vd66WMYA55zoV7y9XtuIGf2F85sNi0bZwBJBP0fKdNUdky4BQFx6PRySADRIB5AVP7nvmBVGtAH5nzZGAZbKLAD6YAAE0gpgXwK985Sthn4sKBIB9gAD6n8sIJoB/23Wa7lrp66wL6ropvaLd79rSe/BPAL/9xhFyuz1U3tpnuUxFYkxMunUTQGkiaPZ7D7VMwSZ6BAo9BfChhFzF88IF/TcEEAIIgEXUdQ7SP3afpoauIV2uF0sCmH1Wed1eubLxAjg+6U2yzAugUlzouxywfLwAOpwu+tqCg5aLVKTGxKSbRid8y8jp/QRwYER+9nGg0CKADqcrpFnAgYYKQACNwdYCmJubS3PmzKFrrrmG4uLiKCUlxe+YpKQkmj59Ol199dUUHx9PeXl5Id3jyiuvpPj4ePr2t79NOTmhPWZGBQIgfNgAcf7VoRYiTQDVjgH80/YSv/2hCiA/ZvBg2QUiUieAZS19wjU2ZHtlL61c/ntGaIuJSTd1DowKnxu7h0T7n9pWRENTq6fI/a5/G0QAm3uGQy6TVgGUCzncbk/AdD8QQGOwtQCmpqbSokWLaM+ePbICuHPnTrryyispOTmZqqqq6OWXX6Zp06ZRU1OTcEx8fDzNmjXLL9ra2oiIhP+Wl5fTtddeG1JlQAUCIHyCdQqhAgH0P5dxvL5b2JZyqpWISFXnfqblkuLPjdA3NmTX0Ys7TgqfpQLIorZjUPZ3EkwAS8NIqWOWAD6y/mjAc+5Zrc8fiTzov20ugDxyAnjXXXfR888/L9p244030vz588O6xw9/+EMqLlbOuTU6Okr9/f1CtLS0xHwFAiBcgnUKoaJFAA+c8U9VoqbcSseNjE9Sz9AYud0exXO1zAIOVQAX7C0TtjEB/NE7eUE76/VHahR/boT+wU/KaOqWf2K37MsK2d8JL4ByeQDDCbMEMNzztAABjGABHBsboyuuuIL27t0rOu6ll16ie++9V9U1e3t7aXR0lIiIWlpa6Nprr6Wenh7F45ctW0ZxcXF+EcsVCIBw0btxt4sA7ufy3knHbfHnhToGcGR8kvJqOml0YpKyQhTA5z8uEbYxAVTbYbM8gVaKUayEFgHkE0XLPQEMJ9QMEwg1ylv7yPnFGeroH6Gi8z00d6M6WdUbCGAEC2BbWxvFxcVRfn6+6LiVK1fSjBkzVF0zPz+fZs+eTTfffDPdcsstsmMMefAEEAD90Ltxt4sABtrPbw9VAJnELdxb5ieA7EnjtmPnZe+tRQAdTv8JCQjj47OiJtntS/eVy9aT+9/MpuUHKqm5Z9jWAsgi1CX+9AYCGAUCWFBQIDpuxYoVdMMNN5hSJlQgAMJH78Y90gQw1DGA/LbkvHrRv29akkYVbf7pV5gY8gK4rzR0AZwVZNkvhHnBBJBP7s3HfW9mR4QAzliUGtLxeoP+O4IFUI9XwOGSmJhIM2fOpBkzZsR8BQIgGN2Do7Qhu446+kdE2/Vu3GNJAO9dm+V3n58mHfPb9udPThIR0Qs7xAI4NDphucggwosl+8qpP0hKl0gQwFBDbyCAESyARN5JIC+88IJo28yZM8OeBBIqqEAABOexTd4xPj98R5yiSe/GPdYFMFDHKRXAv+06bXmHjggvFqeUB022rd8kEAhgNGNrARwcHKTS0lIqLS2luLg4SkhIoNLSUiHNC0sDs3XrVqqqqqJXXnmFpk2bRo2NjaaUDxUIgOAoNeJ6N+5//fRU2B1HpAlgKFFQ1+0ngLOX4ZVupMbjyYWmrbYCAYxubC2A2dnZsrNun3rqKeGYpKQkcjgcdNVVV1F8fDzl5uqfMFIJVCAAgqPUiOvduGvpOKwWwPa+EeoZGpM97vmPtQmgw+miu1cdFv69r7TV8s4coS32nGwx5T4QwOjG1gJoVzAGEAD1KDXiejfuWjoOKwWQX6Lr0vCY33FanwBKAwKIUBtz3gucoNnM0BsIIARQE6hAAASHb8R/sSGfJqbWotW7cdfScVgpgPzrvB+/m+d3nN4CuCq1yvLOHIEINfQG/TcEUBOoQAAER9qQZ1V3+G034j6hXNsuAsiO5z/rLYAIRCSG3qD/hgBqAhUIgOBIG/LMyot+2424TyjXtlIApfn7pMdBABEICKARQADDAGMAAVCPtCGHAHqDCWBlW79oe+/QmOizHpNAEIhID72BAEIANYEKBEBwpA25VQLYPzJO57uGZM/l1+8NVqZgxwXaz2/fc9IrgFUXxALYeumy6DMEEIGAABoBBFADqEAABEfakFslgNdPLT1V3trnd66dBLCld1j0+fmPS2h7YaPlHTACYWXoDfpvCKAmUIEACI60IbdKAAPdT+0r4Em3J+hxgfbz29kr4Op2sQDm13VZ3tkiEHYLvUH/DQEMC4wBBEA90ob8cJX9BFDtE8DRicmgxwXaz29XEkAEAuEfegMBhABqAhUIgOBIG/JoFsCSxh7F/SPj4nOZAJ5tH7C8c0Ug7B56g/4bAqgJVCAAgiNtyKNZAL+3Nktxf9bZDtH25Lx6enLLcXoz/azlnSsCYffQG/TfEEBNoAIBEBxpQx4pAvhxYSPl1XSKjkuvaA/YMQUSwEcSj4m237g4zfJOFYGIlNAb9N8QQE2gAgEQHGlDLieA5a19lFp2Qdf7SDuOQJ2JnADKHftgQo7i/ov9I6rvj0AgQgu9Qf8NAdQEKhAAwZE25DctSaPj9d2yjXxZi3+KFjmWfVlBq1KrhM8ej//sXBYbsuto14lm2c5kaHSCMiov0uclLUE7HqV7tF26LPtzsqjtGAy4H4FABA+9Qf8NAQwLzAIGQD2hNPIpp1rp8tgkPbe9mD6fmiQhpb3P96RtZHySiIjcMulZ1HQmT28rIofTRbOWpgc9Nr9WPj3Lvz4/o/j0z+F0UfzyjJC/BwQCIQ69gQBCADWBCgRAcEJp5FNOtdLGnLqAjX5zjy9R8uUxrwCGOpM2lLIxdhc3y+5/ccdJemFHSdBrWN2BIhCRHHqD/hsCqAlUIACCE0ojv6+0lVanVgds9HkBHB6bCPke/HVDOTYh41zYndezHxVb3oEiEJEceoP+GwKoCVQgAIITSiOvRgD5pdKGRs0TQKs7QAQilkNv0H9DADWBCgRAcEJp5NUIYOuly8L+1kuXaYWrMuzORO9jEQiEMaE36L8hgJpABQIgOKE29E9NTcxQavTbOAH8Y5ivVv/8yUnqGFCeuMHHvtLWsH4OBAKhX+gN+m8IoCZQgQAIjt6N/oU+nwDevepw2Ne+bXlGSOWwugNEIGI59Ab9NwQwLJAGBgAx5y4O0DuZNcKYPB69G329BDCU6Bset7wDRCBiOfQGAggB1AQqEABeWCO9dF+54j69Gn0+D+C3TBLAFz85aXkHiEDEcugN+m8IoCZQgQDwwhrpRxKPKe7To9H3eDyiSSBmCSACgbA29Ab9NwRQE6hAIFZp7hmmksZe4TNrpB81WAAfTy4U7f/mSgggAhELoTfovyGAmkAFArEKa5SX7iun+9/KFj4bLYDS/XetzLS8Y0IgEMaH3qD/hgBqAhUIxCpKjbTZAogngAhEbITeoP+GAGoCFQjEKkqNNJ4AIhAII0Jv0H9DADWBCgRiFaVG+qdJ5grgnSsggAhELITeoP+GAIYF8gCCWEepkTZbAG9+9ZDlHRMCgTA+9AYCCAHUBCoQiFWUGumfmSyACAQiNkJv0H9DADWBCgRiFaVG+ucb8lUfqyaWfVmh27UQCETkht6g/4YAagIVCMQqSo203gIobfit7oQQCIQ1oTfovyGAmkAFArGKUiPNBHBDdh299Nkpcrs9ujb8VndCCATCmtAb9N8QQE2gAoFYRamR/sWUALLPR2u6NDf89Z2DQe+LQCCiO/QG/TcEUBOoQCBWUWqkpQKYUXlRc8P/yPqjQe+LQCCiO/QG/TcEUBOoQCBWUWqkpQL4UEKu5ob/ntVHiIjI49H+OhmBQERm6A36bwigJlCBQKyi1Ej/cmN+wP3hxB0rMmlswk2pZRcs74QQCIQ1oTfovyGAmkAFArGKUiNthAAiEAiE3qD/hgBqAhUIxCpKjTQEEIFAGBF6g/4bAqgJVCAQqyg10nM3FgTcj0AgEOGE3qD/hgCGBdYCBrGOUiM9d2MBJmsgEAjdQ28ggBBATaACgVhifNJNz20vpi1Hzys20nM3FtCkDsmfEQgEgg+9Qf8NAdQEKhCIJfaeagnaSM/dWEBjE27LOwsEAhFdoTfovyGAmkAFArHE9oKGoI303E0FNDI+aXlngUAgoiv0Bv03BFATqEAgVmjsHqJZS9ODNtKPbSqg4bEJyzsLBAIRXaE36L8hgJpABQKxwv1vZqtqpB/bVEADI+OWdxYIBCK6Qm/Qf0MANYEKBIbvu7MAACAASURBVGIFtY30rzYXUN9lCCACgdA39Ab9NwRQE6hAIFZQ20j/anMB9Q6NWd5ZIBCI6Aq9Qf8NAdQEKhCIBnqHxmjS7Ql4zG3LM1Q10r/aXEBdg6OWdxYIBCK6Qm/Qf0MANYEKBCKd6vZ+cjhd9HhyYcDjHkzIUdVI/2pzARXUdVveWSAQiOgKvUH/DQHUBCoQMJPtBQ20/EAleTyBn9aFwrIvK1Q1sL95v9DyDgCBQMRu6A36bwigJlCBgJmwhrC0+ZJu13xtf6VsA3t5bJLKW/sE2fzLp6cs7wAQCETsht6g/4YAagIVCJgJawjza7t0u+brB+QF8NHEY+RwuijlVCsREc3bWWp5B4BAIGI39Ab9NwRQE6hAwCzc3Pq6hfXdul131cEq2QaWbfvV5gIiInr5MzwBRCAQ1oXeoP+GAGoCFQiYxeiEb3m1ovM9ul13dWq1bAPLtv1iQz4REb0EAUQgEBaG3qD/hgDS+fPn6b777qOZM2fS7NmzaWhoSPW5qEDALAZHfcurlTSKBTBYCpdArEkLLIAOp4uGxyborxgDiEAgLAy9Qf8NAaR7772X8vLyiIiop6eHJiYmVJ+LCgTMgk+ufKqpV9he0thDNy1Jo+2FjWFd961DZ4XrXuwfEbbzDW96RTv9+ZOTlncACAQidkNv0H/HuABWVFTQAw88EPb5qEDALDr6R4SG8CQngPeuzdLUQCZknBPOj1+eIWznG970inZ6EQKIQCAsDL1B/21zAczNzaU5c+bQNddcQ3FxcZSSkuJ3TFJSEk2fPp2uvvpqio+PF57mqSElJYUeffRR+slPfkK33XYbrVy5MqTyoQIBs2juGRYawhMNvlfA338rW1MD+e7hGtlGlt+WVt5OL+6AACIQCOtCb9B/21wAU1NTadGiRbRnzx5ZAdy5cyddeeWVlJycTFVVVfTyyy/TtGnTqKmpSTgmPj6eZs2a5RdtbW20e/du+q//+i9qbm6m0dFRuu+++ygjI0NaDEVQgYBZ1HcOCg0hPwv44bdzVTWQQ6PyQxvWHwkugHyyaAQCgbAi9Ab9t80FkEdOAO+66y56/vnnRdtuvPFGmj9/vqprFhQU0MMPPyx8Xrt2La1du1bx+NHRUerv7xeipaUl5isQMIez7QNCQ3iMywP4yPqjQRvIjMqL5HC6KCm7loiI9p5qoYcScqmha4iSsmtlG1mrG3sEAoHgQ28ggBEsgGNjY3TFFVfQ3r17Rce99NJLdO+996q65sTEBN16663U29tLbreb5syZQwcOHFA8ftmyZRQXF+cXsVyBgDmUt/YJDWHuuU5h+y835gdtIG997ZDoGPbvJ7ccp405dZY37AgEAhEs9AYCGMEC2NbWRnFxcZSfny86buXKlTRjxgzV101NTaXZs2fTrFmzaN68eQGPxRNAYBUljb1CQ5hV3SFsfzy5MGgDedvyDNEx7N+/2JBP7+fWW96wa41/7D5teRkQCISxoTcQwCgQwIKCAtFxK1asoBtuuMGUMqECAbMorO8WGsLMyovC9qe2FQVtIJUEcO7GAkrOs0YA71l9RLdrbS9oUNx3++uZlndcCARCe+gN+u8IFkA9XgGHS2JiIs2cOZNmzJgR8xUImENeTafQEKZXtAvbn/2oOGgDGa8ggI9tKqBNFr0C/u6aLN2u9XFho+K+xKxa3e6DQCCsC72BAEawABJ5J4G88MILom0zZ85UPQlEK6hAwCyOVF8UGsKDZReE7XyCZo9HfkWQ21+XF8Bfby70mwRiVqxwVep2rU+ONynua+4ZxjhHBCIKQm/Qf9tcAAcHB6m0tJRKS0spLi6OEhISqLS0VEjzwtLAbN26laqqquiVV16hadOmUWNjeKsihAoqEDCLtPILQkO4/3SbsH3erlJh++jEpOy5SgL4RPJxvzQwwWL6fH0a813Fzbp1DJ8VBRbAzMqLut0LgUBYE3qD/tvmApidnS076/app54SjklKSiKHw0FXXXUVxcfHU25uruHlwitgYDZfnm4TGsKUU63CducXZ4TtfcPjsufy4+AeSvDlDXxyy3F6JzM0Abxhcaoujfmeky26dQy7TijLJAQQgYiO0BsIoM0F0O6gAgGz+KLEJ0xflLQI2+fv8Qlge9+I7Ll3rJCfCPG7rUW0jlsKTk3cwqWU0RJ6StnuAE8TIYAIRHSE3qD/hgBqAhUImAX/mnPXiWZh+z8/96VASc6rl5VAJQF8elsRvZl+NqRG+E6Fa4UaYxNuejTxmGiGcrjxeYny08TmnmEhETYCgYjc0Bv03xBATaACAbPgU518WuRb6pAfA+hwuuj6Rak06fZQc8+wcIyStP3hgxO0Jq06pEb4O2v0Sd/CSK9o13ytLwIIYFM3BBCBiIbQG/TfEMCwwBhAYDR1nYP05JbjdKKhh4hIlK9ve6FvktPLn53yayhf2emVwn2l3rGCSgL4zIfFtCq1KqRG+AfrcnRtzA8ZIIAnGnqEf0MAEYjoCL2BAEIANYEKBIzi/jezyeF00Vfnexu+Ddm+VCYf5jcIx/FpYKRx/1vZRKQsgM9+VBxyOpb/ey9Pc0O+/EClUH69BHDJvnLh88j4pPBvCCACER2hN+i/IYCaQAUCoeJ2e+hkUy+NjMunbGFIG753D/tm6245el447oUdJYoN5vfWZhGROA0MH3/aXkKv7Q9NAH++IT+k46Xxhw9OiH5OPeQskAA2dg9BABGIKAi9Qf8NAdQEKhAIlW3HzpPD6Z2AEQhpw/fWId9kjfdz64Xj+JVA5CK/totmLU2X3ffCjhJa9mVFSI0wP+s4nPjjR8Win1OPGbp7TrbQUk4AJ90e4d99w+MiAbxpSZohnROfpgeBQOgfeoP+GwKoCVQgECrfW5ulqkFjx9y0JI2IiFYd9I3V25hTJxz3zIcngjacX1twUHb7n7aX0OKU8pAa4QNntInOswYI4N5T4ieARETFDT2UX9tFROKnjJ0Do4Z0ThBABMLY0Bv03xDAsMAkEBAuD3CTKJQYm3ALx3x3jfc17qv7K4RtiVm1wrFPbSsKu0F95sMTtGBvWUjnHCy7IIxPDCeeSD4u+lkPVxkjgDy8ABKR5vvJBQQQgTA29AYCCAHUBCpQ9JFWfoGqLhj3+/zhO3lBG7TG7iHhmIff9q5ssyjFJ2rvHq4Rjn1yy/GwG9TfbS0SVhKZqfLVaKpGAZT+3NEigPttLoBzNxVYXgYEQkvoDfpvCKAmUIGii7rOQXI4XfT9qdmzRvDI+qNBG7RjtV3CMWwix78+9429W5dxTjj2N+8Xht2gPp5cSP/Y7U0krTYhc1r5BfrWqsO6NeRHqo0XQH6mMVFsCqBRPzcCYVboDfpvCKAmUIGii5xzneRwuujrCw+S2+0x5B78LFoldp7wrfpx54pMIiKat9OX8HlRShklZtVS66XL9JiGJztzNxUIiaTvVil16RXt9I1l8pNKwmnI9RDAlFOtorGMUswQwOaeYcs7SKX45cZ8w35uBMKs0Bv03xBATaACRRcpp1qFxqZ7cNSQe/DC5vHIS2YCtz7v7GXpRET0oky+v++uyaJfhJGWhU0o+VnSMSGRtNrXuocq2hUnlYTTkGdVd2juGDr6RywXQKOuq0c0dA3ZunwIhJrQG/TfEMCwwCSQ6GTL0fNCY1PZZszvlB+zNzw2IXsMG5fncHqfRhIpp3t5NPFYyA0pe+r2k/VH6S+fegXw4bdzVZ2rR049nqyz2gWQiCCAAQICiIiG0BsIIARQE6hA0cWb6b5ce1lnOwy5By+AF/tHZI+Rzuwdn3TT0wqzfX/CjSlUG7lTr7rvezObnv/Ym0harUjqMWmDxwwBLOaWhiOKPQFs7IYAIiI/9Ab9NwRQE6hA0QWfEmXniaawrzMyPkn7Slupd2jMbx8/G7O2Y0D2fH6msMPpooGRcXoiWX6274/eCW1ptgfW5VB+XZff9l9tVjeW8Ej1Rco+20F3rcykxKxazQ15tk4CyM+SluLxeGhdxjlKOeVdG9mozsnqDlIp8AQQEQ2hN+i/IYCaQAWKLtjTMIdTnGolVD4ubCSH00Wv7q/w28fPAj7V1Ct7vnRGbsfACM3dKC9oal/d3vraISqo66a+4XE6wT0RY6E2n2BWte/JaEVbn+aGXI0AbsqpC3q9QAIoRe4acmMs5UIpEbbSde0QRgjgLa8dsvznQsRW6A36bwigJlCBogv+6dzCvWVhX2dNWjU5nC56bnux374HE3yJoHPPdfrtH52Y9Gv4mrqHFV/R8omlAwWbTUxEdKqp12//c9sDLynHIpt7NV51oV9zQ85mXisFS3rNPq9OraaeoTHRmEgi7QLYNzwetNxfW3BQ8Xyl7XYIIwRQaUgCAmFU6A36bwigJlCBoosfcDIlXbM2GGnl7fTbrUXU0T8iyMhv3i/0O+67a3xLwbnOXPDbz9KJXL8oVXgSeLZ9gH78rvyrXrWzd+9edVi4R3mr/5O7l6ZmAweLHE5az10cUHUOPwlD2pCHKoD7T7cREYnWMCYyVwC//5b/d6503VAinATbq1OrRTkQ5cKIMYAQQITZoTfovyGAmkAFii5uf9336vWR9UeJiKhnaIwWp5RTeWtfwHPnvOd9tftZUZMgU3PeO+p33J0rMoV7fFbkP86QTVj47posumf1EXI4XVTafElWOthxahpPtqQcEdH5riG//SwfYLDgn1rWdvgEcGGAJeXaLl1WbMjDFUA2eeTGxd61kvn7B0PuPn2XgwvgdVMCeLy+W7Zz0trB3a/wOw4U7x6uCbqecyQJ4PULUw25LiLyQ2/Qf0MAwwJpYKIPt9tD13H57b650vvEjI0/e+mzU4rnjk5M0tcXes/dkF0ndI73rs3yO5ZPovx+br3ffjbG7Jcb84Unkvl1XYIMSkNpuzTu51Y36Rka89uvlGZGGkdruoTrsJVTHE6X6AmcNC70KQtgsDGAUgE8cMYrgB6Ph4rO9wj5Gs0QwK/O9167ss3/1bfSdaWxvbCR0srbZfeFI4Dv59YHlG+H05fTcndxs26dsVECOGtpOn11vv7XRUR+6A0EEAKoCVSg6OHSsFiKrltwkCbdHvr71FJpv91apHju6eZLwnmrUquE1T5uW57hdyz/hINf0o3BXuf9+ZOTQoqXI9UXRU8n+fjmSnUreDyYkCPcY2LS7bdfaRbwI5I0M8dqfQLIP0kM9wlgsDQw6494J+Owz0wApRgpgGzpu19v9r7SD0UAV04l3ZaW7Xdb/QUqXAFcEEQAGSWN/pN/1EZ+XZcwttXhNFYAr1+Ep4AI/9Ab9N8QQE2gAkUP9VNPs2YuSaPpU08gOgZGhMkXP0s6pnju9oIGoZH61+dnhCd3X194ULTax6TbI2rQXt1fQe9k1tB9b2ZT58Ao5XNrAGdWXhQmpbjOXKBZS+WXX7uDe6UcKH70Tp6ozNL9SrOAL/aPiD7ncwLY2D0kbA8kgK2cALLXqAzpSiBJ2eLUMu8dFgug3LhJIh3GAF4ep3WHztIjMpNtmnuG6a1DZ6lr6klaKAL4BidNfNnYHxZ8hCuA8/ecCXgMQ4sASr87owRwNgQQoRB6g/4bAqgJVKDogXWO312TJUhVWUsfzZ56ZfuDdTmK5/Kd+bMfFYueyl0emxSOGx6bEDVo/HnvZNYIsvDXT72vm9lTos9LWhSXX1O7Lu9P1ovHI/L7Hk8ulE0N43B6Xx/yn/PrfALIr38b6CkUL5FsZROGdC1gadnelQjgwTJ5AdT6BLB/ZJyIvEMBgnU8eghg9+AoPfOh+LV7OJNAkvPqRSvHBOo4ixV+x6F0vuzz09uK6J+f+0us1pi9DAKIkA+9Qf8NAdQEKlD0wJY4eyTxGP3fe94Zt58VNQmNz7e4WbRS+NQuczcV0MwlacLnDm61D+nYO/41YGJWrSBRCVOvhv+03ZuX8INj5xUbxesCrMvLz2qWPsFk23+5MZ+IxDLHh9vtEV6BOpwuKqzvFq7R0isvgL//4IRfw83+zdY2ZkhXFuGP5b8L9llJAFlOQrmZ11Lkfs6+y14B9HiCC+DYhJviJbkala6rJICMx5MLhX3hCmAgEbuDS/+jJPmhdL7sczQJoNzTWIT9Qm/Qf0MANYEKFD3sPOGVvae3FdEfpgTmr5/6UqPMXpoue97Q6IRo0Lr0NR6/2od0LBw/rm9Ddh39eSoZ8daj54mI6JWd3pm5CRnnVDeS/JNCNjPZ4fSKKQ/bzgRQWjYWHo9H9OrwOCeA/Kvd+XvKROd8+w3f5BT+flIBlK4tzB/rcLpo3aGzom2pCgJIRNQ7NEZut0dxv/Rn5yMUASQiGpeMo1S6bkgCGMYr4OS8evpHAIG5M8IE8BsWCCCfUghh39Ab9N8QQE2gAkUPG7K9s33/tuu0IDO3v+4bXzd9vkskFyPjk/TyZ6dEa/s6nP5pLE5yq33ws2alsSq1SrjWFyUtRERCOZYGyfPGBz9W8BdTk1EcTv8nY8l59TR7abqQ3qa9b0T2ekREpdwkl6LzPcI12hQEkEic75BIWQDlcgTyn9emV4u2BRJAtcj9nKEKoPQ6Stc1QwD/tkudABad9wlgjcocjtJys89PbytSXS/VphhyOL0rjJgtgNKhGQh7ht6g/4YAagIVKHpgszVXuCrp7Uz5J24DU+PEiPzHriklauYTJwdaOs35xRlhxm1m5UUiInptfyU5nOInkcGCf6rIrx8sN4t5khPajgFlASxr8ZW7uMEngLw08hMRiNQLYHoQAVydKhbAtHJjBVBuv5rrEJGQCogPMwQwkGDxAsjnL1T6HljcuDhNttzs89PbivzGhypFsDyFfNxqsgC+tr+SiIh+miS/0g7CPqE36L8hgGGBPIDRBxsHlJRdS58cb5JtgC70XRaO33/am6/vmysP0ys7S0VPV/hgiYuJiEoa/ZdgY/Hc9mL63lqvNLGnbG+mnyWH0+X3lDFQ8K9en/nQNxbvDx+cCPjzj4z7lqBjr55Zo8uLa0mjTwD5yR38RAQi9QIozYnHH+twumjVwSrRtrTy9rB+vzxy35seAnjvWv+k3MEEkP8dKY0BrGzrV6wDyXn1ot+XNMIRwK9OPe2WKzf7/PS2ooDX4CPYSiV8QAARSqE3EEAIoCZQgczlcNVF4fWo3rCJCztPNPlNTGBx7qJvPN+uqaS6rCP0eDyyT4A+Oe5b7YOleXkwIYd+JulwHttUQLe+dogcTu/Sb0REiVnelCj8WL5gwa8N/OKOk8K/n1WxtF1ZSx+dablEREQHyy4IM37PtvteF5Y0+l5pd3ACOE8ijbwMEQUSwAt+jTz/+fUDlaJtdhbA74UhgHweRCUBJCJKLbsguy85rz7gaip3rfQJYKFKAbxpSZrsz0fkWy+bPaUOVh/fTD9rawF8dX8FEUEAIyH0Bv03BFATqEDm0TkwKghWsGXZwoHl+ztU0e63Vu7Nr3rFjJefj6Zy/z3/cYmwTS4n36acOmE/e238k/VHKVfSaT+UkCvM6G3v884c3nLUO/tX7WofDqdYFvlXgy/uOBn2d8Mv+XaKG9PIvzb+Azfzl0i9AErFhj/W4fQ9oWGf0yuiSwD5J8eBBJB/Uto/4ktanZxXr/gzOZxiASyokxfAJ5KP05mWS3Sk+iJ9b22WUM/lyj0+6RaWlgt037czz1HHgLcehyqAMywQQOkfZAj7hd6g/4YAagIVyDzYJA2H0/daUE+YsBQ39IjE5vbXM+hH73jH92Wf7RCO35zrLc+8naXCNj7tCgs2iYGIyHXGKztzNxaQx+OhRSllwqvS2dzkDZY7kL2KvmlJmupGks0kdjjFqVkCLWUXDH7Fj9LmS8L2zgHfGLDC+m66/81s2lXcLPo+WcPN/i0VwINBBHDZlxWibXYWwPtkBG51arXwKv9vu077XUMkgApjAInEYyX5e+shgErDA0L9DliwJfMYSgIoXWXG4fT+oWKmALL6BQG0f+gN+m8IoCZQgczB7faIhOKe1UdUpfsIBZbwua5zkCa5dYHnbiqgx6Zee/HLkL2TWUMOp1eyGL/cmO/XaC3ZVy7s/6KkhRxO75g+hjT/3vULU4XVQ/aeagm5kaxo66OXPztFGZUX6dX9FcL2ebt8ohoqTd2+Mp7mBJCfBNA5MCo6R60AsrWP5Y51OL0TCPhth3QQQPa7ZU92HU5lAQy0Aoy03PwTvNcPVNIdKzKpa3CU3G4PlbX00cSk2+8aap8AHlIQwC1TKYOU6gMvgPl1XbLX0CKAyw9U+t1TrQC+sKPEb1vf8HjECOBshdV5EMaE3qD/hgBqAhXIHI7WdAkNLktzws9G1crYhC+n26XhMSIiumul93Xugr1lwkD9z4p84/lWp3pf7bFXlEREf/yo2K/ReoV7QrjjeCM5nOLxeAMj4jVob3/d12FLx8epifNdvtdz/OvHf31+Juzvh8/3V9bie/3eN+wrO1smjfE9lQLIJtPIHcu+f35bxtTYMy1UtvXTS5+dEsmXnADuOtFMoxOTiteRlpsXOCJS9UeKWgHM5PIl8vcORQD5sZz8OVoEkMiby5Ef/iAVQKV0MVIBnLvRm6vSTAFk9TkcAUzKrqX9p9vowYQcYf1vhHGhN+i/IYCaQAUyBzaZYcm+cmGywVLuyZpW2GSGr3K5/n4y9Xpqy9HzwizL93PrhXNY8lj+FS+fkJflEOQ7Vzamjy31RuSdPMInb77/rWxhX/ZZ8Tq5SsvB8TE4OiGcz55SOpzetXrDhU/3Ih1/uWBvmaxcKj4BlCTU/jKIAM7fc0a0TQ8BZPCzmPuG/QWQH/Mph7TcUgFUAz8zN5AA8mmH+HsHE8BvrhSvYLP16HlhNRV2DP9HCs/6IzWqfx4+f6JaAeQnKTmcxgug3JJ5jHAEkCVsJyJDkmIj5H9XeoH+GwKoCVQg4+kcGBXEp7KtX5g1efvrGbKv1MKhut27tmv88gxhW2JWLd22PIPqOweFPGbrppYlIyKhM1l/pEbYxnIJOpzeJeUcTl+nxq7pcLron5+Lx4Lxuft+yr1y5OXA4Qy87m9T9zDVdQ6KrrsxxzduUosw82P91E7AUSuA+0pb/Rp5/vMbaeI8gPzKKlqJJAFUmsG7VUYA+RU/pALIs6+0leZuKhAma0jxeDz0fm69aPUXNd9HuALIVqXhBfDlz9TnwJQLpXRE0t8TL4DJefXCv6VL/vGx7RgE0MzQG/TfEEBNoAIZD5OYRxO9YjQ+6RbSpeTVdAY5Wx1sbNQD63JE29lYPPYqlX/d+9JUx8QG4RP5BM/h9HVuD7+dK+x/65B3MsASiYx9nxv8/9Q2X8LmMy2XRA3g3dyavHxIO1wGv4bw8gOVsseogV/DWK0AKr4CDlEAWfLt8tY+Olyl39M/IokAyrwCDlkA3wpdANW+AvZ4PDRvZ6nwBwfbJyeA/OdAAqg3SvVRiwASkWhFnlAjHAEkIiH5ujRPJR+8AEonMyH0D71B/w0B1AQqkLHwkz92nWgWtrPZrdInaeHCJiJI18tlJGV7xe4fu333e267d7zfx4WNwjY+gTR7GnjP6iPC/hWuSmEfDz9+iJ+ty6dfcTjFOf74+PrCg7Ll/qzIVx4tM6f7LvvG+rE8gcFQK4App5QFMFjyaq3oJYBsvWIjBVDp3pEggEpr7b74iToBLGvpowfW5Sjm5wwU4Qqg2+2hi/0jsuew4AXQ4/GI/uBC6B96g/4bAqgJVCBjOVbrm/wxPOYb28Zeh81elh5wkL5atk/l9PvT9pKA+/mcf7/dWkQOp0uUmJp/CvBhfoNQRobcq2Qi8WoQ/NPBll7xDGH2WtnhdImS5d6wOFW23PwsYn6sYqgMjvrWSuXTwARCrQBKZzrzxz7zoYkCqOEV8I7j3j8Cvm+AAB5UWPuY7WcSovQdWiGA0yUCyCcM50OtAMrdQ22oFUD+jzC19+QFkIiotkN5rW+E9tAb9N8QQE2gAhkL6yBYKhDGpNsjzNLVY1IAmywxf4/8RAn2lOqJZF/6lrkbvalh+A6arfThcLqEWZvTuYkl/+CWm+Nh6WEcThdt5BJHS9da/c37vnVjH347V/g3W7lBCp9kOUEinaFwecy3TNzJpsBSxFArgPzPLj020gSQf0KrlmACGOzewQTwW6usF0Ai8QxkFkoCeMNi/QSQres9572jsuczwhHA05I/hiCAxobeoP+GAGoCFcg4ugZ9K39Utvl/vyz/2F8+VU5w3Hd5nB5Zf5RWuAKPf5Ob0cvDZO6RRN8EDbbixpFqn4BWtvULjRWbWOJwelduICIhSTM/e5DR0T9CqWUXaGTc90RzeGxC1ADyaWb48VPfkKRWYWRV+2YRv3e4RvYYNfBpcvi1gANxn2RCBPu3VAA/DyiAwZev04Jer4AhgOIyyQlgLzeOlMWfTRDAiUk3ZZ/tEP4fVPp+QxXATJk/PPslKZ3uezObvrNG/So+iMChN+i/IYBhkZiYSDNnzqQZM2bEfAUyCjb5g5cuntJm7wSJGxeniV4P87And1+d71teTY6/TA343iIjZkS+V87f51K0sFU/2Hq5RERtXL687sFRun6htyNrvXSZiIie+dArcPz6wIFwuz2iBpCfEckmlDicLrqNm73Mwz+R3HlC3T3lmOTKcUJl/kW1Arh7ak1luWP/qGL9Yi3o/QTwBxoFUPpELNB12P5IEUAiouKGHipr8S2zKBVAlk5IrQCqkatA5/P7Awmg3NhDNjkp0PXvfzNblMAbAQG0GxBADaACGYPb7RFeISqJi8fjmyDy5ek22WP4pdASs2pljyEieiL5ODmcLtp7qkV2f0Wbt9O6c4Uvqe633/B2PvzauKMTk/SNZel0y2uHaHzSTbdMzVZmqUue3OK9z56T8veRgx8Pxf88/Ni5767Jkj2XJdB2OF3CgPZw4HO8qU0JolYAdwUQwGcNFsAOnQWQLVf4f+/lqS4DL4C9Q2O0/EAl/W3XadH3EejeE31OuQAAIABJREFUH0SQAEqPkwog+x2oFUClsYWBpEFpfyABJCIh/ygLCCAEMBqAAGoAFcgY2JOrWUvTaWhU/ukeEQlrrCq9KuSfyNz3ZraQ1kUKG0/Hr/XLw5ZCm8mNtWO5+6ouiH/39Z2D1DC1Ggcbp8hSp7BOJq1cfmC/HEwiHU6XKM/g6WZfipgXdshPXrk0PEY3v3qInuZSy4QLu1dBnc4CeMI6AQz2BFC6uokUdhwTwEm3h47WdCnKgRy8ADL4PHTB7h1MAO+2QACDddbsGF4A+WEMagTwawu8M99nBVmOLVAZ+f2hCmC/CgG8DwKoa+gN+m8IoCZQgYyB5d3j067IwQaWX78w1a9B5sccsQ5F7vVlS+8wTZ/vPa65Z1j2PnwevMmpCR2s42ngll6Twp5QsnFzP3wnjxxOF+WcU5+/8Ftc7r/Nub7Ezh0DPnnZxE0ckTIyPqkovqHA7nWstiv4weSfFJn9WyqAO080+TXy7N/PbbdmDGBzzzBVtwf/f5qdywQwHMIVwGc+LKavLzxI3VOSqvQdRooAvvjJSWG/HQVwDbesorS+KF0fAggBtDsQQA2gAhkDy7H3wTH5MXkMj8cjpN6Qvr7NmJq48f23soXZt3J5A9lTxMeTCxXvw0+C6BseJ4/HQ9dNrU4S6NXqgwlT4wSnpIm91lY7jo5ILFJ8zryJSTc9va2IvrnysGJnpCfsvmrXYFYrgHyuQumxSml59ELpCaBa2LlWCKDH46GxCd9KOErfoZ0FkI29dTjFeT5DEcDZOgkgG56hVPahUfGELLUCmFEZeu5CBATQLCCAGkAFMgY2mzJXxZOydYfkXwOz16Xz95wROtmblognjIxPuoVVBpTyrTHYWLyW3mE/IVRCOlP4zhXiV8JqYBLpcLqoc2CU/r77NL2Z7k087HZ7dFsOLxjrj9TQvF2lqp8mqhVAPnm29FijBVBpDKBa2LlaBHBgauboLO57YU93n9xyPMCZ8mWRfocQQOUy8vubuofph+/kKY4Dlp4LAYQARgMQQA2gAunPxKRbSP/S0iv/SpaHpVu5fmGqaOzVo1NJk/ecbCGPxzep5HOZxM13rMik8SAixUSx6kK/aGWMQImof7nR+1opdUouWWdVL1mzNxD8K2CWTzASUBLAWRIB3HG80a+RZ//mE28bgR2eABJ504fw6X+IQn91L/0O2R8fWhKAh4razpod81cFAWQTg9ak+ZedHX+dzgIY6s8HAYQARgMQQA2gAunP+a4hcji94/bUCI/H4xGW4GJ/vV8em6SvTb2iZeP62Dq9/HJvjyd7EyuzJ2qBYJMaTjT0CE+OvjrfFbCTZrOLU061qn5tLCXQ0xA7I10Wjf1bKoAfF0IA9UD6HfZdHqfMyotB/7AxsgzBjlMSQCLvuNtA50IAYy/0Bv03BFATqED6w3Ju/fAd9ak03pK8Bs6v884i/ubKw4KgXei7TF+dmuwxb1ep8JRh+nx1TxrZE5Ws6g5q7PZKqtIKHAy2xNtnRU00OuFbTUNpBqEcRjaARqIkgKHkAVSa3awXdngFrBd2qCdqy8COCSSAwc6FAMZe6A36bwigJlCB9Of9XO8A+D9zswKDUXVh6jXwIu9rYLa0m3SVkPl7zvg1Kr//QN1yY2wZtn2lrcJr53iFBMwMtlrHh/kNolnJoYzbs0PHHg5qnwDyYiw9FgIYelmsrCdqy8CO0UMA2ZKMDqdv2bdA5dAiFfx5EEAIYDQAAdQAKpD+OL/wStq6ENau9Xg8wpizlFOtwqvX7QUNouPcbg+daOihJfvK6fbXM+i6BQdV57V7dmoZth3HG4VVSO5ZfSTgOfN2eXOHbcqpo9apVUKuX5iq+uciIuFVdrB72Q21AkhEdMfU5BjpsS/uUP9HQDhAAK0pAztGDwFs7xuhBXvLqLq9329daUMFUKG+ZHLC9721WRBACKCtgQBqABVIf9hf9PtKW0M6j6Vz+f0HJ2jmkjRyOF0Bc7lNTLpDehXLVmfYlFNHBXXepeEeWJcT8Jz5e7wrd7x7uIZqO7w5C29+9ZDqexJ5l896PLmQzl0cCOk8q/m+HgIYwlPgcHC7PfRgQg49/HZuWLkSIYDhlUEPAfzeWv/Vb+wggNIyZkIAIYA2BgKoAVQg/Ylf7l1hI5RUKURElW39osbi5lcP6TprdtmXFeRweieMZFV3kMMZfMkvds6atGo60+J9amjm0lxWsmlqLeefJnnXcg4kgGyGtVQAQxkGEC5utyfsegIBDK8Mv9taRA6nN0F6qAJ4uvkSPfNhMdXJzKTnBTD7rHesbqAyhvpdsbcTEEAIYLQAAdQAKpC+XBr2jZMLtAScHB6PR7T82B9Uju1TC3vCuOzLCiF9zC835gc8Z3Wqd/WA5QcqqbDe+9Tw/reydS2XXZl0e6igrpsGp36P4QigdAyn3YAAhlcGt9sjLLMXqgAGghdANWUM9bvihwxcGpafpczfAwIIAbQ7MS2AZ8+epVtuuUWIf/u3f6OUlBTV56MC6UtJYy85nOE/JVub7luuaWOA5dHCgT3RmrerlPac9HY0wRL1JmR4B6UvSilT/dQwWoEAmlOWSBBAuXN2FUMAERBAs4lpAeQZHBykr3zlKzQ0pLy2qxRUIH1hKUECLcsWiIq2PqGxKGns1bVsLGHxsx8VC//+40eB16rdkO2Vxr/vPk2uM96nhnM3FgQ8J1oJJIB3c8mu+WP/CgEMuSwQQAhgtIbeoP+GAAp88skn9Nhjj4V0DiqQvrBXpkv2lYd1vsfjob9+eop+t7VI9wS4+0q96/D+5v1CYa3WYIKy9eh5cji9T7KY3P5ua5Gu5YoUAgng6eZLdM/qI7T/dJvo2EgRwNLmS1YXBQJI6gTwJ+uPRoQAfnPl4bDOi+bQG/TfNhfA3NxcmjNnDl1zzTUUFxcn+3o2KSmJpk+fTldffTXFx8dTXl54r9geffRR2rNnT0jnoALpC0u18sGx81YXxQ/2CnfOe0eFVUX+9fmZgOewdW7/+FExfVTQQA6n8bnt7EogAVQ69qXP7C2A9Z2DlH22w+piEBEEkEidAK5KrQpfAAdCE8B712bRuYsDYcnOPauPWC5cdgu9Qf9tcwFMTU2lRYsW0Z49e2QFcOfOnXTllVdScnIyVVVV0csvv0zTpk2jpqYm4Zj4+HiaNWuWX7S1tQnH9Pf303//93/TyIj6JbrYebFegfTkgXU55HC6KK+m0+qi+MFy/31r1WHRhJBAsA7pt1uLaOPUGMK/7TptUontRTQKoJ2AAJIwNtcMAexVWKqOSCyAbVP5PyGAEEA7YmsB5JETwLvuuouef/550bYbb7yR5s+fH9K1t2/fTk888UTQ40ZHR6m/v1+IlpaWmK9AejEx6aavL/QmPW69dNnq4vjR3udt/K9bcJBe3V9BDqeLVqVWBTznwJk2cjhd9NimAlo3tVzd4pTwXm9HOuEI4LxdpSaULDqAAEauAJ5o6BF9Tq9ohwBCAE0hYgVwbGyMrrjiCtq7d6/ouJdeeonuvffekK49Z84c2r9/f9Djli1bRnFxcX4RyxVIL853DZHD6aIbF6fpmr9PLyYm3cJawn+celX9dmbg1UrY+J9HEo/R6wcqvdJ4MLA0RiuhCGBSdi3ds/oItdnwDwG7AgG0pwC2qhBA/hz2GQIIATSDiBXAtrY2iouLo/x8cS62lStX0owZM1Rft6+vj/7nf/6HxsaU/4dm4AmgcTBZ+tE79k2TwgZm/2DqVfWmIKlm8mo6yeF00cNv59KCvWWqpDFaCUUAiSislTliGQigOgGskYzJC4XOgVEIIAQwqoh4ASwoEKfVWLFiBd1www2mlAkVSD8253rHyNk599sjicfI4XTR9YtSyeF00Yf5DQGPZ6927nszm17Z6V0XeHOuvvkJIwXWiN+0JM3qokQlEEB1AsjfEwIYWaE36L8jWAD1fAUcKomJiTRz5kyaMWNGzFcgvfjX595llhIy7PuE7LntxaIGKdjqBWz5t7tXHRbO3V5ofc44K4AAGgsEMHQBnBliXdRLADMkqWH4cyCAEEAziVgBJPJOAnnhhRdE22bOnBnyJJBwQQXSj19uzCeH00X7SlutLooiS/eVixqkL0+3BTz+bLv3ddNtyzPoyS3HyeF00RclLSaV1l5AAI0FAhi6AKacCq2t4QWwR4MAsj8MIYDq45H1R0P6XakB/bfNBXBwcJBKS0uptLSU4uLiKCEhgUpLS4U0LywNzNatW6mqqopeeeUVmjZtGjU2mvOUBRVIP25bnkEOp4vKW/usLooiSdm1okbpUEV7wOMbu4cE6fnFBq/gppZdMKm09gICaCwQQPsJ4HfXqBfA320tIofTRc986F3DHAIIATQDWwtgdna27Kzbp556SjgmKSmJHA4HXXXVVRQfH0+5ubmmlQ8VSB8uDY8J/6MPj01YXRxF+A7G4Qyer5CljvnagoP0o3fyyOF02SZxsNlAAI0FAmiuAHYPjga9figC2D8yTl+UtNDAyDgRGS+ANyxOtVzqIIDWY2sBtCsYA6gvJY295HB6x8rZmfzaLlGjVNzQE/B4Xmy/s8bboJ8Ick60AgE0Fgig8QLYNRi6AA6OTqgSQCn8+thGxO8/OGG51EEArQcCqIFYqUCjE5N0oqGH3jtcQ48nF9Kspem0YG+ZbtffNbVO7hPJx3W7phHUdQ6KGqVgr6svj00Kx85emq7qnGgFAmgsEMDQBfDAmcBjeKWEI4BERGUtfVTR1mcrAfzH7tOWSx0E0HoggBqI1gokFT651wXT57uopXdYl/utTq0mh9NFS/fZe5WMIclf87UdgwGPd7s9ft9bfWfgc6IVCKCxQACJ9p5SJ4BvpFXT3E0FNDbhDun63WEKoHQ7BBACaBcggBqIlgo0OjFJRed76N0Awhe/PINe3HGSthc0CBMa3jp0Vpf7s5U1guXVswPsSZ7DqW7JuusXir/L9r7Q1puOFiCAxgIBVC+A4aKnALK0VxBAlQKYeEzX3yVR9PTfWoAAhkE0jAHsGhyldw/X0G/eL6QZiwILX83FAdHKDK4zF8jhdNGdKzJpYjK0v6Ll+P5b2eRwBp9UYQfYKiAOZ+CZgAxeGB1OF/VdHjehlPYDAmgsEMDIEkA+pZQcEEAIoBlAADUQqRXo8tgkPcCJTDDhkzI24abbX/embUkPkgolGOOTbvragoPkcLoiYu1Xls/P4VQ3Y/n21zNF3/O4DsIciUAAjQUCaD8B/M6aI7Lb7SCAf4cARmz/rScQQA1EagVanOJtfO5YkalK+ORg4/ae2lakqSz1UxMrblycRm63/dd/5RtONeXl0znMXqZuHdxoBAJoLL/eXEgOp4v++FGxZWWAAHoJJoDnLg6YLoBr06upur3fFgL406RjEECbAAHUQCRWoMNVvmWItLxybegaIodT+2QQtizSj9/NC/saZvJm+llyOF00Y1GqquPZ622H00UPJZiXo9JuQACNpW94nHYXNwt55KwglgSwKwwB3JRTR8sPVBIR0bIvKwKWVZp0XmuwVYvsIIAv7jgJAbQJEMAwiNQxgB0DIxQ/teLG61MNkRaeSPa+DtUyGWRTTh05nC76y6enNJfHDLYXNpLD6aKbXz2k6niWANrhdNHvtmp7WhrJsO8g1PVXQeQQSwLYORC6APIEE0C5DAJaYr/NBPDdwzUQQBsAAdRAJFUgj8cjLDf08Nu5NDoxqfmaekwGYbPh3s48p7k8ZsCeWH5zpbqk1T/jXnfM33PG4NLZFwhg9BPtAtgz5EvsbrQAEonfHkSVAH5ykoiI3slUL4GPQgANAQKogUiqQB8cO08Op/fV5bmLA7pck58MEmxdXCVYShn2isLutF66TF9bcJAeTy5UdTwbm+VwuujdwzUGl86+sO8Ar4Cjl2gXwF6TBVA6US/aBLCldxgCaDEQQA1ESgU62z5A10+levmooEHXa2udDHLb1CvpirbIWSGj7dJlujym7gnqU9uKhEZstw6dXKTCvgM8AYxerBZA9kYCAhhcAP+2y3oB5MsDAbQGCKAGIqECjYxP0kMJueRwuujpbUUhz/YNhpbJIHyDqialSiTyp+0lws94rLbL6uJYBgQw+tEigHr8cTQ24aa5mwrojbRqzdeSI5oF8LtrsswTwB0QQLsAAdRAJFSgV/d7G5rbX88I2GhpgU0GWRfiZJCSxh5yOF109yp14+kikZc+OyU0YnUxugwcEQQwFmC/41DSHekpgEYTqgB++w1jBZBlJNBDAIfHJlRfS2u8me7rJyCA1gIBDINImQWcfbZD+B8oq7rDsPuwVy93rQxtMsiuE83kcLroyS3HDSub1Tz/se8JoNrXxtEIBDD6OdHQQz/fkE/lreqHc8SqAJa19JHD6aIfvaOc/iqYAIYyiSKYAPL7jI7kvHq/7ypY/DQJAmgEEEAN2LkCdQ+OCqtQLPuywtB7hTsZZFVqFTmcLlq6r9zA0lnLY5sKRI1srAIBBHJEqgB2DCiv6a1GAImILvaPBFwZCAIIATQaCKAG7FqBPB4PPfPhCXI4XfRgQg6NjBv/5IlNBnk6hMkgz3xYTA6n/hNT7MSDCb5GPJaBAAI5YlkAg7E2vdqWAii3djwEMDKBAGrArhXo46lkxdcvTKWqC+aULZzJIPdP5bk6WhO9kyPYk1EIIAQQ+BNJAnhp2FwBHJ2YpH2lrdTRP6K7AM7bVRq2ALJx5RDAyAcCqAE7VqDajgG6YbH3L7QtR8+beu/Hk70579RMBjlU0U7T53v/577Yr9yYRjpvHfIO1P79ByesLoqlQACBHBErgAHaLL0EUO6aagSQzej9xrL0kATwWG2X8FZGLmYsShXWjue3d3ErpEAAIwsIoAbsVoFGJyaFpcee3HKc3G59U74EQ+1kkNPNlwRJXZwSveP/iLzjI7POdtDQaHSmuVELBBDIAQFUh5wU5Z7rlN3e0DVE83aWikStuWdYdB05AQx0L4fTRc98WExE5CeAgc7RSwCNGMdut/7bCiCAYWDXWcCrDnonVdz62qGADZRRjE24hbWGlSaDNPcMC69Fn9pWFPYSciCygAACOSJJAPuGx20hgA1dQ5RZeZEmFdYL5ukdGqPzXUN+1zFbANnbHodTPOY70Dl3rsgU/m3EH9AQQAigJuxUgY7Vdgn/s4S7LJsesJm9cpNB+obHhfUtf/ROHg3G+FOxWAICCOSIRgH8qKCBrl+USicaenS7N7svP6xHjQAqXUeLAPJrIqsVwBsXpwn/3nG8Mei9pAJoBHbqv60CAqgBu1Sg3qExumul93+WBXvLLC2L0mSQ0YlJ+tVmb0qUb606TO190TvuD/gDAQRyRKMAEnnlTE/k5MlsAfzjR8WyxwQ6BwJobyCAGrBDBfJ4PPTcdu/A3fvfyrbFkmrSySAej4de2eltcGYtTTdtZjKwDxBAIEekCqDZE9f0FsD5e85oEsA1adWic0MRwI8LIYB2AQKoATtUoJ0nmsjhdNHXFx4MKQO/kRw400YOp28yyLqMc+Rwuui6BQcp91yn1cUDFsB3BAAwWL34vKTF6qIExQ4CWFjfLWwLRwC3HTtPDybkUMfAiOI5agRwZHySth49L4wvDCaAHxU0yAqgNB8hH3M3Fgj9hhHYof+2GgigBqyuQPWdg8JfVpty6iwpgxz8ZBB+LdzPipqsLhqwCAggkCOiBPCydQJ4puUS7T0l/o7CEUAeNQJ43YKDsgIo5fogyaFzuBnLagXwyS3HaWBk3LAlNK3uv+0ABFADVlag8Uk3/WT9UXI4XfSb9wtNT/kSDDYZhMXa9GqriwQsBAII5IAAho/bRgI4c0maosg5nOKUNWoF8Ldb1a8qFQ4QQAigJqysQGyZoJtfPUQX+i6bfv9gsMkgDqeL/vLpKdsJKjAXCCCQAwKojaLzPaKna0YKIJsFLAc/xk8uhkYnIIA2BAKoAasq0PH6biGvUmrZBVPvHQobsuto4d4yU9YiBvYGAgjkgADqg1EC+FUuf1+4Asjafwig/YAAhoGViaD7Lo/T3asOk8Ppon9+ftq0+wKgBQggkCNSBdBuaazsJIDJefXCv29bnuF3XV4A8+u6IIAWAgHUgNkVyOPx0J8/OUkOp4u+tzYr5pcXA5EDBBDIAQHUBz0FkH9dG44A8tf+66en/O7HC6C0HBBAc4EAasDsCrTnZIswLqO0+ZIp9wRADyCAQI5IEsD+EfsKYH5dF9296jBlne1QfQ77WW597ZDiPq0C+NJnoQsge8P1qcFZIyCAEEBNmFmBmrqHadbSdHI4XbT+SI3h9wNATyCAQI5IFUA7TrwLFbnXtNJ9WgUwMavW75rBBLB3aIzyajoNnzgIAYQAasKsCjQx6aafJR0jh9ObHFPvZYYAMBoIIJAjkgRwIAYFcHqYAni6+RK9nXmORid8EwDZ/u0SAXyDW1UklFfYWoEAQgA1YVYFSphaSWP2snTR+roARAq/21pEDqeLVrgqrS4KsBEQQOswUgAD3U8qgKtTIYBWAQHUgBkVqKSxR3gM/+XpNsPuA4CRDI9NUF5NJ41Puq0uCrARrNOv7RiwuihBiXUBDJQI+obFqRDACAQCqAGjK9DAyDh9+40j5HC6aN7OUkPuAQAAVtHeN0JnWiJjQlusCuCmnDq6Y0UmNXYPKV4LAhiZQAA1YHQFmrezlBxOF31nzREaGBk35B4AAACCE6sCSORNQRYICGBkAgHUgJEVaF9pqzALq6SxR/frAwAAUE8sCeDvPzhBDqeLFqWUqboWBDAygQBqwKgK1Ng9RLOXeVO+JGSc0/XaAAAAQidaBTBeRgCHxyYoq7pDNIs3EBDAyAQCqAEjKtCJhh6KX55BDqeLfpZ0jCYwaB4AACxn0u0RJCUa1jcPJIChokUA3ztcAwG0CAhgGBi1FvDu4mb6+sKD5HC66Mfv5tluwXEAAIhleofGqHtw1Opi6IJdBHCQW3oOAmguEEAN6FWBJt0eWuGqFP4HeGFHCQ2PYZ1fAAAAxqCnAM5YpF4Aj9d3K+6DAJoLBFADelSggZFxenpbkVD512WcM3wJHAAAALGN2QJY0dZH+xVy2UIArQECqAGtFaipe5h+sC6HHE4XzViUqvg/BwAAAKAnZgugmrJAAM0FAqgBLRWooK6bbn3tEDmcLrprZWbEJEMFAAAQ+UAAIYAQQA2EW4E+LWqiry3wTvZ4ZP1RTPYAAABgKhBACCAEUAOhVqCJSTct+7JCqOh/+fRUVKQTAAAAEFlAACGAEEANhFKB+i6P05NbjguVfP2RmqDL6wAAAABGAAGEAEIANaC2AtV3DtL9b2WTw+miGxenUVr5BZNKCAAAAPgDAYQAQgA1oKYCHa3pom9MLet296rDVNHWZ2IJAQAAAH/0FMDrIYARCQRQA8Eq0EcFDXTd1GSPnyYdo44BTPYAAABgPRBACCAEUANKFWh80k2LUsqECj1vZykmewAAALANEEAIIARQA3IV6NLwGP3m/UJyOF00fb6LNubUYbIHAAAAWwEBhABCADUgrUC1HQN079oscjhddNOSNMqovGhxCQEAAAB/mHDd/joEMFaJeQFMSEigm266iWbOnEl//etfQ3pax1eg7LMdNHupd7LHt984QtXtsVupAAAA2BsIIAQwpgWws7OTrrvuOhoZGaHJyUm65557qKCgQPX5rAKtTz9DX53vrbxzNxZQ9+CogaUGAAAAtAEBhADGvABee+21dOnSJRoZGaE777yT6urqVJ/PKtD/e2U3OZwu+ufnp2lswm1giQEAAADtQAAhgLYWwNzcXJozZw5dc801FBcXRykpKX7HJCUl0fTp0+nqq6+m+Ph4ysvLC+ke7733Hv37v/87/ed//ictWLAgpHNZBXLM203JefWY7AEAACAi0FUAF0IAIxFbC2BqaiotWrSI9uzZIyuAO3fupCuvvJKSk5OpqqqKXn75ZZo2bRo1NTUJx8THx9OsWbP8oq2tjXp7e+mhhx6inp4eunz58v9v796Do6rvPo6f7CabG0lKULKBQCQtIaEYbEYpqZAICohSqLQgDFDaGUFECpY6MRQRcbhEptBSQaQ0Oi1FLpXg8GgAiQWcQpRqMgaecA1IQyiFpzRcVEJDPs8fzJ7mJBuM7OZysu/XzM7A7tk9v/2eb87vk7N7TpSVlaW9e/c2eXyeBvqfj5t+1BAAgNZGACQAtukAWJe3ANivXz9NmzbNcl9KSopycnKa9JqbN2/W9OnTzf8vXbpUL7/8cpPHRAMBAOyIAMj8bdsAWF1dLafTqfz8fMtyM2fOVGZmZpNes6ioSPfcc495Esgjjzyit99+u9Hlr127pkuXLpm3ioqKgG8gAID9EAAJgLYNgJWVlTIMQ/v27bMst2jRIiUnJzf5dX/5y18qJSVFvXv3/srLwMyfP1+GYTS4BXIDAQDshwBIALR9AKx/2ZaFCxeqV69ezTIGjgACANoDAiAB0LYB0B8fAfuKBgIA2BEBkPnbtgFQunkSyFNPPWW5LzU1tckngdyulStXKjU1VcnJyQHfQAAA+yEAEgDbdAC8cuWKSkpKVFJSIsMwtHz5cpWUlJiXefFcBiYvL09lZWV65plnFBkZqc8++6xFxkcDAQDsyBO40l/yPQB+65fvEgBtqE0HwN27d3s96WLy5MnmMqtWrVJiYqJcLpfS09O/1nX8fEUDAQDsiADI/N2mA2BbxUfAAAA78+dHwARAeyIA+oAGAgDYEQGQ+ZsA6AMaCABgRwRA5m8CoA9oIACAHREAmb8JgLeB7wACAOyMAEgAJAD6gAYCANgRAZD5mwDoAxoIAGBH/gyA35xDALQjAqAPaCAAgB0RAJm/CYA+oIEAAHZEAGT+JgDeBk4CAQDYGQGQAEgA9AENBACwIwIg8zcB0Ac0EADAjgiAzN8EQB/QQAAAOyIAMn8TAH1AAwEA7IgAyPxNALwNnASmbCxiAAAVuElEQVQCALAzfwbACWs/VOJz7+jehbt8GgsBsGURAH1AAwEA7Oi/AfD2Qltd/3flmpa9d1R//9fnPo2FANiyCIA+oIEAAHbkzwDor7EQAFsWAdAHNBAAwI4IgMzfBEAf0EAAADsiADJ/EwB9QAMBAOyIAMj8TQD0AQ0EALAjAiDzNwHwNnAZGACAnREACYAEQB/QQAAAOyIAMn8TAH1AAwEA7IgAyPxNAPQBDQQAsCMCIPM3AdAHNBAAwI7aUgCc+Pubf0puxpvFLbZO5m8CoE9oIACAHbWlAHjpy+t6u+SMrl77T8utk/mbAOgLGggAYEdtKQC2BuZvAqBPaCAAgB0RAJm/CYC3gesAAgDsjABIACQA+oAGAgDYkScA3ruQABioCIA+oIEAAHZEAGT+JgD6gAYCANgRAZD5mwDoAxoIAGBHBEDmbwKgD2ggAIAdEQCZvwmAPqCBAAB2RABk/iYA+oAGAgDYEQGQ+ZsA6AMaCABgRwRA5m8CoA9oIACAHREAmb8JgD6ggQAAdkQAZP4mAPqABgIA2BEBkPmbAHgb+FvAAAA7IwASAAmAPqCBAAB2RABk/iYA+oAGAgDYEQGQ+ZsA6AMaCABgRw//5gMlPveOFmz739YeSqtg/iYA+oQGAgDY0b8/r9b/fFqpL6/XtPZQWgXzNwHQJzQQAAD2w/xNAPQJDQQAgP0wfxMAfUIDAQBgP8zfBECf0EAAANgP8zcB0Cc0EAAA9sP8TQD0CQ0EAID9MH8TAH1CAwEAYD/M3wRAn9BAAADYD/M3AdAnNBAAAPbD/E0A9AkNBACA/TB/EwB9QgMBAGA/zN8EQJ/QQAAA2A/zNwHQJzQQAAD2w/xNAPQJDQQAgP0wfxMAfVJVVSXDMFRRUaFLly5x48aNGzdu3Gxwq6iokGEYqqqqau0o0WoIgD7wNBA3bty4cePGzX63ioqK1o4SrYYA6IMbN26ooqJCPXv2bPBbRXMeFUxOTm72537Vcrd63NtjTbmv7v9boo6+1JI6tmwdfallU++/VW3beh2/znObu45fVVv2kfxst4U6VlVVqaKiQjdu3GjtKNFqCIB+kJqaav770qXm/15B3fU113O/arlbPe7tsabc19J1bGxc/nwedfTf8263lk29/1a1bet1/DrPbe46eruPfeRXP9YW69jYuPz5vNauYyAjAPrBypUrzX+3xA9l3fU113O/arlbPe7tsabc19J1bGxc/nwedfTf8263lk29/1a1bet1/DrPbe46eruPfeRXP9YW69jYuPz5vNauYyAjAPpZS/1QtnfU0T+oo39QR/+hlv5BHeErAqCfXbt2TfPnz9e1a9daeyi2Rh39gzr6B3X0H2rpH9QRviIAAgAABBgCIAAAQIAhAAIAAAQYAiAAAECAIQACAAAEmHYRAPfu3asRI0YoPj5ehmFo69atlsdra2s1f/58xcfHKywsTFlZWTp06JBlmYsXL2rixImKjo5WdHS0Jk6cqH//+9+WZUpLS5WZmamwsDB16dJFCxYsUG1trWWZt956S6mpqXK5XEpNTVV+fv4tx3L//fdr4sSJ6t69u8LCwpSRkaHCwkJzLB06dFBSUpLcbrfCw8M1bNgwHTt2zPKaJ06c0MiRIxUWFqagoCA5nU4NHTrU8iduPvnkEz300EOKiYlRbGyspkyZoitXrlhep7CwUBkZGerQoYPcbreys7P1n//855a1P3HihH7wgx/ojjvuUFRUlMaMGaNz585ZlvHXujdt2qS+ffsqPDxc3bt319KlSxuMZ+XKlUpJSVFYWJiSk5P1hz/8wfL49evXtWDBAiUlJSk0NFRpaWnavn27ZZnLly9r1qxZlm1y4MAByzLnzp3T5MmTFR8ff8vt0lhtPD17xx13yDAMRUREWGpTt09cLpeio6MVHh5uqU1L9aw3e/bsUXp6ukJDQ9WjRw+tXr36K5/TUtrS/qC+06dPa8SIEYqIiFCnTp30s5/9TNXV1f55482spepa37Vr1zRjxgx16tRJERER+v73v9/u/nyXP2rrzapVq3TXXXcpNDRU6enp+uCDD5rrLcCG2kUALCgo0Ny5c7VlyxavPzy5ubmKiorSli1bdPDgQT3++OOKj4/X5cuXzWUefvhh9enTR/v379f+/fvVp08fjRgxwnz80qVLiouL07hx43Tw4EFt2bJFUVFR+tWvfmUus3//fjmdTi1evFiHDx/W4sWLFRwcrA8//LDRsXTr1k3BwcHavn27jh8/rvnz5ys4OFi9evXSvn379O1vf1sREREaMGCAjhw5oqlTp6p79+66evWqJOnq1atKSkpSjx491LlzZ/3ud7/TAw88oKioKKWlpammpkaVlZXq2LGjpk2bpiNHjujAgQP63ve+px/+8IfmuD799FO5XC4tWLBAx48f1549e5SSkqJf/OIXjdbds+7HHntMpaWlKi0t1ahRo3TfffeZf17HX+suKChQcHCwVq9erfLycr3zzjtyu9165ZVXzGVeffVVRUVFaePGjSovL9eGDRvUoUMHbdu2zVwmOztbXbp00bvvvqvy8nK9+uqrCgsLU3FxsbnM2LFj1bt3b+3du9fcJtHR0Tpz5oykmzvj/v37a+DAgTpw4MAtt0tjtSkoKNDMmTMVGRkpwzC0cuVKS208fbJs2TIFBwerT58+6ty5swoKCszatFTP1nfy5ElFRERo1qxZKisr09q1axUSEqK33nqr0ee0pLayP6ivpqZGffr00aBBg1RcXKxdu3apS5cumjFjhv+L0Axaoq7eTJs2TV27dtWuXbtUXFysQYMGqW/fvqqpqWmW99ka/FHb+jZu3KiQkBCtXbtWZWVlmjVrliIjI3X69OnmfjuwiXYRAOuq/8NTW1srt9ut3Nxc875r164pJiZGr732miSprKxMhmFYJr2ioiIZhqEjR45IuhkuYmJiLNdcWrJkibp06WL+1j927Fg9/PDDlvEMGzZM48aN8zqWL774Qk6nUxEREQ3G8pOf/ERHjx6VYRhav369OZaamhrFxsZq7dq1kqSdO3fK4XAoODhYGzdulHTzt2zDMBQUFKQdO3ZozZo16ty5s+VvHpaUlMgwDB0/flySNGfOHN17772WsW/dulVhYWGN7mQ8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\" width=\"640\">"
+ ],
+ "text/plain": [
+ "<IPython.core.display.HTML object>"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "ys = scipy.fftpack.fft(data[:,0])\n",
+ "ys = 2.0/len(data) * np.abs(ys[:len(data)//2])\n",
+ "s = 1\n",
+ "\n",
+ "ys = np.convolve(ys, np.ones((s,))/s, mode='valid')\n",
+ "\n",
+ "xs = np.linspace(0, 1.0/2.0, len(data)/2)\n",
+ "\n",
+ "ys *= 2*np.pi*xs\n",
+ "#xs = np.linspace(len(data)/2, 1, len(data)/2)\n",
+ "\n",
+ "fig, ax = plt.subplots()\n",
+ "ax.loglog(xs[s//2:-s//2+1 if s > 1 else None], ys)\n",
+ "ax.xaxis.set_major_formatter(plt.FuncFormatter(lambda x, _pos: 1/x))\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 9,
+ "metadata": {},
+ "outputs": [
+ {
+ "name": "stderr",
+ "output_type": "stream",
+ "text": [
+ "/usr/lib/python3.7/site-packages/ipykernel_launcher.py:7: DeprecationWarning: object of type <class 'float'> cannot be safely interpreted as an integer.\n",
+ " import sys\n"
+ ]
+ },
+ {
+ "data": {
+ "application/javascript": [
+ "/* Put everything inside the global mpl namespace */\n",
+ "window.mpl = {};\n",
+ "\n",
+ "\n",
+ "mpl.get_websocket_type = function() {\n",
+ " if (typeof(WebSocket) !== 'undefined') {\n",
+ " return WebSocket;\n",
+ " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
+ " return MozWebSocket;\n",
+ " } else {\n",
+ " alert('Your browser does not have WebSocket support.' +\n",
+ " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
+ " 'Firefox 4 and 5 are also supported but you ' +\n",
+ " 'have to enable WebSockets in about:config.');\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
+ " this.id = figure_id;\n",
+ "\n",
+ " this.ws = websocket;\n",
+ "\n",
+ " this.supports_binary = (this.ws.binaryType != undefined);\n",
+ "\n",
+ " if (!this.supports_binary) {\n",
+ " var warnings = document.getElementById(\"mpl-warnings\");\n",
+ " if (warnings) {\n",
+ " warnings.style.display = 'block';\n",
+ " warnings.textContent = (\n",
+ " \"This browser does not support binary websocket messages. \" +\n",
+ " \"Performance may be slow.\");\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " this.imageObj = new Image();\n",
+ "\n",
+ " this.context = undefined;\n",
+ " this.message = undefined;\n",
+ " this.canvas = undefined;\n",
+ " this.rubberband_canvas = undefined;\n",
+ " this.rubberband_context = undefined;\n",
+ " this.format_dropdown = undefined;\n",
+ "\n",
+ " this.image_mode = 'full';\n",
+ "\n",
+ " this.root = $('<div/>');\n",
+ " this._root_extra_style(this.root)\n",
+ " this.root.attr('style', 'display: inline-block');\n",
+ "\n",
+ " $(parent_element).append(this.root);\n",
+ "\n",
+ " this._init_header(this);\n",
+ " this._init_canvas(this);\n",
+ " this._init_toolbar(this);\n",
+ "\n",
+ " var fig = this;\n",
+ "\n",
+ " this.waiting = false;\n",
+ "\n",
+ " this.ws.onopen = function () {\n",
+ " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
+ " fig.send_message(\"send_image_mode\", {});\n",
+ " if (mpl.ratio != 1) {\n",
+ " fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
+ " }\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " }\n",
+ "\n",
+ " this.imageObj.onload = function() {\n",
+ " if (fig.image_mode == 'full') {\n",
+ " // Full images could contain transparency (where diff images\n",
+ " // almost always do), so we need to clear the canvas so that\n",
+ " // there is no ghosting.\n",
+ " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
+ " }\n",
+ " fig.context.drawImage(fig.imageObj, 0, 0);\n",
+ " };\n",
+ "\n",
+ " this.imageObj.onunload = function() {\n",
+ " 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,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\" width=\"640\">"
+ ],
+ "text/plain": [
+ "<IPython.core.display.HTML object>"
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ }
+ ],
+ "source": [
+ "ys = scipy.fftpack.fft(data[:,0])\n",
+ "ys = 2.0/len(data) * np.abs(ys[:len(data)//2])\n",
+ "s = 30\n",
+ "\n",
+ "ys = np.convolve(ys, np.ones((s,))/s, mode='valid')\n",
+ "\n",
+ "xs = np.linspace(0, 1.0/2.0, len(data)/2)\n",
+ "\n",
+ "ys *= 2*np.pi*xs[s//2:-s//2+1]\n",
+ "\n",
+ "#xs = np.linspace(len(data)/2, 1, len(data)/2)\n",
+ "\n",
+ "fig, ax = plt.subplots()\n",
+ "ax.loglog(xs[s//2:-s//2+1], ys)\n",
+ "ax.xaxis.set_major_formatter(plt.FuncFormatter(lambda x, _pos: 1/x))\n",
+ "plt.show()"
+ ]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": 10,
+ "metadata": {},
+ "outputs": [
+ {
+ "data": {
+ "text/plain": [
+ "15.923566878980893"
+ ]
+ },
+ "execution_count": 10,
+ "metadata": {},
+ "output_type": "execute_result"
+ }
+ ],
+ "source": [
+ "1/0.0628"
+ ]
+ }
+ ],
+ "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.5"
+ }
+ },
+ "nbformat": 4,
+ "nbformat_minor": 2
+}