Growth media

In many instances you might be interested what metabolites your microbial community consumes and produces. micom provides facilities to make this simple. Since flux distributions are usually not unique we will usually analyze the “minimal medium”, meaning the smallest set of import fluxes that allow optimal growth. We will again use our E. coli test case.

In [1]:
from micom import Community, data

tax = data.test_taxonomy()
com = Community(tax, solver="gurobi")
100%|██████████| 5/5 [00:00<00:00,  5.69models/s]

The easiest case would be that we have a particular community growth rate we want to enforce. In this case we can get the minimal medium with:

In [2]:
from micom.media import minimal_medium

med = minimal_medium(com, 0.8)
med
Out[2]:
EX_glc__D_m    10.000000
EX_nh4_m        4.362240
EX_o2_m        18.579253
EX_pi_m         2.942960
dtype: float64

By default this gives the solution with the smallest total import flux. We could also minimize the number of used import fluxes:

In [3]:
minimal_medium(com, 0.8, minimize_components=True)
Out[3]:
EX_glc__D_m     9.193567
EX_nh4_m        4.362240
EX_o2_m        20.192120
EX_pi_m         2.942960
dtype: float64

However, this will be unfeasibly slow and complicated for larger (ergo real) community models so we recommend using the default instead.

As argued before there are many unrealistic growth rate distributions that can be used for a given optimal community growth rate. It is also possible to use the results from cooperative tradeoff as additional constraints in the minimal media calculation.

In [4]:
sol = com.cooperative_tradeoff()
rates = sol.members.growth_rate.drop("medium")  # extracellular medium has no growth rate
med = minimal_medium(com, sol.growth_rate, min_growth=rates)
med
Out[4]:
EX_glc__D_m    10.000000
EX_nh4_m        4.765319
EX_o2_m        21.799493
EX_pi_m         3.214895
dtype: float64

In practice you might want to lower the required growth rates a bit to avoid the inclusion of particular imports just to push you the last few percent to the optimum. For instance to only require 95% of the community and individual growth rates:

In [5]:
med = minimal_medium(com, 0.95*sol.growth_rate, min_growth=0.95*rates)
med
Out[5]:
EX_glc__D_m    10.000000
EX_nh4_m        4.527053
EX_o2_m        19.895962
EX_pi_m         3.054150
dtype: float64

Export fluxes

Sometimes you will also be interested in which metabolites the community produces. This information can be obtained with the exports argument of the minimal_medium function which will also return the active exports (metabolites produced by the community) under minimal growth.

In [6]:
med = minimal_medium(com, sol.growth_rate, min_growth=rates, exports=True)
med
Out[6]:
EX_co2_m      -22.809833
EX_glc__D_m    10.000000
EX_h_m        -17.530865
EX_h2o_m      -29.175827
EX_nh4_m        4.765319
EX_o2_m        21.799493
EX_pi_m         3.214895
dtype: float64

By convention exports have a negative sign and imports a positive one.

Applying growth media

micom pretty much uses the cobrapy method of assigning media. Essentially you will need a dictionary-like structure that maps exchange reactions to their upper import flux bound. Fortunately, the output of minimal_medium can be used directly for that. So to calculate the minimal medium and use it as the actual growth medium afterwards we can do the following:

In [7]:
med = minimal_medium(com, 0.8, min_growth=0.8)
com.medium = med
com.optimize()
Out[7]:
community growth: 0.800
status: optimal
taxa:
abundance growth_rate reactions metabolites
compartments
Escherichia_coli_1 0.2 0.000000 95 72
Escherichia_coli_2 0.2 0.242410 95 72
Escherichia_coli_3 0.2 1.234669 95 72
Escherichia_coli_4 0.2 1.505863 95 72
Escherichia_coli_5 0.2 1.017058 95 72
medium NaN NaN 20 20

As we see the new medium has been applied and as a consequence the growth rate has been lowered to the one specified in the minimal medium calculation.