{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# 16. Paradoxical regulation and linear amplification\n", "\n", "(c) 2019 Justin Bois and Michael Elowitz. 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", "
\n", "
" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Design principle\n", "- Futile cycles in kinase systems can linear amplification that is robust to total protein copy numbers.\n", "\n", "#### Concepts\n", "- Paradoxical regulation.\n", "\n", "#### Techniques\n", "- Use of conservation laws can greatly simplify analysis.\n", "\n", "
\n", "\n", "
" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": true }, "outputs": [ { "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", " }\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", " 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", " console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n", " document.head.appendChild(element);\n", " }\n", " };var element = document.getElementById(\"1001\");\n", " if (element == null) {\n", " console.error(\"Bokeh: ERROR: autoload.js configured with elementid '1001' but no matching script tag was found. \")\n", " return false;\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.pydata.org/bokeh/release/bokeh-1.1.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.1.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.1.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-gl-1.1.0.min.js\"];\n", " var css_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-1.1.0.min.css\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.1.0.min.css\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.1.0.min.css\"];\n", "\n", " var inline_js = [\n", " function(Bokeh) {\n", " Bokeh.set_log_level(\"info\");\n", " },\n", " \n", " function(Bokeh) {\n", " \n", " },\n", " function(Bokeh) {} // ensure no trailing comma for IE\n", " ];\n", "\n", " function run_inline_js() {\n", " \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", " }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 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 console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n };var element = document.getElementById(\"1001\");\n if (element == null) {\n console.error(\"Bokeh: ERROR: autoload.js configured with elementid '1001' but no matching script tag was found. \")\n return false;\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.pydata.org/bokeh/release/bokeh-1.1.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.1.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.1.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-gl-1.1.0.min.js\"];\n var css_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-1.1.0.min.css\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.1.0.min.css\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.1.0.min.css\"];\n\n var inline_js = [\n function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\n \n function(Bokeh) {\n \n },\n function(Bokeh) {} // ensure no trailing comma for IE\n ];\n\n function run_inline_js() {\n \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 }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 pandas as pd\n", "\n", "# Plotting modules\n", "import bokeh.io\n", "import bokeh.plotting\n", "\n", "bokeh.io.output_notebook()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Paradoxical regulation: The I1-FFL revisited\n", "\n", "Let us look back for a moment at an early lesson in which we considered an incoherent feed-forward loop, the I1-FFL, shown below, left. We can abstract the I1-FFL further, wherein X can activate Z and also repress Z with a delay, as shown below, right. The delay is due to the indirect nature of the repression of Z, having to do though the Y intermediary.\n", "\n", "

\n", "\n", "In looking at the figure to the right, we see that X both activates and represses Z. We say that X's action on Y is **paradoxical**, in that the same gene has opposite regulatory effects on the same target. This stands in contrast to negative feedback loops or two _different_ genes regulating the same target in opposite ways.\n", "\n", "

\n", "\n", "We have already seen properties of the I1-FFL with AND logic.\n", "1. It is a pulse generator.\n", "2. It has an accelerated response compared to an unregulated circuit.\n", "\n", "In this lesson, we will further explore properties of circuits that employ paradoxical regulation, starting with simple two-component signaling circuits like the one shown above." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Two-component paradoxical circuits\n", "\n", "Two-component circuits are ubiquitous in signaling systems. It makes sense that this is the case; we need minimally two components, a receptor and a signaling molecule (usually a conjunction with a kinase or phosphatase). " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### First: A two-component non-paradoxical signaling circuit\n", "\n", "Before considering a circuit with paradoxical regulation, let us consider a simpler circuit wherein a signaling molecule allows the receptor kinase X to phosphorylate of a signaling molecule Y, as shown below.\n", "\n", "

\n", "\n", "If we assume the enzymes operate at saturation, we have\n", "\n", "\\begin{align}\n", "\\frac{\\mathrm{d}y_p}{\\mathrm{d}t} = v_1(s)\\,x \\, y - v_2\\,z \\, y_p.\n", "\\end{align}\n", "\n", "We also have conservation of mass; defining $y_0$ to be the total concentration of Y, we have $y_0 = y + y_p$. Using this expression, we have\n", "\n", "\\begin{align}\n", "\\frac{\\mathrm{d}y_p}{\\mathrm{d}t} = v_1(s)\\,x \\, (y_0-y_p) - v_2\\,z \\, y_p.\n", "\\end{align}\n", "\n", "We can solve for the steady state concentration of phosphorylated Y, which will affect the expression of the target gene, by setting $\\mathrm{d}y_p/\\mathrm{d}t = 0$ and solving. The result is\n", "\n", "\\begin{align}\n", "y_p(s) = \\frac{v_1(s)\\,x}{v_1(s)\\,x + v_2\\,z}\\,y_0.\n", "\\end{align}\n", "\n", "This expression reveals a limitation of this circuit. The amount of $y_p$ is obviously dependent on the amount of X, total amount of Y, and amount of Z. We might like the amount of $y_p$ to be dependent only on the concentration of signaling molecule, $s$, and be robust to how much X, Y, and Z are around." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Now: A two-component non-paradoxical signaling circuit\n", "\n", "Consider instead a situation where the receptor X is a bifunctional kinase. In its phosphorylated form, it phosphorylates Y via phosphotransfer with rate $v_3$. This is its activating regulation. In its dephosphorylated state, it serves to dephosphorylate Y with rate $v_2$, giving it its paradoxical repressive regulation. So, X paradoxically acts both as a kinase and phosphatase on the same target, Y. It also gets phosphorylated in contact with the signaling molecules S through consumption of an ATP.\n", "\n", "

\n", "\n", "We can write out the full dynamics of this system and solve for the steady state, but we can take a shortcut. We can think of the system a black box that takes in ATP and outputs ADP and inorganic phosphate. A phosphate comes in as part of ATP and goes out as inorganic phosphate. \n", "\n", "

\n", "\n", "\n", "Conservation of mass dictates that the total flux of this phosphate into the system must match the total flux of Pᵢ out of the system. The influx is $v_1(s)\\,x$ and the outflux is $v_2\\,x\\,y_p$. Setting these fluxes to be equal gives\n", "\n", "\\begin{align}\n", "v_1(s)\\,x = v_2\\,x\\,y_p,\n", "\\end{align}\n", "\n", "so that\n", "\n", "\\begin{align}\n", "y_p = \\frac{v_1(s)}{v_2}.\n", "\\end{align}\n", "\n", "This actually is not quite complete, since we still need to respect conservation of mass of Y, so\n", "\n", "\\begin{align}\n", "y_p = \\begin{cases}\n", "\\frac{v_1(s)}{v_2} & y_0 \\ge \\frac{v_1(s)}{v_2},\\\\[1em]\n", "y_0 & y_0 < \\frac{v_1(s)}{v_2}.\n", "\\end{cases}\n", "\\end{align}\n", "\n", "This is dependent only on $s$, and is completely independent of the total amounts of the proteins X and Y. Importantly, the activity, as quantified by the concentration of phosphorylated Y, is linear in the input $v_1(s)$, with a slope of $v_2^{-1}$. Thus, this system, at least before saturating, is a **perfect linear amplifier** of the input signal.\n", "\n", "Key to the linear amplification of signal is the following.\n", "1. The cell must produce enough Y to make sure it does not saturate. That is, $y_0$ must be at least $v_1(s_\\mathrm{max})/v_2$, where $s_\\mathrm{max}$ is the maximum expected concentration of the signaling molecule.\n", "2. The gain of the amplifier (the slope of the linear response) is inversely proportional to the dephosphorylation rate $v_2$. Slow dephosphorylation gives a larger gain.\n", "3. It is critical that only the dephosphorylated state of the bifunctional kinase X have phosphatase activity. (If the phosphorylated state could act as a phosphatase, the inorganic phosphate balance changes, and we lose the linear amplification feature.)\n", "4. All enzymes are operating at capacity. We would lose perfect linear amplification due to nonlinearities if they were not.\n", "5. We are neglecting slow reactions, such as spontaneous dephosphorylation, which would also destroy robustness to total protein levels." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### An example paradoxical signaling system\n", "\n", "The EnvZ-OmpR system in _E. coli_ is a classic system that features a bifunctional kinase with paradoxical signaling. It has the same architecture as our example above. EnvZ is a histidine kinase that senses osmotic stress, and OmpR regulates expressin of porin genes in response to osmolarity.\n", "\n", "

\n", "\n", "Batchelor and Goulian ([_PNAS_, 2003](https://doi.org/10.1073/pnas.0234782100)) introduced a plasmid to _E. coli_ cells where OmpR is under control of the _lac_ promoter. They could then adjust the OmpR levels by titrating IPTG. They could then monitor the activity of the target promoter, which which they engineered to produce fluorescent proteins. The measured the target promoter activity with low osmolarity (minimal media) and with high osmolarity (minimal media with 15% sucrose). The result of their experiment is shown below (using data digitized from the paper)." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "tags": [ "remove_input" ] }, "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 = {\"431fc569-eca5-49c0-97bd-8290339065d1\":{\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"1011\",\"type\":\"LogAxis\"}],\"center\":[{\"id\":\"1015\",\"type\":\"Grid\"},{\"id\":\"1020\",\"type\":\"Grid\"},{\"id\":\"1048\",\"type\":\"Legend\"}],\"left\":[{\"id\":\"1016\",\"type\":\"LogAxis\"}],\"plot_height\":300,\"plot_width\":500,\"renderers\":[{\"id\":\"1039\",\"type\":\"GlyphRenderer\"}],\"title\":{\"id\":\"1041\",\"type\":\"Title\"},\"toolbar\":{\"id\":\"1027\",\"type\":\"Toolbar\"},\"x_range\":{\"id\":\"1003\",\"type\":\"DataRange1d\"},\"x_scale\":{\"id\":\"1007\",\"type\":\"LogScale\"},\"y_range\":{\"id\":\"1005\",\"type\":\"DataRange1d\"},\"y_scale\":{\"id\":\"1009\",\"type\":\"LogScale\"}},\"id\":\"1002\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"callback\":null,\"data\":{\"fold increase in OmpR\":{\"__ndarray__\":\"wAeNr1w8uz/L9XSN50XWP+TrzWXhUvA/7m+3YMR8/j/6r9Q/hxsLQF2zLwSeLSBAJ9rDsRhAJ0DNsUuewycpQFo2VZi73CxAvKEG8uuzN0AdV5/ECOO6P9WCF0sR1ss/S7PjBIOw5D/YoSHu5ZT7P/THXTlMuP4/58L1/hWoBUACFNL6qCATQJ/dfQTt0CJA6if5jRGXJ0AlOqXloecqQA==\",\"dtype\":\"float64\",\"shape\":[20]},\"index\":[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19],\"osmolarity\":[\"low osmolarity\",\"low osmolarity\",\"low osmolarity\",\"low osmolarity\",\"low osmolarity\",\"low osmolarity\",\"low osmolarity\",\"low osmolarity\",\"low osmolarity\",\"low osmolarity\",\"high osmolarity\",\"high osmolarity\",\"high osmolarity\",\"high osmolarity\",\"high osmolarity\",\"high osmolarity\",\"high osmolarity\",\"high osmolarity\",\"high osmolarity\",\"high osmolarity\"],\"target promoter activity (a.u.)\":{\"__ndarray__\":\"qvHSTWIQ4D/99nXgnBHtP1g5tMh2vu8/1lbsL7sn6z9txf6ye/LmP5m7lpAPeug//fZ14JwR7T9YObTIdr7vP9O84xQdyfE/JuSDns0qAkBLWYY41sXRPycxCKwcmh5ASL99HTjHJkAYldQJaAInQKmkTkATASdAbhKDwMphKEDF/rJ78jApQB+F61G4/ilAtFn1udoqLkALRiV1Aio9QA==\",\"dtype\":\"float64\",\"shape\":[20]}},\"selected\":{\"id\":\"1056\",\"type\":\"Selection\"},\"selection_policy\":{\"id\":\"1057\",\"type\":\"UnionRenderers\"}},\"id\":\"1035\",\"type\":\"ColumnDataSource\"},{\"attributes\":{\"label\":{\"field\":\"osmolarity\"},\"renderers\":[{\"id\":\"1039\",\"type\":\"GlyphRenderer\"}]},\"id\":\"1049\",\"type\":\"LegendItem\"},{\"attributes\":{\"factors\":[\"low osmolarity\",\"high osmolarity\"],\"palette\":[\"#1f78b4\",\"orange\"]},\"id\":\"1034\",\"type\":\"CategoricalColorMapper\"},{\"attributes\":{},\"id\":\"1056\",\"type\":\"Selection\"},{\"attributes\":{},\"id\":\"1021\",\"type\":\"PanTool\"},{\"attributes\":{},\"id\":\"1057\",\"type\":\"UnionRenderers\"},{\"attributes\":{\"overlay\":{\"id\":\"1047\",\"type\":\"BoxAnnotation\"}},\"id\":\"1023\",\"type\":\"BoxZoomTool\"},{\"attributes\":{\"callback\":null},\"id\":\"1003\",\"type\":\"DataRange1d\"},{\"attributes\":{},\"id\":\"1024\",\"type\":\"SaveTool\"},{\"attributes\":{},\"id\":\"1022\",\"type\":\"WheelZoomTool\"},{\"attributes\":{},\"id\":\"1025\",\"type\":\"ResetTool\"},{\"attributes\":{},\"id\":\"1026\",\"type\":\"HelpTool\"},{\"attributes\":{\"active_drag\":\"auto\",\"active_inspect\":\"auto\",\"active_multi\":null,\"active_scroll\":\"auto\",\"active_tap\":\"auto\",\"tools\":[{\"id\":\"1021\",\"type\":\"PanTool\"},{\"id\":\"1022\",\"type\":\"WheelZoomTool\"},{\"id\":\"1023\",\"type\":\"BoxZoomTool\"},{\"id\":\"1024\",\"type\":\"SaveTool\"},{\"id\":\"1025\",\"type\":\"ResetTool\"},{\"id\":\"1026\",\"type\":\"HelpTool\"}]},\"id\":\"1027\",\"type\":\"Toolbar\"},{\"attributes\":{\"callback\":null},\"id\":\"1005\",\"type\":\"DataRange1d\"},{\"attributes\":{\"data_source\":{\"id\":\"1035\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"1037\",\"type\":\"Circle\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1038\",\"type\":\"Circle\"},\"selection_glyph\":null,\"view\":{\"id\":\"1040\",\"type\":\"CDSView\"}},\"id\":\"1039\",\"type\":\"GlyphRenderer\"},{\"attributes\":{},\"id\":\"1007\",\"type\":\"LogScale\"},{\"attributes\":{},\"id\":\"1009\",\"type\":\"LogScale\"},{\"attributes\":{\"fill_color\":{\"field\":\"osmolarity\",\"transform\":{\"id\":\"1034\",\"type\":\"CategoricalColorMapper\"}},\"line_color\":{\"field\":\"osmolarity\",\"transform\":{\"id\":\"1034\",\"type\":\"CategoricalColorMapper\"}},\"x\":{\"field\":\"fold increase in OmpR\"},\"y\":{\"field\":\"target promoter activity (a.u.)\"}},\"id\":\"1037\",\"type\":\"Circle\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#1f77b4\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#1f77b4\"},\"x\":{\"field\":\"fold increase in OmpR\"},\"y\":{\"field\":\"target promoter activity (a.u.)\"}},\"id\":\"1038\",\"type\":\"Circle\"},{\"attributes\":{\"num_minor_ticks\":10},\"id\":\"1012\",\"type\":\"LogTicker\"},{\"attributes\":{\"source\":{\"id\":\"1035\",\"type\":\"ColumnDataSource\"}},\"id\":\"1040\",\"type\":\"CDSView\"},{\"attributes\":{\"ticker\":{\"id\":\"1012\",\"type\":\"LogTicker\"}},\"id\":\"1015\",\"type\":\"Grid\"},{\"attributes\":{\"text\":\"\"},\"id\":\"1041\",\"type\":\"Title\"},{\"attributes\":{\"axis_label\":\"target promoter activity (a.u.)\",\"formatter\":{\"id\":\"1045\",\"type\":\"LogTickFormatter\"},\"ticker\":{\"id\":\"1017\",\"type\":\"LogTicker\"}},\"id\":\"1016\",\"type\":\"LogAxis\"},{\"attributes\":{\"ticker\":null},\"id\":\"1043\",\"type\":\"LogTickFormatter\"},{\"attributes\":{\"axis_label\":\"fold increase in OmpR\",\"formatter\":{\"id\":\"1043\",\"type\":\"LogTickFormatter\"},\"ticker\":{\"id\":\"1012\",\"type\":\"LogTicker\"}},\"id\":\"1011\",\"type\":\"LogAxis\"},{\"attributes\":{\"num_minor_ticks\":10},\"id\":\"1017\",\"type\":\"LogTicker\"},{\"attributes\":{\"ticker\":null},\"id\":\"1045\",\"type\":\"LogTickFormatter\"},{\"attributes\":{\"dimension\":1,\"ticker\":{\"id\":\"1017\",\"type\":\"LogTicker\"}},\"id\":\"1020\",\"type\":\"Grid\"},{\"attributes\":{\"bottom_units\":\"screen\",\"fill_alpha\":{\"value\":0.5},\"fill_color\":{\"value\":\"lightgrey\"},\"left_units\":\"screen\",\"level\":\"overlay\",\"line_alpha\":{\"value\":1.0},\"line_color\":{\"value\":\"black\"},\"line_dash\":[4,4],\"line_width\":{\"value\":2},\"render_mode\":\"css\",\"right_units\":\"screen\",\"top_units\":\"screen\"},\"id\":\"1047\",\"type\":\"BoxAnnotation\"},{\"attributes\":{\"items\":[{\"id\":\"1049\",\"type\":\"LegendItem\"}],\"location\":\"center_left\"},\"id\":\"1048\",\"type\":\"Legend\"}],\"root_ids\":[\"1002\"]},\"title\":\"Bokeh Application\",\"version\":\"1.1.0\"}};\n", " var render_items = [{\"docid\":\"431fc569-eca5-49c0-97bd-8290339065d1\",\"roots\":{\"1002\":\"5eb3ab56-2bdf-477f-974c-0eddc13f106c\"}}];\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", " embed_document(root);\n", " clearInterval(timer);\n", " }\n", " attempts++;\n", " if (attempts > 100) {\n", " console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n", " clearInterval(timer);\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": [ "df = pd.read_csv('batchelor_and_goulian_pnas_2003.csv')\n", "\n", "p = bokeh.plotting.figure(height=300, width=500, \n", " x_axis_label='fold increase in OmpR', \n", " y_axis_label='target promoter activity (a.u.)',\n", " x_axis_type='log', y_axis_type='log')\n", "\n", "p.circle(source=df, \n", " x='fold increase in OmpR', \n", " y='target promoter activity (a.u.)',\n", " color=bokeh.transform.factor_cmap('osmolarity', \n", " ['#1f78b4', 'orange'], \n", " ['low osmolarity', 'high osmolarity']),\n", " legend='osmolarity')\n", "p.legend.location = 'center_left'\n", "\n", "bokeh.io.show(p)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Over at least an order of magnitude the target promoter activity is robust to OmpR concentration, dependent only on the osmolarity of the surroundings." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Design considerations for two-component paradoxical signaling\n", "\n", "At the heart of linear amplification by two-component signaling is the bifunctional histidine kinase (labeled X in our generic two-component signaling system). The total concentration X affect the rates of all reaction. Too little X results in a slow response time, but too much X costs cellular resources. So, there is some optimization with respect to the amount of X, depending on the cell's needs. Importantly, if all enzymes are operating at saturation, and the response is fast enough that we can continue to neglect slow reactions like spontaneous phosphorylation, the perfect linear amplification at steady state is robust to the total level of X (and also Y)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Computing environment" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "tags": [ "remove_input" ] }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "CPython 3.7.3\n", "IPython 7.5.0\n", "\n", "numpy 1.16.3\n", "pandas 0.24.2\n", "bokeh 1.1.0\n", "jupyterlab 0.35.5\n" ] } ], "source": [ "%load_ext watermark\n", "%watermark -v -p numpy,pandas,bokeh,jupyterlab" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.7.3" } }, "nbformat": 4, "nbformat_minor": 2 }