Created
June 6, 2016 00:13
-
-
Save smutch/8b1fae59a359626d57070fd8733fc6db to your computer and use it in GitHub Desktop.
ipynb: PCA
This file contains hidden or 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": { | |
"ExecuteTime": { | |
"end_time": "2016-06-06T09:42:23.237247", | |
"start_time": "2016-06-06T09:42:23.167774" | |
}, | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"name": "stdout", | |
"output_type": "stream", | |
"text": [ | |
"2016-06-06T09:42:23\n", | |
"\n", | |
"CPython 3.5.1\n", | |
"IPython 4.2.0\n", | |
"\n", | |
"compiler : GCC 4.2.1 (Apple Inc. build 5577)\n", | |
"system : Darwin\n", | |
"release : 15.4.0\n", | |
"machine : x86_64\n", | |
"processor : i386\n", | |
"CPU cores : 4\n", | |
"interpreter: 64bit\n" | |
] | |
} | |
], | |
"source": [ | |
"%load_ext watermark\n", | |
"%watermark\n", | |
"%matplotlib notebook\n", | |
"\n", | |
"import matplotlib.pyplot as plt\n", | |
"import numpy as np\n", | |
"from sklearn.decomposition import PCA" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Generate random data from a bivariate normal distribution." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2016-06-06T09:42:29.436543", | |
"start_time": "2016-06-06T09:42:29.254171" | |
}, | |
"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\", \"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", | |
" 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": [ | |
"cov = np.eye(2)\n", | |
"cov[[1,1]] = 3.0\n", | |
"data = np.random.multivariate_normal([1.0,]*2, cov, 100)\n", | |
"\n", | |
"fig, ax = plt.subplots(1, 1)\n", | |
"ax.plot(data[:,0], data[:, 1], ls='', marker='o', color='0.3')\n", | |
"sns.axlabel('x', 'y')\n", | |
"plt.show()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Do the PCA using scikit-learn. I've confirmed that this gives the same result as what we should get if we do it manually as we were trying previously." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 52, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2016-06-06T10:07:05.312521", | |
"start_time": "2016-06-06T10:07:05.307198" | |
}, | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"pca = PCA()\n", | |
"res = pca.fit(data)\n", | |
"eigvec = res.components_\n", | |
"eigval = res.explained_variance_\n", | |
"energy = res.explained_variance_ratio_" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 53, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2016-06-06T10:07:10.774032", | |
"start_time": "2016-06-06T10:07:10.768661" | |
}, | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"array([[-0.72967691, -0.68379208],\n", | |
" [ 0.68379208, -0.72967691]])" | |
] | |
}, | |
"execution_count": 53, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"eigvec" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 55, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2016-06-06T10:07:14.097237", | |
"start_time": "2016-06-06T10:07:14.091943" | |
}, | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"array([ 4.46813433, 0.75264774])" | |
] | |
}, | |
"execution_count": 55, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"eigval" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 33, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2016-06-06T09:56:29.131693", | |
"start_time": "2016-06-06T09:56:29.125858" | |
}, | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"array([ 0.85583621, 0.14416379])" | |
] | |
}, | |
"execution_count": 33, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"energy" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Plot the PCs on top of the data." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 34, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2016-06-06T09:57:11.738164", | |
"start_time": "2016-06-06T09:57:11.613204" | |
}, | |
"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\", \"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", | |
" 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": [ | |
"data_means = data.mean(axis=0)\n", | |
"\n", | |
"fig, ax = plt.subplots(1, 1)\n", | |
"ax.arrow(data_means[0], data_means[1], eigval[0]*eigvec[0][0], eigval[0]*eigvec[0][1], width=0.1, head_width=0.3)\n", | |
"ax.arrow(data_means[0], data_means[1], eigval[1]*eigvec[1][0], eigval[1]*eigvec[1][1], width=0.1, head_width=0.3)\n", | |
"plt.plot(data[:,0], data[:, 1], ls='', marker='o', color='0.3')\n", | |
"ax.plot(data_means[0], data_means[1], ls='', marker='s', color='indianred', ms=10)\n", | |
"plt.show()" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Transform the data into the new basis and replot." | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 61, | |
"metadata": { | |
"ExecuteTime": { | |
"end_time": "2016-06-06T10:09:32.141320", | |
"start_time": "2016-06-06T10:09:32.036905" | |
}, | |
"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\", \"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", | |
" 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": [ | |
"transformed_data = eigvec.T.dot(data.T)\n", | |
"\n", | |
"fig, ax = plt.subplots(1, 1)\n", | |
"plt.plot(transformed_data[0], transformed_data[1], ls='', marker='o', color='0.3')\n", | |
"plt.show()" | |
] | |
} | |
], | |
"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.5.1" | |
}, | |
"latex_envs": { | |
"bibliofile": "biblio.bib", | |
"cite_by": "apalike", | |
"current_citInitial": 1, | |
"eqLabelWithNumbers": true, | |
"eqNumInitial": 0 | |
}, | |
"toc": { | |
"toc_cell": false, | |
"toc_number_sections": true, | |
"toc_threshold": 6, | |
"toc_window_display": false | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 0 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment