Last active
March 21, 2017 10:50
-
-
Save 5agado/15ff55d4729d63f53cec492a933738a8 to your computer and use it in GitHub Desktop.
Analysis of a Personal Public Talk - Exploratory Jupyter Notebook
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"import pandas as pd\n", | |
"import numpy as np\n", | |
"import seaborn as sns\n", | |
"import matplotlib.pyplot as plt\n", | |
"import matplotlib.dates as md\n", | |
"import time\n", | |
"import json\n", | |
"import nltk\n", | |
"from collections import Counter\n", | |
"\n", | |
"sns.set_context(\"paper\")\n", | |
"%matplotlib notebook" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"This notebook is part of an article I wrote: [Analysis of a Personal Public Talk](https://medium.com/@5agado/analysis-of-a-personal-public-talk-9218c429e172#.ldi63adlc). If you interested in a general overview of the project you can refer to such article. \n", | |
"\n", | |
"I'm here going to show the techniques and code used to operate my analysis on heart-rate and speech data." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Heart-Rate Analysis\n", | |
"In this section, I am going to provide an overview of my heart-rate measurements as recorded by my Fitbit Charge HR during the day and talk. \n", | |
"\n", | |
"I used the code and solution mentioned in [my other project](https://medium.com/@5agado/a-quest-for-better-sleep-with-fitbit-data-analysis-5f10b3f548a#.a7vykskjy) for getting and cleaning the Fitbit heart-rate data. I here attached just the cleaned version for the specific data, so the code can be tested without additional dependencies.\n", | |
"\n", | |
"I'm not a big fan of \"playing around with matplotlib setting\", so I rely on quick and dirty ways to obtain the plots I want, without bothering too much on portability or alternative approaches. I nevertheless welcome all suggestions and feedback." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>heart-rate</th>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>time</th>\n", | |
" <th></th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>00:00:00</th>\n", | |
" <td>67</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>00:01:00</th>\n", | |
" <td>68</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>00:02:00</th>\n", | |
" <td>68</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>00:03:00</th>\n", | |
" <td>70</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>00:04:00</th>\n", | |
" <td>70</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" heart-rate\n", | |
"time \n", | |
"00:00:00 67\n", | |
"00:01:00 68\n", | |
"00:02:00 68\n", | |
"00:03:00 70\n", | |
"00:04:00 70" | |
] | |
}, | |
"execution_count": 2, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# Load heart-rate data\n", | |
"# We use parse_dates and custom parser in order to have a ready to use datetime.time type\n", | |
"data = pd.read_csv('2016-12-03_hearth-rate.csv', parse_dates=['time'], index_col='time',\n", | |
" date_parser = lambda x : pd.datetime.strptime(x, '%H:%M:%S').time())\n", | |
"data.head()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>heart-rate</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>count</th>\n", | |
" <td>1440.000000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>mean</th>\n", | |
" <td>80.536806</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>std</th>\n", | |
" <td>14.945722</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>min</th>\n", | |
" <td>53.000000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>25%</th>\n", | |
" <td>70.000000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>50%</th>\n", | |
" <td>81.000000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>75%</th>\n", | |
" <td>89.000000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>max</th>\n", | |
" <td>134.000000</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" heart-rate\n", | |
"count 1440.000000\n", | |
"mean 80.536806\n", | |
"std 14.945722\n", | |
"min 53.000000\n", | |
"25% 70.000000\n", | |
"50% 81.000000\n", | |
"75% 89.000000\n", | |
"max 134.000000" | |
] | |
}, | |
"execution_count": 3, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"data.describe()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"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 = $('<div/>');\n", | |
" this._root_extra_style(this.root)\n", | |
" this.root.attr('style', 'display: inline-block');\n", | |
"\n", | |
" $(parent_element).append(this.root);\n", | |
"\n", | |
" this._init_header(this);\n", | |
" this._init_canvas(this);\n", | |
" this._init_toolbar(this);\n", | |
"\n", | |
" var fig = this;\n", | |
"\n", | |
" this.waiting = false;\n", | |
"\n", | |
" this.ws.onopen = function () {\n", | |
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", | |
" fig.send_message(\"send_image_mode\", {});\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" }\n", | |
"\n", | |
" this.imageObj.onload = function() {\n", | |
" if (fig.image_mode == 'full') {\n", | |
" // Full images could contain transparency (where diff images\n", | |
" // almost always do), so we need to clear the canvas so that\n", | |
" // there is no ghosting.\n", | |
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", | |
" }\n", | |
" fig.context.drawImage(fig.imageObj, 0, 0);\n", | |
" };\n", | |
"\n", | |
" this.imageObj.onunload = function() {\n", | |
" 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", | |
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n", | |
" 'ui-helper-clearfix\"/>');\n", | |
" var titletext = $(\n", | |
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n", | |
" 'text-align: center; padding: 3px;\"/>');\n", | |
" titlebar.append(titletext)\n", | |
" this.root.append(titlebar);\n", | |
" this.header = titletext[0];\n", | |
"}\n", | |
"\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_canvas = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var canvas_div = $('<div/>');\n", | |
"\n", | |
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", | |
"\n", | |
" function canvas_keyboard_event(event) {\n", | |
" return fig.key_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" canvas_div.keydown('key_press', canvas_keyboard_event);\n", | |
" canvas_div.keyup('key_release', canvas_keyboard_event);\n", | |
" this.canvas_div = canvas_div\n", | |
" this._canvas_extra_style(canvas_div)\n", | |
" this.root.append(canvas_div);\n", | |
"\n", | |
" var canvas = $('<canvas/>');\n", | |
" canvas.addClass('mpl-canvas');\n", | |
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", | |
"\n", | |
" this.canvas = canvas[0];\n", | |
" this.context = canvas[0].getContext(\"2d\");\n", | |
"\n", | |
" var rubberband = $('<canvas/>');\n", | |
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", | |
"\n", | |
" var pass_mouse_events = true;\n", | |
"\n", | |
" canvas_div.resizable({\n", | |
" start: function(event, ui) {\n", | |
" pass_mouse_events = false;\n", | |
" },\n", | |
" resize: function(event, ui) {\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" stop: function(event, ui) {\n", | |
" pass_mouse_events = true;\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" });\n", | |
"\n", | |
" function mouse_event_fn(event) {\n", | |
" if (pass_mouse_events)\n", | |
" return fig.mouse_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" rubberband.mousedown('button_press', mouse_event_fn);\n", | |
" rubberband.mouseup('button_release', mouse_event_fn);\n", | |
" // Throttle sequential mouse events to 1 every 20ms.\n", | |
" rubberband.mousemove('motion_notify', mouse_event_fn);\n", | |
"\n", | |
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n", | |
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n", | |
"\n", | |
" canvas_div.on(\"wheel\", function (event) {\n", | |
" event = event.originalEvent;\n", | |
" event['data'] = 'scroll'\n", | |
" if (event.deltaY < 0) {\n", | |
" event.step = 1;\n", | |
" } else {\n", | |
" event.step = -1;\n", | |
" }\n", | |
" mouse_event_fn(event);\n", | |
" });\n", | |
"\n", | |
" canvas_div.append(canvas);\n", | |
" canvas_div.append(rubberband);\n", | |
"\n", | |
" this.rubberband = rubberband;\n", | |
" this.rubberband_canvas = rubberband[0];\n", | |
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n", | |
" this.rubberband_context.strokeStyle = \"#000000\";\n", | |
"\n", | |
" this._resize_canvas = function(width, height) {\n", | |
" // Keep the size of the canvas, canvas container, and rubber band\n", | |
" // canvas in synch.\n", | |
" canvas_div.css('width', width)\n", | |
" canvas_div.css('height', height)\n", | |
"\n", | |
" canvas.attr('width', width);\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 = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items) {\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) {\n", | |
" // put a spacer in here.\n", | |
" continue;\n", | |
" }\n", | |
" var button = $('<button/>');\n", | |
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n", | |
" 'ui-button-icon-only');\n", | |
" button.attr('role', 'button');\n", | |
" button.attr('aria-disabled', 'false');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
"\n", | |
" var icon_img = $('<span/>');\n", | |
" icon_img.addClass('ui-button-icon-primary ui-icon');\n", | |
" icon_img.addClass(image);\n", | |
" icon_img.addClass('ui-corner-all');\n", | |
"\n", | |
" var tooltip_span = $('<span/>');\n", | |
" tooltip_span.addClass('ui-button-text');\n", | |
" tooltip_span.html(tooltip);\n", | |
"\n", | |
" button.append(icon_img);\n", | |
" button.append(tooltip_span);\n", | |
"\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" var fmt_picker_span = $('<span/>');\n", | |
"\n", | |
" var fmt_picker = $('<select/>');\n", | |
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n", | |
" fmt_picker_span.append(fmt_picker);\n", | |
" nav_element.append(fmt_picker_span);\n", | |
" this.format_dropdown = fmt_picker[0];\n", | |
"\n", | |
" for (var ind in mpl.extensions) {\n", | |
" var fmt = mpl.extensions[ind];\n", | |
" var option = $(\n", | |
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n", | |
" fmt_picker.append(option)\n", | |
" }\n", | |
"\n", | |
" // Add hover states to the ui-buttons\n", | |
" $( \".ui-button\" ).hover(\n", | |
" function() { $(this).addClass(\"ui-state-hover\");},\n", | |
" function() { $(this).removeClass(\"ui-state-hover\");}\n", | |
" );\n", | |
"\n", | |
" var status_bar = $('<span class=\"mpl-message\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n", | |
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", | |
" // which will in turn request a refresh of the image.\n", | |
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_message = function(type, properties) {\n", | |
" properties['type'] = type;\n", | |
" properties['figure_id'] = this.id;\n", | |
" this.ws.send(JSON.stringify(properties));\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_draw_message = function() {\n", | |
" if (!this.waiting) {\n", | |
" this.waiting = true;\n", | |
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" var format_dropdown = fig.format_dropdown;\n", | |
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", | |
" fig.ondownload(fig, format);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n", | |
" var size = msg['size'];\n", | |
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n", | |
" fig._resize_canvas(size[0], size[1]);\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n", | |
" var x0 = msg['x0'];\n", | |
" var y0 = fig.canvas.height - msg['y0'];\n", | |
" var x1 = msg['x1'];\n", | |
" var y1 = fig.canvas.height - msg['y1'];\n", | |
" x0 = Math.floor(x0) + 0.5;\n", | |
" y0 = Math.floor(y0) + 0.5;\n", | |
" x1 = Math.floor(x1) + 0.5;\n", | |
" y1 = Math.floor(y1) + 0.5;\n", | |
" var min_x = Math.min(x0, x1);\n", | |
" var min_y = Math.min(y0, y1);\n", | |
" var width = Math.abs(x1 - x0);\n", | |
" var height = Math.abs(y1 - y0);\n", | |
"\n", | |
" fig.rubberband_context.clearRect(\n", | |
" 0, 0, fig.canvas.width, fig.canvas.height);\n", | |
"\n", | |
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n", | |
" // Updates the figure title.\n", | |
" fig.header.textContent = msg['label'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n", | |
" var cursor = msg['cursor'];\n", | |
" switch(cursor)\n", | |
" {\n", | |
" case 0:\n", | |
" cursor = 'pointer';\n", | |
" break;\n", | |
" case 1:\n", | |
" cursor = 'default';\n", | |
" break;\n", | |
" case 2:\n", | |
" cursor = 'crosshair';\n", | |
" break;\n", | |
" case 3:\n", | |
" cursor = 'move';\n", | |
" break;\n", | |
" }\n", | |
" fig.rubberband_canvas.style.cursor = cursor;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_message = function(fig, msg) {\n", | |
" fig.message.textContent = msg['message'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n", | |
" // Request the server to send over a new figure.\n", | |
" fig.send_draw_message();\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n", | |
" fig.image_mode = msg['mode'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Called whenever the canvas gets updated.\n", | |
" this.send_message(\"ack\", {});\n", | |
"}\n", | |
"\n", | |
"// A function to construct a web socket function for onmessage handling.\n", | |
"// Called in the figure constructor.\n", | |
"mpl.figure.prototype._make_on_message_function = function(fig) {\n", | |
" return function socket_on_message(evt) {\n", | |
" if (evt.data instanceof Blob) {\n", | |
" /* FIXME: We get \"Resource interpreted as Image but\n", | |
" * transferred with MIME type text/plain:\" errors on\n", | |
" * Chrome. But how to set the MIME type? It doesn't seem\n", | |
" * to be part of the websocket stream */\n", | |
" evt.data.type = \"image/png\";\n", | |
"\n", | |
" /* Free the memory for the previous frames */\n", | |
" if (fig.imageObj.src) {\n", | |
" (window.URL || window.webkitURL).revokeObjectURL(\n", | |
" fig.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", | |
" evt.data);\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n", | |
" fig.imageObj.src = evt.data;\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var msg = JSON.parse(evt.data);\n", | |
" var msg_type = msg['type'];\n", | |
"\n", | |
" // Call the \"handle_{type}\" callback, which takes\n", | |
" // the figure and JSON message as its only arguments.\n", | |
" try {\n", | |
" var callback = fig[\"handle_\" + msg_type];\n", | |
" } catch (e) {\n", | |
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" if (callback) {\n", | |
" try {\n", | |
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", | |
" callback(fig, msg);\n", | |
" } catch (e) {\n", | |
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n", | |
" }\n", | |
" }\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", | |
"mpl.findpos = function(e) {\n", | |
" //this section is from http://www.quirksmode.org/js/events_properties.html\n", | |
" var targ;\n", | |
" if (!e)\n", | |
" e = window.event;\n", | |
" if (e.target)\n", | |
" targ = e.target;\n", | |
" else if (e.srcElement)\n", | |
" targ = e.srcElement;\n", | |
" if (targ.nodeType == 3) // defeat Safari bug\n", | |
" targ = targ.parentNode;\n", | |
"\n", | |
" // jQuery normalizes the pageX and pageY\n", | |
" // pageX,Y are the mouse positions relative to the document\n", | |
" // offset() returns the position of the element relative to the document\n", | |
" var x = e.pageX - $(targ).offset().left;\n", | |
" var y = e.pageY - $(targ).offset().top;\n", | |
"\n", | |
" return {\"x\": x, \"y\": y};\n", | |
"};\n", | |
"\n", | |
"/*\n", | |
" * return a copy of an object with only non-object keys\n", | |
" * we need this to avoid circular references\n", | |
" * http://stackoverflow.com/a/24161582/3208463\n", | |
" */\n", | |
"function simpleKeys (original) {\n", | |
" return Object.keys(original).reduce(function (obj, key) {\n", | |
" if (typeof original[key] !== 'object')\n", | |
" obj[key] = original[key]\n", | |
" return obj;\n", | |
" }, {});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.mouse_event = function(event, name) {\n", | |
" var canvas_pos = mpl.findpos(event)\n", | |
"\n", | |
" if (name === 'button_press')\n", | |
" {\n", | |
" this.canvas.focus();\n", | |
" this.canvas_div.focus();\n", | |
" }\n", | |
"\n", | |
" var x = canvas_pos.x;\n", | |
" var y = canvas_pos.y;\n", | |
"\n", | |
" this.send_message(name, {x: x, y: y, button: event.button,\n", | |
" step: event.step,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
"\n", | |
" /* This prevents the web browser from automatically changing to\n", | |
" * the text insertion cursor when the button is pressed. We want\n", | |
" * to control all of the cursor setting manually through the\n", | |
" * 'cursor' event from matplotlib */\n", | |
" event.preventDefault();\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" // Handle any extra behaviour associated with a key event\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.key_event = function(event, name) {\n", | |
"\n", | |
" // Prevent repeat events\n", | |
" if (name == 'key_press')\n", | |
" {\n", | |
" if (event.which === this._key)\n", | |
" return;\n", | |
" else\n", | |
" this._key = event.which;\n", | |
" }\n", | |
" if (name == 'key_release')\n", | |
" this._key = null;\n", | |
"\n", | |
" var value = '';\n", | |
" if (event.ctrlKey && event.which != 17)\n", | |
" value += \"ctrl+\";\n", | |
" if (event.altKey && event.which != 18)\n", | |
" value += \"alt+\";\n", | |
" if (event.shiftKey && event.which != 16)\n", | |
" value += \"shift+\";\n", | |
"\n", | |
" value += 'k';\n", | |
" value += event.which.toString();\n", | |
"\n", | |
" this._key_event_extra(event, name);\n", | |
"\n", | |
" this.send_message(name, {key: value,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n", | |
" if (name == 'download') {\n", | |
" this.handle_save(this, null);\n", | |
" } else {\n", | |
" this.send_message(\"toolbar_button\", {name: name});\n", | |
" }\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", | |
" this.message.textContent = tooltip;\n", | |
"};\n", | |
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", | |
"\n", | |
"mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", | |
"\n", | |
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n", | |
" // Create a \"websocket\"-like object which calls the given IPython comm\n", | |
" // object with the appropriate methods. Currently this is a non binary\n", | |
" // socket, so there is still some room for performance tuning.\n", | |
" var ws = {};\n", | |
"\n", | |
" ws.close = function() {\n", | |
" comm.close()\n", | |
" };\n", | |
" ws.send = function(m) {\n", | |
" //console.log('sending', m);\n", | |
" comm.send(m);\n", | |
" };\n", | |
" // Register the callback with on_msg.\n", | |
" comm.on_msg(function(msg) {\n", | |
" //console.log('receiving', msg['content']['data'], msg);\n", | |
" // Pass the mpl event to the overriden (by mpl) onmessage function.\n", | |
" ws.onmessage(msg['content']['data'])\n", | |
" });\n", | |
" return ws;\n", | |
"}\n", | |
"\n", | |
"mpl.mpl_figure_comm = function(comm, msg) {\n", | |
" // This is the function which gets called when the mpl process\n", | |
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n", | |
"\n", | |
" var id = msg.content.data.id;\n", | |
" // Get hold of the div created by the display call when the Comm\n", | |
" // socket was opened in Python.\n", | |
" var element = $(\"#\" + id);\n", | |
" var ws_proxy = comm_websocket_adapter(comm)\n", | |
"\n", | |
" function ondownload(figure, format) {\n", | |
" window.open(figure.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" var fig = new mpl.figure(id, ws_proxy,\n", | |
" ondownload,\n", | |
" element.get(0));\n", | |
"\n", | |
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", | |
" // web socket which is closed, not our websocket->open comm proxy.\n", | |
" ws_proxy.onopen();\n", | |
"\n", | |
" fig.parent_element = element.get(0);\n", | |
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n", | |
" if (!fig.cell_info) {\n", | |
" console.error(\"Failed to find cell for figure\", id, fig);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var output_index = fig.cell_info[2]\n", | |
" var cell = fig.cell_info[0];\n", | |
"\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.handle_close = function(fig, msg) {\n", | |
" fig.root.unbind('remove')\n", | |
"\n", | |
" // Update the output cell to use the data from the current canvas.\n", | |
" fig.push_to_output();\n", | |
" var dataURL = fig.canvas.toDataURL();\n", | |
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n", | |
" // the notebook keyboard shortcuts fail.\n", | |
" IPython.keyboard_manager.enable()\n", | |
" $(fig.parent_element).html('<img src=\"' + dataURL + '\">');\n", | |
" fig.close_ws(fig, msg);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.close_ws = function(fig, msg){\n", | |
" fig.send_message('closing', msg);\n", | |
" // fig.ws.close()\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", | |
" // Turn the data on the canvas into data in the output cell.\n", | |
" var dataURL = this.canvas.toDataURL();\n", | |
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Tell IPython that the notebook contents must change.\n", | |
" IPython.notebook.set_dirty(true);\n", | |
" this.send_message(\"ack\", {});\n", | |
" var fig = this;\n", | |
" // Wait a second, then push the new image to the DOM so\n", | |
" // that it is saved nicely (might be nice to debounce this).\n", | |
" setTimeout(function () { fig.push_to_output() }, 1000);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_toolbar = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var nav_element = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items){\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) { continue; };\n", | |
"\n", | |
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" // Add the status bar.\n", | |
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"\n", | |
" // Add the close button to the window.\n", | |
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", | |
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", | |
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n", | |
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n", | |
" buttongrp.append(button);\n", | |
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", | |
" titlebar.prepend(buttongrp);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(el){\n", | |
" var fig = this\n", | |
" el.on(\"remove\", function(){\n", | |
"\tfig.close_ws(fig, {});\n", | |
" });\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(el){\n", | |
" // this is important to make the div 'focusable\n", | |
" el.attr('tabindex', 0)\n", | |
" // reach out to IPython and tell the keyboard manager to turn it's self\n", | |
" // off when our div gets focus\n", | |
"\n", | |
" // location in version 3\n", | |
" if (IPython.notebook.keyboard_manager) {\n", | |
" IPython.notebook.keyboard_manager.register_events(el);\n", | |
" }\n", | |
" else {\n", | |
" // location in version 2\n", | |
" IPython.keyboard_manager.register_events(el);\n", | |
" }\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" var manager = IPython.notebook.keyboard_manager;\n", | |
" if (!manager)\n", | |
" manager = IPython.keyboard_manager;\n", | |
"\n", | |
" // Check for shift+enter\n", | |
" if (event.shiftKey && event.which == 13) {\n", | |
" this.canvas_div.blur();\n", | |
" event.shiftKey = false;\n", | |
" // Send a \"J\" for go to next cell\n", | |
" event.which = 74;\n", | |
" event.keyCode = 74;\n", | |
" manager.command_mode();\n", | |
" manager.handle_keydown(event);\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" fig.ondownload(fig, null);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.find_output_cell = function(html_output) {\n", | |
" // Return the cell and output element which can be found *uniquely* in the notebook.\n", | |
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", | |
" // IPython event is triggered only after the cells have been serialised, which for\n", | |
" // our purposes (turning an active figure into a static one), is too late.\n", | |
" var cells = IPython.notebook.get_cells();\n", | |
" var ncells = cells.length;\n", | |
" for (var i=0; i<ncells; i++) {\n", | |
" var cell = cells[i];\n", | |
" if (cell.cell_type === 'code'){\n", | |
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n", | |
" var data = cell.output_area.outputs[j];\n", | |
" if (data.data) {\n", | |
" // IPython >= 3 moved mimebundle to data attribute of output\n", | |
" data = data.data;\n", | |
" }\n", | |
" if (data['text/html'] == html_output) {\n", | |
" return [cell, data, j];\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"// Register the function which deals with the matplotlib target/channel.\n", | |
"// The kernel may be null if the page has been refreshed.\n", | |
"if (IPython.notebook.kernel != null) {\n", | |
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", | |
"}\n" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/html": [ | |
"<img src=\"data:image/png;base64,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\">" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"# Plot entire day data\n", | |
"ax = data.plot(color='tomato', linewidth=1.5)\n", | |
"ax.set_xlabel('')\n", | |
"ax.xaxis.set_ticks(np.arange(0, 24*60*60, 3*60*60))\n", | |
"# Disaligned first label really bothers me. We can hide it with this line\n", | |
"ax.xaxis.get_major_ticks()[0].label1.set_visible(False)\n", | |
"plt.show()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"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 = $('<div/>');\n", | |
" this._root_extra_style(this.root)\n", | |
" this.root.attr('style', 'display: inline-block');\n", | |
"\n", | |
" $(parent_element).append(this.root);\n", | |
"\n", | |
" this._init_header(this);\n", | |
" this._init_canvas(this);\n", | |
" this._init_toolbar(this);\n", | |
"\n", | |
" var fig = this;\n", | |
"\n", | |
" this.waiting = false;\n", | |
"\n", | |
" this.ws.onopen = function () {\n", | |
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", | |
" fig.send_message(\"send_image_mode\", {});\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" }\n", | |
"\n", | |
" this.imageObj.onload = function() {\n", | |
" if (fig.image_mode == 'full') {\n", | |
" // Full images could contain transparency (where diff images\n", | |
" // almost always do), so we need to clear the canvas so that\n", | |
" // there is no ghosting.\n", | |
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", | |
" }\n", | |
" fig.context.drawImage(fig.imageObj, 0, 0);\n", | |
" };\n", | |
"\n", | |
" this.imageObj.onunload = function() {\n", | |
" 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", | |
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n", | |
" 'ui-helper-clearfix\"/>');\n", | |
" var titletext = $(\n", | |
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n", | |
" 'text-align: center; padding: 3px;\"/>');\n", | |
" titlebar.append(titletext)\n", | |
" this.root.append(titlebar);\n", | |
" this.header = titletext[0];\n", | |
"}\n", | |
"\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_canvas = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var canvas_div = $('<div/>');\n", | |
"\n", | |
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", | |
"\n", | |
" function canvas_keyboard_event(event) {\n", | |
" return fig.key_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" canvas_div.keydown('key_press', canvas_keyboard_event);\n", | |
" canvas_div.keyup('key_release', canvas_keyboard_event);\n", | |
" this.canvas_div = canvas_div\n", | |
" this._canvas_extra_style(canvas_div)\n", | |
" this.root.append(canvas_div);\n", | |
"\n", | |
" var canvas = $('<canvas/>');\n", | |
" canvas.addClass('mpl-canvas');\n", | |
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", | |
"\n", | |
" this.canvas = canvas[0];\n", | |
" this.context = canvas[0].getContext(\"2d\");\n", | |
"\n", | |
" var rubberband = $('<canvas/>');\n", | |
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", | |
"\n", | |
" var pass_mouse_events = true;\n", | |
"\n", | |
" canvas_div.resizable({\n", | |
" start: function(event, ui) {\n", | |
" pass_mouse_events = false;\n", | |
" },\n", | |
" resize: function(event, ui) {\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" stop: function(event, ui) {\n", | |
" pass_mouse_events = true;\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" });\n", | |
"\n", | |
" function mouse_event_fn(event) {\n", | |
" if (pass_mouse_events)\n", | |
" return fig.mouse_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" rubberband.mousedown('button_press', mouse_event_fn);\n", | |
" rubberband.mouseup('button_release', mouse_event_fn);\n", | |
" // Throttle sequential mouse events to 1 every 20ms.\n", | |
" rubberband.mousemove('motion_notify', mouse_event_fn);\n", | |
"\n", | |
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n", | |
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n", | |
"\n", | |
" canvas_div.on(\"wheel\", function (event) {\n", | |
" event = event.originalEvent;\n", | |
" event['data'] = 'scroll'\n", | |
" if (event.deltaY < 0) {\n", | |
" event.step = 1;\n", | |
" } else {\n", | |
" event.step = -1;\n", | |
" }\n", | |
" mouse_event_fn(event);\n", | |
" });\n", | |
"\n", | |
" canvas_div.append(canvas);\n", | |
" canvas_div.append(rubberband);\n", | |
"\n", | |
" this.rubberband = rubberband;\n", | |
" this.rubberband_canvas = rubberband[0];\n", | |
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n", | |
" this.rubberband_context.strokeStyle = \"#000000\";\n", | |
"\n", | |
" this._resize_canvas = function(width, height) {\n", | |
" // Keep the size of the canvas, canvas container, and rubber band\n", | |
" // canvas in synch.\n", | |
" canvas_div.css('width', width)\n", | |
" canvas_div.css('height', height)\n", | |
"\n", | |
" canvas.attr('width', width);\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 = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items) {\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) {\n", | |
" // put a spacer in here.\n", | |
" continue;\n", | |
" }\n", | |
" var button = $('<button/>');\n", | |
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n", | |
" 'ui-button-icon-only');\n", | |
" button.attr('role', 'button');\n", | |
" button.attr('aria-disabled', 'false');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
"\n", | |
" var icon_img = $('<span/>');\n", | |
" icon_img.addClass('ui-button-icon-primary ui-icon');\n", | |
" icon_img.addClass(image);\n", | |
" icon_img.addClass('ui-corner-all');\n", | |
"\n", | |
" var tooltip_span = $('<span/>');\n", | |
" tooltip_span.addClass('ui-button-text');\n", | |
" tooltip_span.html(tooltip);\n", | |
"\n", | |
" button.append(icon_img);\n", | |
" button.append(tooltip_span);\n", | |
"\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" var fmt_picker_span = $('<span/>');\n", | |
"\n", | |
" var fmt_picker = $('<select/>');\n", | |
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n", | |
" fmt_picker_span.append(fmt_picker);\n", | |
" nav_element.append(fmt_picker_span);\n", | |
" this.format_dropdown = fmt_picker[0];\n", | |
"\n", | |
" for (var ind in mpl.extensions) {\n", | |
" var fmt = mpl.extensions[ind];\n", | |
" var option = $(\n", | |
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n", | |
" fmt_picker.append(option)\n", | |
" }\n", | |
"\n", | |
" // Add hover states to the ui-buttons\n", | |
" $( \".ui-button\" ).hover(\n", | |
" function() { $(this).addClass(\"ui-state-hover\");},\n", | |
" function() { $(this).removeClass(\"ui-state-hover\");}\n", | |
" );\n", | |
"\n", | |
" var status_bar = $('<span class=\"mpl-message\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n", | |
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", | |
" // which will in turn request a refresh of the image.\n", | |
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_message = function(type, properties) {\n", | |
" properties['type'] = type;\n", | |
" properties['figure_id'] = this.id;\n", | |
" this.ws.send(JSON.stringify(properties));\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_draw_message = function() {\n", | |
" if (!this.waiting) {\n", | |
" this.waiting = true;\n", | |
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" var format_dropdown = fig.format_dropdown;\n", | |
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", | |
" fig.ondownload(fig, format);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n", | |
" var size = msg['size'];\n", | |
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n", | |
" fig._resize_canvas(size[0], size[1]);\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n", | |
" var x0 = msg['x0'];\n", | |
" var y0 = fig.canvas.height - msg['y0'];\n", | |
" var x1 = msg['x1'];\n", | |
" var y1 = fig.canvas.height - msg['y1'];\n", | |
" x0 = Math.floor(x0) + 0.5;\n", | |
" y0 = Math.floor(y0) + 0.5;\n", | |
" x1 = Math.floor(x1) + 0.5;\n", | |
" y1 = Math.floor(y1) + 0.5;\n", | |
" var min_x = Math.min(x0, x1);\n", | |
" var min_y = Math.min(y0, y1);\n", | |
" var width = Math.abs(x1 - x0);\n", | |
" var height = Math.abs(y1 - y0);\n", | |
"\n", | |
" fig.rubberband_context.clearRect(\n", | |
" 0, 0, fig.canvas.width, fig.canvas.height);\n", | |
"\n", | |
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n", | |
" // Updates the figure title.\n", | |
" fig.header.textContent = msg['label'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n", | |
" var cursor = msg['cursor'];\n", | |
" switch(cursor)\n", | |
" {\n", | |
" case 0:\n", | |
" cursor = 'pointer';\n", | |
" break;\n", | |
" case 1:\n", | |
" cursor = 'default';\n", | |
" break;\n", | |
" case 2:\n", | |
" cursor = 'crosshair';\n", | |
" break;\n", | |
" case 3:\n", | |
" cursor = 'move';\n", | |
" break;\n", | |
" }\n", | |
" fig.rubberband_canvas.style.cursor = cursor;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_message = function(fig, msg) {\n", | |
" fig.message.textContent = msg['message'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n", | |
" // Request the server to send over a new figure.\n", | |
" fig.send_draw_message();\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n", | |
" fig.image_mode = msg['mode'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Called whenever the canvas gets updated.\n", | |
" this.send_message(\"ack\", {});\n", | |
"}\n", | |
"\n", | |
"// A function to construct a web socket function for onmessage handling.\n", | |
"// Called in the figure constructor.\n", | |
"mpl.figure.prototype._make_on_message_function = function(fig) {\n", | |
" return function socket_on_message(evt) {\n", | |
" if (evt.data instanceof Blob) {\n", | |
" /* FIXME: We get \"Resource interpreted as Image but\n", | |
" * transferred with MIME type text/plain:\" errors on\n", | |
" * Chrome. But how to set the MIME type? It doesn't seem\n", | |
" * to be part of the websocket stream */\n", | |
" evt.data.type = \"image/png\";\n", | |
"\n", | |
" /* Free the memory for the previous frames */\n", | |
" if (fig.imageObj.src) {\n", | |
" (window.URL || window.webkitURL).revokeObjectURL(\n", | |
" fig.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", | |
" evt.data);\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n", | |
" fig.imageObj.src = evt.data;\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var msg = JSON.parse(evt.data);\n", | |
" var msg_type = msg['type'];\n", | |
"\n", | |
" // Call the \"handle_{type}\" callback, which takes\n", | |
" // the figure and JSON message as its only arguments.\n", | |
" try {\n", | |
" var callback = fig[\"handle_\" + msg_type];\n", | |
" } catch (e) {\n", | |
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" if (callback) {\n", | |
" try {\n", | |
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", | |
" callback(fig, msg);\n", | |
" } catch (e) {\n", | |
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n", | |
" }\n", | |
" }\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", | |
"mpl.findpos = function(e) {\n", | |
" //this section is from http://www.quirksmode.org/js/events_properties.html\n", | |
" var targ;\n", | |
" if (!e)\n", | |
" e = window.event;\n", | |
" if (e.target)\n", | |
" targ = e.target;\n", | |
" else if (e.srcElement)\n", | |
" targ = e.srcElement;\n", | |
" if (targ.nodeType == 3) // defeat Safari bug\n", | |
" targ = targ.parentNode;\n", | |
"\n", | |
" // jQuery normalizes the pageX and pageY\n", | |
" // pageX,Y are the mouse positions relative to the document\n", | |
" // offset() returns the position of the element relative to the document\n", | |
" var x = e.pageX - $(targ).offset().left;\n", | |
" var y = e.pageY - $(targ).offset().top;\n", | |
"\n", | |
" return {\"x\": x, \"y\": y};\n", | |
"};\n", | |
"\n", | |
"/*\n", | |
" * return a copy of an object with only non-object keys\n", | |
" * we need this to avoid circular references\n", | |
" * http://stackoverflow.com/a/24161582/3208463\n", | |
" */\n", | |
"function simpleKeys (original) {\n", | |
" return Object.keys(original).reduce(function (obj, key) {\n", | |
" if (typeof original[key] !== 'object')\n", | |
" obj[key] = original[key]\n", | |
" return obj;\n", | |
" }, {});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.mouse_event = function(event, name) {\n", | |
" var canvas_pos = mpl.findpos(event)\n", | |
"\n", | |
" if (name === 'button_press')\n", | |
" {\n", | |
" this.canvas.focus();\n", | |
" this.canvas_div.focus();\n", | |
" }\n", | |
"\n", | |
" var x = canvas_pos.x;\n", | |
" var y = canvas_pos.y;\n", | |
"\n", | |
" this.send_message(name, {x: x, y: y, button: event.button,\n", | |
" step: event.step,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
"\n", | |
" /* This prevents the web browser from automatically changing to\n", | |
" * the text insertion cursor when the button is pressed. We want\n", | |
" * to control all of the cursor setting manually through the\n", | |
" * 'cursor' event from matplotlib */\n", | |
" event.preventDefault();\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" // Handle any extra behaviour associated with a key event\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.key_event = function(event, name) {\n", | |
"\n", | |
" // Prevent repeat events\n", | |
" if (name == 'key_press')\n", | |
" {\n", | |
" if (event.which === this._key)\n", | |
" return;\n", | |
" else\n", | |
" this._key = event.which;\n", | |
" }\n", | |
" if (name == 'key_release')\n", | |
" this._key = null;\n", | |
"\n", | |
" var value = '';\n", | |
" if (event.ctrlKey && event.which != 17)\n", | |
" value += \"ctrl+\";\n", | |
" if (event.altKey && event.which != 18)\n", | |
" value += \"alt+\";\n", | |
" if (event.shiftKey && event.which != 16)\n", | |
" value += \"shift+\";\n", | |
"\n", | |
" value += 'k';\n", | |
" value += event.which.toString();\n", | |
"\n", | |
" this._key_event_extra(event, name);\n", | |
"\n", | |
" this.send_message(name, {key: value,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n", | |
" if (name == 'download') {\n", | |
" this.handle_save(this, null);\n", | |
" } else {\n", | |
" this.send_message(\"toolbar_button\", {name: name});\n", | |
" }\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", | |
" this.message.textContent = tooltip;\n", | |
"};\n", | |
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", | |
"\n", | |
"mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", | |
"\n", | |
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n", | |
" // Create a \"websocket\"-like object which calls the given IPython comm\n", | |
" // object with the appropriate methods. Currently this is a non binary\n", | |
" // socket, so there is still some room for performance tuning.\n", | |
" var ws = {};\n", | |
"\n", | |
" ws.close = function() {\n", | |
" comm.close()\n", | |
" };\n", | |
" ws.send = function(m) {\n", | |
" //console.log('sending', m);\n", | |
" comm.send(m);\n", | |
" };\n", | |
" // Register the callback with on_msg.\n", | |
" comm.on_msg(function(msg) {\n", | |
" //console.log('receiving', msg['content']['data'], msg);\n", | |
" // Pass the mpl event to the overriden (by mpl) onmessage function.\n", | |
" ws.onmessage(msg['content']['data'])\n", | |
" });\n", | |
" return ws;\n", | |
"}\n", | |
"\n", | |
"mpl.mpl_figure_comm = function(comm, msg) {\n", | |
" // This is the function which gets called when the mpl process\n", | |
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n", | |
"\n", | |
" var id = msg.content.data.id;\n", | |
" // Get hold of the div created by the display call when the Comm\n", | |
" // socket was opened in Python.\n", | |
" var element = $(\"#\" + id);\n", | |
" var ws_proxy = comm_websocket_adapter(comm)\n", | |
"\n", | |
" function ondownload(figure, format) {\n", | |
" window.open(figure.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" var fig = new mpl.figure(id, ws_proxy,\n", | |
" ondownload,\n", | |
" element.get(0));\n", | |
"\n", | |
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", | |
" // web socket which is closed, not our websocket->open comm proxy.\n", | |
" ws_proxy.onopen();\n", | |
"\n", | |
" fig.parent_element = element.get(0);\n", | |
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n", | |
" if (!fig.cell_info) {\n", | |
" console.error(\"Failed to find cell for figure\", id, fig);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var output_index = fig.cell_info[2]\n", | |
" var cell = fig.cell_info[0];\n", | |
"\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.handle_close = function(fig, msg) {\n", | |
" fig.root.unbind('remove')\n", | |
"\n", | |
" // Update the output cell to use the data from the current canvas.\n", | |
" fig.push_to_output();\n", | |
" var dataURL = fig.canvas.toDataURL();\n", | |
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n", | |
" // the notebook keyboard shortcuts fail.\n", | |
" IPython.keyboard_manager.enable()\n", | |
" $(fig.parent_element).html('<img src=\"' + dataURL + '\">');\n", | |
" fig.close_ws(fig, msg);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.close_ws = function(fig, msg){\n", | |
" fig.send_message('closing', msg);\n", | |
" // fig.ws.close()\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", | |
" // Turn the data on the canvas into data in the output cell.\n", | |
" var dataURL = this.canvas.toDataURL();\n", | |
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Tell IPython that the notebook contents must change.\n", | |
" IPython.notebook.set_dirty(true);\n", | |
" this.send_message(\"ack\", {});\n", | |
" var fig = this;\n", | |
" // Wait a second, then push the new image to the DOM so\n", | |
" // that it is saved nicely (might be nice to debounce this).\n", | |
" setTimeout(function () { fig.push_to_output() }, 1000);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_toolbar = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var nav_element = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items){\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) { continue; };\n", | |
"\n", | |
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" // Add the status bar.\n", | |
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"\n", | |
" // Add the close button to the window.\n", | |
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", | |
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", | |
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n", | |
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n", | |
" buttongrp.append(button);\n", | |
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", | |
" titlebar.prepend(buttongrp);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(el){\n", | |
" var fig = this\n", | |
" el.on(\"remove\", function(){\n", | |
"\tfig.close_ws(fig, {});\n", | |
" });\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(el){\n", | |
" // this is important to make the div 'focusable\n", | |
" el.attr('tabindex', 0)\n", | |
" // reach out to IPython and tell the keyboard manager to turn it's self\n", | |
" // off when our div gets focus\n", | |
"\n", | |
" // location in version 3\n", | |
" if (IPython.notebook.keyboard_manager) {\n", | |
" IPython.notebook.keyboard_manager.register_events(el);\n", | |
" }\n", | |
" else {\n", | |
" // location in version 2\n", | |
" IPython.keyboard_manager.register_events(el);\n", | |
" }\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" var manager = IPython.notebook.keyboard_manager;\n", | |
" if (!manager)\n", | |
" manager = IPython.keyboard_manager;\n", | |
"\n", | |
" // Check for shift+enter\n", | |
" if (event.shiftKey && event.which == 13) {\n", | |
" this.canvas_div.blur();\n", | |
" event.shiftKey = false;\n", | |
" // Send a \"J\" for go to next cell\n", | |
" event.which = 74;\n", | |
" event.keyCode = 74;\n", | |
" manager.command_mode();\n", | |
" manager.handle_keydown(event);\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" fig.ondownload(fig, null);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.find_output_cell = function(html_output) {\n", | |
" // Return the cell and output element which can be found *uniquely* in the notebook.\n", | |
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", | |
" // IPython event is triggered only after the cells have been serialised, which for\n", | |
" // our purposes (turning an active figure into a static one), is too late.\n", | |
" var cells = IPython.notebook.get_cells();\n", | |
" var ncells = cells.length;\n", | |
" for (var i=0; i<ncells; i++) {\n", | |
" var cell = cells[i];\n", | |
" if (cell.cell_type === 'code'){\n", | |
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n", | |
" var data = cell.output_area.outputs[j];\n", | |
" if (data.data) {\n", | |
" // IPython >= 3 moved mimebundle to data attribute of output\n", | |
" data = data.data;\n", | |
" }\n", | |
" if (data['text/html'] == html_output) {\n", | |
" return [cell, data, j];\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"// Register the function which deals with the matplotlib target/channel.\n", | |
"// The kernel may be null if the page has been refreshed.\n", | |
"if (IPython.notebook.kernel != null) {\n", | |
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", | |
"}\n" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/html": [ | |
"<img src=\"data:image/png;base64,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\">" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"# Consider only the specific time interval (betwen 18.00 and 20.00)\n", | |
"ax = data.plot(color='tomato', linewidth=2)\n", | |
"ax.set_xlabel('')\n", | |
"ax.xaxis.set_ticks(np.arange(0, 24*60*60, 30*60))\n", | |
"ax.set_xlim([18*60*60,20*60*60])\n", | |
"ax.set_ylim([70,140])\n", | |
"\n", | |
"label_y_pos = 142\n", | |
"# Locator lines add basic information for main events\n", | |
"# A:arrived, B-C:first speaker talk, C:start of my talk, D:Q&A, E:last talk \n", | |
"lines = [('18:20:00', 'A'), ('18:35:00', 'B'), ('18:47:00', 'C'), ('19:10:00', 'D'), ('19:30:00', 'E')]\n", | |
"for t in lines:\n", | |
" x_pos = data.index.get_loc(pd.datetime.strptime(t[0], '%H:%M:%S').time())\n", | |
" ax.axvline(x_pos*60, linewidth=1)\n", | |
" ax.text(x_pos*60-60, label_y_pos, t[1])\n", | |
"plt.show()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"# Speech To Text\n", | |
"To convert my audio file to text I used [IBM Watson Speech-to-Text service](http://www.ibm.com/watson/developercloud/speech-to-text.html), which accompanies each recognized word by a confidence level, start and end time. I also relied on the [official Watson Python SDK](https://github.com/watson-developer-cloud/python-sdk) to interact with the APIs.\n", | |
"\n", | |
"Once you add the SDK to your dependencies, just run the following code to convert your audio file (loading and recognition might be tweaked depending on file format and results requirements)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"from watson_developer_cloud import SpeechToTextV1\n", | |
"\n", | |
"# Instantiate the service using your credentials\n", | |
"service = SpeechToTextV1( \n", | |
" username='YOUR_SERVICE_USERNAME',\n", | |
" password='YOUR_SERVICE_PASSWORD'\n", | |
")\n", | |
"\n", | |
"# Load your audio file, feed it to the service and store the results\n", | |
"with open(\"talk.ogg\", 'rb') as audio_file:\n", | |
" res = service.recognize(audio_file, content_type='audio/ogg;codecs=opus',\n", | |
" continuous=True, word_confidence=True, timestamps=True,\n", | |
" interim_results=False)\n", | |
"\n", | |
"# Locally save the results for later use\n", | |
"with open(\"speech_to_text_res.txt\", 'w+') as f:\n", | |
" f.write(json.dumps(res))\n", | |
"#print(json.dumps(res['results'][0]['alternatives'][0], indent=2))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Text Analysis" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"# Load previously saved speech-to-text results\n", | |
"with open(\"speech_to_text_res.txt\", 'r') as f:\n", | |
" res = json.load(f)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 7, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>word</th>\n", | |
" <th>time_start</th>\n", | |
" <th>time_end</th>\n", | |
" <th>confidence</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>0</th>\n", | |
" <td>everyone</td>\n", | |
" <td>0.13</td>\n", | |
" <td>0.47</td>\n", | |
" <td>0.218784</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>for</td>\n", | |
" <td>0.47</td>\n", | |
" <td>0.64</td>\n", | |
" <td>0.553535</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2</th>\n", | |
" <td>being</td>\n", | |
" <td>0.64</td>\n", | |
" <td>0.92</td>\n", | |
" <td>0.520986</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>3</th>\n", | |
" <td>here</td>\n", | |
" <td>0.92</td>\n", | |
" <td>1.30</td>\n", | |
" <td>0.515787</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>4</th>\n", | |
" <td>as</td>\n", | |
" <td>1.34</td>\n", | |
" <td>1.61</td>\n", | |
" <td>0.734724</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" word time_start time_end confidence\n", | |
"0 everyone 0.13 0.47 0.218784\n", | |
"1 for 0.47 0.64 0.553535\n", | |
"2 being 0.64 0.92 0.520986\n", | |
"3 here 0.92 1.30 0.515787\n", | |
"4 as 1.34 1.61 0.734724" | |
] | |
}, | |
"execution_count": 7, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# There is some useful data provided by the Watson service, so we might be interested\n", | |
"# in extracting and storing our results in a handy Pandas dataframe\n", | |
"dfs = []\n", | |
"# For some reasons results are chunked, so we loop on all and extract our data\n", | |
"# Each recognized word is accompanied by a start and end time, as weel as a confidence level\n", | |
"for r in res['results']:\n", | |
" df = pd.DataFrame(r['alternatives'][0]['timestamps'], columns=['word', 'time_start', 'time_end'])\n", | |
" df['confidence'] = [x[1] for x in r['alternatives'][0]['word_confidence']]\n", | |
" dfs.append(df)\n", | |
"# Concatenate all results to obtain a single final dataframe\n", | |
"df = pd.concat(dfs, ignore_index=True)\n", | |
"df.to_csv('text_df.csv', index=False)\n", | |
"df.head()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 8, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>time_start</th>\n", | |
" <th>time_end</th>\n", | |
" <th>confidence</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>count</th>\n", | |
" <td>3358.000000</td>\n", | |
" <td>3358.000000</td>\n", | |
" <td>3358.000000</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>mean</th>\n", | |
" <td>637.831525</td>\n", | |
" <td>638.117996</td>\n", | |
" <td>0.503846</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>std</th>\n", | |
" <td>379.092845</td>\n", | |
" <td>379.099976</td>\n", | |
" <td>0.312730</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>min</th>\n", | |
" <td>0.130000</td>\n", | |
" <td>0.470000</td>\n", | |
" <td>0.004485</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>25%</th>\n", | |
" <td>309.047500</td>\n", | |
" <td>309.670000</td>\n", | |
" <td>0.229432</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>50%</th>\n", | |
" <td>633.185000</td>\n", | |
" <td>633.535000</td>\n", | |
" <td>0.453840</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>75%</th>\n", | |
" <td>962.402500</td>\n", | |
" <td>962.545000</td>\n", | |
" <td>0.788363</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>max</th>\n", | |
" <td>1309.870000</td>\n", | |
" <td>1310.300000</td>\n", | |
" <td>1.000000</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" time_start time_end confidence\n", | |
"count 3358.000000 3358.000000 3358.000000\n", | |
"mean 637.831525 638.117996 0.503846\n", | |
"std 379.092845 379.099976 0.312730\n", | |
"min 0.130000 0.470000 0.004485\n", | |
"25% 309.047500 309.670000 0.229432\n", | |
"50% 633.185000 633.535000 0.453840\n", | |
"75% 962.402500 962.545000 0.788363\n", | |
"max 1309.870000 1310.300000 1.000000" | |
] | |
}, | |
"execution_count": 8, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"df.describe()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 9, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"# Compute some basic stats\n", | |
"\n", | |
"# First let's remove the %HESITATION entries and keep a clean speech dataframe\n", | |
"clean_df = df[df['word']!='%HESITATION']\n", | |
"words = clean_df['word'].values\n", | |
"total_minutes = df['time_end'].values[-1]/60\n", | |
"transcript = \" \".join(words)\n", | |
"tokens_count = len(words)\n", | |
"speech_rate = tokens_count/total_minutes\n", | |
"types_count = len(set(words))\n", | |
"lexical_richness = (types_count/tokens_count)*100" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 10, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Here a summary of the conversation. Overall 3315 words have been said, of which 951 unique ones, \n", | |
"giving a lexical richness of 28.69%. \n", | |
"With the talk total duration of 21.8 minutes, the speech rate is of 152 Words Per Minute (WPM).\n" | |
] | |
} | |
], | |
"source": [ | |
"summary = \"\"\"Here a summary of the conversation. Overall {} words have been said, of which {} unique ones, \n", | |
"giving a lexical richness of {:.2f}%. \n", | |
"With the talk total duration of {:.1f} minutes, the speech rate is of {:.0f} Words Per Minute (WPM).\"\"\".format(tokens_count,\n", | |
" types_count, lexical_richness, total_minutes, speech_rate)\n", | |
"print(summary)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 11, | |
"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 = $('<div/>');\n", | |
" this._root_extra_style(this.root)\n", | |
" this.root.attr('style', 'display: inline-block');\n", | |
"\n", | |
" $(parent_element).append(this.root);\n", | |
"\n", | |
" this._init_header(this);\n", | |
" this._init_canvas(this);\n", | |
" this._init_toolbar(this);\n", | |
"\n", | |
" var fig = this;\n", | |
"\n", | |
" this.waiting = false;\n", | |
"\n", | |
" this.ws.onopen = function () {\n", | |
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", | |
" fig.send_message(\"send_image_mode\", {});\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" }\n", | |
"\n", | |
" this.imageObj.onload = function() {\n", | |
" if (fig.image_mode == 'full') {\n", | |
" // Full images could contain transparency (where diff images\n", | |
" // almost always do), so we need to clear the canvas so that\n", | |
" // there is no ghosting.\n", | |
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", | |
" }\n", | |
" fig.context.drawImage(fig.imageObj, 0, 0);\n", | |
" };\n", | |
"\n", | |
" this.imageObj.onunload = function() {\n", | |
" 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", | |
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n", | |
" 'ui-helper-clearfix\"/>');\n", | |
" var titletext = $(\n", | |
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n", | |
" 'text-align: center; padding: 3px;\"/>');\n", | |
" titlebar.append(titletext)\n", | |
" this.root.append(titlebar);\n", | |
" this.header = titletext[0];\n", | |
"}\n", | |
"\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_canvas = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var canvas_div = $('<div/>');\n", | |
"\n", | |
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", | |
"\n", | |
" function canvas_keyboard_event(event) {\n", | |
" return fig.key_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" canvas_div.keydown('key_press', canvas_keyboard_event);\n", | |
" canvas_div.keyup('key_release', canvas_keyboard_event);\n", | |
" this.canvas_div = canvas_div\n", | |
" this._canvas_extra_style(canvas_div)\n", | |
" this.root.append(canvas_div);\n", | |
"\n", | |
" var canvas = $('<canvas/>');\n", | |
" canvas.addClass('mpl-canvas');\n", | |
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", | |
"\n", | |
" this.canvas = canvas[0];\n", | |
" this.context = canvas[0].getContext(\"2d\");\n", | |
"\n", | |
" var rubberband = $('<canvas/>');\n", | |
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", | |
"\n", | |
" var pass_mouse_events = true;\n", | |
"\n", | |
" canvas_div.resizable({\n", | |
" start: function(event, ui) {\n", | |
" pass_mouse_events = false;\n", | |
" },\n", | |
" resize: function(event, ui) {\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" stop: function(event, ui) {\n", | |
" pass_mouse_events = true;\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" });\n", | |
"\n", | |
" function mouse_event_fn(event) {\n", | |
" if (pass_mouse_events)\n", | |
" return fig.mouse_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" rubberband.mousedown('button_press', mouse_event_fn);\n", | |
" rubberband.mouseup('button_release', mouse_event_fn);\n", | |
" // Throttle sequential mouse events to 1 every 20ms.\n", | |
" rubberband.mousemove('motion_notify', mouse_event_fn);\n", | |
"\n", | |
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n", | |
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n", | |
"\n", | |
" canvas_div.on(\"wheel\", function (event) {\n", | |
" event = event.originalEvent;\n", | |
" event['data'] = 'scroll'\n", | |
" if (event.deltaY < 0) {\n", | |
" event.step = 1;\n", | |
" } else {\n", | |
" event.step = -1;\n", | |
" }\n", | |
" mouse_event_fn(event);\n", | |
" });\n", | |
"\n", | |
" canvas_div.append(canvas);\n", | |
" canvas_div.append(rubberband);\n", | |
"\n", | |
" this.rubberband = rubberband;\n", | |
" this.rubberband_canvas = rubberband[0];\n", | |
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n", | |
" this.rubberband_context.strokeStyle = \"#000000\";\n", | |
"\n", | |
" this._resize_canvas = function(width, height) {\n", | |
" // Keep the size of the canvas, canvas container, and rubber band\n", | |
" // canvas in synch.\n", | |
" canvas_div.css('width', width)\n", | |
" canvas_div.css('height', height)\n", | |
"\n", | |
" canvas.attr('width', width);\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 = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items) {\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) {\n", | |
" // put a spacer in here.\n", | |
" continue;\n", | |
" }\n", | |
" var button = $('<button/>');\n", | |
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n", | |
" 'ui-button-icon-only');\n", | |
" button.attr('role', 'button');\n", | |
" button.attr('aria-disabled', 'false');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
"\n", | |
" var icon_img = $('<span/>');\n", | |
" icon_img.addClass('ui-button-icon-primary ui-icon');\n", | |
" icon_img.addClass(image);\n", | |
" icon_img.addClass('ui-corner-all');\n", | |
"\n", | |
" var tooltip_span = $('<span/>');\n", | |
" tooltip_span.addClass('ui-button-text');\n", | |
" tooltip_span.html(tooltip);\n", | |
"\n", | |
" button.append(icon_img);\n", | |
" button.append(tooltip_span);\n", | |
"\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" var fmt_picker_span = $('<span/>');\n", | |
"\n", | |
" var fmt_picker = $('<select/>');\n", | |
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n", | |
" fmt_picker_span.append(fmt_picker);\n", | |
" nav_element.append(fmt_picker_span);\n", | |
" this.format_dropdown = fmt_picker[0];\n", | |
"\n", | |
" for (var ind in mpl.extensions) {\n", | |
" var fmt = mpl.extensions[ind];\n", | |
" var option = $(\n", | |
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n", | |
" fmt_picker.append(option)\n", | |
" }\n", | |
"\n", | |
" // Add hover states to the ui-buttons\n", | |
" $( \".ui-button\" ).hover(\n", | |
" function() { $(this).addClass(\"ui-state-hover\");},\n", | |
" function() { $(this).removeClass(\"ui-state-hover\");}\n", | |
" );\n", | |
"\n", | |
" var status_bar = $('<span class=\"mpl-message\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n", | |
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", | |
" // which will in turn request a refresh of the image.\n", | |
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_message = function(type, properties) {\n", | |
" properties['type'] = type;\n", | |
" properties['figure_id'] = this.id;\n", | |
" this.ws.send(JSON.stringify(properties));\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_draw_message = function() {\n", | |
" if (!this.waiting) {\n", | |
" this.waiting = true;\n", | |
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" var format_dropdown = fig.format_dropdown;\n", | |
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", | |
" fig.ondownload(fig, format);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n", | |
" var size = msg['size'];\n", | |
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n", | |
" fig._resize_canvas(size[0], size[1]);\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n", | |
" var x0 = msg['x0'];\n", | |
" var y0 = fig.canvas.height - msg['y0'];\n", | |
" var x1 = msg['x1'];\n", | |
" var y1 = fig.canvas.height - msg['y1'];\n", | |
" x0 = Math.floor(x0) + 0.5;\n", | |
" y0 = Math.floor(y0) + 0.5;\n", | |
" x1 = Math.floor(x1) + 0.5;\n", | |
" y1 = Math.floor(y1) + 0.5;\n", | |
" var min_x = Math.min(x0, x1);\n", | |
" var min_y = Math.min(y0, y1);\n", | |
" var width = Math.abs(x1 - x0);\n", | |
" var height = Math.abs(y1 - y0);\n", | |
"\n", | |
" fig.rubberband_context.clearRect(\n", | |
" 0, 0, fig.canvas.width, fig.canvas.height);\n", | |
"\n", | |
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n", | |
" // Updates the figure title.\n", | |
" fig.header.textContent = msg['label'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n", | |
" var cursor = msg['cursor'];\n", | |
" switch(cursor)\n", | |
" {\n", | |
" case 0:\n", | |
" cursor = 'pointer';\n", | |
" break;\n", | |
" case 1:\n", | |
" cursor = 'default';\n", | |
" break;\n", | |
" case 2:\n", | |
" cursor = 'crosshair';\n", | |
" break;\n", | |
" case 3:\n", | |
" cursor = 'move';\n", | |
" break;\n", | |
" }\n", | |
" fig.rubberband_canvas.style.cursor = cursor;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_message = function(fig, msg) {\n", | |
" fig.message.textContent = msg['message'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n", | |
" // Request the server to send over a new figure.\n", | |
" fig.send_draw_message();\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n", | |
" fig.image_mode = msg['mode'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Called whenever the canvas gets updated.\n", | |
" this.send_message(\"ack\", {});\n", | |
"}\n", | |
"\n", | |
"// A function to construct a web socket function for onmessage handling.\n", | |
"// Called in the figure constructor.\n", | |
"mpl.figure.prototype._make_on_message_function = function(fig) {\n", | |
" return function socket_on_message(evt) {\n", | |
" if (evt.data instanceof Blob) {\n", | |
" /* FIXME: We get \"Resource interpreted as Image but\n", | |
" * transferred with MIME type text/plain:\" errors on\n", | |
" * Chrome. But how to set the MIME type? It doesn't seem\n", | |
" * to be part of the websocket stream */\n", | |
" evt.data.type = \"image/png\";\n", | |
"\n", | |
" /* Free the memory for the previous frames */\n", | |
" if (fig.imageObj.src) {\n", | |
" (window.URL || window.webkitURL).revokeObjectURL(\n", | |
" fig.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", | |
" evt.data);\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n", | |
" fig.imageObj.src = evt.data;\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var msg = JSON.parse(evt.data);\n", | |
" var msg_type = msg['type'];\n", | |
"\n", | |
" // Call the \"handle_{type}\" callback, which takes\n", | |
" // the figure and JSON message as its only arguments.\n", | |
" try {\n", | |
" var callback = fig[\"handle_\" + msg_type];\n", | |
" } catch (e) {\n", | |
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" if (callback) {\n", | |
" try {\n", | |
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", | |
" callback(fig, msg);\n", | |
" } catch (e) {\n", | |
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n", | |
" }\n", | |
" }\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", | |
"mpl.findpos = function(e) {\n", | |
" //this section is from http://www.quirksmode.org/js/events_properties.html\n", | |
" var targ;\n", | |
" if (!e)\n", | |
" e = window.event;\n", | |
" if (e.target)\n", | |
" targ = e.target;\n", | |
" else if (e.srcElement)\n", | |
" targ = e.srcElement;\n", | |
" if (targ.nodeType == 3) // defeat Safari bug\n", | |
" targ = targ.parentNode;\n", | |
"\n", | |
" // jQuery normalizes the pageX and pageY\n", | |
" // pageX,Y are the mouse positions relative to the document\n", | |
" // offset() returns the position of the element relative to the document\n", | |
" var x = e.pageX - $(targ).offset().left;\n", | |
" var y = e.pageY - $(targ).offset().top;\n", | |
"\n", | |
" return {\"x\": x, \"y\": y};\n", | |
"};\n", | |
"\n", | |
"/*\n", | |
" * return a copy of an object with only non-object keys\n", | |
" * we need this to avoid circular references\n", | |
" * http://stackoverflow.com/a/24161582/3208463\n", | |
" */\n", | |
"function simpleKeys (original) {\n", | |
" return Object.keys(original).reduce(function (obj, key) {\n", | |
" if (typeof original[key] !== 'object')\n", | |
" obj[key] = original[key]\n", | |
" return obj;\n", | |
" }, {});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.mouse_event = function(event, name) {\n", | |
" var canvas_pos = mpl.findpos(event)\n", | |
"\n", | |
" if (name === 'button_press')\n", | |
" {\n", | |
" this.canvas.focus();\n", | |
" this.canvas_div.focus();\n", | |
" }\n", | |
"\n", | |
" var x = canvas_pos.x;\n", | |
" var y = canvas_pos.y;\n", | |
"\n", | |
" this.send_message(name, {x: x, y: y, button: event.button,\n", | |
" step: event.step,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
"\n", | |
" /* This prevents the web browser from automatically changing to\n", | |
" * the text insertion cursor when the button is pressed. We want\n", | |
" * to control all of the cursor setting manually through the\n", | |
" * 'cursor' event from matplotlib */\n", | |
" event.preventDefault();\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" // Handle any extra behaviour associated with a key event\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.key_event = function(event, name) {\n", | |
"\n", | |
" // Prevent repeat events\n", | |
" if (name == 'key_press')\n", | |
" {\n", | |
" if (event.which === this._key)\n", | |
" return;\n", | |
" else\n", | |
" this._key = event.which;\n", | |
" }\n", | |
" if (name == 'key_release')\n", | |
" this._key = null;\n", | |
"\n", | |
" var value = '';\n", | |
" if (event.ctrlKey && event.which != 17)\n", | |
" value += \"ctrl+\";\n", | |
" if (event.altKey && event.which != 18)\n", | |
" value += \"alt+\";\n", | |
" if (event.shiftKey && event.which != 16)\n", | |
" value += \"shift+\";\n", | |
"\n", | |
" value += 'k';\n", | |
" value += event.which.toString();\n", | |
"\n", | |
" this._key_event_extra(event, name);\n", | |
"\n", | |
" this.send_message(name, {key: value,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n", | |
" if (name == 'download') {\n", | |
" this.handle_save(this, null);\n", | |
" } else {\n", | |
" this.send_message(\"toolbar_button\", {name: name});\n", | |
" }\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", | |
" this.message.textContent = tooltip;\n", | |
"};\n", | |
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", | |
"\n", | |
"mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", | |
"\n", | |
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n", | |
" // Create a \"websocket\"-like object which calls the given IPython comm\n", | |
" // object with the appropriate methods. Currently this is a non binary\n", | |
" // socket, so there is still some room for performance tuning.\n", | |
" var ws = {};\n", | |
"\n", | |
" ws.close = function() {\n", | |
" comm.close()\n", | |
" };\n", | |
" ws.send = function(m) {\n", | |
" //console.log('sending', m);\n", | |
" comm.send(m);\n", | |
" };\n", | |
" // Register the callback with on_msg.\n", | |
" comm.on_msg(function(msg) {\n", | |
" //console.log('receiving', msg['content']['data'], msg);\n", | |
" // Pass the mpl event to the overriden (by mpl) onmessage function.\n", | |
" ws.onmessage(msg['content']['data'])\n", | |
" });\n", | |
" return ws;\n", | |
"}\n", | |
"\n", | |
"mpl.mpl_figure_comm = function(comm, msg) {\n", | |
" // This is the function which gets called when the mpl process\n", | |
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n", | |
"\n", | |
" var id = msg.content.data.id;\n", | |
" // Get hold of the div created by the display call when the Comm\n", | |
" // socket was opened in Python.\n", | |
" var element = $(\"#\" + id);\n", | |
" var ws_proxy = comm_websocket_adapter(comm)\n", | |
"\n", | |
" function ondownload(figure, format) {\n", | |
" window.open(figure.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" var fig = new mpl.figure(id, ws_proxy,\n", | |
" ondownload,\n", | |
" element.get(0));\n", | |
"\n", | |
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", | |
" // web socket which is closed, not our websocket->open comm proxy.\n", | |
" ws_proxy.onopen();\n", | |
"\n", | |
" fig.parent_element = element.get(0);\n", | |
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n", | |
" if (!fig.cell_info) {\n", | |
" console.error(\"Failed to find cell for figure\", id, fig);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var output_index = fig.cell_info[2]\n", | |
" var cell = fig.cell_info[0];\n", | |
"\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.handle_close = function(fig, msg) {\n", | |
" fig.root.unbind('remove')\n", | |
"\n", | |
" // Update the output cell to use the data from the current canvas.\n", | |
" fig.push_to_output();\n", | |
" var dataURL = fig.canvas.toDataURL();\n", | |
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n", | |
" // the notebook keyboard shortcuts fail.\n", | |
" IPython.keyboard_manager.enable()\n", | |
" $(fig.parent_element).html('<img src=\"' + dataURL + '\">');\n", | |
" fig.close_ws(fig, msg);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.close_ws = function(fig, msg){\n", | |
" fig.send_message('closing', msg);\n", | |
" // fig.ws.close()\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", | |
" // Turn the data on the canvas into data in the output cell.\n", | |
" var dataURL = this.canvas.toDataURL();\n", | |
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Tell IPython that the notebook contents must change.\n", | |
" IPython.notebook.set_dirty(true);\n", | |
" this.send_message(\"ack\", {});\n", | |
" var fig = this;\n", | |
" // Wait a second, then push the new image to the DOM so\n", | |
" // that it is saved nicely (might be nice to debounce this).\n", | |
" setTimeout(function () { fig.push_to_output() }, 1000);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_toolbar = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var nav_element = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items){\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) { continue; };\n", | |
"\n", | |
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" // Add the status bar.\n", | |
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"\n", | |
" // Add the close button to the window.\n", | |
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", | |
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", | |
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n", | |
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n", | |
" buttongrp.append(button);\n", | |
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", | |
" titlebar.prepend(buttongrp);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(el){\n", | |
" var fig = this\n", | |
" el.on(\"remove\", function(){\n", | |
"\tfig.close_ws(fig, {});\n", | |
" });\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(el){\n", | |
" // this is important to make the div 'focusable\n", | |
" el.attr('tabindex', 0)\n", | |
" // reach out to IPython and tell the keyboard manager to turn it's self\n", | |
" // off when our div gets focus\n", | |
"\n", | |
" // location in version 3\n", | |
" if (IPython.notebook.keyboard_manager) {\n", | |
" IPython.notebook.keyboard_manager.register_events(el);\n", | |
" }\n", | |
" else {\n", | |
" // location in version 2\n", | |
" IPython.keyboard_manager.register_events(el);\n", | |
" }\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" var manager = IPython.notebook.keyboard_manager;\n", | |
" if (!manager)\n", | |
" manager = IPython.keyboard_manager;\n", | |
"\n", | |
" // Check for shift+enter\n", | |
" if (event.shiftKey && event.which == 13) {\n", | |
" this.canvas_div.blur();\n", | |
" event.shiftKey = false;\n", | |
" // Send a \"J\" for go to next cell\n", | |
" event.which = 74;\n", | |
" event.keyCode = 74;\n", | |
" manager.command_mode();\n", | |
" manager.handle_keydown(event);\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" fig.ondownload(fig, null);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.find_output_cell = function(html_output) {\n", | |
" // Return the cell and output element which can be found *uniquely* in the notebook.\n", | |
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", | |
" // IPython event is triggered only after the cells have been serialised, which for\n", | |
" // our purposes (turning an active figure into a static one), is too late.\n", | |
" var cells = IPython.notebook.get_cells();\n", | |
" var ncells = cells.length;\n", | |
" for (var i=0; i<ncells; i++) {\n", | |
" var cell = cells[i];\n", | |
" if (cell.cell_type === 'code'){\n", | |
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n", | |
" var data = cell.output_area.outputs[j];\n", | |
" if (data.data) {\n", | |
" // IPython >= 3 moved mimebundle to data attribute of output\n", | |
" data = data.data;\n", | |
" }\n", | |
" if (data['text/html'] == html_output) {\n", | |
" return [cell, data, j];\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"// Register the function which deals with the matplotlib target/channel.\n", | |
"// The kernel may be null if the page has been refreshed.\n", | |
"if (IPython.notebook.kernel != null) {\n", | |
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", | |
"}\n" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/html": [ | |
"<img src=\"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAzYAAAESCAYAAAAv7UBIAAAgAElEQVR4nO3deXRUV57g+efKzKrqyuqsyqp0k4kXtNzf/adPnjzTp2q6Zmqqaqqrp7PGZQze0vuSdjrttNNLsph9MTZmNxizeMPYGIwBY5AEktAutC9ISEggCUkIrRHsyumucVc65zd/EJIlIYUkpBdXSN/vOZ9jwIp4TyHd0L16Ee95HhERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERER0dhIRNZba+/o8fdXRWS153meMeZWETlqrc01xjzibi+JiIiIiIj671sisktEGroWNtban4hIftfCRkS2GmP+xvO8b1trcz3P+47LHSYiIiIiIupVVFTUH8fExPyTMWaxtfYOY8wficg+Y8xPeyxsCro+XkS2Wmt/4m6PiYiIiIiIBsgYs0RE/kVE1sTExPyVMeYfeixsiro+zlq7LjY29m/d7SkREREREdEA9VjYnLTWZohIuYicNcZMFZH8ro8TkfdiYmJ+PND9fPXV7/Trr38PAACAcSwyM1Si68gYs6TnyQN6HrExxrwfeo/Nd0KLnAHfY3Pu3G8VAAAA45v/s1Oi66zrPTY9/t69sImOjp4iIlnW2mJjzKPh7sf1IAMAAID//J6bEjnP9SADAACA/1zPOYl8z/UgAwAAgP9czzmJfM/1IAMAAID/XM85iXzP9SADAACA/1zPOYl8z/UgAwAAgP9czzmJfM/1IAMAAID/XM85iXzP9SADAACA/1zPOYl8z/UgAwAAgP9czzmJfM/1IAMAAID/XM85iXzP9SADAACA/1zPOYl8z/UgAwAAgP9czzmJfM/1IAMAAID/XM85iXzP9SADAACA/1zPOYl8z/UgAwAAgP9czzmJfM/1IAMAAID/XM85iXzP9SADAACA/1zPOYl8z/UgAwAAgP9czzmJfM/1IAMAAID/XM85iXzP9SADAACA/1zPOYl8z/UgAwAAgP9czzmJfM/1IAMAAID/XM85iXzP9SADAACA/1zPOYl8z/Ug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I8oRKfT1X2yMWRuBbXWPd7l6tPyw533zOYde4jTaj0N/j/d9PRc2oUXUT0QkzvM8LzY29h+7nn9GutDtu7ARkcv9PdeIyG5r7UFr7S3e1SMaQ34eDi1s1ofu5zkRWRQbG/tA6HP5W2vtf7XWzjTGPBX6mAXGmL/p7+eNiJRNnjz5T2JjY28Tkbro6OhJIjI79P8ekquv7nhbRP5z6HOYaoz5T4M8DNd8DURklrX2YGgf/1FEsowx/1FEfh7ap3mjeeS8z+e/0Fr7P0P7H9vjZ+01i7rRKszPXM9aW9LP47xgNLdPNO4Tkf/LXn0t+VERiTfGzOmzsHn8tttumxz6rUyaiKRGamHj9xEbz/O82NjYf+7xW5Ku9xcUdR1et1ff61EkIm9ba5NGc9uhlzlU9XkS7TpiEy8ihXL1dcdlnud9S0RWdf3AjdA+3GOtzbHWlhpjXhnN7fYtJibm/xCR8tBvcJcYY5aHfsOYP4QflqNWf+MhEtsNfR1OWGt/3fd7MFJ1HbHp8XVYHKltT5ky5Ueh384etdZ+bq19JoILm9Whl+j0Hfu+v7k39D32aGhS/T+MMd8zxjzfNe66JqWRyFr7eOjrfyI2Nvaf/dxWP+P9V30/Zz8eh/4e775HbEIvP8oVkfzQAiMvdNvPrLWbrnfbfRY2z5ur7yW85rkm9P6Toz32ecjPw6ExfNhefY/N/tARoH0ikm2tzbjtttsmh95jEidXjwB9HNpGXN+fN6Gfh2USOqIUuv8doXGSaq2NCY3bw/bqe9Xih/KLt75fgylTpvyo7+MdellY1/0m3HLLLX95vY973/p+/qE/F/X43L/d36JjFLc/4M/cHv/t9TiP5vaJaJxnrb2j6zW2REREREREN1wi8mTot0Pfc70vRERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERERErvr/ATW1usuwr+ERAAAAAElFTkSuQmCC\">" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"# Most common N-grams\n", | |
"words_count = Counter(words)\n", | |
"most_common_words = words_count.most_common(20)\n", | |
"most_common_bigrams = Counter(nltk.bigrams(words)).most_common(5)\n", | |
"most_common_trigrams = Counter(nltk.trigrams(words)).most_common(5)\n", | |
"\n", | |
"# Plot most common words\n", | |
"words, count = zip(*most_common_words)\n", | |
"sns.pointplot(x=words, y=count)\n", | |
"plt.show()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 12, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"['see', 'know', 'mean', 'us', 'get', 'yeah', 'like', 'go', 'example', 'data']\n" | |
] | |
} | |
], | |
"source": [ | |
"# Get most relevant words using TF-IDF\n", | |
"# For this statistic we need additional pieces of text to compare with our speech transcript\n", | |
"# we can simply load some corpora from NLTK \n", | |
"\n", | |
"from sklearn.feature_extraction.text import TfidfVectorizer\n", | |
"from nltk.corpus import stopwords\n", | |
"\n", | |
"# Load corpora for different genres\n", | |
"c1 = nltk.corpus.gutenberg.raw('carroll-alice.txt')\n", | |
"c2 = nltk.corpus.inaugural.raw(\"2009-Obama.txt\")\n", | |
"c3 = nltk.corpus.webtext.raw(\"firefox.txt\")\n", | |
"# Load english stopwords\n", | |
"stops = set(stopwords.words(\"english\"))\n", | |
"\n", | |
"# Compute TF-IDF matrix and print top results for our speech\n", | |
"vectorizer = TfidfVectorizer(analyzer='word',stop_words=stops)\n", | |
"tfIdf = vectorizer.fit_transform([transcript, c1, c2, c3]).toarray()\n", | |
"indices = np.argsort(tfIdf[0])[::-1]\n", | |
"features = vectorizer.get_feature_names()\n", | |
"top_features = [features[i] for i in indices[:10] if tfIdf[0][i]!=0]\n", | |
"print(top_features)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"## Alignments and Speech Rate" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 13, | |
"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 = $('<div/>');\n", | |
" this._root_extra_style(this.root)\n", | |
" this.root.attr('style', 'display: inline-block');\n", | |
"\n", | |
" $(parent_element).append(this.root);\n", | |
"\n", | |
" this._init_header(this);\n", | |
" this._init_canvas(this);\n", | |
" this._init_toolbar(this);\n", | |
"\n", | |
" var fig = this;\n", | |
"\n", | |
" this.waiting = false;\n", | |
"\n", | |
" this.ws.onopen = function () {\n", | |
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", | |
" fig.send_message(\"send_image_mode\", {});\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" }\n", | |
"\n", | |
" this.imageObj.onload = function() {\n", | |
" if (fig.image_mode == 'full') {\n", | |
" // Full images could contain transparency (where diff images\n", | |
" // almost always do), so we need to clear the canvas so that\n", | |
" // there is no ghosting.\n", | |
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", | |
" }\n", | |
" fig.context.drawImage(fig.imageObj, 0, 0);\n", | |
" };\n", | |
"\n", | |
" this.imageObj.onunload = function() {\n", | |
" 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", | |
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n", | |
" 'ui-helper-clearfix\"/>');\n", | |
" var titletext = $(\n", | |
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n", | |
" 'text-align: center; padding: 3px;\"/>');\n", | |
" titlebar.append(titletext)\n", | |
" this.root.append(titlebar);\n", | |
" this.header = titletext[0];\n", | |
"}\n", | |
"\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_canvas = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var canvas_div = $('<div/>');\n", | |
"\n", | |
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", | |
"\n", | |
" function canvas_keyboard_event(event) {\n", | |
" return fig.key_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" canvas_div.keydown('key_press', canvas_keyboard_event);\n", | |
" canvas_div.keyup('key_release', canvas_keyboard_event);\n", | |
" this.canvas_div = canvas_div\n", | |
" this._canvas_extra_style(canvas_div)\n", | |
" this.root.append(canvas_div);\n", | |
"\n", | |
" var canvas = $('<canvas/>');\n", | |
" canvas.addClass('mpl-canvas');\n", | |
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", | |
"\n", | |
" this.canvas = canvas[0];\n", | |
" this.context = canvas[0].getContext(\"2d\");\n", | |
"\n", | |
" var rubberband = $('<canvas/>');\n", | |
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", | |
"\n", | |
" var pass_mouse_events = true;\n", | |
"\n", | |
" canvas_div.resizable({\n", | |
" start: function(event, ui) {\n", | |
" pass_mouse_events = false;\n", | |
" },\n", | |
" resize: function(event, ui) {\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" stop: function(event, ui) {\n", | |
" pass_mouse_events = true;\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" });\n", | |
"\n", | |
" function mouse_event_fn(event) {\n", | |
" if (pass_mouse_events)\n", | |
" return fig.mouse_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" rubberband.mousedown('button_press', mouse_event_fn);\n", | |
" rubberband.mouseup('button_release', mouse_event_fn);\n", | |
" // Throttle sequential mouse events to 1 every 20ms.\n", | |
" rubberband.mousemove('motion_notify', mouse_event_fn);\n", | |
"\n", | |
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n", | |
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n", | |
"\n", | |
" canvas_div.on(\"wheel\", function (event) {\n", | |
" event = event.originalEvent;\n", | |
" event['data'] = 'scroll'\n", | |
" if (event.deltaY < 0) {\n", | |
" event.step = 1;\n", | |
" } else {\n", | |
" event.step = -1;\n", | |
" }\n", | |
" mouse_event_fn(event);\n", | |
" });\n", | |
"\n", | |
" canvas_div.append(canvas);\n", | |
" canvas_div.append(rubberband);\n", | |
"\n", | |
" this.rubberband = rubberband;\n", | |
" this.rubberband_canvas = rubberband[0];\n", | |
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n", | |
" this.rubberband_context.strokeStyle = \"#000000\";\n", | |
"\n", | |
" this._resize_canvas = function(width, height) {\n", | |
" // Keep the size of the canvas, canvas container, and rubber band\n", | |
" // canvas in synch.\n", | |
" canvas_div.css('width', width)\n", | |
" canvas_div.css('height', height)\n", | |
"\n", | |
" canvas.attr('width', width);\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 = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items) {\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) {\n", | |
" // put a spacer in here.\n", | |
" continue;\n", | |
" }\n", | |
" var button = $('<button/>');\n", | |
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n", | |
" 'ui-button-icon-only');\n", | |
" button.attr('role', 'button');\n", | |
" button.attr('aria-disabled', 'false');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
"\n", | |
" var icon_img = $('<span/>');\n", | |
" icon_img.addClass('ui-button-icon-primary ui-icon');\n", | |
" icon_img.addClass(image);\n", | |
" icon_img.addClass('ui-corner-all');\n", | |
"\n", | |
" var tooltip_span = $('<span/>');\n", | |
" tooltip_span.addClass('ui-button-text');\n", | |
" tooltip_span.html(tooltip);\n", | |
"\n", | |
" button.append(icon_img);\n", | |
" button.append(tooltip_span);\n", | |
"\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" var fmt_picker_span = $('<span/>');\n", | |
"\n", | |
" var fmt_picker = $('<select/>');\n", | |
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n", | |
" fmt_picker_span.append(fmt_picker);\n", | |
" nav_element.append(fmt_picker_span);\n", | |
" this.format_dropdown = fmt_picker[0];\n", | |
"\n", | |
" for (var ind in mpl.extensions) {\n", | |
" var fmt = mpl.extensions[ind];\n", | |
" var option = $(\n", | |
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n", | |
" fmt_picker.append(option)\n", | |
" }\n", | |
"\n", | |
" // Add hover states to the ui-buttons\n", | |
" $( \".ui-button\" ).hover(\n", | |
" function() { $(this).addClass(\"ui-state-hover\");},\n", | |
" function() { $(this).removeClass(\"ui-state-hover\");}\n", | |
" );\n", | |
"\n", | |
" var status_bar = $('<span class=\"mpl-message\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n", | |
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", | |
" // which will in turn request a refresh of the image.\n", | |
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_message = function(type, properties) {\n", | |
" properties['type'] = type;\n", | |
" properties['figure_id'] = this.id;\n", | |
" this.ws.send(JSON.stringify(properties));\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_draw_message = function() {\n", | |
" if (!this.waiting) {\n", | |
" this.waiting = true;\n", | |
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" var format_dropdown = fig.format_dropdown;\n", | |
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", | |
" fig.ondownload(fig, format);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n", | |
" var size = msg['size'];\n", | |
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n", | |
" fig._resize_canvas(size[0], size[1]);\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n", | |
" var x0 = msg['x0'];\n", | |
" var y0 = fig.canvas.height - msg['y0'];\n", | |
" var x1 = msg['x1'];\n", | |
" var y1 = fig.canvas.height - msg['y1'];\n", | |
" x0 = Math.floor(x0) + 0.5;\n", | |
" y0 = Math.floor(y0) + 0.5;\n", | |
" x1 = Math.floor(x1) + 0.5;\n", | |
" y1 = Math.floor(y1) + 0.5;\n", | |
" var min_x = Math.min(x0, x1);\n", | |
" var min_y = Math.min(y0, y1);\n", | |
" var width = Math.abs(x1 - x0);\n", | |
" var height = Math.abs(y1 - y0);\n", | |
"\n", | |
" fig.rubberband_context.clearRect(\n", | |
" 0, 0, fig.canvas.width, fig.canvas.height);\n", | |
"\n", | |
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n", | |
" // Updates the figure title.\n", | |
" fig.header.textContent = msg['label'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n", | |
" var cursor = msg['cursor'];\n", | |
" switch(cursor)\n", | |
" {\n", | |
" case 0:\n", | |
" cursor = 'pointer';\n", | |
" break;\n", | |
" case 1:\n", | |
" cursor = 'default';\n", | |
" break;\n", | |
" case 2:\n", | |
" cursor = 'crosshair';\n", | |
" break;\n", | |
" case 3:\n", | |
" cursor = 'move';\n", | |
" break;\n", | |
" }\n", | |
" fig.rubberband_canvas.style.cursor = cursor;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_message = function(fig, msg) {\n", | |
" fig.message.textContent = msg['message'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n", | |
" // Request the server to send over a new figure.\n", | |
" fig.send_draw_message();\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n", | |
" fig.image_mode = msg['mode'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Called whenever the canvas gets updated.\n", | |
" this.send_message(\"ack\", {});\n", | |
"}\n", | |
"\n", | |
"// A function to construct a web socket function for onmessage handling.\n", | |
"// Called in the figure constructor.\n", | |
"mpl.figure.prototype._make_on_message_function = function(fig) {\n", | |
" return function socket_on_message(evt) {\n", | |
" if (evt.data instanceof Blob) {\n", | |
" /* FIXME: We get \"Resource interpreted as Image but\n", | |
" * transferred with MIME type text/plain:\" errors on\n", | |
" * Chrome. But how to set the MIME type? It doesn't seem\n", | |
" * to be part of the websocket stream */\n", | |
" evt.data.type = \"image/png\";\n", | |
"\n", | |
" /* Free the memory for the previous frames */\n", | |
" if (fig.imageObj.src) {\n", | |
" (window.URL || window.webkitURL).revokeObjectURL(\n", | |
" fig.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", | |
" evt.data);\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n", | |
" fig.imageObj.src = evt.data;\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var msg = JSON.parse(evt.data);\n", | |
" var msg_type = msg['type'];\n", | |
"\n", | |
" // Call the \"handle_{type}\" callback, which takes\n", | |
" // the figure and JSON message as its only arguments.\n", | |
" try {\n", | |
" var callback = fig[\"handle_\" + msg_type];\n", | |
" } catch (e) {\n", | |
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" if (callback) {\n", | |
" try {\n", | |
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", | |
" callback(fig, msg);\n", | |
" } catch (e) {\n", | |
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n", | |
" }\n", | |
" }\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", | |
"mpl.findpos = function(e) {\n", | |
" //this section is from http://www.quirksmode.org/js/events_properties.html\n", | |
" var targ;\n", | |
" if (!e)\n", | |
" e = window.event;\n", | |
" if (e.target)\n", | |
" targ = e.target;\n", | |
" else if (e.srcElement)\n", | |
" targ = e.srcElement;\n", | |
" if (targ.nodeType == 3) // defeat Safari bug\n", | |
" targ = targ.parentNode;\n", | |
"\n", | |
" // jQuery normalizes the pageX and pageY\n", | |
" // pageX,Y are the mouse positions relative to the document\n", | |
" // offset() returns the position of the element relative to the document\n", | |
" var x = e.pageX - $(targ).offset().left;\n", | |
" var y = e.pageY - $(targ).offset().top;\n", | |
"\n", | |
" return {\"x\": x, \"y\": y};\n", | |
"};\n", | |
"\n", | |
"/*\n", | |
" * return a copy of an object with only non-object keys\n", | |
" * we need this to avoid circular references\n", | |
" * http://stackoverflow.com/a/24161582/3208463\n", | |
" */\n", | |
"function simpleKeys (original) {\n", | |
" return Object.keys(original).reduce(function (obj, key) {\n", | |
" if (typeof original[key] !== 'object')\n", | |
" obj[key] = original[key]\n", | |
" return obj;\n", | |
" }, {});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.mouse_event = function(event, name) {\n", | |
" var canvas_pos = mpl.findpos(event)\n", | |
"\n", | |
" if (name === 'button_press')\n", | |
" {\n", | |
" this.canvas.focus();\n", | |
" this.canvas_div.focus();\n", | |
" }\n", | |
"\n", | |
" var x = canvas_pos.x;\n", | |
" var y = canvas_pos.y;\n", | |
"\n", | |
" this.send_message(name, {x: x, y: y, button: event.button,\n", | |
" step: event.step,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
"\n", | |
" /* This prevents the web browser from automatically changing to\n", | |
" * the text insertion cursor when the button is pressed. We want\n", | |
" * to control all of the cursor setting manually through the\n", | |
" * 'cursor' event from matplotlib */\n", | |
" event.preventDefault();\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" // Handle any extra behaviour associated with a key event\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.key_event = function(event, name) {\n", | |
"\n", | |
" // Prevent repeat events\n", | |
" if (name == 'key_press')\n", | |
" {\n", | |
" if (event.which === this._key)\n", | |
" return;\n", | |
" else\n", | |
" this._key = event.which;\n", | |
" }\n", | |
" if (name == 'key_release')\n", | |
" this._key = null;\n", | |
"\n", | |
" var value = '';\n", | |
" if (event.ctrlKey && event.which != 17)\n", | |
" value += \"ctrl+\";\n", | |
" if (event.altKey && event.which != 18)\n", | |
" value += \"alt+\";\n", | |
" if (event.shiftKey && event.which != 16)\n", | |
" value += \"shift+\";\n", | |
"\n", | |
" value += 'k';\n", | |
" value += event.which.toString();\n", | |
"\n", | |
" this._key_event_extra(event, name);\n", | |
"\n", | |
" this.send_message(name, {key: value,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n", | |
" if (name == 'download') {\n", | |
" this.handle_save(this, null);\n", | |
" } else {\n", | |
" this.send_message(\"toolbar_button\", {name: name});\n", | |
" }\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", | |
" this.message.textContent = tooltip;\n", | |
"};\n", | |
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", | |
"\n", | |
"mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", | |
"\n", | |
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n", | |
" // Create a \"websocket\"-like object which calls the given IPython comm\n", | |
" // object with the appropriate methods. Currently this is a non binary\n", | |
" // socket, so there is still some room for performance tuning.\n", | |
" var ws = {};\n", | |
"\n", | |
" ws.close = function() {\n", | |
" comm.close()\n", | |
" };\n", | |
" ws.send = function(m) {\n", | |
" //console.log('sending', m);\n", | |
" comm.send(m);\n", | |
" };\n", | |
" // Register the callback with on_msg.\n", | |
" comm.on_msg(function(msg) {\n", | |
" //console.log('receiving', msg['content']['data'], msg);\n", | |
" // Pass the mpl event to the overriden (by mpl) onmessage function.\n", | |
" ws.onmessage(msg['content']['data'])\n", | |
" });\n", | |
" return ws;\n", | |
"}\n", | |
"\n", | |
"mpl.mpl_figure_comm = function(comm, msg) {\n", | |
" // This is the function which gets called when the mpl process\n", | |
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n", | |
"\n", | |
" var id = msg.content.data.id;\n", | |
" // Get hold of the div created by the display call when the Comm\n", | |
" // socket was opened in Python.\n", | |
" var element = $(\"#\" + id);\n", | |
" var ws_proxy = comm_websocket_adapter(comm)\n", | |
"\n", | |
" function ondownload(figure, format) {\n", | |
" window.open(figure.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" var fig = new mpl.figure(id, ws_proxy,\n", | |
" ondownload,\n", | |
" element.get(0));\n", | |
"\n", | |
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", | |
" // web socket which is closed, not our websocket->open comm proxy.\n", | |
" ws_proxy.onopen();\n", | |
"\n", | |
" fig.parent_element = element.get(0);\n", | |
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n", | |
" if (!fig.cell_info) {\n", | |
" console.error(\"Failed to find cell for figure\", id, fig);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var output_index = fig.cell_info[2]\n", | |
" var cell = fig.cell_info[0];\n", | |
"\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.handle_close = function(fig, msg) {\n", | |
" fig.root.unbind('remove')\n", | |
"\n", | |
" // Update the output cell to use the data from the current canvas.\n", | |
" fig.push_to_output();\n", | |
" var dataURL = fig.canvas.toDataURL();\n", | |
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n", | |
" // the notebook keyboard shortcuts fail.\n", | |
" IPython.keyboard_manager.enable()\n", | |
" $(fig.parent_element).html('<img src=\"' + dataURL + '\">');\n", | |
" fig.close_ws(fig, msg);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.close_ws = function(fig, msg){\n", | |
" fig.send_message('closing', msg);\n", | |
" // fig.ws.close()\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", | |
" // Turn the data on the canvas into data in the output cell.\n", | |
" var dataURL = this.canvas.toDataURL();\n", | |
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Tell IPython that the notebook contents must change.\n", | |
" IPython.notebook.set_dirty(true);\n", | |
" this.send_message(\"ack\", {});\n", | |
" var fig = this;\n", | |
" // Wait a second, then push the new image to the DOM so\n", | |
" // that it is saved nicely (might be nice to debounce this).\n", | |
" setTimeout(function () { fig.push_to_output() }, 1000);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_toolbar = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var nav_element = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items){\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) { continue; };\n", | |
"\n", | |
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" // Add the status bar.\n", | |
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"\n", | |
" // Add the close button to the window.\n", | |
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", | |
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", | |
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n", | |
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n", | |
" buttongrp.append(button);\n", | |
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", | |
" titlebar.prepend(buttongrp);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(el){\n", | |
" var fig = this\n", | |
" el.on(\"remove\", function(){\n", | |
"\tfig.close_ws(fig, {});\n", | |
" });\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(el){\n", | |
" // this is important to make the div 'focusable\n", | |
" el.attr('tabindex', 0)\n", | |
" // reach out to IPython and tell the keyboard manager to turn it's self\n", | |
" // off when our div gets focus\n", | |
"\n", | |
" // location in version 3\n", | |
" if (IPython.notebook.keyboard_manager) {\n", | |
" IPython.notebook.keyboard_manager.register_events(el);\n", | |
" }\n", | |
" else {\n", | |
" // location in version 2\n", | |
" IPython.keyboard_manager.register_events(el);\n", | |
" }\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" var manager = IPython.notebook.keyboard_manager;\n", | |
" if (!manager)\n", | |
" manager = IPython.keyboard_manager;\n", | |
"\n", | |
" // Check for shift+enter\n", | |
" if (event.shiftKey && event.which == 13) {\n", | |
" this.canvas_div.blur();\n", | |
" event.shiftKey = false;\n", | |
" // Send a \"J\" for go to next cell\n", | |
" event.which = 74;\n", | |
" event.keyCode = 74;\n", | |
" manager.command_mode();\n", | |
" manager.handle_keydown(event);\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" fig.ondownload(fig, null);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.find_output_cell = function(html_output) {\n", | |
" // Return the cell and output element which can be found *uniquely* in the notebook.\n", | |
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", | |
" // IPython event is triggered only after the cells have been serialised, which for\n", | |
" // our purposes (turning an active figure into a static one), is too late.\n", | |
" var cells = IPython.notebook.get_cells();\n", | |
" var ncells = cells.length;\n", | |
" for (var i=0; i<ncells; i++) {\n", | |
" var cell = cells[i];\n", | |
" if (cell.cell_type === 'code'){\n", | |
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n", | |
" var data = cell.output_area.outputs[j];\n", | |
" if (data.data) {\n", | |
" // IPython >= 3 moved mimebundle to data attribute of output\n", | |
" data = data.data;\n", | |
" }\n", | |
" if (data['text/html'] == html_output) {\n", | |
" return [cell, data, j];\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"// Register the function which deals with the matplotlib target/channel.\n", | |
"// The kernel may be null if the page has been refreshed.\n", | |
"if (IPython.notebook.kernel != null) {\n", | |
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", | |
"}\n" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/html": [ | |
"<img src=\"data:image/png;base64,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\">" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"# Visualize words count distribution across time. Quick way to spot possible speech rate trend\n", | |
"ax = sns.distplot(clean_df['time_end'], kde=False, bins=10)\n", | |
"ax.set_xlabel('Time (seconds)')\n", | |
"plt.show()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 14, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"# More in dept analysis of speech trend\n", | |
"\n", | |
"# Bin the time_end entries and count word occurences for each bin\n", | |
"n_bins = 10\n", | |
"x_bins = np.arange(n_bins)\n", | |
"_, bins = pd.cut(clean_df['time_end'], bins=n_bins, retbins=True, right=False)\n", | |
"bins_word_count = clean_df['time_end'].groupby(np.digitize(clean_df['time_end'], bins)).count()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 15, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"Slope = -5.230 (r = -0.890, p = 0.00056)\n", | |
"Bin size= 2.184 minutes\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 = $('<div/>');\n", | |
" this._root_extra_style(this.root)\n", | |
" this.root.attr('style', 'display: inline-block');\n", | |
"\n", | |
" $(parent_element).append(this.root);\n", | |
"\n", | |
" this._init_header(this);\n", | |
" this._init_canvas(this);\n", | |
" this._init_toolbar(this);\n", | |
"\n", | |
" var fig = this;\n", | |
"\n", | |
" this.waiting = false;\n", | |
"\n", | |
" this.ws.onopen = function () {\n", | |
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", | |
" fig.send_message(\"send_image_mode\", {});\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" }\n", | |
"\n", | |
" this.imageObj.onload = function() {\n", | |
" if (fig.image_mode == 'full') {\n", | |
" // Full images could contain transparency (where diff images\n", | |
" // almost always do), so we need to clear the canvas so that\n", | |
" // there is no ghosting.\n", | |
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", | |
" }\n", | |
" fig.context.drawImage(fig.imageObj, 0, 0);\n", | |
" };\n", | |
"\n", | |
" this.imageObj.onunload = function() {\n", | |
" 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", | |
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n", | |
" 'ui-helper-clearfix\"/>');\n", | |
" var titletext = $(\n", | |
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n", | |
" 'text-align: center; padding: 3px;\"/>');\n", | |
" titlebar.append(titletext)\n", | |
" this.root.append(titlebar);\n", | |
" this.header = titletext[0];\n", | |
"}\n", | |
"\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_canvas = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var canvas_div = $('<div/>');\n", | |
"\n", | |
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", | |
"\n", | |
" function canvas_keyboard_event(event) {\n", | |
" return fig.key_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" canvas_div.keydown('key_press', canvas_keyboard_event);\n", | |
" canvas_div.keyup('key_release', canvas_keyboard_event);\n", | |
" this.canvas_div = canvas_div\n", | |
" this._canvas_extra_style(canvas_div)\n", | |
" this.root.append(canvas_div);\n", | |
"\n", | |
" var canvas = $('<canvas/>');\n", | |
" canvas.addClass('mpl-canvas');\n", | |
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", | |
"\n", | |
" this.canvas = canvas[0];\n", | |
" this.context = canvas[0].getContext(\"2d\");\n", | |
"\n", | |
" var rubberband = $('<canvas/>');\n", | |
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", | |
"\n", | |
" var pass_mouse_events = true;\n", | |
"\n", | |
" canvas_div.resizable({\n", | |
" start: function(event, ui) {\n", | |
" pass_mouse_events = false;\n", | |
" },\n", | |
" resize: function(event, ui) {\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" stop: function(event, ui) {\n", | |
" pass_mouse_events = true;\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" });\n", | |
"\n", | |
" function mouse_event_fn(event) {\n", | |
" if (pass_mouse_events)\n", | |
" return fig.mouse_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" rubberband.mousedown('button_press', mouse_event_fn);\n", | |
" rubberband.mouseup('button_release', mouse_event_fn);\n", | |
" // Throttle sequential mouse events to 1 every 20ms.\n", | |
" rubberband.mousemove('motion_notify', mouse_event_fn);\n", | |
"\n", | |
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n", | |
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n", | |
"\n", | |
" canvas_div.on(\"wheel\", function (event) {\n", | |
" event = event.originalEvent;\n", | |
" event['data'] = 'scroll'\n", | |
" if (event.deltaY < 0) {\n", | |
" event.step = 1;\n", | |
" } else {\n", | |
" event.step = -1;\n", | |
" }\n", | |
" mouse_event_fn(event);\n", | |
" });\n", | |
"\n", | |
" canvas_div.append(canvas);\n", | |
" canvas_div.append(rubberband);\n", | |
"\n", | |
" this.rubberband = rubberband;\n", | |
" this.rubberband_canvas = rubberband[0];\n", | |
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n", | |
" this.rubberband_context.strokeStyle = \"#000000\";\n", | |
"\n", | |
" this._resize_canvas = function(width, height) {\n", | |
" // Keep the size of the canvas, canvas container, and rubber band\n", | |
" // canvas in synch.\n", | |
" canvas_div.css('width', width)\n", | |
" canvas_div.css('height', height)\n", | |
"\n", | |
" canvas.attr('width', width);\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 = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items) {\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) {\n", | |
" // put a spacer in here.\n", | |
" continue;\n", | |
" }\n", | |
" var button = $('<button/>');\n", | |
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n", | |
" 'ui-button-icon-only');\n", | |
" button.attr('role', 'button');\n", | |
" button.attr('aria-disabled', 'false');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
"\n", | |
" var icon_img = $('<span/>');\n", | |
" icon_img.addClass('ui-button-icon-primary ui-icon');\n", | |
" icon_img.addClass(image);\n", | |
" icon_img.addClass('ui-corner-all');\n", | |
"\n", | |
" var tooltip_span = $('<span/>');\n", | |
" tooltip_span.addClass('ui-button-text');\n", | |
" tooltip_span.html(tooltip);\n", | |
"\n", | |
" button.append(icon_img);\n", | |
" button.append(tooltip_span);\n", | |
"\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" var fmt_picker_span = $('<span/>');\n", | |
"\n", | |
" var fmt_picker = $('<select/>');\n", | |
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n", | |
" fmt_picker_span.append(fmt_picker);\n", | |
" nav_element.append(fmt_picker_span);\n", | |
" this.format_dropdown = fmt_picker[0];\n", | |
"\n", | |
" for (var ind in mpl.extensions) {\n", | |
" var fmt = mpl.extensions[ind];\n", | |
" var option = $(\n", | |
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n", | |
" fmt_picker.append(option)\n", | |
" }\n", | |
"\n", | |
" // Add hover states to the ui-buttons\n", | |
" $( \".ui-button\" ).hover(\n", | |
" function() { $(this).addClass(\"ui-state-hover\");},\n", | |
" function() { $(this).removeClass(\"ui-state-hover\");}\n", | |
" );\n", | |
"\n", | |
" var status_bar = $('<span class=\"mpl-message\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n", | |
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", | |
" // which will in turn request a refresh of the image.\n", | |
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_message = function(type, properties) {\n", | |
" properties['type'] = type;\n", | |
" properties['figure_id'] = this.id;\n", | |
" this.ws.send(JSON.stringify(properties));\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_draw_message = function() {\n", | |
" if (!this.waiting) {\n", | |
" this.waiting = true;\n", | |
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" var format_dropdown = fig.format_dropdown;\n", | |
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", | |
" fig.ondownload(fig, format);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n", | |
" var size = msg['size'];\n", | |
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n", | |
" fig._resize_canvas(size[0], size[1]);\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n", | |
" var x0 = msg['x0'];\n", | |
" var y0 = fig.canvas.height - msg['y0'];\n", | |
" var x1 = msg['x1'];\n", | |
" var y1 = fig.canvas.height - msg['y1'];\n", | |
" x0 = Math.floor(x0) + 0.5;\n", | |
" y0 = Math.floor(y0) + 0.5;\n", | |
" x1 = Math.floor(x1) + 0.5;\n", | |
" y1 = Math.floor(y1) + 0.5;\n", | |
" var min_x = Math.min(x0, x1);\n", | |
" var min_y = Math.min(y0, y1);\n", | |
" var width = Math.abs(x1 - x0);\n", | |
" var height = Math.abs(y1 - y0);\n", | |
"\n", | |
" fig.rubberband_context.clearRect(\n", | |
" 0, 0, fig.canvas.width, fig.canvas.height);\n", | |
"\n", | |
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n", | |
" // Updates the figure title.\n", | |
" fig.header.textContent = msg['label'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n", | |
" var cursor = msg['cursor'];\n", | |
" switch(cursor)\n", | |
" {\n", | |
" case 0:\n", | |
" cursor = 'pointer';\n", | |
" break;\n", | |
" case 1:\n", | |
" cursor = 'default';\n", | |
" break;\n", | |
" case 2:\n", | |
" cursor = 'crosshair';\n", | |
" break;\n", | |
" case 3:\n", | |
" cursor = 'move';\n", | |
" break;\n", | |
" }\n", | |
" fig.rubberband_canvas.style.cursor = cursor;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_message = function(fig, msg) {\n", | |
" fig.message.textContent = msg['message'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n", | |
" // Request the server to send over a new figure.\n", | |
" fig.send_draw_message();\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n", | |
" fig.image_mode = msg['mode'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Called whenever the canvas gets updated.\n", | |
" this.send_message(\"ack\", {});\n", | |
"}\n", | |
"\n", | |
"// A function to construct a web socket function for onmessage handling.\n", | |
"// Called in the figure constructor.\n", | |
"mpl.figure.prototype._make_on_message_function = function(fig) {\n", | |
" return function socket_on_message(evt) {\n", | |
" if (evt.data instanceof Blob) {\n", | |
" /* FIXME: We get \"Resource interpreted as Image but\n", | |
" * transferred with MIME type text/plain:\" errors on\n", | |
" * Chrome. But how to set the MIME type? It doesn't seem\n", | |
" * to be part of the websocket stream */\n", | |
" evt.data.type = \"image/png\";\n", | |
"\n", | |
" /* Free the memory for the previous frames */\n", | |
" if (fig.imageObj.src) {\n", | |
" (window.URL || window.webkitURL).revokeObjectURL(\n", | |
" fig.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", | |
" evt.data);\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n", | |
" fig.imageObj.src = evt.data;\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var msg = JSON.parse(evt.data);\n", | |
" var msg_type = msg['type'];\n", | |
"\n", | |
" // Call the \"handle_{type}\" callback, which takes\n", | |
" // the figure and JSON message as its only arguments.\n", | |
" try {\n", | |
" var callback = fig[\"handle_\" + msg_type];\n", | |
" } catch (e) {\n", | |
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" if (callback) {\n", | |
" try {\n", | |
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", | |
" callback(fig, msg);\n", | |
" } catch (e) {\n", | |
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n", | |
" }\n", | |
" }\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", | |
"mpl.findpos = function(e) {\n", | |
" //this section is from http://www.quirksmode.org/js/events_properties.html\n", | |
" var targ;\n", | |
" if (!e)\n", | |
" e = window.event;\n", | |
" if (e.target)\n", | |
" targ = e.target;\n", | |
" else if (e.srcElement)\n", | |
" targ = e.srcElement;\n", | |
" if (targ.nodeType == 3) // defeat Safari bug\n", | |
" targ = targ.parentNode;\n", | |
"\n", | |
" // jQuery normalizes the pageX and pageY\n", | |
" // pageX,Y are the mouse positions relative to the document\n", | |
" // offset() returns the position of the element relative to the document\n", | |
" var x = e.pageX - $(targ).offset().left;\n", | |
" var y = e.pageY - $(targ).offset().top;\n", | |
"\n", | |
" return {\"x\": x, \"y\": y};\n", | |
"};\n", | |
"\n", | |
"/*\n", | |
" * return a copy of an object with only non-object keys\n", | |
" * we need this to avoid circular references\n", | |
" * http://stackoverflow.com/a/24161582/3208463\n", | |
" */\n", | |
"function simpleKeys (original) {\n", | |
" return Object.keys(original).reduce(function (obj, key) {\n", | |
" if (typeof original[key] !== 'object')\n", | |
" obj[key] = original[key]\n", | |
" return obj;\n", | |
" }, {});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.mouse_event = function(event, name) {\n", | |
" var canvas_pos = mpl.findpos(event)\n", | |
"\n", | |
" if (name === 'button_press')\n", | |
" {\n", | |
" this.canvas.focus();\n", | |
" this.canvas_div.focus();\n", | |
" }\n", | |
"\n", | |
" var x = canvas_pos.x;\n", | |
" var y = canvas_pos.y;\n", | |
"\n", | |
" this.send_message(name, {x: x, y: y, button: event.button,\n", | |
" step: event.step,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
"\n", | |
" /* This prevents the web browser from automatically changing to\n", | |
" * the text insertion cursor when the button is pressed. We want\n", | |
" * to control all of the cursor setting manually through the\n", | |
" * 'cursor' event from matplotlib */\n", | |
" event.preventDefault();\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" // Handle any extra behaviour associated with a key event\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.key_event = function(event, name) {\n", | |
"\n", | |
" // Prevent repeat events\n", | |
" if (name == 'key_press')\n", | |
" {\n", | |
" if (event.which === this._key)\n", | |
" return;\n", | |
" else\n", | |
" this._key = event.which;\n", | |
" }\n", | |
" if (name == 'key_release')\n", | |
" this._key = null;\n", | |
"\n", | |
" var value = '';\n", | |
" if (event.ctrlKey && event.which != 17)\n", | |
" value += \"ctrl+\";\n", | |
" if (event.altKey && event.which != 18)\n", | |
" value += \"alt+\";\n", | |
" if (event.shiftKey && event.which != 16)\n", | |
" value += \"shift+\";\n", | |
"\n", | |
" value += 'k';\n", | |
" value += event.which.toString();\n", | |
"\n", | |
" this._key_event_extra(event, name);\n", | |
"\n", | |
" this.send_message(name, {key: value,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n", | |
" if (name == 'download') {\n", | |
" this.handle_save(this, null);\n", | |
" } else {\n", | |
" this.send_message(\"toolbar_button\", {name: name});\n", | |
" }\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", | |
" this.message.textContent = tooltip;\n", | |
"};\n", | |
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", | |
"\n", | |
"mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", | |
"\n", | |
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n", | |
" // Create a \"websocket\"-like object which calls the given IPython comm\n", | |
" // object with the appropriate methods. Currently this is a non binary\n", | |
" // socket, so there is still some room for performance tuning.\n", | |
" var ws = {};\n", | |
"\n", | |
" ws.close = function() {\n", | |
" comm.close()\n", | |
" };\n", | |
" ws.send = function(m) {\n", | |
" //console.log('sending', m);\n", | |
" comm.send(m);\n", | |
" };\n", | |
" // Register the callback with on_msg.\n", | |
" comm.on_msg(function(msg) {\n", | |
" //console.log('receiving', msg['content']['data'], msg);\n", | |
" // Pass the mpl event to the overriden (by mpl) onmessage function.\n", | |
" ws.onmessage(msg['content']['data'])\n", | |
" });\n", | |
" return ws;\n", | |
"}\n", | |
"\n", | |
"mpl.mpl_figure_comm = function(comm, msg) {\n", | |
" // This is the function which gets called when the mpl process\n", | |
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n", | |
"\n", | |
" var id = msg.content.data.id;\n", | |
" // Get hold of the div created by the display call when the Comm\n", | |
" // socket was opened in Python.\n", | |
" var element = $(\"#\" + id);\n", | |
" var ws_proxy = comm_websocket_adapter(comm)\n", | |
"\n", | |
" function ondownload(figure, format) {\n", | |
" window.open(figure.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" var fig = new mpl.figure(id, ws_proxy,\n", | |
" ondownload,\n", | |
" element.get(0));\n", | |
"\n", | |
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", | |
" // web socket which is closed, not our websocket->open comm proxy.\n", | |
" ws_proxy.onopen();\n", | |
"\n", | |
" fig.parent_element = element.get(0);\n", | |
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n", | |
" if (!fig.cell_info) {\n", | |
" console.error(\"Failed to find cell for figure\", id, fig);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var output_index = fig.cell_info[2]\n", | |
" var cell = fig.cell_info[0];\n", | |
"\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.handle_close = function(fig, msg) {\n", | |
" fig.root.unbind('remove')\n", | |
"\n", | |
" // Update the output cell to use the data from the current canvas.\n", | |
" fig.push_to_output();\n", | |
" var dataURL = fig.canvas.toDataURL();\n", | |
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n", | |
" // the notebook keyboard shortcuts fail.\n", | |
" IPython.keyboard_manager.enable()\n", | |
" $(fig.parent_element).html('<img src=\"' + dataURL + '\">');\n", | |
" fig.close_ws(fig, msg);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.close_ws = function(fig, msg){\n", | |
" fig.send_message('closing', msg);\n", | |
" // fig.ws.close()\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", | |
" // Turn the data on the canvas into data in the output cell.\n", | |
" var dataURL = this.canvas.toDataURL();\n", | |
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Tell IPython that the notebook contents must change.\n", | |
" IPython.notebook.set_dirty(true);\n", | |
" this.send_message(\"ack\", {});\n", | |
" var fig = this;\n", | |
" // Wait a second, then push the new image to the DOM so\n", | |
" // that it is saved nicely (might be nice to debounce this).\n", | |
" setTimeout(function () { fig.push_to_output() }, 1000);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_toolbar = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var nav_element = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items){\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) { continue; };\n", | |
"\n", | |
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" // Add the status bar.\n", | |
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"\n", | |
" // Add the close button to the window.\n", | |
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", | |
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", | |
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n", | |
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n", | |
" buttongrp.append(button);\n", | |
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", | |
" titlebar.prepend(buttongrp);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(el){\n", | |
" var fig = this\n", | |
" el.on(\"remove\", function(){\n", | |
"\tfig.close_ws(fig, {});\n", | |
" });\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(el){\n", | |
" // this is important to make the div 'focusable\n", | |
" el.attr('tabindex', 0)\n", | |
" // reach out to IPython and tell the keyboard manager to turn it's self\n", | |
" // off when our div gets focus\n", | |
"\n", | |
" // location in version 3\n", | |
" if (IPython.notebook.keyboard_manager) {\n", | |
" IPython.notebook.keyboard_manager.register_events(el);\n", | |
" }\n", | |
" else {\n", | |
" // location in version 2\n", | |
" IPython.keyboard_manager.register_events(el);\n", | |
" }\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" var manager = IPython.notebook.keyboard_manager;\n", | |
" if (!manager)\n", | |
" manager = IPython.keyboard_manager;\n", | |
"\n", | |
" // Check for shift+enter\n", | |
" if (event.shiftKey && event.which == 13) {\n", | |
" this.canvas_div.blur();\n", | |
" event.shiftKey = false;\n", | |
" // Send a \"J\" for go to next cell\n", | |
" event.which = 74;\n", | |
" event.keyCode = 74;\n", | |
" manager.command_mode();\n", | |
" manager.handle_keydown(event);\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" fig.ondownload(fig, null);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.find_output_cell = function(html_output) {\n", | |
" // Return the cell and output element which can be found *uniquely* in the notebook.\n", | |
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", | |
" // IPython event is triggered only after the cells have been serialised, which for\n", | |
" // our purposes (turning an active figure into a static one), is too late.\n", | |
" var cells = IPython.notebook.get_cells();\n", | |
" var ncells = cells.length;\n", | |
" for (var i=0; i<ncells; i++) {\n", | |
" var cell = cells[i];\n", | |
" if (cell.cell_type === 'code'){\n", | |
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n", | |
" var data = cell.output_area.outputs[j];\n", | |
" if (data.data) {\n", | |
" // IPython >= 3 moved mimebundle to data attribute of output\n", | |
" data = data.data;\n", | |
" }\n", | |
" if (data['text/html'] == html_output) {\n", | |
" return [cell, data, j];\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"// Register the function which deals with the matplotlib target/channel.\n", | |
"// The kernel may be null if the page has been refreshed.\n", | |
"if (IPython.notebook.kernel != null) {\n", | |
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", | |
"}\n" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/html": [ | |
"<img src=\"data:image/png;base64,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\">" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"# Use Scipy to fit our points in a regression model and obtain the regression coefficients\n", | |
"# For our case a bit cleaner that Sklearn alternative linear_model.LinearRegression()\n", | |
"from scipy import stats\n", | |
"\n", | |
"slope, intercept, r, p, _ = stats.linregress(x_bins, bins_word_count.values)\n", | |
"\n", | |
"print('Slope = {:.3f} (r = {:.3f}, p = {:.5f})'.format(slope, r, p))\n", | |
"print('Bin size= {:.3f} minutes'.format((df['time_end'].values[-1]/n_bins)/60))\n", | |
"\n", | |
"# Plot\n", | |
"plt.scatter(x_bins, bins_word_count.values, color='black')\n", | |
"plt.plot(x_bins, intercept + x_bins*slope, color='mediumblue', linewidth=3)\n", | |
"sns.barplot(y=bins_word_count.values, x=x_bins, color=\"salmon\", saturation=.5)\n", | |
"sns.plt.show()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"# Compute new features like pause between words, word length and speech rate at word level. \n", | |
"clean_df.loc[:, 'next_word_spacing'] = (clean_df['time_start'].shift(-1) - clean_df['time_end'])\n", | |
"clean_df.loc[:, 'word_speed'] = clean_df.apply(lambda x : (len(x['word'])/(x['time_end'] - x['time_start'])), axis=1)\n", | |
"clean_df.loc[:, 'word_len'] = clean_df.apply(lambda x : len(x['word']), axis=1)\n", | |
"clean_df.head()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 17, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<div>\n", | |
"<table border=\"1\" class=\"dataframe\">\n", | |
" <thead>\n", | |
" <tr style=\"text-align: right;\">\n", | |
" <th></th>\n", | |
" <th>word_len</th>\n", | |
" <th>next_word_spacing</th>\n", | |
" <th>word_speed</th>\n", | |
" <th>word_count</th>\n", | |
" </tr>\n", | |
" </thead>\n", | |
" <tbody>\n", | |
" <tr>\n", | |
" <th>1</th>\n", | |
" <td>3.925414</td>\n", | |
" <td>0.097707</td>\n", | |
" <td>17.015203</td>\n", | |
" <td>362</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>2</th>\n", | |
" <td>4.149425</td>\n", | |
" <td>0.096264</td>\n", | |
" <td>17.323505</td>\n", | |
" <td>348</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>3</th>\n", | |
" <td>4.009009</td>\n", | |
" <td>0.111111</td>\n", | |
" <td>16.320852</td>\n", | |
" <td>333</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>4</th>\n", | |
" <td>4.228324</td>\n", | |
" <td>0.085145</td>\n", | |
" <td>16.283307</td>\n", | |
" <td>346</td>\n", | |
" </tr>\n", | |
" <tr>\n", | |
" <th>5</th>\n", | |
" <td>4.058462</td>\n", | |
" <td>0.111692</td>\n", | |
" <td>15.694626</td>\n", | |
" <td>325</td>\n", | |
" </tr>\n", | |
" </tbody>\n", | |
"</table>\n", | |
"</div>" | |
], | |
"text/plain": [ | |
" word_len next_word_spacing word_speed word_count\n", | |
"1 3.925414 0.097707 17.015203 362\n", | |
"2 4.149425 0.096264 17.323505 348\n", | |
"3 4.009009 0.111111 16.320852 333\n", | |
"4 4.228324 0.085145 16.283307 346\n", | |
"5 4.058462 0.111692 15.694626 325" | |
] | |
}, | |
"execution_count": 17, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"# Prepare averages of binned data\n", | |
"bin_indices = np.digitize(clean_df['time_end'], bins)\n", | |
"binned_df = clean_df[['word_len','next_word_spacing', 'word_speed', ]].groupby(bin_indices).mean()\n", | |
"binned_df['word_count'] = bins_word_count\n", | |
"binned_df.head()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 18, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
" word_len next_word_spacing word_speed word_count\n", | |
"word_len 1.000000 0.168620 0.132477 -0.460278\n", | |
"next_word_spacing 0.168620 1.000000 -0.194362 -0.861282\n", | |
"word_speed 0.132477 -0.194362 1.000000 0.462469\n", | |
"word_count -0.460278 -0.861282 0.462469 1.000000\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 = $('<div/>');\n", | |
" this._root_extra_style(this.root)\n", | |
" this.root.attr('style', 'display: inline-block');\n", | |
"\n", | |
" $(parent_element).append(this.root);\n", | |
"\n", | |
" this._init_header(this);\n", | |
" this._init_canvas(this);\n", | |
" this._init_toolbar(this);\n", | |
"\n", | |
" var fig = this;\n", | |
"\n", | |
" this.waiting = false;\n", | |
"\n", | |
" this.ws.onopen = function () {\n", | |
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", | |
" fig.send_message(\"send_image_mode\", {});\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" }\n", | |
"\n", | |
" this.imageObj.onload = function() {\n", | |
" if (fig.image_mode == 'full') {\n", | |
" // Full images could contain transparency (where diff images\n", | |
" // almost always do), so we need to clear the canvas so that\n", | |
" // there is no ghosting.\n", | |
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", | |
" }\n", | |
" fig.context.drawImage(fig.imageObj, 0, 0);\n", | |
" };\n", | |
"\n", | |
" this.imageObj.onunload = function() {\n", | |
" 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", | |
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n", | |
" 'ui-helper-clearfix\"/>');\n", | |
" var titletext = $(\n", | |
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n", | |
" 'text-align: center; padding: 3px;\"/>');\n", | |
" titlebar.append(titletext)\n", | |
" this.root.append(titlebar);\n", | |
" this.header = titletext[0];\n", | |
"}\n", | |
"\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_canvas = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var canvas_div = $('<div/>');\n", | |
"\n", | |
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", | |
"\n", | |
" function canvas_keyboard_event(event) {\n", | |
" return fig.key_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" canvas_div.keydown('key_press', canvas_keyboard_event);\n", | |
" canvas_div.keyup('key_release', canvas_keyboard_event);\n", | |
" this.canvas_div = canvas_div\n", | |
" this._canvas_extra_style(canvas_div)\n", | |
" this.root.append(canvas_div);\n", | |
"\n", | |
" var canvas = $('<canvas/>');\n", | |
" canvas.addClass('mpl-canvas');\n", | |
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", | |
"\n", | |
" this.canvas = canvas[0];\n", | |
" this.context = canvas[0].getContext(\"2d\");\n", | |
"\n", | |
" var rubberband = $('<canvas/>');\n", | |
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", | |
"\n", | |
" var pass_mouse_events = true;\n", | |
"\n", | |
" canvas_div.resizable({\n", | |
" start: function(event, ui) {\n", | |
" pass_mouse_events = false;\n", | |
" },\n", | |
" resize: function(event, ui) {\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" stop: function(event, ui) {\n", | |
" pass_mouse_events = true;\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" });\n", | |
"\n", | |
" function mouse_event_fn(event) {\n", | |
" if (pass_mouse_events)\n", | |
" return fig.mouse_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" rubberband.mousedown('button_press', mouse_event_fn);\n", | |
" rubberband.mouseup('button_release', mouse_event_fn);\n", | |
" // Throttle sequential mouse events to 1 every 20ms.\n", | |
" rubberband.mousemove('motion_notify', mouse_event_fn);\n", | |
"\n", | |
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n", | |
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n", | |
"\n", | |
" canvas_div.on(\"wheel\", function (event) {\n", | |
" event = event.originalEvent;\n", | |
" event['data'] = 'scroll'\n", | |
" if (event.deltaY < 0) {\n", | |
" event.step = 1;\n", | |
" } else {\n", | |
" event.step = -1;\n", | |
" }\n", | |
" mouse_event_fn(event);\n", | |
" });\n", | |
"\n", | |
" canvas_div.append(canvas);\n", | |
" canvas_div.append(rubberband);\n", | |
"\n", | |
" this.rubberband = rubberband;\n", | |
" this.rubberband_canvas = rubberband[0];\n", | |
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n", | |
" this.rubberband_context.strokeStyle = \"#000000\";\n", | |
"\n", | |
" this._resize_canvas = function(width, height) {\n", | |
" // Keep the size of the canvas, canvas container, and rubber band\n", | |
" // canvas in synch.\n", | |
" canvas_div.css('width', width)\n", | |
" canvas_div.css('height', height)\n", | |
"\n", | |
" canvas.attr('width', width);\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 = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items) {\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) {\n", | |
" // put a spacer in here.\n", | |
" continue;\n", | |
" }\n", | |
" var button = $('<button/>');\n", | |
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n", | |
" 'ui-button-icon-only');\n", | |
" button.attr('role', 'button');\n", | |
" button.attr('aria-disabled', 'false');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
"\n", | |
" var icon_img = $('<span/>');\n", | |
" icon_img.addClass('ui-button-icon-primary ui-icon');\n", | |
" icon_img.addClass(image);\n", | |
" icon_img.addClass('ui-corner-all');\n", | |
"\n", | |
" var tooltip_span = $('<span/>');\n", | |
" tooltip_span.addClass('ui-button-text');\n", | |
" tooltip_span.html(tooltip);\n", | |
"\n", | |
" button.append(icon_img);\n", | |
" button.append(tooltip_span);\n", | |
"\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" var fmt_picker_span = $('<span/>');\n", | |
"\n", | |
" var fmt_picker = $('<select/>');\n", | |
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n", | |
" fmt_picker_span.append(fmt_picker);\n", | |
" nav_element.append(fmt_picker_span);\n", | |
" this.format_dropdown = fmt_picker[0];\n", | |
"\n", | |
" for (var ind in mpl.extensions) {\n", | |
" var fmt = mpl.extensions[ind];\n", | |
" var option = $(\n", | |
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n", | |
" fmt_picker.append(option)\n", | |
" }\n", | |
"\n", | |
" // Add hover states to the ui-buttons\n", | |
" $( \".ui-button\" ).hover(\n", | |
" function() { $(this).addClass(\"ui-state-hover\");},\n", | |
" function() { $(this).removeClass(\"ui-state-hover\");}\n", | |
" );\n", | |
"\n", | |
" var status_bar = $('<span class=\"mpl-message\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n", | |
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", | |
" // which will in turn request a refresh of the image.\n", | |
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_message = function(type, properties) {\n", | |
" properties['type'] = type;\n", | |
" properties['figure_id'] = this.id;\n", | |
" this.ws.send(JSON.stringify(properties));\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_draw_message = function() {\n", | |
" if (!this.waiting) {\n", | |
" this.waiting = true;\n", | |
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" var format_dropdown = fig.format_dropdown;\n", | |
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", | |
" fig.ondownload(fig, format);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n", | |
" var size = msg['size'];\n", | |
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n", | |
" fig._resize_canvas(size[0], size[1]);\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n", | |
" var x0 = msg['x0'];\n", | |
" var y0 = fig.canvas.height - msg['y0'];\n", | |
" var x1 = msg['x1'];\n", | |
" var y1 = fig.canvas.height - msg['y1'];\n", | |
" x0 = Math.floor(x0) + 0.5;\n", | |
" y0 = Math.floor(y0) + 0.5;\n", | |
" x1 = Math.floor(x1) + 0.5;\n", | |
" y1 = Math.floor(y1) + 0.5;\n", | |
" var min_x = Math.min(x0, x1);\n", | |
" var min_y = Math.min(y0, y1);\n", | |
" var width = Math.abs(x1 - x0);\n", | |
" var height = Math.abs(y1 - y0);\n", | |
"\n", | |
" fig.rubberband_context.clearRect(\n", | |
" 0, 0, fig.canvas.width, fig.canvas.height);\n", | |
"\n", | |
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n", | |
" // Updates the figure title.\n", | |
" fig.header.textContent = msg['label'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n", | |
" var cursor = msg['cursor'];\n", | |
" switch(cursor)\n", | |
" {\n", | |
" case 0:\n", | |
" cursor = 'pointer';\n", | |
" break;\n", | |
" case 1:\n", | |
" cursor = 'default';\n", | |
" break;\n", | |
" case 2:\n", | |
" cursor = 'crosshair';\n", | |
" break;\n", | |
" case 3:\n", | |
" cursor = 'move';\n", | |
" break;\n", | |
" }\n", | |
" fig.rubberband_canvas.style.cursor = cursor;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_message = function(fig, msg) {\n", | |
" fig.message.textContent = msg['message'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n", | |
" // Request the server to send over a new figure.\n", | |
" fig.send_draw_message();\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n", | |
" fig.image_mode = msg['mode'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Called whenever the canvas gets updated.\n", | |
" this.send_message(\"ack\", {});\n", | |
"}\n", | |
"\n", | |
"// A function to construct a web socket function for onmessage handling.\n", | |
"// Called in the figure constructor.\n", | |
"mpl.figure.prototype._make_on_message_function = function(fig) {\n", | |
" return function socket_on_message(evt) {\n", | |
" if (evt.data instanceof Blob) {\n", | |
" /* FIXME: We get \"Resource interpreted as Image but\n", | |
" * transferred with MIME type text/plain:\" errors on\n", | |
" * Chrome. But how to set the MIME type? It doesn't seem\n", | |
" * to be part of the websocket stream */\n", | |
" evt.data.type = \"image/png\";\n", | |
"\n", | |
" /* Free the memory for the previous frames */\n", | |
" if (fig.imageObj.src) {\n", | |
" (window.URL || window.webkitURL).revokeObjectURL(\n", | |
" fig.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", | |
" evt.data);\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n", | |
" fig.imageObj.src = evt.data;\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var msg = JSON.parse(evt.data);\n", | |
" var msg_type = msg['type'];\n", | |
"\n", | |
" // Call the \"handle_{type}\" callback, which takes\n", | |
" // the figure and JSON message as its only arguments.\n", | |
" try {\n", | |
" var callback = fig[\"handle_\" + msg_type];\n", | |
" } catch (e) {\n", | |
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" if (callback) {\n", | |
" try {\n", | |
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", | |
" callback(fig, msg);\n", | |
" } catch (e) {\n", | |
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n", | |
" }\n", | |
" }\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", | |
"mpl.findpos = function(e) {\n", | |
" //this section is from http://www.quirksmode.org/js/events_properties.html\n", | |
" var targ;\n", | |
" if (!e)\n", | |
" e = window.event;\n", | |
" if (e.target)\n", | |
" targ = e.target;\n", | |
" else if (e.srcElement)\n", | |
" targ = e.srcElement;\n", | |
" if (targ.nodeType == 3) // defeat Safari bug\n", | |
" targ = targ.parentNode;\n", | |
"\n", | |
" // jQuery normalizes the pageX and pageY\n", | |
" // pageX,Y are the mouse positions relative to the document\n", | |
" // offset() returns the position of the element relative to the document\n", | |
" var x = e.pageX - $(targ).offset().left;\n", | |
" var y = e.pageY - $(targ).offset().top;\n", | |
"\n", | |
" return {\"x\": x, \"y\": y};\n", | |
"};\n", | |
"\n", | |
"/*\n", | |
" * return a copy of an object with only non-object keys\n", | |
" * we need this to avoid circular references\n", | |
" * http://stackoverflow.com/a/24161582/3208463\n", | |
" */\n", | |
"function simpleKeys (original) {\n", | |
" return Object.keys(original).reduce(function (obj, key) {\n", | |
" if (typeof original[key] !== 'object')\n", | |
" obj[key] = original[key]\n", | |
" return obj;\n", | |
" }, {});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.mouse_event = function(event, name) {\n", | |
" var canvas_pos = mpl.findpos(event)\n", | |
"\n", | |
" if (name === 'button_press')\n", | |
" {\n", | |
" this.canvas.focus();\n", | |
" this.canvas_div.focus();\n", | |
" }\n", | |
"\n", | |
" var x = canvas_pos.x;\n", | |
" var y = canvas_pos.y;\n", | |
"\n", | |
" this.send_message(name, {x: x, y: y, button: event.button,\n", | |
" step: event.step,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
"\n", | |
" /* This prevents the web browser from automatically changing to\n", | |
" * the text insertion cursor when the button is pressed. We want\n", | |
" * to control all of the cursor setting manually through the\n", | |
" * 'cursor' event from matplotlib */\n", | |
" event.preventDefault();\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" // Handle any extra behaviour associated with a key event\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.key_event = function(event, name) {\n", | |
"\n", | |
" // Prevent repeat events\n", | |
" if (name == 'key_press')\n", | |
" {\n", | |
" if (event.which === this._key)\n", | |
" return;\n", | |
" else\n", | |
" this._key = event.which;\n", | |
" }\n", | |
" if (name == 'key_release')\n", | |
" this._key = null;\n", | |
"\n", | |
" var value = '';\n", | |
" if (event.ctrlKey && event.which != 17)\n", | |
" value += \"ctrl+\";\n", | |
" if (event.altKey && event.which != 18)\n", | |
" value += \"alt+\";\n", | |
" if (event.shiftKey && event.which != 16)\n", | |
" value += \"shift+\";\n", | |
"\n", | |
" value += 'k';\n", | |
" value += event.which.toString();\n", | |
"\n", | |
" this._key_event_extra(event, name);\n", | |
"\n", | |
" this.send_message(name, {key: value,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n", | |
" if (name == 'download') {\n", | |
" this.handle_save(this, null);\n", | |
" } else {\n", | |
" this.send_message(\"toolbar_button\", {name: name});\n", | |
" }\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", | |
" this.message.textContent = tooltip;\n", | |
"};\n", | |
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", | |
"\n", | |
"mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", | |
"\n", | |
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n", | |
" // Create a \"websocket\"-like object which calls the given IPython comm\n", | |
" // object with the appropriate methods. Currently this is a non binary\n", | |
" // socket, so there is still some room for performance tuning.\n", | |
" var ws = {};\n", | |
"\n", | |
" ws.close = function() {\n", | |
" comm.close()\n", | |
" };\n", | |
" ws.send = function(m) {\n", | |
" //console.log('sending', m);\n", | |
" comm.send(m);\n", | |
" };\n", | |
" // Register the callback with on_msg.\n", | |
" comm.on_msg(function(msg) {\n", | |
" //console.log('receiving', msg['content']['data'], msg);\n", | |
" // Pass the mpl event to the overriden (by mpl) onmessage function.\n", | |
" ws.onmessage(msg['content']['data'])\n", | |
" });\n", | |
" return ws;\n", | |
"}\n", | |
"\n", | |
"mpl.mpl_figure_comm = function(comm, msg) {\n", | |
" // This is the function which gets called when the mpl process\n", | |
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n", | |
"\n", | |
" var id = msg.content.data.id;\n", | |
" // Get hold of the div created by the display call when the Comm\n", | |
" // socket was opened in Python.\n", | |
" var element = $(\"#\" + id);\n", | |
" var ws_proxy = comm_websocket_adapter(comm)\n", | |
"\n", | |
" function ondownload(figure, format) {\n", | |
" window.open(figure.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" var fig = new mpl.figure(id, ws_proxy,\n", | |
" ondownload,\n", | |
" element.get(0));\n", | |
"\n", | |
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", | |
" // web socket which is closed, not our websocket->open comm proxy.\n", | |
" ws_proxy.onopen();\n", | |
"\n", | |
" fig.parent_element = element.get(0);\n", | |
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n", | |
" if (!fig.cell_info) {\n", | |
" console.error(\"Failed to find cell for figure\", id, fig);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var output_index = fig.cell_info[2]\n", | |
" var cell = fig.cell_info[0];\n", | |
"\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.handle_close = function(fig, msg) {\n", | |
" fig.root.unbind('remove')\n", | |
"\n", | |
" // Update the output cell to use the data from the current canvas.\n", | |
" fig.push_to_output();\n", | |
" var dataURL = fig.canvas.toDataURL();\n", | |
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n", | |
" // the notebook keyboard shortcuts fail.\n", | |
" IPython.keyboard_manager.enable()\n", | |
" $(fig.parent_element).html('<img src=\"' + dataURL + '\">');\n", | |
" fig.close_ws(fig, msg);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.close_ws = function(fig, msg){\n", | |
" fig.send_message('closing', msg);\n", | |
" // fig.ws.close()\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", | |
" // Turn the data on the canvas into data in the output cell.\n", | |
" var dataURL = this.canvas.toDataURL();\n", | |
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Tell IPython that the notebook contents must change.\n", | |
" IPython.notebook.set_dirty(true);\n", | |
" this.send_message(\"ack\", {});\n", | |
" var fig = this;\n", | |
" // Wait a second, then push the new image to the DOM so\n", | |
" // that it is saved nicely (might be nice to debounce this).\n", | |
" setTimeout(function () { fig.push_to_output() }, 1000);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_toolbar = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var nav_element = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items){\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) { continue; };\n", | |
"\n", | |
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" // Add the status bar.\n", | |
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"\n", | |
" // Add the close button to the window.\n", | |
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", | |
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", | |
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n", | |
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n", | |
" buttongrp.append(button);\n", | |
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", | |
" titlebar.prepend(buttongrp);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(el){\n", | |
" var fig = this\n", | |
" el.on(\"remove\", function(){\n", | |
"\tfig.close_ws(fig, {});\n", | |
" });\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(el){\n", | |
" // this is important to make the div 'focusable\n", | |
" el.attr('tabindex', 0)\n", | |
" // reach out to IPython and tell the keyboard manager to turn it's self\n", | |
" // off when our div gets focus\n", | |
"\n", | |
" // location in version 3\n", | |
" if (IPython.notebook.keyboard_manager) {\n", | |
" IPython.notebook.keyboard_manager.register_events(el);\n", | |
" }\n", | |
" else {\n", | |
" // location in version 2\n", | |
" IPython.keyboard_manager.register_events(el);\n", | |
" }\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" var manager = IPython.notebook.keyboard_manager;\n", | |
" if (!manager)\n", | |
" manager = IPython.keyboard_manager;\n", | |
"\n", | |
" // Check for shift+enter\n", | |
" if (event.shiftKey && event.which == 13) {\n", | |
" this.canvas_div.blur();\n", | |
" event.shiftKey = false;\n", | |
" // Send a \"J\" for go to next cell\n", | |
" event.which = 74;\n", | |
" event.keyCode = 74;\n", | |
" manager.command_mode();\n", | |
" manager.handle_keydown(event);\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" fig.ondownload(fig, null);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.find_output_cell = function(html_output) {\n", | |
" // Return the cell and output element which can be found *uniquely* in the notebook.\n", | |
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", | |
" // IPython event is triggered only after the cells have been serialised, which for\n", | |
" // our purposes (turning an active figure into a static one), is too late.\n", | |
" var cells = IPython.notebook.get_cells();\n", | |
" var ncells = cells.length;\n", | |
" for (var i=0; i<ncells; i++) {\n", | |
" var cell = cells[i];\n", | |
" if (cell.cell_type === 'code'){\n", | |
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n", | |
" var data = cell.output_area.outputs[j];\n", | |
" if (data.data) {\n", | |
" // IPython >= 3 moved mimebundle to data attribute of output\n", | |
" data = data.data;\n", | |
" }\n", | |
" if (data['text/html'] == html_output) {\n", | |
" return [cell, data, j];\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"// Register the function which deals with the matplotlib target/channel.\n", | |
"// The kernel may be null if the page has been refreshed.\n", | |
"if (IPython.notebook.kernel != null) {\n", | |
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", | |
"}\n" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/html": [ | |
"<img src=\"data:image/png;base64,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\">" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"# Correlation\n", | |
"corr = binned_df.corr()\n", | |
"print(corr)\n", | |
"# Plot masking the upper triangle\n", | |
"mask = np.zeros_like(corr, dtype=np.bool)\n", | |
"mask[np.triu_indices_from(mask)] = True\n", | |
"sns.heatmap(corr, mask=mask)\n", | |
"plt.show()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 19, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"word_len: slope = 0.014 (r = 0.400, p = 0.25255)\n", | |
"next_word_spacing: slope = 0.004 (r = 0.711, p = 0.02125)\n", | |
"word_speed: slope = -0.129 (r = -0.606, p = 0.06315)\n", | |
"word_count: slope = -5.230 (r = -0.890, p = 0.00056)\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 = $('<div/>');\n", | |
" this._root_extra_style(this.root)\n", | |
" this.root.attr('style', 'display: inline-block');\n", | |
"\n", | |
" $(parent_element).append(this.root);\n", | |
"\n", | |
" this._init_header(this);\n", | |
" this._init_canvas(this);\n", | |
" this._init_toolbar(this);\n", | |
"\n", | |
" var fig = this;\n", | |
"\n", | |
" this.waiting = false;\n", | |
"\n", | |
" this.ws.onopen = function () {\n", | |
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", | |
" fig.send_message(\"send_image_mode\", {});\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" }\n", | |
"\n", | |
" this.imageObj.onload = function() {\n", | |
" if (fig.image_mode == 'full') {\n", | |
" // Full images could contain transparency (where diff images\n", | |
" // almost always do), so we need to clear the canvas so that\n", | |
" // there is no ghosting.\n", | |
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", | |
" }\n", | |
" fig.context.drawImage(fig.imageObj, 0, 0);\n", | |
" };\n", | |
"\n", | |
" this.imageObj.onunload = function() {\n", | |
" 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", | |
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n", | |
" 'ui-helper-clearfix\"/>');\n", | |
" var titletext = $(\n", | |
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n", | |
" 'text-align: center; padding: 3px;\"/>');\n", | |
" titlebar.append(titletext)\n", | |
" this.root.append(titlebar);\n", | |
" this.header = titletext[0];\n", | |
"}\n", | |
"\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_canvas = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var canvas_div = $('<div/>');\n", | |
"\n", | |
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", | |
"\n", | |
" function canvas_keyboard_event(event) {\n", | |
" return fig.key_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" canvas_div.keydown('key_press', canvas_keyboard_event);\n", | |
" canvas_div.keyup('key_release', canvas_keyboard_event);\n", | |
" this.canvas_div = canvas_div\n", | |
" this._canvas_extra_style(canvas_div)\n", | |
" this.root.append(canvas_div);\n", | |
"\n", | |
" var canvas = $('<canvas/>');\n", | |
" canvas.addClass('mpl-canvas');\n", | |
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", | |
"\n", | |
" this.canvas = canvas[0];\n", | |
" this.context = canvas[0].getContext(\"2d\");\n", | |
"\n", | |
" var rubberband = $('<canvas/>');\n", | |
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", | |
"\n", | |
" var pass_mouse_events = true;\n", | |
"\n", | |
" canvas_div.resizable({\n", | |
" start: function(event, ui) {\n", | |
" pass_mouse_events = false;\n", | |
" },\n", | |
" resize: function(event, ui) {\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" stop: function(event, ui) {\n", | |
" pass_mouse_events = true;\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" });\n", | |
"\n", | |
" function mouse_event_fn(event) {\n", | |
" if (pass_mouse_events)\n", | |
" return fig.mouse_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" rubberband.mousedown('button_press', mouse_event_fn);\n", | |
" rubberband.mouseup('button_release', mouse_event_fn);\n", | |
" // Throttle sequential mouse events to 1 every 20ms.\n", | |
" rubberband.mousemove('motion_notify', mouse_event_fn);\n", | |
"\n", | |
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n", | |
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n", | |
"\n", | |
" canvas_div.on(\"wheel\", function (event) {\n", | |
" event = event.originalEvent;\n", | |
" event['data'] = 'scroll'\n", | |
" if (event.deltaY < 0) {\n", | |
" event.step = 1;\n", | |
" } else {\n", | |
" event.step = -1;\n", | |
" }\n", | |
" mouse_event_fn(event);\n", | |
" });\n", | |
"\n", | |
" canvas_div.append(canvas);\n", | |
" canvas_div.append(rubberband);\n", | |
"\n", | |
" this.rubberband = rubberband;\n", | |
" this.rubberband_canvas = rubberband[0];\n", | |
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n", | |
" this.rubberband_context.strokeStyle = \"#000000\";\n", | |
"\n", | |
" this._resize_canvas = function(width, height) {\n", | |
" // Keep the size of the canvas, canvas container, and rubber band\n", | |
" // canvas in synch.\n", | |
" canvas_div.css('width', width)\n", | |
" canvas_div.css('height', height)\n", | |
"\n", | |
" canvas.attr('width', width);\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 = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items) {\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) {\n", | |
" // put a spacer in here.\n", | |
" continue;\n", | |
" }\n", | |
" var button = $('<button/>');\n", | |
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n", | |
" 'ui-button-icon-only');\n", | |
" button.attr('role', 'button');\n", | |
" button.attr('aria-disabled', 'false');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
"\n", | |
" var icon_img = $('<span/>');\n", | |
" icon_img.addClass('ui-button-icon-primary ui-icon');\n", | |
" icon_img.addClass(image);\n", | |
" icon_img.addClass('ui-corner-all');\n", | |
"\n", | |
" var tooltip_span = $('<span/>');\n", | |
" tooltip_span.addClass('ui-button-text');\n", | |
" tooltip_span.html(tooltip);\n", | |
"\n", | |
" button.append(icon_img);\n", | |
" button.append(tooltip_span);\n", | |
"\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" var fmt_picker_span = $('<span/>');\n", | |
"\n", | |
" var fmt_picker = $('<select/>');\n", | |
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n", | |
" fmt_picker_span.append(fmt_picker);\n", | |
" nav_element.append(fmt_picker_span);\n", | |
" this.format_dropdown = fmt_picker[0];\n", | |
"\n", | |
" for (var ind in mpl.extensions) {\n", | |
" var fmt = mpl.extensions[ind];\n", | |
" var option = $(\n", | |
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n", | |
" fmt_picker.append(option)\n", | |
" }\n", | |
"\n", | |
" // Add hover states to the ui-buttons\n", | |
" $( \".ui-button\" ).hover(\n", | |
" function() { $(this).addClass(\"ui-state-hover\");},\n", | |
" function() { $(this).removeClass(\"ui-state-hover\");}\n", | |
" );\n", | |
"\n", | |
" var status_bar = $('<span class=\"mpl-message\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n", | |
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", | |
" // which will in turn request a refresh of the image.\n", | |
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_message = function(type, properties) {\n", | |
" properties['type'] = type;\n", | |
" properties['figure_id'] = this.id;\n", | |
" this.ws.send(JSON.stringify(properties));\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_draw_message = function() {\n", | |
" if (!this.waiting) {\n", | |
" this.waiting = true;\n", | |
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" var format_dropdown = fig.format_dropdown;\n", | |
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", | |
" fig.ondownload(fig, format);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n", | |
" var size = msg['size'];\n", | |
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n", | |
" fig._resize_canvas(size[0], size[1]);\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n", | |
" var x0 = msg['x0'];\n", | |
" var y0 = fig.canvas.height - msg['y0'];\n", | |
" var x1 = msg['x1'];\n", | |
" var y1 = fig.canvas.height - msg['y1'];\n", | |
" x0 = Math.floor(x0) + 0.5;\n", | |
" y0 = Math.floor(y0) + 0.5;\n", | |
" x1 = Math.floor(x1) + 0.5;\n", | |
" y1 = Math.floor(y1) + 0.5;\n", | |
" var min_x = Math.min(x0, x1);\n", | |
" var min_y = Math.min(y0, y1);\n", | |
" var width = Math.abs(x1 - x0);\n", | |
" var height = Math.abs(y1 - y0);\n", | |
"\n", | |
" fig.rubberband_context.clearRect(\n", | |
" 0, 0, fig.canvas.width, fig.canvas.height);\n", | |
"\n", | |
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n", | |
" // Updates the figure title.\n", | |
" fig.header.textContent = msg['label'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n", | |
" var cursor = msg['cursor'];\n", | |
" switch(cursor)\n", | |
" {\n", | |
" case 0:\n", | |
" cursor = 'pointer';\n", | |
" break;\n", | |
" case 1:\n", | |
" cursor = 'default';\n", | |
" break;\n", | |
" case 2:\n", | |
" cursor = 'crosshair';\n", | |
" break;\n", | |
" case 3:\n", | |
" cursor = 'move';\n", | |
" break;\n", | |
" }\n", | |
" fig.rubberband_canvas.style.cursor = cursor;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_message = function(fig, msg) {\n", | |
" fig.message.textContent = msg['message'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n", | |
" // Request the server to send over a new figure.\n", | |
" fig.send_draw_message();\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n", | |
" fig.image_mode = msg['mode'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Called whenever the canvas gets updated.\n", | |
" this.send_message(\"ack\", {});\n", | |
"}\n", | |
"\n", | |
"// A function to construct a web socket function for onmessage handling.\n", | |
"// Called in the figure constructor.\n", | |
"mpl.figure.prototype._make_on_message_function = function(fig) {\n", | |
" return function socket_on_message(evt) {\n", | |
" if (evt.data instanceof Blob) {\n", | |
" /* FIXME: We get \"Resource interpreted as Image but\n", | |
" * transferred with MIME type text/plain:\" errors on\n", | |
" * Chrome. But how to set the MIME type? It doesn't seem\n", | |
" * to be part of the websocket stream */\n", | |
" evt.data.type = \"image/png\";\n", | |
"\n", | |
" /* Free the memory for the previous frames */\n", | |
" if (fig.imageObj.src) {\n", | |
" (window.URL || window.webkitURL).revokeObjectURL(\n", | |
" fig.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", | |
" evt.data);\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n", | |
" fig.imageObj.src = evt.data;\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var msg = JSON.parse(evt.data);\n", | |
" var msg_type = msg['type'];\n", | |
"\n", | |
" // Call the \"handle_{type}\" callback, which takes\n", | |
" // the figure and JSON message as its only arguments.\n", | |
" try {\n", | |
" var callback = fig[\"handle_\" + msg_type];\n", | |
" } catch (e) {\n", | |
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" if (callback) {\n", | |
" try {\n", | |
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", | |
" callback(fig, msg);\n", | |
" } catch (e) {\n", | |
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n", | |
" }\n", | |
" }\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", | |
"mpl.findpos = function(e) {\n", | |
" //this section is from http://www.quirksmode.org/js/events_properties.html\n", | |
" var targ;\n", | |
" if (!e)\n", | |
" e = window.event;\n", | |
" if (e.target)\n", | |
" targ = e.target;\n", | |
" else if (e.srcElement)\n", | |
" targ = e.srcElement;\n", | |
" if (targ.nodeType == 3) // defeat Safari bug\n", | |
" targ = targ.parentNode;\n", | |
"\n", | |
" // jQuery normalizes the pageX and pageY\n", | |
" // pageX,Y are the mouse positions relative to the document\n", | |
" // offset() returns the position of the element relative to the document\n", | |
" var x = e.pageX - $(targ).offset().left;\n", | |
" var y = e.pageY - $(targ).offset().top;\n", | |
"\n", | |
" return {\"x\": x, \"y\": y};\n", | |
"};\n", | |
"\n", | |
"/*\n", | |
" * return a copy of an object with only non-object keys\n", | |
" * we need this to avoid circular references\n", | |
" * http://stackoverflow.com/a/24161582/3208463\n", | |
" */\n", | |
"function simpleKeys (original) {\n", | |
" return Object.keys(original).reduce(function (obj, key) {\n", | |
" if (typeof original[key] !== 'object')\n", | |
" obj[key] = original[key]\n", | |
" return obj;\n", | |
" }, {});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.mouse_event = function(event, name) {\n", | |
" var canvas_pos = mpl.findpos(event)\n", | |
"\n", | |
" if (name === 'button_press')\n", | |
" {\n", | |
" this.canvas.focus();\n", | |
" this.canvas_div.focus();\n", | |
" }\n", | |
"\n", | |
" var x = canvas_pos.x;\n", | |
" var y = canvas_pos.y;\n", | |
"\n", | |
" this.send_message(name, {x: x, y: y, button: event.button,\n", | |
" step: event.step,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
"\n", | |
" /* This prevents the web browser from automatically changing to\n", | |
" * the text insertion cursor when the button is pressed. We want\n", | |
" * to control all of the cursor setting manually through the\n", | |
" * 'cursor' event from matplotlib */\n", | |
" event.preventDefault();\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" // Handle any extra behaviour associated with a key event\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.key_event = function(event, name) {\n", | |
"\n", | |
" // Prevent repeat events\n", | |
" if (name == 'key_press')\n", | |
" {\n", | |
" if (event.which === this._key)\n", | |
" return;\n", | |
" else\n", | |
" this._key = event.which;\n", | |
" }\n", | |
" if (name == 'key_release')\n", | |
" this._key = null;\n", | |
"\n", | |
" var value = '';\n", | |
" if (event.ctrlKey && event.which != 17)\n", | |
" value += \"ctrl+\";\n", | |
" if (event.altKey && event.which != 18)\n", | |
" value += \"alt+\";\n", | |
" if (event.shiftKey && event.which != 16)\n", | |
" value += \"shift+\";\n", | |
"\n", | |
" value += 'k';\n", | |
" value += event.which.toString();\n", | |
"\n", | |
" this._key_event_extra(event, name);\n", | |
"\n", | |
" this.send_message(name, {key: value,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n", | |
" if (name == 'download') {\n", | |
" this.handle_save(this, null);\n", | |
" } else {\n", | |
" this.send_message(\"toolbar_button\", {name: name});\n", | |
" }\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", | |
" this.message.textContent = tooltip;\n", | |
"};\n", | |
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", | |
"\n", | |
"mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", | |
"\n", | |
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n", | |
" // Create a \"websocket\"-like object which calls the given IPython comm\n", | |
" // object with the appropriate methods. Currently this is a non binary\n", | |
" // socket, so there is still some room for performance tuning.\n", | |
" var ws = {};\n", | |
"\n", | |
" ws.close = function() {\n", | |
" comm.close()\n", | |
" };\n", | |
" ws.send = function(m) {\n", | |
" //console.log('sending', m);\n", | |
" comm.send(m);\n", | |
" };\n", | |
" // Register the callback with on_msg.\n", | |
" comm.on_msg(function(msg) {\n", | |
" //console.log('receiving', msg['content']['data'], msg);\n", | |
" // Pass the mpl event to the overriden (by mpl) onmessage function.\n", | |
" ws.onmessage(msg['content']['data'])\n", | |
" });\n", | |
" return ws;\n", | |
"}\n", | |
"\n", | |
"mpl.mpl_figure_comm = function(comm, msg) {\n", | |
" // This is the function which gets called when the mpl process\n", | |
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n", | |
"\n", | |
" var id = msg.content.data.id;\n", | |
" // Get hold of the div created by the display call when the Comm\n", | |
" // socket was opened in Python.\n", | |
" var element = $(\"#\" + id);\n", | |
" var ws_proxy = comm_websocket_adapter(comm)\n", | |
"\n", | |
" function ondownload(figure, format) {\n", | |
" window.open(figure.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" var fig = new mpl.figure(id, ws_proxy,\n", | |
" ondownload,\n", | |
" element.get(0));\n", | |
"\n", | |
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", | |
" // web socket which is closed, not our websocket->open comm proxy.\n", | |
" ws_proxy.onopen();\n", | |
"\n", | |
" fig.parent_element = element.get(0);\n", | |
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n", | |
" if (!fig.cell_info) {\n", | |
" console.error(\"Failed to find cell for figure\", id, fig);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var output_index = fig.cell_info[2]\n", | |
" var cell = fig.cell_info[0];\n", | |
"\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.handle_close = function(fig, msg) {\n", | |
" fig.root.unbind('remove')\n", | |
"\n", | |
" // Update the output cell to use the data from the current canvas.\n", | |
" fig.push_to_output();\n", | |
" var dataURL = fig.canvas.toDataURL();\n", | |
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n", | |
" // the notebook keyboard shortcuts fail.\n", | |
" IPython.keyboard_manager.enable()\n", | |
" $(fig.parent_element).html('<img src=\"' + dataURL + '\">');\n", | |
" fig.close_ws(fig, msg);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.close_ws = function(fig, msg){\n", | |
" fig.send_message('closing', msg);\n", | |
" // fig.ws.close()\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", | |
" // Turn the data on the canvas into data in the output cell.\n", | |
" var dataURL = this.canvas.toDataURL();\n", | |
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Tell IPython that the notebook contents must change.\n", | |
" IPython.notebook.set_dirty(true);\n", | |
" this.send_message(\"ack\", {});\n", | |
" var fig = this;\n", | |
" // Wait a second, then push the new image to the DOM so\n", | |
" // that it is saved nicely (might be nice to debounce this).\n", | |
" setTimeout(function () { fig.push_to_output() }, 1000);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_toolbar = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var nav_element = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items){\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) { continue; };\n", | |
"\n", | |
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" // Add the status bar.\n", | |
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"\n", | |
" // Add the close button to the window.\n", | |
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", | |
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", | |
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n", | |
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n", | |
" buttongrp.append(button);\n", | |
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", | |
" titlebar.prepend(buttongrp);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(el){\n", | |
" var fig = this\n", | |
" el.on(\"remove\", function(){\n", | |
"\tfig.close_ws(fig, {});\n", | |
" });\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(el){\n", | |
" // this is important to make the div 'focusable\n", | |
" el.attr('tabindex', 0)\n", | |
" // reach out to IPython and tell the keyboard manager to turn it's self\n", | |
" // off when our div gets focus\n", | |
"\n", | |
" // location in version 3\n", | |
" if (IPython.notebook.keyboard_manager) {\n", | |
" IPython.notebook.keyboard_manager.register_events(el);\n", | |
" }\n", | |
" else {\n", | |
" // location in version 2\n", | |
" IPython.keyboard_manager.register_events(el);\n", | |
" }\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" var manager = IPython.notebook.keyboard_manager;\n", | |
" if (!manager)\n", | |
" manager = IPython.keyboard_manager;\n", | |
"\n", | |
" // Check for shift+enter\n", | |
" if (event.shiftKey && event.which == 13) {\n", | |
" this.canvas_div.blur();\n", | |
" event.shiftKey = false;\n", | |
" // Send a \"J\" for go to next cell\n", | |
" event.which = 74;\n", | |
" event.keyCode = 74;\n", | |
" manager.command_mode();\n", | |
" manager.handle_keydown(event);\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" fig.ondownload(fig, null);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.find_output_cell = function(html_output) {\n", | |
" // Return the cell and output element which can be found *uniquely* in the notebook.\n", | |
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", | |
" // IPython event is triggered only after the cells have been serialised, which for\n", | |
" // our purposes (turning an active figure into a static one), is too late.\n", | |
" var cells = IPython.notebook.get_cells();\n", | |
" var ncells = cells.length;\n", | |
" for (var i=0; i<ncells; i++) {\n", | |
" var cell = cells[i];\n", | |
" if (cell.cell_type === 'code'){\n", | |
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n", | |
" var data = cell.output_area.outputs[j];\n", | |
" if (data.data) {\n", | |
" // IPython >= 3 moved mimebundle to data attribute of output\n", | |
" data = data.data;\n", | |
" }\n", | |
" if (data['text/html'] == html_output) {\n", | |
" return [cell, data, j];\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"// Register the function which deals with the matplotlib target/channel.\n", | |
"// The kernel may be null if the page has been refreshed.\n", | |
"if (IPython.notebook.kernel != null) {\n", | |
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", | |
"}\n" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/html": [ | |
"<img src=\"data:image/png;base64,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\">" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"# Linear regression data for each new feature\n", | |
"for c in binned_df.columns:\n", | |
" slope, intercept, r, p, _ = stats.linregress(x_bins, binned_df[c])\n", | |
" print('{}: slope = {:.3f} (r = {:.3f}, p = {:.5f})'.format(c, slope, r, p))\n", | |
"\n", | |
"# Quick line plot via Pandas\n", | |
"binned_df.plot(subplots=True, layout=(4,1))\n", | |
"plt.show()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 20, | |
"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 = $('<div/>');\n", | |
" this._root_extra_style(this.root)\n", | |
" this.root.attr('style', 'display: inline-block');\n", | |
"\n", | |
" $(parent_element).append(this.root);\n", | |
"\n", | |
" this._init_header(this);\n", | |
" this._init_canvas(this);\n", | |
" this._init_toolbar(this);\n", | |
"\n", | |
" var fig = this;\n", | |
"\n", | |
" this.waiting = false;\n", | |
"\n", | |
" this.ws.onopen = function () {\n", | |
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", | |
" fig.send_message(\"send_image_mode\", {});\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" }\n", | |
"\n", | |
" this.imageObj.onload = function() {\n", | |
" if (fig.image_mode == 'full') {\n", | |
" // Full images could contain transparency (where diff images\n", | |
" // almost always do), so we need to clear the canvas so that\n", | |
" // there is no ghosting.\n", | |
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", | |
" }\n", | |
" fig.context.drawImage(fig.imageObj, 0, 0);\n", | |
" };\n", | |
"\n", | |
" this.imageObj.onunload = function() {\n", | |
" 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", | |
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n", | |
" 'ui-helper-clearfix\"/>');\n", | |
" var titletext = $(\n", | |
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n", | |
" 'text-align: center; padding: 3px;\"/>');\n", | |
" titlebar.append(titletext)\n", | |
" this.root.append(titlebar);\n", | |
" this.header = titletext[0];\n", | |
"}\n", | |
"\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_canvas = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var canvas_div = $('<div/>');\n", | |
"\n", | |
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", | |
"\n", | |
" function canvas_keyboard_event(event) {\n", | |
" return fig.key_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" canvas_div.keydown('key_press', canvas_keyboard_event);\n", | |
" canvas_div.keyup('key_release', canvas_keyboard_event);\n", | |
" this.canvas_div = canvas_div\n", | |
" this._canvas_extra_style(canvas_div)\n", | |
" this.root.append(canvas_div);\n", | |
"\n", | |
" var canvas = $('<canvas/>');\n", | |
" canvas.addClass('mpl-canvas');\n", | |
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", | |
"\n", | |
" this.canvas = canvas[0];\n", | |
" this.context = canvas[0].getContext(\"2d\");\n", | |
"\n", | |
" var rubberband = $('<canvas/>');\n", | |
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", | |
"\n", | |
" var pass_mouse_events = true;\n", | |
"\n", | |
" canvas_div.resizable({\n", | |
" start: function(event, ui) {\n", | |
" pass_mouse_events = false;\n", | |
" },\n", | |
" resize: function(event, ui) {\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" stop: function(event, ui) {\n", | |
" pass_mouse_events = true;\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" });\n", | |
"\n", | |
" function mouse_event_fn(event) {\n", | |
" if (pass_mouse_events)\n", | |
" return fig.mouse_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" rubberband.mousedown('button_press', mouse_event_fn);\n", | |
" rubberband.mouseup('button_release', mouse_event_fn);\n", | |
" // Throttle sequential mouse events to 1 every 20ms.\n", | |
" rubberband.mousemove('motion_notify', mouse_event_fn);\n", | |
"\n", | |
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n", | |
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n", | |
"\n", | |
" canvas_div.on(\"wheel\", function (event) {\n", | |
" event = event.originalEvent;\n", | |
" event['data'] = 'scroll'\n", | |
" if (event.deltaY < 0) {\n", | |
" event.step = 1;\n", | |
" } else {\n", | |
" event.step = -1;\n", | |
" }\n", | |
" mouse_event_fn(event);\n", | |
" });\n", | |
"\n", | |
" canvas_div.append(canvas);\n", | |
" canvas_div.append(rubberband);\n", | |
"\n", | |
" this.rubberband = rubberband;\n", | |
" this.rubberband_canvas = rubberband[0];\n", | |
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n", | |
" this.rubberband_context.strokeStyle = \"#000000\";\n", | |
"\n", | |
" this._resize_canvas = function(width, height) {\n", | |
" // Keep the size of the canvas, canvas container, and rubber band\n", | |
" // canvas in synch.\n", | |
" canvas_div.css('width', width)\n", | |
" canvas_div.css('height', height)\n", | |
"\n", | |
" canvas.attr('width', width);\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 = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items) {\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) {\n", | |
" // put a spacer in here.\n", | |
" continue;\n", | |
" }\n", | |
" var button = $('<button/>');\n", | |
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n", | |
" 'ui-button-icon-only');\n", | |
" button.attr('role', 'button');\n", | |
" button.attr('aria-disabled', 'false');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
"\n", | |
" var icon_img = $('<span/>');\n", | |
" icon_img.addClass('ui-button-icon-primary ui-icon');\n", | |
" icon_img.addClass(image);\n", | |
" icon_img.addClass('ui-corner-all');\n", | |
"\n", | |
" var tooltip_span = $('<span/>');\n", | |
" tooltip_span.addClass('ui-button-text');\n", | |
" tooltip_span.html(tooltip);\n", | |
"\n", | |
" button.append(icon_img);\n", | |
" button.append(tooltip_span);\n", | |
"\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" var fmt_picker_span = $('<span/>');\n", | |
"\n", | |
" var fmt_picker = $('<select/>');\n", | |
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n", | |
" fmt_picker_span.append(fmt_picker);\n", | |
" nav_element.append(fmt_picker_span);\n", | |
" this.format_dropdown = fmt_picker[0];\n", | |
"\n", | |
" for (var ind in mpl.extensions) {\n", | |
" var fmt = mpl.extensions[ind];\n", | |
" var option = $(\n", | |
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n", | |
" fmt_picker.append(option)\n", | |
" }\n", | |
"\n", | |
" // Add hover states to the ui-buttons\n", | |
" $( \".ui-button\" ).hover(\n", | |
" function() { $(this).addClass(\"ui-state-hover\");},\n", | |
" function() { $(this).removeClass(\"ui-state-hover\");}\n", | |
" );\n", | |
"\n", | |
" var status_bar = $('<span class=\"mpl-message\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n", | |
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", | |
" // which will in turn request a refresh of the image.\n", | |
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_message = function(type, properties) {\n", | |
" properties['type'] = type;\n", | |
" properties['figure_id'] = this.id;\n", | |
" this.ws.send(JSON.stringify(properties));\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_draw_message = function() {\n", | |
" if (!this.waiting) {\n", | |
" this.waiting = true;\n", | |
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" var format_dropdown = fig.format_dropdown;\n", | |
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", | |
" fig.ondownload(fig, format);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n", | |
" var size = msg['size'];\n", | |
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n", | |
" fig._resize_canvas(size[0], size[1]);\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n", | |
" var x0 = msg['x0'];\n", | |
" var y0 = fig.canvas.height - msg['y0'];\n", | |
" var x1 = msg['x1'];\n", | |
" var y1 = fig.canvas.height - msg['y1'];\n", | |
" x0 = Math.floor(x0) + 0.5;\n", | |
" y0 = Math.floor(y0) + 0.5;\n", | |
" x1 = Math.floor(x1) + 0.5;\n", | |
" y1 = Math.floor(y1) + 0.5;\n", | |
" var min_x = Math.min(x0, x1);\n", | |
" var min_y = Math.min(y0, y1);\n", | |
" var width = Math.abs(x1 - x0);\n", | |
" var height = Math.abs(y1 - y0);\n", | |
"\n", | |
" fig.rubberband_context.clearRect(\n", | |
" 0, 0, fig.canvas.width, fig.canvas.height);\n", | |
"\n", | |
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n", | |
" // Updates the figure title.\n", | |
" fig.header.textContent = msg['label'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n", | |
" var cursor = msg['cursor'];\n", | |
" switch(cursor)\n", | |
" {\n", | |
" case 0:\n", | |
" cursor = 'pointer';\n", | |
" break;\n", | |
" case 1:\n", | |
" cursor = 'default';\n", | |
" break;\n", | |
" case 2:\n", | |
" cursor = 'crosshair';\n", | |
" break;\n", | |
" case 3:\n", | |
" cursor = 'move';\n", | |
" break;\n", | |
" }\n", | |
" fig.rubberband_canvas.style.cursor = cursor;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_message = function(fig, msg) {\n", | |
" fig.message.textContent = msg['message'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n", | |
" // Request the server to send over a new figure.\n", | |
" fig.send_draw_message();\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n", | |
" fig.image_mode = msg['mode'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Called whenever the canvas gets updated.\n", | |
" this.send_message(\"ack\", {});\n", | |
"}\n", | |
"\n", | |
"// A function to construct a web socket function for onmessage handling.\n", | |
"// Called in the figure constructor.\n", | |
"mpl.figure.prototype._make_on_message_function = function(fig) {\n", | |
" return function socket_on_message(evt) {\n", | |
" if (evt.data instanceof Blob) {\n", | |
" /* FIXME: We get \"Resource interpreted as Image but\n", | |
" * transferred with MIME type text/plain:\" errors on\n", | |
" * Chrome. But how to set the MIME type? It doesn't seem\n", | |
" * to be part of the websocket stream */\n", | |
" evt.data.type = \"image/png\";\n", | |
"\n", | |
" /* Free the memory for the previous frames */\n", | |
" if (fig.imageObj.src) {\n", | |
" (window.URL || window.webkitURL).revokeObjectURL(\n", | |
" fig.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", | |
" evt.data);\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n", | |
" fig.imageObj.src = evt.data;\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var msg = JSON.parse(evt.data);\n", | |
" var msg_type = msg['type'];\n", | |
"\n", | |
" // Call the \"handle_{type}\" callback, which takes\n", | |
" // the figure and JSON message as its only arguments.\n", | |
" try {\n", | |
" var callback = fig[\"handle_\" + msg_type];\n", | |
" } catch (e) {\n", | |
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" if (callback) {\n", | |
" try {\n", | |
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", | |
" callback(fig, msg);\n", | |
" } catch (e) {\n", | |
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n", | |
" }\n", | |
" }\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", | |
"mpl.findpos = function(e) {\n", | |
" //this section is from http://www.quirksmode.org/js/events_properties.html\n", | |
" var targ;\n", | |
" if (!e)\n", | |
" e = window.event;\n", | |
" if (e.target)\n", | |
" targ = e.target;\n", | |
" else if (e.srcElement)\n", | |
" targ = e.srcElement;\n", | |
" if (targ.nodeType == 3) // defeat Safari bug\n", | |
" targ = targ.parentNode;\n", | |
"\n", | |
" // jQuery normalizes the pageX and pageY\n", | |
" // pageX,Y are the mouse positions relative to the document\n", | |
" // offset() returns the position of the element relative to the document\n", | |
" var x = e.pageX - $(targ).offset().left;\n", | |
" var y = e.pageY - $(targ).offset().top;\n", | |
"\n", | |
" return {\"x\": x, \"y\": y};\n", | |
"};\n", | |
"\n", | |
"/*\n", | |
" * return a copy of an object with only non-object keys\n", | |
" * we need this to avoid circular references\n", | |
" * http://stackoverflow.com/a/24161582/3208463\n", | |
" */\n", | |
"function simpleKeys (original) {\n", | |
" return Object.keys(original).reduce(function (obj, key) {\n", | |
" if (typeof original[key] !== 'object')\n", | |
" obj[key] = original[key]\n", | |
" return obj;\n", | |
" }, {});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.mouse_event = function(event, name) {\n", | |
" var canvas_pos = mpl.findpos(event)\n", | |
"\n", | |
" if (name === 'button_press')\n", | |
" {\n", | |
" this.canvas.focus();\n", | |
" this.canvas_div.focus();\n", | |
" }\n", | |
"\n", | |
" var x = canvas_pos.x;\n", | |
" var y = canvas_pos.y;\n", | |
"\n", | |
" this.send_message(name, {x: x, y: y, button: event.button,\n", | |
" step: event.step,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
"\n", | |
" /* This prevents the web browser from automatically changing to\n", | |
" * the text insertion cursor when the button is pressed. We want\n", | |
" * to control all of the cursor setting manually through the\n", | |
" * 'cursor' event from matplotlib */\n", | |
" event.preventDefault();\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" // Handle any extra behaviour associated with a key event\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.key_event = function(event, name) {\n", | |
"\n", | |
" // Prevent repeat events\n", | |
" if (name == 'key_press')\n", | |
" {\n", | |
" if (event.which === this._key)\n", | |
" return;\n", | |
" else\n", | |
" this._key = event.which;\n", | |
" }\n", | |
" if (name == 'key_release')\n", | |
" this._key = null;\n", | |
"\n", | |
" var value = '';\n", | |
" if (event.ctrlKey && event.which != 17)\n", | |
" value += \"ctrl+\";\n", | |
" if (event.altKey && event.which != 18)\n", | |
" value += \"alt+\";\n", | |
" if (event.shiftKey && event.which != 16)\n", | |
" value += \"shift+\";\n", | |
"\n", | |
" value += 'k';\n", | |
" value += event.which.toString();\n", | |
"\n", | |
" this._key_event_extra(event, name);\n", | |
"\n", | |
" this.send_message(name, {key: value,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n", | |
" if (name == 'download') {\n", | |
" this.handle_save(this, null);\n", | |
" } else {\n", | |
" this.send_message(\"toolbar_button\", {name: name});\n", | |
" }\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", | |
" this.message.textContent = tooltip;\n", | |
"};\n", | |
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", | |
"\n", | |
"mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", | |
"\n", | |
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n", | |
" // Create a \"websocket\"-like object which calls the given IPython comm\n", | |
" // object with the appropriate methods. Currently this is a non binary\n", | |
" // socket, so there is still some room for performance tuning.\n", | |
" var ws = {};\n", | |
"\n", | |
" ws.close = function() {\n", | |
" comm.close()\n", | |
" };\n", | |
" ws.send = function(m) {\n", | |
" //console.log('sending', m);\n", | |
" comm.send(m);\n", | |
" };\n", | |
" // Register the callback with on_msg.\n", | |
" comm.on_msg(function(msg) {\n", | |
" //console.log('receiving', msg['content']['data'], msg);\n", | |
" // Pass the mpl event to the overriden (by mpl) onmessage function.\n", | |
" ws.onmessage(msg['content']['data'])\n", | |
" });\n", | |
" return ws;\n", | |
"}\n", | |
"\n", | |
"mpl.mpl_figure_comm = function(comm, msg) {\n", | |
" // This is the function which gets called when the mpl process\n", | |
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n", | |
"\n", | |
" var id = msg.content.data.id;\n", | |
" // Get hold of the div created by the display call when the Comm\n", | |
" // socket was opened in Python.\n", | |
" var element = $(\"#\" + id);\n", | |
" var ws_proxy = comm_websocket_adapter(comm)\n", | |
"\n", | |
" function ondownload(figure, format) {\n", | |
" window.open(figure.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" var fig = new mpl.figure(id, ws_proxy,\n", | |
" ondownload,\n", | |
" element.get(0));\n", | |
"\n", | |
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", | |
" // web socket which is closed, not our websocket->open comm proxy.\n", | |
" ws_proxy.onopen();\n", | |
"\n", | |
" fig.parent_element = element.get(0);\n", | |
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n", | |
" if (!fig.cell_info) {\n", | |
" console.error(\"Failed to find cell for figure\", id, fig);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var output_index = fig.cell_info[2]\n", | |
" var cell = fig.cell_info[0];\n", | |
"\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.handle_close = function(fig, msg) {\n", | |
" fig.root.unbind('remove')\n", | |
"\n", | |
" // Update the output cell to use the data from the current canvas.\n", | |
" fig.push_to_output();\n", | |
" var dataURL = fig.canvas.toDataURL();\n", | |
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n", | |
" // the notebook keyboard shortcuts fail.\n", | |
" IPython.keyboard_manager.enable()\n", | |
" $(fig.parent_element).html('<img src=\"' + dataURL + '\">');\n", | |
" fig.close_ws(fig, msg);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.close_ws = function(fig, msg){\n", | |
" fig.send_message('closing', msg);\n", | |
" // fig.ws.close()\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", | |
" // Turn the data on the canvas into data in the output cell.\n", | |
" var dataURL = this.canvas.toDataURL();\n", | |
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Tell IPython that the notebook contents must change.\n", | |
" IPython.notebook.set_dirty(true);\n", | |
" this.send_message(\"ack\", {});\n", | |
" var fig = this;\n", | |
" // Wait a second, then push the new image to the DOM so\n", | |
" // that it is saved nicely (might be nice to debounce this).\n", | |
" setTimeout(function () { fig.push_to_output() }, 1000);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_toolbar = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var nav_element = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items){\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) { continue; };\n", | |
"\n", | |
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" // Add the status bar.\n", | |
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"\n", | |
" // Add the close button to the window.\n", | |
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", | |
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", | |
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n", | |
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n", | |
" buttongrp.append(button);\n", | |
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", | |
" titlebar.prepend(buttongrp);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(el){\n", | |
" var fig = this\n", | |
" el.on(\"remove\", function(){\n", | |
"\tfig.close_ws(fig, {});\n", | |
" });\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(el){\n", | |
" // this is important to make the div 'focusable\n", | |
" el.attr('tabindex', 0)\n", | |
" // reach out to IPython and tell the keyboard manager to turn it's self\n", | |
" // off when our div gets focus\n", | |
"\n", | |
" // location in version 3\n", | |
" if (IPython.notebook.keyboard_manager) {\n", | |
" IPython.notebook.keyboard_manager.register_events(el);\n", | |
" }\n", | |
" else {\n", | |
" // location in version 2\n", | |
" IPython.keyboard_manager.register_events(el);\n", | |
" }\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" var manager = IPython.notebook.keyboard_manager;\n", | |
" if (!manager)\n", | |
" manager = IPython.keyboard_manager;\n", | |
"\n", | |
" // Check for shift+enter\n", | |
" if (event.shiftKey && event.which == 13) {\n", | |
" this.canvas_div.blur();\n", | |
" event.shiftKey = false;\n", | |
" // Send a \"J\" for go to next cell\n", | |
" event.which = 74;\n", | |
" event.keyCode = 74;\n", | |
" manager.command_mode();\n", | |
" manager.handle_keydown(event);\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" fig.ondownload(fig, null);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.find_output_cell = function(html_output) {\n", | |
" // Return the cell and output element which can be found *uniquely* in the notebook.\n", | |
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", | |
" // IPython event is triggered only after the cells have been serialised, which for\n", | |
" // our purposes (turning an active figure into a static one), is too late.\n", | |
" var cells = IPython.notebook.get_cells();\n", | |
" var ncells = cells.length;\n", | |
" for (var i=0; i<ncells; i++) {\n", | |
" var cell = cells[i];\n", | |
" if (cell.cell_type === 'code'){\n", | |
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n", | |
" var data = cell.output_area.outputs[j];\n", | |
" if (data.data) {\n", | |
" // IPython >= 3 moved mimebundle to data attribute of output\n", | |
" data = data.data;\n", | |
" }\n", | |
" if (data['text/html'] == html_output) {\n", | |
" return [cell, data, j];\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"// Register the function which deals with the matplotlib target/channel.\n", | |
"// The kernel may be null if the page has been refreshed.\n", | |
"if (IPython.notebook.kernel != null) {\n", | |
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", | |
"}\n" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/html": [ | |
"<img src=\"data:image/png;base64,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\">" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"# Scatter plot with linear regression\n", | |
"fig, axes = plt.subplots(3, sharey=False)\n", | |
"# Word Length\n", | |
"sns.regplot(y=binned_df['word_len'], x=x_bins, ax=axes[0])\n", | |
"axes[0].set_title('Word Length (chars)')\n", | |
"axes[0].set_ylabel('')\n", | |
"axes[0].get_xaxis().set_visible(False)\n", | |
"# Words Spacing\n", | |
"sns.regplot(y=binned_df['next_word_spacing'], x=x_bins, ax=axes[1])\n", | |
"axes[1].set_title('Words Spacing (seconds)')\n", | |
"axes[1].set_ylabel('')\n", | |
"axes[1].get_xaxis().set_visible(False)\n", | |
"# Word Speech Rate\n", | |
"sns.regplot(y=binned_df['word_speed'], x=x_bins, ax=axes[2])\n", | |
"axes[2].set_title('Word Speech Rate (chars per seconds)')\n", | |
"axes[2].set_xlabel('Bins')\n", | |
"axes[2].set_ylabel('')\n", | |
"axes[2].set_ylim([13,20])\n", | |
"\n", | |
"sns.plt.show()" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 21, | |
"metadata": { | |
"collapsed": false, | |
"scrolled": true | |
}, | |
"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 = $('<div/>');\n", | |
" this._root_extra_style(this.root)\n", | |
" this.root.attr('style', 'display: inline-block');\n", | |
"\n", | |
" $(parent_element).append(this.root);\n", | |
"\n", | |
" this._init_header(this);\n", | |
" this._init_canvas(this);\n", | |
" this._init_toolbar(this);\n", | |
"\n", | |
" var fig = this;\n", | |
"\n", | |
" this.waiting = false;\n", | |
"\n", | |
" this.ws.onopen = function () {\n", | |
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n", | |
" fig.send_message(\"send_image_mode\", {});\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" }\n", | |
"\n", | |
" this.imageObj.onload = function() {\n", | |
" if (fig.image_mode == 'full') {\n", | |
" // Full images could contain transparency (where diff images\n", | |
" // almost always do), so we need to clear the canvas so that\n", | |
" // there is no ghosting.\n", | |
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n", | |
" }\n", | |
" fig.context.drawImage(fig.imageObj, 0, 0);\n", | |
" };\n", | |
"\n", | |
" this.imageObj.onunload = function() {\n", | |
" 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", | |
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n", | |
" 'ui-helper-clearfix\"/>');\n", | |
" var titletext = $(\n", | |
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n", | |
" 'text-align: center; padding: 3px;\"/>');\n", | |
" titlebar.append(titletext)\n", | |
" this.root.append(titlebar);\n", | |
" this.header = titletext[0];\n", | |
"}\n", | |
"\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_canvas = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var canvas_div = $('<div/>');\n", | |
"\n", | |
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n", | |
"\n", | |
" function canvas_keyboard_event(event) {\n", | |
" return fig.key_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" canvas_div.keydown('key_press', canvas_keyboard_event);\n", | |
" canvas_div.keyup('key_release', canvas_keyboard_event);\n", | |
" this.canvas_div = canvas_div\n", | |
" this._canvas_extra_style(canvas_div)\n", | |
" this.root.append(canvas_div);\n", | |
"\n", | |
" var canvas = $('<canvas/>');\n", | |
" canvas.addClass('mpl-canvas');\n", | |
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n", | |
"\n", | |
" this.canvas = canvas[0];\n", | |
" this.context = canvas[0].getContext(\"2d\");\n", | |
"\n", | |
" var rubberband = $('<canvas/>');\n", | |
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n", | |
"\n", | |
" var pass_mouse_events = true;\n", | |
"\n", | |
" canvas_div.resizable({\n", | |
" start: function(event, ui) {\n", | |
" pass_mouse_events = false;\n", | |
" },\n", | |
" resize: function(event, ui) {\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" stop: function(event, ui) {\n", | |
" pass_mouse_events = true;\n", | |
" fig.request_resize(ui.size.width, ui.size.height);\n", | |
" },\n", | |
" });\n", | |
"\n", | |
" function mouse_event_fn(event) {\n", | |
" if (pass_mouse_events)\n", | |
" return fig.mouse_event(event, event['data']);\n", | |
" }\n", | |
"\n", | |
" rubberband.mousedown('button_press', mouse_event_fn);\n", | |
" rubberband.mouseup('button_release', mouse_event_fn);\n", | |
" // Throttle sequential mouse events to 1 every 20ms.\n", | |
" rubberband.mousemove('motion_notify', mouse_event_fn);\n", | |
"\n", | |
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n", | |
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n", | |
"\n", | |
" canvas_div.on(\"wheel\", function (event) {\n", | |
" event = event.originalEvent;\n", | |
" event['data'] = 'scroll'\n", | |
" if (event.deltaY < 0) {\n", | |
" event.step = 1;\n", | |
" } else {\n", | |
" event.step = -1;\n", | |
" }\n", | |
" mouse_event_fn(event);\n", | |
" });\n", | |
"\n", | |
" canvas_div.append(canvas);\n", | |
" canvas_div.append(rubberband);\n", | |
"\n", | |
" this.rubberband = rubberband;\n", | |
" this.rubberband_canvas = rubberband[0];\n", | |
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n", | |
" this.rubberband_context.strokeStyle = \"#000000\";\n", | |
"\n", | |
" this._resize_canvas = function(width, height) {\n", | |
" // Keep the size of the canvas, canvas container, and rubber band\n", | |
" // canvas in synch.\n", | |
" canvas_div.css('width', width)\n", | |
" canvas_div.css('height', height)\n", | |
"\n", | |
" canvas.attr('width', width);\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 = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items) {\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) {\n", | |
" // put a spacer in here.\n", | |
" continue;\n", | |
" }\n", | |
" var button = $('<button/>');\n", | |
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n", | |
" 'ui-button-icon-only');\n", | |
" button.attr('role', 'button');\n", | |
" button.attr('aria-disabled', 'false');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
"\n", | |
" var icon_img = $('<span/>');\n", | |
" icon_img.addClass('ui-button-icon-primary ui-icon');\n", | |
" icon_img.addClass(image);\n", | |
" icon_img.addClass('ui-corner-all');\n", | |
"\n", | |
" var tooltip_span = $('<span/>');\n", | |
" tooltip_span.addClass('ui-button-text');\n", | |
" tooltip_span.html(tooltip);\n", | |
"\n", | |
" button.append(icon_img);\n", | |
" button.append(tooltip_span);\n", | |
"\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" var fmt_picker_span = $('<span/>');\n", | |
"\n", | |
" var fmt_picker = $('<select/>');\n", | |
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n", | |
" fmt_picker_span.append(fmt_picker);\n", | |
" nav_element.append(fmt_picker_span);\n", | |
" this.format_dropdown = fmt_picker[0];\n", | |
"\n", | |
" for (var ind in mpl.extensions) {\n", | |
" var fmt = mpl.extensions[ind];\n", | |
" var option = $(\n", | |
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n", | |
" fmt_picker.append(option)\n", | |
" }\n", | |
"\n", | |
" // Add hover states to the ui-buttons\n", | |
" $( \".ui-button\" ).hover(\n", | |
" function() { $(this).addClass(\"ui-state-hover\");},\n", | |
" function() { $(this).removeClass(\"ui-state-hover\");}\n", | |
" );\n", | |
"\n", | |
" var status_bar = $('<span class=\"mpl-message\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n", | |
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n", | |
" // which will in turn request a refresh of the image.\n", | |
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_message = function(type, properties) {\n", | |
" properties['type'] = type;\n", | |
" properties['figure_id'] = this.id;\n", | |
" this.ws.send(JSON.stringify(properties));\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.send_draw_message = function() {\n", | |
" if (!this.waiting) {\n", | |
" this.waiting = true;\n", | |
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" var format_dropdown = fig.format_dropdown;\n", | |
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n", | |
" fig.ondownload(fig, format);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n", | |
" var size = msg['size'];\n", | |
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n", | |
" fig._resize_canvas(size[0], size[1]);\n", | |
" fig.send_message(\"refresh\", {});\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n", | |
" var x0 = msg['x0'];\n", | |
" var y0 = fig.canvas.height - msg['y0'];\n", | |
" var x1 = msg['x1'];\n", | |
" var y1 = fig.canvas.height - msg['y1'];\n", | |
" x0 = Math.floor(x0) + 0.5;\n", | |
" y0 = Math.floor(y0) + 0.5;\n", | |
" x1 = Math.floor(x1) + 0.5;\n", | |
" y1 = Math.floor(y1) + 0.5;\n", | |
" var min_x = Math.min(x0, x1);\n", | |
" var min_y = Math.min(y0, y1);\n", | |
" var width = Math.abs(x1 - x0);\n", | |
" var height = Math.abs(y1 - y0);\n", | |
"\n", | |
" fig.rubberband_context.clearRect(\n", | |
" 0, 0, fig.canvas.width, fig.canvas.height);\n", | |
"\n", | |
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n", | |
" // Updates the figure title.\n", | |
" fig.header.textContent = msg['label'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n", | |
" var cursor = msg['cursor'];\n", | |
" switch(cursor)\n", | |
" {\n", | |
" case 0:\n", | |
" cursor = 'pointer';\n", | |
" break;\n", | |
" case 1:\n", | |
" cursor = 'default';\n", | |
" break;\n", | |
" case 2:\n", | |
" cursor = 'crosshair';\n", | |
" break;\n", | |
" case 3:\n", | |
" cursor = 'move';\n", | |
" break;\n", | |
" }\n", | |
" fig.rubberband_canvas.style.cursor = cursor;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_message = function(fig, msg) {\n", | |
" fig.message.textContent = msg['message'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n", | |
" // Request the server to send over a new figure.\n", | |
" fig.send_draw_message();\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n", | |
" fig.image_mode = msg['mode'];\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Called whenever the canvas gets updated.\n", | |
" this.send_message(\"ack\", {});\n", | |
"}\n", | |
"\n", | |
"// A function to construct a web socket function for onmessage handling.\n", | |
"// Called in the figure constructor.\n", | |
"mpl.figure.prototype._make_on_message_function = function(fig) {\n", | |
" return function socket_on_message(evt) {\n", | |
" if (evt.data instanceof Blob) {\n", | |
" /* FIXME: We get \"Resource interpreted as Image but\n", | |
" * transferred with MIME type text/plain:\" errors on\n", | |
" * Chrome. But how to set the MIME type? It doesn't seem\n", | |
" * to be part of the websocket stream */\n", | |
" evt.data.type = \"image/png\";\n", | |
"\n", | |
" /* Free the memory for the previous frames */\n", | |
" if (fig.imageObj.src) {\n", | |
" (window.URL || window.webkitURL).revokeObjectURL(\n", | |
" fig.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n", | |
" evt.data);\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n", | |
" fig.imageObj.src = evt.data;\n", | |
" fig.updated_canvas_event();\n", | |
" fig.waiting = false;\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var msg = JSON.parse(evt.data);\n", | |
" var msg_type = msg['type'];\n", | |
"\n", | |
" // Call the \"handle_{type}\" callback, which takes\n", | |
" // the figure and JSON message as its only arguments.\n", | |
" try {\n", | |
" var callback = fig[\"handle_\" + msg_type];\n", | |
" } catch (e) {\n", | |
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" if (callback) {\n", | |
" try {\n", | |
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n", | |
" callback(fig, msg);\n", | |
" } catch (e) {\n", | |
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n", | |
" }\n", | |
" }\n", | |
" };\n", | |
"}\n", | |
"\n", | |
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n", | |
"mpl.findpos = function(e) {\n", | |
" //this section is from http://www.quirksmode.org/js/events_properties.html\n", | |
" var targ;\n", | |
" if (!e)\n", | |
" e = window.event;\n", | |
" if (e.target)\n", | |
" targ = e.target;\n", | |
" else if (e.srcElement)\n", | |
" targ = e.srcElement;\n", | |
" if (targ.nodeType == 3) // defeat Safari bug\n", | |
" targ = targ.parentNode;\n", | |
"\n", | |
" // jQuery normalizes the pageX and pageY\n", | |
" // pageX,Y are the mouse positions relative to the document\n", | |
" // offset() returns the position of the element relative to the document\n", | |
" var x = e.pageX - $(targ).offset().left;\n", | |
" var y = e.pageY - $(targ).offset().top;\n", | |
"\n", | |
" return {\"x\": x, \"y\": y};\n", | |
"};\n", | |
"\n", | |
"/*\n", | |
" * return a copy of an object with only non-object keys\n", | |
" * we need this to avoid circular references\n", | |
" * http://stackoverflow.com/a/24161582/3208463\n", | |
" */\n", | |
"function simpleKeys (original) {\n", | |
" return Object.keys(original).reduce(function (obj, key) {\n", | |
" if (typeof original[key] !== 'object')\n", | |
" obj[key] = original[key]\n", | |
" return obj;\n", | |
" }, {});\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.mouse_event = function(event, name) {\n", | |
" var canvas_pos = mpl.findpos(event)\n", | |
"\n", | |
" if (name === 'button_press')\n", | |
" {\n", | |
" this.canvas.focus();\n", | |
" this.canvas_div.focus();\n", | |
" }\n", | |
"\n", | |
" var x = canvas_pos.x;\n", | |
" var y = canvas_pos.y;\n", | |
"\n", | |
" this.send_message(name, {x: x, y: y, button: event.button,\n", | |
" step: event.step,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
"\n", | |
" /* This prevents the web browser from automatically changing to\n", | |
" * the text insertion cursor when the button is pressed. We want\n", | |
" * to control all of the cursor setting manually through the\n", | |
" * 'cursor' event from matplotlib */\n", | |
" event.preventDefault();\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" // Handle any extra behaviour associated with a key event\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.key_event = function(event, name) {\n", | |
"\n", | |
" // Prevent repeat events\n", | |
" if (name == 'key_press')\n", | |
" {\n", | |
" if (event.which === this._key)\n", | |
" return;\n", | |
" else\n", | |
" this._key = event.which;\n", | |
" }\n", | |
" if (name == 'key_release')\n", | |
" this._key = null;\n", | |
"\n", | |
" var value = '';\n", | |
" if (event.ctrlKey && event.which != 17)\n", | |
" value += \"ctrl+\";\n", | |
" if (event.altKey && event.which != 18)\n", | |
" value += \"alt+\";\n", | |
" if (event.shiftKey && event.which != 16)\n", | |
" value += \"shift+\";\n", | |
"\n", | |
" value += 'k';\n", | |
" value += event.which.toString();\n", | |
"\n", | |
" this._key_event_extra(event, name);\n", | |
"\n", | |
" this.send_message(name, {key: value,\n", | |
" guiEvent: simpleKeys(event)});\n", | |
" return false;\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n", | |
" if (name == 'download') {\n", | |
" this.handle_save(this, null);\n", | |
" } else {\n", | |
" this.send_message(\"toolbar_button\", {name: name});\n", | |
" }\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n", | |
" this.message.textContent = tooltip;\n", | |
"};\n", | |
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n", | |
"\n", | |
"mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n", | |
"\n", | |
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n", | |
" // Create a \"websocket\"-like object which calls the given IPython comm\n", | |
" // object with the appropriate methods. Currently this is a non binary\n", | |
" // socket, so there is still some room for performance tuning.\n", | |
" var ws = {};\n", | |
"\n", | |
" ws.close = function() {\n", | |
" comm.close()\n", | |
" };\n", | |
" ws.send = function(m) {\n", | |
" //console.log('sending', m);\n", | |
" comm.send(m);\n", | |
" };\n", | |
" // Register the callback with on_msg.\n", | |
" comm.on_msg(function(msg) {\n", | |
" //console.log('receiving', msg['content']['data'], msg);\n", | |
" // Pass the mpl event to the overriden (by mpl) onmessage function.\n", | |
" ws.onmessage(msg['content']['data'])\n", | |
" });\n", | |
" return ws;\n", | |
"}\n", | |
"\n", | |
"mpl.mpl_figure_comm = function(comm, msg) {\n", | |
" // This is the function which gets called when the mpl process\n", | |
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n", | |
"\n", | |
" var id = msg.content.data.id;\n", | |
" // Get hold of the div created by the display call when the Comm\n", | |
" // socket was opened in Python.\n", | |
" var element = $(\"#\" + id);\n", | |
" var ws_proxy = comm_websocket_adapter(comm)\n", | |
"\n", | |
" function ondownload(figure, format) {\n", | |
" window.open(figure.imageObj.src);\n", | |
" }\n", | |
"\n", | |
" var fig = new mpl.figure(id, ws_proxy,\n", | |
" ondownload,\n", | |
" element.get(0));\n", | |
"\n", | |
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n", | |
" // web socket which is closed, not our websocket->open comm proxy.\n", | |
" ws_proxy.onopen();\n", | |
"\n", | |
" fig.parent_element = element.get(0);\n", | |
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n", | |
" if (!fig.cell_info) {\n", | |
" console.error(\"Failed to find cell for figure\", id, fig);\n", | |
" return;\n", | |
" }\n", | |
"\n", | |
" var output_index = fig.cell_info[2]\n", | |
" var cell = fig.cell_info[0];\n", | |
"\n", | |
"};\n", | |
"\n", | |
"mpl.figure.prototype.handle_close = function(fig, msg) {\n", | |
" fig.root.unbind('remove')\n", | |
"\n", | |
" // Update the output cell to use the data from the current canvas.\n", | |
" fig.push_to_output();\n", | |
" var dataURL = fig.canvas.toDataURL();\n", | |
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n", | |
" // the notebook keyboard shortcuts fail.\n", | |
" IPython.keyboard_manager.enable()\n", | |
" $(fig.parent_element).html('<img src=\"' + dataURL + '\">');\n", | |
" fig.close_ws(fig, msg);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.close_ws = function(fig, msg){\n", | |
" fig.send_message('closing', msg);\n", | |
" // fig.ws.close()\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n", | |
" // Turn the data on the canvas into data in the output cell.\n", | |
" var dataURL = this.canvas.toDataURL();\n", | |
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\">';\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.updated_canvas_event = function() {\n", | |
" // Tell IPython that the notebook contents must change.\n", | |
" IPython.notebook.set_dirty(true);\n", | |
" this.send_message(\"ack\", {});\n", | |
" var fig = this;\n", | |
" // Wait a second, then push the new image to the DOM so\n", | |
" // that it is saved nicely (might be nice to debounce this).\n", | |
" setTimeout(function () { fig.push_to_output() }, 1000);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._init_toolbar = function() {\n", | |
" var fig = this;\n", | |
"\n", | |
" var nav_element = $('<div/>')\n", | |
" nav_element.attr('style', 'width: 100%');\n", | |
" this.root.append(nav_element);\n", | |
"\n", | |
" // Define a callback function for later on.\n", | |
" function toolbar_event(event) {\n", | |
" return fig.toolbar_button_onclick(event['data']);\n", | |
" }\n", | |
" function toolbar_mouse_event(event) {\n", | |
" return fig.toolbar_button_onmouseover(event['data']);\n", | |
" }\n", | |
"\n", | |
" for(var toolbar_ind in mpl.toolbar_items){\n", | |
" var name = mpl.toolbar_items[toolbar_ind][0];\n", | |
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n", | |
" var image = mpl.toolbar_items[toolbar_ind][2];\n", | |
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n", | |
"\n", | |
" if (!name) { continue; };\n", | |
"\n", | |
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n", | |
" button.click(method_name, toolbar_event);\n", | |
" button.mouseover(tooltip, toolbar_mouse_event);\n", | |
" nav_element.append(button);\n", | |
" }\n", | |
"\n", | |
" // Add the status bar.\n", | |
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n", | |
" nav_element.append(status_bar);\n", | |
" this.message = status_bar[0];\n", | |
"\n", | |
" // Add the close button to the window.\n", | |
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n", | |
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n", | |
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n", | |
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n", | |
" buttongrp.append(button);\n", | |
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n", | |
" titlebar.prepend(buttongrp);\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._root_extra_style = function(el){\n", | |
" var fig = this\n", | |
" el.on(\"remove\", function(){\n", | |
"\tfig.close_ws(fig, {});\n", | |
" });\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._canvas_extra_style = function(el){\n", | |
" // this is important to make the div 'focusable\n", | |
" el.attr('tabindex', 0)\n", | |
" // reach out to IPython and tell the keyboard manager to turn it's self\n", | |
" // off when our div gets focus\n", | |
"\n", | |
" // location in version 3\n", | |
" if (IPython.notebook.keyboard_manager) {\n", | |
" IPython.notebook.keyboard_manager.register_events(el);\n", | |
" }\n", | |
" else {\n", | |
" // location in version 2\n", | |
" IPython.keyboard_manager.register_events(el);\n", | |
" }\n", | |
"\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype._key_event_extra = function(event, name) {\n", | |
" var manager = IPython.notebook.keyboard_manager;\n", | |
" if (!manager)\n", | |
" manager = IPython.keyboard_manager;\n", | |
"\n", | |
" // Check for shift+enter\n", | |
" if (event.shiftKey && event.which == 13) {\n", | |
" this.canvas_div.blur();\n", | |
" event.shiftKey = false;\n", | |
" // Send a \"J\" for go to next cell\n", | |
" event.which = 74;\n", | |
" event.keyCode = 74;\n", | |
" manager.command_mode();\n", | |
" manager.handle_keydown(event);\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"mpl.figure.prototype.handle_save = function(fig, msg) {\n", | |
" fig.ondownload(fig, null);\n", | |
"}\n", | |
"\n", | |
"\n", | |
"mpl.find_output_cell = function(html_output) {\n", | |
" // Return the cell and output element which can be found *uniquely* in the notebook.\n", | |
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n", | |
" // IPython event is triggered only after the cells have been serialised, which for\n", | |
" // our purposes (turning an active figure into a static one), is too late.\n", | |
" var cells = IPython.notebook.get_cells();\n", | |
" var ncells = cells.length;\n", | |
" for (var i=0; i<ncells; i++) {\n", | |
" var cell = cells[i];\n", | |
" if (cell.cell_type === 'code'){\n", | |
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n", | |
" var data = cell.output_area.outputs[j];\n", | |
" if (data.data) {\n", | |
" // IPython >= 3 moved mimebundle to data attribute of output\n", | |
" data = data.data;\n", | |
" }\n", | |
" if (data['text/html'] == html_output) {\n", | |
" return [cell, data, j];\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
" }\n", | |
"}\n", | |
"\n", | |
"// Register the function which deals with the matplotlib target/channel.\n", | |
"// The kernel may be null if the page has been refreshed.\n", | |
"if (IPython.notebook.kernel != null) {\n", | |
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n", | |
"}\n" | |
], | |
"text/plain": [ | |
"<IPython.core.display.Javascript object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
}, | |
{ | |
"data": { | |
"text/html": [ | |
"<img src=\"data:image/png;base64,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\">" | |
], | |
"text/plain": [ | |
"<IPython.core.display.HTML object>" | |
] | |
}, | |
"metadata": {}, | |
"output_type": "display_data" | |
} | |
], | |
"source": [ | |
"# Visualize HESITATION distributiona across time\n", | |
"sns.violinplot(x=df[df['word']=='%HESITATION']['time_start'].values, inner=\"stick\")\n", | |
"ax = sns.stripplot(x=df[df['word']=='%HESITATION']['time_start'].values, palette=\"Set2\")\n", | |
"ax.set_xlim(-500)\n", | |
"ax.set_xlabel('seconds')\n", | |
"sns.plt.show()" | |
] | |
} | |
], | |
"metadata": { | |
"anaconda-cloud": {}, | |
"kernelspec": { | |
"display_name": "Python [conda env:fitbit-analyzer]", | |
"language": "python", | |
"name": "conda-env-fitbit-analyzer-py" | |
}, | |
"language_info": { | |
"codemirror_mode": { | |
"name": "ipython", | |
"version": 3 | |
}, | |
"file_extension": ".py", | |
"mimetype": "text/x-python", | |
"name": "python", | |
"nbconvert_exporter": "python", | |
"pygments_lexer": "ipython3", | |
"version": "3.5.1" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 0 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment