When the uAlberta team first started their buoyancy assays, the foremost question in their mind was: how long will it take the bacteria containing the gas vesicles to get to the top? Seconds? Minutes? Hours? Days? To better understand this question and to find an answer, we dug out our physics textbooks and started with a very simple equation: Velocity equals the change in distance over the change in time. We knew that if we can find the velocity of the gas vesicle-producing Escherichia coli bacteria, we can use that to calculate the time it will take for the bacteria to travel a certain distance of the culture tube. At the time, there were a few options: we could take a high-resolution photo every certain interval and trace the distance travelled by a single layer of bacteria; we could measure the absorbance at different depths of the culture over time; or we could streak different levels of the tube on an agar plate and count the resulting number of individual colonies. However, none of these options were advising the initial parameters of our assay so that the E. coli containing the gas vesicles reach the top at a desired time. To understand how these parameters affected the buoyancy of our bacteria, we started by looking at the individual forces that act on these bacteria.

Model Approach by Individual Forces

Force 1) Buoyancy Force

Buoyancy is the force exerted on an object that is wholly or partly immersed in a fluid. In this case, buoyancy force is exerted on the E. coli bacteria containing the desired GVP’s.

\[ Fb = displaced\ liquid\ by\ the\ vesicle\\Fb=mg,\ \ p = \frac{m}{v}\\Fb = pV(g)\\Fb=p*\frac{4}{3}\pi r^3*g\\Fb=-\frac{4}{3}*\pi r^3*(p-p_v)*g \]

Force 2) Drag Force

Drag Force, sometimes also called air resistance or fluid resistance, is the force acting opposite to the relative motion of any object moving with respect to a surrounding fluid.

\[ Fd = Cd*0.5pv^2\\Cd=\frac{24}{Re}(1+0.15Re^{0.687})\\Fd=\frac{24}{200}(1+0.15+Re^{0.687}*0.5pv^2*A\\Fd=\frac{24}{200}(1+0.15+Re^{0.687}*0.5pv^2*2\pi r^2\\p=p_f-p_v \]

Force 3) Added Mass Force

Added mass or virtual mass is the inertia added to a system because an accelerating or decelerating body must move (or deflect) some volume of surrounding fluid as it moves through it. Added mass is a common issue because the object and surrounding fluid cannot occupy the same physical space simultaneously.

Force 4) Basset/History Force (Due to viscosity)

The basset term accounts for viscous effects and addresses the temporal delay in boundary layer development as the relative velocity changes with time.

Force 5) Surface Forces

Surface forces accounts for short-ranged interactions between E. coli bacteria and surface, electrical double layer interactions, van der Waals forces between surface and the bacteria and the surface tensions between bacteria and its surroundings.

Net Force

Finding Acceleration

Solving for acceleration using Force equals mass times acceleration; mass of E. coli bacteria is used.

Terminal Velocity

The above equation representing the acceleration via net force is still limited as it does not allow us to solve for velocity of the E. coli bacteria containing the gas vesicles at different time scales. This is because due to Newton’s 2nd Law of Motion, the acceleration of an object as produced by a net force is directly proportional to the magnitude of the net force, in the same direction as the net force, and inversely proportional to the mass of the object. If the acceleration is constant, then by first-principle kinematics, the velocity must also be constant. To model this relationship, we used G. Stokes Law, where he derives the basic formula for the drag of a sphere in a remarkable 1851 scientific paper. In this paper, he makes an assumption that the Reynold number is less than unity and is thus mainly concerned with spheres of very small diameter when surrounding a liquid fluid. Likewise, we assumed that E. coli bacteria containing the GVP’s are spherical, small and slow moving, in a laminar flow of homogenous LB, have smooth surfaces and do not interact with one another. We also made an assumption that drag force, viscosity and buoyancy force are the only forces affecting the velocity of the GVP’s and all other forces are negligible.

Lets assume a sphere with radius r=a. The viscous and incompressible flow of the sphere will have only radial and polar angle dependent velocity components.

After manipulation:

Substituting f=rk leads to a 4th order polynomial with exponents -1, 1, 2 and 4.

