Skip to content

Instantly share code, notes, and snippets.

@mstimberg
Last active February 27, 2020 14:26
Show Gist options
  • Save mstimberg/f76be93773eaac925e1aa661481ddc09 to your computer and use it in GitHub Desktop.
Save mstimberg/f76be93773eaac925e1aa661481ddc09 to your computer and use it in GitHub Desktop.
Local forward sensitivity analysis of a neural model with Brian 2
Display the source blob
Display the rendered blob
Raw
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"from brian2 import *\n",
"from sympy import Matrix\n",
"%matplotlib notebook"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Function to symbolically calculate the ODEs necessary to perform *local forward sensitivity analysis* (the sensitivity of the variables to given parameters over time) on a Brian model."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"def get_sensitivity_equations(group, parameters, namespace=None, level=1):\n",
"\n",
" if namespace is None:\n",
" namespace = get_local_namespace(level)\n",
" namespace.update(group.namespace)\n",
"\n",
" eqs = group.equations\n",
" diff_eqs = eqs.get_substituted_expressions(group.variables)\n",
" diff_eq_names = [name for name, _ in diff_eqs]\n",
"\n",
" system = Matrix([diff_eq[1] for diff_eq in diff_eqs])\n",
" J = system.jacobian(diff_eq_names)\n",
"\n",
" sensitivity = []\n",
" sensitivity_names = []\n",
" for parameter in parameters:\n",
" F = system.jacobian([parameter])\n",
" names = ['S_{}_{}'.format(diff_eq_name, parameter)\n",
" for diff_eq_name in diff_eq_names]\n",
" sensitivity.append(J * Matrix(names) + F)\n",
" sensitivity_names.append(names)\n",
"\n",
" new_eqs = []\n",
" for names, sensitivity_eqs, param in zip(sensitivity_names, sensitivity, parameters):\n",
" for name, eq, orig_var in zip(names, sensitivity_eqs, diff_eq_names):\n",
" unit = eqs[orig_var].dim / namespace[param].dim\n",
" unit = repr(unit) if not unit.is_dimensionless else '1'\n",
" new_eqs.append('d{lhs}/dt = {rhs} : {unit}'.format(lhs=name,\n",
" rhs=eq,\n",
" unit=unit))\n",
" new_eqs = Equations('\\n'.join(new_eqs))\n",
" return new_eqs"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Trying out the function on a Hodgkin-Huxley model to get the sensitivity to the parameter `El` (leak reversal potential):"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"dS_h_El/dt = S_h_El*(-0.128*exp((0.0555555555555556*VT + 0.944444444444445*mV - 0.0555555555555556*v)/mV)/ms - 4.0/(ms*(exp((0.2*VT + 8.0*mV - 0.2*v)/mV) + 1.0))) + S_v_El*(-0.8*h*exp((0.2*VT + 8.0*mV - 0.2*v)/mV)/(mV*ms*(exp((0.2*VT + 8.0*mV - 0.2*v)/mV) + 1.0)**2) - 0.0555555555555556*(0.128 - 0.128*h)*exp((0.0555555555555556*VT + 0.944444444444445*mV - 0.0555555555555556*v)/mV)/(mV*ms)) : m^-2 kg^-1 s^3 A\n",
"dS_m_El/dt = S_m_El*(-0.32*mV**(-1.0)*(VT + 13.0*mV - v)/(ms*(exp((0.25*VT + 3.25*mV - 0.25*v)/mV) - 1.0)) - 0.28*mV**(-1.0)*(-VT - 40.0*mV + v)/(ms*(exp((-0.2*VT - 8.0*mV + 0.2*v)/mV) - 1.0))) + S_v_El*(0.056*m*mV**(-2.0)*(-VT - 40.0*mV + v)*exp((-0.2*VT - 8.0*mV + 0.2*v)/mV)/(ms*(exp((-0.2*VT - 8.0*mV + 0.2*v)/mV) - 1.0)**2) - 0.28*m*mV**(-1.0)/(ms*(exp((-0.2*VT - 8.0*mV + 0.2*v)/mV) - 1.0)) + 0.08*mV**(-2.0)*(1.0 - m)*(VT + 13.0*mV - v)*exp((0.25*VT + 3.25*mV - 0.25*v)/mV)/(ms*(exp((0.25*VT + 3.25*mV - 0.25*v)/mV) - 1.0)**2) - 0.32*mV**(-1.0)*(1.0 - m)/(ms*(exp((0.25*VT + 3.25*mV - 0.25*v)/mV) - 1.0))) : m^-2 kg^-1 s^3 A\n",
"dS_n_El/dt = S_n_El*(-0.032*mV**(-1.0)*(VT + 15.0*mV - v)/(ms*(exp((0.2*VT + 3.0*mV - 0.2*v)/mV) - 1.0)) - 0.5*exp((0.025*VT + 0.25*mV - 0.025*v)/mV)/ms) + S_v_El*(0.0064*mV**(-2.0)*(1.0 - n)*(VT + 15.0*mV - v)*exp((0.2*VT + 3.0*mV - 0.2*v)/mV)/(ms*(exp((0.2*VT + 3.0*mV - 0.2*v)/mV) - 1.0)**2) - 0.032*mV**(-1.0)*(1.0 - n)/(ms*(exp((0.2*VT + 3.0*mV - 0.2*v)/mV) - 1.0)) + 0.0125*n*exp((0.025*VT + 0.25*mV - 0.025*v)/mV)/(mV*ms)) : m^-2 kg^-1 s^3 A\n",
"dS_v_El/dt = -S_h_El*g_na*m**3*(-ENa + v)/Cm - 3*S_m_El*g_na*h*m**2*(-ENa + v)/Cm - 4*S_n_El*g_kd*n**3*(-EK + v)/Cm + S_v_El*(-g_kd*n**4 - g_na*h*m**3 - gl)/Cm + gl/Cm : 1\n"
]
}
],
"source": [
"eqs = Equations('''\n",
" dv/dt = (gl*(El-v) - g_na*(m*m*m)*h*(v-ENa) - g_kd*(n*n*n*n)*(v-EK) + I)/Cm : volt\n",
" I : amp (constant)\n",
" dm/dt = alpha_m*(1-m)-beta_m*m : 1\n",
" dn/dt = alpha_n*(1-n)-beta_n*n : 1\n",
" dh/dt = alpha_h*(1-h)-beta_h*h : 1\n",
" alpha_m = 0.32*(mV**-1)*(13*mV-v+VT)/ (exp((13*mV-v+VT)/(4*mV))-1.)/ms : Hz\n",
" beta_m = 0.28*(mV**-1)*(v-VT-40*mV)/ (exp((v-VT-40*mV)/(5*mV))-1)/ms : Hz\n",
" alpha_h = 0.128*exp((17*mV-v+VT)/(18*mV))/ms : Hz\n",
" beta_h = 4./(1+exp((40*mV-v+VT)/(5*mV)))/ms : Hz\n",
" alpha_n = 0.032*(mV**-1)*(15*mV-v+VT)/ (exp((15*mV-v+VT)/(5*mV))-1.)/ms : Hz\n",
" beta_n = .5*exp((10*mV-v+VT)/(40*mV))/ms : Hz\n",
" ''')\n",
"# Parameters\n",
"area = 20000 * umetre ** 2\n",
"Cm = (1 * ufarad * cm ** -2) * area\n",
"gl = (5e-5 * siemens * cm ** -2) * area\n",
"El = -70 * mV\n",
"EK = -90 * mV\n",
"ENa = 50 * mV\n",
"g_na = (100 * msiemens * cm ** -2) * area\n",
"g_kd = (30 * msiemens * cm ** -2) * area\n",
"VT = -63 * mV\n",
"group = NeuronGroup(1, eqs, method='exponential_euler')\n",
"\n",
"sensitivity_eqs = get_sensitivity_equations(group, parameters=['El'])\n",
"print(sensitivity_eqs) # a bit ugly, but hopefully correct"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Simulate the model and include the new equations"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"group = NeuronGroup(3, eqs + sensitivity_eqs, method='exponential_euler')\n",
"group.v = El\n",
"group.h = 1\n",
"group.I = [0, 0.1, 0.2]*nA\n",
"mon = StateMonitor(group, variables=True, record=True)\n",
"run(60*ms)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Show the membrane potential and its sensitivy to `El`:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"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",
" event.shiftKey = false;\n",
" // Send a \"J\" for go to next cell\n",
" event.which = 74;\n",
" event.keyCode = 74;\n",
" manager.command_mode();\n",
" manager.handle_keydown(event);\n",
" }\n",
"}\n",
"\n",
"mpl.figure.prototype.handle_save = function(fig, msg) {\n",
" fig.ondownload(fig, null);\n",
"}\n",
"\n",
"\n",
"mpl.find_output_cell = function(html_output) {\n",
" // Return the cell and output element which can be found *uniquely* in the notebook.\n",
" // Note - this is a bit hacky, but it is done because the \"notebook_saving.Notebook\"\n",
" // IPython event is triggered only after the cells have been serialised, which for\n",
" // our purposes (turning an active figure into a static one), is too late.\n",
" var cells = IPython.notebook.get_cells();\n",
" var ncells = cells.length;\n",
" for (var i=0; i<ncells; i++) {\n",
" var cell = cells[i];\n",
" if (cell.cell_type === 'code'){\n",
" for (var j=0; j<cell.output_area.outputs.length; j++) {\n",
" var data = cell.output_area.outputs[j];\n",
" if (data.data) {\n",
" // IPython >= 3 moved mimebundle to data attribute of output\n",
" data = data.data;\n",
" }\n",
" if (data['text/html'] == html_output) {\n",
" return [cell, data, j];\n",
" }\n",
" }\n",
" }\n",
" }\n",
"}\n",
"\n",
"// Register the function which deals with the matplotlib target/channel.\n",
"// The kernel may be null if the page has been refreshed.\n",
"if (IPython.notebook.kernel != null) {\n",
" IPython.notebook.kernel.comm_manager.register_target('matplotlib', mpl.mpl_figure_comm);\n",
"}\n"
],
"text/plain": [
"<IPython.core.display.Javascript object>"
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
"<img src=\"data:image/png;base64,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\" width=\"640\">"
],
"text/plain": [
"<IPython.core.display.HTML object>"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, (ax_top, ax_bottom) = plt.subplots(2, 1, sharex=True)\n",
"ax_top.plot(mon.t/ms, mon.v.T/mV)\n",
"ax_bottom.plot(mon.t/ms, mon.S_v_El.T)\n",
"ax_top.set(ylabel='v (mV)')\n",
"ax_bottom.set(xlabel='time (ms)', ylabel='sensitivity to El')\n",
"fig.tight_layout()"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python [conda env:brian2_py37] *",
"language": "python",
"name": "conda-env-brian2_py37-py"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
}
},
"nbformat": 4,
"nbformat_minor": 4
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment