├── .ipynb_checkpoints ├── build_your_own_gillespie-checkpoint.ipynb ├── build_your_own_gillespie_exercises-checkpoint.ipynb ├── build_your_own_gillespie_solutions-checkpoint.ipynb └── deterministic_modelling-checkpoint.ipynb ├── MATLAB-Gillespie ├── nedelec_francois_gillespie.m └── nedelec_gillespie_choice.m ├── Papers ├── Erban2007.pdf ├── Gillespie1976.pdf └── Gillespie1977.pdf ├── README.md ├── a.png ├── a0.png ├── alg.png ├── algo_im.png ├── b.png ├── build_your_own_gillespie_exercises.ipynb ├── build_your_own_gillespie_solutions.ipynb ├── c1.png ├── c2.png ├── choice.png ├── diag.png ├── explainign_gillespie.key ├── explainign_gillespie.key.zip ├── ode1.png ├── pdf.png ├── pdff.png ├── r1.png ├── r2.png ├── reaction_rate1.png ├── sample.png └── schematic1.png /.ipynb_checkpoints/build_your_own_gillespie_exercises-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Build your own Gillespie algorithm \n", 8 | "\n", 9 | "\n", 10 | "In this tutorial you will learn in detail about the ~~deterministic~~ *stochastic* formalism for the *temporal* modelling of *simple*\\* chemical systems, and you will learn to write the *Gillespie algorithm*, from scratch, using Python 2.7.\n", 11 | "\n", 12 | "\\* the word *simple* referst to \"spatially homogenous\" (i.e. spatially uniform mixture of chemical species, as opposed to spatially varied, where you could find regions with higher concentrations of some molecules but not others).\n", 13 | "\n", 14 | "As you can already imagine, there are many Gillespie algorithm scripts out there, available for you to download freely and use for your simulations. (In particular modifications of the Gillespie algorithm such as the reaction method (Gibson & Bruck) and the tau-leaping are very efficient.) We think it is advantageous in many ways to understand how this formalism is constructed. It will help you, for example, decide in what contexts this framework is more appropiate, and understand the reasons why you might get different results with the deterministic and stochastic approaches.\n", 15 | "\n", 16 | "\n", 17 | "### To note\n", 18 | "\n", 19 | "If you would like to learn in detail about the *deterministic* framework for modelling the temporal evolution of simple chemical systems, we refer you to [this](https://github.com/karinsasaki/biomath-modelling-with-python) tutorial.\n", 20 | "\n", 21 | "The tutorial you currently hold deals only with modelling the evolution of a chemical system, in *time*. If you would like to learn to desing a *spatial* model and simulate it, we refer you to [this (coming soon)]() tutorial.\n", 22 | "\n", 23 | "\n", 24 | "### Structure of tutorial\n", 25 | "\n", 26 | "In **Part 1** we introduce and characterise the stochastic framework as a mathematical model of simple systems of chemical reactions.\n", 27 | "\n", 28 | "In **Part 2** we set the problem that needs to be solved, in precise mathematical formulation.\n", 29 | "\n", 30 | "In **Part 3** we provide steps to help you build your own Gillespie agorithm.\n", 31 | "\n", 32 | "\n", 33 | "### References\n", 34 | "\n", 35 | "The tutorial is heavily based on Gillespie's original 1977 [paper](http://wwwf.imperial.ac.uk/~nsjones/gillespie_1977.pdf) and we will often quote text directly from the paper. \n", 36 | "\n", 37 | "The Wikipedia [page](https://en.wikipedia.org/wiki/Mathematical_model) on Mathematical Models.\n", 38 | "\n", 39 | "\n", 40 | "### Acknowledgements\n", 41 | "\n", 42 | "This tutorial was make by Dr. Karin Sasaki (Centre for Biological Modelling at the European Molecular Biology Laboratory)." 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": {}, 48 | "source": [ 49 | "## Part 1. Characterisation of stochastic mathematical models of the time behaviour of spatially homogenous chemical systems.\n", 50 | "\n", 51 | "### The *stochastic approach* or framework:\n", 52 | "\n", 53 | "1. The time evolution is regarded as a kind of random-walk process. (A *deterministic model*, in contrast, regards the time evolution as a continuous, wholly predictable process.)\n", 54 | "2. The time evolution of the system is governed by differential-difference equations called “master equations” or is computationally calculated exactly by the Gillespie algorithm. (In a *deterministic model*, the time evolution of the system is governed by a set of coupled, ordinary differential equations called the “reaction-rate equations”.)\n", 55 | "\n", 56 | "\n", 57 | "### Reasoning behind the stochastic framework\n", 58 | "\n", 59 | "1. The time evolution of a chemically reacting system is not a continuous process, because molecular population levels obviously can change only by discrete integer amounts. \n", 60 | "2. The time evolution is not a deterministic process, for, the molecular motions are regarded to be governed by the equations of classical mechanics, it is impossible to predict the exact molecular population levels at some future time, unless we take account of the precise positions and velocities of all the molecules in the system. In other words, although the temporal behavior of a chemically reacting system of classical molecules is a deterministic process in the full position-momentum phase space of the system, it is not a deterministic process in the N-dimensional subspace of the species population numbers.\n", 61 | "\n", 62 | "\n", 63 | "### Classification of stochastic models as mathematical models\n", 64 | "\n", 65 | "* **The stochastic model is linear (not nonlinear)** - because chemical reactions exihibit linear relationships between the reactants. For example, an enzymatic reaction \n", 66 | " \n", 67 | " S + E <-> SE -> E + P\n", 68 | " \n", 69 | "is broken down into\n", 70 | "\n", 71 | " S + E -> SE\n", 72 | " SE -> S + E\n", 73 | " SE -> E + P\n", 74 | " \n", 75 | "which all have linear relations between the reactants and products. Note that a linear model does not necessarily predic non-linear expressions.\n", 76 | "\n", 77 | "* **Stochastic models are dynamic (not static i.e. time-invariant)** - because they accounts for time-dependent changes in the state of the system. (A *static model* calculates the system in equillibrium. An example is Flux Balance Analysis of metabolic models using linear programming).\n", 78 | "\n", 79 | "* **Stochastic models are explicit** - all of the input parameters of the overall model are known, and the output parameters can be calculated by a finite series of computations \n", 80 | "\n", 81 | "* **Stochastic models are not always discrete** - a discrete model is one where objects are treated as discrete entities. (A *continuous model* represents the objects in a continuous manner, for example, chemical reactions can be regarded as a continuous rate processes). Chemical master equations do not need to be discrete, as they describe probabilites; in simple cases it might be even possible to solve them without simulation algorithms e.g to calculate probabilities of system states as function of times. Discrete event simulations, such as the Gillespie algorithm, represent just one way (most useful practically) to solve chemical master equations. \n", 82 | "\n", 83 | "* **Stochastic models are probabilistic and not deterministic** - randomness is included in the model in order to capture inherent fluctuations in the molecular population levels. Therefore variable states are described by probability distributions and these models can perform differently for the same set of initial conditions. (A deterministic model is one where the variable states are uniquely determined by parameters in the model and by sets of previous states of these variables. Therefore, a deterministic model always performs the same way for a given set of initial conditions.)" 84 | ] 85 | }, 86 | { 87 | "cell_type": "markdown", 88 | "metadata": { 89 | "collapsed": true 90 | }, 91 | "source": [ 92 | "# Part 2. Setting the problem and translating it into mathematical formalism\n", 93 | "\n", 94 | "### The problem we want to solve\n", 95 | "\n", 96 | "The system:\n", 97 | "\n", 98 | "M chemical reactions `R1, ... ,RM` that involve `N` chemical species `S1, ..., SN`. \n", 99 | "\n", 100 | "The question:\n", 101 | "\n", 102 | "Given `X1, ..., XN` number of particles for each of the species, at some initial time, what will these molecular population levels be at a later time?\n", 103 | "\n", 104 | "\n", 105 | "### Modelling the system stochastically - Translating of the problem into stochastic language \n", 106 | "\n", 107 | "#### Assumptions of the stochastic framework\n", 108 | "\n", 109 | "1. A fixed volume `V` \n", 110 | "2. `V` contains a spatially uniform mixture of `N` chemical species\n", 111 | "3. The chemical species are in thermal (but not necessarily chemical) equilibrium, which means that collisions occur in an essentially random manner.\n", 112 | "3. A chemical reaction occurs whenever two or more molecules of \"appropriate kinds\" (defined by the reaction equations) collide in an \"appropriate way\" (assuming that the two molecules `S1` and `S2` are hard spheres of radii `rl` and `r2`, a collision will occur between them whenever the center-to-center distance between the two molecules decreases to `r12= r1 + r2`). \n", 113 | "4. All collisions are reactive, i.e. they result in chemical alterations of the colliding molecules as defined by the reaction equations.\n", 114 | "\n", 115 | "\n", 116 | "#### A simple chemical system modelled stochastically is characterised by a \"collision/reaction probability per unit time\" (i.e. it is a stochastic Markov process) and not by a \"collision rate\" (i.e. a deterministic rate process)\n", 117 | "\n", 118 | "**Side note:** A stochastic Markov process is one that satisfies the so called *Markov property*, which says that the conditional probability distribution of future states of a process depends only upon the present state, not on the sequence of events that preceded it. \n", 119 | "\n", 120 | "Suppose we have two molecules `S1` and `S2`. Whilst we cannot rigorously calculate *the number of collisions* between `S1` and `S2`, occurring in `V` in any infinitesimal time interval, we can rigorously calculate *the probability of a collision* occurring between `S1` and `S2`, in `V` in any infinitesimal time interval:\n", 121 | "\n", 122 | "#### Calculating the propensity of each reaction (the collision/reaction probability per unit time)\n", 123 | "\n", 124 | "Let's begin with an **example**. Suppose the `S1` and `S2` molecules in `V` can undergo the reaction\n", 125 | "\n", 126 | "```\n", 127 | "R1: S1 + S2 -> 2S1\n", 128 | "```\n", 129 | "\n", 130 | "Then we may assert the existence of a constant `cl`, which depends only on the physical properties of the two molecules and the temperature of the system, such that `c1*dt` is *the average probability that a particular `S1-S2` molecular pair will react according to `R1` in the next infinitesimal time interval `dt`*.\n", 131 | "\n", 132 | "This implies that, if at time `t` there are `X1` of the `S1` molecules and `X2` of the `S2` molecules, making a total of `h1 = Xl*X2` distinct `S1-S2` pairs. Let `a1=h1*c1` then `a1*dt` is *the probability that an `R1` reaction will occur somewhere inside `V` in the next infinitesimal time interval `(t, t + dt)`*.\n", 133 | "\n", 134 | "\n", 135 | "\n", 136 | "Let us take another example. Consider the reverse of the reaction of `R1`:\n", 137 | "\n", 138 | "```\n", 139 | "R2: 2S1 -> S1 + S2\n", 140 | "```\n", 141 | "\n", 142 | "Then we would characterize this reaction by a constant `c2`, such that `c2*dt` is the average probability that a particular pair of `S1` molecules will react according to `R2` in the next `dt`. However, the number of distinct pairs of `S1` molecules in `V` is not `X1*X1` but `h2 = X1*(X1-1)/2!`. . Let `a2=h2*c2`. Hence, the probability that an `R2` reaction will occur somewhere inside `V` in the next time interval `dt` is `a2*dt`. \n", 143 | "\n", 144 | "Now, for the **general form**, suppose the volume `V` contains a mixture of `Xj` molecules of chemical species `Sj (j = 1, ..., N)` and suppose further that these `N` species can interreact through `M` specified chemical reaction channels `Ri (i = 1, ..., M)`. Then we may assert the existence of `M` constants `ci (i = 1, ..., M)`, which depend only on the physical properties of the molecules and the temperature of the system, such that `ci*dt` is the *the average probability that a particular combination of `Ri` reactant molecules will react accordingly in the next infinitesimal time interval dt*. \n", 145 | "\n", 146 | "Let `hi` be the total number of distinct combinations of `R_i` reactant molecules in `V` at time `t` (a simple algebraic expression calculated using the binomial coefficient of the stoichiometry of the reactants). Then, if we multiply `ci*dt` by `hi`, we will obtain the probability `ai*dt` (where `ai=hi*ci`) that an `Ri` reaction will occur somewhere inside `V` in the next infinitesimal time interval `(t, t + dt)`.\n", 147 | "\n", 148 | "**In summary**:\n", 149 | "- *the propensity of a reaction* `Ri (i = 1, ..., M)` is governed solely by the fundamental hypothesis that, for constants `ci`, which depends only on the physical properties of the reactants of `Ri`, `ci*dt` is *the average probability that the particular combination of `Ri` reactant molecules will react in the next infinitesimal time interval dt*. \n", 150 | "- furthermore, the probability of reaction `Ri` happening in the next time interval `(t, t + dt)` is calculated as the product `hi` of the total number of distinct combinations of `Ri` reactant molecules and `ci*dt`, i.e. `ai*dt` for `ai=hi*ci`.\n", 151 | "\n", 152 | "Note: `ci` is called the **stochastic rate constant**.\n", 153 | "\n", 154 | "-> (AH) Very important practical point. Here or later you should provide a way to convert between stochastic (ci) and deterministic (ci) rate constants. And illustrate it with examples.\n", 155 | "Show how to make these calculations for 0, 1st, 2nd and higher order reactions.\n", 156 | "Because in literature deterministic rate constants are normally shown. So one would need it to run stochastic simulations with given deterministic rates and to compare stoshastic simulations to ODE solutions. If needed, you can check our paper (Halavatyi, A.A., Nazarov, P.V., Medves, S., van Troys, M., Ampe, C., Yatskou, M., and Friederich, E. (2009). An integrative simulation model linking major biochemical reactions of actin-polymerization to structural properties of actin filaments. Biophys Chem 140, 24-34.)\n", 157 | "\n", 158 | "#### Calculating the time evolution of the system (that is modelled stochastically)\n", 159 | "\n", 160 | "Let us consider how to sample the time evolution of this system in a way that follows the probability density function of the Chemical Master Equation. Remember that the system is a Markov process, so it is enough to base the argument on the current state of the system. \n", 161 | "\n", 162 | "If we are given that the system is in the state `(X1,...,XN)` at time `t`, essentially all we need in order to “move the system forward in time” is to answer these two questions: \n", 163 | "\n", 164 | "1. when will the next reaction occur, and \n", 165 | "2. what kind of reaction will it be \n", 166 | "\n", 167 | "\n", 168 | "(**Side note on probability disctributions and sampling or drawing from them:** Suppose we have a data generating process, for example, the throwing of a dice. So long as the dice is fair, we know that we will only get numbers 1-6 and that each number has the same probablility as the others. This describes the probability distribution. Now, to draw or sample from the distribution means to throw the dice and record the outcome; we know the outcome has a specific probability, but we can not predict what the outcome will be. Eventually, after you have sampled enough, you can calculate numbers such as the mean (or expected value), the varialce, the quatiles and use these numbers to characterise the distribution. In this case, it is easy to see that the dice follows a uniform distribution.\n", 169 | "\n", 170 | "We can have a similar example with the heights of the people in the room, try it!)\n", 171 | "\n", 172 | "One way to obtain the next time `T` and reaction `mu`, could be to draw two random numbers `r1` and `r2` from the uniform distribution and to use them to calculate the next time and reaction with the following formulas:\n", 173 | "\n", 174 | "\n", 175 | "\n", 176 | "\n", 177 | "\n", 178 | "\n", 179 | "\n", 180 | "(Note that this relies on the propensities of the reactions that we calculated just above; in other words, the next reaction and time are influenced by the propencities of the reactions, but this make sense, since a reaction with a higher propensity should have a higher probabilty of happening than one with a lower propensity.)\n", 181 | "\n", 182 | "It is shown in Gillespie's paper that choosing the next time and reaction in this way, samples directly from the *probability density function* that is the Chemical Master Equation. (Note that this probability density function is a joint probability density function (also knows as a probability measure) of the continuous variable T (0<= T < inf), for the time of the next reaction, and the discrete variable (mu = 1, 2,. ..,M).)\n", 183 | "\n", 184 | "So, in practice, according to the calculations we have made above, of the reation propensities and the next time and reaction, to simulate a stochastic model of any simple chemical system you can just follow this algorithm (the Gillespie algorithm) below:\n", 185 | "\n", 186 | "\n", 187 | "\n", 188 | "and you already have all the tools you need to calculate each step." 189 | ] 190 | }, 191 | { 192 | "cell_type": "markdown", 193 | "metadata": {}, 194 | "source": [ 195 | "## Part 3. The stochastic simulation algorithm\n", 196 | "\n", 197 | "Now that we have the algorithm, we can program it into python so that we can then use it to simulate any simple chemical system. The rest of the tutorial is a collection of small exercises that together lead you to program your own Gillespie algorithm. The instuctions are given in human/maths language and you need to find the appropiate python commands to achieve those steps. Don't worry, we give you hint and you can always refer to the documentation.\n", 198 | "\n", 199 | "\n", 200 | "### Part 3.A. Let's go through one loop of the algorithm, each step (sort of) by hand\n", 201 | "\n", 202 | "We will use the following example system:\n", 203 | "\n", 204 | "```\n", 205 | "R1: S1 + S2 -> 2S1\n", 206 | "```\n", 207 | "\n", 208 | "For each of the steps, follow the instructions and hints and if necessary, check the python documentation." 209 | ] 210 | }, 211 | { 212 | "cell_type": "markdown", 213 | "metadata": {}, 214 | "source": [ 215 | "**Import the required libraries and modules**" 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "execution_count": 1, 221 | "metadata": { 222 | "collapsed": true 223 | }, 224 | "outputs": [], 225 | "source": [ 226 | "# import modules and libraries: numpy, factorial from scipy.special, pyplot from matplotlib\n", 227 | "# allow inline plot with %matplotlib inline" 228 | ] 229 | }, 230 | { 231 | "cell_type": "markdown", 232 | "metadata": {}, 233 | "source": [ 234 | "**Step 0 - Initialization:** \n", 235 | "- Input the desired values for the `M` reaction constants `c1,. ..,cM` and the `N` initial molecular population numbers `X1,...,XN`. \n", 236 | "- Set the time variable `t` and the reaction counter `n` both to zero. " 237 | ] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "execution_count": null, 242 | "metadata": { 243 | "collapsed": false 244 | }, 245 | "outputs": [], 246 | "source": [ 247 | "# reaction constants, c1\n", 248 | "\n", 249 | "print \"c1: \", c1\n", 250 | "\n", 251 | "# initial molecular population numbers X1 of S1 and X2 of S2, \n", 252 | "\n", 253 | "print \"X1: \", X1\n", 254 | "print \"X2: \", X2\n", 255 | "\n", 256 | "# initialise time variable t and reaction counter n\n", 257 | "\n", 258 | "print \"t: \", t\n", 259 | "print \"n: \", n" 260 | ] 261 | }, 262 | { 263 | "cell_type": "markdown", 264 | "metadata": {}, 265 | "source": [ 266 | "**Step 1 - calculate the ai and a0: ** \n", 267 | "- Calculate and store the `M` quantities `a1 = h1*c1,..., aM = hm*cm` for the current molecular population numbers. \n", 268 | "- To fasciliate the manipulation with python, save all the `ai`'s in an array `a`.\n", 269 | "- Calculate and store as `a_0` the sum of the `M` `a_i` values." 270 | ] 271 | }, 272 | { 273 | "cell_type": "code", 274 | "execution_count": null, 275 | "metadata": { 276 | "collapsed": false 277 | }, 278 | "outputs": [], 279 | "source": [ 280 | "# calculate a1 = h1*c1 where h1 is the total number of all possible \n", 281 | "# combinations of pairs S1 and S2\n", 282 | " # go back to the section where the propensities of the reactions were calculated to remind yourself \n", 283 | "\n", 284 | "# define an (numpy) array a with entries each ai\n", 285 | "\n", 286 | "# define a0 as the sum of all ai's\n", 287 | "\n", 288 | "# debug\n", 289 | "print \"a1: \", a1\n", 290 | "print \"a: \", a\n", 291 | "print \"a0: \", a0" 292 | ] 293 | }, 294 | { 295 | "cell_type": "markdown", 296 | "metadata": {}, 297 | "source": [ 298 | "**Step 2 - Get the next reaction and time of reaction: ** \n", 299 | "\n", 300 | "- Generate the pair `(T, mu)` from the set of random pairs whose probability density function is the Chemical Master Equation.\n", 301 | "- When calculating the next reaction, you need a while loop.\n", 302 | "- Recall that numbering in Python starts from 0, so be careful with indexing!" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": null, 308 | "metadata": { 309 | "collapsed": false 310 | }, 311 | "outputs": [], 312 | "source": [ 313 | "# generate random numbers r1 and r2 from the normal distribution, using np.random.random\n", 314 | "\n", 315 | "print \"r1: \", r1\n", 316 | "print \"r2: \", r2\n", 317 | "\n", 318 | "# find the increment T in time as (1/a0)*ln(1/r1)\n", 319 | "\n", 320 | "print \"T: \", T\n", 321 | "\n", 322 | "# choose next reaction\n", 323 | " # initialise mu to 0\n", 324 | " \n", 325 | " # define new variable N = r2*a0 - a[mu]\n", 326 | "\n", 327 | " # while N is positive\n", 328 | " \n", 329 | " # add 1 to mu\n", 330 | " \n", 331 | " # substract a_mu from N\n", 332 | " \n", 333 | " # when the while lopp breaks, allocate the current value of mu to the next reaction variable next_r\n", 334 | "\n", 335 | "print \"next_r: \", next_r" 336 | ] 337 | }, 338 | { 339 | "cell_type": "markdown", 340 | "metadata": {}, 341 | "source": [ 342 | "Does it make sense what the next reaction is?\n", 343 | "\n", 344 | "What happens if you run the code again? Does the same reaction get chosen? Does this make sense?\n", 345 | "\n", 346 | "Make sure that you understand how this while loop achieves the purpose of choosing the next reaction, correctly according to the theory given above, in section \"Calculating the time evolution of the system\"." 347 | ] 348 | }, 349 | { 350 | "cell_type": "markdown", 351 | "metadata": {}, 352 | "source": [ 353 | "**Step 3 - update the system: ** \n", 354 | "\n", 355 | "Using the `T` and `mu` values obtained in step 2, increase `t` by `T`, and adjust the molecular population levels to reflect the occurrence of one `R_i` reaction; e.g., if `R_i` is the reaction `R1`, then increase `X1` by `1` and decrease `X2` by `1`. Then increase the reaction counter `n` by `1`.\n", 356 | "\n", 357 | "(Note: for complicated networks with many reagents and reactions, it is enough to recalculate only those quantities `a_i` corresponding to reactions `R_i` whose reactant population levels were just altered in step 3; also, `a_0` may be recalculated simply by adding to `a_0` the difference between each newly changed `a_i` value and its corresponding old value. However, for simple networks such as this example, checking what changes and what not might take more time then recalculate all quantities a_i.)" 358 | ] 359 | }, 360 | { 361 | "cell_type": "code", 362 | "execution_count": null, 363 | "metadata": { 364 | "collapsed": false 365 | }, 366 | "outputs": [], 367 | "source": [ 368 | "# define the time of next reaction\n", 369 | "\n", 370 | "print \"t: \", t\n", 371 | "\n", 372 | "# add one to the number of reactions count n\n", 373 | "\n", 374 | "print \"n: \", n\n", 375 | "\n", 376 | "# update the system according to the reaction that was chosen\n", 377 | "\n", 378 | "print \"X1: \", X1\n", 379 | "print \"X2: \", X2" 380 | ] 381 | }, 382 | { 383 | "cell_type": "markdown", 384 | "metadata": {}, 385 | "source": [ 386 | "We have simulated the stochastic occurance of one reaction. We can visualise the effect of this reaction by plotting the time vs the concentration of the reactants as follows:" 387 | ] 388 | }, 389 | { 390 | "cell_type": "code", 391 | "execution_count": null, 392 | "metadata": { 393 | "collapsed": false 394 | }, 395 | "outputs": [], 396 | "source": [ 397 | "# create arrays containing all data\n", 398 | "\n", 399 | " # array with initial number of X1 and number after one reaction\n", 400 | " \n", 401 | " # array with initial number of X2 and number after one reaction\n", 402 | " \n", 403 | " # array with initial time and time of reaction one\n", 404 | "\n", 405 | "# create plot using pyplot, remeber to add a legend and annotate the axes\n" 406 | ] 407 | }, 408 | { 409 | "cell_type": "markdown", 410 | "metadata": {}, 411 | "source": [ 412 | "Return to 1 and repeat." 413 | ] 414 | }, 415 | { 416 | "cell_type": "markdown", 417 | "metadata": {}, 418 | "source": [ 419 | "### Part 3.B. - Automate the process\n", 420 | "\n", 421 | "So now, we need to do the same process many many times, to simulate the system to a maximum time (`tmax`) or maximum number of reactions (`nmax`) of our choice. \n", 422 | "\n", 423 | "It is not feasible to carry on typing the same commands every time we need to go through the loop until we reach either `tmax` or `nmax` and we need to implement an automated way of **looping** through the algorithm.\n", 424 | "\n", 425 | "So what should we use? You've guessed it - a while loop, because with a while loop we can test whether the `tmax` or `nmax` bounds have been reached and *while* they have not, we go through yet another loop of the algorithm.\n", 426 | "\n", 427 | "Additionally, to be able to visualise the output of every loop, we will also want to provide an automated way of storing the changing values of the reactants, rather than doing it by hand as we did above.\n", 428 | "\n", 429 | "Finally, it is always a good practice to implement a debugging strategy. We recommend defining a *pause* function that will ask the user (of the program) to press the `` key to continue and to print values that will help the user keep track of the algorithm.\n", 430 | "\n", 431 | "To implement these new changes, let's use a new biochemical system, that has more than one reaction. It is important that this system has more than one reaction because if you can write a program general enough to deal with more than one reaction, then there should be no problem with a system with more reactions. Let's use the following system:\n", 432 | "```\n", 433 | "R1: 2X1 + X2 -> X3\n", 434 | "R2: X1 -> 0\n", 435 | "```\n", 436 | "\n", 437 | "(**Note on how to represent this system of chemical equations in matrix form:** \n", 438 | "We can write any system on chemical equations in matrix form. First we choose a convention, for example, the rows of the matrix correspond to the reactions and the columns to the reactants. Next, we read off the effect that the reactions have on each of the reactants, for example, R1 consumes 2 (molecules) of X1 and 1 of X2 and produces 1 of X3. Finally, we recod these numbers i correcsponding matrix entries.\n", 439 | "\n", 440 | "For the example above, the array form for the system above would be:\n", 441 | "\n", 442 | "```\n", 443 | " X1 X2 X3\n", 444 | "R1 -2 -1 1\n", 445 | "R2 -1 0 0\n", 446 | "```\n", 447 | "\n", 448 | "You can also choose to write the stoichiometry of the substrates and producs, which which case you only take into account how the substrates/products are affected. So for example, the substrate stoichiometry array of the system above would be:\n", 449 | "\n", 450 | "```\n", 451 | " X1 X2 X3\n", 452 | "R1 -2 -1 0\n", 453 | "R2 -1 0 0\n", 454 | "```\n", 455 | "\n", 456 | "Can yu write the one for the products?)" 457 | ] 458 | }, 459 | { 460 | "cell_type": "markdown", 461 | "metadata": {}, 462 | "source": [ 463 | "#### Import required libraries" 464 | ] 465 | }, 466 | { 467 | "cell_type": "code", 468 | "execution_count": null, 469 | "metadata": { 470 | "collapsed": true 471 | }, 472 | "outputs": [], 473 | "source": [ 474 | "# import required libraries and modules: numpy, factorial from scipy.special, pyplot \n", 475 | "# enable inline plotting" 476 | ] 477 | }, 478 | { 479 | "cell_type": "markdown", 480 | "metadata": {}, 481 | "source": [ 482 | "#### Define debug function" 483 | ] 484 | }, 485 | { 486 | "cell_type": "code", 487 | "execution_count": null, 488 | "metadata": { 489 | "collapsed": false 490 | }, 491 | "outputs": [], 492 | "source": [ 493 | "# define a pause function for debugging\n", 494 | "\n", 495 | "#def ...\n", 496 | " \n", 497 | " # using the command raw_input, define a variable that prints out a message along the lines of \n", 498 | " # \"Press the key to continue...\" and take as input nothing.\n" 499 | ] 500 | }, 501 | { 502 | "cell_type": "markdown", 503 | "metadata": {}, 504 | "source": [ 505 | "#### Step 0 of algorithm" 506 | ] 507 | }, 508 | { 509 | "cell_type": "code", 510 | "execution_count": null, 511 | "metadata": { 512 | "collapsed": false 513 | }, 514 | "outputs": [], 515 | "source": [ 516 | "# **************************** \n", 517 | "# step 0: input rate values, initial contidions values and initialise time \n", 518 | "# and reactions counter\n", 519 | "# **************************** \n", 520 | "\n", 521 | "# Define the stoichiometry of the system as a numpy array, with the number of reactions in the rows \n", 522 | "# and the number of reactants in the columns. \n", 523 | "\n", 524 | " # Define the stochiometry of the substrates and products separatelly; Use the variable names \n", 525 | " # stoch_subst for the substrates and stoch_prods for the products\n", 526 | " \n", 527 | " # Using these define the stoch variable as the summ of stoch_subst and stoch_prods\n", 528 | "\n", 529 | " # Keep track of the following:\n", 530 | " # (i ranges 0 -> M-1, where M is the number of reactions, j ranges 0 -> N-1, where N is the \n", 531 | " # number of species)\n", 532 | "\n", 533 | " # allocate the number of reactions to variable num_rxn and number of species to varialbe num_spec,\n", 534 | " # use the command shape of numpy and array indexing\n", 535 | "\n", 536 | "# define the ci parameters in an array variable called rates\n", 537 | "\n", 538 | "# define the initial conditions of the reactants in an array variable init\n", 539 | "\n", 540 | "# specify the maximum time, tmax, and maximum number of reactions, nrmax\n", 541 | "\n", 542 | "# Initialise the current_species variable to init\n", 543 | "\n", 544 | "# Initialise the current time current_t and the time and reaction counters t_count \n", 545 | "# and react_count to 0\n", 546 | "\n", 547 | "# debug: print all the variables to check everything is correct" 548 | ] 549 | }, 550 | { 551 | "cell_type": "code", 552 | "execution_count": null, 553 | "metadata": { 554 | "collapsed": false, 555 | "scrolled": true 556 | }, 557 | "outputs": [], 558 | "source": [ 559 | "# Initialise variables to store time and molecule numbers\n", 560 | "\n", 561 | " # You need the arrays to be large enough to contain all the possible number of iterations the \n", 562 | " # algorithm goes through (which we don't know, a priori, how many iterations that will be). \n", 563 | " # Call this cariable largenum\n", 564 | "\n", 565 | " # Initialise a zeros array called store_t to store all the times of reactions (with dimensions largenum,1)\n", 566 | " \n", 567 | " # Initialise a zeros array called store_mols to store all reactants after each reaction \n", 568 | " # (with dimensions largenum,num_spec)\n", 569 | "\n", 570 | " # Initialise a zeros array called store_r to store all the reaction ids (with dimensions largenum,1)\n", 571 | "\n", 572 | "# debug by printing all the variables and check for correct numbers" 573 | ] 574 | }, 575 | { 576 | "cell_type": "code", 577 | "execution_count": null, 578 | "metadata": { 579 | "collapsed": false 580 | }, 581 | "outputs": [], 582 | "source": [ 583 | "# store current time and state\n", 584 | "\n", 585 | " # store current time of the system by indexing store_t with t_count (why?) and equating that entry it \n", 586 | " # to current_t\n", 587 | "\n", 588 | " # store current numbers of molecules of each species by indexing store_mols with [t_count,:] (why?) and \n", 589 | " # equating that row it to current_species\n", 590 | "\n", 591 | "# debug by printing 10 rows of the two arrays above and checking for correct recording of data\n" 592 | ] 593 | }, 594 | { 595 | "cell_type": "markdown", 596 | "metadata": {}, 597 | "source": [ 598 | "#### Define a function to automate the choosing of the next time and reaction and check it works correctly" 599 | ] 600 | }, 601 | { 602 | "cell_type": "code", 603 | "execution_count": 2, 604 | "metadata": { 605 | "collapsed": false 606 | }, 607 | "outputs": [], 608 | "source": [ 609 | "# define a function to choose the next time and reaction\n", 610 | "\n", 611 | "# define function with name choose_t_r and inputs a0 and a\n", 612 | " \n", 613 | " # generate random numbers r1 and r2 from the uniform distribution\n", 614 | " \n", 615 | " # choose the increment T in time as (1/a0)*ln(1/r1)\n", 616 | " \n", 617 | " # choose the next reaction \n", 618 | " \n", 619 | " # initialise S to sum(a)\n", 620 | " \n", 621 | " # initialise mu to 0\n", 622 | " \n", 623 | " # initialise to N= r2*a0 - a[mu]\n", 624 | "\n", 625 | " # while loop:\n", 626 | " \n", 627 | " # while N is positive\n", 628 | " \n", 629 | " # add one to mu\n", 630 | " \n", 631 | " # substract a[mu] from N\n", 632 | "\n", 633 | " # when the while loop breaks, allocate the current value of mu to next_r\n", 634 | "\n", 635 | " # return T and next_r\n", 636 | "\n", 637 | "\n", 638 | "# To debug choose_t_r write a function that runs choose_t_r 1000 times:\n", 639 | "\n", 640 | "# define function run_choose_t_r_many_times with input a, the array of ai's\n", 641 | "\n", 642 | " # define a0 as the sum of a\n", 643 | " \n", 644 | " # define a zeros array r with dimensions 1000,1, to store the outputs of each time choose_t_r is run\n", 645 | " \n", 646 | " # define a for loop with index i that ranges from 0-999\n", 647 | "\n", 648 | " # define a variable res that is the output of choose_t_r\n", 649 | "\n", 650 | " # store the choice of reaction, res, in r\n", 651 | " \n", 652 | " # plot a histogram of all the reactions chosen, using pyplot hist\n", 653 | "\n", 654 | " # make sure that the bins are centred at the integer values that correspond \n", 655 | " # to the reactions by defining an array bins with the bounds of each bin\n", 656 | " \n", 657 | " \n", 658 | "# Ask youself what you expect the histogram to look like, given the current parameter values:\n", 659 | " # Run function run_choose_t_r_many_times with different values of a:\n", 660 | " # By changing the values of a you can check that different reactions are being chosen \n", 661 | " # representatively with the system.\n", 662 | " # For example, for a = np.array([9000*0.0001, 10*1]), i.e. the rate for reaction R1 \n", 663 | " # is 0.0001 and for reaction R2 is 1, the proportions of choosing reaction R1 or R2 \n", 664 | " # should be similar, around 1:1, but for a = np.array([9000*0.01, 10*1]) R1 should \n", 665 | " # be chosen many more times than R2, in fact, on a ratio of around 10:1." 666 | ] 667 | }, 668 | { 669 | "cell_type": "markdown", 670 | "metadata": {}, 671 | "source": [ 672 | "#### Automate the calculation of the propensitites of the reactions" 673 | ] 674 | }, 675 | { 676 | "cell_type": "markdown", 677 | "metadata": {}, 678 | "source": [ 679 | "Think about how exactly to calculate the algebraic statement that equals `ai = hi*ci`.\n", 680 | "\n", 681 | "It is helpful to write down many examples in order to come up with a formula.\n", 682 | "\n", 683 | "Let's think through this particular example together:\n", 684 | "\n", 685 | "We have the substrate stoichiometry being\n", 686 | "\n", 687 | "```\n", 688 | " -2 -1 0\n", 689 | " -1 0 0\n", 690 | "```\n", 691 | "\n", 692 | "suppose we want to work out `hi` for `R1`. Let's start with `X1`. We know that the algebraic expression is `X1(X1-1)`. Notice that this is the same as the binomial coefficient `binom(X1,2)` multiplied by `2!`. (If you don't remember what the binomial coefficient is and how to calculate it, you can refer to the subsection below this explanation.)\n", 693 | "\n", 694 | "Now suppose that the substrate stoichiometry is\n", 695 | "\n", 696 | "```\n", 697 | " -3 -1 0\n", 698 | " -1 0 0\n", 699 | "```\n", 700 | "\n", 701 | "to calculate the algebraic expression for `X1`, we know it is `X1*(X1-1)*(X1-2)`, which equals `binom(X1,3)*3!`.\n", 702 | "\n", 703 | "We star to see a pattern here, can you write it down explicitly in Python language? The answer is below, but we encourage you to work it out for yourself. You will need the `binomial` and `factorial` functions. Also, be careful with the signs and remember that you can use the `absolute` function.\n", 704 | "\n", 705 | ".\n", 706 | "\n", 707 | ".\n", 708 | "\n", 709 | ".\n", 710 | "\n", 711 | ".\n", 712 | "\n", 713 | ".\n", 714 | "\n", 715 | ".\n", 716 | "\n", 717 | ".\n", 718 | "\n", 719 | ".\n", 720 | "\n", 721 | "If you did the hand calculations, you saw that to calculate `hi` you need the following formula:\n", 722 | "\n", 723 | "```\n", 724 | "hi = hi*binom(current_species[j],np.absolute(stoch_subst[i,j]))*factorial(np.absolute(stoch_subst[i,j]))\n", 725 | "```\n", 726 | "\n", 727 | "Unfortunatelly, python does not seem to have a binomial coefficient function, so we define it here (perhaps it is fortunate, it gives us a chance to practice writting a new function! Make sure you understand it). (If you know of an already existing function, let us know!)\n", 728 | "\n", 729 | "\n", 730 | "(**Side note on the binomial coefficient:** The binomial coefficient, say 4choose2 is the number of ways two objects can be chosen from four objects. For example if I have four letters, A, B, C and D, I can choose:\n", 731 | "```\n", 732 | "AB\n", 733 | "AC\n", 734 | "AD\n", 735 | "BC\n", 736 | "BD\n", 737 | "CB\n", 738 | "```\n", 739 | "and if you stare at this list for a while, you will convince yourself these are all the possible distinct ways of choosing 2 letters out of those 4. So the binomial coefficient 4choose2 = 6.\n", 740 | "\n", 741 | "In general, you do not write all the possibilities down. You use a formula: NchooseK = N!/K!(N-K)! where the factorial, say 5! means that you multiply all the integers from 5 down to 1 together, to get `5*4*3*2*1 = 120`.\n", 742 | "\n", 743 | "If you want to check various binomial coefficients, you can go to [WolframAlpha](http://www.wolframalpha.com/) and use binom[n,m] to make the calculations.)" 744 | ] 745 | }, 746 | { 747 | "cell_type": "code", 748 | "execution_count": null, 749 | "metadata": { 750 | "collapsed": false 751 | }, 752 | "outputs": [], 753 | "source": [ 754 | "# define a function to calculate the binomial coefficient\n", 755 | "def binom(n,m):\n", 756 | " b=[0]*(n+1)\n", 757 | " b[0]=1\n", 758 | " for i in xrange(1,n+1):\n", 759 | " b[i]=1\n", 760 | " j=i-1\n", 761 | " while j>0:\n", 762 | " b[j]+=b[j-1]\n", 763 | " j-=1\n", 764 | " return b[m]\n", 765 | "\n", 766 | "# debug - test binom\n" 767 | ] 768 | }, 769 | { 770 | "cell_type": "markdown", 771 | "metadata": {}, 772 | "source": [ 773 | "#### Write the main loop of the algorithm - Steps 1, 2 and 3" 774 | ] 775 | }, 776 | { 777 | "cell_type": "code", 778 | "execution_count": null, 779 | "metadata": { 780 | "collapsed": false, 781 | "scrolled": true 782 | }, 783 | "outputs": [], 784 | "source": [ 785 | "# Now we write the main loop. Remember it is important to print values and using \n", 786 | "# the pause function to help yourself to debug the program.\n", 787 | "\n", 788 | "# while loop current_t < tmax \n", 789 | " \n", 790 | " # **************************** \n", 791 | " # step 1: calculate ai and a0\n", 792 | " # **************************** \n", 793 | " \n", 794 | " # debug\n", 795 | " print \"step 1: calculate ai and a0\"\n", 796 | " \n", 797 | " # initialise variable a to a ones array of dimensions num_rxn,1\n", 798 | " \n", 799 | " # (recall i ranges 1 -> M, where M is the number of reactions, j ranges 1 -> N, \n", 800 | " # where N is the number of species)\n", 801 | " \n", 802 | " # make a for loop with index i that ranges from 0 to num_rxns\n", 803 | " \n", 804 | " # initialise hi to 1\n", 805 | "\n", 806 | " # make a for loop with index j that ranges from 0 to the number of species \n", 807 | " # (i.e. len(init))\n", 808 | " \n", 809 | " # check the reactant (i,j) of the substrate stoichiomety matrix is involved \n", 810 | " # in this reaction (use an if statement). \n", 811 | " # if not, continue to the next reactant \n", 812 | "\n", 813 | " # if yes, follow the steps below\n", 814 | " \n", 815 | " # check the reactant has molecules available (use an if statement)\n", 816 | " # if it does not, equate hi to 0 (why?) and go to the next reactant\n", 817 | " \n", 818 | " # if it does, calculate hi using the formula you worked out above.\n", 819 | " # at this stage, for debugging purposes, you might like to include\n", 820 | " # print statements of various values and using the pause function.\n", 821 | "\n", 822 | " # e.g. debug\n", 823 | " #print \"reaction (i):\", i\n", 824 | " #print \"reactant (j):\", j\n", 825 | " #print \"current_species[j]:\", current_species[j]\n", 826 | " #print \"stoch_subst[i,j]:\", stoch_subst[i,j]\n", 827 | " #print \"np.absolute(stoch_subst[i,j]):\", np.absolute(stoch_subst[i,j])\n", 828 | " #print \"binom(current_species[j],np.absolute(stoch_subst[i,j]):\", binom(current_species[j],np.absolute(stoch_subst[i,j])) \n", 829 | " #print \"factorial(np.absolute(stoch_subst[i,j])):\", factorial(np.absolute(stoch_subst[i,j]))\n", 830 | " #print \"int(factorial(np.absolute(stoch_subst[i,j]))):\", int(factorial(np.absolute(stoch_subst[i,j])))\n", 831 | " #print \"binom(current_species[j],np.absolute(stoch_subst[i,j]))*factorial(np.absolute(stoch_subst[i,j])):\", binom(current_species[j],np.absolute(stoch_subst[i,j]))*factorial(np.absolute(stoch_subst[i,j])) \n", 832 | " #pause()\n", 833 | " \n", 834 | " # save the current value of ai as hi*ci (i.e. hi*rates[i]) to variable a, at a[i]\n", 835 | " \n", 836 | " # save a0 as the sum of all a's\n", 837 | "\n", 838 | " \n", 839 | " # **************************** \n", 840 | " # step 2: choose next t and r\n", 841 | " # **************************** \n", 842 | "\n", 843 | " # debug\n", 844 | " print \"step 2: choose next t and r\"\n", 845 | "\n", 846 | " # run choose_t_r to get the change in time and the next reaction, save them to \n", 847 | " # variables dt and next_r\n", 848 | " \n", 849 | " \n", 850 | " # **************************** \n", 851 | " # step 3: update and store system\n", 852 | " # **************************** \n", 853 | " \n", 854 | " # debug\n", 855 | " print \"step 3: update and store system\"\n", 856 | " \n", 857 | " # update the system: \n", 858 | " \n", 859 | " # update current_t by adding T\n", 860 | " \n", 861 | " # update current_species by adding np.transpose(stoch[next_r,:]), why?\n", 862 | "\n", 863 | " # update the time counter t_count and reaction counter react_count by adding 1\n", 864 | " \n", 865 | " # store current system to store_t[t_count], store_mols[t_count,:], store_r[t_count]" 866 | ] 867 | }, 868 | { 869 | "cell_type": "markdown", 870 | "metadata": {}, 871 | "source": [ 872 | "#### Collect and plot results of simulations" 873 | ] 874 | }, 875 | { 876 | "cell_type": "code", 877 | "execution_count": null, 878 | "metadata": { 879 | "collapsed": false 880 | }, 881 | "outputs": [], 882 | "source": [ 883 | "# Get rid of empty entries in store_t, store_mols and store_r\n", 884 | " \n", 885 | "# plot the results of the simulation using pyplot, time on the y-axis and concentrations\n", 886 | "# on the x-axis, remember to add a legend and to label the axes\n", 887 | "\n", 888 | "# debug: plot a histogram of the reactions chosen by the algorithm (by plotting store_r)" 889 | ] 890 | }, 891 | { 892 | "cell_type": "markdown", 893 | "metadata": {}, 894 | "source": [ 895 | "### Part 3.C. Make the algorithm into a function so that you can run it with *any* biochemical system\n", 896 | "\n", 897 | "Now, it would be great if we could just call a function that would work for any set of reactions and that we can just run one line of code rather than the whole set up and while loop over and over. We do this below. (Note that you can now get rid of the debugging commands as we have tested every bit and it is all working and we want the program to run smoothly without user input.)\n", 898 | "\n", 899 | "#### Program the algorithm as a function" 900 | ] 901 | }, 902 | { 903 | "cell_type": "code", 904 | "execution_count": null, 905 | "metadata": { 906 | "collapsed": false 907 | }, 908 | "outputs": [], 909 | "source": [ 910 | "# ----------------------------\n", 911 | "# ----------------------------\n", 912 | "# IMPORT ALL NECESSARY LIBRARIES AND MODULES\n", 913 | "# ----------------------------\n", 914 | "# ----------------------------\n", 915 | "\n", 916 | "\n", 917 | "# ----------------------------\n", 918 | "# ----------------------------\n", 919 | "# DEFINE OTHER FUNCTIONS NECESSARY\n", 920 | "# ----------------------------\n", 921 | "# ----------------------------\n", 922 | "\n", 923 | "# define a function to choose the next time and reaction\n", 924 | "\n", 925 | "\n", 926 | "# define a function to calculate the binomial coefficient\n", 927 | "\n", 928 | "\n", 929 | "# ----------------------------\n", 930 | "# ----------------------------\n", 931 | "# DEFINE SIMULATION FUNCTION\n", 932 | "# ----------------------------\n", 933 | "# ----------------------------\n", 934 | "\n", 935 | "# define my_gillespie function with unput values init, rates, stoch_subst, stoch_prods, tmax, nrmax \n", 936 | "# and output values store_t, store_mols, store_r\n", 937 | " \n", 938 | " \n", 939 | " # --------------------------\n", 940 | " # set up\n", 941 | " # --------------------------\n", 942 | " \n", 943 | " # **************************** \n", 944 | " # step 0: input rate values, initial contidions values and initialise time and reactions counter\n", 945 | " # **************************** \n", 946 | " \n", 947 | " # define the stoichiometry (variable stoch) of the system as a numpy array as a sum of the substrate and product stoichiometries\n", 948 | " \n", 949 | " # initialise num_rxn and num_spec to the correct values\n", 950 | " \n", 951 | " # initialise current time and current species variables and the time and reaction counters, current_t, \n", 952 | " # current_species, t_count, react_count\n", 953 | " \n", 954 | " # initialise variables to store time and molecule numbers, largenum, store_t, store_mols, store_r\n", 955 | " \n", 956 | " # store current time and state of system in store_t and store_mols\n", 957 | " \n", 958 | " \n", 959 | " # --------------------------\n", 960 | " # main while loop\n", 961 | " # --------------------------\n", 962 | " \n", 963 | " # **************************** \n", 964 | " # step 1: calculate ai and a0\n", 965 | " # **************************** \n", 966 | " \n", 967 | " # initialise variable a to a ones array of dimensions num_rxn,1\n", 968 | " \n", 969 | " # make a for loop with index i that ranges from 0 to num_rxns\n", 970 | " \n", 971 | " # initialise hi to 1\n", 972 | "\n", 973 | " # make a for loop with index j that ranges from 0 to the number of species (i.e. len(init))\n", 974 | " \n", 975 | " # check the reactant (i,j) of the substrate stoichiomety matrix is involved \n", 976 | " # in this reaction (use an if statement). \n", 977 | " \n", 978 | " # if not, continue to the next reactant \n", 979 | "\n", 980 | " # if yes, follow the steps below\n", 981 | " \n", 982 | " # check the reactant has molecules available (use an if statement)\n", 983 | " # if it does not, equate hi to 0 (why?) and go to the next reactant\n", 984 | " \n", 985 | " # if it does, calculate hi using the formula you worked out above.\n", 986 | " # at this stage, for debugging purposes, you might like to include\n", 987 | " # print statements of various values and using the pause function.\n", 988 | " \n", 989 | " # save the current value of ai as hi*ci (i.e. hi*rates[i]) to variable a, at a[i]\n", 990 | " \n", 991 | " # save a0 as the sum of all a's\n", 992 | " \n", 993 | " # **************************** \n", 994 | " # step 2: choose next t and r\n", 995 | " # **************************** \n", 996 | "\n", 997 | " # run choose_t_r to get the change in time and the next reaction, save them to \n", 998 | " # variables T and next_r \n", 999 | " \n", 1000 | " # **************************** \n", 1001 | " # step 3: update and store system\n", 1002 | " # **************************** \n", 1003 | " \n", 1004 | " # update the system: \n", 1005 | " \n", 1006 | " # update current_t by adding T\n", 1007 | " \n", 1008 | " # update current_species by adding np.transpose(stoch[next_r,:]), why?\n", 1009 | "\n", 1010 | " # update the time counter t_count and reaction counter react_count by adding 1\n", 1011 | " \n", 1012 | " # store current system to store_t[t_count], store_mols[t_count,:], store_r[t_count]\n", 1013 | " \n", 1014 | " \n", 1015 | "\n", 1016 | " # store final output - get rid of empty entries in store_t, store_mols, store_r\n", 1017 | " \n", 1018 | " # return result" 1019 | ] 1020 | }, 1021 | { 1022 | "cell_type": "markdown", 1023 | "metadata": {}, 1024 | "source": [ 1025 | "#### Run a few simulations with different scenarios" 1026 | ] 1027 | }, 1028 | { 1029 | "cell_type": "code", 1030 | "execution_count": null, 1031 | "metadata": { 1032 | "collapsed": true 1033 | }, 1034 | "outputs": [], 1035 | "source": [ 1036 | "# ----------------------------\n", 1037 | "# ----------------------------\n", 1038 | "# RUN SIMULATION\n", 1039 | "# R1: X1 + X2 -> 2X1\n", 1040 | "# R2: X1 -> 0\n", 1041 | "# ----------------------------\n", 1042 | "# ----------------------------\n", 1043 | "\n", 1044 | "# ****************************\n", 1045 | "# step A: define rate values, initial contidions values, tmax and nrmax\n", 1046 | "# ****************************\n", 1047 | "\n", 1048 | "# define the stochiometry of the substrates and products separatelly\n", 1049 | "\n", 1050 | "# define the ci parameters (variable rates)\n", 1051 | "\n", 1052 | "# define the initial conditions of the reactants (variable init)\n", 1053 | "\n", 1054 | "# define the maximum time, tmax, and and maximum number of reactions, nrmax\n", 1055 | "\n", 1056 | "# ****************************\n", 1057 | "# step B: run simulation\n", 1058 | "# ****************************\n", 1059 | "\n", 1060 | "# ****************************\n", 1061 | "# step C: plot results of simulation in a graph\n", 1062 | "# ****************************\n", 1063 | "\n" 1064 | ] 1065 | }, 1066 | { 1067 | "cell_type": "code", 1068 | "execution_count": null, 1069 | "metadata": { 1070 | "collapsed": false 1071 | }, 1072 | "outputs": [], 1073 | "source": [ 1074 | "# ----------------------------\n", 1075 | "# ----------------------------\n", 1076 | "# RUN ANOTHER SIMULATION\n", 1077 | "# R1: D -> D + R\n", 1078 | "# R2: R -> R + P\n", 1079 | "# R3: R -> 0\n", 1080 | "# R4: P -> 0\n", 1081 | "# ----------------------------\n", 1082 | "# ----------------------------" 1083 | ] 1084 | }, 1085 | { 1086 | "cell_type": "markdown", 1087 | "metadata": {}, 1088 | "source": [ 1089 | "## Part 4. Next steps\n", 1090 | "\n", 1091 | "### Stochastic vs deterministic\n", 1092 | "\n", 1093 | "Probably the bext thing you can try to do it to compare the results of these stochastic simulations with results you would get when you model the same systems deterministically, with a system of Ordinary Differential Equations (ODEs). This will actually validate our stochastic simulation algorithm.\n", 1094 | "\n", 1095 | "Note that ODE modelling is performed in terms of concentrations and deterministic rate constants; and stochastic calculations are in stochastic constants and molecule numbers. So for the results to be comparable, we need to make conversions properly. Luckily, Gillespie spells this out for us in his paper and if you are interested, you can have a look at page 2343, section IIC. Connection with the Deterministic Reaction-Rate Constant. \n", 1096 | "\n", 1097 | "Recall the stochastic reaction rate constant is `c_i`, which we introduced in Part 2.\n", 1098 | "\n", 1099 | "Let's denote the deterministic rate constant for reaction `R_i` with `k_i`.\n", 1100 | "\n", 1101 | "The conclusion of Gillespie's analysis is that \n", 1102 | "\n", 1103 | "```\n", 1104 | "k_i = (V^(m-1))*c_i\n", 1105 | "```\n", 1106 | "\n", 1107 | "The presence of the factor `V^(m-1)`, where `m` is the number of reactant molecules in reaction `R_i`, is merely a consequence of the fact that the reaction-rate constant is normally used in differential equations that contain molecular concentrations (numbers of molecules per unit volume) rather than total numbers of molecules. For example, if reaction `R_i` had three reactant molecules, we would have `V^2` instead of `V`;if `R_i`had only one reactant molecule (a simple isomerization), the factor `V` would be absent.\n", 1108 | "\n", 1109 | "Furthermore, in general, if `R`, has `n` identical reactant molecules, then `c` will be larger than `k` by a factor of `n!`. So, for example, if we have `R: 2X1 -> X2` then `k=V*c/2`.\n", 1110 | "\n", 1111 | "So let's translate the following system and simulate it deterministically (if you need to learn this topic or prefresh your memory, we refer you to [this](https://github.com/karinsasaki/biomath-modelling-with-python) tutorial):\n", 1112 | "```\n", 1113 | "R1: D -> D + R\n", 1114 | "R2: R -> R + P\n", 1115 | "R3: R -> 0\n", 1116 | "R4: P -> 0\n", 1117 | "```\n", 1118 | "\n", 1119 | "We had defined the stochastic rate constants as follows:\n", 1120 | "\n", 1121 | "```\n", 1122 | "c1 = 0.01\n", 1123 | "c2 = 0.1\n", 1124 | "c3 = 0.0001\n", 1125 | "c4 = 0.0001\n", 1126 | "```\n", 1127 | "\n", 1128 | "Let's assume the volume of the system is 1, then the deterministic rate constants are:\n", 1129 | "\n", 1130 | "```\n", 1131 | "k1 = 0.01\n", 1132 | "k2 = 0.1\n", 1133 | "k2 = 0.0001\n", 1134 | "k2 = 0.0001\n", 1135 | "```\n", 1136 | "\n", 1137 | "The same! Why? because there is only one reactant molecule in each reaction.\n", 1138 | "\n", 1139 | "Now we show how to simulate the system deterministically:" 1140 | ] 1141 | }, 1142 | { 1143 | "cell_type": "code", 1144 | "execution_count": 1, 1145 | "metadata": { 1146 | "collapsed": false 1147 | }, 1148 | "outputs": [ 1149 | { 1150 | "data": { 1151 | "image/png": "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\n", 1152 | "text/plain": [ 1153 | "" 1154 | ] 1155 | }, 1156 | "metadata": {}, 1157 | "output_type": "display_data" 1158 | } 1159 | ], 1160 | "source": [ 1161 | "# import modules and libraries\n", 1162 | "import numpy as np\n", 1163 | "from scipy.integrate import odeint\n", 1164 | "import matplotlib.pyplot as plt\n", 1165 | "%matplotlib inline\n", 1166 | "\n", 1167 | "# Parameters\n", 1168 | "k1 = 0.01\n", 1169 | "k2 = 0.1\n", 1170 | "k3 = 0.0001\n", 1171 | "k4 = 0.0001\n", 1172 | "params = (k1, k2, k3, k4)\n", 1173 | "\n", 1174 | "# Initial conditions\n", 1175 | "D_0 = 1\n", 1176 | "R_0 = 0\n", 1177 | "P_0 = 0\n", 1178 | "ini = (D_0, R_0, P_0)\n", 1179 | "\n", 1180 | "# Time\n", 1181 | "dt = 0.1\n", 1182 | "t = np.arange(0,50,dt)\n", 1183 | "\n", 1184 | "# ODE system (in format used for odeint)\n", 1185 | "def myODE(init,t,params):\n", 1186 | " \n", 1187 | " k1, k2, k3, k4 = params\n", 1188 | " \n", 1189 | " D, R, P = init\n", 1190 | "\n", 1191 | " # rates\n", 1192 | " v1 = k1*D\n", 1193 | " v2 = k2*R\n", 1194 | " v3 = k3*R\n", 1195 | " v4 = k4*P\n", 1196 | " \n", 1197 | " # equations\n", 1198 | " dD = 0\n", 1199 | " dR = v1 + v2 - v3\n", 1200 | " dP = v2 - v4\n", 1201 | " \n", 1202 | " return (dD, dR, dP)\n", 1203 | "\n", 1204 | "# Solve using odeint from scipy.integrate\n", 1205 | "solution = odeint(myODE,ini,t,args=(params,)) \n", 1206 | "tD = solution[:,0]\n", 1207 | "tR = solution[:,1]\n", 1208 | "tP = solution[:,2]\n", 1209 | "\n", 1210 | "# Show over time\n", 1211 | "fig, ax = plt.subplots()\n", 1212 | "ax.plot(t, tD, label='D')\n", 1213 | "ax.plot(t, tR, label='R')\n", 1214 | "ax.plot(t, tP, label='P')\n", 1215 | "plt.xlabel('time')\n", 1216 | "plt.ylabel('concentration')\n", 1217 | "legend = ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n", 1218 | "plt.show()" 1219 | ] 1220 | }, 1221 | { 1222 | "cell_type": "markdown", 1223 | "metadata": {}, 1224 | "source": [ 1225 | "### Exercise\n", 1226 | "\n", 1227 | "Demonstrate the effect of sample volume on the simulation results. Keep concentration the same and run simulations for different volumes (each time converting concentrations to molecule numbers). Show that for small volumes stoshastic curves are not completely reproducible and deviate from deterministic solution. For large volumes stochastic and deterministic solutions should be very close.\n" 1228 | ] 1229 | }, 1230 | { 1231 | "cell_type": "code", 1232 | "execution_count": null, 1233 | "metadata": { 1234 | "collapsed": true 1235 | }, 1236 | "outputs": [], 1237 | "source": [] 1238 | }, 1239 | { 1240 | "cell_type": "code", 1241 | "execution_count": null, 1242 | "metadata": { 1243 | "collapsed": true 1244 | }, 1245 | "outputs": [], 1246 | "source": [] 1247 | }, 1248 | { 1249 | "cell_type": "code", 1250 | "execution_count": null, 1251 | "metadata": { 1252 | "collapsed": true 1253 | }, 1254 | "outputs": [], 1255 | "source": [] 1256 | }, 1257 | { 1258 | "cell_type": "markdown", 1259 | "metadata": {}, 1260 | "source": [ 1261 | "\n", 1262 | "## Part 5. The end\n", 1263 | "\n", 1264 | "Next, as we have metioned before, the algorithm that we have written here is not the most computationally speedy and there are modifications of the Gillespie algorithm that are much more efficient. You could have a look at the difference in efficiency with the reaction method (Gibson & Bruck) and the tau-leaping method.\n", 1265 | "\n", 1266 | "\n", 1267 | "This is the end of the tutorial. Good job on finishing it! " 1268 | ] 1269 | } 1270 | ], 1271 | "metadata": { 1272 | "kernelspec": { 1273 | "display_name": "Python 2", 1274 | "language": "python", 1275 | "name": "python2" 1276 | }, 1277 | "language_info": { 1278 | "codemirror_mode": { 1279 | "name": "ipython", 1280 | "version": 2 1281 | }, 1282 | "file_extension": ".py", 1283 | "mimetype": "text/x-python", 1284 | "name": "python", 1285 | "nbconvert_exporter": "python", 1286 | "pygments_lexer": "ipython2", 1287 | "version": "2.7.12" 1288 | } 1289 | }, 1290 | "nbformat": 4, 1291 | "nbformat_minor": 0 1292 | } 1293 | -------------------------------------------------------------------------------- /.ipynb_checkpoints/deterministic_modelling-checkpoint.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "collapsed": true 7 | }, 8 | "source": [ 9 | "# Deterministic modelling\n", 10 | "\n", 11 | "\n", 12 | "### Translating of the problem into ODE language\n", 13 | "\n", 14 | "If we assume that:\n", 15 | "1. the number of molecules of the ith species in V at time t can be represented by a continuous, single-valued function X_i(t) (i= 1,...,N),\n", 16 | "2. each of the M chemical reactions can be regarded as a continuous rate process, \n", 17 | "\n", 18 | "then we can construct a set of coupled, first-order, ordinary differential equations of the form\n", 19 | "\n", 20 | "\n", 21 | "\n", 22 | "The specific forms of the functions f_i are determined by the structures and rate constants of the M chemical reaction channels, and are called the *reaction-rate equations*. Solving them for the X_i(t), subject to the prescribed initial conditions, is tantamount to solving the time-evolution problem posed earlier. Reliably solving reaction-rate equations on a computer is simple and can be learned from the tutorial on \"deterministic models of biochemical reactions\"." 23 | ] 24 | } 25 | ], 26 | "metadata": { 27 | "kernelspec": { 28 | "display_name": "Python 2", 29 | "language": "python", 30 | "name": "python2" 31 | }, 32 | "language_info": { 33 | "codemirror_mode": { 34 | "name": "ipython", 35 | "version": 2 36 | }, 37 | "file_extension": ".py", 38 | "mimetype": "text/x-python", 39 | "name": "python", 40 | "nbconvert_exporter": "python", 41 | "pygments_lexer": "ipython2", 42 | "version": "2.7.11" 43 | } 44 | }, 45 | "nbformat": 4, 46 | "nbformat_minor": 0 47 | } 48 | -------------------------------------------------------------------------------- /MATLAB-Gillespie/nedelec_francois_gillespie.m: -------------------------------------------------------------------------------- 1 | function [ ht, hn ] = francois_gillespie(stoch, rates, initial, tmax) 2 | 3 | % function [ ht, hn ] = gillespie(stoch, rates, initial, tmax) 4 | % 5 | % Simulate a system of reactions defined in a stoichiometry matrix for a time `tmax`, 6 | % with a set of rates and the initial abundance of each species. 7 | % The system of reaction is simulated stochastically with Gillespie's method. 8 | % 9 | % `stoch` is a stoichiometry matrix: 10 | % its number of lines should be the number of reaction 11 | % its number of column should be the number of species 12 | % the vector `rates` should provide the rate of each reaction specified in `stoch` 13 | % the vector `initial` specifies the initial aboundance of each species. 14 | % 15 | % The output is a vector of time `ht`, and a matrix `hn` containing the number of each species, 16 | % for every time point. 17 | % 18 | % 19 | % Example: to simulate a simple decay: 20 | % A -> B with rate kA 21 | % 22 | % [ ht, hn ] = gillespie([-1], [kA], [nA], 100); 23 | % plot(ht, hn); 24 | % 25 | % Example: to simulate an equilibrium: 26 | % A -> B with rate kA 27 | % B -> A with rate kB 28 | % 29 | % [ ht, hn ] = gillespie([ -1, 1; 1, -1 ], [kA, kB], [nA, nB], 100); 30 | % plot(ht, hn); 31 | % 32 | % 33 | % Copyright F. Nedelec, 09.2014 34 | 35 | 36 | 37 | 38 | [ nreac, nspec ] = size(stoch); 39 | 40 | if length(rates) ~= nreac 41 | error('the rate vector does not match the number of reactions'); 42 | end 43 | rates = reshape(rates, nreac, 1); 44 | 45 | if length(initial) ~= nspec 46 | error('the initial state vector does not match the number of species'); 47 | end 48 | 49 | t = 0; 50 | n = reshape(initial, 1, nspec); 51 | vo = ones(nreac, 1); 52 | stoch_in = -stoch .* ( stoch < 0 ); 53 | 54 | est = ceil( 2 * sum(initial) * sum(rates) * tmax ); 55 | ht = zeros(est, 1); 56 | hn = zeros(est, nspec); 57 | 58 | 59 | tix = 1; 60 | ht(tix) = t; 61 | hn(tix, :) = n; 62 | 63 | while t < tmax; 64 | 65 | pp = prod(power(vo * n, stoch_in), 2) .* rates; 66 | [dt, ix] = gillespie_choice(pp); 67 | t = t + dt; 68 | n = n + stoch(ix, :); 69 | 70 | tix = tix + 1; 71 | ht(tix) = t; 72 | hn(tix, :) = n; 73 | 74 | end 75 | 76 | ht = ht(1:tix); 77 | hn = hn(1:tix, :); 78 | 79 | end -------------------------------------------------------------------------------- /MATLAB-Gillespie/nedelec_gillespie_choice.m: -------------------------------------------------------------------------------- 1 | function [ T, N ] = gillespie_choice(rates) 2 | 3 | % set the time delay T, and the index N of the next reaction 4 | % according to Gillespie's procedure. 5 | % The input is a vector of reaction rates. 6 | % 7 | % Two random numbers are used. 8 | % F. Nedelec, 2012 9 | 10 | S = sum(rates); 11 | 12 | T = -log(rand) / S; 13 | 14 | N = 1; 15 | X = rand * S - rates(1); 16 | 17 | while X > 0 18 | N = N + 1; 19 | X = X - rates(N); 20 | end 21 | 22 | 23 | end -------------------------------------------------------------------------------- /Papers/Erban2007.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/Papers/Erban2007.pdf -------------------------------------------------------------------------------- /Papers/Gillespie1976.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/Papers/Gillespie1976.pdf -------------------------------------------------------------------------------- /Papers/Gillespie1977.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/Papers/Gillespie1977.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Gillespie algorithm with Python 2 | 3 | ## AIM 4 | 5 | Understand the Gillespie Algorithm and build it yourself in Python. 6 | 7 | 8 | ## REQUIREMENTS 9 | - Python 2.7 (we recommend the Anaconda distribution, which includes most of the required modules) 10 | - Modules: NumPy, SciPy 11 | 12 | 13 | ## INSTRUCTIONS TO FOLLOW THE TUTORIAL 14 | 15 | - Files you should have: ipython notebook titled build_your_own_gillespie.ipnb 16 | - To start the ipython notebooks: 17 | - On Mac: 18 | - start a new terminal window and type “jupyter notebook”, then press enter. When a new browser window opens, navigate to the folder where you have saved the tutorials. Click on the tutorial that you want to follow. 19 | - On Windows: 20 | - Open Command Prompt (cmd); in the command prompt change the current path to either directory containing tutorial or any of its parents (cd [disk_label]:/path/to/directory) (otherwise I can not navigate to the needed folder in browser later on); then you can run "jupyter notebook" from the command prompt. 21 | - Using Jupyter notebook: When you want to type code into a cell, simply click on it to activate it. When you want to run the code, press shift+enter. You can learn how to use Jupyter notebooks from, e.g., https://jupyter-notebook-beginner-guide.readthedocs.io/en/latest/ 22 | - The tutorial is self explanatory, indicating the steps to be taken next, what you should aim at achieving after carrying out those steps and the commands that could be used (there is not a one correct answer; these are suggestions). 23 | - With this exercise we want to encourage you to become a more independent programmer, so if there is a command you don't quite know how to use, make sure you read the documentation. To do so, most of the time is enough to google the words 'documentation, python' and the name of the module or function you want to use. 24 | - If you are following this tutorial in class, if you have any questions, raise your hand and someone will come to help you. 25 | 26 | 27 | ## OTHER MATERIALS 28 | - We provide you with the original paper by Gillespie where he builds the algorithm and other relevant papers 29 | - We also share with you a Gillespie algorithm written in MATLAB, by Francois Nedelec (EMBL). 30 | 31 | 32 | ## FEEDBACK 33 | Feel free to send your query to: 34 | karin.sasaki@embl.de 35 | 36 | 37 | -------------------------------------------------------------------------------- /a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/a.png -------------------------------------------------------------------------------- /a0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/a0.png -------------------------------------------------------------------------------- /alg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/alg.png -------------------------------------------------------------------------------- /algo_im.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/algo_im.png -------------------------------------------------------------------------------- /b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/b.png -------------------------------------------------------------------------------- /build_your_own_gillespie_exercises.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Build your own Gillespie algorithm \n", 8 | "\n", 9 | "\n", 10 | "In this tutorial you will learn in detail about the ~~deterministic~~ *stochastic* formalism for the *temporal* modelling of *simple*\\* chemical systems, and you will learn to write the *Gillespie algorithm*, from scratch, using Python 2.7.\n", 11 | "\n", 12 | "\\* the word *simple* referst to \"spatially homogenous\" (i.e. spatially uniform mixture of chemical species, as opposed to spatially varied, where you could find regions with higher concentrations of some molecules but not others).\n", 13 | "\n", 14 | "As you can already imagine, there are many Gillespie algorithm scripts out there, available for you to download freely and use for your simulations. (In particular modifications of the Gillespie algorithm such as the reaction method (Gibson & Bruck) and the tau-leaping are very efficient.) We think it is advantageous in many ways to understand how this formalism is constructed. It will help you, for example, decide in what contexts this framework is more appropiate, and understand the reasons why you might get different results with the deterministic and stochastic approaches.\n", 15 | "\n", 16 | "\n", 17 | "### To note\n", 18 | "\n", 19 | "If you would like to learn in detail about the *deterministic* framework for modelling the temporal evolution of simple chemical systems, we refer you to [this](https://github.com/karinsasaki/biomath-modelling-with-python) tutorial.\n", 20 | "\n", 21 | "The tutorial you currently hold deals only with modelling the evolution of a chemical system, in *time*. If you would like to learn to desing a *spatial* model and simulate it, we refer you to [this (coming soon)]() tutorial.\n", 22 | "\n", 23 | "\n", 24 | "### Structure of tutorial\n", 25 | "\n", 26 | "In **Part 1** we introduce and characterise the stochastic framework as a mathematical model of simple systems of chemical reactions.\n", 27 | "\n", 28 | "In **Part 2** we set the problem that needs to be solved, in precise mathematical formulation.\n", 29 | "\n", 30 | "In **Part 3** we provide steps to help you build your own Gillespie agorithm.\n", 31 | "\n", 32 | "\n", 33 | "### References\n", 34 | "\n", 35 | "The tutorial is heavily based on Gillespie's original 1977 [paper](http://wwwf.imperial.ac.uk/~nsjones/gillespie_1977.pdf) and we will often quote text directly from the paper. \n", 36 | "\n", 37 | "The Wikipedia [page](https://en.wikipedia.org/wiki/Mathematical_model) on Mathematical Models.\n", 38 | "\n", 39 | "\n", 40 | "### Acknowledgements\n", 41 | "\n", 42 | "This tutorial was make by Dr. Karin Sasaki (Centre for Biological Modelling at the European Molecular Biology Laboratory)." 43 | ] 44 | }, 45 | { 46 | "cell_type": "markdown", 47 | "metadata": {}, 48 | "source": [ 49 | "## Part 1. Characterisation of stochastic mathematical models of the time behaviour of spatially homogenous chemical systems.\n", 50 | "\n", 51 | "### The *stochastic approach* or framework:\n", 52 | "\n", 53 | "1. The time evolution is regarded as a kind of random-walk process. (A *deterministic model*, in contrast, regards the time evolution as a continuous, wholly predictable process.)\n", 54 | "2. The time evolution of the system is governed by differential-difference equations called “master equations” or is computationally calculated exactly by the Gillespie algorithm. (In a *deterministic model*, the time evolution of the system is governed by a set of coupled, ordinary differential equations called the “reaction-rate equations”.)\n", 55 | "\n", 56 | "\n", 57 | "### Reasoning behind the stochastic framework\n", 58 | "\n", 59 | "1. The time evolution of a chemically reacting system is not a continuous process, because molecular population levels obviously can change only by discrete integer amounts. \n", 60 | "2. The time evolution is not a deterministic process, for, the molecular motions are regarded to be governed by the equations of classical mechanics, it is impossible to predict the exact molecular population levels at some future time, unless we take account of the precise positions and velocities of all the molecules in the system. In other words, although the temporal behavior of a chemically reacting system of classical molecules is a deterministic process in the full position-momentum phase space of the system, it is not a deterministic process in the N-dimensional subspace of the species population numbers.\n", 61 | "\n", 62 | "\n", 63 | "### Classification of stochastic models as mathematical models\n", 64 | "\n", 65 | "* **The stochastic model is linear (not nonlinear)** - because chemical reactions exihibit linear relationships between the reactants. For example, an enzymatic reaction \n", 66 | " \n", 67 | " S + E <-> SE -> E + P\n", 68 | " \n", 69 | "is broken down into\n", 70 | "\n", 71 | " S + E -> SE\n", 72 | " SE -> S + E\n", 73 | " SE -> E + P\n", 74 | " \n", 75 | "which all have linear relations between the reactants and products. Note that a linear model does not necessarily predic non-linear expressions.\n", 76 | "\n", 77 | "* **Stochastic models are dynamic (not static i.e. time-invariant)** - because they accounts for time-dependent changes in the state of the system. (A *static model* calculates the system in equillibrium. An example is Flux Balance Analysis of metabolic models using linear programming).\n", 78 | "\n", 79 | "* **Stochastic models are explicit** - all of the input parameters of the overall model are known, and the output parameters can be calculated by a finite series of computations \n", 80 | "\n", 81 | "* **Stochastic models are not always discrete** - a discrete model is one where objects are treated as discrete entities. (A *continuous model* represents the objects in a continuous manner, for example, chemical reactions can be regarded as a continuous rate processes). Chemical master equations do not need to be discrete, as they describe probabilites; in simple cases it might be even possible to solve them without simulation algorithms e.g to calculate probabilities of system states as function of times. Discrete event simulations, such as the Gillespie algorithm, represent just one way (most useful practically) to solve chemical master equations. \n", 82 | "\n", 83 | "* **Stochastic models are probabilistic and not deterministic** - randomness is included in the model in order to capture inherent fluctuations in the molecular population levels. Therefore variable states are described by probability distributions and these models can perform differently for the same set of initial conditions. (A deterministic model is one where the variable states are uniquely determined by parameters in the model and by sets of previous states of these variables. Therefore, a deterministic model always performs the same way for a given set of initial conditions.)" 84 | ] 85 | }, 86 | { 87 | "cell_type": "markdown", 88 | "metadata": { 89 | "collapsed": true 90 | }, 91 | "source": [ 92 | "# Part 2. Setting the problem and translating it into mathematical formalism\n", 93 | "\n", 94 | "### The problem we want to solve\n", 95 | "\n", 96 | "The system:\n", 97 | "\n", 98 | "M chemical reactions `R1, ... ,RM` that involve `N` chemical species `S1, ..., SN`. \n", 99 | "\n", 100 | "The question:\n", 101 | "\n", 102 | "Given `X1, ..., XN` number of particles for each of the species, at some initial time, what will these molecular population levels be at a later time?\n", 103 | "\n", 104 | "\n", 105 | "### Modelling the system stochastically - Translating of the problem into stochastic language \n", 106 | "\n", 107 | "#### Assumptions of the stochastic framework\n", 108 | "\n", 109 | "1. A fixed volume `V` \n", 110 | "2. `V` contains a spatially uniform mixture of `N` chemical species\n", 111 | "3. The chemical species are in thermal (but not necessarily chemical) equilibrium, which means that collisions occur in an essentially random manner.\n", 112 | "3. A chemical reaction occurs whenever two or more molecules of \"appropriate kinds\" (defined by the reaction equations) collide in an \"appropriate way\" (assuming that the two molecules `S1` and `S2` are hard spheres of radii `rl` and `r2`, a collision will occur between them whenever the center-to-center distance between the two molecules decreases to `r12= r1 + r2`). \n", 113 | "4. All collisions are reactive, i.e. they result in chemical alterations of the colliding molecules as defined by the reaction equations.\n", 114 | "\n", 115 | "\n", 116 | "#### A simple chemical system modelled stochastically is characterised by a \"collision/reaction probability per unit time\" (i.e. it is a stochastic Markov process) and not by a \"collision rate\" (i.e. a deterministic rate process)\n", 117 | "\n", 118 | "**Side note:** A stochastic Markov process is one that satisfies the so called *Markov property*, which says that the conditional probability distribution of future states of a process depends only upon the present state, not on the sequence of events that preceded it. \n", 119 | "\n", 120 | "Suppose we have two molecules `S1` and `S2`. Whilst we cannot rigorously calculate *the number of collisions* between `S1` and `S2`, occurring in `V` in any infinitesimal time interval, we can rigorously calculate *the probability of a collision* occurring between `S1` and `S2`, in `V` in any infinitesimal time interval:\n", 121 | "\n", 122 | "#### Calculating the propensity of each reaction (the collision/reaction probability per unit time)\n", 123 | "\n", 124 | "Let's begin with an **example**. Suppose the `S1` and `S2` molecules in `V` can undergo the reaction\n", 125 | "\n", 126 | "```\n", 127 | "R1: S1 + S2 -> 2S1\n", 128 | "```\n", 129 | "\n", 130 | "Then we may assert the existence of a constant `cl`, which depends only on the physical properties of the two molecules and the temperature of the system, such that `c1*dt` is *the average probability that a particular `S1-S2` molecular pair will react according to `R1` in the next infinitesimal time interval `dt`*.\n", 131 | "\n", 132 | "This implies that, if at time `t` there are `X1` of the `S1` molecules and `X2` of the `S2` molecules, making a total of `h1 = Xl*X2` distinct `S1-S2` pairs. Let `a1=h1*c1` then `a1*dt` is *the probability that an `R1` reaction will occur somewhere inside `V` in the next infinitesimal time interval `(t, t + dt)`*.\n", 133 | "\n", 134 | "\n", 135 | "\n", 136 | "Let us take another example. Consider the reverse of the reaction of `R1`:\n", 137 | "\n", 138 | "```\n", 139 | "R2: 2S1 -> S1 + S2\n", 140 | "```\n", 141 | "\n", 142 | "Then we would characterize this reaction by a constant `c2`, such that `c2*dt` is the average probability that a particular pair of `S1` molecules will react according to `R2` in the next `dt`. However, the number of distinct pairs of `S1` molecules in `V` is not `X1*X1` but `h2 = X1*(X1-1)/2!`. . Let `a2=h2*c2`. Hence, the probability that an `R2` reaction will occur somewhere inside `V` in the next time interval `dt` is `a2*dt`. \n", 143 | "\n", 144 | "Now, for the **general form**, suppose the volume `V` contains a mixture of `Xj` molecules of chemical species `Sj (j = 1, ..., N)` and suppose further that these `N` species can interreact through `M` specified chemical reaction channels `Ri (i = 1, ..., M)`. Then we may assert the existence of `M` constants `ci (i = 1, ..., M)`, which depend only on the physical properties of the molecules and the temperature of the system, such that `ci*dt` is the *the average probability that a particular combination of `Ri` reactant molecules will react accordingly in the next infinitesimal time interval dt*. \n", 145 | "\n", 146 | "Let `hi` be the total number of distinct combinations of `R_i` reactant molecules in `V` at time `t` (a simple algebraic expression calculated using the binomial coefficient of the stoichiometry of the reactants). Then, if we multiply `ci*dt` by `hi`, we will obtain the probability `ai*dt` (where `ai=hi*ci`) that an `Ri` reaction will occur somewhere inside `V` in the next infinitesimal time interval `(t, t + dt)`.\n", 147 | "\n", 148 | "**In summary**:\n", 149 | "- *the propensity of a reaction* `Ri (i = 1, ..., M)` is governed solely by the fundamental hypothesis that, for constants `ci`, which depends only on the physical properties of the reactants of `Ri`, `ci*dt` is *the average probability that the particular combination of `Ri` reactant molecules will react in the next infinitesimal time interval dt*. \n", 150 | "- furthermore, the probability of reaction `Ri` happening in the next time interval `(t, t + dt)` is calculated as the product `hi` of the total number of distinct combinations of `Ri` reactant molecules and `ci*dt`, i.e. `ai*dt` for `ai=hi*ci`.\n", 151 | "\n", 152 | "Note: `ci` is called the **stochastic rate constant**.\n", 153 | "\n", 154 | "-> (AH) Very important practical point. Here or later you should provide a way to convert between stochastic (ci) and deterministic (ci) rate constants. And illustrate it with examples.\n", 155 | "Show how to make these calculations for 0, 1st, 2nd and higher order reactions.\n", 156 | "Because in literature deterministic rate constants are normally shown. So one would need it to run stochastic simulations with given deterministic rates and to compare stoshastic simulations to ODE solutions. If needed, you can check our paper (Halavatyi, A.A., Nazarov, P.V., Medves, S., van Troys, M., Ampe, C., Yatskou, M., and Friederich, E. (2009). An integrative simulation model linking major biochemical reactions of actin-polymerization to structural properties of actin filaments. Biophys Chem 140, 24-34.)\n", 157 | "\n", 158 | "#### Calculating the time evolution of the system (that is modelled stochastically)\n", 159 | "\n", 160 | "Let us consider how to sample the time evolution of this system in a way that follows the probability density function of the Chemical Master Equation. Remember that the system is a Markov process, so it is enough to base the argument on the current state of the system. \n", 161 | "\n", 162 | "If we are given that the system is in the state `(X1,...,XN)` at time `t`, essentially all we need in order to “move the system forward in time” is to answer these two questions: \n", 163 | "\n", 164 | "1. when will the next reaction occur, and \n", 165 | "2. what kind of reaction will it be \n", 166 | "\n", 167 | "\n", 168 | "(**Side note on probability disctributions and sampling or drawing from them:** Suppose we have a data generating process, for example, the throwing of a dice. So long as the dice is fair, we know that we will only get numbers 1-6 and that each number has the same probablility as the others. This describes the probability distribution. Now, to draw or sample from the distribution means to throw the dice and record the outcome; we know the outcome has a specific probability, but we can not predict what the outcome will be. Eventually, after you have sampled enough, you can calculate numbers such as the mean (or expected value), the varialce, the quatiles and use these numbers to characterise the distribution. In this case, it is easy to see that the dice follows a uniform distribution.\n", 169 | "\n", 170 | "We can have a similar example with the heights of the people in the room, try it!)\n", 171 | "\n", 172 | "One way to obtain the next time `T` and reaction `mu`, could be to draw two random numbers `r1` and `r2` from the uniform distribution and to use them to calculate the next time and reaction with the following formulas:\n", 173 | "\n", 174 | "\n", 175 | "\n", 176 | "\n", 177 | "\n", 178 | "\n", 179 | "\n", 180 | "(Note that this relies on the propensities of the reactions that we calculated just above; in other words, the next reaction and time are influenced by the propencities of the reactions, but this make sense, since a reaction with a higher propensity should have a higher probabilty of happening than one with a lower propensity.)\n", 181 | "\n", 182 | "It is shown in Gillespie's paper that choosing the next time and reaction in this way, samples directly from the *probability density function* that is the Chemical Master Equation. (Note that this probability density function is a joint probability density function (also knows as a probability measure) of the continuous variable T (0<= T < inf), for the time of the next reaction, and the discrete variable (mu = 1, 2,. ..,M).)\n", 183 | "\n", 184 | "So, in practice, according to the calculations we have made above, of the reation propensities and the next time and reaction, to simulate a stochastic model of any simple chemical system you can just follow this algorithm (the Gillespie algorithm) below:\n", 185 | "\n", 186 | "\n", 187 | "\n", 188 | "and you already have all the tools you need to calculate each step." 189 | ] 190 | }, 191 | { 192 | "cell_type": "markdown", 193 | "metadata": {}, 194 | "source": [ 195 | "## Part 3. The stochastic simulation algorithm\n", 196 | "\n", 197 | "Now that we have the algorithm, we can program it into python so that we can then use it to simulate any simple chemical system. The rest of the tutorial is a collection of small exercises that together lead you to program your own Gillespie algorithm. The instuctions are given in human/maths language and you need to find the appropiate python commands to achieve those steps. Don't worry, we give you hint and you can always refer to the documentation.\n", 198 | "\n", 199 | "\n", 200 | "### Part 3.A. Let's go through one loop of the algorithm, each step (sort of) by hand\n", 201 | "\n", 202 | "We will use the following example system:\n", 203 | "\n", 204 | "```\n", 205 | "R1: S1 + S2 -> 2S1\n", 206 | "```\n", 207 | "\n", 208 | "For each of the steps, follow the instructions and hints and if necessary, check the python documentation." 209 | ] 210 | }, 211 | { 212 | "cell_type": "markdown", 213 | "metadata": {}, 214 | "source": [ 215 | "**Import the required libraries and modules**" 216 | ] 217 | }, 218 | { 219 | "cell_type": "code", 220 | "execution_count": 1, 221 | "metadata": { 222 | "collapsed": true 223 | }, 224 | "outputs": [], 225 | "source": [ 226 | "# import modules and libraries: numpy, factorial from scipy.special, pyplot from matplotlib\n", 227 | "# allow inline plot with %matplotlib inline" 228 | ] 229 | }, 230 | { 231 | "cell_type": "markdown", 232 | "metadata": {}, 233 | "source": [ 234 | "**Step 0 - Initialization:** \n", 235 | "- Input the desired values for the `M` reaction constants `c1,. ..,cM` and the `N` initial molecular population numbers `X1,...,XN`. \n", 236 | "- Set the time variable `t` and the reaction counter `n` both to zero. " 237 | ] 238 | }, 239 | { 240 | "cell_type": "code", 241 | "execution_count": null, 242 | "metadata": { 243 | "collapsed": false 244 | }, 245 | "outputs": [], 246 | "source": [ 247 | "# reaction constants, c1\n", 248 | "\n", 249 | "print \"c1: \", c1\n", 250 | "\n", 251 | "# initial molecular population numbers X1 of S1 and X2 of S2, \n", 252 | "\n", 253 | "print \"X1: \", X1\n", 254 | "print \"X2: \", X2\n", 255 | "\n", 256 | "# initialise time variable t and reaction counter n\n", 257 | "\n", 258 | "print \"t: \", t\n", 259 | "print \"n: \", n" 260 | ] 261 | }, 262 | { 263 | "cell_type": "markdown", 264 | "metadata": {}, 265 | "source": [ 266 | "**Step 1 - calculate the ai and a0: ** \n", 267 | "- Calculate and store the `M` quantities `a1 = h1*c1,..., aM = hm*cm` for the current molecular population numbers. \n", 268 | "- To fasciliate the manipulation with python, save all the `ai`'s in an array `a`.\n", 269 | "- Calculate and store as `a_0` the sum of the `M` `a_i` values." 270 | ] 271 | }, 272 | { 273 | "cell_type": "code", 274 | "execution_count": null, 275 | "metadata": { 276 | "collapsed": false 277 | }, 278 | "outputs": [], 279 | "source": [ 280 | "# calculate a1 = h1*c1 where h1 is the total number of all possible \n", 281 | "# combinations of pairs S1 and S2\n", 282 | " # go back to the section where the propensities of the reactions were calculated to remind yourself \n", 283 | "\n", 284 | "# define an (numpy) array a with entries each ai\n", 285 | "\n", 286 | "# define a0 as the sum of all ai's\n", 287 | "\n", 288 | "# debug\n", 289 | "print \"a1: \", a1\n", 290 | "print \"a: \", a\n", 291 | "print \"a0: \", a0" 292 | ] 293 | }, 294 | { 295 | "cell_type": "markdown", 296 | "metadata": {}, 297 | "source": [ 298 | "**Step 2 - Get the next reaction and time of reaction: ** \n", 299 | "\n", 300 | "- Generate the pair `(T, mu)` from the set of random pairs whose probability density function is the Chemical Master Equation.\n", 301 | "- When calculating the next reaction, you need a while loop.\n", 302 | "- Recall that numbering in Python starts from 0, so be careful with indexing!" 303 | ] 304 | }, 305 | { 306 | "cell_type": "code", 307 | "execution_count": null, 308 | "metadata": { 309 | "collapsed": false 310 | }, 311 | "outputs": [], 312 | "source": [ 313 | "# generate random numbers r1 and r2 from the normal distribution, using np.random.random\n", 314 | "\n", 315 | "print \"r1: \", r1\n", 316 | "print \"r2: \", r2\n", 317 | "\n", 318 | "# find the increment T in time as (1/a0)*ln(1/r1)\n", 319 | "\n", 320 | "print \"T: \", T\n", 321 | "\n", 322 | "# choose next reaction\n", 323 | " # initialise mu to 0\n", 324 | " \n", 325 | " # define new variable N = r2*a0 - a[mu]\n", 326 | "\n", 327 | " # while N is positive\n", 328 | " \n", 329 | " # add 1 to mu\n", 330 | " \n", 331 | " # substract a_mu from N\n", 332 | " \n", 333 | " # when the while lopp breaks, allocate the current value of mu to the next reaction variable next_r\n", 334 | "\n", 335 | "print \"next_r: \", next_r" 336 | ] 337 | }, 338 | { 339 | "cell_type": "markdown", 340 | "metadata": {}, 341 | "source": [ 342 | "Does it make sense what the next reaction is?\n", 343 | "\n", 344 | "What happens if you run the code again? Does the same reaction get chosen? Does this make sense?\n", 345 | "\n", 346 | "Make sure that you understand how this while loop achieves the purpose of choosing the next reaction, correctly according to the theory given above, in section \"Calculating the time evolution of the system\"." 347 | ] 348 | }, 349 | { 350 | "cell_type": "markdown", 351 | "metadata": {}, 352 | "source": [ 353 | "**Step 3 - update the system: ** \n", 354 | "\n", 355 | "Using the `T` and `mu` values obtained in step 2, increase `t` by `T`, and adjust the molecular population levels to reflect the occurrence of one `R_i` reaction; e.g., if `R_i` is the reaction `R1`, then increase `X1` by `1` and decrease `X2` by `1`. Then increase the reaction counter `n` by `1`.\n", 356 | "\n", 357 | "(Note: for complicated networks with many reagents and reactions, it is enough to recalculate only those quantities `a_i` corresponding to reactions `R_i` whose reactant population levels were just altered in step 3; also, `a_0` may be recalculated simply by adding to `a_0` the difference between each newly changed `a_i` value and its corresponding old value. However, for simple networks such as this example, checking what changes and what not might take more time then recalculate all quantities a_i.)" 358 | ] 359 | }, 360 | { 361 | "cell_type": "code", 362 | "execution_count": null, 363 | "metadata": { 364 | "collapsed": false 365 | }, 366 | "outputs": [], 367 | "source": [ 368 | "# define the time of next reaction\n", 369 | "\n", 370 | "print \"t: \", t\n", 371 | "\n", 372 | "# add one to the number of reactions count n\n", 373 | "\n", 374 | "print \"n: \", n\n", 375 | "\n", 376 | "# update the system according to the reaction that was chosen\n", 377 | "\n", 378 | "print \"X1: \", X1\n", 379 | "print \"X2: \", X2" 380 | ] 381 | }, 382 | { 383 | "cell_type": "markdown", 384 | "metadata": {}, 385 | "source": [ 386 | "We have simulated the stochastic occurance of one reaction. We can visualise the effect of this reaction by plotting the time vs the concentration of the reactants as follows:" 387 | ] 388 | }, 389 | { 390 | "cell_type": "code", 391 | "execution_count": null, 392 | "metadata": { 393 | "collapsed": false 394 | }, 395 | "outputs": [], 396 | "source": [ 397 | "# create arrays containing all data\n", 398 | "\n", 399 | " # array with initial number of X1 and number after one reaction\n", 400 | " \n", 401 | " # array with initial number of X2 and number after one reaction\n", 402 | " \n", 403 | " # array with initial time and time of reaction one\n", 404 | "\n", 405 | "# create plot using pyplot, remeber to add a legend and annotate the axes\n" 406 | ] 407 | }, 408 | { 409 | "cell_type": "markdown", 410 | "metadata": {}, 411 | "source": [ 412 | "Return to 1 and repeat." 413 | ] 414 | }, 415 | { 416 | "cell_type": "markdown", 417 | "metadata": {}, 418 | "source": [ 419 | "### Part 3.B. - Automate the process\n", 420 | "\n", 421 | "So now, we need to do the same process many many times, to simulate the system to a maximum time (`tmax`) or maximum number of reactions (`nmax`) of our choice. \n", 422 | "\n", 423 | "It is not feasible to carry on typing the same commands every time we need to go through the loop until we reach either `tmax` or `nmax` and we need to implement an automated way of **looping** through the algorithm.\n", 424 | "\n", 425 | "So what should we use? You've guessed it - a while loop, because with a while loop we can test whether the `tmax` or `nmax` bounds have been reached and *while* they have not, we go through yet another loop of the algorithm.\n", 426 | "\n", 427 | "Additionally, to be able to visualise the output of every loop, we will also want to provide an automated way of storing the changing values of the reactants, rather than doing it by hand as we did above.\n", 428 | "\n", 429 | "Finally, it is always a good practice to implement a debugging strategy. We recommend defining a *pause* function that will ask the user (of the program) to press the `` key to continue and to print values that will help the user keep track of the algorithm.\n", 430 | "\n", 431 | "To implement these new changes, let's use a new biochemical system, that has more than one reaction. It is important that this system has more than one reaction because if you can write a program general enough to deal with more than one reaction, then there should be no problem with a system with more reactions. Let's use the following system:\n", 432 | "```\n", 433 | "R1: 2X1 + X2 -> X3\n", 434 | "R2: X1 -> 0\n", 435 | "```\n", 436 | "\n", 437 | "(**Note on how to represent this system of chemical equations in matrix form:** \n", 438 | "We can write any system on chemical equations in matrix form. First we choose a convention, for example, the rows of the matrix correspond to the reactions and the columns to the reactants. Next, we read off the effect that the reactions have on each of the reactants, for example, R1 consumes 2 (molecules) of X1 and 1 of X2 and produces 1 of X3. Finally, we recod these numbers i correcsponding matrix entries.\n", 439 | "\n", 440 | "For the example above, the array form for the system above would be:\n", 441 | "\n", 442 | "```\n", 443 | " X1 X2 X3\n", 444 | "R1 -2 -1 1\n", 445 | "R2 -1 0 0\n", 446 | "```\n", 447 | "\n", 448 | "You can also choose to write the stoichiometry of the substrates and producs, which which case you only take into account how the substrates/products are affected. So for example, the substrate stoichiometry array of the system above would be:\n", 449 | "\n", 450 | "```\n", 451 | " X1 X2 X3\n", 452 | "R1 -2 -1 0\n", 453 | "R2 -1 0 0\n", 454 | "```\n", 455 | "\n", 456 | "Can yu write the one for the products?)" 457 | ] 458 | }, 459 | { 460 | "cell_type": "markdown", 461 | "metadata": {}, 462 | "source": [ 463 | "#### Import required libraries" 464 | ] 465 | }, 466 | { 467 | "cell_type": "code", 468 | "execution_count": null, 469 | "metadata": { 470 | "collapsed": true 471 | }, 472 | "outputs": [], 473 | "source": [ 474 | "# import required libraries and modules: numpy, factorial from scipy.special, pyplot \n", 475 | "# enable inline plotting" 476 | ] 477 | }, 478 | { 479 | "cell_type": "markdown", 480 | "metadata": {}, 481 | "source": [ 482 | "#### Define debug function" 483 | ] 484 | }, 485 | { 486 | "cell_type": "code", 487 | "execution_count": null, 488 | "metadata": { 489 | "collapsed": false 490 | }, 491 | "outputs": [], 492 | "source": [ 493 | "# define a pause function for debugging\n", 494 | "\n", 495 | "#def ...\n", 496 | " \n", 497 | " # using the command raw_input, define a variable that prints out a message along the lines of \n", 498 | " # \"Press the key to continue...\" and take as input nothing.\n" 499 | ] 500 | }, 501 | { 502 | "cell_type": "markdown", 503 | "metadata": {}, 504 | "source": [ 505 | "#### Step 0 of algorithm" 506 | ] 507 | }, 508 | { 509 | "cell_type": "code", 510 | "execution_count": null, 511 | "metadata": { 512 | "collapsed": false 513 | }, 514 | "outputs": [], 515 | "source": [ 516 | "# **************************** \n", 517 | "# step 0: input rate values, initial contidions values and initialise time \n", 518 | "# and reactions counter\n", 519 | "# **************************** \n", 520 | "\n", 521 | "# Define the stoichiometry of the system as a numpy array, with the number of reactions in the rows \n", 522 | "# and the number of reactants in the columns. \n", 523 | "\n", 524 | " # Define the stochiometry of the substrates and products separatelly; Use the variable names \n", 525 | " # stoch_subst for the substrates and stoch_prods for the products\n", 526 | " \n", 527 | " # Using these define the stoch variable as the summ of stoch_subst and stoch_prods\n", 528 | "\n", 529 | " # Keep track of the following:\n", 530 | " # (i ranges 0 -> M-1, where M is the number of reactions, j ranges 0 -> N-1, where N is the \n", 531 | " # number of species)\n", 532 | "\n", 533 | " # allocate the number of reactions to variable num_rxn and number of species to varialbe num_spec,\n", 534 | " # use the command shape of numpy and array indexing\n", 535 | "\n", 536 | "# define the ci parameters in an array variable called rates\n", 537 | "\n", 538 | "# define the initial conditions of the reactants in an array variable init\n", 539 | "\n", 540 | "# specify the maximum time, tmax, and maximum number of reactions, nrmax\n", 541 | "\n", 542 | "# Initialise the current_species variable to init\n", 543 | "\n", 544 | "# Initialise the current time current_t and the time and reaction counters t_count \n", 545 | "# and react_count to 0\n", 546 | "\n", 547 | "# debug: print all the variables to check everything is correct" 548 | ] 549 | }, 550 | { 551 | "cell_type": "code", 552 | "execution_count": null, 553 | "metadata": { 554 | "collapsed": false, 555 | "scrolled": true 556 | }, 557 | "outputs": [], 558 | "source": [ 559 | "# Initialise variables to store time and molecule numbers\n", 560 | "\n", 561 | " # You need the arrays to be large enough to contain all the possible number of iterations the \n", 562 | " # algorithm goes through (which we don't know, a priori, how many iterations that will be). \n", 563 | " # Call this cariable largenum\n", 564 | "\n", 565 | " # Initialise a zeros array called store_t to store all the times of reactions (with dimensions largenum,1)\n", 566 | " \n", 567 | " # Initialise a zeros array called store_mols to store all reactants after each reaction \n", 568 | " # (with dimensions largenum,num_spec)\n", 569 | "\n", 570 | " # Initialise a zeros array called store_r to store all the reaction ids (with dimensions largenum,1)\n", 571 | "\n", 572 | "# debug by printing all the variables and check for correct numbers" 573 | ] 574 | }, 575 | { 576 | "cell_type": "code", 577 | "execution_count": null, 578 | "metadata": { 579 | "collapsed": false 580 | }, 581 | "outputs": [], 582 | "source": [ 583 | "# store current time and state\n", 584 | "\n", 585 | " # store current time of the system by indexing store_t with t_count (why?) and equating that entry it \n", 586 | " # to current_t\n", 587 | "\n", 588 | " # store current numbers of molecules of each species by indexing store_mols with [t_count,:] (why?) and \n", 589 | " # equating that row it to current_species\n", 590 | "\n", 591 | "# debug by printing 10 rows of the two arrays above and checking for correct recording of data\n" 592 | ] 593 | }, 594 | { 595 | "cell_type": "markdown", 596 | "metadata": {}, 597 | "source": [ 598 | "#### Define a function to automate the choosing of the next time and reaction and check it works correctly" 599 | ] 600 | }, 601 | { 602 | "cell_type": "code", 603 | "execution_count": 2, 604 | "metadata": { 605 | "collapsed": false 606 | }, 607 | "outputs": [], 608 | "source": [ 609 | "# define a function to choose the next time and reaction\n", 610 | "\n", 611 | "# define function with name choose_t_r and inputs a0 and a\n", 612 | " \n", 613 | " # generate random numbers r1 and r2 from the uniform distribution\n", 614 | " \n", 615 | " # choose the increment T in time as (1/a0)*ln(1/r1)\n", 616 | " \n", 617 | " # choose the next reaction \n", 618 | " \n", 619 | " # initialise S to sum(a)\n", 620 | " \n", 621 | " # initialise mu to 0\n", 622 | " \n", 623 | " # initialise to N= r2*a0 - a[mu]\n", 624 | "\n", 625 | " # while loop:\n", 626 | " \n", 627 | " # while N is positive\n", 628 | " \n", 629 | " # add one to mu\n", 630 | " \n", 631 | " # substract a[mu] from N\n", 632 | "\n", 633 | " # when the while loop breaks, allocate the current value of mu to next_r\n", 634 | "\n", 635 | " # return T and next_r\n", 636 | "\n", 637 | "\n", 638 | "# To debug choose_t_r write a function that runs choose_t_r 1000 times:\n", 639 | "\n", 640 | "# define function run_choose_t_r_many_times with input a, the array of ai's\n", 641 | "\n", 642 | " # define a0 as the sum of a\n", 643 | " \n", 644 | " # define a zeros array r with dimensions 1000,1, to store the outputs of each time choose_t_r is run\n", 645 | " \n", 646 | " # define a for loop with index i that ranges from 0-999\n", 647 | "\n", 648 | " # define a variable res that is the output of choose_t_r\n", 649 | "\n", 650 | " # store the choice of reaction, res, in r\n", 651 | " \n", 652 | " # plot a histogram of all the reactions chosen, using pyplot hist\n", 653 | "\n", 654 | " # make sure that the bins are centred at the integer values that correspond \n", 655 | " # to the reactions by defining an array bins with the bounds of each bin\n", 656 | " \n", 657 | " \n", 658 | "# Ask youself what you expect the histogram to look like, given the current parameter values:\n", 659 | " # Run function run_choose_t_r_many_times with different values of a:\n", 660 | " # By changing the values of a you can check that different reactions are being chosen \n", 661 | " # representatively with the system.\n", 662 | " # For example, for a = np.array([9000*0.0001, 10*1]), i.e. the rate for reaction R1 \n", 663 | " # is 0.0001 and for reaction R2 is 1, the proportions of choosing reaction R1 or R2 \n", 664 | " # should be similar, around 1:1, but for a = np.array([9000*0.01, 10*1]) R1 should \n", 665 | " # be chosen many more times than R2, in fact, on a ratio of around 10:1." 666 | ] 667 | }, 668 | { 669 | "cell_type": "markdown", 670 | "metadata": {}, 671 | "source": [ 672 | "#### Automate the calculation of the propensitites of the reactions" 673 | ] 674 | }, 675 | { 676 | "cell_type": "markdown", 677 | "metadata": {}, 678 | "source": [ 679 | "Think about how exactly to calculate the algebraic statement that equals `ai = hi*ci`.\n", 680 | "\n", 681 | "It is helpful to write down many examples in order to come up with a formula.\n", 682 | "\n", 683 | "Let's think through this particular example together:\n", 684 | "\n", 685 | "We have the substrate stoichiometry being\n", 686 | "\n", 687 | "```\n", 688 | " -2 -1 0\n", 689 | " -1 0 0\n", 690 | "```\n", 691 | "\n", 692 | "suppose we want to work out `hi` for `R1`. Let's start with `X1`. We know that the algebraic expression is `X1(X1-1)`. Notice that this is the same as the binomial coefficient `binom(X1,2)` multiplied by `2!`. (If you don't remember what the binomial coefficient is and how to calculate it, you can refer to the subsection below this explanation.)\n", 693 | "\n", 694 | "Now suppose that the substrate stoichiometry is\n", 695 | "\n", 696 | "```\n", 697 | " -3 -1 0\n", 698 | " -1 0 0\n", 699 | "```\n", 700 | "\n", 701 | "to calculate the algebraic expression for `X1`, we know it is `X1*(X1-1)*(X1-2)`, which equals `binom(X1,3)*3!`.\n", 702 | "\n", 703 | "We star to see a pattern here, can you write it down explicitly in Python language? The answer is below, but we encourage you to work it out for yourself. You will need the `binomial` and `factorial` functions. Also, be careful with the signs and remember that you can use the `absolute` function.\n", 704 | "\n", 705 | ".\n", 706 | "\n", 707 | ".\n", 708 | "\n", 709 | ".\n", 710 | "\n", 711 | ".\n", 712 | "\n", 713 | ".\n", 714 | "\n", 715 | ".\n", 716 | "\n", 717 | ".\n", 718 | "\n", 719 | ".\n", 720 | "\n", 721 | "If you did the hand calculations, you saw that to calculate `hi` you need the following formula:\n", 722 | "\n", 723 | "```\n", 724 | "hi = hi*binom(current_species[j],np.absolute(stoch_subst[i,j]))*factorial(np.absolute(stoch_subst[i,j]))\n", 725 | "```\n", 726 | "\n", 727 | "Unfortunatelly, python does not seem to have a binomial coefficient function, so we define it here (perhaps it is fortunate, it gives us a chance to practice writting a new function! Make sure you understand it). (If you know of an already existing function, let us know!)\n", 728 | "\n", 729 | "\n", 730 | "(**Side note on the binomial coefficient:** The binomial coefficient, say 4choose2 is the number of ways two objects can be chosen from four objects. For example if I have four letters, A, B, C and D, I can choose:\n", 731 | "```\n", 732 | "AB\n", 733 | "AC\n", 734 | "AD\n", 735 | "BC\n", 736 | "BD\n", 737 | "CB\n", 738 | "```\n", 739 | "and if you stare at this list for a while, you will convince yourself these are all the possible distinct ways of choosing 2 letters out of those 4. So the binomial coefficient 4choose2 = 6.\n", 740 | "\n", 741 | "In general, you do not write all the possibilities down. You use a formula: NchooseK = N!/K!(N-K)! where the factorial, say 5! means that you multiply all the integers from 5 down to 1 together, to get `5*4*3*2*1 = 120`.\n", 742 | "\n", 743 | "If you want to check various binomial coefficients, you can go to [WolframAlpha](http://www.wolframalpha.com/) and use binom[n,m] to make the calculations.)" 744 | ] 745 | }, 746 | { 747 | "cell_type": "code", 748 | "execution_count": null, 749 | "metadata": { 750 | "collapsed": false 751 | }, 752 | "outputs": [], 753 | "source": [ 754 | "# define a function to calculate the binomial coefficient\n", 755 | "def binom(n,m):\n", 756 | " b=[0]*(n+1)\n", 757 | " b[0]=1\n", 758 | " for i in xrange(1,n+1):\n", 759 | " b[i]=1\n", 760 | " j=i-1\n", 761 | " while j>0:\n", 762 | " b[j]+=b[j-1]\n", 763 | " j-=1\n", 764 | " return b[m]\n", 765 | "\n", 766 | "# debug - test binom\n" 767 | ] 768 | }, 769 | { 770 | "cell_type": "markdown", 771 | "metadata": {}, 772 | "source": [ 773 | "#### Write the main loop of the algorithm - Steps 1, 2 and 3" 774 | ] 775 | }, 776 | { 777 | "cell_type": "code", 778 | "execution_count": null, 779 | "metadata": { 780 | "collapsed": false, 781 | "scrolled": true 782 | }, 783 | "outputs": [], 784 | "source": [ 785 | "# Now we write the main loop. Remember it is important to print values and using \n", 786 | "# the pause function to help yourself to debug the program.\n", 787 | "\n", 788 | "# while loop current_t < tmax \n", 789 | " \n", 790 | " # **************************** \n", 791 | " # step 1: calculate ai and a0\n", 792 | " # **************************** \n", 793 | " \n", 794 | " # debug\n", 795 | " print \"step 1: calculate ai and a0\"\n", 796 | " \n", 797 | " # initialise variable a to a ones array of dimensions num_rxn,1\n", 798 | " \n", 799 | " # (recall i ranges 1 -> M, where M is the number of reactions, j ranges 1 -> N, \n", 800 | " # where N is the number of species)\n", 801 | " \n", 802 | " # make a for loop with index i that ranges from 0 to num_rxns\n", 803 | " \n", 804 | " # initialise hi to 1\n", 805 | "\n", 806 | " # make a for loop with index j that ranges from 0 to the number of species \n", 807 | " # (i.e. len(init))\n", 808 | " \n", 809 | " # check the reactant (i,j) of the substrate stoichiomety matrix is involved \n", 810 | " # in this reaction (use an if statement). \n", 811 | " # if not, continue to the next reactant \n", 812 | "\n", 813 | " # if yes, follow the steps below\n", 814 | " \n", 815 | " # check the reactant has molecules available (use an if statement)\n", 816 | " # if it does not, equate hi to 0 (why?) and go to the next reactant\n", 817 | " \n", 818 | " # if it does, calculate hi using the formula you worked out above.\n", 819 | " # at this stage, for debugging purposes, you might like to include\n", 820 | " # print statements of various values and using the pause function.\n", 821 | "\n", 822 | " # e.g. debug\n", 823 | " #print \"reaction (i):\", i\n", 824 | " #print \"reactant (j):\", j\n", 825 | " #print \"current_species[j]:\", current_species[j]\n", 826 | " #print \"stoch_subst[i,j]:\", stoch_subst[i,j]\n", 827 | " #print \"np.absolute(stoch_subst[i,j]):\", np.absolute(stoch_subst[i,j])\n", 828 | " #print \"binom(current_species[j],np.absolute(stoch_subst[i,j]):\", binom(current_species[j],np.absolute(stoch_subst[i,j])) \n", 829 | " #print \"factorial(np.absolute(stoch_subst[i,j])):\", factorial(np.absolute(stoch_subst[i,j]))\n", 830 | " #print \"int(factorial(np.absolute(stoch_subst[i,j]))):\", int(factorial(np.absolute(stoch_subst[i,j])))\n", 831 | " #print \"binom(current_species[j],np.absolute(stoch_subst[i,j]))*factorial(np.absolute(stoch_subst[i,j])):\", binom(current_species[j],np.absolute(stoch_subst[i,j]))*factorial(np.absolute(stoch_subst[i,j])) \n", 832 | " #pause()\n", 833 | " \n", 834 | " # save the current value of ai as hi*ci (i.e. hi*rates[i]) to variable a, at a[i]\n", 835 | " \n", 836 | " # save a0 as the sum of all a's\n", 837 | "\n", 838 | " \n", 839 | " # **************************** \n", 840 | " # step 2: choose next t and r\n", 841 | " # **************************** \n", 842 | "\n", 843 | " # debug\n", 844 | " print \"step 2: choose next t and r\"\n", 845 | "\n", 846 | " # run choose_t_r to get the change in time and the next reaction, save them to \n", 847 | " # variables dt and next_r\n", 848 | " \n", 849 | " \n", 850 | " # **************************** \n", 851 | " # step 3: update and store system\n", 852 | " # **************************** \n", 853 | " \n", 854 | " # debug\n", 855 | " print \"step 3: update and store system\"\n", 856 | " \n", 857 | " # update the system: \n", 858 | " \n", 859 | " # update current_t by adding T\n", 860 | " \n", 861 | " # update current_species by adding np.transpose(stoch[next_r,:]), why?\n", 862 | "\n", 863 | " # update the time counter t_count and reaction counter react_count by adding 1\n", 864 | " \n", 865 | " # store current system to store_t[t_count], store_mols[t_count,:], store_r[t_count]" 866 | ] 867 | }, 868 | { 869 | "cell_type": "markdown", 870 | "metadata": {}, 871 | "source": [ 872 | "#### Collect and plot results of simulations" 873 | ] 874 | }, 875 | { 876 | "cell_type": "code", 877 | "execution_count": null, 878 | "metadata": { 879 | "collapsed": false 880 | }, 881 | "outputs": [], 882 | "source": [ 883 | "# Get rid of empty entries in store_t, store_mols and store_r\n", 884 | " \n", 885 | "# plot the results of the simulation using pyplot, time on the y-axis and concentrations\n", 886 | "# on the x-axis, remember to add a legend and to label the axes\n", 887 | "\n", 888 | "# debug: plot a histogram of the reactions chosen by the algorithm (by plotting store_r)" 889 | ] 890 | }, 891 | { 892 | "cell_type": "markdown", 893 | "metadata": {}, 894 | "source": [ 895 | "### Part 3.C. Make the algorithm into a function so that you can run it with *any* biochemical system\n", 896 | "\n", 897 | "Now, it would be great if we could just call a function that would work for any set of reactions and that we can just run one line of code rather than the whole set up and while loop over and over. We do this below. (Note that you can now get rid of the debugging commands as we have tested every bit and it is all working and we want the program to run smoothly without user input.)\n", 898 | "\n", 899 | "#### Program the algorithm as a function" 900 | ] 901 | }, 902 | { 903 | "cell_type": "code", 904 | "execution_count": null, 905 | "metadata": { 906 | "collapsed": false 907 | }, 908 | "outputs": [], 909 | "source": [ 910 | "# ----------------------------\n", 911 | "# ----------------------------\n", 912 | "# IMPORT ALL NECESSARY LIBRARIES AND MODULES\n", 913 | "# ----------------------------\n", 914 | "# ----------------------------\n", 915 | "\n", 916 | "\n", 917 | "# ----------------------------\n", 918 | "# ----------------------------\n", 919 | "# DEFINE OTHER FUNCTIONS NECESSARY\n", 920 | "# ----------------------------\n", 921 | "# ----------------------------\n", 922 | "\n", 923 | "# define a function to choose the next time and reaction\n", 924 | "\n", 925 | "\n", 926 | "# define a function to calculate the binomial coefficient\n", 927 | "\n", 928 | "\n", 929 | "# ----------------------------\n", 930 | "# ----------------------------\n", 931 | "# DEFINE SIMULATION FUNCTION\n", 932 | "# ----------------------------\n", 933 | "# ----------------------------\n", 934 | "\n", 935 | "# define my_gillespie function with unput values init, rates, stoch_subst, stoch_prods, tmax, nrmax \n", 936 | "# and output values store_t, store_mols, store_r\n", 937 | " \n", 938 | " \n", 939 | " # --------------------------\n", 940 | " # set up\n", 941 | " # --------------------------\n", 942 | " \n", 943 | " # **************************** \n", 944 | " # step 0: input rate values, initial contidions values and initialise time and reactions counter\n", 945 | " # **************************** \n", 946 | " \n", 947 | " # define the stoichiometry (variable stoch) of the system as a numpy array as a sum of the substrate and product stoichiometries\n", 948 | " \n", 949 | " # initialise num_rxn and num_spec to the correct values\n", 950 | " \n", 951 | " # initialise current time and current species variables and the time and reaction counters, current_t, \n", 952 | " # current_species, t_count, react_count\n", 953 | " \n", 954 | " # initialise variables to store time and molecule numbers, largenum, store_t, store_mols, store_r\n", 955 | " \n", 956 | " # store current time and state of system in store_t and store_mols\n", 957 | " \n", 958 | " \n", 959 | " # --------------------------\n", 960 | " # main while loop\n", 961 | " # --------------------------\n", 962 | " \n", 963 | " # **************************** \n", 964 | " # step 1: calculate ai and a0\n", 965 | " # **************************** \n", 966 | " \n", 967 | " # initialise variable a to a ones array of dimensions num_rxn,1\n", 968 | " \n", 969 | " # make a for loop with index i that ranges from 0 to num_rxns\n", 970 | " \n", 971 | " # initialise hi to 1\n", 972 | "\n", 973 | " # make a for loop with index j that ranges from 0 to the number of species (i.e. len(init))\n", 974 | " \n", 975 | " # check the reactant (i,j) of the substrate stoichiomety matrix is involved \n", 976 | " # in this reaction (use an if statement). \n", 977 | " \n", 978 | " # if not, continue to the next reactant \n", 979 | "\n", 980 | " # if yes, follow the steps below\n", 981 | " \n", 982 | " # check the reactant has molecules available (use an if statement)\n", 983 | " # if it does not, equate hi to 0 (why?) and go to the next reactant\n", 984 | " \n", 985 | " # if it does, calculate hi using the formula you worked out above.\n", 986 | " # at this stage, for debugging purposes, you might like to include\n", 987 | " # print statements of various values and using the pause function.\n", 988 | " \n", 989 | " # save the current value of ai as hi*ci (i.e. hi*rates[i]) to variable a, at a[i]\n", 990 | " \n", 991 | " # save a0 as the sum of all a's\n", 992 | " \n", 993 | " # **************************** \n", 994 | " # step 2: choose next t and r\n", 995 | " # **************************** \n", 996 | "\n", 997 | " # run choose_t_r to get the change in time and the next reaction, save them to \n", 998 | " # variables T and next_r \n", 999 | " \n", 1000 | " # **************************** \n", 1001 | " # step 3: update and store system\n", 1002 | " # **************************** \n", 1003 | " \n", 1004 | " # update the system: \n", 1005 | " \n", 1006 | " # update current_t by adding T\n", 1007 | " \n", 1008 | " # update current_species by adding np.transpose(stoch[next_r,:]), why?\n", 1009 | "\n", 1010 | " # update the time counter t_count and reaction counter react_count by adding 1\n", 1011 | " \n", 1012 | " # store current system to store_t[t_count], store_mols[t_count,:], store_r[t_count]\n", 1013 | " \n", 1014 | " \n", 1015 | "\n", 1016 | " # store final output - get rid of empty entries in store_t, store_mols, store_r\n", 1017 | " \n", 1018 | " # return result" 1019 | ] 1020 | }, 1021 | { 1022 | "cell_type": "markdown", 1023 | "metadata": {}, 1024 | "source": [ 1025 | "#### Run a few simulations with different scenarios" 1026 | ] 1027 | }, 1028 | { 1029 | "cell_type": "code", 1030 | "execution_count": null, 1031 | "metadata": { 1032 | "collapsed": true 1033 | }, 1034 | "outputs": [], 1035 | "source": [ 1036 | "# ----------------------------\n", 1037 | "# ----------------------------\n", 1038 | "# RUN SIMULATION\n", 1039 | "# R1: X1 + X2 -> 2X1\n", 1040 | "# R2: X1 -> 0\n", 1041 | "# ----------------------------\n", 1042 | "# ----------------------------\n", 1043 | "\n", 1044 | "# ****************************\n", 1045 | "# step A: define rate values, initial contidions values, tmax and nrmax\n", 1046 | "# ****************************\n", 1047 | "\n", 1048 | "# define the stochiometry of the substrates and products separatelly\n", 1049 | "\n", 1050 | "# define the ci parameters (variable rates)\n", 1051 | "\n", 1052 | "# define the initial conditions of the reactants (variable init)\n", 1053 | "\n", 1054 | "# define the maximum time, tmax, and and maximum number of reactions, nrmax\n", 1055 | "\n", 1056 | "# ****************************\n", 1057 | "# step B: run simulation\n", 1058 | "# ****************************\n", 1059 | "\n", 1060 | "# ****************************\n", 1061 | "# step C: plot results of simulation in a graph\n", 1062 | "# ****************************\n", 1063 | "\n" 1064 | ] 1065 | }, 1066 | { 1067 | "cell_type": "code", 1068 | "execution_count": null, 1069 | "metadata": { 1070 | "collapsed": false 1071 | }, 1072 | "outputs": [], 1073 | "source": [ 1074 | "# ----------------------------\n", 1075 | "# ----------------------------\n", 1076 | "# RUN ANOTHER SIMULATION\n", 1077 | "# R1: D -> D + R\n", 1078 | "# R2: R -> R + P\n", 1079 | "# R3: R -> 0\n", 1080 | "# R4: P -> 0\n", 1081 | "# ----------------------------\n", 1082 | "# ----------------------------" 1083 | ] 1084 | }, 1085 | { 1086 | "cell_type": "markdown", 1087 | "metadata": {}, 1088 | "source": [ 1089 | "## Part 4. Next steps\n", 1090 | "\n", 1091 | "### Stochastic vs deterministic\n", 1092 | "\n", 1093 | "Probably the bext thing you can try to do it to compare the results of these stochastic simulations with results you would get when you model the same systems deterministically, with a system of Ordinary Differential Equations (ODEs). This will actually validate our stochastic simulation algorithm.\n", 1094 | "\n", 1095 | "Note that ODE modelling is performed in terms of concentrations and deterministic rate constants; and stochastic calculations are in stochastic constants and molecule numbers. So for the results to be comparable, we need to make conversions properly. Luckily, Gillespie spells this out for us in his paper and if you are interested, you can have a look at page 2343, section IIC. Connection with the Deterministic Reaction-Rate Constant. \n", 1096 | "\n", 1097 | "Recall the stochastic reaction rate constant is `c_i`, which we introduced in Part 2.\n", 1098 | "\n", 1099 | "Let's denote the deterministic rate constant for reaction `R_i` with `k_i`.\n", 1100 | "\n", 1101 | "The conclusion of Gillespie's analysis is that \n", 1102 | "\n", 1103 | "```\n", 1104 | "k_i = (V^(m-1))*c_i\n", 1105 | "```\n", 1106 | "\n", 1107 | "The presence of the factor `V^(m-1)`, where `m` is the number of reactant molecules in reaction `R_i`, is merely a consequence of the fact that the reaction-rate constant is normally used in differential equations that contain molecular concentrations (numbers of molecules per unit volume) rather than total numbers of molecules. For example, if reaction `R_i` had three reactant molecules, we would have `V^2` instead of `V`;if `R_i`had only one reactant molecule (a simple isomerization), the factor `V` would be absent.\n", 1108 | "\n", 1109 | "Furthermore, in general, if `R`, has `n` identical reactant molecules, then `c` will be larger than `k` by a factor of `n!`. So, for example, if we have `R: 2X1 -> X2` then `k=V*c/2`.\n", 1110 | "\n", 1111 | "So let's translate the following system and simulate it deterministically (if you need to learn this topic or prefresh your memory, we refer you to [this](https://github.com/karinsasaki/biomath-modelling-with-python) tutorial):\n", 1112 | "```\n", 1113 | "R1: D -> D + R\n", 1114 | "R2: R -> R + P\n", 1115 | "R3: R -> 0\n", 1116 | "R4: P -> 0\n", 1117 | "```\n", 1118 | "\n", 1119 | "We had defined the stochastic rate constants as follows:\n", 1120 | "\n", 1121 | "```\n", 1122 | "c1 = 0.01\n", 1123 | "c2 = 0.1\n", 1124 | "c3 = 0.0001\n", 1125 | "c4 = 0.0001\n", 1126 | "```\n", 1127 | "\n", 1128 | "Let's assume the volume of the system is 1, then the deterministic rate constants are:\n", 1129 | "\n", 1130 | "```\n", 1131 | "k1 = 0.01\n", 1132 | "k2 = 0.1\n", 1133 | "k2 = 0.0001\n", 1134 | "k2 = 0.0001\n", 1135 | "```\n", 1136 | "\n", 1137 | "The same! Why? because there is only one reactant molecule in each reaction.\n", 1138 | "\n", 1139 | "Now we show how to simulate the system deterministically:" 1140 | ] 1141 | }, 1142 | { 1143 | "cell_type": "code", 1144 | "execution_count": 1, 1145 | "metadata": { 1146 | "collapsed": false 1147 | }, 1148 | "outputs": [ 1149 | { 1150 | "data": { 1151 | "image/png": "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\n", 1152 | "text/plain": [ 1153 | "" 1154 | ] 1155 | }, 1156 | "metadata": {}, 1157 | "output_type": "display_data" 1158 | } 1159 | ], 1160 | "source": [ 1161 | "# import modules and libraries\n", 1162 | "import numpy as np\n", 1163 | "from scipy.integrate import odeint\n", 1164 | "import matplotlib.pyplot as plt\n", 1165 | "%matplotlib inline\n", 1166 | "\n", 1167 | "# Parameters\n", 1168 | "k1 = 0.01\n", 1169 | "k2 = 0.1\n", 1170 | "k3 = 0.0001\n", 1171 | "k4 = 0.0001\n", 1172 | "params = (k1, k2, k3, k4)\n", 1173 | "\n", 1174 | "# Initial conditions\n", 1175 | "D_0 = 1\n", 1176 | "R_0 = 0\n", 1177 | "P_0 = 0\n", 1178 | "ini = (D_0, R_0, P_0)\n", 1179 | "\n", 1180 | "# Time\n", 1181 | "dt = 0.1\n", 1182 | "t = np.arange(0,50,dt)\n", 1183 | "\n", 1184 | "# ODE system (in format used for odeint)\n", 1185 | "def myODE(init,t,params):\n", 1186 | " \n", 1187 | " k1, k2, k3, k4 = params\n", 1188 | " \n", 1189 | " D, R, P = init\n", 1190 | "\n", 1191 | " # rates\n", 1192 | " v1 = k1*D\n", 1193 | " v2 = k2*R\n", 1194 | " v3 = k3*R\n", 1195 | " v4 = k4*P\n", 1196 | " \n", 1197 | " # equations\n", 1198 | " dD = 0\n", 1199 | " dR = v1 + v2 - v3\n", 1200 | " dP = v2 - v4\n", 1201 | " \n", 1202 | " return (dD, dR, dP)\n", 1203 | "\n", 1204 | "# Solve using odeint from scipy.integrate\n", 1205 | "solution = odeint(myODE,ini,t,args=(params,)) \n", 1206 | "tD = solution[:,0]\n", 1207 | "tR = solution[:,1]\n", 1208 | "tP = solution[:,2]\n", 1209 | "\n", 1210 | "# Show over time\n", 1211 | "fig, ax = plt.subplots()\n", 1212 | "ax.plot(t, tD, label='D')\n", 1213 | "ax.plot(t, tR, label='R')\n", 1214 | "ax.plot(t, tP, label='P')\n", 1215 | "plt.xlabel('time')\n", 1216 | "plt.ylabel('concentration')\n", 1217 | "legend = ax.legend(loc='center left', bbox_to_anchor=(1, 0.5))\n", 1218 | "plt.show()" 1219 | ] 1220 | }, 1221 | { 1222 | "cell_type": "markdown", 1223 | "metadata": {}, 1224 | "source": [ 1225 | "### Exercise\n", 1226 | "\n", 1227 | "Demonstrate the effect of sample volume on the simulation results. Keep concentration the same and run simulations for different volumes (each time converting concentrations to molecule numbers). Show that for small volumes stoshastic curves are not completely reproducible and deviate from deterministic solution. For large volumes stochastic and deterministic solutions should be very close.\n" 1228 | ] 1229 | }, 1230 | { 1231 | "cell_type": "code", 1232 | "execution_count": null, 1233 | "metadata": { 1234 | "collapsed": true 1235 | }, 1236 | "outputs": [], 1237 | "source": [] 1238 | }, 1239 | { 1240 | "cell_type": "code", 1241 | "execution_count": null, 1242 | "metadata": { 1243 | "collapsed": true 1244 | }, 1245 | "outputs": [], 1246 | "source": [] 1247 | }, 1248 | { 1249 | "cell_type": "code", 1250 | "execution_count": null, 1251 | "metadata": { 1252 | "collapsed": true 1253 | }, 1254 | "outputs": [], 1255 | "source": [] 1256 | }, 1257 | { 1258 | "cell_type": "markdown", 1259 | "metadata": {}, 1260 | "source": [ 1261 | "\n", 1262 | "## Part 5. The end\n", 1263 | "\n", 1264 | "Next, as we have metioned before, the algorithm that we have written here is not the most computationally speedy and there are modifications of the Gillespie algorithm that are much more efficient. You could have a look at the difference in efficiency with the reaction method (Gibson & Bruck) and the tau-leaping method.\n", 1265 | "\n", 1266 | "\n", 1267 | "This is the end of the tutorial. Good job on finishing it! " 1268 | ] 1269 | } 1270 | ], 1271 | "metadata": { 1272 | "kernelspec": { 1273 | "display_name": "Python 2", 1274 | "language": "python", 1275 | "name": "python2" 1276 | }, 1277 | "language_info": { 1278 | "codemirror_mode": { 1279 | "name": "ipython", 1280 | "version": 2 1281 | }, 1282 | "file_extension": ".py", 1283 | "mimetype": "text/x-python", 1284 | "name": "python", 1285 | "nbconvert_exporter": "python", 1286 | "pygments_lexer": "ipython2", 1287 | "version": "2.7.12" 1288 | } 1289 | }, 1290 | "nbformat": 4, 1291 | "nbformat_minor": 0 1292 | } 1293 | -------------------------------------------------------------------------------- /c1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/c1.png -------------------------------------------------------------------------------- /c2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/c2.png -------------------------------------------------------------------------------- /choice.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/choice.png -------------------------------------------------------------------------------- /diag.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/diag.png -------------------------------------------------------------------------------- /explainign_gillespie.key: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/explainign_gillespie.key -------------------------------------------------------------------------------- /explainign_gillespie.key.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/explainign_gillespie.key.zip -------------------------------------------------------------------------------- /ode1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/ode1.png -------------------------------------------------------------------------------- /pdf.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/pdf.png -------------------------------------------------------------------------------- /pdff.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/pdff.png -------------------------------------------------------------------------------- /r1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/r1.png -------------------------------------------------------------------------------- /r2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/r2.png -------------------------------------------------------------------------------- /reaction_rate1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/reaction_rate1.png -------------------------------------------------------------------------------- /sample.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/sample.png -------------------------------------------------------------------------------- /schematic1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/karinsasaki/gillespie-algorithm-python/80acb8d8c44f6a4a4ee11de1981538389253d032/schematic1.png --------------------------------------------------------------------------------