{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Numerical simulatin of β-catenin destruction cycle\n", "\n", "(c) 2020 Justin Bois. With the exception of pasted graphics, where the source is noted, this work is licensed under a [Creative Commons Attribution License CC-BY 4.0](https://creativecommons.org/licenses/by/4.0/). All code contained herein is licensed under an [MIT license](https://opensource.org/licenses/MIT).\n", "\n", "This document was prepared at [Caltech](http://www.caltech.edu) with financial support from the [Donna and Benjamin M. Rosen Bioengineering Center](http://rosen.caltech.edu).\n", "\n", "\n", "\n", "*This document was generated from a Jupyter notebook, which may be downloaded [here](l03_betacat_destruction_cycle.ipynb).*" ] }, { "cell_type": "code", "execution_count": 1, "metadata": {}, "outputs": [ { "data": { "application/javascript": [ "\n", "(function(root) {\n", " function now() {\n", " return new Date();\n", " }\n", "\n", " var force = true;\n", "\n", " if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n", " root._bokeh_onload_callbacks = [];\n", " root._bokeh_is_loading = undefined;\n", " }\n", "\n", " if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n", " root._bokeh_timeout = Date.now() + 5000;\n", " root._bokeh_failed_load = false;\n", " }\n", "\n", " function run_callbacks() {\n", " try {\n", " root._bokeh_onload_callbacks.forEach(function(callback) {\n", " if (callback != null)\n", " callback();\n", " });\n", " } finally {\n", " delete root._bokeh_onload_callbacks\n", " }\n", " console.debug(\"Bokeh: all callbacks have finished\");\n", " }\n", "\n", " function load_libs(css_urls, js_urls, callback) {\n", " if (css_urls == null) css_urls = [];\n", " if (js_urls == null) js_urls = [];\n", "\n", " root._bokeh_onload_callbacks.push(callback);\n", " if (root._bokeh_is_loading > 0) {\n", " console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", " return null;\n", " }\n", " if (js_urls == null || js_urls.length === 0) {\n", " run_callbacks();\n", " return null;\n", " }\n", " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", " root._bokeh_is_loading = css_urls.length + js_urls.length;\n", "\n", " function on_load() {\n", " root._bokeh_is_loading--;\n", " if (root._bokeh_is_loading === 0) {\n", " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n", " run_callbacks()\n", " }\n", " }\n", "\n", " function on_error() {\n", " console.error(\"failed to load \" + url);\n", " }\n", "\n", " for (var i = 0; i < css_urls.length; i++) {\n", " var url = css_urls[i];\n", " const element = document.createElement(\"link\");\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.rel = \"stylesheet\";\n", " element.type = \"text/css\";\n", " element.href = url;\n", " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n", " document.body.appendChild(element);\n", " }\n", "\n", " var skip = [];\n", " if (window.requirejs) {\n", " require([], function() {\n", " })\n", " }\n", " for (var i = 0; i < js_urls.length; i++) {\n", " var url = js_urls[i];\n", " if (skip.indexOf(url) >= 0) { on_load(); continue; }\n", " var element = document.createElement('script');\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.async = false;\n", " element.src = url;\n", " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " document.head.appendChild(element);\n", " }\n", "\tif (!js_urls.length) {\n", " on_load()\n", " }\n", " };\n", "\n", " function inject_raw_css(css) {\n", " const element = document.createElement(\"style\");\n", " element.appendChild(document.createTextNode(css));\n", " document.body.appendChild(element);\n", " }\n", "\n", " var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.2.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.2.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.2.3.min.js\", \"https://unpkg.com/@holoviz/panel@^0.10.2/dist/panel.min.js\"];\n", " var css_urls = [\"https://unpkg.com/@holoviz/panel@0.10.2/dist/css/alerts.css\", \"https://unpkg.com/@holoviz/panel@0.10.2/dist/css/card.css\", \"https://unpkg.com/@holoviz/panel@0.10.2/dist/css/widgets.css\", \"https://unpkg.com/@holoviz/panel@0.10.2/dist/css/markdown.css\", \"https://unpkg.com/@holoviz/panel@0.10.2/dist/css/json.css\", \"https://unpkg.com/@holoviz/panel@0.10.2/dist/css/dataframe.css\"];\n", "\n", " var inline_js = [\n", " function(Bokeh) {\n", " Bokeh.set_log_level(\"info\");\n", " },\n", " function(Bokeh) {} // ensure no trailing comma for IE\n", " ];\n", "\n", " function run_inline_js() {\n", " if ((root.Bokeh !== undefined) || (force === true)) {\n", " for (var i = 0; i < inline_js.length; i++) {\n", " inline_js[i].call(root, root.Bokeh);\n", " }} else if (Date.now() < root._bokeh_timeout) {\n", " setTimeout(run_inline_js, 100);\n", " } else if (!root._bokeh_failed_load) {\n", " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", " root._bokeh_failed_load = true;\n", " }\n", " }\n", "\n", " if (root._bokeh_is_loading === 0) {\n", " console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n", " run_inline_js();\n", " } else {\n", " load_libs(css_urls, js_urls, function() {\n", " console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n", " run_inline_js();\n", " });\n", " }\n", "}(window));" ], "application/vnd.holoviews_load.v0+json": "\n(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls == null || js_urls.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n root._bokeh_is_loading = css_urls.length + js_urls.length;\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n\n function on_error() {\n console.error(\"failed to load \" + url);\n }\n\n for (var i = 0; i < css_urls.length; i++) {\n var url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n }\n\n var skip = [];\n if (window.requirejs) {\n require([], function() {\n })\n }\n for (var i = 0; i < js_urls.length; i++) {\n var url = js_urls[i];\n if (skip.indexOf(url) >= 0) { on_load(); continue; }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n\tif (!js_urls.length) {\n on_load()\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.2.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.2.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.2.3.min.js\", \"https://unpkg.com/@holoviz/panel@^0.10.2/dist/panel.min.js\"];\n var css_urls = [\"https://unpkg.com/@holoviz/panel@0.10.2/dist/css/alerts.css\", \"https://unpkg.com/@holoviz/panel@0.10.2/dist/css/card.css\", \"https://unpkg.com/@holoviz/panel@0.10.2/dist/css/widgets.css\", \"https://unpkg.com/@holoviz/panel@0.10.2/dist/css/markdown.css\", \"https://unpkg.com/@holoviz/panel@0.10.2/dist/css/json.css\", \"https://unpkg.com/@holoviz/panel@0.10.2/dist/css/dataframe.css\"];\n\n var inline_js = [\n function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\n function(Bokeh) {} // ensure no trailing comma for IE\n ];\n\n function run_inline_js() {\n if ((root.Bokeh !== undefined) || (force === true)) {\n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n }\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));" }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "if ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n", " window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n", "}\n", "\n", "\n", " function JupyterCommManager() {\n", " }\n", "\n", " JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n", " if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", " comm_manager.register_target(comm_id, function(comm) {\n", " comm.on_msg(msg_handler);\n", " });\n", " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", " window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n", " comm.onMsg = msg_handler;\n", " });\n", " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", " google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n", " var messages = comm.messages[Symbol.asyncIterator]();\n", " function processIteratorResult(result) {\n", " var message = result.value;\n", " console.log(message)\n", " var content = {data: message.data, comm_id};\n", " var buffers = []\n", " for (var buffer of message.buffers || []) {\n", " buffers.push(new DataView(buffer))\n", " }\n", " var metadata = message.metadata || {};\n", " var msg = {content, buffers, metadata}\n", " msg_handler(msg);\n", " return messages.next().then(processIteratorResult);\n", " }\n", " return messages.next().then(processIteratorResult);\n", " })\n", " }\n", " }\n", "\n", " JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n", " if (comm_id in window.PyViz.comms) {\n", " return window.PyViz.comms[comm_id];\n", " } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n", " var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n", " var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n", " if (msg_handler) {\n", " comm.on_msg(msg_handler);\n", " }\n", " } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n", " var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n", " comm.open();\n", " if (msg_handler) {\n", " comm.onMsg = msg_handler;\n", " }\n", " } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n", " var comm_promise = google.colab.kernel.comms.open(comm_id)\n", " comm_promise.then((comm) => {\n", " window.PyViz.comms[comm_id] = comm;\n", " if (msg_handler) {\n", " var messages = comm.messages[Symbol.asyncIterator]();\n", " function processIteratorResult(result) {\n", " var message = result.value;\n", " var content = {data: message.data};\n", " var metadata = message.metadata || {comm_id};\n", " var msg = {content, metadata}\n", " msg_handler(msg);\n", " return messages.next().then(processIteratorResult);\n", " }\n", " return messages.next().then(processIteratorResult);\n", " }\n", " }) \n", " var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n", " return comm_promise.then((comm) => {\n", " comm.send(data, metadata, buffers, disposeOnDone);\n", " });\n", " };\n", " var comm = {\n", " send: sendClosure\n", " };\n", " }\n", " window.PyViz.comms[comm_id] = comm;\n", " return comm;\n", " }\n", " window.PyViz.comm_manager = new JupyterCommManager();\n", " \n", "\n", "\n", "var JS_MIME_TYPE = 'application/javascript';\n", "var HTML_MIME_TYPE = 'text/html';\n", "var EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\n", "var CLASS_NAME = 'output';\n", "\n", "/**\n", " * Render data to the DOM node\n", " */\n", "function render(props, node) {\n", " var div = document.createElement(\"div\");\n", " var script = document.createElement(\"script\");\n", " node.appendChild(div);\n", " node.appendChild(script);\n", "}\n", "\n", "/**\n", " * Handle when a new output is added\n", " */\n", "function handle_add_output(event, handle) {\n", " var output_area = handle.output_area;\n", " var output = handle.output;\n", " if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n", " return\n", " }\n", " var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n", " var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n", " if (id !== undefined) {\n", " var nchildren = toinsert.length;\n", " var html_node = toinsert[nchildren-1].children[0];\n", " html_node.innerHTML = output.data[HTML_MIME_TYPE];\n", " var scripts = [];\n", " var nodelist = html_node.querySelectorAll(\"script\");\n", " for (var i in nodelist) {\n", " if (nodelist.hasOwnProperty(i)) {\n", " scripts.push(nodelist[i])\n", " }\n", " }\n", "\n", " scripts.forEach( function (oldScript) {\n", " var newScript = document.createElement(\"script\");\n", " var attrs = [];\n", " var nodemap = oldScript.attributes;\n", " for (var j in nodemap) {\n", " if (nodemap.hasOwnProperty(j)) {\n", " attrs.push(nodemap[j])\n", " }\n", " }\n", " attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n", " newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n", " oldScript.parentNode.replaceChild(newScript, oldScript);\n", " });\n", " if (JS_MIME_TYPE in output.data) {\n", " toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n", " }\n", " output_area._hv_plot_id = id;\n", " if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n", " window.PyViz.plot_index[id] = Bokeh.index[id];\n", " } else {\n", " window.PyViz.plot_index[id] = null;\n", " }\n", " } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n", " var bk_div = document.createElement(\"div\");\n", " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n", " var script_attrs = bk_div.children[0].attributes;\n", " for (var i = 0; i < script_attrs.length; i++) {\n", " toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n", " }\n", " // store reference to server id on output_area\n", " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n", " }\n", "}\n", "\n", "/**\n", " * Handle when an output is cleared or removed\n", " */\n", "function handle_clear_output(event, handle) {\n", " var id = handle.cell.output_area._hv_plot_id;\n", " var server_id = handle.cell.output_area._bokeh_server_id;\n", " if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n", " var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n", " if (server_id !== null) {\n", " comm.send({event_type: 'server_delete', 'id': server_id});\n", " return;\n", " } else if (comm !== null) {\n", " comm.send({event_type: 'delete', 'id': id});\n", " }\n", " delete PyViz.plot_index[id];\n", " if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n", " var doc = window.Bokeh.index[id].model.document\n", " doc.clear();\n", " const i = window.Bokeh.documents.indexOf(doc);\n", " if (i > -1) {\n", " window.Bokeh.documents.splice(i, 1);\n", " }\n", " }\n", "}\n", "\n", "/**\n", " * Handle kernel restart event\n", " */\n", "function handle_kernel_cleanup(event, handle) {\n", " delete PyViz.comms[\"hv-extension-comm\"];\n", " window.PyViz.plot_index = {}\n", "}\n", "\n", "/**\n", " * Handle update_display_data messages\n", " */\n", "function handle_update_output(event, handle) {\n", " handle_clear_output(event, {cell: {output_area: handle.output_area}})\n", " handle_add_output(event, handle)\n", "}\n", "\n", "function register_renderer(events, OutputArea) {\n", " function append_mime(data, metadata, element) {\n", " // create a DOM node to render to\n", " var toinsert = this.create_output_subarea(\n", " metadata,\n", " CLASS_NAME,\n", " EXEC_MIME_TYPE\n", " );\n", " this.keyboard_manager.register_events(toinsert);\n", " // Render to node\n", " var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n", " render(props, toinsert[0]);\n", " element.append(toinsert);\n", " return toinsert\n", " }\n", "\n", " events.on('output_added.OutputArea', handle_add_output);\n", " events.on('output_updated.OutputArea', handle_update_output);\n", " events.on('clear_output.CodeCell', handle_clear_output);\n", " events.on('delete.Cell', handle_clear_output);\n", " events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n", "\n", " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n", " safe: true,\n", " index: 0\n", " });\n", "}\n", "\n", "if (window.Jupyter !== undefined) {\n", " try {\n", " var events = require('base/js/events');\n", " var OutputArea = require('notebook/js/outputarea').OutputArea;\n", " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n", " register_renderer(events, OutputArea);\n", " }\n", " } catch(err) {\n", " }\n", "}\n" ], "application/vnd.holoviews_load.v0+json": "\nif ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n}\n\n\n function JupyterCommManager() {\n }\n\n JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n comm_manager.register_target(comm_id, function(comm) {\n comm.on_msg(msg_handler);\n });\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n comm.onMsg = msg_handler;\n });\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n console.log(message)\n var content = {data: message.data, comm_id};\n var buffers = []\n for (var buffer of message.buffers || []) {\n buffers.push(new DataView(buffer))\n }\n var metadata = message.metadata || {};\n var msg = {content, buffers, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n })\n }\n }\n\n JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n if (comm_id in window.PyViz.comms) {\n return window.PyViz.comms[comm_id];\n } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n if (msg_handler) {\n comm.on_msg(msg_handler);\n }\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n comm.open();\n if (msg_handler) {\n comm.onMsg = msg_handler;\n }\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n var comm_promise = google.colab.kernel.comms.open(comm_id)\n comm_promise.then((comm) => {\n window.PyViz.comms[comm_id] = comm;\n if (msg_handler) {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data};\n var metadata = message.metadata || {comm_id};\n var msg = {content, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n }\n }) \n var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n return comm_promise.then((comm) => {\n comm.send(data, metadata, buffers, disposeOnDone);\n });\n };\n var comm = {\n send: sendClosure\n };\n }\n window.PyViz.comms[comm_id] = comm;\n return comm;\n }\n window.PyViz.comm_manager = new JupyterCommManager();\n \n\n\nvar JS_MIME_TYPE = 'application/javascript';\nvar HTML_MIME_TYPE = 'text/html';\nvar EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\nvar CLASS_NAME = 'output';\n\n/**\n * Render data to the DOM node\n */\nfunction render(props, node) {\n var div = document.createElement(\"div\");\n var script = document.createElement(\"script\");\n node.appendChild(div);\n node.appendChild(script);\n}\n\n/**\n * Handle when a new output is added\n */\nfunction handle_add_output(event, handle) {\n var output_area = handle.output_area;\n var output = handle.output;\n if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n return\n }\n var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n if (id !== undefined) {\n var nchildren = toinsert.length;\n var html_node = toinsert[nchildren-1].children[0];\n html_node.innerHTML = output.data[HTML_MIME_TYPE];\n var scripts = [];\n var nodelist = html_node.querySelectorAll(\"script\");\n for (var i in nodelist) {\n if (nodelist.hasOwnProperty(i)) {\n scripts.push(nodelist[i])\n }\n }\n\n scripts.forEach( function (oldScript) {\n var newScript = document.createElement(\"script\");\n var attrs = [];\n var nodemap = oldScript.attributes;\n for (var j in nodemap) {\n if (nodemap.hasOwnProperty(j)) {\n attrs.push(nodemap[j])\n }\n }\n attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n oldScript.parentNode.replaceChild(newScript, oldScript);\n });\n if (JS_MIME_TYPE in output.data) {\n toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n }\n output_area._hv_plot_id = id;\n if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n window.PyViz.plot_index[id] = Bokeh.index[id];\n } else {\n window.PyViz.plot_index[id] = null;\n }\n } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n var bk_div = document.createElement(\"div\");\n bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n var script_attrs = bk_div.children[0].attributes;\n for (var i = 0; i < script_attrs.length; i++) {\n toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n }\n // store reference to server id on output_area\n output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n }\n}\n\n/**\n * Handle when an output is cleared or removed\n */\nfunction handle_clear_output(event, handle) {\n var id = handle.cell.output_area._hv_plot_id;\n var server_id = handle.cell.output_area._bokeh_server_id;\n if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n if (server_id !== null) {\n comm.send({event_type: 'server_delete', 'id': server_id});\n return;\n } else if (comm !== null) {\n comm.send({event_type: 'delete', 'id': id});\n }\n delete PyViz.plot_index[id];\n if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n var doc = window.Bokeh.index[id].model.document\n doc.clear();\n const i = window.Bokeh.documents.indexOf(doc);\n if (i > -1) {\n window.Bokeh.documents.splice(i, 1);\n }\n }\n}\n\n/**\n * Handle kernel restart event\n */\nfunction handle_kernel_cleanup(event, handle) {\n delete PyViz.comms[\"hv-extension-comm\"];\n window.PyViz.plot_index = {}\n}\n\n/**\n * Handle update_display_data messages\n */\nfunction handle_update_output(event, handle) {\n handle_clear_output(event, {cell: {output_area: handle.output_area}})\n handle_add_output(event, handle)\n}\n\nfunction register_renderer(events, OutputArea) {\n function append_mime(data, metadata, element) {\n // create a DOM node to render to\n var toinsert = this.create_output_subarea(\n metadata,\n CLASS_NAME,\n EXEC_MIME_TYPE\n );\n this.keyboard_manager.register_events(toinsert);\n // Render to node\n var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n render(props, toinsert[0]);\n element.append(toinsert);\n return toinsert\n }\n\n events.on('output_added.OutputArea', handle_add_output);\n events.on('output_updated.OutputArea', handle_update_output);\n events.on('clear_output.CodeCell', handle_clear_output);\n events.on('delete.Cell', handle_clear_output);\n events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n\n OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n safe: true,\n index: 0\n });\n}\n\nif (window.Jupyter !== undefined) {\n try {\n var events = require('base/js/events');\n var OutputArea = require('notebook/js/outputarea').OutputArea;\n if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n register_renderer(events, OutputArea);\n }\n } catch(err) {\n }\n}\n" }, "metadata": {}, "output_type": "display_data" }, { "data": { "text/html": [ "\n", "
\n", " \n", " Loading BokehJS ...\n", "
" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "\n", "(function(root) {\n", " function now() {\n", " return new Date();\n", " }\n", "\n", " var force = true;\n", "\n", " if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n", " root._bokeh_onload_callbacks = [];\n", " root._bokeh_is_loading = undefined;\n", " }\n", "\n", " var JS_MIME_TYPE = 'application/javascript';\n", " var HTML_MIME_TYPE = 'text/html';\n", " var EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n", " var CLASS_NAME = 'output_bokeh rendered_html';\n", "\n", " /**\n", " * Render data to the DOM node\n", " */\n", " function render(props, node) {\n", " var script = document.createElement(\"script\");\n", " node.appendChild(script);\n", " }\n", "\n", " /**\n", " * Handle when an output is cleared or removed\n", " */\n", " function handleClearOutput(event, handle) {\n", " var cell = handle.cell;\n", "\n", " var id = cell.output_area._bokeh_element_id;\n", " var server_id = cell.output_area._bokeh_server_id;\n", " // Clean up Bokeh references\n", " if (id != null && id in Bokeh.index) {\n", " Bokeh.index[id].model.document.clear();\n", " delete Bokeh.index[id];\n", " }\n", "\n", " if (server_id !== undefined) {\n", " // Clean up Bokeh references\n", " var cmd = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n", " cell.notebook.kernel.execute(cmd, {\n", " iopub: {\n", " output: function(msg) {\n", " var id = msg.content.text.trim();\n", " if (id in Bokeh.index) {\n", " Bokeh.index[id].model.document.clear();\n", " delete Bokeh.index[id];\n", " }\n", " }\n", " }\n", " });\n", " // Destroy server and session\n", " var cmd = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n", " cell.notebook.kernel.execute(cmd);\n", " }\n", " }\n", "\n", " /**\n", " * Handle when a new output is added\n", " */\n", " function handleAddOutput(event, handle) {\n", " var output_area = handle.output_area;\n", " var output = handle.output;\n", "\n", " // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n", " if ((output.output_type != \"display_data\") || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n", " return\n", " }\n", "\n", " var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n", "\n", " if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n", " toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n", " // store reference to embed id on output_area\n", " output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n", " }\n", " if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n", " var bk_div = document.createElement(\"div\");\n", " bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n", " var script_attrs = bk_div.children[0].attributes;\n", " for (var i = 0; i < script_attrs.length; i++) {\n", " toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n", " toinsert[toinsert.length - 1].firstChild.textContent = bk_div.children[0].textContent\n", " }\n", " // store reference to server id on output_area\n", " output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n", " }\n", " }\n", "\n", " function register_renderer(events, OutputArea) {\n", "\n", " function append_mime(data, metadata, element) {\n", " // create a DOM node to render to\n", " var toinsert = this.create_output_subarea(\n", " metadata,\n", " CLASS_NAME,\n", " EXEC_MIME_TYPE\n", " );\n", " this.keyboard_manager.register_events(toinsert);\n", " // Render to node\n", " var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n", " render(props, toinsert[toinsert.length - 1]);\n", " element.append(toinsert);\n", " return toinsert\n", " }\n", "\n", " /* Handle when an output is cleared or removed */\n", " events.on('clear_output.CodeCell', handleClearOutput);\n", " events.on('delete.Cell', handleClearOutput);\n", "\n", " /* Handle when a new output is added */\n", " events.on('output_added.OutputArea', handleAddOutput);\n", "\n", " /**\n", " * Register the mime type and append_mime function with output_area\n", " */\n", " OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n", " /* Is output safe? */\n", " safe: true,\n", " /* Index of renderer in `output_area.display_order` */\n", " index: 0\n", " });\n", " }\n", "\n", " // register the mime type if in Jupyter Notebook environment and previously unregistered\n", " if (root.Jupyter !== undefined) {\n", " var events = require('base/js/events');\n", " var OutputArea = require('notebook/js/outputarea').OutputArea;\n", "\n", " if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n", " register_renderer(events, OutputArea);\n", " }\n", " }\n", "\n", " \n", " if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n", " root._bokeh_timeout = Date.now() + 5000;\n", " root._bokeh_failed_load = false;\n", " }\n", "\n", " var NB_LOAD_WARNING = {'data': {'text/html':\n", " \"
\\n\"+\n", " \"

\\n\"+\n", " \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n", " \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n", " \"

\\n\"+\n", " \"\\n\"+\n", " \"\\n\"+\n", " \"from bokeh.resources import INLINE\\n\"+\n", " \"output_notebook(resources=INLINE)\\n\"+\n", " \"\\n\"+\n", " \"
\"}};\n", "\n", " function display_loaded() {\n", " var el = document.getElementById(\"1001\");\n", " if (el != null) {\n", " el.textContent = \"BokehJS is loading...\";\n", " }\n", " if (root.Bokeh !== undefined) {\n", " if (el != null) {\n", " el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n", " }\n", " } else if (Date.now() < root._bokeh_timeout) {\n", " setTimeout(display_loaded, 100)\n", " }\n", " }\n", "\n", "\n", " function run_callbacks() {\n", " try {\n", " root._bokeh_onload_callbacks.forEach(function(callback) {\n", " if (callback != null)\n", " callback();\n", " });\n", " } finally {\n", " delete root._bokeh_onload_callbacks\n", " }\n", " console.debug(\"Bokeh: all callbacks have finished\");\n", " }\n", "\n", " function load_libs(css_urls, js_urls, callback) {\n", " if (css_urls == null) css_urls = [];\n", " if (js_urls == null) js_urls = [];\n", "\n", " root._bokeh_onload_callbacks.push(callback);\n", " if (root._bokeh_is_loading > 0) {\n", " console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n", " return null;\n", " }\n", " if (js_urls == null || js_urls.length === 0) {\n", " run_callbacks();\n", " return null;\n", " }\n", " console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n", " root._bokeh_is_loading = css_urls.length + js_urls.length;\n", "\n", " function on_load() {\n", " root._bokeh_is_loading--;\n", " if (root._bokeh_is_loading === 0) {\n", " console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n", " run_callbacks()\n", " }\n", " }\n", "\n", " function on_error() {\n", " console.error(\"failed to load \" + url);\n", " }\n", "\n", " for (var i = 0; i < css_urls.length; i++) {\n", " var url = css_urls[i];\n", " const element = document.createElement(\"link\");\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.rel = \"stylesheet\";\n", " element.type = \"text/css\";\n", " element.href = url;\n", " console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n", " document.body.appendChild(element);\n", " }\n", "\n", " const hashes = {\"https://cdn.bokeh.org/bokeh/release/bokeh-2.2.3.min.js\": \"T2yuo9Oe71Cz/I4X9Ac5+gpEa5a8PpJCDlqKYO0CfAuEszu1JrXLl8YugMqYe3sM\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.2.3.min.js\": \"98GDGJ0kOMCUMUePhksaQ/GYgB3+NH9h996V88sh3aOiUNX3N+fLXAtry6xctSZ6\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.2.3.min.js\": \"89bArO+nlbP3sgakeHjCo1JYxYR5wufVgA3IbUvDY+K7w4zyxJqssu7wVnfeKCq8\"};\n", "\n", " for (var i = 0; i < js_urls.length; i++) {\n", " var url = js_urls[i];\n", " var element = document.createElement('script');\n", " element.onload = on_load;\n", " element.onerror = on_error;\n", " element.async = false;\n", " element.src = url;\n", " if (url in hashes) {\n", " element.crossOrigin = \"anonymous\";\n", " element.integrity = \"sha384-\" + hashes[url];\n", " }\n", " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " document.head.appendChild(element);\n", " }\n", " };\n", "\n", " function inject_raw_css(css) {\n", " const element = document.createElement(\"style\");\n", " element.appendChild(document.createTextNode(css));\n", " document.body.appendChild(element);\n", " }\n", "\n", " \n", " var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.2.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.2.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.2.3.min.js\", \"https://unpkg.com/@holoviz/panel@^0.10.2/dist/panel.min.js\"];\n", " var css_urls = [\"/static/extensions/panel/css/alerts.css\", \"/static/extensions/panel/css/card.css\", \"/static/extensions/panel/css/widgets.css\", \"/static/extensions/panel/css/markdown.css\", \"/static/extensions/panel/css/json.css\", \"/static/extensions/panel/css/dataframe.css\"];\n", " \n", "\n", " var inline_js = [\n", " function(Bokeh) {\n", " Bokeh.set_log_level(\"info\");\n", " },\n", " function(Bokeh) {\n", " \n", " \n", " }\n", " ];\n", "\n", " function run_inline_js() {\n", " \n", " if (root.Bokeh !== undefined || force === true) {\n", " \n", " for (var i = 0; i < inline_js.length; i++) {\n", " inline_js[i].call(root, root.Bokeh);\n", " }\n", " if (force === true) {\n", " display_loaded();\n", " }} else if (Date.now() < root._bokeh_timeout) {\n", " setTimeout(run_inline_js, 100);\n", " } else if (!root._bokeh_failed_load) {\n", " console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n", " root._bokeh_failed_load = true;\n", " } else if (force !== true) {\n", " var cell = $(document.getElementById(\"1001\")).parents('.cell').data().cell;\n", " cell.output_area.append_execute_result(NB_LOAD_WARNING)\n", " }\n", "\n", " }\n", "\n", " if (root._bokeh_is_loading === 0) {\n", " console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n", " run_inline_js();\n", " } else {\n", " load_libs(css_urls, js_urls, function() {\n", " console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n", " run_inline_js();\n", " });\n", " }\n", "}(window));" ], "application/vnd.bokehjs_load.v0+json": "\n(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n\n if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n root._bokeh_onload_callbacks = [];\n root._bokeh_is_loading = undefined;\n }\n\n \n\n \n if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n var NB_LOAD_WARNING = {'data': {'text/html':\n \"
\\n\"+\n \"

\\n\"+\n \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n \"

\\n\"+\n \"\\n\"+\n \"\\n\"+\n \"from bokeh.resources import INLINE\\n\"+\n \"output_notebook(resources=INLINE)\\n\"+\n \"\\n\"+\n \"
\"}};\n\n function display_loaded() {\n var el = document.getElementById(\"1001\");\n if (el != null) {\n el.textContent = \"BokehJS is loading...\";\n }\n if (root.Bokeh !== undefined) {\n if (el != null) {\n el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n }\n } else if (Date.now() < root._bokeh_timeout) {\n setTimeout(display_loaded, 100)\n }\n }\n\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n\n root._bokeh_onload_callbacks.push(callback);\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls == null || js_urls.length === 0) {\n run_callbacks();\n return null;\n }\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n root._bokeh_is_loading = css_urls.length + js_urls.length;\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n\n function on_error() {\n console.error(\"failed to load \" + url);\n }\n\n for (var i = 0; i < css_urls.length; i++) {\n var url = css_urls[i];\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n }\n\n const hashes = {\"https://cdn.bokeh.org/bokeh/release/bokeh-2.2.3.min.js\": \"T2yuo9Oe71Cz/I4X9Ac5+gpEa5a8PpJCDlqKYO0CfAuEszu1JrXLl8YugMqYe3sM\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.2.3.min.js\": \"98GDGJ0kOMCUMUePhksaQ/GYgB3+NH9h996V88sh3aOiUNX3N+fLXAtry6xctSZ6\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.2.3.min.js\": \"89bArO+nlbP3sgakeHjCo1JYxYR5wufVgA3IbUvDY+K7w4zyxJqssu7wVnfeKCq8\"};\n\n for (var i = 0; i < js_urls.length; i++) {\n var url = js_urls[i];\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n if (url in hashes) {\n element.crossOrigin = \"anonymous\";\n element.integrity = \"sha384-\" + hashes[url];\n }\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n \n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-2.2.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-2.2.3.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-2.2.3.min.js\", \"https://unpkg.com/@holoviz/panel@^0.10.2/dist/panel.min.js\"];\n var css_urls = [\"/static/extensions/panel/css/alerts.css\", \"/static/extensions/panel/css/card.css\", \"/static/extensions/panel/css/widgets.css\", \"/static/extensions/panel/css/markdown.css\", \"/static/extensions/panel/css/json.css\", \"/static/extensions/panel/css/dataframe.css\"];\n \n\n var inline_js = [\n function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\n function(Bokeh) {\n \n \n }\n ];\n\n function run_inline_js() {\n \n if (root.Bokeh !== undefined || force === true) {\n \n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }\n if (force === true) {\n display_loaded();\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n } else if (force !== true) {\n var cell = $(document.getElementById(\"1001\")).parents('.cell').data().cell;\n cell.output_area.append_execute_result(NB_LOAD_WARNING)\n }\n\n }\n\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n run_inline_js();\n } else {\n load_libs(css_urls, js_urls, function() {\n console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n run_inline_js();\n });\n }\n}(window));" }, "metadata": {}, "output_type": "display_data" } ], "source": [ "import numpy as np\n", "import pandas as pd\n", "import scipy.integrate\n", "\n", "import bokeh.io\n", "import bokeh.plotting\n", "\n", "import panel as pn\n", "pn.extension()\n", "\n", "bokeh.io.output_notebook()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "In this document, I present a numerical solution for the dynamical equations describing the β-catenin destruction cycle, as described in the [Lee, et al. paper](https://doi.org/10.1371/journal.pbio.0000010). As a reminder, the destruction cycle is part of the broader Wnt signaling pathway, as shown in this figure from the Lee, et al. paper.\n", "\n", "
\n", "\n", "\n", "\n", "
\n", "\n", "\n", "To aid in interpreting the dynamical equations, the chemical species and their corresponding numerical label that are involved in the cycle are:\n", "\n", "|number | species |\n", "|--:--|--:--|\n", "|3 | APC*/Axin*/GSK-3|\n", "|8 | β-catenin/APC*/Axin*/GSK-3 |\n", "|9 | β-catenin*/APC*/Axin*/GSK-3 |\n", "|10 | β-catenin* |\n", "|11 | β-catenin |\n", "\n", "The mass action equations describing the dynamics are\n", "\n", "\\begin{align}\n", "&\\frac{\\mathrm{d}c_3}{\\mathrm{d}t} = -k_8 c_3 c_{11} + k_{\\text{-}8}c_8 + k_{10}c_9, \\label{eq:41} \\\\\n", "&\\frac{\\mathrm{d}c_8}{\\mathrm{d}t} = k_8 c_3 c_{11} - k_{\\text{-}8}c_8 - k_9c_8, \\label{eq:42}\\\\\n", "&\\frac{\\mathrm{d}c_9}{\\mathrm{d}t} = k_9c_8 - k_{10} c_9,\\label{eq:43} \\\\\n", "&\\frac{\\mathrm{d}c_{10}}{\\mathrm{d}t} = k_{10} c_9 - k_{11}c_{10}, \\label{eq:44}\\\\\n", "&\\frac{\\mathrm{d}c_{11}}{\\mathrm{d}t} = k_{12} - k_8 c_3 c_{11} + k_{\\text{-}8}c_8.\n", "\\end{align}\n", "\n", "Most of the parameters are measured and reported, at least approximately, in the Lee, et al. paper. The parameters $k_8$, $k_{\\text{-}8}$ and $k_{12}$ are unknown. However, $K_\\mathrm{d} = k_{\\text{-}8}/k_8$ is known, so we only have two parameters to set. We will develop an interactive plotting app to allow us to investigate the dynamics of the respective species as the two parameters $k_8$ and $k_{-8}$ are varied. In doing so, we will see how the `scipy.integrate.solve_ivp()` function works to numerically solve systems of ordinary differential equations." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Numerical integration using SciPy\n", "\n", "There are three main APIs for solving real-valued initial value problems in the SciPy library. They are [`scipy.integrate.solve_ivp()`](https://docs.scipy.org/doc/scipy/reference/generated/scipy.integrate.solve_ivp.html#scipy.integrate.solve_ivp), [`ode()`](https://scipy.github.io/devdocs/generated/scipy.integrate.ode.html#scipy.integrate.ode), and [`odeint()`](https://scipy.github.io/devdocs/generated/scipy.integrate.odeint.html#scipy.integrate.odeint). According to the SciPy developers, `scipy.integrate.solve_ivp()` is the preferred method, with the others labeled as having an \"old\" API. The `solve_ivp()` function has the flexibility of allowing choice of multiple numerical algorithms for solving ODEs. However, for the kinds of problems we encounter in this class, I find that the generic LSODA algorithm developed by Linda Petzold and Alan Hindmarsh that handles both stiff and non-stiff problems with variable time stepping is the best option. This is the only solver offered in the `odeint()` function. If we compare the two solvers, `solve_ivp()` and `odeint()`, the former has a large overhead, which can lead to performance issues for small problems (for large problems, this is not a big deal). Since most of our problems are small, we will use `odeint()`. It has much better performance, and though its API is different, it is still intuitive.\n", "\n", "The basic call signature for `scipy.integrate.odeint()` is\n", "\n", " scipy.integrate.odeint(func, y0, t, args=())\n", " \n", "There are many other keyword arguments to set algorithmic parameters, but we will generally not need them (and you can read about them in [the docs](https://scipy.github.io/devdocs/generated/scipy.integrate.odeint.html#scipy.integrate.odeint).\n", "\n", "Importantly, `fun` is a vector-valued function with call signature `f(y, t, *args)` that specifies the right hand side of the system of ODEs to be solved. `t` is a scalar time point and `y` is a one-dimensional array (though multidimensional arrays are possible; see the SciPy docs). `y0` is an array with the initial conditions.\n", "\n", "Let's put together some code to solve the ODEs describing the β-catenin destruction cycle!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Numerical solution of the β-catenin destruction cycle dynamics\n", "\n", "First, the preliminaries. We'll sed up parameters and names of the respective species." ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "# Key for names\n", "names = ['Axin complex', 'Axin-βcat', 'Axin-βcat*', 'βcat*', 'βcat']\n", "\n", "# Define known parameters\n", "c_A = 50 # nM (given by fixed GSK-3 concentration)\n", "k9 = 206 # 1/min\n", "k10 = 206 # 1/min\n", "k11 = 0.417 # 1/min\n", "Kd8 = 120 # nM\n", "\n", "# Unknown parameters\n", "km8 = 1 # 1/min\n", "k12 = 100 # nM/min\n", "\n", "# k8 determined form Kd8 and km8\n", "k8 = km8 / Kd8 # 1/nM-min\n", "\n", "# Set up params for ODE\n", "params = (k8, km8, k9, k10, k11, k12)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "For our initial conditions, we will assume that we have no $\\beta$-catenin and that we have a fixed amount of APC/Axin/GKC-3." ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "# Initial conditions\n", "c0 = np.array([c_A, 0, 0, 0, 0])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now we define the right hand side of the ODEs. We do need to pass in parameters. We list the parameters after the required arguments, `t` and `y` (for the present case, `y` is `c`). The function needs to return an array of time derivatives, in the present case five of them." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "def dcdt(c, t, k8, km8, k9, k10, k11, k12):\n", " \"\"\"\n", " Time derivative of concentrations.\n", " c = (c3, c8, c9, c10, c11)\n", " \"\"\"\n", " # Unpack concentrations\n", " c3, c8, c9, c10, c11 = c\n", " \n", " # Build derivatives\n", " deriv = np.empty(5)\n", " deriv[0] = -k8*c3*c11 + km8*c8 + k10*c9\n", " deriv[1] = k8*c3*c11 - (km8 + k9)*c8\n", " deriv[2] = k9*c8 - k10*c9\n", " deriv[3] = k10*c9 - k11*c10\n", " deriv[4] = -k8*c3*c11 + km8*c8 + k12\n", " \n", " return deriv" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, we just have to specify what time points we want." ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "# Set up time points\n", "t = np.linspace(0, 20, 300)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We are finally ready to run the solver." ] }, { "cell_type": "code", "execution_count": 6, "metadata": {}, "outputs": [], "source": [ "c = scipy.integrate.odeint(dcdt, c0, t, args=params)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The result is a Numpy array where each column corresponds to one of the variables we are solving for in the ODE, in this case the concentrations. We can use these to plot the solution." ] }, { "cell_type": "code", "execution_count": 7, "metadata": {}, "outputs": [ { "data": { "text/html": [ "\n", "\n", "\n", "\n", "\n", "\n", "
\n" ] }, "metadata": {}, "output_type": "display_data" }, { "data": { "application/javascript": [ "(function(root) {\n", " function embed_document(root) {\n", " \n", " var docs_json = {\"6b5dedea-cb7b-4196-9675-2efbdf8fb910\":{\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"1011\"}],\"center\":[{\"id\":\"1014\"},{\"id\":\"1018\"},{\"id\":\"1047\"}],\"left\":[{\"id\":\"1015\"}],\"plot_height\":350,\"plot_width\":450,\"renderers\":[{\"id\":\"1036\"},{\"id\":\"1052\"},{\"id\":\"1069\"},{\"id\":\"1088\"},{\"id\":\"1109\"}],\"title\":{\"id\":\"1039\"},\"toolbar\":{\"id\":\"1026\"},\"x_range\":{\"id\":\"1003\"},\"x_scale\":{\"id\":\"1007\"},\"y_range\":{\"id\":\"1005\"},\"y_scale\":{\"id\":\"1009\"}},\"id\":\"1002\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{},\"id\":\"1024\",\"type\":\"HelpTool\"},{\"attributes\":{},\"id\":\"1019\",\"type\":\"PanTool\"},{\"attributes\":{},\"id\":\"1103\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"overlay\":{\"id\":\"1025\"}},\"id\":\"1021\",\"type\":\"BoxZoomTool\"},{\"attributes\":{\"line_color\":\"#2ca02c\",\"line_width\":3,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1067\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"1022\",\"type\":\"SaveTool\"},{\"attributes\":{},\"id\":\"1023\",\"type\":\"ResetTool\"},{\"attributes\":{\"source\":{\"id\":\"1066\"}},\"id\":\"1070\",\"type\":\"CDSView\"},{\"attributes\":{\"line_alpha\":0.1,\"line_color\":\"#2ca02c\",\"line_width\":3,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1068\",\"type\":\"Line\"},{\"attributes\":{\"line_color\":\"#d62728\",\"line_width\":3,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1086\",\"type\":\"Line\"},{\"attributes\":{\"items\":[{\"id\":\"1048\"},{\"id\":\"1065\"},{\"id\":\"1084\"},{\"id\":\"1105\"},{\"id\":\"1128\"}],\"location\":\"center_right\"},\"id\":\"1047\",\"type\":\"Legend\"},{\"attributes\":{\"data_source\":{\"id\":\"1106\"},\"glyph\":{\"id\":\"1107\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1108\"},\"selection_glyph\":null,\"view\":{\"id\":\"1110\"}},\"id\":\"1109\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"data_source\":{\"id\":\"1049\"},\"glyph\":{\"id\":\"1050\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1051\"},\"selection_glyph\":null,\"view\":{\"id\":\"1053\"}},\"id\":\"1052\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"label\":{\"value\":\"Axin-\\u03b2cat*\"},\"renderers\":[{\"id\":\"1069\"}]},\"id\":\"1084\",\"type\":\"LegendItem\"},{\"attributes\":{\"text\":\"\"},\"id\":\"1039\",\"type\":\"Title\"},{\"attributes\":{},\"id\":\"1064\",\"type\":\"Selection\"},{\"attributes\":{\"line_color\":\"#ff7f0e\",\"line_width\":3,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1050\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"1083\",\"type\":\"Selection\"},{\"attributes\":{\"label\":{\"value\":\"Axin complex\"},\"renderers\":[{\"id\":\"1036\"}]},\"id\":\"1048\",\"type\":\"LegendItem\"},{\"attributes\":{\"data\":{\"x\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[300]},\"y\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[300]}},\"selected\":{\"id\":\"1127\"},\"selection_policy\":{\"id\":\"1126\"}},\"id\":\"1106\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"line_alpha\":0.1,\"line_color\":\"#1f77b4\",\"line_width\":3,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1035\",\"type\":\"Line\"},{\"attributes\":{\"source\":{\"id\":\"1106\"}},\"id\":\"1110\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"1082\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"line_color\":\"#1f77b4\",\"line_width\":3,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1034\",\"type\":\"Line\"},{\"attributes\":{\"data\":{\"x\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[300]},\"y\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[300]}},\"selected\":{\"id\":\"1064\"},\"selection_policy\":{\"id\":\"1063\"}},\"id\":\"1049\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"line_alpha\":0.1,\"line_color\":\"#9467bd\",\"line_width\":3,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1108\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"1040\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"source\":{\"id\":\"1033\"}},\"id\":\"1037\",\"type\":\"CDSView\"},{\"attributes\":{\"source\":{\"id\":\"1049\"}},\"id\":\"1053\",\"type\":\"CDSView\"},{\"attributes\":{\"line_alpha\":0.1,\"line_color\":\"#ff7f0e\",\"line_width\":3,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1051\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"1127\",\"type\":\"Selection\"},{\"attributes\":{\"label\":{\"value\":\"\\u03b2cat\"},\"renderers\":[{\"id\":\"1109\"}]},\"id\":\"1128\",\"type\":\"LegendItem\"},{\"attributes\":{},\"id\":\"1042\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"data\":{\"x\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[300]},\"y\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[300]}},\"selected\":{\"id\":\"1083\"},\"selection_policy\":{\"id\":\"1082\"}},\"id\":\"1066\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"label\":{\"value\":\"Axin-\\u03b2cat\"},\"renderers\":[{\"id\":\"1052\"}]},\"id\":\"1065\",\"type\":\"LegendItem\"},{\"attributes\":{\"active_drag\":\"auto\",\"active_inspect\":\"auto\",\"active_multi\":null,\"active_scroll\":\"auto\",\"active_tap\":\"auto\",\"tools\":[{\"id\":\"1019\"},{\"id\":\"1020\"},{\"id\":\"1021\"},{\"id\":\"1022\"},{\"id\":\"1023\"},{\"id\":\"1024\"}]},\"id\":\"1026\",\"type\":\"Toolbar\"},{\"attributes\":{\"bottom_units\":\"screen\",\"fill_alpha\":0.5,\"fill_color\":\"lightgrey\",\"left_units\":\"screen\",\"level\":\"overlay\",\"line_alpha\":1.0,\"line_color\":\"black\",\"line_dash\":[4,4],\"line_width\":2,\"right_units\":\"screen\",\"top_units\":\"screen\"},\"id\":\"1025\",\"type\":\"BoxAnnotation\"},{\"attributes\":{},\"id\":\"1020\",\"type\":\"WheelZoomTool\"},{\"attributes\":{},\"id\":\"1126\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"end\":20},\"id\":\"1003\",\"type\":\"Range1d\"},{\"attributes\":{\"data_source\":{\"id\":\"1085\"},\"glyph\":{\"id\":\"1086\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1087\"},\"selection_glyph\":null,\"view\":{\"id\":\"1089\"}},\"id\":\"1088\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"data_source\":{\"id\":\"1033\"},\"glyph\":{\"id\":\"1034\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1035\"},\"selection_glyph\":null,\"view\":{\"id\":\"1037\"}},\"id\":\"1036\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"1005\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"1009\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"1063\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"1007\",\"type\":\"LinearScale\"},{\"attributes\":{\"data\":{\"x\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[300]},\"y\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[300]}},\"selected\":{\"id\":\"1104\"},\"selection_policy\":{\"id\":\"1103\"}},\"id\":\"1085\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"axis_label\":\"time (min)\",\"formatter\":{\"id\":\"1040\"},\"ticker\":{\"id\":\"1012\"}},\"id\":\"1011\",\"type\":\"LinearAxis\"},{\"attributes\":{\"source\":{\"id\":\"1085\"}},\"id\":\"1089\",\"type\":\"CDSView\"},{\"attributes\":{},\"id\":\"1012\",\"type\":\"BasicTicker\"},{\"attributes\":{\"line_alpha\":0.1,\"line_color\":\"#d62728\",\"line_width\":3,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1087\",\"type\":\"Line\"},{\"attributes\":{\"axis\":{\"id\":\"1011\"},\"ticker\":null},\"id\":\"1014\",\"type\":\"Grid\"},{\"attributes\":{\"line_color\":\"#9467bd\",\"line_width\":3,\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1107\",\"type\":\"Line\"},{\"attributes\":{},\"id\":\"1045\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"label\":{\"value\":\"\\u03b2cat*\"},\"renderers\":[{\"id\":\"1088\"}]},\"id\":\"1105\",\"type\":\"LegendItem\"},{\"attributes\":{\"data\":{\"x\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[300]},\"y\":{\"__ndarray__\":\"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\",\"dtype\":\"float64\",\"order\":\"little\",\"shape\":[300]}},\"selected\":{\"id\":\"1046\"},\"selection_policy\":{\"id\":\"1045\"}},\"id\":\"1033\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"1046\",\"type\":\"Selection\"},{\"attributes\":{\"axis_label\":\"conc (nM)\",\"formatter\":{\"id\":\"1042\"},\"ticker\":{\"id\":\"1016\"}},\"id\":\"1015\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"1104\",\"type\":\"Selection\"},{\"attributes\":{\"axis\":{\"id\":\"1015\"},\"dimension\":1,\"ticker\":null},\"id\":\"1018\",\"type\":\"Grid\"},{\"attributes\":{},\"id\":\"1016\",\"type\":\"BasicTicker\"},{\"attributes\":{\"data_source\":{\"id\":\"1066\"},\"glyph\":{\"id\":\"1067\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1068\"},\"selection_glyph\":null,\"view\":{\"id\":\"1070\"}},\"id\":\"1069\",\"type\":\"GlyphRenderer\"}],\"root_ids\":[\"1002\"]},\"title\":\"Bokeh Application\",\"version\":\"2.2.3\"}};\n", " var render_items = [{\"docid\":\"6b5dedea-cb7b-4196-9675-2efbdf8fb910\",\"root_ids\":[\"1002\"],\"roots\":{\"1002\":\"dea5d090-2e9f-42c3-b78d-4240829b3ee1\"}}];\n", " root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n", "\n", " }\n", " if (root.Bokeh !== undefined) {\n", " embed_document(root);\n", " } else {\n", " var attempts = 0;\n", " var timer = setInterval(function(root) {\n", " if (root.Bokeh !== undefined) {\n", " clearInterval(timer);\n", " embed_document(root);\n", " } else {\n", " attempts++;\n", " if (attempts > 100) {\n", " clearInterval(timer);\n", " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", " }\n", " }\n", " }, 10, root)\n", " }\n", "})(window);" ], "application/vnd.bokehjs_exec.v0+json": "" }, "metadata": { "application/vnd.bokehjs_exec.v0+json": { "id": "1002" } }, "output_type": "display_data" } ], "source": [ "# Set up canvas on which to paint plot\n", "p = bokeh.plotting.figure(\n", " plot_width=450,\n", " plot_height=350,\n", " x_axis_label=\"time (min)\",\n", " y_axis_label=\"conc (nM)\",\n", " x_range=[0, 20],\n", ")\n", "\n", "# Specify colors\n", "colors = bokeh.palettes.d3[\"Category10\"][5]\n", "\n", "# Add glyphs\n", "for c_res, name, color in zip(c.transpose(), names, colors):\n", " p.line(t, c_res, line_width=3, color=color, legend_label=name)\n", "\n", "# Place legend\n", "p.legend.location = \"center_right\"\n", "\n", "bokeh.io.show(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The Axin-β-catenin complexes, both activated and not activated, remain at low levels and closely track each other (if you zoom, you can see that the orange and green curves do not quite perfectly overlap). The unbound Axin complex does not vary much from its initial concentration of 50 nM." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Interactive plots with Panel\n", "\n", "When investigating how parameter values affect dynamics, it is convenient to be able to quickly adjust parameter values and see how the response changes. Interactive plotting is a very useful tool in this regard. We can make sliders to vary parameter values and see how the dynamics change.\n", "\n", "[Panel](https://panel.pyviz.org) really facilitates this. It allows specification of interactive sliders that can then be used to change appearance of plots.\n", "\n", "First, we will set up sliders for our six parameters, $k_8$, $k_{-8}$, $k_9$, $k_{10}$, $k_{11}$, and $k_{12}$. These allow us to change the values of the parameters." ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "k8_slider = pn.widgets.FloatSlider(\n", " name=\"k8\", start=0.001, end=0.1, step=0.0001, value=k8\n", ")\n", "\n", "km8_slider = pn.widgets.FloatSlider(\n", " name=\"km8\", start=0.001, end=100, step=0.001, value=km8\n", ")\n", "\n", "k9_slider = pn.widgets.FloatSlider(\n", " name=\"k9\", start=10.0, end=1000, step=0.1, value=k9\n", ")\n", "\n", "k10_slider = pn.widgets.FloatSlider(\n", " name=\"k10\", start=10.0, end=1000, step=0.1, value=k10\n", ")\n", "\n", "k11_slider = pn.widgets.FloatSlider(\n", " name=\"k11\", start=0.001, end=1, step=0.001, value=k11\n", ")\n", "\n", "k12_slider = pn.widgets.FloatSlider(\n", " name=\"k12\", start=10, end=1000, step=0.1, value=k12\n", " )" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next, all we have to do is write a function to make a plot of the solution for a given set of parameters. This function essentially just contains code we already wrote. To link the parameters of the function to the values of the slider, we use the `@pn.depends` decorator from Panel." ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "@pn.depends(\n", " k8_slider.param.value,\n", " km8_slider.param.value,\n", " k9_slider.param.value,\n", " k10_slider.param.value,\n", " k11_slider.param.value,\n", " k12_slider.param.value,\n", ")\n", "def plot_solution(k8, km8, k9, k10, k11, k12):\n", " # Unpack parameters\n", " params = (k8, km8, k9, k10, k11, k12)\n", "\n", " # Run the solver\n", " c = scipy.integrate.odeint(dcdt, c0, t, args=params)\n", "\n", " # Set up canvas on which to paint plot\n", " p = bokeh.plotting.figure(\n", " plot_width=450,\n", " plot_height=350,\n", " x_axis_label=\"time (min)\",\n", " y_axis_label=\"conc (nM)\",\n", " x_range=[0, 20],\n", " )\n", "\n", " # Specify colors\n", " colors = bokeh.palettes.d3[\"Category10\"][5]\n", "\n", " # Add glyphs\n", " for c_res, name, color in zip(c.transpose(), names, colors):\n", " p.line(t, c_res, line_width=3, color=color, legend_label=name)\n", "\n", " # Place legend\n", " p.legend.location = \"center_right\"\n", "\n", " return p" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Finally, we can set up a layout. We stack the slider widgets as a column and place them next to the plot. Note that this interactivity only works in a running notebook, not in an HTML rendering of the notebook. Note also that we have not included units for the parameters on the slider, but the units are indicated above." ] }, { "cell_type": "code", "execution_count": 10, "metadata": {}, "outputs": [ { "data": {}, "metadata": {}, "output_type": "display_data" }, { "data": { "application/vnd.holoviews_exec.v0+json": "", "text/html": [ "
\n", "\n", "\n", "\n", "\n", "\n", "
\n", "
\n", "" ], "text/plain": [ "Row\n", " [0] ParamFunction(function)\n", " [1] Spacer(width=15)\n", " [2] Column(width=300)\n", " [0] FloatSlider(end=0.1, name='k8', start=0.001, step=0.0001, value=0.008333333333333333, value_throttled=0.008333333333333333)\n", " [1] FloatSlider(end=100, name='km8', start=0.001, step=0.001, value=1, value_throttled=1)\n", " [2] FloatSlider(end=1000, name='k9', start=10.0, value=206, value_throttled=206)\n", " [3] FloatSlider(end=1000, name='k10', start=10.0, value=206, value_throttled=206)\n", " [4] FloatSlider(name='k11', start=0.001, step=0.001, value=0.417, value_throttled=0.417)\n", " [5] FloatSlider(end=1000, name='k12', start=10, value=100, value_throttled=100)" ] }, "execution_count": 10, "metadata": { "application/vnd.holoviews_exec.v0+json": { "id": "1358" } }, "output_type": "execute_result" } ], "source": [ "widgets = pn.Column(\n", " k8_slider, km8_slider, k9_slider, k10_slider, k11_slider, k12_slider, width=300\n", ")\n", "\n", "pn.Row(plot_solution, pn.Spacer(width=15), widgets)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "The interactive plotting shows that $k_{12}$ simply sets the scale of the concentration of β-catenin, with the axic complex concentrations being essentially unchanged. The parameter $k_{-8}$ adjusts the relative amounts of active and inactive β-catenin." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Computing environment" ] }, { "cell_type": "code", "execution_count": 11, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPython 3.8.5\n", "IPython 7.19.0\n", "\n", "numpy 1.19.2\n", "scipy 1.5.2\n", "bokeh 2.2.3\n", "panel 0.10.2\n", "jupyterlab 2.2.6\n" ] } ], "source": [ "%load_ext watermark\n", "%watermark -v -p numpy,scipy,bokeh,panel,jupyterlab" ] } ], "metadata": { "anaconda-cloud": {}, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.8.5" } }, "nbformat": 4, "nbformat_minor": 4 }