{ "cells": [ { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": 101, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "%matplotlib nbagg" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\n", "
\n", "# [Physics 411](http://jklymak.github.io/Phy411/) Time Series Analysis\n", "*Jody Klymak*\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Week 5: Periodigram and Leakage" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "
\n", "\"Turbulence\n", "
\n", "\n", "We saw previously that the discrete power spectral estimate is quite imprecise, with an uncertainty of a factor of almost 40, if the data is normally distributed. This is unacceptably imprecise if you are trying to find a small-ish peak. \n", "\n", "As with any other time when your data is too noisy, the solution is to average the data in some ways. There are two ways to do this that are commonly used. 1) is to take your raw spectrum and smooth in frequency or 2) to take a number of spectra from adjoining windows of data and average the spectra. (2) is called the **periodigram**, and is the focus of this lesson.\n", "\n", "There are also issues in the finite power spectrum estimate relating to the periodicity of the data. The assumption inherent in the power spectrum is that the signal is periodic with period $T$. This is usually not the case, and if $T$ is small, the assumption can lead to artifacts in the spectrum. This is called **leakage**, and can be suppressed by **windowing**\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Frequency Smoothing" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "An obvious, and easy, method to smooth the spectrum, is to simply smooth the spectrum in frequency. We do this with a finite convolution, or a boxcar filter:\n", "\n", "\\begin{equation}\n", " \\tilde{G}_{xx}\\left(f_i\\right) = \\frac{1}{2W+1}\\sum_{k=i-W}^{i+W} G_{xx}\\left(f_k\\right) \n", "\\end{equation}\n", "\n", "where here we have specified the boxcar to have width $2W+1$ frequency bins. \n", "\n", "To see how this works, we create a Gaussian random noise time series and add a sine wave to it:" ] }, { "cell_type": "code", "execution_count": 36, "metadata": { "collapsed": false }, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof(MozWebSocket) !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert('Your browser does not have WebSocket support.' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.');\n", " };\n", "}\n", "\n", "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = (this.ws.binaryType != undefined);\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById(\"mpl-warnings\");\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent = (\n", " \"This browser does not support binary websocket messages. \" +\n", " \"Performance may be slow.\");\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = $('
');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " fig.waiting = false;\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " this.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '
');\n", " var titletext = $(\n", " '
');\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 = $('
');\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 = $('');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width);\n", " canvas.attr('height', height);\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('
')\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 = $('');\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 = $('');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "\n", " // Add the close button to the window.\n", " var buttongrp = $('
');\n", " var button = $('');\n", " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", " button.mouseover('Close figure', toolbar_mouse_event);\n", " buttongrp.append(button);\n", " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", " titlebar.prepend(buttongrp);\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= 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": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "" ] }, "execution_count": 37, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fig,ax=plt.subplots(1,1)\n", "\n", "f = np.arange(N/2)/T\n", "fN = 1./2./dt\n", "# get the theory\n", "Gtheory = 1./fN+0.*f\n", "ind = np.where(f>=f0)[0][0] # get the index of f0\n", "Gtheory[ind]+=amp**2/2.*T\n", "# get the spectral estimate:\n", "X = dt*np.fft.fft(x)\n", "G = (2./T)*np.real(np.conj(X[:N/2])*X[:N/2])\n", "# plot\n", "ax.loglog(f[1:],Gtheory[1:],color='r',label='Expected')\n", "ax.loglog(f[1:],G[1:],label='Random')\n", "ax.legend(loc=3)\n", "# get the error bars:\n", "inter = stats.chi2.interval(0.95,df=2)\n", "ax.fill_between(f[1:],2.*G[1:]/inter[1],2.*G[1:]/inter[0],alpha=0.5,\n", " linewidth=0.0,edgecolor=None,color=None,facecolor='b')\n", "ax.set_xlabel('f [Hz]');ax.set_ylabel('$G_{xx}(f)$')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Hopefully its clear from the above that the peak barely shows up above the variance of the spectral estimate. Certainly it is not significant with 95% confidence. \n", "\n", "So we see if smoothing in frequency space can help improve the spectrum:" ] }, { "cell_type": "code", "execution_count": 38, "metadata": { "collapsed": false }, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof(MozWebSocket) !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert('Your browser does not have WebSocket support.' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.');\n", " };\n", "}\n", "\n", "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = (this.ws.binaryType != undefined);\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById(\"mpl-warnings\");\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent = (\n", " \"This browser does not support binary websocket messages. \" +\n", " \"Performance may be slow.\");\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = $('
');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " fig.waiting = false;\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " this.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '
');\n", " var titletext = $(\n", " '
');\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 = $('
');\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 = $('');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width);\n", " canvas.attr('height', height);\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('
')\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 = $('');\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 = $('');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "\n", " // Add the close button to the window.\n", " var buttongrp = $('
');\n", " var button = $('');\n", " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", " button.mouseover('Close figure', toolbar_mouse_event);\n", " buttongrp.append(button);\n", " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", " titlebar.prepend(buttongrp);\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= 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": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "name": "stdout", "output_type": "stream", "text": [ "10.0\n" ] } ], "source": [ "N= 2560\n", "T = 2048.\n", "dt = T/N\n", "\n", "fig,ax=plt.subplots(1,1)\n", "t=np.arange(0,T,dt)\n", "f0=1./30.; om = 2*np.pi*f0; amp=0.5\n", "x=np.random.randn(N)+amp*np.cos(om*t)\n", "ax.plot(t,x,'k')\n", "NFFT=256\n", "# there is a better way to do this, but lets brute force it:\n", "nblock = np.floor(N/NFFT)\n", "print nblock\n", "for ind in range(int(nblock)):\n", " inds =range(ind*NFFT,(ind+1)*NFFT)\n", " tblock=t[inds]\n", " xblock=x[inds]\n", " ax.plot(tblock,xblock)\n", "ax.set_xlabel('t [s]');ax.set_ylabel('X [V]')\n", "plt.axis('tight')\n", "fig.tight_layout()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here we have coloured our 10 blocks of data that we will take independent periodigrams of. (Note that we cannot average the data and take the periodigram and expect to get anything sensible).\n", "\n", "Then we compute the power spectra for the 10 blocks and plot. We will also plot the raw periodigram:" ] }, { "cell_type": "code", "execution_count": 40, "metadata": { "collapsed": false }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "/Users/jklymak/anaconda/lib/python2.7/site-packages/ipykernel/__main__.py:1: DeprecationWarning: using a non-integer number instead of an integer will result in an error in the future\n", " if __name__ == '__main__':\n" ] }, { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof(MozWebSocket) !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert('Your browser does not have WebSocket support.' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.');\n", " };\n", "}\n", "\n", "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = (this.ws.binaryType != undefined);\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById(\"mpl-warnings\");\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent = (\n", " \"This browser does not support binary websocket messages. \" +\n", " \"Performance may be slow.\");\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = $('
');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " fig.waiting = false;\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " this.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '
');\n", " var titletext = $(\n", " '
');\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 = $('
');\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 = $('');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width);\n", " canvas.attr('height', height);\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('
')\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 = $('');\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 = $('');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "\n", " // Add the close button to the window.\n", " var buttongrp = $('
');\n", " var button = $('');\n", " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", " button.mouseover('Close figure', toolbar_mouse_event);\n", " buttongrp.append(button);\n", " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", " titlebar.prepend(buttongrp);\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= 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": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "" ] }, "execution_count": 43, "metadata": {}, "output_type": "execute_result" } ], "source": [ "# make the theory spectrum:\n", "fN=1/2./dt\n", "Gtheory = 1./fN+0.*f\n", "ind = np.where(f>=f0)[0][0]\n", "Gtheory[ind]+=amp**2/2.*T\n", "\n", "fig,ax=plt.subplots(1,1)\n", "ax.loglog(f,Graw,color='0.5')\n", "ax.loglog(f,Gtheory,'r')\n", "# get error bars:\n", "dof=2*nblock\n", "inter = stats.chi2.interval(0.95,df=dof)\n", "Gblockm=np.mean(Gblock,axis=0)\n", "ax.fill_between(fblock[1:],dof*Gblockm[1:]/inter[1],dof*Gblockm[1:]/inter[0],alpha=0.45,\n", " linewidth=0.0,edgecolor=None,color=None,facecolor='g',zorder=3)\n", "ax.loglog(fblock,Gblockm,'k',linewidth=2,zorder=10)\n", "ax.set_xlabel('f [Hz]');ax.set_ylabel('$G_{xx}(f)\\ \\ [V^2\\,Hz^{-1}$')\n", "ax.set_title('%d blocks = %d degrees of freedom'%(nblock,2*nblock))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So, some things to note: \n", " \n", " 1. The block-spectra do not extend to as low frequencies as the raw periodigram. This should not be surprising because the raw periodigram is taking a longer data set than the individual blocks. Indeed $f_1=\\delta f = 1/T$, so the longer $T$ the lower a frequency can be resolved.\n", " 2. The resolution of the bloc spectra is also less than the raw. i.e. we get the same tradeoff as smoothing in frequency - we lose frequency resolution, again because $\\delta f = 1/T$. \n", " \n", "So, is this better than frequency smoothing? The question depends on what you are trying to do and what your signal is like. If you need the low frequency information, then the block-average method is obviously problematic. However, as we saw above, you also need to be careful how you \"average\" those lower few bins. Do they give the same result?" ] }, { "cell_type": "code", "execution_count": 49, "metadata": { "collapsed": false }, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof(MozWebSocket) !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert('Your browser does not have WebSocket support.' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.');\n", " };\n", "}\n", "\n", "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = (this.ws.binaryType != undefined);\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById(\"mpl-warnings\");\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent = (\n", " \"This browser does not support binary websocket messages. \" +\n", " \"Performance may be slow.\");\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = $('
');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " fig.waiting = false;\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " this.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '
');\n", " var titletext = $(\n", " '
');\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 = $('
');\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 = $('');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width);\n", " canvas.attr('height', height);\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('
')\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 = $('');\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 = $('');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "\n", " // Add the close button to the window.\n", " var buttongrp = $('
');\n", " var button = $('');\n", " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", " button.mouseover('Close figure', toolbar_mouse_event);\n", " buttongrp.append(button);\n", " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", " titlebar.prepend(buttongrp);\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= 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": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "" ] }, "execution_count": 53, "metadata": {}, "output_type": "execute_result" } ], "source": [ "N= 128; T = 2048.; dt = T/N\n", "np.random.seed(seed=456)\n", "x=np.cumsum(np.random.randn(N)*dt)\n", "t = np.arange(0,T,dt)\n", "tt=[]; xx=[]\n", "for ind in range(4):\n", " tt=np.hstack((tt,t+ind*T))\n", " xx=np.hstack((xx,x))\n", "fig,ax=plt.subplots(1,1)\n", "ax.plot(tt,xx,'k')\n", "for ind in range(4):\n", " ax.plot(t+ind*T,x);\n", "ax.set_xlabel('t [s]');ax.set_ylabel('x [V]')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "There is a large discontibuity at $t=T=2048 s$. This discontibuity shows up in the spectra. Similarly if we consider a sine wave:" ] }, { "cell_type": "code", "execution_count": 12, "metadata": { "collapsed": false }, "outputs": [ { "data": { "text/plain": [ "" ] }, "execution_count": 12, "metadata": {}, "output_type": "execute_result" }, { "data": { "image/png": "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\nagAAAABJRU5ErkJggg==\n", "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "N= 2049;T = 2048.;dt = T/N;om = 2*np.pi/600.\n", "t = np.arange(0,T,dt);x=np.sin(om*t)\n", "tt=[];xx=[]\n", "for ind in range(3):\n", " tt=np.hstack((tt,t+ind*T))\n", " xx=np.hstack((xx,x))\n", "fig,ax=plt.subplots(1,1)\n", "ax.plot(tt,xx,'k');ax.plot(t,x,'r');ax.plot(t+T,x,'b');ax.plot(t+T*2,x,'g')\n", "ax.set_xlabel('t [s]');ax.set_ylabel('x [V]')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Again the discontiuty at $t=T$ is going to show up in our spectral estimation. \n", "\n", "For the single frequency, lets consider the raw periodigram of the signal. \n", "\n", "*NOTE: below we will define a function to do the raw periodigram steps outlined above.*" ] }, { "cell_type": "code", "execution_count": 54, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def rawperio(x,fs):\n", " dt=1./fs\n", " N = len(x)\n", " T = N*dt\n", " X = dt*np.fft.fft(x)\n", " G = (2./T)*np.real(np.conj(X[:N/2])*X[:N/2])\n", " f= np.arange(N/2)/T\n", " return G[1:],f[1:]" ] }, { "cell_type": "code", "execution_count": 56, "metadata": { "collapsed": false }, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof(MozWebSocket) !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert('Your browser does not have WebSocket support.' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.');\n", " };\n", "}\n", "\n", "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = (this.ws.binaryType != undefined);\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById(\"mpl-warnings\");\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent = (\n", " \"This browser does not support binary websocket messages. \" +\n", " \"Performance may be slow.\");\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = $('
');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " fig.waiting = false;\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " this.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '
');\n", " var titletext = $(\n", " '
');\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 = $('
');\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 = $('');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width);\n", " canvas.attr('height', height);\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('
')\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 = $('');\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 = $('');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "\n", " // Add the close button to the window.\n", " var buttongrp = $('
');\n", " var button = $('');\n", " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", " button.mouseover('Close figure', toolbar_mouse_event);\n", " buttongrp.append(button);\n", " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", " titlebar.prepend(buttongrp);\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= 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": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "" ] }, "execution_count": 57, "metadata": {}, "output_type": "execute_result" } ], "source": [ "f0=1.\n", "fig,ax=plt.subplots(1,1)\n", "f=np.linspace(-20.,20.,100000)\n", "for T in [2,5,10,20]:\n", " thesinc=T*np.sinc((f-f0)*T)**2/2.\n", " df = np.median(np.diff(f))\n", " ax.plot(f,thesinc,label='$T=%d [s]$'%T)\n", "ax.set_xlim([0,2]);ax.set_ylim([0,11]);ax.legend()\n", "ax.set_xlabel('$f\\ [Hz]$');ax.set_ylabel('$S_{xx}(f)\\ \\ [V^2 Hz^{-1}]$')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is the effect of calculating the power spectrum of a finite time series. There is nothing about discretizing the time series in here yet. Note that as $T$ gets larger, the power spectrum more closely approaches a delta function, with the \"sidelobes\" closer to fundamental peak, and the fundamental peak gets much taller. The fundamental peak is $T/2$ high. \n", "\n", "The \"sidelobes\" are the subsidiary peaks on either side of the main peak. These sidelobes are highest at when $\\left|\\sin(\\pi (f-f_0)T)\\right|\\approx 1$, or when \n", "$f-f_0\\approx\\frac{2n+1}{2T}$, *except* for the first time, which is burried in the roll off, so $\\left|n\\right|>0$. The sidelobe amplitudes are approximately \n", "\n", "\\begin{equation}\n", " 2T\\left(\\frac{1 }{\\pi (2n+1)}\\right)^2\n", "\\end{equation}\n", "\n", "or $4/\\left(\\pi (2n+1)\\right)^2$ of the peak height. So the first sidelobe, $n=1$ is $0.045$ of the peak value, or $10\\mathrm{log}_{10}(0.045)=-13.5$ dB. The second side lobe is at $n=2$, or $f-f_0 \\approx \\frac{5}{2T}$ and is $0.016$ of the peak or -18 dB.\n", "\n", "These sidelobes explain the energy that leaks into the frequencies around the peak as shown below:" ] }, { "cell_type": "code", "execution_count": 60, "metadata": { "collapsed": false }, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof(MozWebSocket) !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert('Your browser does not have WebSocket support.' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.');\n", " };\n", "}\n", "\n", "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = (this.ws.binaryType != undefined);\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById(\"mpl-warnings\");\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent = (\n", " \"This browser does not support binary websocket messages. \" +\n", " \"Performance may be slow.\");\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = $('
');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " fig.waiting = false;\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " this.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '
');\n", " var titletext = $(\n", " '
');\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 = $('
');\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 = $('');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width);\n", " canvas.attr('height', height);\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('
')\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 = $('');\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 = $('');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "\n", " // Add the close button to the window.\n", " var buttongrp = $('
');\n", " var button = $('');\n", " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", " button.mouseover('Close figure', toolbar_mouse_event);\n", " buttongrp.append(button);\n", " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", " titlebar.prepend(buttongrp);\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= 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": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "(0.0001, 5000.0)" ] }, "execution_count": 66, "metadata": {}, "output_type": "execute_result" } ], "source": [ "t = np.arange(0,T,dt); \n", "om1 = 2*np.pi*(f[30]+0.3*df)\n", "om2 = 2*np.pi*(f[15]+0.3*df)\n", "x=np.sin(om1*t)+0.005*np.sin(om2*t+0.1)+np.random.randn(len(t))/100.\n", "G,f=rawperio(x,1./dt)\n", "xback=0.*np.sin(om1*t)+0.005*np.sin(om2*t+0.1)+np.random.randn(len(t))/100.\n", "Gg,f=rawperio(xback,1./dt)\n", "df=np.median(np.diff(f))\n", "fig,ax=plt.subplots(1,1)\n", "ax.loglog(f,Gg,label='Periodigram w/o main peak')\n", "ax.loglog(f,G,label='Periodigam')\n", "ax.set_xlabel('f [Hz]');ax.set_ylabel('$G_xx(f)$')\n", "ff = np.logspace(np.log10(f[0]),np.log10(f[-1]),10000)\n", "theory = 0*ff+1./100.**2/f[-1]\n", "ind = np.where(ff>=om1/2./np.pi)[0][0]\n", "theory[ind]=0.5/df\n", "ind = np.where(ff>=om2/2./np.pi)[0][0]\n", "theory[ind]=0.5/df*0.015**2\n", "ax.loglog(ff,theory,label='Theory')\n", "ax.legend(loc=2,fontsize='small')\n", "ax.set_xlabel('f [Hz]');ax.set_ylabel('$G_xx(f)$');ax.set_ylim([1e-4,0.5e4])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The weaker peak is definitely well above the \"noise\" of our process, but is obscured by the sidelobe leakage from the dominant peak in the green curve.\n", "\n", "The solution to this problem is to smooth out the discontibuities at the edge of the spectrum by applying a window that makes the edge of the window go to zero. " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Windows to reduce sidelobe leakage" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "So the solution is to apply a window that reduces the sidelobe leakage. Here we apply the Hanning window:\n", "\n", "\\begin{equation}\n", " w(n)=0.5\\left(1-\\cos \\left(\\frac{2\\pi n}{N-1} \\right) \\right)\n", "\\end{equation}\n", "\n", "where $n=0,1...N-1$, and $N$ is the length of the time series. Before describing it, lets see the effect on the powerspectrum calculated above:" ] }, { "cell_type": "code", "execution_count": 69, "metadata": { "collapsed": false }, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof(MozWebSocket) !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert('Your browser does not have WebSocket support.' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.');\n", " };\n", "}\n", "\n", "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = (this.ws.binaryType != undefined);\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById(\"mpl-warnings\");\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent = (\n", " \"This browser does not support binary websocket messages. \" +\n", " \"Performance may be slow.\");\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = $('
');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " fig.waiting = false;\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " this.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '
');\n", " var titletext = $(\n", " '
');\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 = $('
');\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 = $('');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width);\n", " canvas.attr('height', height);\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('
')\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 = $('');\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 = $('');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "\n", " // Add the close button to the window.\n", " var buttongrp = $('
');\n", " var button = $('');\n", " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", " button.mouseover('Close figure', toolbar_mouse_event);\n", " buttongrp.append(button);\n", " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", " titlebar.prepend(buttongrp);\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= 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": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "def plotit():\n", " # convenience so we can replot below\n", " T=1.;N=2048;dt=T/N;f0=0\n", " fig,axs=plt.subplots(1,2)\n", " ax=axs[0]\n", " tt=np.arange(-0.5*T,1.5*T,dt);xx = 0*tt;xx[(tt>=0)&(tt<=T)]=1.\n", " ax.plot(tt,xx)\n", " wind = 0.5*(1-np.cos(2*np.pi*np.arange(0,N)/(N-1)));wind = wind/np.sqrt(np.sum(wind**2/N))\n", " xx[(tt>=0)&(tt');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " fig.waiting = false;\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " this.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '
');\n", " var titletext = $(\n", " '
');\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 = $('
');\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 = $('');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width);\n", " canvas.attr('height', height);\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('
')\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 = $('');\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 = $('');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "\n", " // Add the close button to the window.\n", " var buttongrp = $('
');\n", " var button = $('');\n", " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", " button.mouseover('Close figure', toolbar_mouse_event);\n", " buttongrp.append(button);\n", " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", " titlebar.prepend(buttongrp);\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= 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": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "" ] }, "execution_count": 85, "metadata": {}, "output_type": "execute_result" } ], "source": [ "N = 2048\n", "Nfft = 256\n", "wind = 0.5*(1-np.cos(2*np.pi*np.arange(0,Nfft)/(Nfft-1)))\n", "x = np.random.randn(N)\n", "xwind = 0.*x\n", "Nblock = 2*N/Nfft-1\n", "fig,ax=plt.subplots(1,1)\n", "ax.plot(x,color='0.5')\n", "vv=0\n", "for ind in range(Nblock):\n", " inds = range(ind*Nfft/2,(ind+2)*Nfft/2)\n", " xwind[inds]=x[inds]*wind\n", " ax.plot(inds,xwind[inds])\n", " vv=vv+sum(xwind[inds]**2)\n", "ax.axis('tight');ax.set_xlabel('t [s]');ax.set_ylabel('X [V]')\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Here the overlapping windows are coloured. The underlying time series in in grey. You can see the tapering to zero at the edges, and the enhancement of variance towards the center. \n", "\n", "Back to our example time series, we can see the effect of some block averaging:" ] }, { "cell_type": "code", "execution_count": 98, "metadata": { "collapsed": false }, "outputs": [ { "data": { "application/javascript": [ "/* Put everything inside the global mpl namespace */\n", "window.mpl = {};\n", "\n", "mpl.get_websocket_type = function() {\n", " if (typeof(WebSocket) !== 'undefined') {\n", " return WebSocket;\n", " } else if (typeof(MozWebSocket) !== 'undefined') {\n", " return MozWebSocket;\n", " } else {\n", " alert('Your browser does not have WebSocket support.' +\n", " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n", " 'Firefox 4 and 5 are also supported but you ' +\n", " 'have to enable WebSockets in about:config.');\n", " };\n", "}\n", "\n", "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n", " this.id = figure_id;\n", "\n", " this.ws = websocket;\n", "\n", " this.supports_binary = (this.ws.binaryType != undefined);\n", "\n", " if (!this.supports_binary) {\n", " var warnings = document.getElementById(\"mpl-warnings\");\n", " if (warnings) {\n", " warnings.style.display = 'block';\n", " warnings.textContent = (\n", " \"This browser does not support binary websocket messages. \" +\n", " \"Performance may be slow.\");\n", " }\n", " }\n", "\n", " this.imageObj = new Image();\n", "\n", " this.context = undefined;\n", " this.message = undefined;\n", " this.canvas = undefined;\n", " this.rubberband_canvas = undefined;\n", " this.rubberband_context = undefined;\n", " this.format_dropdown = undefined;\n", "\n", " this.image_mode = 'full';\n", "\n", " this.root = $('
');\n", " this._root_extra_style(this.root)\n", " this.root.attr('style', 'display: inline-block');\n", "\n", " $(parent_element).append(this.root);\n", "\n", " this._init_header(this);\n", " this._init_canvas(this);\n", " this._init_toolbar(this);\n", "\n", " var fig = this;\n", "\n", " this.waiting = false;\n", "\n", " this.ws.onopen = function () {\n", " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", " fig.send_message(\"send_image_mode\", {});\n", " fig.send_message(\"refresh\", {});\n", " }\n", "\n", " this.imageObj.onload = function() {\n", " if (fig.image_mode == 'full') {\n", " // Full images could contain transparency (where diff images\n", " // almost always do), so we need to clear the canvas so that\n", " // there is no ghosting.\n", " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", " }\n", " fig.context.drawImage(fig.imageObj, 0, 0);\n", " fig.waiting = false;\n", " };\n", "\n", " this.imageObj.onunload = function() {\n", " this.ws.close();\n", " }\n", "\n", " this.ws.onmessage = this._make_on_message_function(this);\n", "\n", " this.ondownload = ondownload;\n", "}\n", "\n", "mpl.figure.prototype._init_header = function() {\n", " var titlebar = $(\n", " '
');\n", " var titletext = $(\n", " '
');\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 = $('
');\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 = $('');\n", " canvas.addClass('mpl-canvas');\n", " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", "\n", " this.canvas = canvas[0];\n", " this.context = canvas[0].getContext(\"2d\");\n", "\n", " var rubberband = $('');\n", " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", "\n", " var pass_mouse_events = true;\n", "\n", " canvas_div.resizable({\n", " start: function(event, ui) {\n", " pass_mouse_events = false;\n", " },\n", " resize: function(event, ui) {\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " stop: function(event, ui) {\n", " pass_mouse_events = true;\n", " fig.request_resize(ui.size.width, ui.size.height);\n", " },\n", " });\n", "\n", " function mouse_event_fn(event) {\n", " if (pass_mouse_events)\n", " return fig.mouse_event(event, event['data']);\n", " }\n", "\n", " rubberband.mousedown('button_press', mouse_event_fn);\n", " rubberband.mouseup('button_release', mouse_event_fn);\n", " // Throttle sequential mouse events to 1 every 20ms.\n", " rubberband.mousemove('motion_notify', mouse_event_fn);\n", "\n", " rubberband.mouseenter('figure_enter', mouse_event_fn);\n", " rubberband.mouseleave('figure_leave', mouse_event_fn);\n", "\n", " canvas_div.on(\"wheel\", function (event) {\n", " event = event.originalEvent;\n", " event['data'] = 'scroll'\n", " if (event.deltaY < 0) {\n", " event.step = 1;\n", " } else {\n", " event.step = -1;\n", " }\n", " mouse_event_fn(event);\n", " });\n", "\n", " canvas_div.append(canvas);\n", " canvas_div.append(rubberband);\n", "\n", " this.rubberband = rubberband;\n", " this.rubberband_canvas = rubberband[0];\n", " this.rubberband_context = rubberband[0].getContext(\"2d\");\n", " this.rubberband_context.strokeStyle = \"#000000\";\n", "\n", " this._resize_canvas = function(width, height) {\n", " // Keep the size of the canvas, canvas container, and rubber band\n", " // canvas in synch.\n", " canvas_div.css('width', width)\n", " canvas_div.css('height', height)\n", "\n", " canvas.attr('width', width);\n", " canvas.attr('height', height);\n", "\n", " rubberband.attr('width', width);\n", " rubberband.attr('height', height);\n", " }\n", "\n", " // Set the figure to an initial 600x600px, this will subsequently be updated\n", " // upon first draw.\n", " this._resize_canvas(600, 600);\n", "\n", " // Disable right mouse context menu.\n", " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n", " return false;\n", " });\n", "\n", " function set_focus () {\n", " canvas.focus();\n", " canvas_div.focus();\n", " }\n", "\n", " window.setTimeout(set_focus, 100);\n", "}\n", "\n", "mpl.figure.prototype._init_toolbar = function() {\n", " var fig = this;\n", "\n", " var nav_element = $('
')\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 = $('');\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 = $('');\n", " nav_element.append(status_bar);\n", " this.message = status_bar[0];\n", "\n", " // Add the close button to the window.\n", " var buttongrp = $('
');\n", " var button = $('');\n", " button.click(function (evt) { fig.handle_close(fig, {}); } );\n", " button.mouseover('Close figure', toolbar_mouse_event);\n", " buttongrp.append(button);\n", " var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", " titlebar.prepend(buttongrp);\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= 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": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "" ], "text/plain": [ "" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/plain": [ "" ] }, "execution_count": 99, "metadata": {}, "output_type": "execute_result" } ], "source": [ "fig,ax,x=plotit(f)\n", "import matplotlib.mlab as mlab\n", "Gcanned,fcanned = mlab.psd(x,NFFT=512,Fs=1./dt,window=mlab.window_hanning,noverlap=256)\n", "ax.loglog(fcanned,Gcanned,'b',label='Canned')\n", "ax.legend(loc=0)\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Note that this returns the same result as our by-hand routine. " ] } ], "metadata": { "kernelspec": { "display_name": "Python 2", "language": "python", "name": "python2" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 2 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython2", "version": "2.7.10" } }, "nbformat": 4, "nbformat_minor": 0 }