Using different velocity components and radial pressure gradient from above

Carrying out the integrations and solving for Force due to pressure, and force due to viscosity.

Final equation derived by G. Stokes in 1851:

Limitations of Stokes Law

There are several assumptions made to meet the limitations of the Stokes law. We assumed the following behaviour of the bacteria in the LB culture:

  • Fluid flows in parallels layers, with no disruption between the layers - Laminar Flow
  • E. coli bacteria are spherical shaped, rather than rod.
  • LB solution is homogeneous, uniform in composition, with a single density (not a gradient)
  • Bacteria and GVP’s do not interact or interfere with one another
  • All molecules have smooth surfaces

Qualitative Model for Terminal Velocity

To understand the affect of different parameters, such as number of bacteria, number of gas vesicles per bacteria, E.coli diameter, density, and viscosity, we created a model in Java using Netbeans. This model allowed us to qualitatively understand how each parameter influences the velocity of the bacteria in accordance with Stokes’ Law. This model also assumes that the random movement due to bacterial death and diffusing is negligible.. From this model, our team was able to understand how these parameters affect buoyancy and how they can be tuned to increase or decrease bacterial separation due to buoyancy. However, in the future, it will be more useful to incorporation diffusion coefficients. sedimentation rate and interactions between molecules to more realistically represent what happens to the bacteria in culture.

Click here to view the Java code

