Tutorial 3 - cellmodeller/CellModeller GitHub Wiki
In this tutorial we will cover how to make cells produce diffusible signals. To do this we will study a simple system, where two species of bacteria (A and B) are grown together, each producing a their own diffusible signal. To make this case more interesting, the behaviour of the two strains is mutualistic – the growth rate of each bacteria type is dependent on the signal of the other.
Let's open Examples/Tutorial_3/Tutorial_3.py and run it in the GUI, as well as in a text editor.
This model is set up in a similar way to the previous tutorial, with 2 species initialized in the integrator. However, a new addition to the model setup is the initialization of the signalling model GridDiffusion, imported from CellModeller.Signalling. This signalling module diffuses extracellular signals on a 3D spatial grid.
Note that we have to specify the dimensions, size and origin of the grid on which the signals diffuse. In this case, our grid is 80x80x8 units, with each grid cube 2x2x2 units. In order to have the cells growing in the middle of the grid, we initialize the grid origin at (-160,-160,-16). These parameters are used when the signalling grid is initialized:
grid_dim = (80, 80, 8)
grid_size = (4, 4, 4)
grid_orig = (-160, -160, -16)
n_signals = 2
n_species = 2
…
sig = GridDiffusion(sim, n_signals, grid_dim, grid_size, grid_orig, [10.0, 10.0])
integ = CLCrankNicIntegrator(sim, n_signals, n_species, max_cells, sig)
sim.init(biophys, regul, sig, integ)
Note that here, the diffusion rates on the grid are set in the last argument of GridDiffusion initialization, in this case they are set to 10 for each signal.
The mathematical model underlying the mutualistic behaviour is simple:
Each bacterium produces an intercellular chemical species with a constant rate, specific to its cell type. These then diffuse out of the cell, resulting in two diffusing signals that diffuse through the extracellular space. These then diffuse into cells, turning back into chemical species within the cells.
In order to model mutualistic behaviour, we want the growth of cell of type A dependent on the presence of cell type B. The growth rate of each bacteria type is therefore linked to the concentration of the signal produced by the other cell type. This is summarised the following figure:
In this model we have 2 species, representing each chemical intracellularly, and 2 signals, representing them extracellularly.
To set the production and diffusion rates within the simulations. These are intialized within the preamble to set up all our variables (This is required as this is OpenCL code, and not python code):
cl_prefix = \
'''
const float Da = 1.0f;
const float Db = 1.0f;
const float ka = 1.f;
const float kb = 1.f;
float alpha_in = species[0];
float alpha = signals[0];
float beta_in = species[1];
float beta = signals[1];
'''
Here we have intialized the diffusion rates through the membrane for signals A and B, Da and Db, and production rates, ka and kb, as well as the chemical concentrations both outside and inside the cells.
The specRateCL function specifies intracellular chemical reactions, as shown in previous Tutorials. This function specifies a constant intracellular production rate, dependent on cell type, as well as diffusion of the chemical in and out of the cell:
def specRateCL():
global cl_prefix
return cl_prefix + '''
if (cellType==0){
rates[0] = ka + Da*(alpha-alpha_in)*area/gridVolume;
rates[1] = Db*(beta-beta_in)*area/gridVolume;
} else {
rates[0] = Da*(alpha-alpha_in)*area/gridVolume;
rates[1] = kb + Db*(beta-beta_in)*area/gridVolume;
}
'''
The sigRateCL function specifies the behaviour of the extracellular signals. Diffusion on the grid is handled explicitly by the GridDiffusion module, so this just deals with diffusion in and out of the cells:
def sigRateCL():
global cl_prefix
return cl_prefix + '''
rates[0] = -Da*(alpha-alpha_in)*area/gridVolume;
rates[1] = -Db*(beta-beta_in)*area/gridVolume;
'''
And in the update function, we see that the cell growth rate is dynamically regulated by the signals:
if cell.cellType==0:
cell.growthRate = 0.1 + v_max * cell.species[1] / (Km + cell.species[1])
else:
cell.growthRate = 0.1 + v_max * cell.species[0] / (Km + cell.species[0])
This model produces colonies with 2 cell types that cooperate. Since the growth rate of each cell type is dependent on proximity to the other type, it results in intermixed colonies:
When the growth rates are set to be independent of any species (set to 1 for both cell type), we see a drastic change in colony structure: