Growth rates and fluxes¶
One of the major applications of micom is to identify growth rates and fluxes for a given community. We will return to our E. coli toy example.
In [1]:
from micom import Community, data
tax = data.test_taxonomy()
com = Community(tax, solver="gurobi")
100%|██████████| 5/5 [00:00<00:00, 5.79models/s]
FBA¶
If one is only interested in the community growth rate \(\mu_c\) we can use normal FBA to optimize this growth rate. By default micom assigns the community growth rate as the objective for a community model.
In [2]:
print(com.objective.expression)
com.optimize()
1.0*community_objective
Out[2]:
status: optimal
taxa:
abundance | growth_rate | reactions | metabolites | |
---|---|---|---|---|
compartments | ||||
Escherichia_coli_1 | 0.2 | 0.000000 | 95 | 72 |
Escherichia_coli_2 | 0.2 | 0.000000 | 95 | 72 |
Escherichia_coli_3 | 0.2 | 0.477843 | 95 | 72 |
Escherichia_coli_4 | 0.2 | 3.573952 | 95 | 72 |
Escherichia_coli_5 | 0.2 | 0.317813 | 95 | 72 |
medium | NaN | NaN | 20 | 20 |
optimize
returns a full-fledged solution object and you can inspect
several aspects of it. For instance to get individual growth rates and
information for the taxa:
In [3]:
sol = com.optimize()
sol.members
Out[3]:
abundance | growth_rate | reactions | metabolites | |
---|---|---|---|---|
compartments | ||||
Escherichia_coli_1 | 0.2 | 0.000000 | 95 | 72 |
Escherichia_coli_2 | 0.2 | 0.000000 | 95 | 72 |
Escherichia_coli_3 | 0.2 | 0.477843 | 95 | 72 |
Escherichia_coli_4 | 0.2 | 3.573952 | 95 | 72 |
Escherichia_coli_5 | 0.2 | 0.317813 | 95 | 72 |
medium | NaN | NaN | 20 | 20 |
By default micom does not return fluxes since that can be slow for
realistic large community models. If you want fluxes as well you can do
so by passing the fluxes
argument to optimize
. You can also
specifiy if you would like the fluxes to be obtained by parsimonious
FBA.
In [4]:
sol = com.optimize(fluxes=True, pfba=True)
sol.fluxes
Out[4]:
reaction | ACALD | ACALDt | ACKr | ACONTa | ACONTb | ACt2r | ADK1 | AKGDH | AKGt2r | ALCD2x | ... | RPI | SUCCt2_2 | SUCCt3 | SUCDi | SUCOAS | TALA | THD2 | TKT1 | TKT2 | TPI |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
compartment | |||||||||||||||||||||
Escherichia_coli_1 | 0.0 | 0.0 | 0.0 | 1.864444 | 1.864444 | 0.0 | 0.0 | 0.000000 | 0.0 | 0.0 | ... | 0.000000 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.000000 | 0.000000 | 1.864444 |
Escherichia_coli_2 | 0.0 | 0.0 | 0.0 | 1.864444 | 1.864444 | 0.0 | 0.0 | 0.000000 | 0.0 | 0.0 | ... | 0.000000 | 0.0 | 0.0 | 0.000000 | 0.000000 | 0.000000 | 0.0 | 0.000000 | 0.000000 | 1.864444 |
Escherichia_coli_3 | 0.0 | 0.0 | 0.0 | 3.243922 | 3.243922 | 0.0 | 0.0 | 4.097684 | 0.0 | 0.0 | ... | -1.026049 | 0.0 | 0.0 | 4.097684 | -4.097684 | 0.597089 | 0.0 | 0.597089 | 0.424588 | 3.494184 |
Escherichia_coli_4 | 0.0 | 0.0 | 0.0 | 20.166971 | 20.166971 | 0.0 | 0.0 | 18.670618 | 0.0 | 0.0 | ... | -9.670409 | 0.0 | 0.0 | 18.670618 | -18.670618 | 6.462073 | 0.0 | 6.462073 | 5.171876 | 27.029342 |
Escherichia_coli_5 | 0.0 | 0.0 | 0.0 | 2.896466 | 2.896466 | 0.0 | 0.0 | 2.553577 | 0.0 | 0.0 | ... | -0.711058 | 0.0 | 0.0 | 2.553577 | -2.553577 | 0.425757 | 0.0 | 0.425757 | 0.311026 | 3.134495 |
medium | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
6 rows × 115 columns
By defaults fluxes are stratified by taxa and the external medium to aid further analysis.
Returning to the growth rates we can see the major problem with regular FBA for community levels. Usually it will maximize growth for only a few taxa in the model yielding unrealistically high growth rates. However, in our setup we have 5 identical E. coli strains and we would expect all of the taxa to grow with the same rate (see Methods section).
Cooperative tradeoff¶
Cooperative tradeoff is a two step methods that allows you to get a unique solution for the the individuals growth rates that favors individual growth but still allows for a sup-optimal community growth rate. For that we always have to decide on a fraction of the maximum community growth rate we want to enforce. Our own results based on a data set of 189 gut microbiomes suggest that this tradeoff has tobe substantially lower than the optimal community growth rate to yield realistic growth rates (<=50% optimum). For our E. coli model we can start with getting the best solution while still maintaining optimal community growth (100% of maximum).
Cooperative tradeoff requires a QP-capable solver such as cplex or gurobi (both have academic licenses available)!
In [10]:
sol = com.cooperative_tradeoff(fraction=1.0)
sol
Out[10]:
status: optimal
taxa:
abundance | growth_rate | reactions | metabolites | |
---|---|---|---|---|
compartments | ||||
Escherichia_coli_1 | 0.2 | 0.873922 | 95 | 72 |
Escherichia_coli_2 | 0.2 | 0.873922 | 95 | 72 |
Escherichia_coli_3 | 0.2 | 0.873922 | 95 | 72 |
Escherichia_coli_4 | 0.2 | 0.873922 | 95 | 72 |
Escherichia_coli_5 | 0.2 | 0.873922 | 95 | 72 |
medium | NaN | NaN | 20 | 20 |
As we see all taxa now grow at the same rate as would be expected. If we
want fluxes as well we can again request those using the fluxes
and
pfba
arguments.
In [6]:
sol = com.cooperative_tradeoff(fluxes=True, pfba=True)
sol.fluxes
Out[6]:
reaction | ACALD | ACALDt | ACKr | ACONTa | ACONTb | ACt2r | ADK1 | AKGDH | AKGt2r | ALCD2x | ... | RPI | SUCCt2_2 | SUCCt3 | SUCDi | SUCOAS | TALA | THD2 | TKT1 | TKT2 | TPI |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
compartment | |||||||||||||||||||||
Escherichia_coli_1 | 0.0 | 0.0 | 0.0 | 6.00725 | 6.00725 | 0.0 | 0.0 | 5.064376 | 0.0 | 0.0 | ... | -2.281503 | 0.0 | 0.0 | 5.064376 | -5.064376 | 1.496984 | 0.0 | 1.496984 | 1.181498 | 7.477382 |
Escherichia_coli_2 | 0.0 | 0.0 | 0.0 | 6.00725 | 6.00725 | 0.0 | 0.0 | 5.064376 | 0.0 | 0.0 | ... | -2.281503 | 0.0 | 0.0 | 5.064376 | -5.064376 | 1.496984 | 0.0 | 1.496984 | 1.181498 | 7.477382 |
Escherichia_coli_3 | 0.0 | 0.0 | 0.0 | 6.00725 | 6.00725 | 0.0 | 0.0 | 5.064376 | 0.0 | 0.0 | ... | -2.281503 | 0.0 | 0.0 | 5.064376 | -5.064376 | 1.496984 | 0.0 | 1.496984 | 1.181498 | 7.477382 |
Escherichia_coli_4 | 0.0 | 0.0 | 0.0 | 6.00725 | 6.00725 | 0.0 | 0.0 | 5.064376 | 0.0 | 0.0 | ... | -2.281503 | 0.0 | 0.0 | 5.064376 | -5.064376 | 1.496984 | 0.0 | 1.496984 | 1.181498 | 7.477382 |
Escherichia_coli_5 | 0.0 | 0.0 | 0.0 | 6.00725 | 6.00725 | 0.0 | 0.0 | 5.064376 | 0.0 | 0.0 | ... | -2.281503 | 0.0 | 0.0 | 5.064376 | -5.064376 | 1.496984 | 0.0 | 1.496984 | 1.181498 | 7.477382 |
medium | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
6 rows × 115 columns
Also if you have prior information about the growth rates you can also enforce a minimum individual growth rate for the taxa.
In [7]:
sol1 = com.cooperative_tradeoff(min_growth=0.1) # single value
sol2 = com.cooperative_tradeoff(min_growth=[0.1, 0.2, 0.3, 0.4, 0.5]) # one value for each taxa
print(sol1, sol2)
<CommunitySolution 0.874 at 0x7f58ed03fc50> <CommunitySolution 0.874 at 0x7f58ed03fe80>
Finally, you might want to see the impact of the tradeoff parameter on
your solution. For this you can simply pass in an array-like type as the
fraction
parameter.
In [8]:
import numpy as np
sols = com.cooperative_tradeoff(fraction=np.arange(0.1, 1.01, 0.1))
sols
Out[8]:
tradeoff | solution | |
---|---|---|
0 | 1.0 | <CommunitySolution 0.874 at 0x7f58ed03f470> |
1 | 0.9 | <CommunitySolution 0.787 at 0x7f58ed03f2b0> |
2 | 0.8 | <CommunitySolution 0.699 at 0x7f58ed036080> |
3 | 0.7 | <CommunitySolution 0.612 at 0x7f58ed3f2240> |
4 | 0.6 | <CommunitySolution 0.524 at 0x7f58ed03f550> |
5 | 0.5 | <CommunitySolution 0.437 at 0x7f58ed03f320> |
6 | 0.4 | <CommunitySolution 0.350 at 0x7f58ed088630> |
7 | 0.3 | <CommunitySolution 0.262 at 0x7f58ed5a3cf8> |
8 | 0.2 | <CommunitySolution 0.175 at 0x7f58ed5d7780> |
9 | 0.1 | <CommunitySolution 0.087 at 0x7f58ed5d7b38> |
The solutions can than be inspected by the usual pandas methods. See the pandas documentation for more infos.
In [9]:
rates = sols.solution.apply(lambda x: x.members.growth_rate)
rates
Out[9]:
compartments | Escherichia_coli_1 | Escherichia_coli_2 | Escherichia_coli_3 | Escherichia_coli_4 | Escherichia_coli_5 | medium |
---|---|---|---|---|---|---|
0 | 0.873922 | 0.873922 | 0.873922 | 0.873922 | 0.873922 | NaN |
1 | 0.786529 | 0.786529 | 0.786529 | 0.786529 | 0.786529 | NaN |
2 | 0.699137 | 0.699137 | 0.699137 | 0.699137 | 0.699137 | NaN |
3 | 0.611745 | 0.611745 | 0.611745 | 0.611745 | 0.611745 | NaN |
4 | 0.524353 | 0.524353 | 0.524353 | 0.524353 | 0.524353 | NaN |
5 | 0.436961 | 0.436961 | 0.436961 | 0.436961 | 0.436961 | NaN |
6 | 0.349569 | 0.349569 | 0.349569 | 0.349569 | 0.349569 | NaN |
7 | 0.262176 | 0.262176 | 0.262176 | 0.262176 | 0.262176 | NaN |
8 | 0.174784 | 0.174784 | 0.174784 | 0.174784 | 0.174784 | NaN |
9 | 0.087392 | 0.087392 | 0.087392 | 0.087392 | 0.087392 | NaN |