import java.awt.Color; import java.awt.EventQueue; import java.awt.Graphics; import java.awt.Graphics2D; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowAdapter; import java.awt.Container; import java.awt.event.WindowEvent; import java.awt.geom.Ellipse2D; import java.awt.geom.GeneralPath; import java.awt.RenderingHints; import java.awt.BorderLayout; import java.awt.GridLayout; import java.util.Random; import java.util.List; import java.util.ArrayList; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JLabel; import javax.swing.Timer; import javax.swing.JTextField; import javax.swing.JSlider; import javax.swing.JButton; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener; import javax.swing.border.Border; import javax.swing.BorderFactory; class eCOLI { int x, y; double speed; } class Surface extends JPanel implements ActionListener { GeneralPath star; List<Ellipse2D.Double> eCOLIs; List<Double> speed_y; private Timer timer; private int acc_grav = 9, diam = 10, col_dens = 20, visc = 20, sol_dens = 19, inside_val = 0; public static double average_velocity = 2.5; private final double points[][] = { {0, RISE.HEIGHT}, {400, RISE.HEIGHT}, {250, RISE.HEIGHT-300}, {250, RISE.HEIGHT-450}, {280, RISE.HEIGHT-470}, {120, RISE.HEIGHT-470}, {150, RISE.HEIGHT-450}, {150, RISE.HEIGHT-300} }; public Surface() { star = new GeneralPath(); eCOLIs = new ArrayList<Ellipse2D.Double>(); speed_y = new ArrayList<Double>(); set_eCOLIs(20); initTimer(); } public void reset() { for(int i=0; i<eCOLIs.size(); ++i) { double x = Math.random() * 340 + 30; eCOLIs.get(i).setFrame(x, RISE.HEIGHT-20, diam, diam); } } private double get_velocity() { double speed_tmp = (double)acc_grav * (double)diam * (double)diam; speed_tmp *= ((double)col_dens + (double)inside_val) - ((double)sol_dens - (double)inside_val); speed_tmp /= 18.0 * (double)visc; average_velocity = (double)Math.round(100.0 * speed_tmp) / 100.0; average_velocity = Math.min(average_velocity, 15.0); average_velocity = Math.max(average_velocity, 0.0); speed_tmp += Math.random() * 2; speed_tmp = Math.min(speed_tmp, 15.0); speed_tmp = Math.max(speed_tmp, 0.0); return speed_tmp; } public void set_eCOLIs(int val) { int len = eCOLIs.size(); if(val > len) { for(int i=len; i<=val; ++i) { Ellipse2D.Double eCOLI_tmp = new Ellipse2D.Double(); double speed_tmp; double x = Math.random() * 340 + 30; eCOLI_tmp.setFrame(x, RISE.HEIGHT-20, diam, diam); eCOLIs.add(eCOLI_tmp); speed_y.add(get_velocity()); } } else { for(int i=len-1; i>=val; --i) { eCOLIs.remove(i); speed_y.remove(i); } } } public void set_eCOLIs_1(int val) { inside_val = val; for(int i=0; i<eCOLIs.size(); ++i) speed_y.add(i, get_velocity()); } public void set_acc_grav(int val) { acc_grav = val; for(int i=0; i<eCOLIs.size(); ++i) speed_y.add(i, get_velocity()); } public void set_diam(int val) { diam = val; for(int i=0; i<eCOLIs.size(); ++i) speed_y.add(i, get_velocity()); } public void set_col_dens(int val) { col_dens = val; for(int i=0; i<eCOLIs.size(); ++i) speed_y.add(i, get_velocity()); } public void set_visc(int val) { visc = val; for(int i=0; i<eCOLIs.size(); ++i) speed_y.add(i, get_velocity()); } public void set_sol_dens(int val) { sol_dens = val; for(int i=0; i<eCOLIs.size(); ++i) speed_y.add(i, get_velocity()); } private void initTimer() { timer = new Timer(30, this); timer.setInitialDelay(150); timer.start(); } private void moveUp(int p) { if(eCOLIs.get(p).getY() > RISE.HEIGHT-470+diam) { double new_x = eCOLIs.get(p).getX(); double new_y = eCOLIs.get(p).getY() - speed_y.get(p); double line_right_x = (new_y - RISE.HEIGHT + 800) / 2.07 - diam; double line_left_x = (RISE.HEIGHT - new_y) / 1.9; if(new_y > RISE.HEIGHT-300) { new_x = Math.min(new_x, line_right_x); new_x = Math.max(new_x, line_left_x); } eCOLIs.get(p).setFrame(new_x, new_y, diam, diam); } else { double new_x = eCOLIs.get(p).getX(); if(new_x + diam > 250) new_x -= diam; else if(new_x - diam < 0) new_x += diam; eCOLIs.get(p).setFrame(new_x, RISE.HEIGHT-470+diam, diam, diam); } } private void draweCOLIs(Graphics2D g2d) { for(int i=0; i<eCOLIs.size(); ++i) { g2d.setColor(new Color(209, 175, 165)); moveUp(i); g2d.fill(eCOLIs.get(i)); } } private void drawBottle(Graphics2D g2d) { star.moveTo(points[0][0], points[0][1]); for (int k=1; k<points.length; k++) star.lineTo(points[k][0], points[k][1]); star.closePath(); g2d.fill(star); } private void doDrawing(Graphics g) { Graphics2D g2d = (Graphics2D) g.create(); g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g2d.setRenderingHint(RenderingHints.KEY_RENDERING, RenderingHints.VALUE_RENDER_QUALITY); g2d.setPaint(new Color(255, 99, 185)); g2d.translate(100, -70); drawBottle(g2d); draweCOLIs(g2d); g2d.dispose(); } @Override public void paintComponent(Graphics g) { super.paintComponent(g); doDrawing(g); } @Override public void actionPerformed(ActionEvent e) { repaint(); } } public class RISE extends JFrame { public static int WIDTH = 900; public static int HEIGHT = 600; Container container = getContentPane(); JPanel panel; Surface surface; JSlider s_num_eCOLIs, s_num_1_eCOLIs, s_diam; JSlider s_col_dens, s_visc, s_sol_dens; JButton reset_btn; JLabel avg_vel; public RISE() { JLabel l_num_eCOLIs = new JLabel("Number of eCOLIs: "); JLabel l_num_1_eCOLIs = new JLabel("Number of eCOLIs 2: "); JLabel l_acc_grav = new JLabel("Acceleration of Gravity: "); JLabel l_diam = new JLabel("E. coli Diameter: "); JLabel l_col_dens = new JLabel("E. coli Density: "); JLabel l_visc = new JLabel("Solution Viscosity: "); JLabel l_sol_dens = new JLabel("Solution Density: "); s_num_eCOLIs = new JSlider(JSlider.HORIZONTAL, 0, 1000, 20); s_num_1_eCOLIs = new JSlider(JSlider.HORIZONTAL, 0, 100, 0); s_diam = new JSlider(JSlider.HORIZONTAL, 0, 20, 10); s_col_dens = new JSlider(JSlider.HORIZONTAL, 0, 5000, 19); s_visc = new JSlider(JSlider.HORIZONTAL, 0, 1000, 20); s_sol_dens = new JSlider(JSlider.HORIZONTAL, 0, 5000, 20); add_sliders_listeners(); reset_btn = new JButton("reset"); add_buttons_listeners(); avg_vel = new JLabel("Average Velocity = " + String.valueOf(Surface.average_velocity)); panel = new JPanel(new GridLayout(0, 1)); Border emptyBorder = BorderFactory.createEmptyBorder(20, 20, 0, 0); panel.setBorder(emptyBorder); add_in_panel(l_num_eCOLIs, s_num_eCOLIs); add_in_panel(l_num_1_eCOLIs, s_num_1_eCOLIs); add_in_panel(l_diam, s_diam); add_in_panel(l_col_dens, s_col_dens); add_in_panel(l_visc, s_visc); add_in_panel(l_sol_dens, s_sol_dens); panel.add(reset_btn); panel.add(avg_vel); container.add(BorderLayout.WEST, panel); surface = new Surface(); container.add(surface); setTitle("RISE"); setSize(WIDTH, HEIGHT); setLocationRelativeTo(null); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); } private void add_in_panel(JLabel lb, JSlider sl) { panel.add(lb); panel.add(sl); } private void add_sliders_listeners() { s_num_eCOLIs.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { JSlider tempSlider = (JSlider)e.getSource(); int val = (int)tempSlider.getValue(); surface.set_eCOLIs(val); surface.repaint(); } }); s_num_1_eCOLIs.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { JSlider tempSlider = (JSlider)e.getSource(); int val = (int)tempSlider.getValue(); surface.set_eCOLIs_1(val); avg_vel.setText("Average Velocity = " + String.valueOf(Surface.average_velocity)); surface.repaint(); } }); s_diam.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { JSlider tempSlider = (JSlider)e.getSource(); int val = (int)tempSlider.getValue(); surface.set_diam(val); avg_vel.setText("Average Velocity = " + String.valueOf(Surface.average_velocity)); surface.repaint(); } }); s_col_dens.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { JSlider tempSlider = (JSlider)e.getSource(); int val = (int)tempSlider.getValue(); surface.set_col_dens(val); avg_vel.setText("Average Velocity = " + String.valueOf(Surface.average_velocity)); surface.repaint(); } }); s_visc.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { JSlider tempSlider = (JSlider)e.getSource(); int val = (int)tempSlider.getValue(); surface.set_visc(val); avg_vel.setText("Average Velocity = " + String.valueOf(Surface.average_velocity)); surface.repaint(); } }); s_sol_dens.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { JSlider tempSlider = (JSlider)e.getSource(); int val = (int)tempSlider.getValue(); surface.set_sol_dens(val); avg_vel.setText("Average Velocity = " + String.valueOf(Surface.average_velocity)); surface.repaint(); } }); } private void add_buttons_listeners() { reset_btn.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { surface.reset(); } }); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { RISE ex = new RISE(); ex.setVisible(true); } }); } } `

Viscosity vs Velocity Trends

Figure 1: Graph representing the effect of increasing viscosity on velocity. When the viscosity of the solution increases, the velocity decreases exponentially. For comparison, the blue dot represents the viscosity of water.

Figure 2: Position vs Time graph for solutions with different viscosities. With increasing viscosities, the bacteria are able to travel faster through the media.

Péclet Number

We collaborated with the IISc Bangalore 2017 team, who is also working with gas vesicles, and they informed us that diffusion plays a significant role in the buoyancy of the bacteria. Diffusion’s importance is highlighted by their Péclet number (Pe) calculation: the ratio of the rate of advection of a physical quantity by the flow to the rate of diffusion of the same quantity driven by an appropriate gradient. This is calculated by taking the product of Reynolds number and the Schmidt number. If the Péclet number is extremely small compared to 1, diffusion is dominant over advective transfer and must be considered during our calculations.

\[ Pe_L = \frac{Lu}{D}=Re_LSc \]

The ratio for Péclet number (Pe) is as follows, where L is the characteristic length scale of the system (~200 nm for a gas vesicle), u the local velocity of the fluid and D the mass diffusion coefficient.

For a typical gas vesicle particle at room temperature (T = 273K),

  • L ~ 500 nm
  • u ~ 10 nm/s
  • RH ~ 20nm

Substituting these numbers, we get a Péclet number on the order of 10-3, which implies dominant diffusive effects when gas vesicles are allowed to settle at the equilibrium concentration profile. In such a case, we require a model that can account for the behaviour of floating particles in the highly-diffusive regime.

Illustrations: Qualitative solutions to the model

Collaboration with the IISc BANGALORE TEAM

Illustration 1: Uniform initial profile with exponential boundary conditions. Assuming the initial mixing is uniform, this is the most natural way in which we expect the concentration function to evolve on the boundaries. The exact initial and boundary conditions are taken such that they satisfy each other nicely. The contour plot below shows how the profile evolves over time. The legend on the right shows the relative magnitude of concentrations present in the plot.

Illustration 2: Exponential initial profile with exponential boundary conditions. Such a situation can arise in the event the particles have settled down due to gravity initially but start floating instantaneously at t=0. While quite unrealistic, this solution might be useful in cases where the gas vesicles have been reversibly denatured but are allowed to float up after removing the denaturing agent. The plot below shows how the profile evolves over time.

Illustration 3: Linear initial profile with exponential boundary conditions. This is the most unlikely of the three cases we've dealth with till now. An linear initial profile is almost impossible under normal conditions unless some kind of external agency maintains it. Even then, we've tried to solve the equations to show how the concentrations will evolve for such a case.

Illustration 4: Uniform initial profile with quadratic boundary conditions. While not usually encountered in nature, saturating inverse quadratic solutions are given here for demonstration purposes. The first of them is obivously, the uniform initial distribution.

Illustration 5: Exponential initial profile with quadratic boundary conditions.

Illustration 6: Linear initial profile with quadratic boundary conditions.

Future Direction

While our models and equations give a good representation of the affect of different parameters on the buoyancy of E. coli, it will be beneficial to check the accuracy of this model experimentally in the near future. To do so, we intend to use different methods to see how the flotation of GVP’s changes with time. We will use several approaches to do this: we will take high-resolutions picture at 1 hour intervals and build a macro to trace the distance of a single layer of bacteria. This seems feasible using java-based image processing program, ImageJ. Secondly, we intend to measure the absorbance at different levels of the culture tube over time and compare these absorbances. Depending on the amount of GVP’s in the bacteria, we expect their to be an uneven distribution among the gradient of the culture in the tube. Finally, we will do one more test where we will be pellet different portions of the tube and statistically analyze the amount of colonies present in each layer. After performing these tests, we will go back to our model and determine its accuracy. If we find that the model does not completely represent the experimented observations, then we will go back and start eliminating our assumptions until the model has been modified to a near-perfect accuracy.


  • Stokes, G.G., 1851, On the effect of the internal friction of fluids on the motion of pendulums: Cambridge Philosophical Society, Transactions, v. 9, no. 8, p. 287.
  • Schubauer, G.B., and Skramstad, H.K., 1947, Laminar boundary-layer oscillations and stability of laminar flow: Journal of Aeronautical Science, 14 (2), p. 69-78.
  • Nielsen, P., 1984, On the motion of suspended sand particles: Journal of Geophysical Research, v. 89, p. 616-626.
  • Nielsen, Peter. Combined Convection-diffusion modelling of sediment entrainment. Coastal Engineering 1992 . doi:10.1061/9780872629332.244
  • Patankar, Suhas V. (1980). Numerical Heat Transfer and Fluid Flow. New York: McGraw-Hill. p. 102.
  • Walsby AE. Gas vesicles. Microbiological Reviews. 1994;58(1):94-144
  • Creating Java simulation:

Special thanks to all our sponsors!

Social Media