May 2, 2017

Simulation of bacterial growth

How could we simulate the bacteria growth under different temperatures?

By Claire Baudelet, Gabriel Ragala, Léo Houairi



Life sciences have definitely something to do with computational ones! And that’s what we experimented, during this one-day so exciting project. After spending a whole week growing bacteria in the laboratory, we decided then to continue characterizing them… ...but with the hindsight of modelisation. What is striking is that modelisation is both a way to go deeper in the topic and to take distance from it. As a matter of fact, despite having no contact with any bacteria, we had to ask ourselves about all the little things that are actually the keys for a good understanding of bacterial growth! If creativity does have a place in designing an ingenious program, the main problem is indeed to be as realistic as possible. So, here, as we wanted to design a model for bacterial growth under different temperatures, we expected both to have a pattern coherent with the observable circular shape of any real colony and to get different patterns depending on temperature. It’s useful to know that till a certain point where cells die instead of growing, an increase in temperature corresponds to an increase in the growth rate. A good model would then help predicting the spatial repartition of growing bacteria of a colony under any temperature.

To solve our question, we coded for an entire day! The traditional Petri dish was simulated by a matrix, containing for each position either 0 for  “no bacterium” or 1 for “bacterium”. But during each replication step, newly created bacteria were rather symbolized by a 3 in order to prevent them from being also duplicated. At the end of the step, every 3 becomes a 1. Then, at each timestep, a random number between 0 and 7 is generated to make the new bacterium go into one of the eight positions around the mother cell. And, if the box chosen is already full,we simulated the shift provoked by the creation of the bacteria, by saying that  if there’s a 3 or a 1, you  look at the next case until you find an empty one. And, last but not least,  the influence of temperature on growth is controlled by an input parameter for which the user has to enter the time needed for one cell to divide once under the wanted temperature. The division period of a bacterium at a certain temperature can be deduced from the growth rate at the same temperature: for example if the growth rate at 20 °C is 0,2 division by minute, then you know that a division will take 5 minutes to occur. We eventually made a cloud of points at each timestep to represent the results.

Blogpost.gif30.gif
Here are two simulations of a growing colony. As expected, both colonies are quite circular. Also, due to different temperatures, they don’t grow at the same speed. When temperature requires a division time of 20 mn, after 300 mn of growth, the colony is clearly bigger than the one undergoing a division time of 30 mn!

5 colonies définies.gif

Also, have a look at that picture! Here we put five colonies on the same matrix. And if you look closely, you can see that they don’t have exactly the same shape, which is proof of how our program is random!
From our results, we can conclude that we managed to make a simple but quite coherent simulation of bacterial growth in function of temperature. The follow up of our project would probably be to include many more parameters that have an impact on cell growth such as the quantity of nutrients. Also, natural death of the bacteria has to be taken into account, by adding a limited lifetime to each bacterium. So far we obtained indeed a so ideal but not that realistic number of bacteria of exactly 2 to the power of the number of division…  Finally, we could also do a 3D simulation, which would gave to the bacteria the possibility to grow on top of another bacterium.




Feel free to contact us for any reason about this project, at :


And if you want to have a look at our code, see below!
The explanations are given after each “#”.


#!/usr/bin/python
# -*- coding: utf-8 -*-

import random #We need function random for this program
import numpy as np
import matplotlib.pyplot as plt

x = 1000 #We set the size of the matrix
y = 1000
m = x - 1 #If we use the full matrix, the program will fail at some point when it will try to add a number outside the
         #matrix. Not using the border of the matrix solve this problem.
n = y - 1
Z = [(600,600)] #This variable store the position of the bacteria
X = [] #This two lines will be use to store both coordinate of the bacteria
Y = []
xpos = np.zeros((x,y)) #This is generating the matrix
xpos[600,600] = 1 #This is setting the first bacterium

L = [0,1,2,3,4,5,6,7] #This is list is use to generate a random direction

