# 2 # """ StochasticCells runs a simple homodimerization reaction for a small total number of molecules N, comparing the approximate continuum dynamics with the true stochastic dynamics. """ # # # See the exercise "StochasticCells.pdf" from StochasticCells.html # in http://www.physics.cornell.edu/~myers/teaching/ComputationalMethods/ComputerExercises/ # # import scipy, scipy.integrate RA = scipy.random import pylab # """Global values of rate constants (probably should be members of a class)""" kb = 1.0 ku = 2.0 # def dydt(y,t): """ Gives the time evolution law dydt for y = [M,D], in the form needed by odeint """ pass # def PlotODE(N, tMax=1.0, dt = 0.01): """Plots the continuum time evolution of M(t), given N total monomer molecules and no dimer molecules at time t=0. Uses scipy.arange to produce an array of times; calls scipy.integrate.odeint(dydt, y0, times) to get yTrajectory M(t) is first column of yTrajectory = yTrajectory[:,0] uses pylab.plot to plot times versus M(t) """ pass # def StochasticTrajectory(N, tMax=10.0): """ Implements the Gillespie algorithm, as described in the text. If t1, t2, t3, ..., tFinal are the resulting reaction times and M1, M2, M3, ..., MFinal are the number of monomers just after each reaction, the routine returns an array times = [0.0, t1, t1, t2, t2, ..., tFinal, tMax] and an array Ms = [N, N, M1, M1, M2, M2, ..., MFinal, MFinal] (suitable for plotting, since the concentration M(t) = M_n between t_n and t_{n+1}, and then abruptly jumps to M_{n+1}). This is easy to do: initialize them at t=0, append just before and just after each reaction, and add a point at t=tMax. You can generate tWait in two ways: (1) import random, generate a random number r0 uniformly in [0,1), and let tWait = -log(1-r0)/gammaTot. (Check that this generates an exponential distribution! We take 1-r0 to avoid rare errors when r0 happens to be exactly zero.) (2) for convenience, define RA=scipy.random, and generate a random number with an exponential distribution of mean 1/gammaTot. RA insists on returning an array of random numbers, so you need to tell it to give an array of length one and pull it out: tWait = RA.exponential(1.0/gammaTot, 1)[0] Of course, you could also generate an exponential random number of width one and then divide by gammaTot: tWait = RA.exponential(1.0, 1)[0]/gammaTot Generating r is easy: call RA.random() or random.random() and multiply by gammaTot. Notice that, since there are only two reactions, you can just check if r > bindingRate to see if you want to bind or unbind. """ pass # def PlotODEVsStochastic(N, tMax=1.0, dt = 0.01): """Plots the continuum time evolution of M(t) versus the stochastic trajectory given by the Gillespie algorithm. Again, N total monomer molecules and no dimer molecules at time t=0. """ pass # def PlotODEVsAverageStochastic(N, nAverage, tMax=1.0, dt = 0.001): """Plots the continuum time evolution of M(t) versus the average of nAverage stochastic trajectories. Computes the stochastic averages at the same times = (dt, 2 dt, ...) that odeint uses (except for zero). The stochastic simulation returns values at irregular times: how can we evaluate M at regular intervals? We can find the stochastic interval [stochasticTimes[indexStochastic], stochasticTimes[indexStochastic+1]) containing time[index] by searching forward from the previous interval, something like this: ... indexStochastic = 0 for index in range(len(times)): while (indexStochastic < len(stochasticTimes)-1) \ & (stochasticTimes[indexStochastic+1] < times[index]): indexStochastic+=1 (add stochastic M[indexStochastic] to total M[index]...) Or, we can use the "searchsorted" method defined for arrays: t = scipy.searchsorted(stochasticTimes, times) m = [stochasticMs[e-1] for e in t] (add m to total M) Check that your method is working by plotting the stochastic trajectory (as lines) and the interpolated trajectory (as points: 'ro') """ pass # # Copyright (C) Cornell University # All rights reserved. # Apache License, Version 2.0