From 1e7b0c85fde79c33d9aa99ad0792ac77ebe0eb88 Mon Sep 17 00:00:00 2001 From: Jack Arthur Date: Wed, 19 Feb 2020 16:26:35 +0000 Subject: [PATCH 1/3] Fixes general markov jump model for gillespie simulations of systems of reactions --- examples/toy-model-logistic.ipynb | 9 +- examples/toy-model-michaelis-menten.ipynb | 339 ++++++++++++++++++ examples/toy-model-schlogl.ipynb | 238 ++++++++++++ .../test_toy_stochastic_degradation_model.py | 28 +- pints/toy/__init__.py | 1 - pints/toy/stochastic/__init__.py | 16 + .../_degradation_model.py} | 6 +- pints/toy/stochastic/_markov_jump_model.py | 187 ++++++++++ .../toy/stochastic/_michaelis_menten_model.py | 44 +++ pints/toy/stochastic/_schlogl_model.py | 56 +++ 10 files changed, 903 insertions(+), 21 deletions(-) create mode 100644 examples/toy-model-michaelis-menten.ipynb create mode 100644 examples/toy-model-schlogl.ipynb create mode 100644 pints/toy/stochastic/__init__.py rename pints/toy/{_stochastic_degradation_model.py => stochastic/_degradation_model.py} (97%) create mode 100644 pints/toy/stochastic/_markov_jump_model.py create mode 100644 pints/toy/stochastic/_michaelis_menten_model.py create mode 100644 pints/toy/stochastic/_schlogl_model.py diff --git a/examples/toy-model-logistic.ipynb b/examples/toy-model-logistic.ipynb index 0ed958e51..3a3540924 100644 --- a/examples/toy-model-logistic.ipynb +++ b/examples/toy-model-logistic.ipynb @@ -17,7 +17,10 @@ "cell_type": "code", "execution_count": 1, "metadata": { - "collapsed": true + "collapsed": true, + "jupyter": { + "outputs_hidden": true + } }, "outputs": [], "source": [ @@ -200,9 +203,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.7" + "version": "3.7.4" } }, "nbformat": 4, - "nbformat_minor": 2 + "nbformat_minor": 4 } diff --git a/examples/toy-model-michaelis-menten.ipynb b/examples/toy-model-michaelis-menten.ipynb new file mode 100644 index 000000000..f6a15147d --- /dev/null +++ b/examples/toy-model-michaelis-menten.ipynb @@ -0,0 +1,339 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Michaelis-Menten\n", + "\n", + "- X1+X2 -> X3 \n", + "- X3 -> X1+X2 \n", + "- X3 -> X2+X4" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import pints\n", + "import pints.toy.stochastic\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import math" + ] + }, + { + "cell_type": "code", + "execution_count": 22, + "metadata": {}, + "outputs": [], + "source": [ + "import line_profiler" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Specify initial concentration, time points at which to record concentration values, and rate constant value (k)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "x_0 = [1e4, 2e3, 2e4, 0]\n", + "model = pints.toy.stochastic.MichaelisMentenModel(x_0)\n", + "\n", + "times = np.linspace(0, 24, 100)\n", + "k = [1e-5, 0.2, 0.2]\n", + "\n", + "values = model.simulate(k, times)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.step(times, values[:,0], label = 'X1')\n", + "plt.step(times, values[:,1], label = 'X2')\n", + "plt.step(times, values[:,2], label = 'X3')\n", + "plt.step(times, values[:,3], label = 'X4')\n", + "plt.legend()\n", + "plt.xlabel('time')\n", + "plt.ylabel('concentration (A(t))')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We can also evaluate this model using tau-leaping for more efficient but approximate simulations" + ] + }, + { + "cell_type": "code", + "execution_count": 24, + "metadata": {}, + "outputs": [], + "source": [ + "values_exact = model.simulate(k, times)\n", + "values_approx = model.simulate(k, times, approx=True, approx_tau=0.0125)" + ] + }, + { + "cell_type": "code", + "execution_count": 39, + "metadata": {}, + "outputs": [], + "source": [ + "def plot_output(vs, suffix=''):\n", + " plt.step(times, vs[:,0], label = 'X1'+suffix)\n", + " plt.step(times, vs[:,1], label = 'X2'+suffix)\n", + " plt.step(times, vs[:,2], label = 'X3'+suffix)\n", + " plt.step(times, vs[:,3], label = 'X4'+suffix)\n", + " plt.legend()\n", + " plt.xlabel('time')\n", + " plt.ylabel('Molecule Count')\n", + " plt.show()" + ] + }, + { + "cell_type": "code", + "execution_count": 40, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZUAAAEGCAYAAACtqQjWAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAAgAElEQVR4nO3de7RVdb338fdXBPFGCt42bG45SAQsip2o3TynYyFa6POIt5MaOQ4eU7vqkBj1UGaFeTLN0sRHAR0qWmaa4e34iJdCdONDolySR0W2ECKbAjMl5fv8MeeC6WZd5lprzrXWXOvzGmOPvddvzTXnb7Zlf/pdp7k7IiIiSdil3hUQEZHmoVAREZHEKFRERCQxChUREUmMQkVERBKza70rUGv77befDxs2rN7VEBHJlMWLF7/u7vuXOq7lQmXYsGF0dnbWuxoiIpliZqvjHKfuLxERSYxCRUREEqNQERGRxChUREQkMamFipkNNrNHzGy5mT1vZl8Ny79rZq+a2ZLwa2LkM98ys1VmttLMPhspnxCWrTKzaZHy4Wa2yMxeMLPbzaxPWvcjIiKlpdlSeQf4prsfChwBnGdmo8L3furuY8Ov+QDhe6cCo4EJwDVm1svMegG/AI4FRgGnRc5zWXiuEcAm4OwU70dEREpILVTcfZ27PxP+vAVYDgwq8pFJwDx3f9vdXwJWAYeHX6vc/UV33wrMAyaZmQH/Cvw6/Pxc4IR07kZEROKoyToVMxsGfBhYBHwMON/MzgQ6CVozmwgC58nIx7rYEUJrepSPBwYAf3X3d/IcLyLS0jbdfgeb7713++vdDh3JQdOnp37d1EPFzPYC7gS+5u6bzexa4PuAh99/AnwJsDwfd/K3przI8fnqMBWYCjBkyJByb0FEJBOiQfLm008DsMdHP1rTOqQaKmbWmyBQbnH33wC4+/rI+9cDuSjtAgZHPt4OrA1/zlf+OrCPme0atlaix7+Hu88CZgF0dHToqWQikmk9WyE50SDZ46Mfpd/xx7PvKSfXtG6phUo45nEDsNzdr4iUt7n7uvDlicBz4c/3ALea2RXAQGAE8BRBi2SEmQ0HXiUYzD/d3d3MHgFOIhhnOQu4O637ERGppzitkHoFSVSaLZWPAWcAS81sSVg2nWD21liCrqqXgXMA3P15M7sDWEYwc+w8d38XwMzOBx4AegE3uvvz4fkuBuaZ2aXA/yUIMRGRplAoSBohPAqxVntGfUdHh2tDSRFpVMVaJPUMEjNb7O4dpY5ruV2KRUQaTRZbJIUoVERE6qCZgiRKoSIikpJCs7SguYIkSqEiIpKguGtFmilIohQqIiJVataurEooVEREKqAgyU+hIiISk4KkNIWKiEgRCpLyKFRERHpQkFROoSIigoIkKQoVEWlZCpLkKVREpKUoSNKlUBGRpqcgqR2Fiog0JQVJfShURKRpKEjqT6EiIpnVc8NGBUn9KVREJFOKbdioIKk/hYqIZMrme+/lrRUr6DtypEKkASlURKThRVsnuUAZevNNda6V5KNQEZGGVKibq+/IkfQ7/vh6Vk2KUKiISMPQ7K3sU6iISF0pSJqLQkVEak5B0rwUKiJSc5rB1bwUKiJSE5rB1RoUKiKSGs3gaj0KFRFJlMZLWptCRUSqpiCRHIWKiFREQSL5KFREpCKawSX5KFREJDbN4JJSdknrxGY22MweMbPlZva8mX01LO9vZg+Z2Qvh933DcjOzn5nZKjN71sw+EjnXWeHxL5jZWZHycWa2NPzMz8zM0rofkVa16fY7WH3Gmaw+40z+MmPG9q4uzeCSfNJsqbwDfNPdnzGzvYHFZvYQ8EXgYXefaWbTgGnAxcCxwIjwazxwLTDezPoDM4AOwMPz3OPum8JjpgJPAvOBCcB9Kd6TSNPTg6+kGqmFiruvA9aFP28xs+XAIGAScHR42FxgAUGoTAJucncHnjSzfcysLTz2IXfvBgiDaYKZLQD6ufvCsPwm4ARSCpXLnroMgIsPvziN04s0jOhYCejBVw2pczYs/XV5nznoMDh2Zjr1iajJmIqZDQM+DCwCDgwDB3dfZ2YHhIcNAtZEPtYVlhUr78pTnu/6UwlaNAwZMqSie1jRvaKiz4lkgcZK6qzckFj9RPB96MfTqU8VUg8VM9sLuBP4mrtvLjLske8Nr6B850L3WcAsgI6OjrzHiLQarXavgbhhUW5IDP04HHYSdEypvG4pSTVUzKw3QaDc4u6/CYvXm1lb2EppA14Ly7uAwZGPtwNrw/Kje5QvCMvb8xwvIgVobUmC4gRG3LBo4JAoV2qhEs7EugFY7u5XRN66BzgLmBl+vztSfr6ZzSMYqP9bGDwPAD/MzRIDPgN8y927zWyLmR1B0K12JnB1Wvcj0gy0tqQChcIjTmA0UVjElWZL5WPAGcBSM1sSlk0nCJM7zOxs4BVgcvjefGAisAp4E5gCEIbH94Gnw+MuyQ3aA+cCc4DdCQboNfNLpAeNl8RUbni0YGDEkebsryfIP+4B8Ok8xztwXoFz3QjcmKe8ExhTRTVFml60ddKy4yXVdFUpPMqiFfUiTajpWieVTKGNUldVzShURJpEU8zmqmb8ohgFRs0oVESaRKYG4TV+0bQUKiIZ1vDdXAqPlqNQEcmYhunm0uC35KFQEcmYmndzaZ2GlEGhIpIBqXRzVbuFiAJD8lColGFl90qm3B/8A5r4/olM/sDkEp8QqVxi3VzVzqhSeEgZFCoxTXz/xO0/r+xeCaBQkVSV3c2lQXFpABYsZG8dHR0d3tnZWdU5cq2V2RNmJ1Elke0KdnNVu3mhwkOqZGaL3b2j1HFqqYjUWd5ursF96bsP9Ov/Esw+ToPikhkKFZFa69Hq2HzrWt56bSt9D+jDHvu/Tb+h/2DfT3/kvZ9RYEhGKFREkhSjm2rTw8+wefXu0Pd9ANsDZejpA4GBCg/JNIWKSLWiQRKjm2rz+oN46+9O32GHAdD3IILZXI26pYpIGRQqInHFmV1VoJvqPQPwf91A39ENtp2KSEIUKiKQypYjDbOdikgNKVSktdRwy5FM7RoskpCSoWJmD7v7p0uViTSUOi0EbPhdg0VSVjBUzKwvsAewn5nty45HA/cDBtagbiLFFeuyqtMqcj26V1pdsZbKOcDXCAJkMTtCZTPwi5Tr1fC0D1idxJ1pVcN1HWqdiOxQMFTc/SrgKjO7wN2vrmGdGp72AauBKmZa1YIG4UXyKzmm4u5Xm9lRwLDo8e7esv9XbPIHJm8PkVxrRRIQpxXSICvLNQgvkl+cgfqbgYOBJcC7YbEDLRsqkqBCQdIg4RGlbi6R0uJMKe4ARnmrbWcs6clQkERpEF5K+ec//0lXVxdvvfVWvatSsb59+9Le3k7v3r0r+nycUHkOOAhYV9EVpHU1+LhIHGqdSDm6urrYe++9GTZsGGZW+gMNxt3ZuHEjXV1dDB8+vKJzxAmV/YBlZvYU8Hbk4p+v6IrSOpb+Gv6yFA467L3lDR4kUWqdSDneeuutzAYKgJkxYMAANmzYUPE54oTKdys+u7SGQi2SXKBM+X3t61QFtU6kGlkNlJxq6x9n9tejVV1BmlOcmVoHHRa0SDJAU4SlWaxZs4ZPfvKTLF68mP79+7Np0yY+8pGPsGDBAs455xyefPJJPv7xj3Nv+N970uLM/tpCMNsLoA/QG/i7u/dLpUbSmHq2RjI0LhKHpghLsxg8eDDnnnsu06ZNY9asWUybNo2pU6cydOhQLrroIt58802uu+661K4fp6Wyd/S1mZ0AHJ5ajaRxFGuNNEGQqJtLmtXXv/51xo0bx5VXXskTTzzB1VcH69c//elPs2DBglSvXfYuxe7+WzOblkZlsqqptmzJ6HTfSmgQXtL0vd89z7K1mxM956iB/ZjxudElj+vduzeXX345EyZM4MEHH6RPnz6J1qOYON1f/yPycheCdSsl16yY2Y3A8cBr7j4mLPsu8B9AbmrBdHefH773LeBsggWWX3H3B8LyCcBVQC/gf7v7zLB8ODAP6A88A5zh7ltL1StpTbdlS3TGVhMGiVon0iruu+8+2traeO655zjmmGNqdt04LZXPRX5+B3gZmBTjc3OAn7Pzyvufuvt/RQvMbBRwKjCaYAPL/zazD4Rv/wI4BugCnjaze9x9GXBZeK55ZvZLgkC6Nka9EtUUW7ZEWycZnbEVl1onUitxWhRpWbJkCQ899ND2QflTTz2Vtra2mlw7zphKRX8p3f0xMxsW8/BJwDx3fxt4ycxWsWPcZpW7vwhgZvOASWa2HPhX4PTwmLkEU59rHiqZVaibK0MztuJS60Raibtz7rnncuWVVzJkyBAuuugiLrzwQm655ZaaXH+XUgeYWbuZ3WVmr5nZejO708zaq7jm+Wb2rJndGD6nBWAQsCZyTFdYVqh8APBXd3+nR3mhe5hqZp1m1lnNop6mkuvmgiBMjr8yaJ1M+X1TdXfBjtYJoNaJNL3rr7+eIUOGbO/y+vKXv8yKFSt49NFH+cQnPsHkyZN5+OGHaW9v54EHHkj8+nG6v2YDtwK5gYIvhGWVdNJdC3yfYEzm+8BPgC+x41ktUU7+0PMix+fl7rOAWQAdHR2tu4dZC3VzqXUirWrq1KlMnTp1++tevXqxePFiAB5//PHUr1+ypQLs7+6z3f2d8GsOsH8lF3P39e7+rrtvA65nRxdXFzA4cmg7sLZI+evAPma2a49yKSbaOmnCbq4otU5E6iNOS+V1M/sCcFv4+jRgYyUXM7M2d89tTHkiwWaVAPcAt5rZFQQD9SOApwhaJCPCmV6vEgzmn+7ubmaPACcRzAA7C7i7kjo1vRZpnURbJqDWiUi9xGmpfAk4GfgLwU7FJ4VlRZnZbcBC4BAz6zKzs4Efm9lSM3sW+Bfg6wDu/jxwB7AMuB84L2zRvAOcDzwALAfuCI8FuBj4RjioPwC4IeY9t5YWaZ1EWyag1olIvcSZ/fUKUPaOxO5+Wp7ign/43f0HwA/ylM8H5ucpf5EGXNnfEAshW7B1opaJSGMo2FIxsx+b2X/mKf+6mV2WbrWyaeL7J3JI/0OAIFzmv7hTFtZGC7ZO1DIRaQzFWirHA2PylF8FPEvQ/SQRSS6EvHXRK9y95NWSx00aO4jTxw9R60REGkKxMRUPZ2n1LNxG/im9UqVbF73CKdct5JTrFjL9rqUseqm76PGLXupm+l1LOeW6hTz/4A1sffVPwRtqnYi0rDVr1jB8+HC6u4O/H5s2bWL48OE8+uijHHnkkYwePZoPfvCD3H777alcv1hL5U0zG+HuL0QLzWwE8I9UatNierZGciEyfnh/xg/vv6MVEuPzW956h2do56dbvx28uRhYvBCg5HkanVonIvEV2vq+ra2Nm266iREjRrB27VrGjRvHZz/7WfbZZ59Er18sVP4XcJ+ZXUrwJwqCzSS/BXwt0Vq0qLuXvMqydZsZ1RY8miZOkESd3uthTu8TdHlt7dPFC7sM2+mYRS91s+il7u3hk8WA0X5dIuXJt/V9dKfigQMHcsABB7Bhw4bahYq73xc+O+Ui4IKw+Dngf7r70kRr0UKirYtcoNx+zpGVnSyyo3CfQR9i9GEncXvHe88VvV6WAkatE8m8+6btmDCTlIMOg2Nnljys1Nb3Tz31FFu3buXggw9Otn6UmFLs7s8RLCyUKvT8ww5Bq2RUWz8mjS24ZVk8JQbkTx8/ZHtwZClg1DoRqU6hre/XrVvHGWecwdy5c9lllzhLFctT9kO6JL7cmpVl6zbz5hsfZNRenym7i2sn+WZ5xdToAaPWiTSVGC2KtBTa+n7z5s0cd9xxXHrppRxxxBGpXFuhkpLow7vesjXs0R9unzKj+hNHH6JVxSyvQgGzbN3m7e/XmlonItUrtPX97NmzOfHEEznzzDOZPDm9RdkKlZT8c9N43lwdPCFgm8+E3RI8ecJrUKIBc8p1C1m2bjOnXFebmWNqnYgkK9/W93PmzOFHP/oRjz32GBs3bmTOnDkAzJkzh7FjxyZ6/TiPE/4AwZb1B7r7GDP7IPB5d7800Zo0mejMrj1225X99qwiVaro8ipXdIynFt1iap2IJKvY1vczZiTQW1JCnJbK9QQzwK4DcPdnzexWQKFSQm5m15T7+1V3ooS6vOKIO+4CyYWMWicizSNOqOzh7k+ZvWcR/TuFDm5l+aYLJ6YO264UChiobuwlX5eXiDSHuM9TOZjwyYpmdhLBFvjSQ7TLq+rpwjXs8oojGjBQ3diLurxEmlecUDmP4FG8I83sVeAlgkcKSx5VLWaMqmGXVyXKHXvRgLxIa4jzPJUXgX8zsz2BXdx9S/rVaj4VPWelgXcaLndKslonIq2hYKiY2TcKlAPg7lekVKdMiTOOEl2zsrJ7JUB9Ht6VkkJTksc9u4CjX13CgXvvptaJSIsotkZ/7xJfwo5xFKDgOMrkD0xm9oTZzJ4we/tDvJrVpLGDtgfr0CVPYKv+zLJ1m3nxfQNZMfqoOtdOpPkV2vp+9erVjBs3jrFjxzJ69Gh++ctfpnL9YhtKfi+VKzahxMZRGmxwvhLHvvwkH3siGDvZ/I/1dB00lDmTLw72PPsrjK/RokqRVlVs6/s//vGP7LbbbrzxxhuMGTOGz3/+8wwcODDR68dZ/DibcOZXlLt/KdGaSMMPzscRHTvpN3oURxx/PMeecmTDbAUj0gpKbX3/9ttvs23bTs9gTESc2V/3Rn7uC5wIrE2lNtLQg/Nx5Rs7qedWMCL1cNlTl7Gie0Wi5xzZfyQXH176Se6Ftr5fs2YNxx13HKtWreLyyy9PvJUC8WZ/3Rl9bWa3Af+deE0ypNpFjhXNBGtg5S5mrPVWMCKtKN/W94MHD+bZZ59l7dq1nHDCCZx00kkceOCBiV63kg0lRwAt/a++mkWO75kJtmEp/GUpk/8wJyjI6DhKudOFG30LfpEkxGlRpKXQ1vc5AwcOZPTo0Tz++OOcdFKy3exxxlS28N4xlb8A9ftfq0FUOjg/+QOTt7dMpszpgK1/h97hmxkaR0lqMWMjbsEvkmWFtr6/7LLLGDBgALvvvjubNm3iD3/4A9/4Rt6VI1WJ0/2l6cNp6rMnfDF7YyhpLGbUuItI9QptfX/DDTdw5513Yma4OxdeeCGHHZZ8z0iclsqJwP9x97+Fr/cBjnb33yZeG2lY0ZYJpL/VisZdRCqTha3vZ7j7XbkX7v5XM5sBtFSopLoDcQZEWyZA6lutqFtMJJvihEq+Vfct98TIRHcgjljJ1u0zwaCxZ4PVa5sVdYuJZEeccOg0syuAXxAM2F8ALE61Vg0qkZXzkVXzEzdvgvftu/2tRtsXrBGfe6JuMZHGFidULgC+A9wevn4Q+HZqNWp2kVXzk/uNZPKYk6AjaKlEWyyNoBF3Fq7HkylFJL44s7/+Dkwzs73c/Y24JzazG4HjgdfcfUxY1p8gnIYBLwMnu/smC7Y+vgqYCLwJfNHdnwk/cxY7QuxSd58blo8D5gC7A/OBr7r7TtvJNKQGXjWfpeeepPVkShGpXLFdigEws6PMbBmwLHz9ITO7Jsa55wATepRNAx529xHAw+FrgGMJFlWOAKYC14bX6g/MAMYDhwMzzCzXX3RteGzucz2vJRXItU4g/cH4JJ0+fgi3n3Pk9q9Rbf22j72cct1Cbl30Sr2rKNISSoYK8FPgs8BGAHf/E/DJUh9y98eA7h7Fk4C54c9zgRMi5Td54ElgHzNrC6/7kLt3u/sm4CFgQvheP3dfGLZOboqcK9NyW7hMuX8Kv/rzr+pSh1zrZOjNN7HvKSfXpQ7Vim7Bv+ilbqbftVQBIy2h2Nb3AJs3b2bQoEGcf/75qVw/1iwud1+TezhX6N0Kr3egu68Lz7nOzA4IywcBayLHdYVlxcq78pRnWr0e5tWIA/LV0pRkaVWFtr4fOnQoAN/5znf41Kc+ldr144TKGjM7CnAz6wN8BViecD0sT5lXUJ7/5GZTCbrKGDKksj8mowamvy7lPVu41HDQvhEH5JOkKcnSavJtfQ+wePFi1q9fz4QJE+js7Ezl2nFC5T8JBtFzrYMHgfMqvN56M2sLWyltwGtheRcwOHJcO8H2+l3A0T3KF4Tl7XmOz8vdZwGzADo6OioazJ/xudGVfCyQgYdvNfKAfJI0JVlq5S8//CFvL0926/vdDh3JQdOnlzwu39b327Zt45vf/CY333wzDz/8cKL1iooz++t14N8Tut49wFnAzPD73ZHy881sHsGg/N/C4HkA+GFkcP4zwLfcvdvMtpjZEcAi4Ezg6oTqmLwKH76V5hb5zdjlFYd2SJZW0XPr+2uuuYaJEycyePDg0h+uQsFQMbOrKdKl5O5fKXbi8LkrRwP7mVkXwSyumcAdZnY28AqQ+ys5n2A68SqCKcVTwmt0m9n3gafD4y5x99zg/7nsmFJ8X/jVuMqcRpz2+Eqzd3nFoXEXSVOcFkVa8m19v3DhQh5//HGuueYa3njjDbZu3cpee+3FzJkzE722FVraEa4PKSi3XiRrOjo6PK2+xIJmHxd8r3BtSq61MnvC7KqqkaU1KPWUG3fJzR5Tq0XiWr58OYceemhd6+DuHHXUUVxyySUcc8wxXH311Tz55JPccsst24+ZM2cOnZ2d/PznP897jnz3YWaL3b2j1PULtlR6hoaZ7R0Ux18AKY1FrZN4NO4iWVZo6/tHH3001VlfOQVbKtsPMBsD3Az0J5h1tQE4092fT712KchqS2Vl90oO6X8IUPn4yuozzgRQ66QMPcddAMYP7w8oYGRnjdBSSUIqLZWIWcA33P2R8MRHA9cDR5VfValENeMrrTognxSNu4iUJ06o7JkLFAB3X2Bme6ZYp+aQ4DTiatavqMsrOVrvIlJanFB50cy+Q9AFBvAF4KX0qtQkKpxGHEe5U401IJ88jbuI5BcnVL4EfA/4DcGYymOEU36lhBR2I47TFaYur/RpvYsU4u702NYqU6rd7D3O4sdNBFuzSAOI0xWmLq/aUsBITt++fdm4cSMDBgzIZLC4Oxs3bqRv374Vn6PY4sd7Slz88xVfVRJTqCtMXV71oYH91tbe3k5XVxcbNmyod1Uq1rdvX9rb20sfWECxlsqRBDsE30awFUr2YrfJRbvCDnzoWfqteJ7V/X+nLq8GoYH91tO7d2+GDx9e72rUVbFQOQg4BjgNOB34PXBbVtenNKNoV9gDVx/Ofl1vsIIVcAD0+mgbQ+tcP9mh2MB+7n2FjDSDYivq3wXuB+43s90IwmWBmV3i7o27eWOLGrD7AF5vh3kXjA4XSr7Gv9W7UrJdsUcfa+xFmknRgfowTI4jCJRhwM8IZoFJPjXe4j46y2vv1RvZf+RIZk+YXdNnsUj5ogEDGtyX5lJsoH4uMIZg99/vuftzNatVVqW4NiWfYrO80tw2X5Kl2WPSTIrtUrwN+Hv4MnqQEWwsmf6jEFOQ6t5fVe7xVa5Ce3n96s+/Yv6L8wHoXB/ca8eBwZY9Cpjs0L5j0kiS2KV4l2SrJLUSHcCPBkwtn3sv1VMLRrIozop6aSDlrpbvuVhS3WLZpPUvkhUKlYypZrV82k+TlNrQ+hdpZAqVDKp0tbxaLc1HG1tKo1GoZEAaG0RGWy2d6zvpXN+5fexFAZMdccddohQ2kiaFSgaksUGkBvObT7EFljkag5G0lXyccLNJfEpxvgWPCU8pruVjgJN6dLE0ptwYzKi2YEWAWi0SV5KPE5ZiUlrwWK9noqhbrLlpDEbSppZKtVJa8Lj6jDPfEyb9jj+efU85OdFrlNKzW+yQ/ocwe8LsmtZB0qPFlVKOuC0VhUq1UgwVqE2XVxw9u8V6Uism24oFTE8KnNak7i9JVLRbrCd1k2VfnEF+UJeZlKaWSrUSbKnkG0dplJZKMdprrHWoy6x1qfurgEYOlUYYR6mWAqZ1KGBai0KlgEYPFWiccZRqFQuYKIVN9ilgmp/GVKTuCi2wjNJ4THPQjsqSo5ZKtapoqUTHUCBb4yhJUXdZc4s7q0xh0/jU/VVAI4VKzzEUyOY4SlIUMM2t0KwydZdlQ0OHipm9DGwB3gXecfcOM+sP3A4MA14GTnb3TWZmwFXAROBN4Ivu/kx4nrOAb4envdTd55a6diKhktDWLM02hpIkjce0DrVmsiELodLh7q9Hyn4MdLv7TDObBuzr7heb2UTgAoJQGQ9c5e7jwxDqBDoIHne8GBjn7puKXTuRUJl93I4wgWBrlo4pZZ9GoRJPsfEYUGummag107iyGCorgaPdfZ2ZtQEL3P0QM7su/Pm26HG5L3c/Jyx/z3GFJBYqUPU4SiuOoSQpbmsGFDhZp9ll9dfos78ceNDMHLjO3WcBB7r7OoAwWA4Ijx0ErIl8tissK1S+EzObCkwFGDKkvv/xpbGNfauKM7sMdp5hFqWwyYZynhujkKmveoXKx9x9bRgcD5nZiiLHWp4yL1K+c2EQWrMgaKmUW9mkqXWSvGjA9BR3OnMhCp7GUmxLGU1hrr+6hIq7rw2/v2ZmdwGHA+vNrC3S/fVaeHgXMDjy8XZgbVh+dI/yBSlXXTKoUOAUa93kaB1NY4sGDOjpl42g5qFiZnsCu7j7lvDnzwCXAPcAZwEzw+93hx+5BzjfzOYRDNT/LQyeB4Afmtm+4XGfAb5Vw1uRjCvWusnpOW6jlk1ji7Mxploz6apHS+VA4K5gpjC7Are6+/1m9jRwh5mdDbwC5P5VzieY+bWKYErxFAB37zaz7wNPh8dd4u7dtbuN+Or1wC2pXtxxmxyN3zSOnq2YHLVm0qXFj5Uoc/ZXM2wUKfHEnf7ckwKnPuJOYY5q1bBp6CnF9VSvUAGtR2llpWanQeHAyVHw1I7Wy+ys0acUi7SUSmanRalbrbbUdVY5hYpInZU7YSBKYVNblUwE6KnZA0fdX5WI0f2llfNSC5WM4Shs0lXqccyQze4zjakUUHGolLmJpAbnpZ4qnTCQo+BJR5Y3z1SoFFBxqJS5iaQG56URxR2/Ac1US1vWZp4pVAqoKlRAM76k6VU6U01hk4xGDRvN/hKRimgftfqKM/MsqtF2CFBLJS4NzosUVG23msKmcnHHaUYN7MeMz42u+DpqqdSBtrWXVqVp0fUTZ5pzLamlEleMlgL1TEQAAAY5SURBVIrGUUTKp5lq2aCWiohkQpKPJqiEQilZChURaUjVdKnFpa635ClUqqRt7UXqJ07wFKNxnuQpVKqkwXmR7Cq3601Tp0tTqCRAU4dFmkutxnmaMXwUKiIiMSU5ztOsrR6FiohIguKO89Ridls9AkmhElduI0kRkQSkPbutZyCN7D+Siw+/uKJzlUOhEtexM7f/qBlfIlIL1cxuq3a6daUUKhXQjC8RaXTVTreulEKlQprxJSKys13qXQEREWkeChUREUmMQkVERBKjUBERkcRooD4mTSMWESlNLZWYctOIAU0jFhEpQC2VMmgasYhIcWqpiIhIYhQqIiKSmMyHiplNMLOVZrbKzKbVuz4iIq0s06FiZr2AXwDHAqOA08xsVH1rJSLSujIdKsDhwCp3f9HdtwLzgEl1rpOISMvK+uyvQcCayOsuYHzPg8xsKjAVYMiQIRVdaLdDtS5FRKSUrIeK5SnznQrcZwGzADo6OnZ6P46Dpk+v5GMiIi0l691fXcDgyOt2YG2d6iIi0vKyHipPAyPMbLiZ9QFOBe6pc51ERFpWpru/3P0dMzsfeADoBdzo7s/XuVoiIi0r06EC4O7zgdo/iFlERHaS9e4vERFpIAoVERFJjEJFREQSo1AREZHEmHtFawEzy8w2AKsr/Ph+wOsJVidLWvneobXvv5XvHVr7/qP3PtTd9y/1gZYLlWqYWae7d9S7HvXQyvcOrX3/rXzv0Nr3X8m9q/tLREQSo1AREZHEKFTKM6veFaijVr53aO37b+V7h9a+/7LvXWMqIiKSGLVUREQkMQoVERFJjEIlBjObYGYrzWyVmU2rd31qzcxeNrOlZrbEzDrrXZ+0mdmNZvaamT0XKetvZg+Z2Qvh933rWce0FLj375rZq+Hvf4mZTaxnHdNiZoPN7BEzW25mz5vZV8Pypv/dF7n3sn/3GlMpwcx6AX8GjiF4KNjTwGnuvqyuFashM3sZ6HD3llgAZmafBN4AbnL3MWHZj4Fud58Z/h+Lfd394nrWMw0F7v27wBvu/l/1rFvazKwNaHP3Z8xsb2AxcALwRZr8d1/k3k+mzN+9WiqlHQ6scvcX3X0rMA+YVOc6SYrc/TGgu0fxJGBu+PNcgn9wTafAvbcEd1/n7s+EP28BlgODaIHffZF7L5tCpbRBwJrI6y4q/B87wxx40MwWm9nUelemTg5093UQ/AMEDqhzfWrtfDN7Nuwea7run57MbBjwYWARLfa773HvUObvXqFSmuUpa7U+w4+5+0eAY4Hzwi4SaR3XAgcDY4F1wE/qW510mdlewJ3A19x9c73rU0t57r3s371CpbQuYHDkdTuwtk51qQt3Xxt+fw24i6BLsNWsD/udc/3Pr9W5PjXj7uvd/V133wZcTxP//s2sN8Ef1Vvc/TdhcUv87vPdeyW/e4VKaU8DI8xsuJn1AU4F7qlznWrGzPYMB+4wsz2BzwDPFf9UU7oHOCv8+Szg7jrWpaZyf1BDJ9Kkv38zM+AGYLm7XxF5q+l/94XuvZLfvWZ/xRBOo7sS6AXc6O4/qHOVasbM3k/QOgHYFbi12e/fzG4DjibY9ns9MAP4LXAHMAR4BZjs7k03oF3g3o8m6P5w4GXgnNwYQzMxs48DjwNLgW1h8XSCsYWm/t0XuffTKPN3r1AREZHEqPtLREQSo1AREZHEKFRERCQxChUREUmMQkVERBKjUBFJkZntY2ZfDn8eaGa/rnedRNKkKcUiKQr3Ubo3t+OvSLPbtd4VEGlyM4GDzWwJ8AJwqLuPMbMvEux22wsYQ7CnUh/gDOBtYKK7d5vZwcAvgP2BN4H/cPcVtb8NkXjU/SWSrmnA/3P3scBFPd4bA5xOsJ/SD4A33f3DwELgzPCYWcAF7j4OuBC4pia1FqmQWioi9fNI+OyKLWb2N+B3YflS4IPhjrFHAb8KtmYCYLfaV1MkPoWKSP28Hfl5W+T1NoJ/m7sAfw1bOSKZoO4vkXRtAfau5IPh8yxeMrPJEOwka2YfSrJyIklTqIikyN03An8ws+eAyys4xb8DZ5vZn4Dn0aOspcFpSrGIiCRGLRUREUmMQkVERBKjUBERkcQoVEREJDEKFRERSYxCRUREEqNQERGRxPx/W0deu+iMt3QAAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot_output(values_exact)\n" + ] + }, + { + "cell_type": "code", + "execution_count": 33, + "metadata": {}, + "outputs": [], + "source": [ + "def mc_estimate_approx(n,tau):\n", + " return sum([model.simulate(k, times, approx=True, approx_tau=tau) for i in range(n)])/n" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "def mse(r1,r2):\n", + " return np.square(r1 - r2).mean()" + ] + }, + { + "cell_type": "code", + "execution_count": 23, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "2.17 s ± 167 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "%timeit model.simulate(k, times)" + ] + }, + { + "cell_type": "code", + "execution_count": 35, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "43.9 ms ± 793 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" + ] + } + ], + "source": [ + "%timeit model.simulate(k, times, approx=True, approx_tau=0.0125)" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": {}, + "outputs": [], + "source": [ + "empirical_mean = sum([model.simulate(k, times) for i in range(30)])/30" + ] + }, + { + "cell_type": "code", + "execution_count": 34, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plot_output(empirical_mean)" + ] + }, + { + "cell_type": "code", + "execution_count": 37, + "metadata": {}, + "outputs": [], + "source": [ + "exact_mse = 0\n", + "for i in range(25):\n", + " exact = model.simulate(k, times)\n", + " exact_mse += mse(exact, empirical_mean)/25" + ] + }, + { + "cell_type": "code", + "execution_count": 38, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Running for tau = 0.0125\n", + "Running for tau = 0.025\n", + "Running for tau = 0.05\n", + "Running for tau = 0.1\n", + "Running for tau = 0.25\n", + "Running for tau = 0.5\n", + "Running for tau = 1\n" + ] + } + ], + "source": [ + "taus = [0.0125, 0.025, 0.05, 0.1, 0.25, 0.5, 1]\n", + "approx_mses = []\n", + "for tau in taus:\n", + " amse=0\n", + " print(\"Running for tau = \" + str(tau))\n", + " for i in range(1000):\n", + " sim = model.simulate(k, times, approx=True, approx_tau=tau)\n", + " amse += mse(empirical_mean, sim)/1000\n", + " approx_mses.append(amse)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + }, + { + "cell_type": "code", + "execution_count": 46, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 46, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot([0]+taus[:4], [exact_mse]+approx_mses[:4], 'bo')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "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.4" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/toy-model-schlogl.ipynb b/examples/toy-model-schlogl.ipynb new file mode 100644 index 000000000..3abfb724b --- /dev/null +++ b/examples/toy-model-schlogl.ipynb @@ -0,0 +1,238 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Schlögl" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- A + 2X -> 3X, rate k1\n", + "- 3X -> A+2X, rate k2\n", + "- B -> X, rate k3\n", + "- X -> B, rate k4" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import pints\n", + "import pints.toy.stochastic\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import math" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "import line_profiler" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "x_0 = 250\n", + "\n", + "model = pints.toy.stochastic.SchloglModel(x_0)\n", + "\n", + "times = np.linspace(0, 5, 100)\n", + "k = [3e-7, 1e-4, 1e-3, 3.5]\n", + "\n", + "valuess = [model.simulate(k, times, approx=True, approx_tau=0.0125) for i in range(10000)]" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "380 ms ± 56.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "%timeit model.simulate(k, times)" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "16.3 ms ± 565 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" + ] + } + ], + "source": [ + "%timeit model.simulate(k, times, approx=True, approx_tau=0.0125)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "for values in valuess:\n", + " plt.step(times, values)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [], + "source": [ + "valuess = np.array(valuess)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "No handles with labels found to put in legend.\n" + ] + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.hist(valuess[:,-1])\n", + "plt.legend()\n", + "plt.xlabel('X')\n", + "plt.ylabel('Probability')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Given the stochastic nature of this model, every iteration returns a different result. However, averaging the concentration values at each time step, produces a reproducible result which tends towards a deterministic function as the the number of iterations tends to infinity (Erban et al., 2007): $ n_0e^{-kt} $\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "N = 100\n", + "average = np.zeros(len(times))\n", + "for i in range(N):\n", + " values = np.asarray(model.simulate(k, times))[0,:]\n", + " average += (values/N)\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "average.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "plt.plot(times, average, label = 'deterministic mean of A(t)')\n", + "plt.title('stochastic degradation across different iterations')\n", + "plt.xlabel('time')\n", + "plt.ylabel('concentration (A(t))')\n", + "plt.legend(loc = 'upper right')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The deterministic mean (from above) is plotted with the deterministic standard deviation. \n", + "The deterministic variance of this model is given by: $e^{-2kt}(-1 + e^{kt})n_0$" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mean = model.mean(k, times)\n", + "variance = model.variance(k, times)\n", + "std_dev = np.sqrt(variance)\n", + "\n", + "plt.plot(times, mean, '-', label = 'deterministic mean of A(t)')\n", + "plt.plot(times, mean + std_dev, '--', label = 'standard deviation upper bound')\n", + "plt.plot(times, mean - std_dev, '--', label = 'standard deviation lower bound')\n", + "plt.legend(loc = 'upper right')\n", + "plt.xlabel('time')\n", + "plt.ylabel('concentration (A(t))')\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.4" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/pints/tests/test_toy_stochastic_degradation_model.py b/pints/tests/test_toy_stochastic_degradation_model.py index 4e00cf74a..d5f5217fd 100755 --- a/pints/tests/test_toy_stochastic_degradation_model.py +++ b/pints/tests/test_toy_stochastic_degradation_model.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # -# Tests if the stochastic degradation (toy) model works. +# Tests if the degradation (toy) model works. # # This file is part of PINTS. # Copyright (c) 2017-2019, University of Oxford. @@ -11,16 +11,16 @@ import numpy as np import pints import pints.toy -from pints.toy import StochasticDegradationModel +from pints.toy. import DegradationModel -class TestStochasticDegradation(unittest.TestCase): +class TestDegradation(unittest.TestCase): """ - Tests if the stochastic degradation (toy) model works. + Tests if the degradation (toy) model works. """ def test_start_with_zero(self): # Test the special case where the initial molecule count is zero - model = StochasticDegradationModel(0) + model = DegradationModel(0) times = [0, 1, 2, 100, 1000] parameters = [0.1] values = model.simulate(parameters, times) @@ -29,7 +29,7 @@ def test_start_with_zero(self): def test_start_with_twenty(self): # Run small simulation - model = pints.toy.StochasticDegradationModel(20) + model = pints.toy.DegradationModel(20) times = [0, 1, 2, 100, 1000] parameters = [0.1] values = model.simulate(parameters, times) @@ -39,7 +39,7 @@ def test_start_with_twenty(self): self.assertTrue(np.all(values[1:] <= values[:-1])) def test_suggested(self): - model = pints.toy.StochasticDegradationModel(20) + model = pints.toy.DegradationModel(20) times = model.suggested_times() parameters = model.suggested_parameters() self.assertTrue(len(times) == 101) @@ -47,7 +47,7 @@ def test_suggested(self): def test_simulate(self): times = np.linspace(0, 100, 101) - model = StochasticDegradationModel(20) + model = DegradationModel(20) time, mol_count = model.simulate_raw([0.1]) values = model.interpolate_mol_counts(time, mol_count, times) self.assertTrue(len(time), len(mol_count)) @@ -68,27 +68,27 @@ def test_simulate(self): def test_mean_variance(self): # test mean - model = pints.toy.StochasticDegradationModel(10) + model = pints.toy.DegradationModel(10) v_mean = model.mean([1], [5, 10]) self.assertEqual(v_mean[0], 10 * np.exp(-5)) self.assertEqual(v_mean[1], 10 * np.exp(-10)) - model = pints.toy.StochasticDegradationModel(20) + model = pints.toy.DegradationModel(20) v_mean = model.mean([5], [7.2]) self.assertEqual(v_mean[0], 20 * np.exp(-7.2 * 5)) # test variance - model = pints.toy.StochasticDegradationModel(10) + model = pints.toy.DegradationModel(10) v_var = model.variance([1], [5, 10]) self.assertEqual(v_var[0], 10 * (np.exp(5) - 1.0) / np.exp(10)) self.assertAlmostEqual(v_var[1], 10 * (np.exp(10) - 1.0) / np.exp(20)) - model = pints.toy.StochasticDegradationModel(20) + model = pints.toy.DegradationModel(20) v_var = model.variance([2.0], [2.0]) self.assertAlmostEqual(v_var[0], 20 * (np.exp(4) - 1.0) / np.exp(8)) def test_errors(self): - model = pints.toy.StochasticDegradationModel(20) + model = pints.toy.DegradationModel(20) # parameters, times cannot be negative times = np.linspace(0, 100, 101) parameters = [-0.1] @@ -109,7 +109,7 @@ def test_errors(self): self.assertRaises(ValueError, model.variance, parameters_3, times) # Initial value can't be negative - self.assertRaises(ValueError, pints.toy.StochasticDegradationModel, -1) + self.assertRaises(ValueError, pints.toy.DegradationModel, -1) if __name__ == '__main__': diff --git a/pints/toy/__init__.py b/pints/toy/__init__.py index b8ad8b3f9..b6d52a421 100644 --- a/pints/toy/__init__.py +++ b/pints/toy/__init__.py @@ -33,4 +33,3 @@ from ._simple_egg_box import SimpleEggBoxLogPDF # noqa from ._sir_model import SIRModel # noqa from ._twisted_gaussian_banana import TwistedGaussianLogPDF # noqa -from ._stochastic_degradation_model import StochasticDegradationModel # noqa diff --git a/pints/toy/stochastic/__init__.py b/pints/toy/stochastic/__init__.py new file mode 100644 index 000000000..2e71b8f82 --- /dev/null +++ b/pints/toy/stochastic/__init__.py @@ -0,0 +1,16 @@ +# +# Root of the toy module. +# Provides a number of toy models and logpdfs for tests of Pints' functions. +# +# This file is part of PINTS. +# Copyright (c) 2017-2019, University of Oxford. +# For licensing information, see the LICENSE file distributed with the PINTS +# software package. +# +from __future__ import absolute_import, division +from __future__ import print_function, unicode_literals + +from ._degradation_model import DegradationModel # noqa +from ._markov_jump_model import MarkovJumpModel # noqa +from ._michaelis_menten_model import MichaelisMentenModel # noqa +from ._schlogl_model import SchloglModel \ No newline at end of file diff --git a/pints/toy/_stochastic_degradation_model.py b/pints/toy/stochastic/_degradation_model.py similarity index 97% rename from pints/toy/_stochastic_degradation_model.py rename to pints/toy/stochastic/_degradation_model.py index 2041962ab..97a2044dc 100644 --- a/pints/toy/_stochastic_degradation_model.py +++ b/pints/toy/stochastic/_degradation_model.py @@ -12,10 +12,10 @@ from scipy.interpolate import interp1d import pints -from . import ToyModel +from .. import ToyModel -class StochasticDegradationModel(pints.ForwardModel, ToyModel): +class DegradationModel(pints.ForwardModel, ToyModel): r""" Stochastic degradation model of a single chemical reaction starting from an initial molecule count :math:`A(0)` and degrading to 0 with a fixed rate @@ -65,7 +65,7 @@ class StochasticDegradationModel(pints.ForwardModel, ToyModel): https://doi.org/10.1016/0021-9991(76)90041-3 """ def __init__(self, initial_molecule_count=20): - super(StochasticDegradationModel, self).__init__() + super(DegradationModel, self).__init__() self._n0 = float(initial_molecule_count) if self._n0 < 0: raise ValueError('Initial molecule count cannot be negative.') diff --git a/pints/toy/stochastic/_markov_jump_model.py b/pints/toy/stochastic/_markov_jump_model.py new file mode 100644 index 000000000..a539be4eb --- /dev/null +++ b/pints/toy/stochastic/_markov_jump_model.py @@ -0,0 +1,187 @@ +# +# Stochastic degradation toy model. +# +# This file is part of PINTS. +# Copyright (c) 2017-2019, University of Oxford. +# For licensing information, see the LICENSE file distributed with the PINTS +# software package. +# +from __future__ import absolute_import, division +from __future__ import print_function, unicode_literals +import numpy as np +import math +from scipy.interpolate import interp1d +import scipy +import pints + +from .. import ToyModel + + +class MarkovJumpModel(pints.ForwardModel, ToyModel): + r""" + A general purpose Markov Jump model used for any systems of reactions + that proceed through jumps. We simulate a population of N different species, + reacting through M different mechanisms. + + A model has three parameters: + - x_0 - an N-vector specifying the initial population of each fo the N species + - V - an NxM matrix consisting of stochiometric vectors v_i specifying + the changes to the state, x, from reaction i taking place + - a - a function from the current state, x, and reaction rates, k, + to a vector of the rates of each reaction taking place + + Simulations are performed using Gillespie's algorithm [1]_, [2]_: + + 1. Sample values :math:`r_0`, :math:`r_1`, from a uniform distribution + + .. math:: + r_0, r_1 \sim U(0,1) + + 2. Calculate the time :math:`\tau` until the next single reaction as + + .. math:: + \tau = \frac{-\ln(r)}{a_0} + + 3. Decide which reaction, i, takes place using r_1*a_0 and iterating through + propensities + + 4. Update the state :math:`x` at time :math:`t + \tau` as: + + .. math:: + x(t + \tau) = x(t) + V[i] + + 4. Return to step (1) until no reaction can take place + + The model has one parameter, the rate constant :math:`k`. + + Extends :class:`pints.ForwardModel`, :class:`pints.toy.ToyModel`. + + Parameters + ---------- + initial_molecule_count + The initial molecule count :math:`A(0)`. + + References + ---------- + .. [1] A Practical Guide to Stochastic Simulations of Reaction Diffusion + Processes. Erban, Chapman, Maini (2007). + arXiv:0704.1908v2 [q-bio.SC] + https://arxiv.org/abs/0704.1908 + + .. [2] A general method for numerically simulating the stochastic time + evolution of coupled chemical reactions. Gillespie (1976). + Journal of Computational Physics + https://doi.org/10.1016/0021-9991(76)90041-3 + """ + def __init__(self, x0, V, a): + super(MarkovJumpModel, self).__init__() + self._x0 = np.asarray(x0) + self._V = V + self._a = a + if any(self._x0 < 0): + raise ValueError('Initial molecule count cannot be negative.') + + def n_parameters(self): + """ See :meth:`pints.ForwardModel.n_parameters()`. """ + return len(self._v) + + def simulate_raw(self, rates, max_time): + """ + Returns raw times, mol counts when reactions occur + """ + # parameters = np.asarray(parameters) + # if len(parameters) != self.n_parameters(): + # raise ValueError('This model should have only 1 parameter.') + # k = parameters[0] + + current_rates = self._a(self._x0, rates) + a_0 = sum(current_rates) + + # Initial time and count + t = 0 + x = np.array(self._x0) + + # Run gillespie SSA, calculating time until next + # reaction, deciding which reaction, and applying it + mol_count = [np.array(x)] + time = [t] + while a_0 > 0 and t <= max_time: + r_1, r_2 = np.random.uniform(0, 1, 2) + t += -np.log(r_1) / (a_0) + s = 0 + r = 0 + while s <= r_2 * a_0: + s += current_rates[r] + r+=1 + r-=1 + x = np.add(x, self._V[r]) + + current_rates = self._a(x, rates) + a_0 = sum(current_rates) + + time.append(t) + mol_count.append(np.array(x)) + return time, mol_count + + def simulate_approx(self, rates, max_time, tau): + assert tau > 0, "cannot tau-leap with negative tau" + current_rates = np.array(self._a(self._x0, rates)) + # Initial time and count + t = 0 + x = self._x0.copy() + N = len(rates) + # Run gillespie SSA, calculating time until next + # reaction, deciding which reaction, and applying it + mol_count = [x.copy()] + time = [t] + while any(current_rates > 0) and t <= max_time: + # Estimate number of each reaction in [t, t+tau) + k = [np.random.poisson(current_rates[i]*tau) for i in range(N)] + + # Apply the reactions + for r in range(N): + x += np.array(self._V[r])*k[r] + + # Update rates + current_rates = np.array(self._a(x, rates)) + + # Advance Time + t += tau + time.append(t) + mol_count.append(x.copy()) + return time, mol_count + + def interpolate_mol_counts(self, time, mol_count, output_times): + """ + Takes raw times and inputs and mol counts and outputs interpolated + values at output_times + """ + # Interpolate as step function, decreasing mol_count by 1 at each + # reaction time point + interp_func = interp1d(time, mol_count, kind='previous', axis=0, + fill_value="extrapolate", bounds_error=False) + + # Compute molecule count values at given time points using f1 + # at any time beyond the last reaction, molecule count = 0 + values = interp_func(output_times) + return values + + + def simulate(self, parameters, times, approx=False, approx_tau=None): + """ See :meth:`pints.ForwardModel.simulate()`. """ + times = np.asarray(times) + if np.any(times < 0): + raise ValueError('Negative times are not allowed.') + if not approx: + # run Gillespie + time, mol_count = self.simulate_raw(parameters, max(times)) + else: + if (not approx_tau) or approx_tau <= 0: + ValueError("You must provide a positive value for approx_tau\ + to use tau-leaping approximation") + # Run Euler tau-leaping + time, mol_count = self.simulate_approx(parameters, max(times), approx_tau) + # interpolate + values = self.interpolate_mol_counts(np.asarray(time), np.asarray(mol_count), times) + return values + diff --git a/pints/toy/stochastic/_michaelis_menten_model.py b/pints/toy/stochastic/_michaelis_menten_model.py new file mode 100644 index 000000000..19a981824 --- /dev/null +++ b/pints/toy/stochastic/_michaelis_menten_model.py @@ -0,0 +1,44 @@ +# +# Stochastic degradation toy model. +# +# This file is part of PINTS. +# Copyright (c) 2017-2019, University of Oxford. +# For licensing information, see the LICENSE file distributed with the PINTS +# software package. +# +from __future__ import absolute_import, division +from __future__ import print_function, unicode_literals +import numpy as np +from scipy.interpolate import interp1d +import pints + +from . import MarkovJumpModel + + +class MichaelisMentenModel(MarkovJumpModel): + r""" + Simulates the Michaelis Menten Dynamics using Gillespie. + + This system of reaction involved 4 chemical species with + inital counts x_0, and reactions: + - X1+X2 -> X3 with rate k1 + - X3 -> X1+X2 with rate k2 + - X3 -> X2+X4 with rate k3 + """ + def __init__(self, x_0): + mat = [[-1, -1, 1, 0], + [ 1, 1, -1, 0], + [ 0, 1, -1, 1]] + super(MichaelisMentenModel, self).__init__(x_0, mat, self._propensities) + + @staticmethod + def _propensities(xs,ks): + return [ + xs[0]*xs[1]*ks[0], + xs[2]*ks[1], + xs[2]*ks[2] + ] + + def n_parameters(self): + """ See :meth:`pints.ForwardModel.n_parameters()`. """ + return 3 diff --git a/pints/toy/stochastic/_schlogl_model.py b/pints/toy/stochastic/_schlogl_model.py new file mode 100644 index 000000000..c66ab92db --- /dev/null +++ b/pints/toy/stochastic/_schlogl_model.py @@ -0,0 +1,56 @@ +# +# Stochastic Schlogl toy model. +# +# This file is part of PINTS. +# Copyright (c) 2017-2019, University of Oxford. +# For licensing information, see the LICENSE file distributed with the PINTS +# software package. +# +from __future__ import absolute_import, division +from __future__ import print_function, unicode_literals +import numpy as np +from scipy.interpolate import interp1d +import pints + +from . import MarkovJumpModel + + +class SchloglModel(MarkovJumpModel): + r""" + Simulates the Schlögl System using Gillespie. + + This system of reaction involved 4 chemical species with + inital counts x_0, and reactions: + - A + 2X -> 3X, rate k1 + - 3X -> A+2X, rate k2 + - B -> X, rate k3 + - X -> B, rate k4 + """ + def __init__(self, x_0): + self.a_count = 1e5 + self.b_count = 2e5 + # We are only concered with the change in X concentration + mat = [[ 1], + [-1], + [ 1], + [-1]] + super(SchloglModel, self).__init__([x_0], mat, self._propensities) + + def simulate(self, parameters, times, approx=None, approx_tau=None): + return super(SchloglModel, self).simulate(parameters, times, approx, approx_tau)[:,0] + + r""" + Calculate the rates of reaction based on molecular availability + xs is of the form [A, B, X] + """ + def _propensities(self, xs, ks): + return [ + self.a_count*xs[0]*(xs[0]-1)*ks[0], + xs[0]*(xs[0]-1)*(xs[0]-2)*ks[1], + self.b_count*ks[2], + xs[0]*ks[3] + ] + + def n_parameters(self): + """ See :meth:`pints.ForwardModel.n_parameters()`. """ + return 4 From 4f5068fe35bf9d35e49a798a78a10c00854aebb1 Mon Sep 17 00:00:00 2001 From: Jack Arthur Date: Sun, 15 Mar 2020 13:11:39 +0000 Subject: [PATCH 2/3] Code style fixes --- examples/toy-model-michaelis-menten.ipynb | 126 +++++------------- .../test_toy_stochastic_degradation_model.py | 2 +- pints/toy/stochastic/__init__.py | 2 +- pints/toy/stochastic/_markov_jump_model.py | 42 +++--- .../toy/stochastic/_michaelis_menten_model.py | 24 ++-- pints/toy/stochastic/_schlogl_model.py | 24 ++-- 6 files changed, 80 insertions(+), 140 deletions(-) diff --git a/examples/toy-model-michaelis-menten.ipynb b/examples/toy-model-michaelis-menten.ipynb index f6a15147d..0c9ed5cc0 100644 --- a/examples/toy-model-michaelis-menten.ipynb +++ b/examples/toy-model-michaelis-menten.ipynb @@ -13,7 +13,7 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": 2, "metadata": {}, "outputs": [], "source": [ @@ -26,7 +26,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 3, "metadata": {}, "outputs": [], "source": [ @@ -42,7 +42,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 4, "metadata": {}, "outputs": [], "source": [ @@ -57,12 +57,12 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": 5, "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -93,7 +93,7 @@ }, { "cell_type": "code", - "execution_count": 24, + "execution_count": 6, "metadata": {}, "outputs": [], "source": [ @@ -103,7 +103,7 @@ }, { "cell_type": "code", - "execution_count": 39, + "execution_count": 7, "metadata": {}, "outputs": [], "source": [ @@ -120,12 +120,12 @@ }, { "cell_type": "code", - "execution_count": 40, + "execution_count": 8, "metadata": {}, "outputs": [ { "data": { - "image/png": "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\n", + "image/png": "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\n", "text/plain": [ "
" ] @@ -142,7 +142,7 @@ }, { "cell_type": "code", - "execution_count": 33, + "execution_count": 9, "metadata": {}, "outputs": [], "source": [ @@ -152,7 +152,7 @@ }, { "cell_type": "code", - "execution_count": 17, + "execution_count": 10, "metadata": {}, "outputs": [], "source": [ @@ -162,14 +162,27 @@ }, { "cell_type": "code", - "execution_count": 23, + "execution_count": 11, "metadata": {}, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "2.17 s ± 167 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + "ename": "KeyboardInterrupt", + "evalue": "", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mKeyboardInterrupt\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mget_ipython\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrun_line_magic\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m'timeit'\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m'model.simulate(k, times)'\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m/opt/anaconda3/lib/python3.7/site-packages/IPython/core/interactiveshell.py\u001b[0m in \u001b[0;36mrun_line_magic\u001b[0;34m(self, magic_name, line, _stack_depth)\u001b[0m\n\u001b[1;32m 2312\u001b[0m \u001b[0mkwargs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;34m'local_ns'\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msys\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_getframe\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstack_depth\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mf_locals\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2313\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mbuiltin_trap\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 2314\u001b[0;31m \u001b[0mresult\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfn\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2315\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mresult\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2316\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mtimeit\u001b[0;34m(self, line, cell, local_ns)\u001b[0m\n", + "\u001b[0;32m/opt/anaconda3/lib/python3.7/site-packages/IPython/core/magic.py\u001b[0m in \u001b[0;36m\u001b[0;34m(f, *a, **k)\u001b[0m\n\u001b[1;32m 185\u001b[0m \u001b[0;31m# but it's overkill for just that one bit of state.\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 186\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmagic_deco\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 187\u001b[0;31m \u001b[0mcall\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;32mlambda\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0mf\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mk\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 188\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 189\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mcallable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0marg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/opt/anaconda3/lib/python3.7/site-packages/IPython/core/magics/execution.py\u001b[0m in \u001b[0;36mtimeit\u001b[0;34m(self, line, cell, local_ns)\u001b[0m\n\u001b[1;32m 1160\u001b[0m \u001b[0;32mbreak\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1161\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m-> 1162\u001b[0;31m \u001b[0mall_runs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtimer\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrepeat\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrepeat\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mnumber\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 1163\u001b[0m \u001b[0mbest\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmin\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mall_runs\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0mnumber\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 1164\u001b[0m \u001b[0mworst\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mmax\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mall_runs\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0mnumber\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/opt/anaconda3/lib/python3.7/timeit.py\u001b[0m in \u001b[0;36mrepeat\u001b[0;34m(self, repeat, number)\u001b[0m\n\u001b[1;32m 202\u001b[0m \u001b[0mr\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 203\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0mrange\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mrepeat\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 204\u001b[0;31m \u001b[0mt\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtimeit\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mnumber\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 205\u001b[0m \u001b[0mr\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mappend\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 206\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mr\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/opt/anaconda3/lib/python3.7/site-packages/IPython/core/magics/execution.py\u001b[0m in \u001b[0;36mtimeit\u001b[0;34m(self, number)\u001b[0m\n\u001b[1;32m 167\u001b[0m \u001b[0mgc\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdisable\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 168\u001b[0m \u001b[0;32mtry\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 169\u001b[0;31m \u001b[0mtiming\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0minner\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mit\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mtimer\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 170\u001b[0m \u001b[0;32mfinally\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 171\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mgcold\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36minner\u001b[0;34m(_it, _timer)\u001b[0m\n", + "\u001b[0;32m/opt/anaconda3/lib/python3.7/site-packages/pints/toy/stochastic/_markov_jump_model.py\u001b[0m in \u001b[0;36msimulate\u001b[0;34m(self, parameters, times, approx, approx_tau)\u001b[0m\n\u001b[1;32m 175\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mapprox\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 176\u001b[0m \u001b[0;31m# run Gillespie\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 177\u001b[0;31m \u001b[0mtime\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmol_count\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mself\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msimulate_raw\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mparameters\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mmax\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mtimes\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 178\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 179\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0;32mnot\u001b[0m \u001b[0mapprox_tau\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mor\u001b[0m \u001b[0mapprox_tau\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/opt/anaconda3/lib/python3.7/site-packages/pints/toy/stochastic/_markov_jump_model.py\u001b[0m in \u001b[0;36msimulate_raw\u001b[0;34m(self, rates, max_time)\u001b[0m\n\u001b[1;32m 107\u001b[0m \u001b[0mtime\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;34m[\u001b[0m\u001b[0mt\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 108\u001b[0m \u001b[0;32mwhile\u001b[0m \u001b[0ma_0\u001b[0m \u001b[0;34m>\u001b[0m \u001b[0;36m0\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mt\u001b[0m \u001b[0;34m<=\u001b[0m \u001b[0mmax_time\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m--> 109\u001b[0;31m \u001b[0mr_1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mr_2\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mrandom\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0muniform\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;36m0\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;36m2\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 110\u001b[0m \u001b[0mt\u001b[0m \u001b[0;34m+=\u001b[0m \u001b[0;34m-\u001b[0m\u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mlog\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mr_1\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;34m/\u001b[0m \u001b[0;34m(\u001b[0m\u001b[0ma_0\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 111\u001b[0m \u001b[0ms\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m0\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mKeyboardInterrupt\u001b[0m: " ] } ], @@ -179,24 +192,16 @@ }, { "cell_type": "code", - "execution_count": 35, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "43.9 ms ± 793 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" - ] - } - ], + "outputs": [], "source": [ "%timeit model.simulate(k, times, approx=True, approx_tau=0.0125)" ] }, { "cell_type": "code", - "execution_count": 25, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -205,29 +210,16 @@ }, { "cell_type": "code", - "execution_count": 34, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], + "outputs": [], "source": [ "plot_output(empirical_mean)" ] }, { "cell_type": "code", - "execution_count": 37, + "execution_count": null, "metadata": {}, "outputs": [], "source": [ @@ -239,23 +231,9 @@ }, { "cell_type": "code", - "execution_count": 38, + "execution_count": null, "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Running for tau = 0.0125\n", - "Running for tau = 0.025\n", - "Running for tau = 0.05\n", - "Running for tau = 0.1\n", - "Running for tau = 0.25\n", - "Running for tau = 0.5\n", - "Running for tau = 1\n" - ] - } - ], + "outputs": [], "source": [ "taus = [0.0125, 0.025, 0.05, 0.1, 0.25, 0.5, 1]\n", "approx_mses = []\n", @@ -273,36 +251,6 @@ "execution_count": null, "metadata": {}, "outputs": [], - "source": [] - }, - { - "cell_type": "code", - "execution_count": 46, - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "[]" - ] - }, - "execution_count": 46, - "metadata": {}, - "output_type": "execute_result" - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], "source": [ "plt.plot([0]+taus[:4], [exact_mse]+approx_mses[:4], 'bo')" ] diff --git a/pints/tests/test_toy_stochastic_degradation_model.py b/pints/tests/test_toy_stochastic_degradation_model.py index d5f5217fd..5605b338c 100755 --- a/pints/tests/test_toy_stochastic_degradation_model.py +++ b/pints/tests/test_toy_stochastic_degradation_model.py @@ -11,7 +11,7 @@ import numpy as np import pints import pints.toy -from pints.toy. import DegradationModel +from pints.toy.stochastic import DegradationModel class TestDegradation(unittest.TestCase): diff --git a/pints/toy/stochastic/__init__.py b/pints/toy/stochastic/__init__.py index 2e71b8f82..61e23b3b9 100644 --- a/pints/toy/stochastic/__init__.py +++ b/pints/toy/stochastic/__init__.py @@ -13,4 +13,4 @@ from ._degradation_model import DegradationModel # noqa from ._markov_jump_model import MarkovJumpModel # noqa from ._michaelis_menten_model import MichaelisMentenModel # noqa -from ._schlogl_model import SchloglModel \ No newline at end of file +from ._schlogl_model import SchloglModel # noqa diff --git a/pints/toy/stochastic/_markov_jump_model.py b/pints/toy/stochastic/_markov_jump_model.py index a539be4eb..0f1122789 100644 --- a/pints/toy/stochastic/_markov_jump_model.py +++ b/pints/toy/stochastic/_markov_jump_model.py @@ -9,9 +9,7 @@ from __future__ import absolute_import, division from __future__ import print_function, unicode_literals import numpy as np -import math from scipy.interpolate import interp1d -import scipy import pints from .. import ToyModel @@ -20,13 +18,14 @@ class MarkovJumpModel(pints.ForwardModel, ToyModel): r""" A general purpose Markov Jump model used for any systems of reactions - that proceed through jumps. We simulate a population of N different species, + that proceed through jumps. We simulate a population of N different species reacting through M different mechanisms. A model has three parameters: - - x_0 - an N-vector specifying the initial population of each fo the N species + - x_0 - an N-vector specifying the initial population of each + of the N species - V - an NxM matrix consisting of stochiometric vectors v_i specifying - the changes to the state, x, from reaction i taking place + the changes to the state, x, from reaction i taking place - a - a function from the current state, x, and reaction rates, k, to a vector of the rates of each reaction taking place @@ -42,8 +41,8 @@ class MarkovJumpModel(pints.ForwardModel, ToyModel): .. math:: \tau = \frac{-\ln(r)}{a_0} - 3. Decide which reaction, i, takes place using r_1*a_0 and iterating through - propensities + 3. Decide which reaction, i, takes place using r_1 * a_0 and iterating + through propensities 4. Update the state :math:`x` at time :math:`t + \tau` as: @@ -83,7 +82,7 @@ def __init__(self, x0, V, a): def n_parameters(self): """ See :meth:`pints.ForwardModel.n_parameters()`. """ - return len(self._v) + return len(self._V) def simulate_raw(self, rates, max_time): """ @@ -112,8 +111,8 @@ def simulate_raw(self, rates, max_time): r = 0 while s <= r_2 * a_0: s += current_rates[r] - r+=1 - r-=1 + r += 1 + r -= 1 x = np.add(x, self._V[r]) current_rates = self._a(x, rates) @@ -136,12 +135,12 @@ def simulate_approx(self, rates, max_time, tau): time = [t] while any(current_rates > 0) and t <= max_time: # Estimate number of each reaction in [t, t+tau) - k = [np.random.poisson(current_rates[i]*tau) for i in range(N)] - + k = [np.random.poisson(current_rates[i] * tau) for i in range(N)] + # Apply the reactions for r in range(N): - x += np.array(self._V[r])*k[r] - + x += np.array(self._V[r]) * k[r] + # Update rates current_rates = np.array(self._a(x, rates)) @@ -158,21 +157,20 @@ def interpolate_mol_counts(self, time, mol_count, output_times): """ # Interpolate as step function, decreasing mol_count by 1 at each # reaction time point - interp_func = interp1d(time, mol_count, kind='previous', axis=0, - fill_value="extrapolate", bounds_error=False) + interp_func = interp1d(time, mol_count, kind='previous', axis=0, + fill_value="extrapolate", bounds_error=False) # Compute molecule count values at given time points using f1 # at any time beyond the last reaction, molecule count = 0 values = interp_func(output_times) return values - - def simulate(self, parameters, times, approx=False, approx_tau=None): + def simulate(self, parameters, times, approx_tau=None): """ See :meth:`pints.ForwardModel.simulate()`. """ times = np.asarray(times) if np.any(times < 0): raise ValueError('Negative times are not allowed.') - if not approx: + if approx_tau is None: # run Gillespie time, mol_count = self.simulate_raw(parameters, max(times)) else: @@ -180,8 +178,10 @@ def simulate(self, parameters, times, approx=False, approx_tau=None): ValueError("You must provide a positive value for approx_tau\ to use tau-leaping approximation") # Run Euler tau-leaping - time, mol_count = self.simulate_approx(parameters, max(times), approx_tau) + time, mol_count = self.simulate_approx(parameters, max(times), + approx_tau) # interpolate - values = self.interpolate_mol_counts(np.asarray(time), np.asarray(mol_count), times) + values = self.interpolate_mol_counts(np.asarray(time), + np.asarray(mol_count), times) return values diff --git a/pints/toy/stochastic/_michaelis_menten_model.py b/pints/toy/stochastic/_michaelis_menten_model.py index 19a981824..2861717a0 100644 --- a/pints/toy/stochastic/_michaelis_menten_model.py +++ b/pints/toy/stochastic/_michaelis_menten_model.py @@ -8,9 +8,6 @@ # from __future__ import absolute_import, division from __future__ import print_function, unicode_literals -import numpy as np -from scipy.interpolate import interp1d -import pints from . import MarkovJumpModel @@ -18,25 +15,26 @@ class MichaelisMentenModel(MarkovJumpModel): r""" Simulates the Michaelis Menten Dynamics using Gillespie. - - This system of reaction involved 4 chemical species with + + This system of reaction involves 4 chemical species with inital counts x_0, and reactions: - X1+X2 -> X3 with rate k1 - X3 -> X1+X2 with rate k2 - X3 -> X2+X4 with rate k3 """ def __init__(self, x_0): - mat = [[-1, -1, 1, 0], - [ 1, 1, -1, 0], - [ 0, 1, -1, 1]] - super(MichaelisMentenModel, self).__init__(x_0, mat, self._propensities) + mat = [[-1, -1, 1, 0], + [1, 1, -1, 0], + [0, 1, -1, 1]] + super(MichaelisMentenModel, self).__init__(x_0, + mat, self._propensities) @staticmethod - def _propensities(xs,ks): + def _propensities(xs, ks): return [ - xs[0]*xs[1]*ks[0], - xs[2]*ks[1], - xs[2]*ks[2] + xs[0] * xs[1] * ks[0], + xs[2] * ks[1], + xs[2] * ks[2] ] def n_parameters(self): diff --git a/pints/toy/stochastic/_schlogl_model.py b/pints/toy/stochastic/_schlogl_model.py index c66ab92db..a5a19c070 100644 --- a/pints/toy/stochastic/_schlogl_model.py +++ b/pints/toy/stochastic/_schlogl_model.py @@ -8,9 +8,6 @@ # from __future__ import absolute_import, division from __future__ import print_function, unicode_literals -import numpy as np -from scipy.interpolate import interp1d -import pints from . import MarkovJumpModel @@ -18,7 +15,7 @@ class SchloglModel(MarkovJumpModel): r""" Simulates the Schlögl System using Gillespie. - + This system of reaction involved 4 chemical species with inital counts x_0, and reactions: - A + 2X -> 3X, rate k1 @@ -30,25 +27,22 @@ def __init__(self, x_0): self.a_count = 1e5 self.b_count = 2e5 # We are only concered with the change in X concentration - mat = [[ 1], + mat = [[1], [-1], - [ 1], + [1], [-1]] super(SchloglModel, self).__init__([x_0], mat, self._propensities) def simulate(self, parameters, times, approx=None, approx_tau=None): - return super(SchloglModel, self).simulate(parameters, times, approx, approx_tau)[:,0] + return super(SchloglModel, self).simulate( + parameters, times, approx, approx_tau)[:, 0] - r""" - Calculate the rates of reaction based on molecular availability - xs is of the form [A, B, X] - """ def _propensities(self, xs, ks): return [ - self.a_count*xs[0]*(xs[0]-1)*ks[0], - xs[0]*(xs[0]-1)*(xs[0]-2)*ks[1], - self.b_count*ks[2], - xs[0]*ks[3] + self.a_count * xs[0] * (xs[0] - 1) * ks[0], + xs[0] * (xs[0] - 1) * (xs[0] - 2) * ks[1], + self.b_count * ks[2], + xs[0] * ks[3] ] def n_parameters(self): From bfef3a30f26b430bf8ae6b18a7b6904115a699e0 Mon Sep 17 00:00:00 2001 From: Jack Arthur Date: Tue, 5 May 2020 18:13:07 +0100 Subject: [PATCH 3/3] Move notebooks and minor changes to stochastic models --- examples/toy-model-schlogl.ipynb | 238 ---- examples/toy/100 | 15 + .../model-michaelis-menten.ipynb} | 0 examples/toy/model-schlogl.ipynb | 1168 +++++++++++++++++ examples/toy/model-sir.ipynb | 4 +- pints/toy/stochastic/_markov_jump_model.py | 3 +- pints/toy/stochastic/_schlogl_model.py | 8 +- 7 files changed, 1191 insertions(+), 245 deletions(-) delete mode 100644 examples/toy-model-schlogl.ipynb create mode 100644 examples/toy/100 rename examples/{toy-model-michaelis-menten.ipynb => toy/model-michaelis-menten.ipynb} (100%) create mode 100644 examples/toy/model-schlogl.ipynb diff --git a/examples/toy-model-schlogl.ipynb b/examples/toy-model-schlogl.ipynb deleted file mode 100644 index 3abfb724b..000000000 --- a/examples/toy-model-schlogl.ipynb +++ /dev/null @@ -1,238 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "# Schlögl" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "- A + 2X -> 3X, rate k1\n", - "- 3X -> A+2X, rate k2\n", - "- B -> X, rate k3\n", - "- X -> B, rate k4" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "metadata": {}, - "outputs": [], - "source": [ - "import pints\n", - "import pints.toy.stochastic\n", - "import matplotlib.pyplot as plt\n", - "import numpy as np\n", - "import math" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "metadata": {}, - "outputs": [], - "source": [ - "import line_profiler" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "metadata": {}, - "outputs": [], - "source": [ - "x_0 = 250\n", - "\n", - "model = pints.toy.stochastic.SchloglModel(x_0)\n", - "\n", - "times = np.linspace(0, 5, 100)\n", - "k = [3e-7, 1e-4, 1e-3, 3.5]\n", - "\n", - "valuess = [model.simulate(k, times, approx=True, approx_tau=0.0125) for i in range(10000)]" - ] - }, - { - "cell_type": "code", - "execution_count": 4, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "380 ms ± 56.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" - ] - } - ], - "source": [ - "%timeit model.simulate(k, times)" - ] - }, - { - "cell_type": "code", - "execution_count": 5, - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "16.3 ms ± 565 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)\n" - ] - } - ], - "source": [ - "%timeit model.simulate(k, times, approx=True, approx_tau=0.0125)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "for values in valuess:\n", - " plt.step(times, values)" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "metadata": {}, - "outputs": [], - "source": [ - "valuess = np.array(valuess)" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "No handles with labels found to put in legend.\n" - ] - }, - { - "data": { - "image/png": "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\n", - "text/plain": [ - "
" - ] - }, - "metadata": { - "needs_background": "light" - }, - "output_type": "display_data" - } - ], - "source": [ - "plt.hist(valuess[:,-1])\n", - "plt.legend()\n", - "plt.xlabel('X')\n", - "plt.ylabel('Probability')\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "Given the stochastic nature of this model, every iteration returns a different result. However, averaging the concentration values at each time step, produces a reproducible result which tends towards a deterministic function as the the number of iterations tends to infinity (Erban et al., 2007): $ n_0e^{-kt} $\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "N = 100\n", - "average = np.zeros(len(times))\n", - "for i in range(N):\n", - " values = np.asarray(model.simulate(k, times))[0,:]\n", - " average += (values/N)\n", - " " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "average.shape" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "\n", - "plt.plot(times, average, label = 'deterministic mean of A(t)')\n", - "plt.title('stochastic degradation across different iterations')\n", - "plt.xlabel('time')\n", - "plt.ylabel('concentration (A(t))')\n", - "plt.legend(loc = 'upper right')\n", - "plt.show()" - ] - }, - { - "cell_type": "markdown", - "metadata": {}, - "source": [ - "The deterministic mean (from above) is plotted with the deterministic standard deviation. \n", - "The deterministic variance of this model is given by: $e^{-2kt}(-1 + e^{kt})n_0$" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "metadata": {}, - "outputs": [], - "source": [ - "mean = model.mean(k, times)\n", - "variance = model.variance(k, times)\n", - "std_dev = np.sqrt(variance)\n", - "\n", - "plt.plot(times, mean, '-', label = 'deterministic mean of A(t)')\n", - "plt.plot(times, mean + std_dev, '--', label = 'standard deviation upper bound')\n", - "plt.plot(times, mean - std_dev, '--', label = 'standard deviation lower bound')\n", - "plt.legend(loc = 'upper right')\n", - "plt.xlabel('time')\n", - "plt.ylabel('concentration (A(t))')\n", - "plt.show()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "Python 3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.7.4" - } - }, - "nbformat": 4, - "nbformat_minor": 4 -} diff --git a/examples/toy/100 b/examples/toy/100 new file mode 100644 index 000000000..16eeae493 --- /dev/null +++ b/examples/toy/100 @@ -0,0 +1,15 @@ +Timer unit: 1e-06 s + +Total time: 5.4e-05 s +File: +Function: _propensities at line 1 + +Line # Hits Time Per Hit % Time Line Contents +============================================================== + 1 def _propensities(xs, ks): + 2 return [ + 3 1 37.0 37.0 68.5 1e5 * xs[0] ** 2 * ks[0], + 4 1 10.0 10.0 18.5 xs[0] ** 3 * ks[1], + 5 1 1.0 1.0 1.9 2e5 * ks[2], + 6 1 6.0 6.0 11.1 xs[0] * ks[3] + 7 ] \ No newline at end of file diff --git a/examples/toy-model-michaelis-menten.ipynb b/examples/toy/model-michaelis-menten.ipynb similarity index 100% rename from examples/toy-model-michaelis-menten.ipynb rename to examples/toy/model-michaelis-menten.ipynb diff --git a/examples/toy/model-schlogl.ipynb b/examples/toy/model-schlogl.ipynb new file mode 100644 index 000000000..7d86c1baa --- /dev/null +++ b/examples/toy/model-schlogl.ipynb @@ -0,0 +1,1168 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Schlögl" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "- A + 2X -> 3X, rate k1\n", + "- 3X -> A+2X, rate k2\n", + "- B -> X, rate k3\n", + "- X -> B, rate k4" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import pints\n", + "import pints.toy.stochastic\n", + "import matplotlib.pyplot as plt\n", + "import numpy as np\n", + "import math\n", + "from tqdm import tqdm" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "%load_ext line_profiler" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\n", + "\n", + " 0%| | 0/1000 [00:00" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "for value in valuess[:10]:\n", + " plt.step(times, value)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "376 ms ± 43.3 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)\n" + ] + } + ], + "source": [ + "%timeit model.simulate(k, times)" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "31.7 ms ± 1.31 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)\n" + ] + } + ], + "source": [ + "%timeit model.simulate(k, times, approx_tau=0.0125)" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "valuess = np.array(valuess)" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "No handles with labels found to put in legend.\n" + ] + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYUAAAEGCAYAAACKB4k+AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjEsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy8QZhcZAAATVElEQVR4nO3df/BldX3f8edL2bhJoALLQggL+W4M1mDSANlYZmyM1kYFomisDjaN1NCsmcEp1LTjaiaNncbpmghJ7Q/sGhhXowIdtG4C+YEM0XEa1F2k/BApi27gK5vdlaZCalHAd/+45/vxsnv3+727+73fc7/7fT5m7pxzP+ece9575uy+9nzOuZ+bqkKSJIBn9V2AJGl6GAqSpMZQkCQ1hoIkqTEUJEnNMX0XcCROOumkmpmZ6bsMSVpWduzY8Y2qWjtq2bIOhZmZGbZv3953GZK0rCT5q4Mts/tIktRMLBSSnJ7ktiT3Jbk3yeVd+7uTfD3Jnd3rgqFt3plkZ5L7k7xyUrVJkkabZPfRU8CvV9UdSY4DdiS5pVv2e1X1vuGVk5wFXAy8EPhh4NNJnl9VT0+wRknSkImFQlXtBnZ3848nuQ84bZ5NLgKuq6pvA19LshN4EfCXk6pRkpa7J598ktnZWZ544okDlq1evZp169axatWqsT9vSW40J5kBzgE+D7wYeFuSNwPbGVxN/A2DwLh9aLNZRoRIko3ARoAzzjhjonVL0rSbnZ3luOOOY2ZmhiStvap49NFHmZ2dZf369WN/3sRvNCc5FrgRuKKqHgOuBp4HnM3gSuLKuVVHbH7AaH1VtaWqNlTVhrVrRz5RJUkrxhNPPMGaNWueEQgASVizZs3IK4j5TDQUkqxiEAgfrapPAFTVnqp6uqq+C3yQQRcRDK4MTh/afB3wyCTrk6Sjwf6BsFD7fCb59FGAa4D7quqqofZTh1Z7HXBPN78NuDjJc5KsB84EvjCp+iRJB5rkPYUXA78M3J3kzq7tXcCbkpzNoGtoF/BWgKq6N8kNwJcZPLl0mU8eSdLSmuTTR59j9H2Cm+fZ5j3AeyZVk7SUZjbd1Mt+d22+sJf9qj9VNbKr6HB+RM1vNEvSMrZ69WoeffTRAwJg7umj1atXH9LnLeuxjyRppVu3bh2zs7Ps27fvgGVz31M4FIaCJC1jq1atOqTvISzEUNBRra9+fWm58p6CJKkxFCRJjaEgSWoMBUlSYyhIkhpDQZLUGAqSpMZQkCQ1hoIkqTEUJEmNoSBJagwFSVJjKEiSGkNBktQYCpKkxlCQJDWGgiSpMRQkSY2hIElqDAVJUmMoSJIaQ0GS1BgKkqTGUJAkNYaCJKkxFCRJjaEgSWoMBUlSYyhIkhpDQZLUTCwUkpye5LYk9yW5N8nlXfuJSW5J8kA3PaFrT5L3J9mZ5K4k506qNknSaJO8UngK+PWq+nHgPOCyJGcBm4Bbq+pM4NbuPcD5wJndayNw9QRrkySNMLFQqKrdVXVHN/84cB9wGnARsLVbbSvw2m7+IuDDNXA7cHySUydVnyTpQEtyTyHJDHAO8HnglKraDYPgAE7uVjsNeHhos9mubf/P2phke5Lt+/btm2TZkrTiTDwUkhwL3AhcUVWPzbfqiLY6oKFqS1VtqKoNa9euXawyJUlMOBSSrGIQCB+tqk90zXvmuoW66d6ufRY4fWjzdcAjk6xPkvRMk3z6KMA1wH1VddXQom3AJd38JcCnhtrf3D2FdB7wzbluJknS0jhmgp/9YuCXgbuT3Nm1vQvYDNyQ5FLgIeAN3bKbgQuAncC3gLdMsDZJ0ggTC4Wq+hyj7xMAvHzE+gVcNql6JEkL8xvNkqTGUJAkNYaCJKkxFCRJjaEgSWoMBUlSYyhIkhpDQZLUGAqSpMZQkCQ1hoIkqTEUJEmNoSBJagwFSVJjKEiSGkNBktQYCpKkxlCQJDWGgiSpMRQkSY2hIElqDAVJUmMoSJIaQ0GS1BgKkqTGUJAkNYaCJKkxFCRJzTF9F6CVYWbTTX2XsGL0dax3bb6wl/1qcXmlIElqxgqFJDcmuTCJISJJR7Fx/5G/GvgnwANJNid5wQRrkiT1ZKxQqKpPV9UvAecCu4BbkvyPJG9JsmqSBUqSls7Y3UFJ1gD/DPjnwJeA/8AgJG45yPrXJtmb5J6htncn+XqSO7vXBUPL3plkZ5L7k7zyMP88kqQjMNbTR0k+AbwA+Ajw6qra3S26Psn2g2z2IeA/AR/er/33qup9+33+WcDFwAuBHwY+neT5VfX0WH8KSdKiGPeR1D+oqpuHG5I8p6q+XVUbRm1QVZ9NMjPm518EXFdV3wa+lmQn8CLgL8fcXpK0CMbtPvrtEW2H+w/225Lc1XUvndC1nQY8PLTObNd2gCQbk2xPsn3fvn2HWYIkaZR5QyHJDyX5aeD7k5yT5Nzu9VLgBw5jf1cDzwPOBnYDV87tasS6NeoDqmpLVW2oqg1r1649jBIkSQezUPfRKxncXF4HXDXU/jjwrkPdWVXtmZtP8kHgj7u3s8DpQ6uuAx451M+XJB2ZeUOhqrYCW5O8vqpuPNKdJTl16Cb164C5J5O2AR9LchWDG81nAl840v1Jkg7NvKGQ5J9W1R8CM0nevv/yqrpqxGZz234ceClwUpJZ4LeAlyY5m0HX0C7grd3n3JvkBuDLwFPAZT55JElLb6Huox/spsce6gdX1ZtGNF8zz/rvAd5zqPuRJC2ehbqP/ms3/bdLU44kqU8LdR+9f77lVfUvFrccSVKfFuo+2rEkVUiSpsI4Tx9JklaIhbqPfr+qrkjyR4z4MllVvWZilUmSltxC3Ucf6abvm3ctSdJRYaHuox3d9DNJvo/BSKkF3F9V31mC+iRJS2jcobMvBD4APMhgnKL1Sd5aVX8yyeIkSUtr3KGzrwReVlU7AZI8D7gJMBQk6Sgy7tDZe+cCofNVYO8E6pEk9Wihp49+sZu9N8nNwA0M7im8AfjihGuTJC2xhbqPXj00vwf4uW5+H3DCgatLkpazhZ4+estSFSJJ6t+4Tx+tBi4FXgisnmuvql+ZUF2SpB6Me6P5I8APMfglts8w+GW0xydVlCSpH+OGwo9V1W8C/7cbD+lC4CcnV5YkqQ/jhsKT3fT/JPkJ4LnAzEQqkiT1Ztwvr21JcgLwmwx+T/nYbl6SdBQZKxSq6g+62c8APzq5ciRJfRqr+yjJmiT/MckdSXYk+f0kayZdnCRpaY17T+E6BsNavB74x8A3gOsnVZQkqR/j3lM4sar+3dD7307y2kkUJEnqz7hXCrcluTjJs7rXGxmMkipJOoosNCDe4wwGwAvwduAPu0XPAv4W+K2JVidJWlILjX103FIVIknq37j3FEjyGuAl3du/qKo/nkxJkqS+jPtI6mbgcuDL3evyrk2SdBQZ90rhAuDsqvouQJKtwJeATZMqTJK09MZ9+gjg+KH55y52IZKk/o17pfDvgS8luY3Bk0gvAd45saokSb1YMBSSBPgccB7wMwxC4R1V9dcTrk2StMQWDIWqqiT/vap+msEIqZKko9S49xRuT/IzE61EktS7cUPhZQyC4cEkdyW5O8ld822Q5Noke5PcM9R2YpJbkjzQTU/o2pPk/Ul2dp9/7uH/kSRJh2vcUDifwe8o/EPg1cAvdNP5fAh41X5tm4Bbq+pM4Fa+90jr+cCZ3WsjcPWYdUmSFtFCYx+tBn4N+DHgbuCaqnpqnA+uqs8mmdmv+SLgpd38VuAvgHd07R+uqmJwRXJ8klOravd4fwxJ0mJY6EphK7CBQSCcD1x5hPs7Ze4f+m56ctd+GvDw0HqzXdsBkmxMsj3J9n379h1hOZKkYQs9fXRWVf0kQJJrgC9MqI6MaKtRK1bVFmALwIYNG0auI0k6PAtdKTw5NzNut9EC9iQ5FaCb7u3aZ4HTh9ZbBzyyCPuTJB2ChULhp5I81r0eB/7e3HySxw5jf9uAS7r5S4BPDbW/uXsK6Tzgm95PkKSlt9DvKTz7cD84yccZ3FQ+Kcksgx/k2QzckORS4CHgDd3qNzMYdG8n8C3gLYe7X0nS4Rv79xQOVVW96SCLXj5i3QIum1QtkqTxHMooqZKko5yhIElqDAVJUmMoSJIaQ0GS1BgKkqTGUJAkNYaCJKkxFCRJzcS+0SxpZZnZdFNv+961+cLe9n208UpBktQYCpKkxlCQJDWGgiSpMRQkSY2hIElqDAVJUmMoSJIaQ0GS1BgKkqTGYS5WkD6HIZC0PHilIElqDAVJUmMoSJIaQ0GS1BgKkqTGUJAkNYaCJKkxFCRJjaEgSWoMBUlSYyhIkhpDQZLU9DIgXpJdwOPA08BTVbUhyYnA9cAMsAt4Y1X9TR/1SdJK1eeVwsuq6uyq2tC93wTcWlVnArd27yVJS2iauo8uArZ281uB1/ZYiyStSH2FQgF/nmRHko1d2ylVtRugm57cU22StGL19SM7L66qR5KcDNyS5CvjbtiFyEaAM844Y1L1SdKK1MuVQlU90k33Ap8EXgTsSXIqQDfde5Btt1TVhqrasHbt2qUqWZJWhCUPhSQ/mOS4uXngFcA9wDbgkm61S4BPLXVtkrTS9dF9dArwySRz+/9YVf1pki8CNyS5FHgIeEMPtUnSirbkoVBVXwV+akT7o8DLl7oeSdL3TNMjqZKknhkKkqTGUJAkNYaCJKkxFCRJjaEgSWoMBUlSYyhIkhpDQZLUGAqSpMZQkCQ1hoIkqTEUJEmNoSBJagwFSVJjKEiSGkNBktT08XOckrSoZjbd1Mt+d22+sJf9TpJXCpKkxlCQJDWGgiSpMRQkSY2hIElqfPqoB309KSFJC/FKQZLUGAqSpMZQkCQ1hoIkqTEUJEmNoSBJagwFSVJjKEiSGkNBktT4jWZJOkx9jk4wqd9ymLorhSSvSnJ/kp1JNvVdjyStJFN1pZDk2cB/Bn4emAW+mGRbVX15sffl+EOSdKBpu1J4EbCzqr5aVd8BrgMu6rkmSVoxpupKATgNeHjo/Szw94dXSLIR2Ni9/dsk9y9RbcNOAr7Rw36P1HKseznWDMuz7uVYMyzPuo+45rz3iPb/IwdbMG2hkBFt9Yw3VVuALUtTzmhJtlfVhj5rOBzLse7lWDMsz7qXY82wPOue5pqnrftoFjh96P064JGeapGkFWfaQuGLwJlJ1if5PuBiYFvPNUnSijFV3UdV9VSStwF/BjwbuLaq7u25rFF67b46Asux7uVYMyzPupdjzbA8657amlNVC68lSVoRpq37SJLUI0NBktQYCvNI8neT3Dn0eizJFUneneTrQ+0XTEGt1ybZm+SeobYTk9yS5IFuekLXniTv74YSuSvJuVNW9+8m+UpX2yeTHN+1zyT5f0PH/QNTVPNBz4kk7+yO9f1JXtlHzV0do+q+fqjmXUnu7Nqn5VifnuS2JPcluTfJ5V37VJ/b89Q91ec2AFXla4wXgxvff83gSx/vBv5V3zXtV99LgHOBe4bafgfY1M1vAt7bzV8A/AmD74WcB3x+yup+BXBMN//eobpnhtebsppHnhPAWcD/BJ4DrAceBJ49LXXvt/xK4N9M2bE+FTi3mz8O+F/dMZ3qc3ueuqf63K4qrxQOwcuBB6vqr/ouZJSq+izwv/drvgjY2s1vBV471P7hGrgdOD7JqUtT6TONqruq/ryqnure3s7g+ypT4yDH+mAuAq6rqm9X1deAnQyGc1ly89WdJMAbgY8vaVELqKrdVXVHN/84cB+DkQ+m+tw+WN3Tfm6D3UeH4mKe+Rfmbd0l4LVzl65T6JSq2g2DkxQ4uWsfNZzIaUtc27h+hcH//OasT/KlJJ9J8rN9FXUQo86J5XKsfxbYU1UPDLVN1bFOMgOcA3yeZXRu71f3sKk8tw2FMWTwRbrXAP+ta7oaeB5wNrCbwWX3crLgcCLTIMlvAE8BH+2adgNnVNU5wNuBjyX5O33Vt5+DnRPL4lgDb+KZ/+mZqmOd5FjgRuCKqnpsvlVHtPV2vA9W9zSf24bCeM4H7qiqPQBVtaeqnq6q7wIfpKfugDHsmbt07qZ7u/apH04kySXALwC/VF2na9cF82g3v4NB//zz+6vye+Y5J5bDsT4G+EXg+rm2aTrWSVYx+If1o1X1ia556s/tg9Q99ee2oTCeZ/wvar8+ytcB9xywxXTYBlzSzV8CfGqo/c3dkxrnAd+cuxSfBkleBbwDeE1VfWuofW0Gv7lBkh8FzgS+2k+VzzTPObENuDjJc5KsZ1DzF5a6vgX8I+ArVTU71zAtx7q713ENcF9VXTW0aKrP7YPVvSzO7b7vdE/7C/gB4FHguUNtHwHuBu5icBKeOgV1fpzBJeiTDP63dCmwBrgVeKCbntitGwY/ZvRg9+fYMGV172TQL3xn9/pAt+7rgXsZPM1zB/DqKar5oOcE8Bvdsb4fOH+ajnXX/iHg1/Zbd1qO9T9g0P1z19D5cMG0n9vz1D3V53ZVOcyFJOl77D6SJDWGgiSpMRQkSY2hIElqDAVJUmMoSIukGxnza0lO7N6f0L3/kb5rk8ZlKEiLpKoeZjDcxeauaTOwpaZ0EEVpFL+nIC2ibmiDHcC1wK8C51TVd/qtShrfMX0XIB1NqurJJP8a+FPgFQaClhu7j6TFdz6D4SR+ou9CpENlKEiLKMnZwM8z+NWvf9nXjxdJh8tQkBZJNzLm1QzGzn8I+F3gff1WJR0aQ0FaPL8KPFRVt3Tv/wvwgiQ/12NN0iHx6SNJUuOVgiSpMRQkSY2hIElqDAVJUmMoSJIaQ0GS1BgKkqTm/wMVD8zJmmkRYwAAAABJRU5ErkJggg==\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.hist(valuess[:,-1])\n", + "plt.legend()\n", + "plt.xlabel('X')\n", + "plt.ylabel('Probability')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Given the stochastic nature of this model, every iteration returns a different result. However, averaging the concentration values at each time step, produces a reproducible result which tends towards a deterministic function as the the number of iterations tends to infinity (Erban et al., 2007): $ n_0e^{-kt} $\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "N = 100\n", + "average = np.zeros(len(times))\n", + "for i in range(N):\n", + " values = np.asarray(model.simulate(k, times))[0,:]\n", + " average += (values/N)\n", + " " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "average.shape" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\n", + "plt.plot(times, average, label = 'deterministic mean of A(t)')\n", + "plt.title('stochastic degradation across different iterations')\n", + "plt.xlabel('time')\n", + "plt.ylabel('concentration (A(t))')\n", + "plt.legend(loc = 'upper right')\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The deterministic mean (from above) is plotted with the deterministic standard deviation. \n", + "The deterministic variance of this model is given by: $e^{-2kt}(-1 + e^{kt})n_0$" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "mean = model.mean(k, times)\n", + "variance = model.variance(k, times)\n", + "std_dev = np.sqrt(variance)\n", + "\n", + "plt.plot(times, mean, '-', label = 'deterministic mean of A(t)')\n", + "plt.plot(times, mean + std_dev, '--', label = 'standard deviation upper bound')\n", + "plt.plot(times, mean - std_dev, '--', label = 'standard deviation lower bound')\n", + "plt.legend(loc = 'upper right')\n", + "plt.xlabel('time')\n", + "plt.ylabel('concentration (A(t))')\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.4" + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/examples/toy/model-sir.ipynb b/examples/toy/model-sir.ipynb index 26ec07ee0..50b446ad4 100644 --- a/examples/toy/model-sir.ipynb +++ b/examples/toy/model-sir.ipynb @@ -285,9 +285,9 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.6.7" + "version": "3.7.4" } }, "nbformat": 4, - "nbformat_minor": 1 + "nbformat_minor": 4 } diff --git a/pints/toy/stochastic/_markov_jump_model.py b/pints/toy/stochastic/_markov_jump_model.py index 0f1122789..6bda241f4 100644 --- a/pints/toy/stochastic/_markov_jump_model.py +++ b/pints/toy/stochastic/_markov_jump_model.py @@ -11,6 +11,7 @@ import numpy as np from scipy.interpolate import interp1d import pints +import random from .. import ToyModel @@ -105,7 +106,7 @@ def simulate_raw(self, rates, max_time): mol_count = [np.array(x)] time = [t] while a_0 > 0 and t <= max_time: - r_1, r_2 = np.random.uniform(0, 1, 2) + r_1, r_2 = random.random(), random.random() t += -np.log(r_1) / (a_0) s = 0 r = 0 diff --git a/pints/toy/stochastic/_schlogl_model.py b/pints/toy/stochastic/_schlogl_model.py index a5a19c070..7f904e590 100644 --- a/pints/toy/stochastic/_schlogl_model.py +++ b/pints/toy/stochastic/_schlogl_model.py @@ -35,12 +35,12 @@ def __init__(self, x_0): def simulate(self, parameters, times, approx=None, approx_tau=None): return super(SchloglModel, self).simulate( - parameters, times, approx, approx_tau)[:, 0] + parameters, times, approx_tau)[:, 0] - def _propensities(self, xs, ks): + def _propensities(self, xs, ks): return [ - self.a_count * xs[0] * (xs[0] - 1) * ks[0], - xs[0] * (xs[0] - 1) * (xs[0] - 2) * ks[1], + self.a_count * xs[0] * xs[0] * ks[0], + xs[0] * xs[0] * xs[0] * ks[1], self.b_count * ks[2], xs[0] * ks[3] ]