print('Choose a period of division at the temperature used:')
T = input() #This is use to ask a period of division to the user
t = 0 #This line is setting the time counter to 0
while t < 2: #This line control the number of divisions
    for a in range(0,m):
           for b in range(0,n): #This two lines as the computer to look to all the matrix
                   if xpos[a][b] == 1: #If the computer find a 1 (a bacterium)
                   alea = random.choice(L) #Generate an aleatory number between 0 and 7
                   if alea == 0:
                           if xpos[a+1][b] == 0: #Look at the case [a+1][b], if it's empty:
                                   xpos[a+1][b] = 3 #Add a 3 to the case
                           else:  #If not, look to the next case until you find an empty one
                                   i = 1
                                   while xpos[a+i][b] != 0:
                                       i = i + 1
                                   else:
                                   xpos[a+i][b] = 3
                   if alea == 1: #All the other lines starting by if alea ... are the same than the first one I explained but for the other 7 directions   
                          if xpos[a-1][b] == 0:
                                   xpos[a-1][b] = 3
                           else:
                                   j = 1
                                   while xpos[a-j][b] != 0:
                                       j = j + 1
                                   else:
                                       xpos[a-j][b] = 3
                   if alea == 2:
                           if xpos[a][b+1] == 0:
                                   xpos[a][b+1] = 3
                           else:
                                   k = 1
                                   while xpos[a][b+k] != 0:
                                       k = k + 1
                                   else:
                                       xpos[a][b+k] = 3
                   if alea == 3:
                           if xpos[a][b-1] == 0:
                                   xpos[a][b-1] = 3
                           else:
                                   l = 1
                                   while xpos[a][b-1] != 0:
                                       l = l + 1
                                   else:
                                       xpos[a][b-1] = 3
                   if alea == 4:
                           if xpos[a+1][b+1] == 0:
                                   xpos[a+1][b+1] = 3
                           else:
                                   e = 1
                                   f = 1
                                   while xpos[a+e][b+f] !=0 :
                                       e = e + 1
                                       f = f + 1
                                   else:
                                       xpos[a+e][b+f] =3
                   if alea == 5:
                           if xpos[a+1][b-1] == 0:
                                   xpos[a+1][b-1] = 3
                           else:
                                   g = 1
                                   h = 1
                                   while xpos[a+g][b-h] != 0:
                                       g = g + 1
                                       h = h + 1
                                   else:
                                       xpos[a+g][b-h] = 3
                   if  alea == 6:
                           if xpos[a-1][b+1] == 0:
                                   xpos[a-1][b+1] = 3
                           else:
                                   v = 1
                                   u = 1
                                   while xpos[a-v][b+u] != 0:
                                       v = v + 1
                                       u = u +1
                                   else:
                                       xpos[a-v][b+u] = 3
                   if alea == 7:
                           if xpos[a-1][b-1] == 0:
                                   xpos[a-1][b-1] = 3
                           else:
                                   p = 1
                                   q = 1
                                   while xpos[a-p][b-q] != 0:
                                       p = p + 1
                                       q = q + 1
                                   else:
                                       xpos[a-p][b-q] = 3
t = t + 1 #Up the time counter
    for a in range(0,m):
           for b in range(0,n): #Look at all the matrix
                   if xpos[a][b] == 3:
               X    pos[a][b] = 1 #If you find a 3 (a new bacterium); transform into a 1 (a real bacterium)
    for a in range (0,m):
           for b in range (0,n): #Look at all the matrix
                   if xpos[a][b] == 1: #If you find a one
                       if (a,b) not in [Z]: #And if it's not already in the matrix
                               X.append(b) #Add his b coordinate to list X
                               Y.append(a) #Add his a coordinate to list Y
                               Z.append((b,a)) #Add his position to Z
time = t*T #This is a counter of time in minutes, period of division * number of division
plt.scatter(X,Y) #This set the cloud of point
plt.axis([500, 700, 500, 700]) #This set the part of the cloud of point you want to see
plt.title('Colonies of bacteria after ' + str(time) + ' min') #This set the title of the graph
plt.show() #This allows you to see the cloud of points

No comments:

Post a Comment

Blog disclaimer

The content created by the Learning thru research Student Bloggers and those providing comments are theirs alone, and do not reflect the opinions of Centre de recherche interdisciplinaire, University Paris Descartes or any employee thereof. The authors of posts and comments are responsible for the accuracy of any of the information supplied on this blog, as well as for any content copyright issues.