Skip to content

Instantly share code, notes, and snippets.

@marcusmueller
Created October 25, 2020 08:13
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marcusmueller/6a01705caf7f8e56ec496cc6c553b93f to your computer and use it in GitHub Desktop.
Save marcusmueller/6a01705caf7f8e56ec496cc6c553b93f to your computer and use it in GitHub Desktop.
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Analyze IIR filters"
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"# first, import stuff\n",
"import numpy\n",
"from scipy import signal\n",
"# We want our plots interactive\n",
"%matplotlib notebook\n",
"from matplotlib import pyplot\n",
"# because of nicer colors and lines, at least try:\n",
"try:\n",
" import seaborn\n",
"except:\n",
" # but don't fail if you don't find seaborn\n",
" pass"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let's design a moving average (MA) and an exponentially weighted moving average (EWMA)"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"length_MA = 16 # length of the averaged part\n",
"a_MA = [1] # no recursive path, i.e. only previous _input_ matters\n",
"b_MA = [1/length_MA] * length_MA # by using a 1/length as the coefficient,\n",
" # the total amplitude response still stays 1 at f = 0\n",
"\n",
"weight_EWMA = 0.25\n",
"a_EWMA = [1, weight_EWMA-1] # we feed back the last output with, slightly \"attenuated\"\n",
"b_EWMA = [weight_EWMA] # and we incorporate the new input sample, but only with a low weight"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Getting their frequency responses is easy enough:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"omega_MA, H_MA = signal.freqz(b_MA, a_MA)\n",
"omega_EWMA, H_EWMA = signal.freqz(b_EWMA, a_EWMA)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Plotting this isn't much harder'"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"application/javascript": [
"/* Put everything inside the global mpl namespace */\n",
"window.mpl = {};\n",
"\n",
"\n",
"mpl.get_websocket_type = function() {\n",
" if (typeof(WebSocket) !== 'undefined') {\n",
" return WebSocket;\n",
" } else if (typeof(MozWebSocket) !== 'undefined') {\n",
" return MozWebSocket;\n",
" } else {\n",
" alert('Your browser does not have WebSocket support. ' +\n",
" 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
" 'Firefox 4 and 5 are also supported but you ' +\n",
" 'have to enable WebSockets in about:config.');\n",
" };\n",
"}\n",
"\n",
"mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
" this.id = figure_id;\n",
"\n",
" this.ws = websocket;\n",
"\n",
" this.supports_binary = (this.ws.binaryType != undefined);\n",
"\n",
" if (!this.supports_binary) {\n",
" var warnings = document.getElementById(\"mpl-warnings\");\n",
" if (warnings) {\n",
" warnings.style.display = 'block';\n",
" warnings.textContent = (\n",
" \"This browser does not support binary websocket messages. \" +\n",
" \"Performance may be slow.\");\n",
" }\n",
" }\n",
"\n",
" this.imageObj = new Image();\n",
"\n",
" this.context = undefined;\n",
" this.message = undefined;\n",
" this.canvas = undefined;\n",
" this.rubberband_canvas = undefined;\n",
" this.rubberband_context = undefined;\n",
" this.format_dropdown = undefined;\n",
"\n",
" this.image_mode = 'full';\n",
"\n",
" this.root = $('<div/>');\n",
" this._root_extra_style(this.root)\n",
" this.root.attr('style', 'display: inline-block');\n",
"\n",
" $(parent_element).append(this.root);\n",
"\n",
" this._init_header(this);\n",
" this._init_canvas(this);\n",
" this._init_toolbar(this);\n",
"\n",
" var fig = this;\n",
"\n",
" this.waiting = false;\n",
"\n",
" this.ws.onopen = function () {\n",
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
" fig.send_message(\"send_image_mode\", {});\n",
" if (mpl.ratio != 1) {\n",
" fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
" }\n",
" fig.send_message(\"refresh\", {});\n",
" }\n",
"\n",
" this.imageObj.onload = function() {\n",
" if (fig.image_mode == 'full') {\n",
" // Full images could contain transparency (where diff images\n",
" // almost always do), so we need to clear the canvas so that\n",
" // there is no ghosting.\n",
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
" }\n",
" fig.context.drawImage(fig.imageObj, 0, 0);\n",
" };\n",
"\n",
" this.imageObj.onunload = function() {\n",
" 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 / mpl.ratio, fig.canvas.height / mpl.ratio);\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",
" // select the cell after this one\n",
" var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
" IPython.notebook.select(index + 1);\n",
" }\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" fig.ondownload(fig, null);\n",
"}\n",
"\n",
"\n",
"mpl.find_output_cell = function(html_output) {\n",
" // Return the cell and output element which can be found *uniquely* in the notebook.\n",
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
" // IPython event is triggered only after the cells have been serialised, which for\n",
" // our purposes (turning an active figure into a static one), is too late.\n",
" var cells = IPython.notebook.get_cells();\n",
" var ncells = cells.length;\n",
" for (var i=0; i<ncells; i++) {\n",
" var cell = cells[i];\n",
" if (cell.cell_type === 'code'){\n",
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
" var data = cell.output_area.outputs[j];\n",
" if (data.data) {\n",
" // IPython >= 3 moved mimebundle to data attribute of output\n",
" data = data.data;\n",
" }\n",
" if (data['text/html'] == html_output) {\n",
" return [cell, data, j];\n",
" }\n",
" }\n",
" }\n",
" }\n",
"}\n",
"\n",
"// Register the function which deals with the matplotlib target/channel.\n",
"// The kernel may be null if the page has been refreshed.\n",
"if (IPython.notebook.kernel != null) {\n",
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
"}\n"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<img src=\"data:image/png;base64,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TGFy2AC8vc+9eemll/D444/7+tKC0mCT0DmW1RlqAMKxPDBJkvCXv/wF3/zmN1FWVjaoz3BMe28o97k3HNPeeeKJJ/Daa6/1+mccx6RgABLElPKwkZGRKC4uxttvv42RI0eiqqoKABAaGorJkyeL9yvl8WbOnIni4mJERkayPN4geHuf16xZg8OHD6OsrAyFhYUIDQ1FSEgIDh48qNdfwfBaW1uRm5uL3NxchISEYPXq1cjNzRWljjmWfcPb+8yxPDRTp07Fl7/8ZSQnJ/co9drR0SHewzGt3lDuM8e0d2bNmoXU1FRcvHgR+fn5mD17Nv71X/8VcXFxADiOqW8MQILcxo0bYTKZcOutt2LChAk9Eulee+01TJo0qcf7k5OTce+99+LWW2/FqFGj2CBokLy5z8uWLcMdd9yBf/u3f8NXvvIVPPLII/0m7VHfzcGUp2wcy77h7X3mWB6a3u5xSEgIduzYId7DMa3eUO4zx7R3/vjHP4rffV/72tfw5JNPiuAD4DimvjEAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizTAAISIiIiIizfx/CD6El1U8dbYAAAAASUVORK5CYII=\" width=\"800\">"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"#prepare plotting\n",
"fig = pyplot.figure(figsize=(8,6), dpi=100)\n",
"pyplot.plot(omega_MA, numpy.abs(H_MA), label=\"MA amplitude response\")\n",
"pyplot.plot(omega_EWMA, numpy.abs(H_EWMA), label=\"EWMA amplitude response\")\n",
"pyplot.show()\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"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.9"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment