This HTML version of the exercises is only intended to give you a quick view of what the exercises are about. Use the .ipynb file to solve the exercises!

Exercise 3: Simulation of gene expression and regulation (DL 20 November)

Lecturer: Antti Honkela

Your name:

Name of your pair:

In this exercise you will implement simulators to simulate biochemical reaction systems similar to ones that could be used to simulate gene expression. Each task is worth 2 points.

Task 1: Discrete event simulation I: Simple systems

In this task your aim is to perform stochastic simulation of simple discrete reaction systems with a single species X in different scenarios. Each scenario comes with a number of questions. Please answer these by having your code print out the answers.

a) Simulate the decay of a population of 100 individuals with decay rate 1.

The corresponding reaction system is: \[ X \rightarrow \emptyset \]

In []:
%matplotlib inline
# Import some useful modules
import matplotlib.pyplot as plt
import numpy as np
import numpy.random as npr

# Suggested structure: simulate the decay of a population of N0 individuals at rate 'rate' for 'numsteps' steps
def simulate_decay(N0, rate, numsteps):
    # Current population size
    N = N0
    # Current time
    t_cur = 0
    # History of population size across the simulation
    Nhist = np.zeros(numsteps)
    Nhist[0] = N
    # Times of the corresponding population sizes
    Thist = np.zeros(numsteps)
    Thist[0] = t_cur
    # ...
    # ADD CODE FOR PERFORMING THE SIMULATION HERE
    # ...
    return (Thist, Nhist)

b) Simulate a birth-death process of a population of 100 individuals with decay rate 1 and birth rates [0.8, 1, 1.2] for 10000 steps.

The corresponding reaction system is:
In []:
def simulate_birthdeath(N0, birthrate, deathrate, numsteps):
    # Current population size
    N = N0
    # Current time
    t_cur = 0
    # History of population size across the simulation
    Nhist = np.zeros(numsteps)
    Nhist[0] = N
    # Times of the corresponding population sizes
    Thist = np.zeros(numsteps)
    Thist[0] = t_cur
    # ...
    # ADD CODE FOR PERFORMING THE SIMULATION HERE
    # ...
    return (Thist, Nhist)

c) Simulate a migration-death process of a population of 100 individuals with decay rate 1 and migration rates [1.0, 10.0, 100.0] for 10000 steps.

The corresponding reaction system is:
In []:
def simulate_migrationdeath(N0, migrationrate, deathrate, numsteps):
    # Current population size
    N = N0
    # Current time
    t_cur = 0
    # History of population size across the simulation
    Nhist = np.zeros(numsteps)
    Nhist[0] = N
    # Times of the corresponding population sizes
    Thist = np.zeros(numsteps)
    Thist[0] = t_cur
    # ...
    # ADD CODE FOR PERFORMING THE SIMULATION HERE
    # ...
    return (Thist, Nhist)

Briefly summarise how each model behaves qualitatively in the text area below:

Task 2: Discrete event simulation II: The general case

a) Implement the general Stochastic Simulation Algorithm of Gillespie (1977).

In []:
# Suggested skeleton for the simulation algorithm
# Suggested arguments are NumPy arrays with sizes as follows:
# inputs: [reactions x state]
# outputs: [reactions x state]
# rates: [reactions]
def stochastic_simulation_algorithm(initstate, inputs, outputs, rates, numsteps):
    # Current time and state
    t_cur = 0
    state = 1.0 * initstate
    # State history
    Nhist = np.zeros((numsteps, len(state)))
    Nhist[0,:] = state
    # Time history
    Thist = np.zeros(numsteps)
    Thist[0] = t_cur
    # ...
    # ADD CODE FOR PERFORMING THE SIMULATION HERE
    # ...
    return (Thist, Nhist)

b) Use your simulator to simulate the Lotka-Volterra predator-prey system:

In []:

Task 3: Continuous-state simulation

a) Implement a deterministic ordinary differential equation simulator using the same input as the stochastic simulator above.

Your simulator should follow Eq. (11) in Gillespie (2000) paper. In order to discretise the time, please select a finite time step and apply the Euler discretisation of approximating \[ \frac{dX(t)}{dt} = f(X(t)) \] by \[ X(t + \tau) \approx X(t) + \tau \cdot f(X(t)). \]

In []:
# Suggested skeleton with same arguments as above, except tau is the time step
def simulate_reaction_ode(initstate, inputs, outputs, rates, numsteps, tau):
    pass

b) Implement a stochastic continuous-state simulator using the same input as above.

Your simulator should follow Eq. (21) of the Gillespie (2000) paper.

In []:
# Suggested skeleton with same arguments as above, except tau is the time step
def simulate_chemical_langevin_eq(initstate, inputs, outputs, rates, numsteps, tau):
    pass

Task 4: Simulating repression

In this task you will implement a simplified model of repressive regulation, a simplified "repressilator". This is more complicated than the predator-prey system in 2b because preventing preduction is not the same as enhancing degradation. (In the predator analogue, predators would only target the young and therefore decrease the birth rate of prey but leave the existing (adult) population intact.

The repressilator model has 3 genes, each of which represses the next in a cycle A -> B -> C -> A. A realistic model would include 6 species to model both mRNAs and protein levels of each gene. In this task we simplify things a bit by combining the mRNA and protein for each gene.

In order to simulate repression, we augment the model by introducing additional states \(aX\) and \(rX\) that represent "active" and "repressed" promoter states of gene \(X \in \{A, B, C\}\). Production of gene \(X\) only happens when the promoter is in the active state and the repressor moves the promoter into repressed state. The system can be expressed through reactions:

These reactions are repeated for all genes, resulting in total 12 reactions for the 9 species in the system.

In []:

Bonus task: implement a full repressilator model including both mRNAs and proteins. Try to assign realistic rates for all the reactions. Simulate your model using the simulators you implemented in Tasks 2 and/or 3 and visualise the results.

In []:

Task 5: Simulating network motifs

a) Use the simulators to simulate from the SIM (single input motif) network motif.

Using a model with regulator \(TF\) and targets \(X_i\) the system can be expressed through reactions:

Starting with relatively high TF abundance and fairly low decay will give interesting profiles.

You can experiment with rate constants to obtain interesting results. One set of rate constants that yield reasonable behaviour is:

target_transcription_rates = np.logspace(-1, 1, N) target_decay_rates = np.logspace(-1, 2, N) TF_decay_rate = 10 TF_initial_abundance = 100

In []:

b) Use the simulators to simulate from the feed-forward loop network motif.

In []:

General hints and warnings