diff --git a/examples/basic/basic_notebook1.ipynb b/examples/basic/basic_notebook1.ipynb
index acf3fac5..179dc702 100644
--- a/examples/basic/basic_notebook1.ipynb
+++ b/examples/basic/basic_notebook1.ipynb
@@ -1,19 +1,28 @@
{
"cells": [
{
- "cell_type": "code",
- "execution_count": 1,
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "# eFeature Extraction Library\n",
+ "\n",
+ "The eFEL Python library can be used to extract eFeatures (like action potential width, firing frequency, etc) from membrane voltage traces recording during electrophysiological experiments on neurons.\n",
+ "\n",
+ "This notebook shows an introductory example on how to use this library."
+ ]
+ },
+ {
+ "cell_type": "markdown",
"metadata": {
"collapsed": false
},
- "outputs": [],
"source": [
- "%matplotlib inline"
+ "First we need to install the library and import it together with some helper functionality."
]
},
{
"cell_type": "code",
- "execution_count": 2,
+ "execution_count": 1,
"metadata": {
"collapsed": false
},
@@ -22,74 +31,837 @@
"name": "stdout",
"output_type": "stream",
"text": [
- "Requirement already satisfied (use --upgrade to upgrade): efel in /Users/werner/local/pythonenv/lib/python2.7/site-packages\r\n",
- "Requirement already satisfied (use --upgrade to upgrade): numpy>=1.6 in /Users/werner/local/pythonenv/lib/python2.7/site-packages (from efel)\r\n"
+ "Requirement already satisfied (use --upgrade to upgrade): efel in /usr/local/lib/python2.7/site-packages\r\n",
+ "Requirement already satisfied (use --upgrade to upgrade): json2html in /usr/local/lib/python2.7/site-packages\r\n",
+ "Requirement already satisfied (use --upgrade to upgrade): numpy>=1.6 in /usr/local/lib/python2.7/site-packages (from efel)\r\n"
]
}
],
"source": [
- "!pip install efel"
+ "!pip install efel json2html\n",
+ "import efel\n",
+ "\n",
+ "import urllib, numpy, IPython\n",
+ "from json2html import *\n",
+ "\n",
+ "%matplotlib notebook\n",
+ "from matplotlib import pyplot as plt\n",
+ "plt.rcParams['figure.figsize'] = 10, 10"
]
},
{
- "cell_type": "code",
- "execution_count": 3,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
+ "cell_type": "markdown",
+ "metadata": {},
"source": [
- "import efel"
+ "## Fetching the data"
]
},
{
- "cell_type": "code",
- "execution_count": 5,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
+ "cell_type": "markdown",
+ "metadata": {},
"source": [
- "import urllib\n",
- "import numpy"
+ "We will fetch the data from the test directory in the eFEL Github repository. The data consists of a text file with the first column being the time points and the second the membrane voltage (in respectively, ms and mV)"
]
},
{
"cell_type": "code",
- "execution_count": 6,
+ "execution_count": 2,
"metadata": {
"collapsed": false
},
"outputs": [],
"source": [
- "test_url = 'https://raw.githubusercontent.com/BlueBrain/eFEL/master/efel/tests/testdata/allfeatures/testdata.txt'"
+ "test_url = 'https://raw.githubusercontent.com/BlueBrain/eFEL/master/efel/tests/testdata/allfeatures/testdata.txt'\n",
+ "test_data = numpy.loadtxt(urllib.urlopen(test_url))\n",
+ "time = test_data[:,0]\n",
+ "voltage = test_data[:, 1]"
]
},
{
- "cell_type": "code",
- "execution_count": 7,
- "metadata": {
- "collapsed": false
- },
- "outputs": [],
+ "cell_type": "markdown",
+ "metadata": {},
"source": [
- "test_data = numpy.loadtxt(urllib.urlopen(test_url))\n",
- "time = test_data[:,0]\n",
- "voltage = test_data[:, 1]\n"
+ "We can now plot this data"
]
},
{
"cell_type": "code",
- "execution_count": 10,
+ "execution_count": 3,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
- "image/png": "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\npT6GYAAAAABJRU5ErkJggg==\n",
+ "application/javascript": [
+ "/* Put everything inside the global mpl namespace */\n",
+ "window.mpl = {};\n",
+ "\n",
+ "mpl.get_websocket_type = function() {\n",
+ " if (typeof(WebSocket) !== 'undefined') {\n",
+ " return WebSocket;\n",
+ " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
+ " return MozWebSocket;\n",
+ " } else {\n",
+ " alert('Your browser does not have WebSocket support.' +\n",
+ " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
+ " 'Firefox 4 and 5 are also supported but you ' +\n",
+ " 'have to enable WebSockets in about:config.');\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
+ " this.id = figure_id;\n",
+ "\n",
+ " this.ws = websocket;\n",
+ "\n",
+ " this.supports_binary = (this.ws.binaryType != undefined);\n",
+ "\n",
+ " if (!this.supports_binary) {\n",
+ " var warnings = document.getElementById(\"mpl-warnings\");\n",
+ " if (warnings) {\n",
+ " warnings.style.display = 'block';\n",
+ " warnings.textContent = (\n",
+ " \"This browser does not support binary websocket messages. \" +\n",
+ " \"Performance may be slow.\");\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " this.imageObj = new Image();\n",
+ "\n",
+ " this.context = undefined;\n",
+ " this.message = undefined;\n",
+ " this.canvas = undefined;\n",
+ " this.rubberband_canvas = undefined;\n",
+ " this.rubberband_context = undefined;\n",
+ " this.format_dropdown = undefined;\n",
+ "\n",
+ " this.image_mode = 'full';\n",
+ "\n",
+ " this.root = $('
');\n",
+ " this._root_extra_style(this.root)\n",
+ " this.root.attr('style', 'display: inline-block');\n",
+ "\n",
+ " $(parent_element).append(this.root);\n",
+ "\n",
+ " this._init_header(this);\n",
+ " this._init_canvas(this);\n",
+ " this._init_toolbar(this);\n",
+ "\n",
+ " var fig = this;\n",
+ "\n",
+ " this.waiting = false;\n",
+ "\n",
+ " this.ws.onopen = function () {\n",
+ " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
+ " fig.send_message(\"send_image_mode\", {});\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " }\n",
+ "\n",
+ " this.imageObj.onload = function() {\n",
+ " if (fig.image_mode == 'full') {\n",
+ " // Full images could contain transparency (where diff images\n",
+ " // almost always do), so we need to clear the canvas so that\n",
+ " // there is no ghosting.\n",
+ " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
+ " }\n",
+ " fig.context.drawImage(fig.imageObj, 0, 0);\n",
+ " };\n",
+ "\n",
+ " this.imageObj.onunload = function() {\n",
+ " this.ws.close();\n",
+ " }\n",
+ "\n",
+ " this.ws.onmessage = this._make_on_message_function(this);\n",
+ "\n",
+ " this.ondownload = ondownload;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_header = function() {\n",
+ " var titlebar = $(\n",
+ " '');\n",
+ " var titletext = $(\n",
+ " '');\n",
+ " titlebar.append(titletext)\n",
+ " this.root.append(titlebar);\n",
+ " this.header = titletext[0];\n",
+ "}\n",
+ "\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
+ "\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
+ "\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_canvas = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var canvas_div = $('');\n",
+ "\n",
+ " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
+ "\n",
+ " function canvas_keyboard_event(event) {\n",
+ " return fig.key_event(event, event['data']);\n",
+ " }\n",
+ "\n",
+ " canvas_div.keydown('key_press', canvas_keyboard_event);\n",
+ " canvas_div.keyup('key_release', canvas_keyboard_event);\n",
+ " this.canvas_div = canvas_div\n",
+ " this._canvas_extra_style(canvas_div)\n",
+ " this.root.append(canvas_div);\n",
+ "\n",
+ " var canvas = $('');\n",
+ " canvas.addClass('mpl-canvas');\n",
+ " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
+ "\n",
+ " this.canvas = canvas[0];\n",
+ " this.context = canvas[0].getContext(\"2d\");\n",
+ "\n",
+ " var rubberband = $('');\n",
+ " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
+ "\n",
+ " var pass_mouse_events = true;\n",
+ "\n",
+ " canvas_div.resizable({\n",
+ " start: function(event, ui) {\n",
+ " pass_mouse_events = false;\n",
+ " },\n",
+ " resize: function(event, ui) {\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " stop: function(event, ui) {\n",
+ " pass_mouse_events = true;\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " });\n",
+ "\n",
+ " function mouse_event_fn(event) {\n",
+ " if (pass_mouse_events)\n",
+ " return fig.mouse_event(event, event['data']);\n",
+ " }\n",
+ "\n",
+ " rubberband.mousedown('button_press', mouse_event_fn);\n",
+ " rubberband.mouseup('button_release', mouse_event_fn);\n",
+ " // Throttle sequential mouse events to 1 every 20ms.\n",
+ " rubberband.mousemove('motion_notify', mouse_event_fn);\n",
+ "\n",
+ " rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
+ " rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
+ "\n",
+ " canvas_div.on(\"wheel\", function (event) {\n",
+ " event = event.originalEvent;\n",
+ " event['data'] = 'scroll'\n",
+ " if (event.deltaY < 0) {\n",
+ " event.step = 1;\n",
+ " } else {\n",
+ " event.step = -1;\n",
+ " }\n",
+ " mouse_event_fn(event);\n",
+ " });\n",
+ "\n",
+ " canvas_div.append(canvas);\n",
+ " canvas_div.append(rubberband);\n",
+ "\n",
+ " this.rubberband = rubberband;\n",
+ " this.rubberband_canvas = rubberband[0];\n",
+ " this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
+ " this.rubberband_context.strokeStyle = \"#000000\";\n",
+ "\n",
+ " this._resize_canvas = function(width, height) {\n",
+ " // Keep the size of the canvas, canvas container, and rubber band\n",
+ " // canvas in synch.\n",
+ " canvas_div.css('width', width)\n",
+ " canvas_div.css('height', height)\n",
+ "\n",
+ " canvas.attr('width', width);\n",
+ " canvas.attr('height', height);\n",
+ "\n",
+ " rubberband.attr('width', width);\n",
+ " rubberband.attr('height', height);\n",
+ " }\n",
+ "\n",
+ " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
+ " // upon first draw.\n",
+ " this._resize_canvas(600, 600);\n",
+ "\n",
+ " // Disable right mouse context menu.\n",
+ " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
+ " return false;\n",
+ " });\n",
+ "\n",
+ " function set_focus () {\n",
+ " canvas.focus();\n",
+ " canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " window.setTimeout(set_focus, 100);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_toolbar = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var nav_element = $('')\n",
+ " nav_element.attr('style', 'width: 100%');\n",
+ " this.root.append(nav_element);\n",
+ "\n",
+ " // Define a callback function for later on.\n",
+ " function toolbar_event(event) {\n",
+ " return fig.toolbar_button_onclick(event['data']);\n",
+ " }\n",
+ " function toolbar_mouse_event(event) {\n",
+ " return fig.toolbar_button_onmouseover(event['data']);\n",
+ " }\n",
+ "\n",
+ " for(var toolbar_ind in mpl.toolbar_items) {\n",
+ " var name = mpl.toolbar_items[toolbar_ind][0];\n",
+ " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
+ " var image = mpl.toolbar_items[toolbar_ind][2];\n",
+ " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
+ "\n",
+ " if (!name) {\n",
+ " // put a spacer in here.\n",
+ " continue;\n",
+ " }\n",
+ " var button = $('');\n",
+ " button.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 = $('');\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 = $('');\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 = $('');\n",
+ "\n",
+ " var fmt_picker = $('');\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",
+ " '', {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 = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
+ " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
+ " // which will in turn request a refresh of the image.\n",
+ " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_message = function(type, properties) {\n",
+ " properties['type'] = type;\n",
+ " properties['figure_id'] = this.id;\n",
+ " this.ws.send(JSON.stringify(properties));\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_draw_message = function() {\n",
+ " if (!this.waiting) {\n",
+ " this.waiting = true;\n",
+ " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " var format_dropdown = fig.format_dropdown;\n",
+ " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
+ " fig.ondownload(fig, format);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
+ " var size = msg['size'];\n",
+ " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
+ " fig._resize_canvas(size[0], size[1]);\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
+ " var x0 = msg['x0'];\n",
+ " var y0 = fig.canvas.height - msg['y0'];\n",
+ " var x1 = msg['x1'];\n",
+ " var y1 = fig.canvas.height - msg['y1'];\n",
+ " x0 = Math.floor(x0) + 0.5;\n",
+ " y0 = Math.floor(y0) + 0.5;\n",
+ " x1 = Math.floor(x1) + 0.5;\n",
+ " y1 = Math.floor(y1) + 0.5;\n",
+ " var min_x = Math.min(x0, x1);\n",
+ " var min_y = Math.min(y0, y1);\n",
+ " var width = Math.abs(x1 - x0);\n",
+ " var height = Math.abs(y1 - y0);\n",
+ "\n",
+ " fig.rubberband_context.clearRect(\n",
+ " 0, 0, fig.canvas.width, fig.canvas.height);\n",
+ "\n",
+ " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
+ " // Updates the figure title.\n",
+ " fig.header.textContent = msg['label'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
+ " var cursor = msg['cursor'];\n",
+ " switch(cursor)\n",
+ " {\n",
+ " case 0:\n",
+ " cursor = 'pointer';\n",
+ " break;\n",
+ " case 1:\n",
+ " cursor = 'default';\n",
+ " break;\n",
+ " case 2:\n",
+ " cursor = 'crosshair';\n",
+ " break;\n",
+ " case 3:\n",
+ " cursor = 'move';\n",
+ " break;\n",
+ " }\n",
+ " fig.rubberband_canvas.style.cursor = cursor;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
+ " fig.message.textContent = msg['message'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
+ " // Request the server to send over a new figure.\n",
+ " fig.send_draw_message();\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
+ " fig.image_mode = msg['mode'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.updated_canvas_event = function() {\n",
+ " // Called whenever the canvas gets updated.\n",
+ " this.send_message(\"ack\", {});\n",
+ "}\n",
+ "\n",
+ "// A function to construct a web socket function for onmessage handling.\n",
+ "// Called in the figure constructor.\n",
+ "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
+ " return function socket_on_message(evt) {\n",
+ " if (evt.data instanceof Blob) {\n",
+ " /* FIXME: We get \"Resource interpreted as Image but\n",
+ " * transferred with MIME type text/plain:\" errors on\n",
+ " * Chrome. But how to set the MIME type? It doesn't seem\n",
+ " * to be part of the websocket stream */\n",
+ " evt.data.type = \"image/png\";\n",
+ "\n",
+ " /* Free the memory for the previous frames */\n",
+ " if (fig.imageObj.src) {\n",
+ " (window.URL || window.webkitURL).revokeObjectURL(\n",
+ " fig.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
+ " evt.data);\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
+ " fig.imageObj.src = evt.data;\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var msg = JSON.parse(evt.data);\n",
+ " var msg_type = msg['type'];\n",
+ "\n",
+ " // Call the \"handle_{type}\" callback, which takes\n",
+ " // the figure and JSON message as its only arguments.\n",
+ " try {\n",
+ " var callback = fig[\"handle_\" + msg_type];\n",
+ " } catch (e) {\n",
+ " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " if (callback) {\n",
+ " try {\n",
+ " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
+ " callback(fig, msg);\n",
+ " } catch (e) {\n",
+ " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
+ " }\n",
+ " }\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
+ "mpl.findpos = function(e) {\n",
+ " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
+ " var targ;\n",
+ " if (!e)\n",
+ " e = window.event;\n",
+ " if (e.target)\n",
+ " targ = e.target;\n",
+ " else if (e.srcElement)\n",
+ " targ = e.srcElement;\n",
+ " if (targ.nodeType == 3) // defeat Safari bug\n",
+ " targ = targ.parentNode;\n",
+ "\n",
+ " // jQuery normalizes the pageX and pageY\n",
+ " // pageX,Y are the mouse positions relative to the document\n",
+ " // offset() returns the position of the element relative to the document\n",
+ " var x = e.pageX - $(targ).offset().left;\n",
+ " var y = e.pageY - $(targ).offset().top;\n",
+ "\n",
+ " return {\"x\": x, \"y\": y};\n",
+ "};\n",
+ "\n",
+ "/*\n",
+ " * return a copy of an object with only non-object keys\n",
+ " * we need this to avoid circular references\n",
+ " * http://stackoverflow.com/a/24161582/3208463\n",
+ " */\n",
+ "function simpleKeys (original) {\n",
+ " return Object.keys(original).reduce(function (obj, key) {\n",
+ " if (typeof original[key] !== 'object')\n",
+ " obj[key] = original[key]\n",
+ " return obj;\n",
+ " }, {});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.mouse_event = function(event, name) {\n",
+ " var canvas_pos = mpl.findpos(event)\n",
+ "\n",
+ " if (name === 'button_press')\n",
+ " {\n",
+ " this.canvas.focus();\n",
+ " this.canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " var x = canvas_pos.x;\n",
+ " var y = canvas_pos.y;\n",
+ "\n",
+ " this.send_message(name, {x: x, y: y, button: event.button,\n",
+ " step: event.step,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ "\n",
+ " /* This prevents the web browser from automatically changing to\n",
+ " * the text insertion cursor when the button is pressed. We want\n",
+ " * to control all of the cursor setting manually through the\n",
+ " * 'cursor' event from matplotlib */\n",
+ " event.preventDefault();\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " // Handle any extra behaviour associated with a key event\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.key_event = function(event, name) {\n",
+ "\n",
+ " // Prevent repeat events\n",
+ " if (name == 'key_press')\n",
+ " {\n",
+ " if (event.which === this._key)\n",
+ " return;\n",
+ " else\n",
+ " this._key = event.which;\n",
+ " }\n",
+ " if (name == 'key_release')\n",
+ " this._key = null;\n",
+ "\n",
+ " var value = '';\n",
+ " if (event.ctrlKey && event.which != 17)\n",
+ " value += \"ctrl+\";\n",
+ " if (event.altKey && event.which != 18)\n",
+ " value += \"alt+\";\n",
+ " if (event.shiftKey && event.which != 16)\n",
+ " value += \"shift+\";\n",
+ "\n",
+ " value += 'k';\n",
+ " value += event.which.toString();\n",
+ "\n",
+ " this._key_event_extra(event, name);\n",
+ "\n",
+ " this.send_message(name, {key: value,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
+ " if (name == 'download') {\n",
+ " this.handle_save(this, null);\n",
+ " } else {\n",
+ " this.send_message(\"toolbar_button\", {name: name});\n",
+ " }\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
+ " this.message.textContent = tooltip;\n",
+ "};\n",
+ "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
+ "\n",
+ "mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n",
+ "\n",
+ "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
+ " // Create a \"websocket\"-like object which calls the given IPython comm\n",
+ " // object with the appropriate methods. Currently this is a non binary\n",
+ " // socket, so there is still some room for performance tuning.\n",
+ " var ws = {};\n",
+ "\n",
+ " ws.close = function() {\n",
+ " comm.close()\n",
+ " };\n",
+ " ws.send = function(m) {\n",
+ " //console.log('sending', m);\n",
+ " comm.send(m);\n",
+ " };\n",
+ " // Register the callback with on_msg.\n",
+ " comm.on_msg(function(msg) {\n",
+ " //console.log('receiving', msg['content']['data'], msg);\n",
+ " // Pass the mpl event to the overriden (by mpl) onmessage function.\n",
+ " ws.onmessage(msg['content']['data'])\n",
+ " });\n",
+ " return ws;\n",
+ "}\n",
+ "\n",
+ "mpl.mpl_figure_comm = function(comm, msg) {\n",
+ " // This is the function which gets called when the mpl process\n",
+ " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
+ "\n",
+ " var id = msg.content.data.id;\n",
+ " // Get hold of the div created by the display call when the Comm\n",
+ " // socket was opened in Python.\n",
+ " var element = $(\"#\" + id);\n",
+ " var ws_proxy = comm_websocket_adapter(comm)\n",
+ "\n",
+ " function ondownload(figure, format) {\n",
+ " window.open(figure.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " var fig = new mpl.figure(id, ws_proxy,\n",
+ " ondownload,\n",
+ " element.get(0));\n",
+ "\n",
+ " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
+ " // web socket which is closed, not our websocket->open comm proxy.\n",
+ " ws_proxy.onopen();\n",
+ "\n",
+ " fig.parent_element = element.get(0);\n",
+ " fig.cell_info = mpl.find_output_cell(\"\");\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('');\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'] = '';\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 = $('')\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 = $('');\n",
+ " button.click(method_name, toolbar_event);\n",
+ " button.mouseover(tooltip, toolbar_mouse_event);\n",
+ " nav_element.append(button);\n",
+ " }\n",
+ "\n",
+ " // Add the status bar.\n",
+ " var status_bar = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "\n",
+ " // Add the close button to the window.\n",
+ " var buttongrp = $('');\n",
+ " var button = $('');\n",
+ " button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
+ " button.mouseover('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= 3 moved mimebundle to data attribute of output\n",
+ " data = data.data;\n",
+ " }\n",
+ " if (data['text/html'] == html_output) {\n",
+ " return [cell, data, j];\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "// Register the function which deals with the matplotlib target/channel.\n",
+ "// The kernel may be null if the page has been refreshed.\n",
+ "if (IPython.notebook.kernel != null) {\n",
+ " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
+ "}\n"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ ""
+ ],
"text/plain": [
- ""
+ ""
]
},
"metadata": {},
@@ -97,25 +869,799 @@
}
],
"source": [
- "from matplotlib import pyplot as plt\n",
"plt.rcParams['figure.figsize'] = 10, 10\n",
"\n",
- "plt.plot(time, voltage)\n",
- "plt.show()"
+ "fig1, ax1 = plt.subplots(1)\n",
+ "ax1.plot(time, voltage)\n",
+ "ax1.set_xlabel('Time (ms)')\n",
+ "ax1.set_ylabel('Membrane voltage (mV)');"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Let's zoom in on one spike"
]
},
{
"cell_type": "code",
- "execution_count": 14,
+ "execution_count": 4,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
- "image/png": "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\nTkSuQmCC\n",
+ "application/javascript": [
+ "/* Put everything inside the global mpl namespace */\n",
+ "window.mpl = {};\n",
+ "\n",
+ "mpl.get_websocket_type = function() {\n",
+ " if (typeof(WebSocket) !== 'undefined') {\n",
+ " return WebSocket;\n",
+ " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
+ " return MozWebSocket;\n",
+ " } else {\n",
+ " alert('Your browser does not have WebSocket support.' +\n",
+ " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
+ " 'Firefox 4 and 5 are also supported but you ' +\n",
+ " 'have to enable WebSockets in about:config.');\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
+ " this.id = figure_id;\n",
+ "\n",
+ " this.ws = websocket;\n",
+ "\n",
+ " this.supports_binary = (this.ws.binaryType != undefined);\n",
+ "\n",
+ " if (!this.supports_binary) {\n",
+ " var warnings = document.getElementById(\"mpl-warnings\");\n",
+ " if (warnings) {\n",
+ " warnings.style.display = 'block';\n",
+ " warnings.textContent = (\n",
+ " \"This browser does not support binary websocket messages. \" +\n",
+ " \"Performance may be slow.\");\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " this.imageObj = new Image();\n",
+ "\n",
+ " this.context = undefined;\n",
+ " this.message = undefined;\n",
+ " this.canvas = undefined;\n",
+ " this.rubberband_canvas = undefined;\n",
+ " this.rubberband_context = undefined;\n",
+ " this.format_dropdown = undefined;\n",
+ "\n",
+ " this.image_mode = 'full';\n",
+ "\n",
+ " this.root = $('');\n",
+ " this._root_extra_style(this.root)\n",
+ " this.root.attr('style', 'display: inline-block');\n",
+ "\n",
+ " $(parent_element).append(this.root);\n",
+ "\n",
+ " this._init_header(this);\n",
+ " this._init_canvas(this);\n",
+ " this._init_toolbar(this);\n",
+ "\n",
+ " var fig = this;\n",
+ "\n",
+ " this.waiting = false;\n",
+ "\n",
+ " this.ws.onopen = function () {\n",
+ " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
+ " fig.send_message(\"send_image_mode\", {});\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " }\n",
+ "\n",
+ " this.imageObj.onload = function() {\n",
+ " if (fig.image_mode == 'full') {\n",
+ " // Full images could contain transparency (where diff images\n",
+ " // almost always do), so we need to clear the canvas so that\n",
+ " // there is no ghosting.\n",
+ " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
+ " }\n",
+ " fig.context.drawImage(fig.imageObj, 0, 0);\n",
+ " };\n",
+ "\n",
+ " this.imageObj.onunload = function() {\n",
+ " this.ws.close();\n",
+ " }\n",
+ "\n",
+ " this.ws.onmessage = this._make_on_message_function(this);\n",
+ "\n",
+ " this.ondownload = ondownload;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_header = function() {\n",
+ " var titlebar = $(\n",
+ " '');\n",
+ " var titletext = $(\n",
+ " '');\n",
+ " titlebar.append(titletext)\n",
+ " this.root.append(titlebar);\n",
+ " this.header = titletext[0];\n",
+ "}\n",
+ "\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
+ "\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
+ "\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_canvas = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var canvas_div = $('');\n",
+ "\n",
+ " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
+ "\n",
+ " function canvas_keyboard_event(event) {\n",
+ " return fig.key_event(event, event['data']);\n",
+ " }\n",
+ "\n",
+ " canvas_div.keydown('key_press', canvas_keyboard_event);\n",
+ " canvas_div.keyup('key_release', canvas_keyboard_event);\n",
+ " this.canvas_div = canvas_div\n",
+ " this._canvas_extra_style(canvas_div)\n",
+ " this.root.append(canvas_div);\n",
+ "\n",
+ " var canvas = $('');\n",
+ " canvas.addClass('mpl-canvas');\n",
+ " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
+ "\n",
+ " this.canvas = canvas[0];\n",
+ " this.context = canvas[0].getContext(\"2d\");\n",
+ "\n",
+ " var rubberband = $('');\n",
+ " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
+ "\n",
+ " var pass_mouse_events = true;\n",
+ "\n",
+ " canvas_div.resizable({\n",
+ " start: function(event, ui) {\n",
+ " pass_mouse_events = false;\n",
+ " },\n",
+ " resize: function(event, ui) {\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " stop: function(event, ui) {\n",
+ " pass_mouse_events = true;\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " });\n",
+ "\n",
+ " function mouse_event_fn(event) {\n",
+ " if (pass_mouse_events)\n",
+ " return fig.mouse_event(event, event['data']);\n",
+ " }\n",
+ "\n",
+ " rubberband.mousedown('button_press', mouse_event_fn);\n",
+ " rubberband.mouseup('button_release', mouse_event_fn);\n",
+ " // Throttle sequential mouse events to 1 every 20ms.\n",
+ " rubberband.mousemove('motion_notify', mouse_event_fn);\n",
+ "\n",
+ " rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
+ " rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
+ "\n",
+ " canvas_div.on(\"wheel\", function (event) {\n",
+ " event = event.originalEvent;\n",
+ " event['data'] = 'scroll'\n",
+ " if (event.deltaY < 0) {\n",
+ " event.step = 1;\n",
+ " } else {\n",
+ " event.step = -1;\n",
+ " }\n",
+ " mouse_event_fn(event);\n",
+ " });\n",
+ "\n",
+ " canvas_div.append(canvas);\n",
+ " canvas_div.append(rubberband);\n",
+ "\n",
+ " this.rubberband = rubberband;\n",
+ " this.rubberband_canvas = rubberband[0];\n",
+ " this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
+ " this.rubberband_context.strokeStyle = \"#000000\";\n",
+ "\n",
+ " this._resize_canvas = function(width, height) {\n",
+ " // Keep the size of the canvas, canvas container, and rubber band\n",
+ " // canvas in synch.\n",
+ " canvas_div.css('width', width)\n",
+ " canvas_div.css('height', height)\n",
+ "\n",
+ " canvas.attr('width', width);\n",
+ " canvas.attr('height', height);\n",
+ "\n",
+ " rubberband.attr('width', width);\n",
+ " rubberband.attr('height', height);\n",
+ " }\n",
+ "\n",
+ " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
+ " // upon first draw.\n",
+ " this._resize_canvas(600, 600);\n",
+ "\n",
+ " // Disable right mouse context menu.\n",
+ " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
+ " return false;\n",
+ " });\n",
+ "\n",
+ " function set_focus () {\n",
+ " canvas.focus();\n",
+ " canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " window.setTimeout(set_focus, 100);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_toolbar = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var nav_element = $('')\n",
+ " nav_element.attr('style', 'width: 100%');\n",
+ " this.root.append(nav_element);\n",
+ "\n",
+ " // Define a callback function for later on.\n",
+ " function toolbar_event(event) {\n",
+ " return fig.toolbar_button_onclick(event['data']);\n",
+ " }\n",
+ " function toolbar_mouse_event(event) {\n",
+ " return fig.toolbar_button_onmouseover(event['data']);\n",
+ " }\n",
+ "\n",
+ " for(var toolbar_ind in mpl.toolbar_items) {\n",
+ " var name = mpl.toolbar_items[toolbar_ind][0];\n",
+ " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
+ " var image = mpl.toolbar_items[toolbar_ind][2];\n",
+ " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
+ "\n",
+ " if (!name) {\n",
+ " // put a spacer in here.\n",
+ " continue;\n",
+ " }\n",
+ " var button = $('');\n",
+ " button.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 = $('');\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 = $('');\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 = $('');\n",
+ "\n",
+ " var fmt_picker = $('');\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",
+ " '', {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 = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
+ " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
+ " // which will in turn request a refresh of the image.\n",
+ " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_message = function(type, properties) {\n",
+ " properties['type'] = type;\n",
+ " properties['figure_id'] = this.id;\n",
+ " this.ws.send(JSON.stringify(properties));\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_draw_message = function() {\n",
+ " if (!this.waiting) {\n",
+ " this.waiting = true;\n",
+ " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " var format_dropdown = fig.format_dropdown;\n",
+ " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
+ " fig.ondownload(fig, format);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
+ " var size = msg['size'];\n",
+ " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
+ " fig._resize_canvas(size[0], size[1]);\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
+ " var x0 = msg['x0'];\n",
+ " var y0 = fig.canvas.height - msg['y0'];\n",
+ " var x1 = msg['x1'];\n",
+ " var y1 = fig.canvas.height - msg['y1'];\n",
+ " x0 = Math.floor(x0) + 0.5;\n",
+ " y0 = Math.floor(y0) + 0.5;\n",
+ " x1 = Math.floor(x1) + 0.5;\n",
+ " y1 = Math.floor(y1) + 0.5;\n",
+ " var min_x = Math.min(x0, x1);\n",
+ " var min_y = Math.min(y0, y1);\n",
+ " var width = Math.abs(x1 - x0);\n",
+ " var height = Math.abs(y1 - y0);\n",
+ "\n",
+ " fig.rubberband_context.clearRect(\n",
+ " 0, 0, fig.canvas.width, fig.canvas.height);\n",
+ "\n",
+ " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
+ " // Updates the figure title.\n",
+ " fig.header.textContent = msg['label'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
+ " var cursor = msg['cursor'];\n",
+ " switch(cursor)\n",
+ " {\n",
+ " case 0:\n",
+ " cursor = 'pointer';\n",
+ " break;\n",
+ " case 1:\n",
+ " cursor = 'default';\n",
+ " break;\n",
+ " case 2:\n",
+ " cursor = 'crosshair';\n",
+ " break;\n",
+ " case 3:\n",
+ " cursor = 'move';\n",
+ " break;\n",
+ " }\n",
+ " fig.rubberband_canvas.style.cursor = cursor;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
+ " fig.message.textContent = msg['message'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
+ " // Request the server to send over a new figure.\n",
+ " fig.send_draw_message();\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
+ " fig.image_mode = msg['mode'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.updated_canvas_event = function() {\n",
+ " // Called whenever the canvas gets updated.\n",
+ " this.send_message(\"ack\", {});\n",
+ "}\n",
+ "\n",
+ "// A function to construct a web socket function for onmessage handling.\n",
+ "// Called in the figure constructor.\n",
+ "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
+ " return function socket_on_message(evt) {\n",
+ " if (evt.data instanceof Blob) {\n",
+ " /* FIXME: We get \"Resource interpreted as Image but\n",
+ " * transferred with MIME type text/plain:\" errors on\n",
+ " * Chrome. But how to set the MIME type? It doesn't seem\n",
+ " * to be part of the websocket stream */\n",
+ " evt.data.type = \"image/png\";\n",
+ "\n",
+ " /* Free the memory for the previous frames */\n",
+ " if (fig.imageObj.src) {\n",
+ " (window.URL || window.webkitURL).revokeObjectURL(\n",
+ " fig.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
+ " evt.data);\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
+ " fig.imageObj.src = evt.data;\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var msg = JSON.parse(evt.data);\n",
+ " var msg_type = msg['type'];\n",
+ "\n",
+ " // Call the \"handle_{type}\" callback, which takes\n",
+ " // the figure and JSON message as its only arguments.\n",
+ " try {\n",
+ " var callback = fig[\"handle_\" + msg_type];\n",
+ " } catch (e) {\n",
+ " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " if (callback) {\n",
+ " try {\n",
+ " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
+ " callback(fig, msg);\n",
+ " } catch (e) {\n",
+ " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
+ " }\n",
+ " }\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
+ "mpl.findpos = function(e) {\n",
+ " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
+ " var targ;\n",
+ " if (!e)\n",
+ " e = window.event;\n",
+ " if (e.target)\n",
+ " targ = e.target;\n",
+ " else if (e.srcElement)\n",
+ " targ = e.srcElement;\n",
+ " if (targ.nodeType == 3) // defeat Safari bug\n",
+ " targ = targ.parentNode;\n",
+ "\n",
+ " // jQuery normalizes the pageX and pageY\n",
+ " // pageX,Y are the mouse positions relative to the document\n",
+ " // offset() returns the position of the element relative to the document\n",
+ " var x = e.pageX - $(targ).offset().left;\n",
+ " var y = e.pageY - $(targ).offset().top;\n",
+ "\n",
+ " return {\"x\": x, \"y\": y};\n",
+ "};\n",
+ "\n",
+ "/*\n",
+ " * return a copy of an object with only non-object keys\n",
+ " * we need this to avoid circular references\n",
+ " * http://stackoverflow.com/a/24161582/3208463\n",
+ " */\n",
+ "function simpleKeys (original) {\n",
+ " return Object.keys(original).reduce(function (obj, key) {\n",
+ " if (typeof original[key] !== 'object')\n",
+ " obj[key] = original[key]\n",
+ " return obj;\n",
+ " }, {});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.mouse_event = function(event, name) {\n",
+ " var canvas_pos = mpl.findpos(event)\n",
+ "\n",
+ " if (name === 'button_press')\n",
+ " {\n",
+ " this.canvas.focus();\n",
+ " this.canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " var x = canvas_pos.x;\n",
+ " var y = canvas_pos.y;\n",
+ "\n",
+ " this.send_message(name, {x: x, y: y, button: event.button,\n",
+ " step: event.step,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ "\n",
+ " /* This prevents the web browser from automatically changing to\n",
+ " * the text insertion cursor when the button is pressed. We want\n",
+ " * to control all of the cursor setting manually through the\n",
+ " * 'cursor' event from matplotlib */\n",
+ " event.preventDefault();\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " // Handle any extra behaviour associated with a key event\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.key_event = function(event, name) {\n",
+ "\n",
+ " // Prevent repeat events\n",
+ " if (name == 'key_press')\n",
+ " {\n",
+ " if (event.which === this._key)\n",
+ " return;\n",
+ " else\n",
+ " this._key = event.which;\n",
+ " }\n",
+ " if (name == 'key_release')\n",
+ " this._key = null;\n",
+ "\n",
+ " var value = '';\n",
+ " if (event.ctrlKey && event.which != 17)\n",
+ " value += \"ctrl+\";\n",
+ " if (event.altKey && event.which != 18)\n",
+ " value += \"alt+\";\n",
+ " if (event.shiftKey && event.which != 16)\n",
+ " value += \"shift+\";\n",
+ "\n",
+ " value += 'k';\n",
+ " value += event.which.toString();\n",
+ "\n",
+ " this._key_event_extra(event, name);\n",
+ "\n",
+ " this.send_message(name, {key: value,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
+ " if (name == 'download') {\n",
+ " this.handle_save(this, null);\n",
+ " } else {\n",
+ " this.send_message(\"toolbar_button\", {name: name});\n",
+ " }\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
+ " this.message.textContent = tooltip;\n",
+ "};\n",
+ "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
+ "\n",
+ "mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n",
+ "\n",
+ "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
+ " // Create a \"websocket\"-like object which calls the given IPython comm\n",
+ " // object with the appropriate methods. Currently this is a non binary\n",
+ " // socket, so there is still some room for performance tuning.\n",
+ " var ws = {};\n",
+ "\n",
+ " ws.close = function() {\n",
+ " comm.close()\n",
+ " };\n",
+ " ws.send = function(m) {\n",
+ " //console.log('sending', m);\n",
+ " comm.send(m);\n",
+ " };\n",
+ " // Register the callback with on_msg.\n",
+ " comm.on_msg(function(msg) {\n",
+ " //console.log('receiving', msg['content']['data'], msg);\n",
+ " // Pass the mpl event to the overriden (by mpl) onmessage function.\n",
+ " ws.onmessage(msg['content']['data'])\n",
+ " });\n",
+ " return ws;\n",
+ "}\n",
+ "\n",
+ "mpl.mpl_figure_comm = function(comm, msg) {\n",
+ " // This is the function which gets called when the mpl process\n",
+ " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
+ "\n",
+ " var id = msg.content.data.id;\n",
+ " // Get hold of the div created by the display call when the Comm\n",
+ " // socket was opened in Python.\n",
+ " var element = $(\"#\" + id);\n",
+ " var ws_proxy = comm_websocket_adapter(comm)\n",
+ "\n",
+ " function ondownload(figure, format) {\n",
+ " window.open(figure.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " var fig = new mpl.figure(id, ws_proxy,\n",
+ " ondownload,\n",
+ " element.get(0));\n",
+ "\n",
+ " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
+ " // web socket which is closed, not our websocket->open comm proxy.\n",
+ " ws_proxy.onopen();\n",
+ "\n",
+ " fig.parent_element = element.get(0);\n",
+ " fig.cell_info = mpl.find_output_cell(\"\");\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('');\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'] = '';\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 = $('')\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 = $('');\n",
+ " button.click(method_name, toolbar_event);\n",
+ " button.mouseover(tooltip, toolbar_mouse_event);\n",
+ " nav_element.append(button);\n",
+ " }\n",
+ "\n",
+ " // Add the status bar.\n",
+ " var status_bar = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "\n",
+ " // Add the close button to the window.\n",
+ " var buttongrp = $('');\n",
+ " var button = $('');\n",
+ " button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
+ " button.mouseover('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= 3 moved mimebundle to data attribute of output\n",
+ " data = data.data;\n",
+ " }\n",
+ " if (data['text/html'] == html_output) {\n",
+ " return [cell, data, j];\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "// Register the function which deals with the matplotlib target/channel.\n",
+ "// The kernel may be null if the page has been refreshed.\n",
+ "if (IPython.notebook.kernel != null) {\n",
+ " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
+ "}\n"
+ ],
"text/plain": [
- ""
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
]
},
"metadata": {},
@@ -123,20 +1669,34 @@
}
],
"source": [
- "from matplotlib import pyplot as plt\n",
- "plt.rcParams['figure.figsize'] = 10, 10\n",
+ "fig2, ax2 = plt.subplots(1)\n",
"time_spike_indices = numpy.where((time > 900) & (time < 930))\n",
"time_spike = time[time_spike_indices]\n",
"voltage_spike = voltage[time_spike_indices]\n",
- "plt.plot(time_spike, voltage_spike)\n",
- "plt.xlabel('time (ms)')\n",
- "plt.ylabel('voltage (mV)')\n",
- "plt.show()"
+ "ax2.plot(time_spike, voltage_spike)\n",
+ "ax2.set_xlabel('Time (ms)')\n",
+ "ax2.set_ylabel('Membrane voltage (mV)');"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "## eFeature extraction"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now that we have the data, we can use the eFEL to extract eFeature values from the trace.\n",
+ "\n",
+ "We will use the getFeatureValues() function, which accepts as input a dictionary that represents the trace, and the request eFeature names. The trace dictionary consists of the time and voltage trace, and two floats stim_start and stim_end that specify when the stimulus starts and stops."
]
},
{
"cell_type": "code",
- "execution_count": 15,
+ "execution_count": 5,
"metadata": {
"collapsed": false
},
@@ -147,42 +1707,826 @@
"trace = {'T': time, 'V': voltage, 'stim_start': [stim_start], 'stim_end': [stim_end]}"
]
},
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "Now we call the getFeatureValues() function and print the eFeature values. The eFeatures that are calculated on single action potentials will return a list with the values for the individual spikes. "
+ ]
+ },
{
"cell_type": "code",
- "execution_count": 16,
+ "execution_count": 6,
"metadata": {
"collapsed": false
},
"outputs": [
{
- "name": "stdout",
- "output_type": "stream",
- "text": [
- "{'AP_amplitude': array([ 72.57824413, 46.36725526, 41.15466792, 39.7631751 ,\n",
- " 36.1614653 , 37.84892957]), 'AP_begin_time': array([ 706.8, 909.8, 1404.3, 1710.3, 2385.7, 2636. ]), 'peak_voltage': array([ 18.7490201 , 9.26229141, 5.71846652, 5.84323464,\n",
- " 3.56232023, 4.47506991]), 'AP_begin_width': array([ 4.7, 4.4, 4.7, 4.6, 4.8, 5. ]), 'AP_begin_voltage': array([-53.82922403, -37.10496385, -35.4362014 , -33.91994045,\n",
- " -32.59914507, -33.37385967]), 'peak_time': array([ 708. , 911.3, 1406. , 1712. , 2387.5, 2637.8])}\n"
- ]
+ "data": {
+ "text/html": [
+ "AP_amplitude | - 72.5782441262
- 46.3672552618
- 41.1546679158
- 39.7631750953
- 36.1614653031
- 37.8489295737
|
---|
AP_begin_time | - 706.8
- 909.8
- 1404.3
- 1710.3
- 2385.7
- 2636.0
|
---|
peak_voltage | - 18.7490200995
- 9.26229141264
- 5.71846652014
- 5.84323464261
- 3.56232022925
- 4.47506990872
|
---|
AP_begin_width | |
---|
mean_frequency | |
---|
AP_begin_voltage | - -53.8292240267
- -37.1049638492
- -35.4362013957
- -33.9199404527
- -32.5991450739
- -33.373859665
|
---|
peak_time | - 708.0
- 911.3
- 1406.0
- 1712.0
- 2387.5
- 2637.8
|
---|
"
+ ],
+ "text/plain": [
+ ""
+ ]
+ },
+ "execution_count": 6,
+ "metadata": {},
+ "output_type": "execute_result"
}
],
"source": [
"feature_values = efel.getFeatureValues([trace], ['AP_amplitude', 'peak_time', 'peak_voltage', 'AP_begin_time', 'AP_begin_width', \n",
- " 'AP_begin_voltage'])[0]\n",
- "print feature_values"
+ " 'AP_begin_voltage', 'mean_frequency'])[0]\n",
+ "feature_values = {feature_name: list(values) for feature_name, values in feature_values.iteritems()}\n",
+ "IPython.display.HTML(json2html.convert(json=feature_values))"
+ ]
+ },
+ {
+ "cell_type": "markdown",
+ "metadata": {},
+ "source": [
+ "We can take the calculated eFeatures for the first action potential, and overlay them on a plot."
]
},
{
"cell_type": "code",
- "execution_count": 17,
+ "execution_count": 8,
"metadata": {
"collapsed": false
},
"outputs": [
{
"data": {
- "image/png": "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\n",
+ "application/javascript": [
+ "/* Put everything inside the global mpl namespace */\n",
+ "window.mpl = {};\n",
+ "\n",
+ "mpl.get_websocket_type = function() {\n",
+ " if (typeof(WebSocket) !== 'undefined') {\n",
+ " return WebSocket;\n",
+ " } else if (typeof(MozWebSocket) !== 'undefined') {\n",
+ " return MozWebSocket;\n",
+ " } else {\n",
+ " alert('Your browser does not have WebSocket support.' +\n",
+ " 'Please try Chrome, Safari or Firefox ≥ 6. ' +\n",
+ " 'Firefox 4 and 5 are also supported but you ' +\n",
+ " 'have to enable WebSockets in about:config.');\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure = function(figure_id, websocket, ondownload, parent_element) {\n",
+ " this.id = figure_id;\n",
+ "\n",
+ " this.ws = websocket;\n",
+ "\n",
+ " this.supports_binary = (this.ws.binaryType != undefined);\n",
+ "\n",
+ " if (!this.supports_binary) {\n",
+ " var warnings = document.getElementById(\"mpl-warnings\");\n",
+ " if (warnings) {\n",
+ " warnings.style.display = 'block';\n",
+ " warnings.textContent = (\n",
+ " \"This browser does not support binary websocket messages. \" +\n",
+ " \"Performance may be slow.\");\n",
+ " }\n",
+ " }\n",
+ "\n",
+ " this.imageObj = new Image();\n",
+ "\n",
+ " this.context = undefined;\n",
+ " this.message = undefined;\n",
+ " this.canvas = undefined;\n",
+ " this.rubberband_canvas = undefined;\n",
+ " this.rubberband_context = undefined;\n",
+ " this.format_dropdown = undefined;\n",
+ "\n",
+ " this.image_mode = 'full';\n",
+ "\n",
+ " this.root = $('');\n",
+ " this._root_extra_style(this.root)\n",
+ " this.root.attr('style', 'display: inline-block');\n",
+ "\n",
+ " $(parent_element).append(this.root);\n",
+ "\n",
+ " this._init_header(this);\n",
+ " this._init_canvas(this);\n",
+ " this._init_toolbar(this);\n",
+ "\n",
+ " var fig = this;\n",
+ "\n",
+ " this.waiting = false;\n",
+ "\n",
+ " this.ws.onopen = function () {\n",
+ " fig.send_message(\"supports_binary\", {value: fig.supports_binary});\n",
+ " fig.send_message(\"send_image_mode\", {});\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " }\n",
+ "\n",
+ " this.imageObj.onload = function() {\n",
+ " if (fig.image_mode == 'full') {\n",
+ " // Full images could contain transparency (where diff images\n",
+ " // almost always do), so we need to clear the canvas so that\n",
+ " // there is no ghosting.\n",
+ " fig.context.clearRect(0, 0, fig.canvas.width, fig.canvas.height);\n",
+ " }\n",
+ " fig.context.drawImage(fig.imageObj, 0, 0);\n",
+ " };\n",
+ "\n",
+ " this.imageObj.onunload = function() {\n",
+ " this.ws.close();\n",
+ " }\n",
+ "\n",
+ " this.ws.onmessage = this._make_on_message_function(this);\n",
+ "\n",
+ " this.ondownload = ondownload;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_header = function() {\n",
+ " var titlebar = $(\n",
+ " '');\n",
+ " var titletext = $(\n",
+ " '');\n",
+ " titlebar.append(titletext)\n",
+ " this.root.append(titlebar);\n",
+ " this.header = titletext[0];\n",
+ "}\n",
+ "\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype._canvas_extra_style = function(canvas_div) {\n",
+ "\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype._root_extra_style = function(canvas_div) {\n",
+ "\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_canvas = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var canvas_div = $('');\n",
+ "\n",
+ " canvas_div.attr('style', 'position: relative; clear: both; outline: 0');\n",
+ "\n",
+ " function canvas_keyboard_event(event) {\n",
+ " return fig.key_event(event, event['data']);\n",
+ " }\n",
+ "\n",
+ " canvas_div.keydown('key_press', canvas_keyboard_event);\n",
+ " canvas_div.keyup('key_release', canvas_keyboard_event);\n",
+ " this.canvas_div = canvas_div\n",
+ " this._canvas_extra_style(canvas_div)\n",
+ " this.root.append(canvas_div);\n",
+ "\n",
+ " var canvas = $('');\n",
+ " canvas.addClass('mpl-canvas');\n",
+ " canvas.attr('style', \"left: 0; top: 0; z-index: 0; outline: 0\")\n",
+ "\n",
+ " this.canvas = canvas[0];\n",
+ " this.context = canvas[0].getContext(\"2d\");\n",
+ "\n",
+ " var rubberband = $('');\n",
+ " rubberband.attr('style', \"position: absolute; left: 0; top: 0; z-index: 1;\")\n",
+ "\n",
+ " var pass_mouse_events = true;\n",
+ "\n",
+ " canvas_div.resizable({\n",
+ " start: function(event, ui) {\n",
+ " pass_mouse_events = false;\n",
+ " },\n",
+ " resize: function(event, ui) {\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " stop: function(event, ui) {\n",
+ " pass_mouse_events = true;\n",
+ " fig.request_resize(ui.size.width, ui.size.height);\n",
+ " },\n",
+ " });\n",
+ "\n",
+ " function mouse_event_fn(event) {\n",
+ " if (pass_mouse_events)\n",
+ " return fig.mouse_event(event, event['data']);\n",
+ " }\n",
+ "\n",
+ " rubberband.mousedown('button_press', mouse_event_fn);\n",
+ " rubberband.mouseup('button_release', mouse_event_fn);\n",
+ " // Throttle sequential mouse events to 1 every 20ms.\n",
+ " rubberband.mousemove('motion_notify', mouse_event_fn);\n",
+ "\n",
+ " rubberband.mouseenter('figure_enter', mouse_event_fn);\n",
+ " rubberband.mouseleave('figure_leave', mouse_event_fn);\n",
+ "\n",
+ " canvas_div.on(\"wheel\", function (event) {\n",
+ " event = event.originalEvent;\n",
+ " event['data'] = 'scroll'\n",
+ " if (event.deltaY < 0) {\n",
+ " event.step = 1;\n",
+ " } else {\n",
+ " event.step = -1;\n",
+ " }\n",
+ " mouse_event_fn(event);\n",
+ " });\n",
+ "\n",
+ " canvas_div.append(canvas);\n",
+ " canvas_div.append(rubberband);\n",
+ "\n",
+ " this.rubberband = rubberband;\n",
+ " this.rubberband_canvas = rubberband[0];\n",
+ " this.rubberband_context = rubberband[0].getContext(\"2d\");\n",
+ " this.rubberband_context.strokeStyle = \"#000000\";\n",
+ "\n",
+ " this._resize_canvas = function(width, height) {\n",
+ " // Keep the size of the canvas, canvas container, and rubber band\n",
+ " // canvas in synch.\n",
+ " canvas_div.css('width', width)\n",
+ " canvas_div.css('height', height)\n",
+ "\n",
+ " canvas.attr('width', width);\n",
+ " canvas.attr('height', height);\n",
+ "\n",
+ " rubberband.attr('width', width);\n",
+ " rubberband.attr('height', height);\n",
+ " }\n",
+ "\n",
+ " // Set the figure to an initial 600x600px, this will subsequently be updated\n",
+ " // upon first draw.\n",
+ " this._resize_canvas(600, 600);\n",
+ "\n",
+ " // Disable right mouse context menu.\n",
+ " $(this.rubberband_canvas).bind(\"contextmenu\",function(e){\n",
+ " return false;\n",
+ " });\n",
+ "\n",
+ " function set_focus () {\n",
+ " canvas.focus();\n",
+ " canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " window.setTimeout(set_focus, 100);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._init_toolbar = function() {\n",
+ " var fig = this;\n",
+ "\n",
+ " var nav_element = $('')\n",
+ " nav_element.attr('style', 'width: 100%');\n",
+ " this.root.append(nav_element);\n",
+ "\n",
+ " // Define a callback function for later on.\n",
+ " function toolbar_event(event) {\n",
+ " return fig.toolbar_button_onclick(event['data']);\n",
+ " }\n",
+ " function toolbar_mouse_event(event) {\n",
+ " return fig.toolbar_button_onmouseover(event['data']);\n",
+ " }\n",
+ "\n",
+ " for(var toolbar_ind in mpl.toolbar_items) {\n",
+ " var name = mpl.toolbar_items[toolbar_ind][0];\n",
+ " var tooltip = mpl.toolbar_items[toolbar_ind][1];\n",
+ " var image = mpl.toolbar_items[toolbar_ind][2];\n",
+ " var method_name = mpl.toolbar_items[toolbar_ind][3];\n",
+ "\n",
+ " if (!name) {\n",
+ " // put a spacer in here.\n",
+ " continue;\n",
+ " }\n",
+ " var button = $('');\n",
+ " button.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 = $('');\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 = $('');\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 = $('');\n",
+ "\n",
+ " var fmt_picker = $('');\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",
+ " '', {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 = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.request_resize = function(x_pixels, y_pixels) {\n",
+ " // Request matplotlib to resize the figure. Matplotlib will then trigger a resize in the client,\n",
+ " // which will in turn request a refresh of the image.\n",
+ " this.send_message('resize', {'width': x_pixels, 'height': y_pixels});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_message = function(type, properties) {\n",
+ " properties['type'] = type;\n",
+ " properties['figure_id'] = this.id;\n",
+ " this.ws.send(JSON.stringify(properties));\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.send_draw_message = function() {\n",
+ " if (!this.waiting) {\n",
+ " this.waiting = true;\n",
+ " this.ws.send(JSON.stringify({type: \"draw\", figure_id: this.id}));\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_save = function(fig, msg) {\n",
+ " var format_dropdown = fig.format_dropdown;\n",
+ " var format = format_dropdown.options[format_dropdown.selectedIndex].value;\n",
+ " fig.ondownload(fig, format);\n",
+ "}\n",
+ "\n",
+ "\n",
+ "mpl.figure.prototype.handle_resize = function(fig, msg) {\n",
+ " var size = msg['size'];\n",
+ " if (size[0] != fig.canvas.width || size[1] != fig.canvas.height) {\n",
+ " fig._resize_canvas(size[0], size[1]);\n",
+ " fig.send_message(\"refresh\", {});\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_rubberband = function(fig, msg) {\n",
+ " var x0 = msg['x0'];\n",
+ " var y0 = fig.canvas.height - msg['y0'];\n",
+ " var x1 = msg['x1'];\n",
+ " var y1 = fig.canvas.height - msg['y1'];\n",
+ " x0 = Math.floor(x0) + 0.5;\n",
+ " y0 = Math.floor(y0) + 0.5;\n",
+ " x1 = Math.floor(x1) + 0.5;\n",
+ " y1 = Math.floor(y1) + 0.5;\n",
+ " var min_x = Math.min(x0, x1);\n",
+ " var min_y = Math.min(y0, y1);\n",
+ " var width = Math.abs(x1 - x0);\n",
+ " var height = Math.abs(y1 - y0);\n",
+ "\n",
+ " fig.rubberband_context.clearRect(\n",
+ " 0, 0, fig.canvas.width, fig.canvas.height);\n",
+ "\n",
+ " fig.rubberband_context.strokeRect(min_x, min_y, width, height);\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_figure_label = function(fig, msg) {\n",
+ " // Updates the figure title.\n",
+ " fig.header.textContent = msg['label'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_cursor = function(fig, msg) {\n",
+ " var cursor = msg['cursor'];\n",
+ " switch(cursor)\n",
+ " {\n",
+ " case 0:\n",
+ " cursor = 'pointer';\n",
+ " break;\n",
+ " case 1:\n",
+ " cursor = 'default';\n",
+ " break;\n",
+ " case 2:\n",
+ " cursor = 'crosshair';\n",
+ " break;\n",
+ " case 3:\n",
+ " cursor = 'move';\n",
+ " break;\n",
+ " }\n",
+ " fig.rubberband_canvas.style.cursor = cursor;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_message = function(fig, msg) {\n",
+ " fig.message.textContent = msg['message'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_draw = function(fig, msg) {\n",
+ " // Request the server to send over a new figure.\n",
+ " fig.send_draw_message();\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.handle_image_mode = function(fig, msg) {\n",
+ " fig.image_mode = msg['mode'];\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.updated_canvas_event = function() {\n",
+ " // Called whenever the canvas gets updated.\n",
+ " this.send_message(\"ack\", {});\n",
+ "}\n",
+ "\n",
+ "// A function to construct a web socket function for onmessage handling.\n",
+ "// Called in the figure constructor.\n",
+ "mpl.figure.prototype._make_on_message_function = function(fig) {\n",
+ " return function socket_on_message(evt) {\n",
+ " if (evt.data instanceof Blob) {\n",
+ " /* FIXME: We get \"Resource interpreted as Image but\n",
+ " * transferred with MIME type text/plain:\" errors on\n",
+ " * Chrome. But how to set the MIME type? It doesn't seem\n",
+ " * to be part of the websocket stream */\n",
+ " evt.data.type = \"image/png\";\n",
+ "\n",
+ " /* Free the memory for the previous frames */\n",
+ " if (fig.imageObj.src) {\n",
+ " (window.URL || window.webkitURL).revokeObjectURL(\n",
+ " fig.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " fig.imageObj.src = (window.URL || window.webkitURL).createObjectURL(\n",
+ " evt.data);\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ " else if (typeof evt.data === 'string' && evt.data.slice(0, 21) == \"data:image/png;base64\") {\n",
+ " fig.imageObj.src = evt.data;\n",
+ " fig.updated_canvas_event();\n",
+ " fig.waiting = false;\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " var msg = JSON.parse(evt.data);\n",
+ " var msg_type = msg['type'];\n",
+ "\n",
+ " // Call the \"handle_{type}\" callback, which takes\n",
+ " // the figure and JSON message as its only arguments.\n",
+ " try {\n",
+ " var callback = fig[\"handle_\" + msg_type];\n",
+ " } catch (e) {\n",
+ " console.log(\"No handler for the '\" + msg_type + \"' message type: \", msg);\n",
+ " return;\n",
+ " }\n",
+ "\n",
+ " if (callback) {\n",
+ " try {\n",
+ " // console.log(\"Handling '\" + msg_type + \"' message: \", msg);\n",
+ " callback(fig, msg);\n",
+ " } catch (e) {\n",
+ " console.log(\"Exception inside the 'handler_\" + msg_type + \"' callback:\", e, e.stack, msg);\n",
+ " }\n",
+ " }\n",
+ " };\n",
+ "}\n",
+ "\n",
+ "// from http://stackoverflow.com/questions/1114465/getting-mouse-location-in-canvas\n",
+ "mpl.findpos = function(e) {\n",
+ " //this section is from http://www.quirksmode.org/js/events_properties.html\n",
+ " var targ;\n",
+ " if (!e)\n",
+ " e = window.event;\n",
+ " if (e.target)\n",
+ " targ = e.target;\n",
+ " else if (e.srcElement)\n",
+ " targ = e.srcElement;\n",
+ " if (targ.nodeType == 3) // defeat Safari bug\n",
+ " targ = targ.parentNode;\n",
+ "\n",
+ " // jQuery normalizes the pageX and pageY\n",
+ " // pageX,Y are the mouse positions relative to the document\n",
+ " // offset() returns the position of the element relative to the document\n",
+ " var x = e.pageX - $(targ).offset().left;\n",
+ " var y = e.pageY - $(targ).offset().top;\n",
+ "\n",
+ " return {\"x\": x, \"y\": y};\n",
+ "};\n",
+ "\n",
+ "/*\n",
+ " * return a copy of an object with only non-object keys\n",
+ " * we need this to avoid circular references\n",
+ " * http://stackoverflow.com/a/24161582/3208463\n",
+ " */\n",
+ "function simpleKeys (original) {\n",
+ " return Object.keys(original).reduce(function (obj, key) {\n",
+ " if (typeof original[key] !== 'object')\n",
+ " obj[key] = original[key]\n",
+ " return obj;\n",
+ " }, {});\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.mouse_event = function(event, name) {\n",
+ " var canvas_pos = mpl.findpos(event)\n",
+ "\n",
+ " if (name === 'button_press')\n",
+ " {\n",
+ " this.canvas.focus();\n",
+ " this.canvas_div.focus();\n",
+ " }\n",
+ "\n",
+ " var x = canvas_pos.x;\n",
+ " var y = canvas_pos.y;\n",
+ "\n",
+ " this.send_message(name, {x: x, y: y, button: event.button,\n",
+ " step: event.step,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ "\n",
+ " /* This prevents the web browser from automatically changing to\n",
+ " * the text insertion cursor when the button is pressed. We want\n",
+ " * to control all of the cursor setting manually through the\n",
+ " * 'cursor' event from matplotlib */\n",
+ " event.preventDefault();\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype._key_event_extra = function(event, name) {\n",
+ " // Handle any extra behaviour associated with a key event\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.key_event = function(event, name) {\n",
+ "\n",
+ " // Prevent repeat events\n",
+ " if (name == 'key_press')\n",
+ " {\n",
+ " if (event.which === this._key)\n",
+ " return;\n",
+ " else\n",
+ " this._key = event.which;\n",
+ " }\n",
+ " if (name == 'key_release')\n",
+ " this._key = null;\n",
+ "\n",
+ " var value = '';\n",
+ " if (event.ctrlKey && event.which != 17)\n",
+ " value += \"ctrl+\";\n",
+ " if (event.altKey && event.which != 18)\n",
+ " value += \"alt+\";\n",
+ " if (event.shiftKey && event.which != 16)\n",
+ " value += \"shift+\";\n",
+ "\n",
+ " value += 'k';\n",
+ " value += event.which.toString();\n",
+ "\n",
+ " this._key_event_extra(event, name);\n",
+ "\n",
+ " this.send_message(name, {key: value,\n",
+ " guiEvent: simpleKeys(event)});\n",
+ " return false;\n",
+ "}\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onclick = function(name) {\n",
+ " if (name == 'download') {\n",
+ " this.handle_save(this, null);\n",
+ " } else {\n",
+ " this.send_message(\"toolbar_button\", {name: name});\n",
+ " }\n",
+ "};\n",
+ "\n",
+ "mpl.figure.prototype.toolbar_button_onmouseover = function(tooltip) {\n",
+ " this.message.textContent = tooltip;\n",
+ "};\n",
+ "mpl.toolbar_items = [[\"Home\", \"Reset original view\", \"fa fa-home icon-home\", \"home\"], [\"Back\", \"Back to previous view\", \"fa fa-arrow-left icon-arrow-left\", \"back\"], [\"Forward\", \"Forward to next view\", \"fa fa-arrow-right icon-arrow-right\", \"forward\"], [\"\", \"\", \"\", \"\"], [\"Pan\", \"Pan axes with left mouse, zoom with right\", \"fa fa-arrows icon-move\", \"pan\"], [\"Zoom\", \"Zoom to rectangle\", \"fa fa-square-o icon-check-empty\", \"zoom\"], [\"\", \"\", \"\", \"\"], [\"Download\", \"Download plot\", \"fa fa-floppy-o icon-save\", \"download\"]];\n",
+ "\n",
+ "mpl.extensions = [\"eps\", \"pdf\", \"png\", \"ps\", \"raw\", \"svg\"];\n",
+ "\n",
+ "mpl.default_extension = \"png\";var comm_websocket_adapter = function(comm) {\n",
+ " // Create a \"websocket\"-like object which calls the given IPython comm\n",
+ " // object with the appropriate methods. Currently this is a non binary\n",
+ " // socket, so there is still some room for performance tuning.\n",
+ " var ws = {};\n",
+ "\n",
+ " ws.close = function() {\n",
+ " comm.close()\n",
+ " };\n",
+ " ws.send = function(m) {\n",
+ " //console.log('sending', m);\n",
+ " comm.send(m);\n",
+ " };\n",
+ " // Register the callback with on_msg.\n",
+ " comm.on_msg(function(msg) {\n",
+ " //console.log('receiving', msg['content']['data'], msg);\n",
+ " // Pass the mpl event to the overriden (by mpl) onmessage function.\n",
+ " ws.onmessage(msg['content']['data'])\n",
+ " });\n",
+ " return ws;\n",
+ "}\n",
+ "\n",
+ "mpl.mpl_figure_comm = function(comm, msg) {\n",
+ " // This is the function which gets called when the mpl process\n",
+ " // starts-up an IPython Comm through the \"matplotlib\" channel.\n",
+ "\n",
+ " var id = msg.content.data.id;\n",
+ " // Get hold of the div created by the display call when the Comm\n",
+ " // socket was opened in Python.\n",
+ " var element = $(\"#\" + id);\n",
+ " var ws_proxy = comm_websocket_adapter(comm)\n",
+ "\n",
+ " function ondownload(figure, format) {\n",
+ " window.open(figure.imageObj.src);\n",
+ " }\n",
+ "\n",
+ " var fig = new mpl.figure(id, ws_proxy,\n",
+ " ondownload,\n",
+ " element.get(0));\n",
+ "\n",
+ " // Call onopen now - mpl needs it, as it is assuming we've passed it a real\n",
+ " // web socket which is closed, not our websocket->open comm proxy.\n",
+ " ws_proxy.onopen();\n",
+ "\n",
+ " fig.parent_element = element.get(0);\n",
+ " fig.cell_info = mpl.find_output_cell(\"\");\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('');\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'] = '';\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 = $('')\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 = $('');\n",
+ " button.click(method_name, toolbar_event);\n",
+ " button.mouseover(tooltip, toolbar_mouse_event);\n",
+ " nav_element.append(button);\n",
+ " }\n",
+ "\n",
+ " // Add the status bar.\n",
+ " var status_bar = $('');\n",
+ " nav_element.append(status_bar);\n",
+ " this.message = status_bar[0];\n",
+ "\n",
+ " // Add the close button to the window.\n",
+ " var buttongrp = $('');\n",
+ " var button = $('');\n",
+ " button.click(function (evt) { fig.handle_close(fig, {}); } );\n",
+ " button.mouseover('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= 3 moved mimebundle to data attribute of output\n",
+ " data = data.data;\n",
+ " }\n",
+ " if (data['text/html'] == html_output) {\n",
+ " return [cell, data, j];\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ " }\n",
+ "}\n",
+ "\n",
+ "// Register the function which deals with the matplotlib target/channel.\n",
+ "// The kernel may be null if the page has been refreshed.\n",
+ "if (IPython.notebook.kernel != null) {\n",
+ " IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
+ "}\n"
+ ],
"text/plain": [
- ""
+ ""
+ ]
+ },
+ "metadata": {},
+ "output_type": "display_data"
+ },
+ {
+ "data": {
+ "text/html": [
+ ""
+ ],
+ "text/plain": [
+ ""
]
},
"metadata": {},
@@ -197,20 +2541,27 @@
"second_ap_begin_width = feature_values['AP_begin_width'][1]\n",
"second_ap_begin_voltage = feature_values['AP_begin_voltage'][1]\n",
"\n",
- "\n",
- "from matplotlib import pyplot as plt\n",
- "plt.rcParams['figure.figsize'] = 16, 12\n",
"time_spike_indices = numpy.where((time > 900) & (time < 930))\n",
"time_spike = time[time_spike_indices]\n",
"voltage_spike = voltage[time_spike_indices]\n",
- "plt.plot(time_spike, voltage_spike)\n",
- "plt.plot([second_peak_time, second_peak_time], [second_peak_voltage, second_peak_voltage-second_peak_amplitude], linewidth=4)\n",
- "plt.plot([second_ap_begin_time, second_ap_begin_time+second_ap_begin_width], \n",
+ "\n",
+ "fig3, ax3 = plt.subplots(1)\n",
+ "ax3.plot(time_spike, voltage_spike)\n",
+ "ax3.plot([second_peak_time, second_peak_time], [second_peak_voltage, second_peak_voltage-second_peak_amplitude], linewidth=4)\n",
+ "ax3.plot([second_ap_begin_time, second_ap_begin_time+second_ap_begin_width], \n",
" [second_ap_begin_voltage, second_ap_begin_voltage], linewidth=4)\n",
- "plt.xlabel('time (ms)')\n",
- "plt.ylabel('voltage (mV)')\n",
- "plt.show()"
+ "ax3.set_xlabel('time (ms)')\n",
+ "ax3.set_ylabel('voltage (mV)');"
]
+ },
+ {
+ "cell_type": "code",
+ "execution_count": null,
+ "metadata": {
+ "collapsed": true
+ },
+ "outputs": [],
+ "source": []
}
],
"metadata": {
@@ -229,7 +2580,7 @@
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython2",
- "version": "2.7.9"
+ "version": "2.7.11"
}
},
"nbformat": 4,