Skip to content

Instantly share code, notes, and snippets.

@joshcarter
Created May 30, 2019 22:38
Show Gist options
  • Save joshcarter/6fdcda1fc3a3a97387ede3b41134e8d1 to your computer and use it in GitHub Desktop.
Save joshcarter/6fdcda1fc3a3a97387ede3b41134e8d1 to your computer and use it in GitHub Desktop.
Python notebook test
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"import statistics\n",
"%matplotlib notebook\n",
"import matplotlib.pyplot as plt\n",
"import numpy as np"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Question 1\n",
"\n",
"How Many Times Do You Read During A Week?"
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Mean: 18.2\n",
"Median: 14.0\n",
"Mode error: no unique mode; found 3 equally common values\n"
]
}
],
"source": [
"responses = [7, 25, 5, 7, 30, 25, 3, 25, 30, 14, 50, 16, \n",
" 17, 50, 3, 0, 0, 13, 10, 14, 50, 7]\n",
"print(f\"Mean: {statistics.mean(responses):.1f}\")\n",
"print(f\"Median: {statistics.median(responses):.1f}\")\n",
"try:\n",
" print(f\"Mode: {statistics.mode(responses)}\")\n",
"except statistics.StatisticsError as e:\n",
" print(f\"Mode error: {e}\")\n",
" "
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"data": {
"application/javascript": [
"/* Put everything inside the global mpl namespace */\n",
"window.mpl = {};\n",
"\n",
"\n",
"mpl.get_websocket_type = function() {\n",
" if (typeof(WebSocket) !== 'undefined') {\n",
" return WebSocket;\n",
" } else if (typeof(MozWebSocket) !== 'undefined') {\n",
" return MozWebSocket;\n",
" } else {\n",
" alert('Your browser does not have WebSocket support.' +\n",
" 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
" 'Firefox 4 and 5 are also supported but you ' +\n",
" 'have to enable WebSockets in about:config.');\n",
" };\n",
"}\n",
"\n",
"mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
" this.id = figure_id;\n",
"\n",
" this.ws = websocket;\n",
"\n",
" this.supports_binary = (this.ws.binaryType != undefined);\n",
"\n",
" if (!this.supports_binary) {\n",
" var warnings = document.getElementById(\"mpl-warnings\");\n",
" if (warnings) {\n",
" warnings.style.display = 'block';\n",
" warnings.textContent = (\n",
" \"This browser does not support binary websocket messages. \" +\n",
" \"Performance may be slow.\");\n",
" }\n",
" }\n",
"\n",
" this.imageObj = new Image();\n",
"\n",
" this.context = undefined;\n",
" this.message = undefined;\n",
" this.canvas = undefined;\n",
" this.rubberband_canvas = undefined;\n",
" this.rubberband_context = undefined;\n",
" this.format_dropdown = undefined;\n",
"\n",
" this.image_mode = 'full';\n",
"\n",
" this.root = $('<div/>');\n",
" this._root_extra_style(this.root)\n",
" this.root.attr('style', 'display: inline-block');\n",
"\n",
" $(parent_element).append(this.root);\n",
"\n",
" this._init_header(this);\n",
" this._init_canvas(this);\n",
" this._init_toolbar(this);\n",
"\n",
" var fig = this;\n",
"\n",
" this.waiting = false;\n",
"\n",
" this.ws.onopen = function () {\n",
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
" fig.send_message(\"send_image_mode\", {});\n",
" if (mpl.ratio != 1) {\n",
" fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
" }\n",
" fig.send_message(\"refresh\", {});\n",
" }\n",
"\n",
" this.imageObj.onload = function() {\n",
" if (fig.image_mode == 'full') {\n",
" // Full images could contain transparency (where diff images\n",
" // almost always do), so we need to clear the canvas so that\n",
" // there is no ghosting.\n",
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
" }\n",
" fig.context.drawImage(fig.imageObj, 0, 0);\n",
" };\n",
"\n",
" this.imageObj.onunload = function() {\n",
" 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 backingStore = this.context.backingStorePixelRatio ||\n",
"\tthis.context.webkitBackingStorePixelRatio ||\n",
"\tthis.context.mozBackingStorePixelRatio ||\n",
"\tthis.context.msBackingStorePixelRatio ||\n",
"\tthis.context.oBackingStorePixelRatio ||\n",
"\tthis.context.backingStorePixelRatio || 1;\n",
"\n",
" mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
"\n",
" var rubberband = $('<canvas/>');\n",
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
"\n",
" var pass_mouse_events = true;\n",
"\n",
" canvas_div.resizable({\n",
" start: function(event, ui) {\n",
" pass_mouse_events = false;\n",
" },\n",
" resize: function(event, ui) {\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" stop: function(event, ui) {\n",
" pass_mouse_events = true;\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" });\n",
"\n",
" function mouse_event_fn(event) {\n",
" if (pass_mouse_events)\n",
" return fig.mouse_event(event, event['data']);\n",
" }\n",
"\n",
" rubberband.mousedown('button_press', mouse_event_fn);\n",
" rubberband.mouseup('button_release', mouse_event_fn);\n",
" // Throttle sequential mouse events to 1 every 20ms.\n",
" rubberband.mousemove('motion_notify', mouse_event_fn);\n",
"\n",
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
"\n",
" canvas_div.on(\"wheel\", function (event) {\n",
" event = event.originalEvent;\n",
" event['data'] = 'scroll'\n",
" if (event.deltaY < 0) {\n",
" event.step = 1;\n",
" } else {\n",
" event.step = -1;\n",
" }\n",
" mouse_event_fn(event);\n",
" });\n",
"\n",
" canvas_div.append(canvas);\n",
" canvas_div.append(rubberband);\n",
"\n",
" this.rubberband = rubberband;\n",
" this.rubberband_canvas = rubberband[0];\n",
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
" this.rubberband_context.strokeStyle = \"#000000\";\n",
"\n",
" this._resize_canvas = function(width, height) {\n",
" // Keep the size of the canvas, canvas container, and rubber band\n",
" // canvas in synch.\n",
" canvas_div.css('width', width)\n",
" canvas_div.css('height', height)\n",
"\n",
" canvas.attr('width', width * mpl.ratio);\n",
" canvas.attr('height', height * mpl.ratio);\n",
" canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
"\n",
" rubberband.attr('width', width);\n",
" rubberband.attr('height', height);\n",
" }\n",
"\n",
" // Set the figure to an initial 600x600px, this will subsequently be updated\n",
" // upon first draw.\n",
" this._resize_canvas(600, 600);\n",
"\n",
" // Disable right mouse context menu.\n",
" $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
" return false;\n",
" });\n",
"\n",
" function set_focus () {\n",
" canvas.focus();\n",
" canvas_div.focus();\n",
" }\n",
"\n",
" window.setTimeout(set_focus, 100);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items) {\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) {\n",
" // put a spacer in here.\n",
" continue;\n",
" }\n",
" var button = $('<button/>');\n",
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
" 'ui-button-icon-only');\n",
" button.attr('role', 'button');\n",
" button.attr('aria-disabled', 'false');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
"\n",
" var icon_img = $('<span/>');\n",
" icon_img.addClass('ui-button-icon-primary ui-icon');\n",
" icon_img.addClass(image);\n",
" icon_img.addClass('ui-corner-all');\n",
"\n",
" var tooltip_span = $('<span/>');\n",
" tooltip_span.addClass('ui-button-text');\n",
" tooltip_span.html(tooltip);\n",
"\n",
" button.append(icon_img);\n",
" button.append(tooltip_span);\n",
"\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" var fmt_picker_span = $('<span/>');\n",
"\n",
" var fmt_picker = $('<select/>');\n",
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
" fmt_picker_span.append(fmt_picker);\n",
" nav_element.append(fmt_picker_span);\n",
" this.format_dropdown = fmt_picker[0];\n",
"\n",
" for (var ind in mpl.extensions) {\n",
" var fmt = mpl.extensions[ind];\n",
" var option = $(\n",
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
" fmt_picker.append(option)\n",
" }\n",
"\n",
" // Add hover states to the ui-buttons\n",
" $( \".ui-button\" ).hover(\n",
" function() { $(this).addClass(\"ui-state-hover\");},\n",
" function() { $(this).removeClass(\"ui-state-hover\");}\n",
" );\n",
"\n",
" var status_bar = $('<span class=\"mpl-message\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"}\n",
"\n",
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
" // which will in turn request a refresh of the image.\n",
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
"}\n",
"\n",
"mpl.figure.prototype.send_message = function(type, properties) {\n",
" properties['type'] = type;\n",
" properties['figure_id'] = this.id;\n",
" this.ws.send(JSON.stringify(properties));\n",
"}\n",
"\n",
"mpl.figure.prototype.send_draw_message = function() {\n",
" if (!this.waiting) {\n",
" this.waiting = true;\n",
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
" }\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" var format_dropdown = fig.format_dropdown;\n",
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
" fig.ondownload(fig, format);\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
" var size = msg['size'];\n",
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
" fig._resize_canvas(size[0], size[1]);\n",
" fig.send_message(\"refresh\", {});\n",
" };\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
" var x0 = msg['x0'] / mpl.ratio;\n",
" var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
" var x1 = msg['x1'] / mpl.ratio;\n",
" var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
" x0 = Math.floor(x0) + 0.5;\n",
" y0 = Math.floor(y0) + 0.5;\n",
" x1 = Math.floor(x1) + 0.5;\n",
" y1 = Math.floor(y1) + 0.5;\n",
" var min_x = Math.min(x0, x1);\n",
" var min_y = Math.min(y0, y1);\n",
" var width = Math.abs(x1 - x0);\n",
" var height = Math.abs(y1 - y0);\n",
"\n",
" fig.rubberband_context.clearRect(\n",
" 0, 0, fig.canvas.width, fig.canvas.height);\n",
"\n",
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
" // Updates the figure title.\n",
" fig.header.textContent = msg['label'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
" var cursor = msg['cursor'];\n",
" switch(cursor)\n",
" {\n",
" case 0:\n",
" cursor = 'pointer';\n",
" break;\n",
" case 1:\n",
" cursor = 'default';\n",
" break;\n",
" case 2:\n",
" cursor = 'crosshair';\n",
" break;\n",
" case 3:\n",
" cursor = 'move';\n",
" break;\n",
" }\n",
" fig.rubberband_canvas.style.cursor = cursor;\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_message = function(fig, msg) {\n",
" fig.message.textContent = msg['message'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
" // Request the server to send over a new figure.\n",
" fig.send_draw_message();\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
" fig.image_mode = msg['mode'];\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Called whenever the canvas gets updated.\n",
" this.send_message(\"ack\", {});\n",
"}\n",
"\n",
"// A function to construct a web socket function for onmessage handling.\n",
"// Called in the figure constructor.\n",
"mpl.figure.prototype._make_on_message_function = function(fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
" /* FIXME: We get \"Resource interpreted as Image but\n",
" * transferred with MIME type text/plain:\" errors on\n",
" * Chrome. But how to set the MIME type? It doesn't seem\n",
" * to be part of the websocket stream */\n",
" evt.data.type = \"image/png\";\n",
"\n",
" /* Free the memory for the previous frames */\n",
" if (fig.imageObj.src) {\n",
" (window.URL || window.webkitURL).revokeObjectURL(\n",
" fig.imageObj.src);\n",
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
" evt.data);\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
" fig.imageObj.src = evt.data;\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
"\n",
" var msg = JSON.parse(evt.data);\n",
" var msg_type = msg['type'];\n",
"\n",
" // Call the \"handle_{type}\" callback, which takes\n",
" // the figure and JSON message as its only arguments.\n",
" try {\n",
" var callback = fig[\"handle_\" + msg_type];\n",
" } catch (e) {\n",
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
" return;\n",
" }\n",
"\n",
" if (callback) {\n",
" try {\n",
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
" callback(fig, msg);\n",
" } catch (e) {\n",
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
" }\n",
" }\n",
" };\n",
"}\n",
"\n",
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
"mpl.findpos = function(e) {\n",
" //this section is from http://www.quirksmode.org/js/events_properties.html\n",
" var targ;\n",
" if (!e)\n",
" e = window.event;\n",
" if (e.target)\n",
" targ = e.target;\n",
" else if (e.srcElement)\n",
" targ = e.srcElement;\n",
" if (targ.nodeType == 3) // defeat Safari bug\n",
" targ = targ.parentNode;\n",
"\n",
" // jQuery normalizes the pageX and pageY\n",
" // pageX,Y are the mouse positions relative to the document\n",
" // offset() returns the position of the element relative to the document\n",
" var x = e.pageX - $(targ).offset().left;\n",
" var y = e.pageY - $(targ).offset().top;\n",
"\n",
" return {\"x\": x, \"y\": y};\n",
"};\n",
"\n",
"/*\n",
" * return a copy of an object with only non-object keys\n",
" * we need this to avoid circular references\n",
" * http://stackoverflow.com/a/24161582/3208463\n",
" */\n",
"function simpleKeys (original) {\n",
" return Object.keys(original).reduce(function (obj, key) {\n",
" if (typeof original[key] !== 'object')\n",
" obj[key] = original[key]\n",
" return obj;\n",
" }, {});\n",
"}\n",
"\n",
"mpl.figure.prototype.mouse_event = function(event, name) {\n",
" var canvas_pos = mpl.findpos(event)\n",
"\n",
" if (name === 'button_press')\n",
" {\n",
" this.canvas.focus();\n",
" this.canvas_div.focus();\n",
" }\n",
"\n",
" var x = canvas_pos.x * mpl.ratio;\n",
" var y = canvas_pos.y * mpl.ratio;\n",
"\n",
" this.send_message(name, {x: x, y: y, button: event.button,\n",
" step: event.step,\n",
" guiEvent: simpleKeys(event)});\n",
"\n",
" /* This prevents the web browser from automatically changing to\n",
" * the text insertion cursor when the button is pressed. We want\n",
" * to control all of the cursor setting manually through the\n",
" * 'cursor' event from matplotlib */\n",
" event.preventDefault();\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" // Handle any extra behaviour associated with a key event\n",
"}\n",
"\n",
"mpl.figure.prototype.key_event = function(event, name) {\n",
"\n",
" // Prevent repeat events\n",
" if (name == 'key_press')\n",
" {\n",
" if (event.which === this._key)\n",
" return;\n",
" else\n",
" this._key = event.which;\n",
" }\n",
" if (name == 'key_release')\n",
" this._key = null;\n",
"\n",
" var value = '';\n",
" if (event.ctrlKey && event.which != 17)\n",
" value += \"ctrl+\";\n",
" if (event.altKey && event.which != 18)\n",
" value += \"alt+\";\n",
" if (event.shiftKey && event.which != 16)\n",
" value += \"shift+\";\n",
"\n",
" value += 'k';\n",
" value += event.which.toString();\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
" this.send_message(name, {key: value,\n",
" guiEvent: simpleKeys(event)});\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
" if (name == 'download') {\n",
" this.handle_save(this, null);\n",
" } else {\n",
" this.send_message(\"toolbar_button\", {name: name});\n",
" }\n",
"};\n",
"\n",
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
" this.message.textContent = tooltip;\n",
"};\n",
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
"\n",
"mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
" // Create a \"websocket\"-like object which calls the given IPython comm\n",
" // object with the appropriate methods. Currently this is a non binary\n",
" // socket, so there is still some room for performance tuning.\n",
" var ws = {};\n",
"\n",
" ws.close = function() {\n",
" comm.close()\n",
" };\n",
" ws.send = function(m) {\n",
" //console.log('sending', m);\n",
" comm.send(m);\n",
" };\n",
" // Register the callback with on_msg.\n",
" comm.on_msg(function(msg) {\n",
" //console.log('receiving', msg['content']['data'], msg);\n",
" // Pass the mpl event to the 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",
" var width = fig.canvas.width/mpl.ratio\n",
" fig.root.unbind('remove')\n",
"\n",
" // Update the output cell to use the data from the current canvas.\n",
" fig.push_to_output();\n",
" var dataURL = fig.canvas.toDataURL();\n",
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
" // the notebook keyboard shortcuts fail.\n",
" IPython.keyboard_manager.enable()\n",
" $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
" fig.close_ws(fig, msg);\n",
"}\n",
"\n",
"mpl.figure.prototype.close_ws = function(fig, msg){\n",
" fig.send_message('closing', msg);\n",
" // fig.ws.close()\n",
"}\n",
"\n",
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
" // Turn the data on the canvas into data in the output cell.\n",
" var width = this.canvas.width/mpl.ratio\n",
" var dataURL = this.canvas.toDataURL();\n",
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Tell IPython that the notebook contents must change.\n",
" IPython.notebook.set_dirty(true);\n",
" this.send_message(\"ack\", {});\n",
" var fig = this;\n",
" // Wait a second, then push the new image to the DOM so\n",
" // that it is saved nicely (might be nice to debounce this).\n",
" setTimeout(function () { fig.push_to_output() }, 1000);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items){\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) { continue; };\n",
"\n",
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" // Add the status bar.\n",
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"\n",
" // Add the close button to the window.\n",
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
" buttongrp.append(button);\n",
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
" titlebar.prepend(buttongrp);\n",
"}\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(el){\n",
" var fig = this\n",
" el.on(\"remove\", function(){\n",
"\tfig.close_ws(fig, {});\n",
" });\n",
"}\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(el){\n",
" // this is important to make the div 'focusable\n",
" el.attr('tabindex', 0)\n",
" // reach out to IPython and tell the keyboard manager to turn it's self\n",
" // off when our div gets focus\n",
"\n",
" // location in version 3\n",
" if (IPython.notebook.keyboard_manager) {\n",
" IPython.notebook.keyboard_manager.register_events(el);\n",
" }\n",
" else {\n",
" // location in version 2\n",
" IPython.keyboard_manager.register_events(el);\n",
" }\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" var manager = IPython.notebook.keyboard_manager;\n",
" if (!manager)\n",
" manager = IPython.keyboard_manager;\n",
"\n",
" // Check for shift+enter\n",
" if (event.shiftKey && event.which == 13) {\n",
" this.canvas_div.blur();\n",
" // select the cell after this one\n",
" var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
" IPython.notebook.select(index + 1);\n",
" }\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" fig.ondownload(fig, null);\n",
"}\n",
"\n",
"\n",
"mpl.find_output_cell = function(html_output) {\n",
" // Return the cell and output element which can be found *uniquely* in the notebook.\n",
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
" // IPython event is triggered only after the cells have been serialised, which for\n",
" // our purposes (turning an active figure into a static one), is too late.\n",
" var cells = IPython.notebook.get_cells();\n",
" var ncells = cells.length;\n",
" for (var i=0; i<ncells; i++) {\n",
" var cell = cells[i];\n",
" if (cell.cell_type === 'code'){\n",
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
" var data = cell.output_area.outputs[j];\n",
" if (data.data) {\n",
" // IPython >= 3 moved mimebundle to data attribute of output\n",
" data = data.data;\n",
" }\n",
" if (data['text/html'] == html_output) {\n",
" return [cell, data, j];\n",
" }\n",
" }\n",
" }\n",
" }\n",
"}\n",
"\n",
"// Register the function which deals with the matplotlib target/channel.\n",
"// The kernel may be null if the page has been refreshed.\n",
"if (IPython.notebook.kernel != null) {\n",
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
"}\n"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<img src=\"data:image/png;base64,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EICDHoxtEVhAQAAKwOoYCcCqoPUEBhUQgIMejG0RWEBAAArA6hgJwKqg9QQGFRCAgx6MbRFYQEAACsDqGAnAqqD1BAYVEICDHoxtEVhAQAAKwOoYCcCqoPUEBhUQgIMejG0RWEBAAArA6hgJwKqg9QQGFRCAgx6MbRFYQEAACsDqGAnAqqD1BAYVEICDHoxtEVhAQAAKwOoYCcCqoPUEBhUQgIMejG0RWEBAAArA6hgJwKqg9QQGFRCAgx6MbRFYQEAACsDqGAnAqqD1BAYVEICDHoxtEVhAQAAKwOoYCcCqoPUEBhUQgIMejG0RWEBAAArA6hgJwKqg9QQGFRCAgx6MbRFYQEAACsDqGAnAqqD1BAYVEICDHoxtEVhAQAAKwOoYCcCqoPUEBhUQgIMejG0RWEBAAArA6hgJwKqg9QQGFRCAgx6MbRFYQEAACsDqGAnAqqD1BAYVEICDHoxtEVhAQAAKwOoYCcCqoPUEBhUQgIMejG0RWEBAAArA6hgJwKqg9QQGFRCAgx6MbRFYQEAACsDqGAnAqqD1BAYVEICDHoxtEVhAQAAKwOoYCcCqoPUEBhUQgIMejG0RWEBAAArA6hgJwKqg9QQGFRCAgx6MbRFYQEAACsDqGAnAqqD1BAYVEICDHoxtEVhAQAAKwOoYCcCqoPUEBhUQgIMejG0RWEBAAArA6hgJwKqg9QQGFRCAgx6MbRFYQEAACsDqGAnAqqD1BAYVEICDHoxtEVhAQAAKwOoYCcCqoPUEBhUQgIMejG0RWEBAAArA6hgJwKqg9QQGFRCAgx6MbRFYQEAACsDqGAnAqqD1BAYVEICDHoxtEVhAQAAKwOoYCcCqoPUEBhUQgIMejG0RWEBAAArA6hgJwKqg9QQGFRCAgx6MbRFYQEAACsDqGAnAqqD1BAYVEICDHoxtEVhAQAAKwOoYCcCqoPUEBhUQgIMejG0RWEBAAArA6hgJwKqg9QQGFRCAgx6MbRFYQEAACsDqGAnAqqD1BAYVEICDHoxtEVhAQAAKwOoYCcCqoPUEBhUQgIMejG0RWEBAAArA6hgJwKqg9QQGFRCAgx6MbRFYQEAACsDqGAnAqqD1BAYVEICDHoxtEVhAQAAKwOoYCcCqoPUEBhUQgIMejG0RWEBAAArA6hgJwKqg9QQGFRCAgx6MbRFYQEAACsDqGAnAqqD1BAYVEICDHoxtEVhAQAAKwOoYCcCqoPUEBhUQgIMejG0RWEBAAArA6hgJwKqg9QQGFRCAgx6MbRFYQEAACsDqGAnAqqD1BAYVEICDHoxtEVhAQAAKwOoYCcCqoPUEBhUQgIMejG0RWEBAAArA6hgJwKqg9QQGFRCAgx6MbRFYQEAAbk8AvirJa5N8S5KvmWbncUleneTWJNckeVuSlyS57wCzJQAPgOVSAsdJQAAep9OyVwIHExCA2xGAn5XkLUk+lOTH9wTgK5PcluRFSd6T5DVJnprkKUk+0jlKArATymUEjpuAADxuJ2a/BPoFBODmB+Djk7wjyUuTfH2Sd00B2B79eyjJ65O8bhqZq5M8nOSWJG/uHCMB2AnlMgLHTUAAHrcTs18C/QICcPMD8E1JPpjka5P8xJ4AfGKSdye5Yfpvu1Pz1unfX9Y5RgKwE8plBI6bgAA8bidmvwT6BQTgZgfglyT5uiTtKeD2lO7eAHzG9Jq/a5O8f8/ItKeKH0ty0yXG6Iok7Z/drxNJHtzZ2cnJk60FfREgsCkCAnBTTtLvQeCjBQTg5gbgdUn+U5LPS/IL09EvEYB3JLl9/ygJQH+8ENg8AQG4eWfqNyKwKyAANzcAvyDJ9yf5jT3j/rHTo3u/meTTk/zXQzwF7BFAf34Q2BIBAbglB+3X3EoBAbi5Adiemv20fVP9XUnuSfJNSX5xehNIewNIeyNI+2rP4T7iTSBb+WeBX5rARwkIQENBYHMFBODmBuDFpnbvU8Dt9vYxMO3zAfd+DMzTfAzM5t7h/WYEDiIgAA+i5VoCx0tAAG53AO5+EPSLpw+Cvnv6uJh7DzDG3gV8ACyXEjhOAgLwOJ2WvRI4mIAA3K4APNh09F0tAPucXEXg2AkIwGN3ZDZMoFtAAArA7mG5xIUCsCpoPYFBBQTgoAdjWwQWEBCAArA6RgKwKmg9gUEFBOCgB2NbBBYQEIACsDpGArAqaD2BQQUE4KAHY1sEFhAQgAKwOkYCsCpoPYFBBQTgoAdjWwQWEBCAArA6RgKwKmg9gUEFBOCgB2NbBBYQEIACsDpGArAqaD2BQQUE4KAHY1sEFhAQgAKwOkYCsCpoPYFBBQTgoAdjWwQWEBCAArA6RgKwKmg9gUEFBOCgB2NbBBYQEIACsDpGArAqaD2BQQUE4KAHY1sEFhAQgAKwOkYCsCpoPYFBBQTgoAdjWwQWEBCAArA6RgKwKmg9gUEFBOCgB2NbBBYQEIACsDpGArAqaD2BQQUE4KAHY1sEFhAQgAKwOkYCsCpoPYFBBQTgoAdjWwQWEBCAArA6RgKwKmg9gUEFBOCgB2NbBBYQEIACsDpGArAqaD2BQQUE4KAHY1sEFhAQgAKwOkYCsCpoPYFBBQTgoAdjWwQWEBCAArA6RgKwKmg9gUEFBOCgB2NbBBYQEIACsDpGArAqaD2BQQUE4KAHY1sEFhAQgAKwOkYCsCpoPYFBBQTgoAdjWwQWEBCAArA6RgKwKmg9gUEFBOCgB2NbBBYQEIACsDpGArAqaD2BQQUE4KAHY1sEFhAQgAKwOkYCsCpoPYFBBQTgoAdjWwQWEBCAArA6RgKwKmg9gUEFBOCgB2NbBBYQEIACsDpGArAqaD2BQQUE4KAHY1sEFhAQgAKwOkYCsCpoPYFBBQTgoAdjWwQWEBCAArA6RgKwKmg9gUEFBOCgB2NbBBYQEIACsDpGArAqaD2BQQUE4KAHY1sEFhAQgAKwOkYCsCpoPYFBBQTgoAdjWwQWEBCAArA6RgKwKmg9gUEFBOCgB2NbBBYQEIACsDpGArAqaD2BQQUE4KAHY1sEFhAQgAKwOkYCsCpoPYFBBQTgoAdjWwQWEBCAArA6RgKwKmg9gUEFBOCgB2NbBBYQEIACsDpGArAqaD2BQQUE4KAHY1sEFhAQgAKwOkYCsCpoPYFBBQTgoAdjWwQWEBCAArA6RgKwKmg9gUEFBOCgB2NbBBYQEIACsDpGArAqaD2BQQUE4KAHY1sEFhAQgAKwOkYCsCpoPYFBBQTgoAdjWwQWEBCAArA6RgKwKmg9gUEFBOCgB2NbBBYQEIACsDpGArAqaD2BQQUE4KAHY1sEFhAQgAKwOkYCsCpoPYFBBQTgoAdjWwQWEBCAArA6RgKwKmg9gUEFBOCgB2NbBBYQEIACsDpGArAqaD2BQQUE4KAHY1sEFhAQgAKwOkYCsCpoPYFBBQTgoAdjWwQWEBCAArA6RgKwKmg9gUEFBOCgB2NbBBYQEIACsDpGArAqaD2BQQUE4KAHY1sEFhAQgAKwOkYCsCpoPYFBBQTgoAdjWwQWEBCAArA6RgKwKmg9gUEFBOCgB2NbBBYQEIACsDpGArAqaD2BQQUE4KAHY1sEFhAQgAKwOkYCsCpoPYFBBQTgoAdjWwQW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\" width=\"640\">"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"''"
]
},
"execution_count": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"fig1,ax1 = plt.subplots()\n",
"ax1.set_title('Question 1')\n",
"ax1.boxplot(responses)\n",
"\"\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Question 2\n",
"\n",
"Which of These do You Like to Read From?"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [
{
"data": {
"application/javascript": [
"/* Put everything inside the global mpl namespace */\n",
"window.mpl = {};\n",
"\n",
"\n",
"mpl.get_websocket_type = function() {\n",
" if (typeof(WebSocket) !== 'undefined') {\n",
" return WebSocket;\n",
" } else if (typeof(MozWebSocket) !== 'undefined') {\n",
" return MozWebSocket;\n",
" } else {\n",
" alert('Your browser does not have WebSocket support.' +\n",
" 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
" 'Firefox 4 and 5 are also supported but you ' +\n",
" 'have to enable WebSockets in about:config.');\n",
" };\n",
"}\n",
"\n",
"mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
" this.id = figure_id;\n",
"\n",
" this.ws = websocket;\n",
"\n",
" this.supports_binary = (this.ws.binaryType != undefined);\n",
"\n",
" if (!this.supports_binary) {\n",
" var warnings = document.getElementById(\"mpl-warnings\");\n",
" if (warnings) {\n",
" warnings.style.display = 'block';\n",
" warnings.textContent = (\n",
" \"This browser does not support binary websocket messages. \" +\n",
" \"Performance may be slow.\");\n",
" }\n",
" }\n",
"\n",
" this.imageObj = new Image();\n",
"\n",
" this.context = undefined;\n",
" this.message = undefined;\n",
" this.canvas = undefined;\n",
" this.rubberband_canvas = undefined;\n",
" this.rubberband_context = undefined;\n",
" this.format_dropdown = undefined;\n",
"\n",
" this.image_mode = 'full';\n",
"\n",
" this.root = $('<div/>');\n",
" this._root_extra_style(this.root)\n",
" this.root.attr('style', 'display: inline-block');\n",
"\n",
" $(parent_element).append(this.root);\n",
"\n",
" this._init_header(this);\n",
" this._init_canvas(this);\n",
" this._init_toolbar(this);\n",
"\n",
" var fig = this;\n",
"\n",
" this.waiting = false;\n",
"\n",
" this.ws.onopen = function () {\n",
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
" fig.send_message(\"send_image_mode\", {});\n",
" if (mpl.ratio != 1) {\n",
" fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
" }\n",
" fig.send_message(\"refresh\", {});\n",
" }\n",
"\n",
" this.imageObj.onload = function() {\n",
" if (fig.image_mode == 'full') {\n",
" // Full images could contain transparency (where diff images\n",
" // almost always do), so we need to clear the canvas so that\n",
" // there is no ghosting.\n",
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
" }\n",
" fig.context.drawImage(fig.imageObj, 0, 0);\n",
" };\n",
"\n",
" this.imageObj.onunload = function() {\n",
" 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 backingStore = this.context.backingStorePixelRatio ||\n",
"\tthis.context.webkitBackingStorePixelRatio ||\n",
"\tthis.context.mozBackingStorePixelRatio ||\n",
"\tthis.context.msBackingStorePixelRatio ||\n",
"\tthis.context.oBackingStorePixelRatio ||\n",
"\tthis.context.backingStorePixelRatio || 1;\n",
"\n",
" mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
"\n",
" var rubberband = $('<canvas/>');\n",
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
"\n",
" var pass_mouse_events = true;\n",
"\n",
" canvas_div.resizable({\n",
" start: function(event, ui) {\n",
" pass_mouse_events = false;\n",
" },\n",
" resize: function(event, ui) {\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" stop: function(event, ui) {\n",
" pass_mouse_events = true;\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" });\n",
"\n",
" function mouse_event_fn(event) {\n",
" if (pass_mouse_events)\n",
" return fig.mouse_event(event, event['data']);\n",
" }\n",
"\n",
" rubberband.mousedown('button_press', mouse_event_fn);\n",
" rubberband.mouseup('button_release', mouse_event_fn);\n",
" // Throttle sequential mouse events to 1 every 20ms.\n",
" rubberband.mousemove('motion_notify', mouse_event_fn);\n",
"\n",
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
"\n",
" canvas_div.on(\"wheel\", function (event) {\n",
" event = event.originalEvent;\n",
" event['data'] = 'scroll'\n",
" if (event.deltaY < 0) {\n",
" event.step = 1;\n",
" } else {\n",
" event.step = -1;\n",
" }\n",
" mouse_event_fn(event);\n",
" });\n",
"\n",
" canvas_div.append(canvas);\n",
" canvas_div.append(rubberband);\n",
"\n",
" this.rubberband = rubberband;\n",
" this.rubberband_canvas = rubberband[0];\n",
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
" this.rubberband_context.strokeStyle = \"#000000\";\n",
"\n",
" this._resize_canvas = function(width, height) {\n",
" // Keep the size of the canvas, canvas container, and rubber band\n",
" // canvas in synch.\n",
" canvas_div.css('width', width)\n",
" canvas_div.css('height', height)\n",
"\n",
" canvas.attr('width', width * mpl.ratio);\n",
" canvas.attr('height', height * mpl.ratio);\n",
" canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
"\n",
" rubberband.attr('width', width);\n",
" rubberband.attr('height', height);\n",
" }\n",
"\n",
" // Set the figure to an initial 600x600px, this will subsequently be updated\n",
" // upon first draw.\n",
" this._resize_canvas(600, 600);\n",
"\n",
" // Disable right mouse context menu.\n",
" $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
" return false;\n",
" });\n",
"\n",
" function set_focus () {\n",
" canvas.focus();\n",
" canvas_div.focus();\n",
" }\n",
"\n",
" window.setTimeout(set_focus, 100);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items) {\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) {\n",
" // put a spacer in here.\n",
" continue;\n",
" }\n",
" var button = $('<button/>');\n",
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
" 'ui-button-icon-only');\n",
" button.attr('role', 'button');\n",
" button.attr('aria-disabled', 'false');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
"\n",
" var icon_img = $('<span/>');\n",
" icon_img.addClass('ui-button-icon-primary ui-icon');\n",
" icon_img.addClass(image);\n",
" icon_img.addClass('ui-corner-all');\n",
"\n",
" var tooltip_span = $('<span/>');\n",
" tooltip_span.addClass('ui-button-text');\n",
" tooltip_span.html(tooltip);\n",
"\n",
" button.append(icon_img);\n",
" button.append(tooltip_span);\n",
"\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" var fmt_picker_span = $('<span/>');\n",
"\n",
" var fmt_picker = $('<select/>');\n",
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
" fmt_picker_span.append(fmt_picker);\n",
" nav_element.append(fmt_picker_span);\n",
" this.format_dropdown = fmt_picker[0];\n",
"\n",
" for (var ind in mpl.extensions) {\n",
" var fmt = mpl.extensions[ind];\n",
" var option = $(\n",
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
" fmt_picker.append(option)\n",
" }\n",
"\n",
" // Add hover states to the ui-buttons\n",
" $( \".ui-button\" ).hover(\n",
" function() { $(this).addClass(\"ui-state-hover\");},\n",
" function() { $(this).removeClass(\"ui-state-hover\");}\n",
" );\n",
"\n",
" var status_bar = $('<span class=\"mpl-message\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"}\n",
"\n",
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
" // which will in turn request a refresh of the image.\n",
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
"}\n",
"\n",
"mpl.figure.prototype.send_message = function(type, properties) {\n",
" properties['type'] = type;\n",
" properties['figure_id'] = this.id;\n",
" this.ws.send(JSON.stringify(properties));\n",
"}\n",
"\n",
"mpl.figure.prototype.send_draw_message = function() {\n",
" if (!this.waiting) {\n",
" this.waiting = true;\n",
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
" }\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" var format_dropdown = fig.format_dropdown;\n",
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
" fig.ondownload(fig, format);\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
" var size = msg['size'];\n",
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
" fig._resize_canvas(size[0], size[1]);\n",
" fig.send_message(\"refresh\", {});\n",
" };\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
" var x0 = msg['x0'] / mpl.ratio;\n",
" var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
" var x1 = msg['x1'] / mpl.ratio;\n",
" var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
" x0 = Math.floor(x0) + 0.5;\n",
" y0 = Math.floor(y0) + 0.5;\n",
" x1 = Math.floor(x1) + 0.5;\n",
" y1 = Math.floor(y1) + 0.5;\n",
" var min_x = Math.min(x0, x1);\n",
" var min_y = Math.min(y0, y1);\n",
" var width = Math.abs(x1 - x0);\n",
" var height = Math.abs(y1 - y0);\n",
"\n",
" fig.rubberband_context.clearRect(\n",
" 0, 0, fig.canvas.width, fig.canvas.height);\n",
"\n",
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
" // Updates the figure title.\n",
" fig.header.textContent = msg['label'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
" var cursor = msg['cursor'];\n",
" switch(cursor)\n",
" {\n",
" case 0:\n",
" cursor = 'pointer';\n",
" break;\n",
" case 1:\n",
" cursor = 'default';\n",
" break;\n",
" case 2:\n",
" cursor = 'crosshair';\n",
" break;\n",
" case 3:\n",
" cursor = 'move';\n",
" break;\n",
" }\n",
" fig.rubberband_canvas.style.cursor = cursor;\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_message = function(fig, msg) {\n",
" fig.message.textContent = msg['message'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
" // Request the server to send over a new figure.\n",
" fig.send_draw_message();\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
" fig.image_mode = msg['mode'];\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Called whenever the canvas gets updated.\n",
" this.send_message(\"ack\", {});\n",
"}\n",
"\n",
"// A function to construct a web socket function for onmessage handling.\n",
"// Called in the figure constructor.\n",
"mpl.figure.prototype._make_on_message_function = function(fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
" /* FIXME: We get \"Resource interpreted as Image but\n",
" * transferred with MIME type text/plain:\" errors on\n",
" * Chrome. But how to set the MIME type? It doesn't seem\n",
" * to be part of the websocket stream */\n",
" evt.data.type = \"image/png\";\n",
"\n",
" /* Free the memory for the previous frames */\n",
" if (fig.imageObj.src) {\n",
" (window.URL || window.webkitURL).revokeObjectURL(\n",
" fig.imageObj.src);\n",
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
" evt.data);\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
" fig.imageObj.src = evt.data;\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
"\n",
" var msg = JSON.parse(evt.data);\n",
" var msg_type = msg['type'];\n",
"\n",
" // Call the \"handle_{type}\" callback, which takes\n",
" // the figure and JSON message as its only arguments.\n",
" try {\n",
" var callback = fig[\"handle_\" + msg_type];\n",
" } catch (e) {\n",
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
" return;\n",
" }\n",
"\n",
" if (callback) {\n",
" try {\n",
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
" callback(fig, msg);\n",
" } catch (e) {\n",
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
" }\n",
" }\n",
" };\n",
"}\n",
"\n",
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
"mpl.findpos = function(e) {\n",
" //this section is from http://www.quirksmode.org/js/events_properties.html\n",
" var targ;\n",
" if (!e)\n",
" e = window.event;\n",
" if (e.target)\n",
" targ = e.target;\n",
" else if (e.srcElement)\n",
" targ = e.srcElement;\n",
" if (targ.nodeType == 3) // defeat Safari bug\n",
" targ = targ.parentNode;\n",
"\n",
" // jQuery normalizes the pageX and pageY\n",
" // pageX,Y are the mouse positions relative to the document\n",
" // offset() returns the position of the element relative to the document\n",
" var x = e.pageX - $(targ).offset().left;\n",
" var y = e.pageY - $(targ).offset().top;\n",
"\n",
" return {\"x\": x, \"y\": y};\n",
"};\n",
"\n",
"/*\n",
" * return a copy of an object with only non-object keys\n",
" * we need this to avoid circular references\n",
" * http://stackoverflow.com/a/24161582/3208463\n",
" */\n",
"function simpleKeys (original) {\n",
" return Object.keys(original).reduce(function (obj, key) {\n",
" if (typeof original[key] !== 'object')\n",
" obj[key] = original[key]\n",
" return obj;\n",
" }, {});\n",
"}\n",
"\n",
"mpl.figure.prototype.mouse_event = function(event, name) {\n",
" var canvas_pos = mpl.findpos(event)\n",
"\n",
" if (name === 'button_press')\n",
" {\n",
" this.canvas.focus();\n",
" this.canvas_div.focus();\n",
" }\n",
"\n",
" var x = canvas_pos.x * mpl.ratio;\n",
" var y = canvas_pos.y * mpl.ratio;\n",
"\n",
" this.send_message(name, {x: x, y: y, button: event.button,\n",
" step: event.step,\n",
" guiEvent: simpleKeys(event)});\n",
"\n",
" /* This prevents the web browser from automatically changing to\n",
" * the text insertion cursor when the button is pressed. We want\n",
" * to control all of the cursor setting manually through the\n",
" * 'cursor' event from matplotlib */\n",
" event.preventDefault();\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" // Handle any extra behaviour associated with a key event\n",
"}\n",
"\n",
"mpl.figure.prototype.key_event = function(event, name) {\n",
"\n",
" // Prevent repeat events\n",
" if (name == 'key_press')\n",
" {\n",
" if (event.which === this._key)\n",
" return;\n",
" else\n",
" this._key = event.which;\n",
" }\n",
" if (name == 'key_release')\n",
" this._key = null;\n",
"\n",
" var value = '';\n",
" if (event.ctrlKey && event.which != 17)\n",
" value += \"ctrl+\";\n",
" if (event.altKey && event.which != 18)\n",
" value += \"alt+\";\n",
" if (event.shiftKey && event.which != 16)\n",
" value += \"shift+\";\n",
"\n",
" value += 'k';\n",
" value += event.which.toString();\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
" this.send_message(name, {key: value,\n",
" guiEvent: simpleKeys(event)});\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
" if (name == 'download') {\n",
" this.handle_save(this, null);\n",
" } else {\n",
" this.send_message(\"toolbar_button\", {name: name});\n",
" }\n",
"};\n",
"\n",
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
" this.message.textContent = tooltip;\n",
"};\n",
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
"\n",
"mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
" // Create a \"websocket\"-like object which calls the given IPython comm\n",
" // object with the appropriate methods. Currently this is a non binary\n",
" // socket, so there is still some room for performance tuning.\n",
" var ws = {};\n",
"\n",
" ws.close = function() {\n",
" comm.close()\n",
" };\n",
" ws.send = function(m) {\n",
" //console.log('sending', m);\n",
" comm.send(m);\n",
" };\n",
" // Register the callback with on_msg.\n",
" comm.on_msg(function(msg) {\n",
" //console.log('receiving', msg['content']['data'], msg);\n",
" // Pass the mpl event to the 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",
" var width = fig.canvas.width/mpl.ratio\n",
" fig.root.unbind('remove')\n",
"\n",
" // Update the output cell to use the data from the current canvas.\n",
" fig.push_to_output();\n",
" var dataURL = fig.canvas.toDataURL();\n",
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
" // the notebook keyboard shortcuts fail.\n",
" IPython.keyboard_manager.enable()\n",
" $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
" fig.close_ws(fig, msg);\n",
"}\n",
"\n",
"mpl.figure.prototype.close_ws = function(fig, msg){\n",
" fig.send_message('closing', msg);\n",
" // fig.ws.close()\n",
"}\n",
"\n",
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
" // Turn the data on the canvas into data in the output cell.\n",
" var width = this.canvas.width/mpl.ratio\n",
" var dataURL = this.canvas.toDataURL();\n",
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Tell IPython that the notebook contents must change.\n",
" IPython.notebook.set_dirty(true);\n",
" this.send_message(\"ack\", {});\n",
" var fig = this;\n",
" // Wait a second, then push the new image to the DOM so\n",
" // that it is saved nicely (might be nice to debounce this).\n",
" setTimeout(function () { fig.push_to_output() }, 1000);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items){\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) { continue; };\n",
"\n",
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" // Add the status bar.\n",
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"\n",
" // Add the close button to the window.\n",
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
" buttongrp.append(button);\n",
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
" titlebar.prepend(buttongrp);\n",
"}\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(el){\n",
" var fig = this\n",
" el.on(\"remove\", function(){\n",
"\tfig.close_ws(fig, {});\n",
" });\n",
"}\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(el){\n",
" // this is important to make the div 'focusable\n",
" el.attr('tabindex', 0)\n",
" // reach out to IPython and tell the keyboard manager to turn it's self\n",
" // off when our div gets focus\n",
"\n",
" // location in version 3\n",
" if (IPython.notebook.keyboard_manager) {\n",
" IPython.notebook.keyboard_manager.register_events(el);\n",
" }\n",
" else {\n",
" // location in version 2\n",
" IPython.keyboard_manager.register_events(el);\n",
" }\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" var manager = IPython.notebook.keyboard_manager;\n",
" if (!manager)\n",
" manager = IPython.keyboard_manager;\n",
"\n",
" // Check for shift+enter\n",
" if (event.shiftKey && event.which == 13) {\n",
" this.canvas_div.blur();\n",
" // select the cell after this one\n",
" var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
" IPython.notebook.select(index + 1);\n",
" }\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" fig.ondownload(fig, null);\n",
"}\n",
"\n",
"\n",
"mpl.find_output_cell = function(html_output) {\n",
" // Return the cell and output element which can be found *uniquely* in the notebook.\n",
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
" // IPython event is triggered only after the cells have been serialised, which for\n",
" // our purposes (turning an active figure into a static one), is too late.\n",
" var cells = IPython.notebook.get_cells();\n",
" var ncells = cells.length;\n",
" for (var i=0; i<ncells; i++) {\n",
" var cell = cells[i];\n",
" if (cell.cell_type === 'code'){\n",
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
" var data = cell.output_area.outputs[j];\n",
" if (data.data) {\n",
" // IPython >= 3 moved mimebundle to data attribute of output\n",
" data = data.data;\n",
" }\n",
" if (data['text/html'] == html_output) {\n",
" return [cell, data, j];\n",
" }\n",
" }\n",
" }\n",
" }\n",
"}\n",
"\n",
"// Register the function which deals with the matplotlib target/channel.\n",
"// The kernel may be null if the page has been refreshed.\n",
"if (IPython.notebook.kernel != null) {\n",
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
"}\n"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<img src=\"data:image/png;base64,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\" width=\"640\">"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"''"
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"options = ['Paperback', 'Hardback', 'Kindle', 'Tablet', 'Computer', 'Smartphone', 'None']\n",
"responses = [11, 16, 6, 1, 3, 3, 1]\n",
"\n",
"fig2,ax2 = plt.subplots()\n",
"ax2.set_title('Question 2')\n",
"y_pos = np.arange(len(options))\n",
"ax2.barh(y_pos, responses, align='center')\n",
"ax2.set_yticks(y_pos)\n",
"ax2.set_yticklabels(options)\n",
"ax2.invert_yaxis()\n",
"ax2.set_xlabel('Responses')\n",
"\"\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Question 3\n",
"\n",
"From One to Five, How Much Do You Like These Genres?"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [
{
"data": {
"application/javascript": [
"/* Put everything inside the global mpl namespace */\n",
"window.mpl = {};\n",
"\n",
"\n",
"mpl.get_websocket_type = function() {\n",
" if (typeof(WebSocket) !== 'undefined') {\n",
" return WebSocket;\n",
" } else if (typeof(MozWebSocket) !== 'undefined') {\n",
" return MozWebSocket;\n",
" } else {\n",
" alert('Your browser does not have WebSocket support.' +\n",
" 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
" 'Firefox 4 and 5 are also supported but you ' +\n",
" 'have to enable WebSockets in about:config.');\n",
" };\n",
"}\n",
"\n",
"mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
" this.id = figure_id;\n",
"\n",
" this.ws = websocket;\n",
"\n",
" this.supports_binary = (this.ws.binaryType != undefined);\n",
"\n",
" if (!this.supports_binary) {\n",
" var warnings = document.getElementById(\"mpl-warnings\");\n",
" if (warnings) {\n",
" warnings.style.display = 'block';\n",
" warnings.textContent = (\n",
" \"This browser does not support binary websocket messages. \" +\n",
" \"Performance may be slow.\");\n",
" }\n",
" }\n",
"\n",
" this.imageObj = new Image();\n",
"\n",
" this.context = undefined;\n",
" this.message = undefined;\n",
" this.canvas = undefined;\n",
" this.rubberband_canvas = undefined;\n",
" this.rubberband_context = undefined;\n",
" this.format_dropdown = undefined;\n",
"\n",
" this.image_mode = 'full';\n",
"\n",
" this.root = $('<div/>');\n",
" this._root_extra_style(this.root)\n",
" this.root.attr('style', 'display: inline-block');\n",
"\n",
" $(parent_element).append(this.root);\n",
"\n",
" this._init_header(this);\n",
" this._init_canvas(this);\n",
" this._init_toolbar(this);\n",
"\n",
" var fig = this;\n",
"\n",
" this.waiting = false;\n",
"\n",
" this.ws.onopen = function () {\n",
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
" fig.send_message(\"send_image_mode\", {});\n",
" if (mpl.ratio != 1) {\n",
" fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
" }\n",
" fig.send_message(\"refresh\", {});\n",
" }\n",
"\n",
" this.imageObj.onload = function() {\n",
" if (fig.image_mode == 'full') {\n",
" // Full images could contain transparency (where diff images\n",
" // almost always do), so we need to clear the canvas so that\n",
" // there is no ghosting.\n",
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
" }\n",
" fig.context.drawImage(fig.imageObj, 0, 0);\n",
" };\n",
"\n",
" this.imageObj.onunload = function() {\n",
" 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 backingStore = this.context.backingStorePixelRatio ||\n",
"\tthis.context.webkitBackingStorePixelRatio ||\n",
"\tthis.context.mozBackingStorePixelRatio ||\n",
"\tthis.context.msBackingStorePixelRatio ||\n",
"\tthis.context.oBackingStorePixelRatio ||\n",
"\tthis.context.backingStorePixelRatio || 1;\n",
"\n",
" mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
"\n",
" var rubberband = $('<canvas/>');\n",
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
"\n",
" var pass_mouse_events = true;\n",
"\n",
" canvas_div.resizable({\n",
" start: function(event, ui) {\n",
" pass_mouse_events = false;\n",
" },\n",
" resize: function(event, ui) {\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" stop: function(event, ui) {\n",
" pass_mouse_events = true;\n",
" fig.request_resize(ui.size.width, ui.size.height);\n",
" },\n",
" });\n",
"\n",
" function mouse_event_fn(event) {\n",
" if (pass_mouse_events)\n",
" return fig.mouse_event(event, event['data']);\n",
" }\n",
"\n",
" rubberband.mousedown('button_press', mouse_event_fn);\n",
" rubberband.mouseup('button_release', mouse_event_fn);\n",
" // Throttle sequential mouse events to 1 every 20ms.\n",
" rubberband.mousemove('motion_notify', mouse_event_fn);\n",
"\n",
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
"\n",
" canvas_div.on(\"wheel\", function (event) {\n",
" event = event.originalEvent;\n",
" event['data'] = 'scroll'\n",
" if (event.deltaY < 0) {\n",
" event.step = 1;\n",
" } else {\n",
" event.step = -1;\n",
" }\n",
" mouse_event_fn(event);\n",
" });\n",
"\n",
" canvas_div.append(canvas);\n",
" canvas_div.append(rubberband);\n",
"\n",
" this.rubberband = rubberband;\n",
" this.rubberband_canvas = rubberband[0];\n",
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
" this.rubberband_context.strokeStyle = \"#000000\";\n",
"\n",
" this._resize_canvas = function(width, height) {\n",
" // Keep the size of the canvas, canvas container, and rubber band\n",
" // canvas in synch.\n",
" canvas_div.css('width', width)\n",
" canvas_div.css('height', height)\n",
"\n",
" canvas.attr('width', width * mpl.ratio);\n",
" canvas.attr('height', height * mpl.ratio);\n",
" canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
"\n",
" rubberband.attr('width', width);\n",
" rubberband.attr('height', height);\n",
" }\n",
"\n",
" // Set the figure to an initial 600x600px, this will subsequently be updated\n",
" // upon first draw.\n",
" this._resize_canvas(600, 600);\n",
"\n",
" // Disable right mouse context menu.\n",
" $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
" return false;\n",
" });\n",
"\n",
" function set_focus () {\n",
" canvas.focus();\n",
" canvas_div.focus();\n",
" }\n",
"\n",
" window.setTimeout(set_focus, 100);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items) {\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) {\n",
" // put a spacer in here.\n",
" continue;\n",
" }\n",
" var button = $('<button/>');\n",
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
" 'ui-button-icon-only');\n",
" button.attr('role', 'button');\n",
" button.attr('aria-disabled', 'false');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
"\n",
" var icon_img = $('<span/>');\n",
" icon_img.addClass('ui-button-icon-primary ui-icon');\n",
" icon_img.addClass(image);\n",
" icon_img.addClass('ui-corner-all');\n",
"\n",
" var tooltip_span = $('<span/>');\n",
" tooltip_span.addClass('ui-button-text');\n",
" tooltip_span.html(tooltip);\n",
"\n",
" button.append(icon_img);\n",
" button.append(tooltip_span);\n",
"\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" var fmt_picker_span = $('<span/>');\n",
"\n",
" var fmt_picker = $('<select/>');\n",
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
" fmt_picker_span.append(fmt_picker);\n",
" nav_element.append(fmt_picker_span);\n",
" this.format_dropdown = fmt_picker[0];\n",
"\n",
" for (var ind in mpl.extensions) {\n",
" var fmt = mpl.extensions[ind];\n",
" var option = $(\n",
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
" fmt_picker.append(option)\n",
" }\n",
"\n",
" // Add hover states to the ui-buttons\n",
" $( \".ui-button\" ).hover(\n",
" function() { $(this).addClass(\"ui-state-hover\");},\n",
" function() { $(this).removeClass(\"ui-state-hover\");}\n",
" );\n",
"\n",
" var status_bar = $('<span class=\"mpl-message\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"}\n",
"\n",
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
" // which will in turn request a refresh of the image.\n",
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
"}\n",
"\n",
"mpl.figure.prototype.send_message = function(type, properties) {\n",
" properties['type'] = type;\n",
" properties['figure_id'] = this.id;\n",
" this.ws.send(JSON.stringify(properties));\n",
"}\n",
"\n",
"mpl.figure.prototype.send_draw_message = function() {\n",
" if (!this.waiting) {\n",
" this.waiting = true;\n",
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
" }\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" var format_dropdown = fig.format_dropdown;\n",
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
" fig.ondownload(fig, format);\n",
"}\n",
"\n",
"\n",
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
" var size = msg['size'];\n",
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
" fig._resize_canvas(size[0], size[1]);\n",
" fig.send_message(\"refresh\", {});\n",
" };\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
" var x0 = msg['x0'] / mpl.ratio;\n",
" var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
" var x1 = msg['x1'] / mpl.ratio;\n",
" var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
" x0 = Math.floor(x0) + 0.5;\n",
" y0 = Math.floor(y0) + 0.5;\n",
" x1 = Math.floor(x1) + 0.5;\n",
" y1 = Math.floor(y1) + 0.5;\n",
" var min_x = Math.min(x0, x1);\n",
" var min_y = Math.min(y0, y1);\n",
" var width = Math.abs(x1 - x0);\n",
" var height = Math.abs(y1 - y0);\n",
"\n",
" fig.rubberband_context.clearRect(\n",
" 0, 0, fig.canvas.width, fig.canvas.height);\n",
"\n",
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
" // Updates the figure title.\n",
" fig.header.textContent = msg['label'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
" var cursor = msg['cursor'];\n",
" switch(cursor)\n",
" {\n",
" case 0:\n",
" cursor = 'pointer';\n",
" break;\n",
" case 1:\n",
" cursor = 'default';\n",
" break;\n",
" case 2:\n",
" cursor = 'crosshair';\n",
" break;\n",
" case 3:\n",
" cursor = 'move';\n",
" break;\n",
" }\n",
" fig.rubberband_canvas.style.cursor = cursor;\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_message = function(fig, msg) {\n",
" fig.message.textContent = msg['message'];\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
" // Request the server to send over a new figure.\n",
" fig.send_draw_message();\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
" fig.image_mode = msg['mode'];\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Called whenever the canvas gets updated.\n",
" this.send_message(\"ack\", {});\n",
"}\n",
"\n",
"// A function to construct a web socket function for onmessage handling.\n",
"// Called in the figure constructor.\n",
"mpl.figure.prototype._make_on_message_function = function(fig) {\n",
" return function socket_on_message(evt) {\n",
" if (evt.data instanceof Blob) {\n",
" /* FIXME: We get \"Resource interpreted as Image but\n",
" * transferred with MIME type text/plain:\" errors on\n",
" * Chrome. But how to set the MIME type? It doesn't seem\n",
" * to be part of the websocket stream */\n",
" evt.data.type = \"image/png\";\n",
"\n",
" /* Free the memory for the previous frames */\n",
" if (fig.imageObj.src) {\n",
" (window.URL || window.webkitURL).revokeObjectURL(\n",
" fig.imageObj.src);\n",
" }\n",
"\n",
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
" evt.data);\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
" fig.imageObj.src = evt.data;\n",
" fig.updated_canvas_event();\n",
" fig.waiting = false;\n",
" return;\n",
" }\n",
"\n",
" var msg = JSON.parse(evt.data);\n",
" var msg_type = msg['type'];\n",
"\n",
" // Call the \"handle_{type}\" callback, which takes\n",
" // the figure and JSON message as its only arguments.\n",
" try {\n",
" var callback = fig[\"handle_\" + msg_type];\n",
" } catch (e) {\n",
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
" return;\n",
" }\n",
"\n",
" if (callback) {\n",
" try {\n",
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
" callback(fig, msg);\n",
" } catch (e) {\n",
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
" }\n",
" }\n",
" };\n",
"}\n",
"\n",
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
"mpl.findpos = function(e) {\n",
" //this section is from http://www.quirksmode.org/js/events_properties.html\n",
" var targ;\n",
" if (!e)\n",
" e = window.event;\n",
" if (e.target)\n",
" targ = e.target;\n",
" else if (e.srcElement)\n",
" targ = e.srcElement;\n",
" if (targ.nodeType == 3) // defeat Safari bug\n",
" targ = targ.parentNode;\n",
"\n",
" // jQuery normalizes the pageX and pageY\n",
" // pageX,Y are the mouse positions relative to the document\n",
" // offset() returns the position of the element relative to the document\n",
" var x = e.pageX - $(targ).offset().left;\n",
" var y = e.pageY - $(targ).offset().top;\n",
"\n",
" return {\"x\": x, \"y\": y};\n",
"};\n",
"\n",
"/*\n",
" * return a copy of an object with only non-object keys\n",
" * we need this to avoid circular references\n",
" * http://stackoverflow.com/a/24161582/3208463\n",
" */\n",
"function simpleKeys (original) {\n",
" return Object.keys(original).reduce(function (obj, key) {\n",
" if (typeof original[key] !== 'object')\n",
" obj[key] = original[key]\n",
" return obj;\n",
" }, {});\n",
"}\n",
"\n",
"mpl.figure.prototype.mouse_event = function(event, name) {\n",
" var canvas_pos = mpl.findpos(event)\n",
"\n",
" if (name === 'button_press')\n",
" {\n",
" this.canvas.focus();\n",
" this.canvas_div.focus();\n",
" }\n",
"\n",
" var x = canvas_pos.x * mpl.ratio;\n",
" var y = canvas_pos.y * mpl.ratio;\n",
"\n",
" this.send_message(name, {x: x, y: y, button: event.button,\n",
" step: event.step,\n",
" guiEvent: simpleKeys(event)});\n",
"\n",
" /* This prevents the web browser from automatically changing to\n",
" * the text insertion cursor when the button is pressed. We want\n",
" * to control all of the cursor setting manually through the\n",
" * 'cursor' event from matplotlib */\n",
" event.preventDefault();\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" // Handle any extra behaviour associated with a key event\n",
"}\n",
"\n",
"mpl.figure.prototype.key_event = function(event, name) {\n",
"\n",
" // Prevent repeat events\n",
" if (name == 'key_press')\n",
" {\n",
" if (event.which === this._key)\n",
" return;\n",
" else\n",
" this._key = event.which;\n",
" }\n",
" if (name == 'key_release')\n",
" this._key = null;\n",
"\n",
" var value = '';\n",
" if (event.ctrlKey && event.which != 17)\n",
" value += \"ctrl+\";\n",
" if (event.altKey && event.which != 18)\n",
" value += \"alt+\";\n",
" if (event.shiftKey && event.which != 16)\n",
" value += \"shift+\";\n",
"\n",
" value += 'k';\n",
" value += event.which.toString();\n",
"\n",
" this._key_event_extra(event, name);\n",
"\n",
" this.send_message(name, {key: value,\n",
" guiEvent: simpleKeys(event)});\n",
" return false;\n",
"}\n",
"\n",
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
" if (name == 'download') {\n",
" this.handle_save(this, null);\n",
" } else {\n",
" this.send_message(\"toolbar_button\", {name: name});\n",
" }\n",
"};\n",
"\n",
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
" this.message.textContent = tooltip;\n",
"};\n",
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
"\n",
"mpl.extensions = [\"eps\", \"jpeg\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\", \"tif\"];\n",
"\n",
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
" // Create a \"websocket\"-like object which calls the given IPython comm\n",
" // object with the appropriate methods. Currently this is a non binary\n",
" // socket, so there is still some room for performance tuning.\n",
" var ws = {};\n",
"\n",
" ws.close = function() {\n",
" comm.close()\n",
" };\n",
" ws.send = function(m) {\n",
" //console.log('sending', m);\n",
" comm.send(m);\n",
" };\n",
" // Register the callback with on_msg.\n",
" comm.on_msg(function(msg) {\n",
" //console.log('receiving', msg['content']['data'], msg);\n",
" // Pass the mpl event to the 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",
" var width = fig.canvas.width/mpl.ratio\n",
" fig.root.unbind('remove')\n",
"\n",
" // Update the output cell to use the data from the current canvas.\n",
" fig.push_to_output();\n",
" var dataURL = fig.canvas.toDataURL();\n",
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
" // the notebook keyboard shortcuts fail.\n",
" IPython.keyboard_manager.enable()\n",
" $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
" fig.close_ws(fig, msg);\n",
"}\n",
"\n",
"mpl.figure.prototype.close_ws = function(fig, msg){\n",
" fig.send_message('closing', msg);\n",
" // fig.ws.close()\n",
"}\n",
"\n",
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
" // Turn the data on the canvas into data in the output cell.\n",
" var width = this.canvas.width/mpl.ratio\n",
" var dataURL = this.canvas.toDataURL();\n",
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
"}\n",
"\n",
"mpl.figure.prototype.updated_canvas_event = function() {\n",
" // Tell IPython that the notebook contents must change.\n",
" IPython.notebook.set_dirty(true);\n",
" this.send_message(\"ack\", {});\n",
" var fig = this;\n",
" // Wait a second, then push the new image to the DOM so\n",
" // that it is saved nicely (might be nice to debounce this).\n",
" setTimeout(function () { fig.push_to_output() }, 1000);\n",
"}\n",
"\n",
"mpl.figure.prototype._init_toolbar = function() {\n",
" var fig = this;\n",
"\n",
" var nav_element = $('<div/>')\n",
" nav_element.attr('style', 'width: 100%');\n",
" this.root.append(nav_element);\n",
"\n",
" // Define a callback function for later on.\n",
" function toolbar_event(event) {\n",
" return fig.toolbar_button_onclick(event['data']);\n",
" }\n",
" function toolbar_mouse_event(event) {\n",
" return fig.toolbar_button_onmouseover(event['data']);\n",
" }\n",
"\n",
" for(var toolbar_ind in mpl.toolbar_items){\n",
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
"\n",
" if (!name) { continue; };\n",
"\n",
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
" button.click(method_name, toolbar_event);\n",
" button.mouseover(tooltip, toolbar_mouse_event);\n",
" nav_element.append(button);\n",
" }\n",
"\n",
" // Add the status bar.\n",
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
" nav_element.append(status_bar);\n",
" this.message = status_bar[0];\n",
"\n",
" // Add the close button to the window.\n",
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
" buttongrp.append(button);\n",
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
" titlebar.prepend(buttongrp);\n",
"}\n",
"\n",
"mpl.figure.prototype._root_extra_style = function(el){\n",
" var fig = this\n",
" el.on(\"remove\", function(){\n",
"\tfig.close_ws(fig, {});\n",
" });\n",
"}\n",
"\n",
"mpl.figure.prototype._canvas_extra_style = function(el){\n",
" // this is important to make the div 'focusable\n",
" el.attr('tabindex', 0)\n",
" // reach out to IPython and tell the keyboard manager to turn it's self\n",
" // off when our div gets focus\n",
"\n",
" // location in version 3\n",
" if (IPython.notebook.keyboard_manager) {\n",
" IPython.notebook.keyboard_manager.register_events(el);\n",
" }\n",
" else {\n",
" // location in version 2\n",
" IPython.keyboard_manager.register_events(el);\n",
" }\n",
"\n",
"}\n",
"\n",
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
" var manager = IPython.notebook.keyboard_manager;\n",
" if (!manager)\n",
" manager = IPython.keyboard_manager;\n",
"\n",
" // Check for shift+enter\n",
" if (event.shiftKey && event.which == 13) {\n",
" this.canvas_div.blur();\n",
" // select the cell after this one\n",
" var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
" IPython.notebook.select(index + 1);\n",
" }\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" fig.ondownload(fig, null);\n",
"}\n",
"\n",
"\n",
"mpl.find_output_cell = function(html_output) {\n",
" // Return the cell and output element which can be found *uniquely* in the notebook.\n",
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
" // IPython event is triggered only after the cells have been serialised, which for\n",
" // our purposes (turning an active figure into a static one), is too late.\n",
" var cells = IPython.notebook.get_cells();\n",
" var ncells = cells.length;\n",
" for (var i=0; i<ncells; i++) {\n",
" var cell = cells[i];\n",
" if (cell.cell_type === 'code'){\n",
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
" var data = cell.output_area.outputs[j];\n",
" if (data.data) {\n",
" // IPython >= 3 moved mimebundle to data attribute of output\n",
" data = data.data;\n",
" }\n",
" if (data['text/html'] == html_output) {\n",
" return [cell, data, j];\n",
" }\n",
" }\n",
" }\n",
" }\n",
"}\n",
"\n",
"// Register the function which deals with the matplotlib target/channel.\n",
"// The kernel may be null if the page has been refreshed.\n",
"if (IPython.notebook.kernel != null) {\n",
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
"}\n"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<img src=\"data:image/png;base64,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\" width=\"640\">"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/plain": [
"''"
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"options = ['Horror', 'Mystery', 'Sci-Fi', 'Historical', 'Romance', 'Thriller', 'Western', 'Non-Fiction', 'Fantasy', 'Comedy']\n",
"responses = [[1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,2,3,4,5,5,5,5],\n",
" [1,1,3,3,3,3,3,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5],\n",
" [1,1,1,1,1,1,1,1,1,2,2,2,3,3,4,4,4,4,4,4,5,5],\n",
" [1,1,1,1,1,2,2,2,2,2,2,2,2,2,2,3,3,3,3,5,5,5],\n",
" [1,1,1,1,1,2,2,2,2,3,3,3,3,3,3,4,4,4,4,4,5,5],\n",
" [1,1,2,2,3,3,3,3,3,4,4,4,4,4,4,4,5,5,5,5,5,5], \n",
" [1,1,1,1,1,1,1,1,2,2,2,2,2,3,3,3,3,3,4,4,4,5], \n",
" [1,1,1,2,2,2,2,2,2,2,3,3,3,3,3,3,4,4,4,5,5,5], \n",
" [1,2,2,2,2,2,3,3,3,4,4,4,4,5,5,5,5,5,5,5,5,5], \n",
" [1,1,3,3,3,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5] ]\n",
"\n",
"fig3,ax3 = plt.subplots()\n",
"ax3.set_title('Question 3')\n",
"ax3.boxplot(responses)\n",
"ax3.set_xticklabels(options)\n",
"plt.setp(ax3.get_xticklabels(), rotation=30)\n",
"\"\""
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Question 4\n",
"\n",
"What Formats Do You Like To Read In?"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": [
"options = ['Graphic Novels', 'Novels', 'Kindle', 'Tablet', 'Computer', 'Smartphone', 'None']\n",
"responses = [11, 16, 6, 1, 3, 3, 1]\n",
"\n",
"fig2,ax2 = plt.subplots()\n",
"ax2.set_title('Question 2')\n",
"y_pos = np.arange(len(options))\n",
"ax2.barh(y_pos, responses, align='center')\n",
"ax2.set_yticks(y_pos)\n",
"ax2.set_yticklabels(options)\n",
"ax2.invert_yaxis()\n",
"ax2.set_xlabel('Responses')\n",
"\"\""
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"collapsed": true
},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.6.1"
}
},
"nbformat": 4,
"nbformat_minor": 2
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment