868 lines
60 KiB
Text
868 lines
60 KiB
Text
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 2,
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import matplotlib\n",
|
|
"%matplotlib notebook\n",
|
|
"from matplotlib import pyplot as plt\n",
|
|
"import json\n",
|
|
"import numpy as np"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 3,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"name": "stdout",
|
|
"output_type": "stream",
|
|
"text": [
|
|
"[0.021634511649608612, 0.021226437762379646, 0.021718157455325127, 0.02069423533976078, 0.020945267751812935, 0.020484745502471924, 0.020257309079170227, 0.020306363701820374, 0.019664078950881958, 0.02021571435034275]\n"
|
|
]
|
|
}
|
|
],
|
|
"source": [
|
|
"path = './trained_net/loss_values_SLLShift_E3_03-11_17-34_120'\n",
|
|
"\n",
|
|
"with open(path,'rb') as f:\n",
|
|
" dump = f.read()\n",
|
|
"\n",
|
|
"values = json.loads(dump)\n",
|
|
"\n",
|
|
"k = 20\n",
|
|
"#values = np.convolve(values,[1/k]*k,'valid')\n",
|
|
"\n",
|
|
"print(values[:10])"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": 4,
|
|
"metadata": {},
|
|
"outputs": [
|
|
{
|
|
"data": {
|
|
"application/javascript": [
|
|
"/* Put everything inside the global mpl namespace */\n",
|
|
"window.mpl = {};\n",
|
|
"\n",
|
|
"\n",
|
|
"mpl.get_websocket_type = function() {\n",
|
|
" if (typeof(WebSocket) !== 'undefined') {\n",
|
|
" return WebSocket;\n",
|
|
" } else if (typeof(MozWebSocket) !== 'undefined') {\n",
|
|
" return MozWebSocket;\n",
|
|
" } else {\n",
|
|
" alert('Your browser does not have WebSocket support. ' +\n",
|
|
" 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
|
|
" 'Firefox 4 and 5 are also supported but you ' +\n",
|
|
" 'have to enable WebSockets in about:config.');\n",
|
|
" };\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
|
|
" this.id = figure_id;\n",
|
|
"\n",
|
|
" this.ws = websocket;\n",
|
|
"\n",
|
|
" this.supports_binary = (this.ws.binaryType != undefined);\n",
|
|
"\n",
|
|
" if (!this.supports_binary) {\n",
|
|
" var warnings = document.getElementById(\"mpl-warnings\");\n",
|
|
" if (warnings) {\n",
|
|
" warnings.style.display = 'block';\n",
|
|
" warnings.textContent = (\n",
|
|
" \"This browser does not support binary websocket messages. \" +\n",
|
|
" \"Performance may be slow.\");\n",
|
|
" }\n",
|
|
" }\n",
|
|
"\n",
|
|
" this.imageObj = new Image();\n",
|
|
"\n",
|
|
" this.context = undefined;\n",
|
|
" this.message = undefined;\n",
|
|
" this.canvas = undefined;\n",
|
|
" this.rubberband_canvas = undefined;\n",
|
|
" this.rubberband_context = undefined;\n",
|
|
" this.format_dropdown = undefined;\n",
|
|
"\n",
|
|
" this.image_mode = 'full';\n",
|
|
"\n",
|
|
" this.root = $('<div/>');\n",
|
|
" this._root_extra_style(this.root)\n",
|
|
" this.root.attr('style', 'display: inline-block');\n",
|
|
"\n",
|
|
" $(parent_element).append(this.root);\n",
|
|
"\n",
|
|
" this._init_header(this);\n",
|
|
" this._init_canvas(this);\n",
|
|
" this._init_toolbar(this);\n",
|
|
"\n",
|
|
" var fig = this;\n",
|
|
"\n",
|
|
" this.waiting = false;\n",
|
|
"\n",
|
|
" this.ws.onopen = function () {\n",
|
|
" fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
|
|
" fig.send_message(\"send_image_mode\", {});\n",
|
|
" if (mpl.ratio != 1) {\n",
|
|
" fig.send_message(\"set_dpi_ratio\", {'dpi_ratio': mpl.ratio});\n",
|
|
" }\n",
|
|
" fig.send_message(\"refresh\", {});\n",
|
|
" }\n",
|
|
"\n",
|
|
" this.imageObj.onload = function() {\n",
|
|
" if (fig.image_mode == 'full') {\n",
|
|
" // Full images could contain transparency (where diff images\n",
|
|
" // almost always do), so we need to clear the canvas so that\n",
|
|
" // there is no ghosting.\n",
|
|
" fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
|
|
" }\n",
|
|
" fig.context.drawImage(fig.imageObj, 0, 0);\n",
|
|
" };\n",
|
|
"\n",
|
|
" this.imageObj.onunload = function() {\n",
|
|
" fig.ws.close();\n",
|
|
" }\n",
|
|
"\n",
|
|
" this.ws.onmessage = this._make_on_message_function(this);\n",
|
|
"\n",
|
|
" this.ondownload = ondownload;\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype._init_header = function() {\n",
|
|
" var titlebar = $(\n",
|
|
" '<div class=\"ui-dialog-titlebar ui-widget-header ui-corner-all ' +\n",
|
|
" 'ui-helper-clearfix\"/>');\n",
|
|
" var titletext = $(\n",
|
|
" '<div class=\"ui-dialog-title\" style=\"width: 100%; ' +\n",
|
|
" 'text-align: center; padding: 3px;\"/>');\n",
|
|
" titlebar.append(titletext)\n",
|
|
" this.root.append(titlebar);\n",
|
|
" this.header = titletext[0];\n",
|
|
"}\n",
|
|
"\n",
|
|
"\n",
|
|
"\n",
|
|
"mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
|
|
"\n",
|
|
"}\n",
|
|
"\n",
|
|
"\n",
|
|
"mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
|
|
"\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype._init_canvas = function() {\n",
|
|
" var fig = this;\n",
|
|
"\n",
|
|
" var canvas_div = $('<div/>');\n",
|
|
"\n",
|
|
" canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
|
|
"\n",
|
|
" function canvas_keyboard_event(event) {\n",
|
|
" return fig.key_event(event, event['data']);\n",
|
|
" }\n",
|
|
"\n",
|
|
" canvas_div.keydown('key_press', canvas_keyboard_event);\n",
|
|
" canvas_div.keyup('key_release', canvas_keyboard_event);\n",
|
|
" this.canvas_div = canvas_div\n",
|
|
" this._canvas_extra_style(canvas_div)\n",
|
|
" this.root.append(canvas_div);\n",
|
|
"\n",
|
|
" var canvas = $('<canvas/>');\n",
|
|
" canvas.addClass('mpl-canvas');\n",
|
|
" canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
|
|
"\n",
|
|
" this.canvas = canvas[0];\n",
|
|
" this.context = canvas[0].getContext(\"2d\");\n",
|
|
"\n",
|
|
" var backingStore = this.context.backingStorePixelRatio ||\n",
|
|
"\tthis.context.webkitBackingStorePixelRatio ||\n",
|
|
"\tthis.context.mozBackingStorePixelRatio ||\n",
|
|
"\tthis.context.msBackingStorePixelRatio ||\n",
|
|
"\tthis.context.oBackingStorePixelRatio ||\n",
|
|
"\tthis.context.backingStorePixelRatio || 1;\n",
|
|
"\n",
|
|
" mpl.ratio = (window.devicePixelRatio || 1) / backingStore;\n",
|
|
"\n",
|
|
" var rubberband = $('<canvas/>');\n",
|
|
" rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
|
|
"\n",
|
|
" var pass_mouse_events = true;\n",
|
|
"\n",
|
|
" canvas_div.resizable({\n",
|
|
" start: function(event, ui) {\n",
|
|
" pass_mouse_events = false;\n",
|
|
" },\n",
|
|
" resize: function(event, ui) {\n",
|
|
" fig.request_resize(ui.size.width, ui.size.height);\n",
|
|
" },\n",
|
|
" stop: function(event, ui) {\n",
|
|
" pass_mouse_events = true;\n",
|
|
" fig.request_resize(ui.size.width, ui.size.height);\n",
|
|
" },\n",
|
|
" });\n",
|
|
"\n",
|
|
" function mouse_event_fn(event) {\n",
|
|
" if (pass_mouse_events)\n",
|
|
" return fig.mouse_event(event, event['data']);\n",
|
|
" }\n",
|
|
"\n",
|
|
" rubberband.mousedown('button_press', mouse_event_fn);\n",
|
|
" rubberband.mouseup('button_release', mouse_event_fn);\n",
|
|
" // Throttle sequential mouse events to 1 every 20ms.\n",
|
|
" rubberband.mousemove('motion_notify', mouse_event_fn);\n",
|
|
"\n",
|
|
" rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
|
|
" rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
|
|
"\n",
|
|
" canvas_div.on(\"wheel\", function (event) {\n",
|
|
" event = event.originalEvent;\n",
|
|
" event['data'] = 'scroll'\n",
|
|
" if (event.deltaY < 0) {\n",
|
|
" event.step = 1;\n",
|
|
" } else {\n",
|
|
" event.step = -1;\n",
|
|
" }\n",
|
|
" mouse_event_fn(event);\n",
|
|
" });\n",
|
|
"\n",
|
|
" canvas_div.append(canvas);\n",
|
|
" canvas_div.append(rubberband);\n",
|
|
"\n",
|
|
" this.rubberband = rubberband;\n",
|
|
" this.rubberband_canvas = rubberband[0];\n",
|
|
" this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
|
|
" this.rubberband_context.strokeStyle = \"#000000\";\n",
|
|
"\n",
|
|
" this._resize_canvas = function(width, height) {\n",
|
|
" // Keep the size of the canvas, canvas container, and rubber band\n",
|
|
" // canvas in synch.\n",
|
|
" canvas_div.css('width', width)\n",
|
|
" canvas_div.css('height', height)\n",
|
|
"\n",
|
|
" canvas.attr('width', width * mpl.ratio);\n",
|
|
" canvas.attr('height', height * mpl.ratio);\n",
|
|
" canvas.attr('style', 'width: ' + width + 'px; height: ' + height + 'px;');\n",
|
|
"\n",
|
|
" rubberband.attr('width', width);\n",
|
|
" rubberband.attr('height', height);\n",
|
|
" }\n",
|
|
"\n",
|
|
" // Set the figure to an initial 600x600px, this will subsequently be updated\n",
|
|
" // upon first draw.\n",
|
|
" this._resize_canvas(600, 600);\n",
|
|
"\n",
|
|
" // Disable right mouse context menu.\n",
|
|
" $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
|
|
" return false;\n",
|
|
" });\n",
|
|
"\n",
|
|
" function set_focus () {\n",
|
|
" canvas.focus();\n",
|
|
" canvas_div.focus();\n",
|
|
" }\n",
|
|
"\n",
|
|
" window.setTimeout(set_focus, 100);\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype._init_toolbar = function() {\n",
|
|
" var fig = this;\n",
|
|
"\n",
|
|
" var nav_element = $('<div/>');\n",
|
|
" nav_element.attr('style', 'width: 100%');\n",
|
|
" this.root.append(nav_element);\n",
|
|
"\n",
|
|
" // Define a callback function for later on.\n",
|
|
" function toolbar_event(event) {\n",
|
|
" return fig.toolbar_button_onclick(event['data']);\n",
|
|
" }\n",
|
|
" function toolbar_mouse_event(event) {\n",
|
|
" return fig.toolbar_button_onmouseover(event['data']);\n",
|
|
" }\n",
|
|
"\n",
|
|
" for(var toolbar_ind in mpl.toolbar_items) {\n",
|
|
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
|
|
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
|
|
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
|
|
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
|
|
"\n",
|
|
" if (!name) {\n",
|
|
" // put a spacer in here.\n",
|
|
" continue;\n",
|
|
" }\n",
|
|
" var button = $('<button/>');\n",
|
|
" button.addClass('ui-button ui-widget ui-state-default ui-corner-all ' +\n",
|
|
" 'ui-button-icon-only');\n",
|
|
" button.attr('role', 'button');\n",
|
|
" button.attr('aria-disabled', 'false');\n",
|
|
" button.click(method_name, toolbar_event);\n",
|
|
" button.mouseover(tooltip, toolbar_mouse_event);\n",
|
|
"\n",
|
|
" var icon_img = $('<span/>');\n",
|
|
" icon_img.addClass('ui-button-icon-primary ui-icon');\n",
|
|
" icon_img.addClass(image);\n",
|
|
" icon_img.addClass('ui-corner-all');\n",
|
|
"\n",
|
|
" var tooltip_span = $('<span/>');\n",
|
|
" tooltip_span.addClass('ui-button-text');\n",
|
|
" tooltip_span.html(tooltip);\n",
|
|
"\n",
|
|
" button.append(icon_img);\n",
|
|
" button.append(tooltip_span);\n",
|
|
"\n",
|
|
" nav_element.append(button);\n",
|
|
" }\n",
|
|
"\n",
|
|
" var fmt_picker_span = $('<span/>');\n",
|
|
"\n",
|
|
" var fmt_picker = $('<select/>');\n",
|
|
" fmt_picker.addClass('mpl-toolbar-option ui-widget ui-widget-content');\n",
|
|
" fmt_picker_span.append(fmt_picker);\n",
|
|
" nav_element.append(fmt_picker_span);\n",
|
|
" this.format_dropdown = fmt_picker[0];\n",
|
|
"\n",
|
|
" for (var ind in mpl.extensions) {\n",
|
|
" var fmt = mpl.extensions[ind];\n",
|
|
" var option = $(\n",
|
|
" '<option/>', {selected: fmt === mpl.default_extension}).html(fmt);\n",
|
|
" fmt_picker.append(option);\n",
|
|
" }\n",
|
|
"\n",
|
|
" // Add hover states to the ui-buttons\n",
|
|
" $( \".ui-button\" ).hover(\n",
|
|
" function() { $(this).addClass(\"ui-state-hover\");},\n",
|
|
" function() { $(this).removeClass(\"ui-state-hover\");}\n",
|
|
" );\n",
|
|
"\n",
|
|
" var status_bar = $('<span class=\"mpl-message\"/>');\n",
|
|
" nav_element.append(status_bar);\n",
|
|
" this.message = status_bar[0];\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
|
|
" // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
|
|
" // which will in turn request a refresh of the image.\n",
|
|
" this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.send_message = function(type, properties) {\n",
|
|
" properties['type'] = type;\n",
|
|
" properties['figure_id'] = this.id;\n",
|
|
" this.ws.send(JSON.stringify(properties));\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.send_draw_message = function() {\n",
|
|
" if (!this.waiting) {\n",
|
|
" this.waiting = true;\n",
|
|
" this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
|
|
" }\n",
|
|
"}\n",
|
|
"\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
|
|
" var format_dropdown = fig.format_dropdown;\n",
|
|
" var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
|
|
" fig.ondownload(fig, format);\n",
|
|
"}\n",
|
|
"\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
|
|
" var size = msg['size'];\n",
|
|
" if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
|
|
" fig._resize_canvas(size[0], size[1]);\n",
|
|
" fig.send_message(\"refresh\", {});\n",
|
|
" };\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
|
|
" var x0 = msg['x0'] / mpl.ratio;\n",
|
|
" var y0 = (fig.canvas.height - msg['y0']) / mpl.ratio;\n",
|
|
" var x1 = msg['x1'] / mpl.ratio;\n",
|
|
" var y1 = (fig.canvas.height - msg['y1']) / mpl.ratio;\n",
|
|
" x0 = Math.floor(x0) + 0.5;\n",
|
|
" y0 = Math.floor(y0) + 0.5;\n",
|
|
" x1 = Math.floor(x1) + 0.5;\n",
|
|
" y1 = Math.floor(y1) + 0.5;\n",
|
|
" var min_x = Math.min(x0, x1);\n",
|
|
" var min_y = Math.min(y0, y1);\n",
|
|
" var width = Math.abs(x1 - x0);\n",
|
|
" var height = Math.abs(y1 - y0);\n",
|
|
"\n",
|
|
" fig.rubberband_context.clearRect(\n",
|
|
" 0, 0, fig.canvas.width / mpl.ratio, fig.canvas.height / mpl.ratio);\n",
|
|
"\n",
|
|
" fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
|
|
" // Updates the figure title.\n",
|
|
" fig.header.textContent = msg['label'];\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
|
|
" var cursor = msg['cursor'];\n",
|
|
" switch(cursor)\n",
|
|
" {\n",
|
|
" case 0:\n",
|
|
" cursor = 'pointer';\n",
|
|
" break;\n",
|
|
" case 1:\n",
|
|
" cursor = 'default';\n",
|
|
" break;\n",
|
|
" case 2:\n",
|
|
" cursor = 'crosshair';\n",
|
|
" break;\n",
|
|
" case 3:\n",
|
|
" cursor = 'move';\n",
|
|
" break;\n",
|
|
" }\n",
|
|
" fig.rubberband_canvas.style.cursor = cursor;\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_message = function(fig, msg) {\n",
|
|
" fig.message.textContent = msg['message'];\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
|
|
" // Request the server to send over a new figure.\n",
|
|
" fig.send_draw_message();\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
|
|
" fig.image_mode = msg['mode'];\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.updated_canvas_event = function() {\n",
|
|
" // Called whenever the canvas gets updated.\n",
|
|
" this.send_message(\"ack\", {});\n",
|
|
"}\n",
|
|
"\n",
|
|
"// A function to construct a web socket function for onmessage handling.\n",
|
|
"// Called in the figure constructor.\n",
|
|
"mpl.figure.prototype._make_on_message_function = function(fig) {\n",
|
|
" return function socket_on_message(evt) {\n",
|
|
" if (evt.data instanceof Blob) {\n",
|
|
" /* FIXME: We get \"Resource interpreted as Image but\n",
|
|
" * transferred with MIME type text/plain:\" errors on\n",
|
|
" * Chrome. But how to set the MIME type? It doesn't seem\n",
|
|
" * to be part of the websocket stream */\n",
|
|
" evt.data.type = \"image/png\";\n",
|
|
"\n",
|
|
" /* Free the memory for the previous frames */\n",
|
|
" if (fig.imageObj.src) {\n",
|
|
" (window.URL || window.webkitURL).revokeObjectURL(\n",
|
|
" fig.imageObj.src);\n",
|
|
" }\n",
|
|
"\n",
|
|
" fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
|
|
" evt.data);\n",
|
|
" fig.updated_canvas_event();\n",
|
|
" fig.waiting = false;\n",
|
|
" return;\n",
|
|
" }\n",
|
|
" else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
|
|
" fig.imageObj.src = evt.data;\n",
|
|
" fig.updated_canvas_event();\n",
|
|
" fig.waiting = false;\n",
|
|
" return;\n",
|
|
" }\n",
|
|
"\n",
|
|
" var msg = JSON.parse(evt.data);\n",
|
|
" var msg_type = msg['type'];\n",
|
|
"\n",
|
|
" // Call the \"handle_{type}\" callback, which takes\n",
|
|
" // the figure and JSON message as its only arguments.\n",
|
|
" try {\n",
|
|
" var callback = fig[\"handle_\" + msg_type];\n",
|
|
" } catch (e) {\n",
|
|
" console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
|
|
" return;\n",
|
|
" }\n",
|
|
"\n",
|
|
" if (callback) {\n",
|
|
" try {\n",
|
|
" // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
|
|
" callback(fig, msg);\n",
|
|
" } catch (e) {\n",
|
|
" console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
|
|
" }\n",
|
|
" }\n",
|
|
" };\n",
|
|
"}\n",
|
|
"\n",
|
|
"// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
|
|
"mpl.findpos = function(e) {\n",
|
|
" //this section is from http://www.quirksmode.org/js/events_properties.html\n",
|
|
" var targ;\n",
|
|
" if (!e)\n",
|
|
" e = window.event;\n",
|
|
" if (e.target)\n",
|
|
" targ = e.target;\n",
|
|
" else if (e.srcElement)\n",
|
|
" targ = e.srcElement;\n",
|
|
" if (targ.nodeType == 3) // defeat Safari bug\n",
|
|
" targ = targ.parentNode;\n",
|
|
"\n",
|
|
" // jQuery normalizes the pageX and pageY\n",
|
|
" // pageX,Y are the mouse positions relative to the document\n",
|
|
" // offset() returns the position of the element relative to the document\n",
|
|
" var x = e.pageX - $(targ).offset().left;\n",
|
|
" var y = e.pageY - $(targ).offset().top;\n",
|
|
"\n",
|
|
" return {\"x\": x, \"y\": y};\n",
|
|
"};\n",
|
|
"\n",
|
|
"/*\n",
|
|
" * return a copy of an object with only non-object keys\n",
|
|
" * we need this to avoid circular references\n",
|
|
" * http://stackoverflow.com/a/24161582/3208463\n",
|
|
" */\n",
|
|
"function simpleKeys (original) {\n",
|
|
" return Object.keys(original).reduce(function (obj, key) {\n",
|
|
" if (typeof original[key] !== 'object')\n",
|
|
" obj[key] = original[key]\n",
|
|
" return obj;\n",
|
|
" }, {});\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.mouse_event = function(event, name) {\n",
|
|
" var canvas_pos = mpl.findpos(event)\n",
|
|
"\n",
|
|
" if (name === 'button_press')\n",
|
|
" {\n",
|
|
" this.canvas.focus();\n",
|
|
" this.canvas_div.focus();\n",
|
|
" }\n",
|
|
"\n",
|
|
" var x = canvas_pos.x * mpl.ratio;\n",
|
|
" var y = canvas_pos.y * mpl.ratio;\n",
|
|
"\n",
|
|
" this.send_message(name, {x: x, y: y, button: event.button,\n",
|
|
" step: event.step,\n",
|
|
" guiEvent: simpleKeys(event)});\n",
|
|
"\n",
|
|
" /* This prevents the web browser from automatically changing to\n",
|
|
" * the text insertion cursor when the button is pressed. We want\n",
|
|
" * to control all of the cursor setting manually through the\n",
|
|
" * 'cursor' event from matplotlib */\n",
|
|
" event.preventDefault();\n",
|
|
" return false;\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
|
|
" // Handle any extra behaviour associated with a key event\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.key_event = function(event, name) {\n",
|
|
"\n",
|
|
" // Prevent repeat events\n",
|
|
" if (name == 'key_press')\n",
|
|
" {\n",
|
|
" if (event.which === this._key)\n",
|
|
" return;\n",
|
|
" else\n",
|
|
" this._key = event.which;\n",
|
|
" }\n",
|
|
" if (name == 'key_release')\n",
|
|
" this._key = null;\n",
|
|
"\n",
|
|
" var value = '';\n",
|
|
" if (event.ctrlKey && event.which != 17)\n",
|
|
" value += \"ctrl+\";\n",
|
|
" if (event.altKey && event.which != 18)\n",
|
|
" value += \"alt+\";\n",
|
|
" if (event.shiftKey && event.which != 16)\n",
|
|
" value += \"shift+\";\n",
|
|
"\n",
|
|
" value += 'k';\n",
|
|
" value += event.which.toString();\n",
|
|
"\n",
|
|
" this._key_event_extra(event, name);\n",
|
|
"\n",
|
|
" this.send_message(name, {key: value,\n",
|
|
" guiEvent: simpleKeys(event)});\n",
|
|
" return false;\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
|
|
" if (name == 'download') {\n",
|
|
" this.handle_save(this, null);\n",
|
|
" } else {\n",
|
|
" this.send_message(\"toolbar_button\", {name: name});\n",
|
|
" }\n",
|
|
"};\n",
|
|
"\n",
|
|
"mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
|
|
" this.message.textContent = tooltip;\n",
|
|
"};\n",
|
|
"mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
|
|
"\n",
|
|
"mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n",
|
|
"\n",
|
|
"mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
|
|
" // Create a \"websocket\"-like object which calls the given IPython comm\n",
|
|
" // object with the appropriate methods. Currently this is a non binary\n",
|
|
" // socket, so there is still some room for performance tuning.\n",
|
|
" var ws = {};\n",
|
|
"\n",
|
|
" ws.close = function() {\n",
|
|
" comm.close()\n",
|
|
" };\n",
|
|
" ws.send = function(m) {\n",
|
|
" //console.log('sending', m);\n",
|
|
" comm.send(m);\n",
|
|
" };\n",
|
|
" // Register the callback with on_msg.\n",
|
|
" comm.on_msg(function(msg) {\n",
|
|
" //console.log('receiving', msg['content']['data'], msg);\n",
|
|
" // Pass the mpl event to the overridden (by mpl) onmessage function.\n",
|
|
" ws.onmessage(msg['content']['data'])\n",
|
|
" });\n",
|
|
" return ws;\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.mpl_figure_comm = function(comm, msg) {\n",
|
|
" // This is the function which gets called when the mpl process\n",
|
|
" // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
|
|
"\n",
|
|
" var id = msg.content.data.id;\n",
|
|
" // Get hold of the div created by the display call when the Comm\n",
|
|
" // socket was opened in Python.\n",
|
|
" var element = $(\"#\" + id);\n",
|
|
" var ws_proxy = comm_websocket_adapter(comm)\n",
|
|
"\n",
|
|
" function ondownload(figure, format) {\n",
|
|
" window.open(figure.imageObj.src);\n",
|
|
" }\n",
|
|
"\n",
|
|
" var fig = new mpl.figure(id, ws_proxy,\n",
|
|
" ondownload,\n",
|
|
" element.get(0));\n",
|
|
"\n",
|
|
" // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
|
|
" // web socket which is closed, not our websocket->open comm proxy.\n",
|
|
" ws_proxy.onopen();\n",
|
|
"\n",
|
|
" fig.parent_element = element.get(0);\n",
|
|
" fig.cell_info = mpl.find_output_cell(\"<div id='\" + id + \"'></div>\");\n",
|
|
" if (!fig.cell_info) {\n",
|
|
" console.error(\"Failed to find cell for figure\", id, fig);\n",
|
|
" return;\n",
|
|
" }\n",
|
|
"\n",
|
|
" var output_index = fig.cell_info[2]\n",
|
|
" var cell = fig.cell_info[0];\n",
|
|
"\n",
|
|
"};\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_close = function(fig, msg) {\n",
|
|
" var width = fig.canvas.width/mpl.ratio\n",
|
|
" fig.root.unbind('remove')\n",
|
|
"\n",
|
|
" // Update the output cell to use the data from the current canvas.\n",
|
|
" fig.push_to_output();\n",
|
|
" var dataURL = fig.canvas.toDataURL();\n",
|
|
" // Re-enable the keyboard manager in IPython - without this line, in FF,\n",
|
|
" // the notebook keyboard shortcuts fail.\n",
|
|
" IPython.keyboard_manager.enable()\n",
|
|
" $(fig.parent_element).html('<img src=\"' + dataURL + '\" width=\"' + width + '\">');\n",
|
|
" fig.close_ws(fig, msg);\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.close_ws = function(fig, msg){\n",
|
|
" fig.send_message('closing', msg);\n",
|
|
" // fig.ws.close()\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.push_to_output = function(remove_interactive) {\n",
|
|
" // Turn the data on the canvas into data in the output cell.\n",
|
|
" var width = this.canvas.width/mpl.ratio\n",
|
|
" var dataURL = this.canvas.toDataURL();\n",
|
|
" this.cell_info[1]['text/html'] = '<img src=\"' + dataURL + '\" width=\"' + width + '\">';\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.updated_canvas_event = function() {\n",
|
|
" // Tell IPython that the notebook contents must change.\n",
|
|
" IPython.notebook.set_dirty(true);\n",
|
|
" this.send_message(\"ack\", {});\n",
|
|
" var fig = this;\n",
|
|
" // Wait a second, then push the new image to the DOM so\n",
|
|
" // that it is saved nicely (might be nice to debounce this).\n",
|
|
" setTimeout(function () { fig.push_to_output() }, 1000);\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype._init_toolbar = function() {\n",
|
|
" var fig = this;\n",
|
|
"\n",
|
|
" var nav_element = $('<div/>');\n",
|
|
" nav_element.attr('style', 'width: 100%');\n",
|
|
" this.root.append(nav_element);\n",
|
|
"\n",
|
|
" // Define a callback function for later on.\n",
|
|
" function toolbar_event(event) {\n",
|
|
" return fig.toolbar_button_onclick(event['data']);\n",
|
|
" }\n",
|
|
" function toolbar_mouse_event(event) {\n",
|
|
" return fig.toolbar_button_onmouseover(event['data']);\n",
|
|
" }\n",
|
|
"\n",
|
|
" for(var toolbar_ind in mpl.toolbar_items){\n",
|
|
" var name = mpl.toolbar_items[toolbar_ind][0];\n",
|
|
" var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
|
|
" var image = mpl.toolbar_items[toolbar_ind][2];\n",
|
|
" var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
|
|
"\n",
|
|
" if (!name) { continue; };\n",
|
|
"\n",
|
|
" var button = $('<button class=\"btn btn-default\" href=\"#\" title=\"' + name + '\"><i class=\"fa ' + image + ' fa-lg\"></i></button>');\n",
|
|
" button.click(method_name, toolbar_event);\n",
|
|
" button.mouseover(tooltip, toolbar_mouse_event);\n",
|
|
" nav_element.append(button);\n",
|
|
" }\n",
|
|
"\n",
|
|
" // Add the status bar.\n",
|
|
" var status_bar = $('<span class=\"mpl-message\" style=\"text-align:right; float: right;\"/>');\n",
|
|
" nav_element.append(status_bar);\n",
|
|
" this.message = status_bar[0];\n",
|
|
"\n",
|
|
" // Add the close button to the window.\n",
|
|
" var buttongrp = $('<div class=\"btn-group inline pull-right\"></div>');\n",
|
|
" var button = $('<button class=\"btn btn-mini btn-primary\" href=\"#\" title=\"Stop Interaction\"><i class=\"fa fa-power-off icon-remove icon-large\"></i></button>');\n",
|
|
" button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
|
|
" button.mouseover('Stop Interaction', toolbar_mouse_event);\n",
|
|
" buttongrp.append(button);\n",
|
|
" var titlebar = this.root.find($('.ui-dialog-titlebar'));\n",
|
|
" titlebar.prepend(buttongrp);\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype._root_extra_style = function(el){\n",
|
|
" var fig = this\n",
|
|
" el.on(\"remove\", function(){\n",
|
|
"\tfig.close_ws(fig, {});\n",
|
|
" });\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype._canvas_extra_style = function(el){\n",
|
|
" // this is important to make the div 'focusable\n",
|
|
" el.attr('tabindex', 0)\n",
|
|
" // reach out to IPython and tell the keyboard manager to turn it's self\n",
|
|
" // off when our div gets focus\n",
|
|
"\n",
|
|
" // location in version 3\n",
|
|
" if (IPython.notebook.keyboard_manager) {\n",
|
|
" IPython.notebook.keyboard_manager.register_events(el);\n",
|
|
" }\n",
|
|
" else {\n",
|
|
" // location in version 2\n",
|
|
" IPython.keyboard_manager.register_events(el);\n",
|
|
" }\n",
|
|
"\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype._key_event_extra = function(event, name) {\n",
|
|
" var manager = IPython.notebook.keyboard_manager;\n",
|
|
" if (!manager)\n",
|
|
" manager = IPython.keyboard_manager;\n",
|
|
"\n",
|
|
" // Check for shift+enter\n",
|
|
" if (event.shiftKey && event.which == 13) {\n",
|
|
" this.canvas_div.blur();\n",
|
|
" // select the cell after this one\n",
|
|
" var index = IPython.notebook.find_cell_index(this.cell_info[0]);\n",
|
|
" IPython.notebook.select(index + 1);\n",
|
|
" }\n",
|
|
"}\n",
|
|
"\n",
|
|
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
|
|
" fig.ondownload(fig, null);\n",
|
|
"}\n",
|
|
"\n",
|
|
"\n",
|
|
"mpl.find_output_cell = function(html_output) {\n",
|
|
" // Return the cell and output element which can be found *uniquely* in the notebook.\n",
|
|
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
|
|
" // IPython event is triggered only after the cells have been serialised, which for\n",
|
|
" // our purposes (turning an active figure into a static one), is too late.\n",
|
|
" var cells = IPython.notebook.get_cells();\n",
|
|
" var ncells = cells.length;\n",
|
|
" for (var i=0; i<ncells; i++) {\n",
|
|
" var cell = cells[i];\n",
|
|
" if (cell.cell_type === 'code'){\n",
|
|
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
|
|
" var data = cell.output_area.outputs[j];\n",
|
|
" if (data.data) {\n",
|
|
" // IPython >= 3 moved mimebundle to data attribute of output\n",
|
|
" data = data.data;\n",
|
|
" }\n",
|
|
" if (data['text/html'] == html_output) {\n",
|
|
" return [cell, data, j];\n",
|
|
" }\n",
|
|
" }\n",
|
|
" }\n",
|
|
" }\n",
|
|
"}\n",
|
|
"\n",
|
|
"// Register the function which deals with the matplotlib target/channel.\n",
|
|
"// The kernel may be null if the page has been refreshed.\n",
|
|
"if (IPython.notebook.kernel != null) {\n",
|
|
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
|
|
"}\n"
|
|
],
|
|
"text/plain": [
|
|
"<IPython.core.display.Javascript object>"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
},
|
|
{
|
|
"data": {
|
|
"text/html": [
|
|
"<img src=\"data:image/png;base64,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Bx7QV7/61R7rxMXF6ZVXXjn3jQpTsAA4f/58LVq0SJWVlXrrrbd0/fXX69prr/V/A4AJ2+71evXNb35TN998s3+ZE/Z7sO2WzN7nFRUVSkhIUExMjEaNGqXFixdLcsb+DrXtktn73AkIgMOILwCWlZVZlk+bNk1jxowZolnZc+rUKV1yySV6+umn/X8s6+rqLOv8+Mc/1u233y4p9B+Mr3zlK3rwwQclhQ7E//zP/6wnnngiAlvRt1ABcDC2NbDZBIqNjdW8efPOfaPCFCwAdldXV6fY2FgtXLhQkhnbPnnyZLndbssB7U7Y78G2OxiT9nlra6t27dql9evXKzs7W//0T/+krVu3OmJ/h9r2YEza505AABxGTPgIOJivfOUrSk9P5yNgmfnRUDgBUOr6g+47Virat33KlCm64oortHfvXsty0/d7qO0OxaR9Hui2227TT37yE+P3dzC+bQ/F1H1uIgLgMDN27FhNmjTJsiwlJSVqTgLprqWlRZdffrkef/xx/wHTM2fO9N/e2toa9IDpV1991b9OXV1d0IOG161b519n7dq1w/IkkMHYVt8B0oHvQsyfP39ITwLp7ujRo4qPj9ecOXMkRe+2e71e/fSnP9WnP/1p7dy5M+jtJu73vrY7GFP2eTC33nqr0tLSjN3fvfFtezAm73MTEQCHGd9lYAoKCuTxeDR16lQlJCSoqqpqqKcWll/84hcqKirS3r17tXbtWt1111264IIL/POfMWOGRo0apcLCQlVWVuree+8NesmEK664Qu+99542btyoW2+9NehlAz73uc9pzZo1WrNmjT772c8O+mVgTp48qfLycpWXl8vlcmnWrFkqLy/3X7JnsLbVd4mE2267TRs3btR7772nK664IqKXSOht20+ePKlf/OIXKisr0759+7Rq1Sr967/+qy6//PKo3/ZJkyZp1KhRKioqslz64syZM/51TNzvfW23yfv8kUceUUlJifbt26eKigo9+uij+shHPqJly5ZJMnN/h7PtJu9zpyAADkN5eXlyu92Ki4tTamqq5VILw53vGlixsbH69Kc/re985zuW40V8F0299NJLFR8fr/Hjx1vOJJSk5uZmTZkyRZ/4xCf00Y9+VHfddZf2799vWefYsWO6//77/Rcovf/++wf9QtCrVq3qcRFUl8vlf3U8mNtaXV2tb3zjG/roRz+qT3ziE5oyZYr/QOzB3vYzZ87oa1/7mi6++GLFxsbqqquuUlpaWo/tisZtD7bNLpdLf/nLX/zrmLjf+9puk/f5j370I//f44svvli33XabP/xJZu7vcLbd5H3uFARAAAAAhyEAAgAAOAwBEAAAwGEIgAAAAA5DAAQAAHAYAiAAAIDDEAABAAAchgAIAADgMARAAAAAhyEAAgAAOAwBEAAAwGEIgAAAAA5DAAQAAHAYAiAAAIDDEAABAAAchgAIAADgMARAAAAAhyEAAgAAOAwBEAAAwGEIgAAAAA5DAAQAAHAYAiAAAIDDEAABAAAchgAIAADgMARAAAAAhyEAAgAAOAwBEAAAwGEIgAAAAA5DAAQAAHAYAiAAAIDDEAABAAAchgAIAADgMP8fBQl2x8yHh4oAAAAASUVORK5CYII=\" width=\"640\">"
|
|
],
|
|
"text/plain": [
|
|
"<IPython.core.display.HTML object>"
|
|
]
|
|
},
|
|
"metadata": {},
|
|
"output_type": "display_data"
|
|
}
|
|
],
|
|
"source": [
|
|
"fig, ax = plt.subplots()\n",
|
|
"\n",
|
|
"ax.plot(np.arange(0,len(values),1),values)\n",
|
|
"\n",
|
|
"fig.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.8.5"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 4
|
|
}
|