10. Growth media¶
The availability of nutrients has a major impact on metabolic fluxes and
cobrapy
provides some helpers to manage the exchanges between the
external environment and your metabolic model. In experimental settings
the “environment” is usually constituted by the growth medium, ergo the
concentrations of all metabolites and co-factors available to the
modeled organism. However, constraint-based metabolic models only
consider fluxes. Thus, you will first have to translate your
concentrations into fluxes. For instance by assuming that 1 gDW of your
organism cannot consume the entire concentration of a metabolite in 24h
which gives you an estimate of the upper exchange flux of
concentration / (1 gDW * 24 h)
. If you have direct measurement of
exchange fluxes you can of course use those as well (and those will be
much more accurate).
The current growth medium of a model is managed by the medium
attribute.
In [1]:
from cobra.test import create_test_model
model = create_test_model("textbook")
model.medium
Out[1]:
{'EX_co2_e': 1000.0,
'EX_glc__D_e': 10.0,
'EX_h2o_e': 1000.0,
'EX_h_e': 1000.0,
'EX_nh4_e': 1000.0,
'EX_o2_e': 1000.0,
'EX_pi_e': 1000.0}
This will return a dictionary that contains all active exchange fluxes
(the ones having non-zero flux bounds). Right now we see that we have
enabled aerobic growth. You can modify a growth medium of a model by
assigning a dictionary to model.medium
that maps exchange reactions
to their respective upper import bounds. For now let us enforce
anaerobic growth by shutting off the oxygen import.
In [2]:
medium = model.medium
medium["EX_o2_e"] = 0.0
model.medium = medium
model.medium
Out[2]:
{'EX_co2_e': 1000.0,
'EX_glc__D_e': 10.0,
'EX_h2o_e': 1000.0,
'EX_h_e': 1000.0,
'EX_nh4_e': 1000.0,
'EX_pi_e': 1000.0}
As we can see oxygen import is now removed from the list of active exchanges and we can verify that this also leads to a lower growth rate.
In [3]:
model.slim_optimize()
Out[3]:
0.21166294973530736
Setting the growth medium also connects to the context manager, so you can set a specific growth medium in a reversible manner.
In [4]:
model = create_test_model("textbook")
with model:
medium = model.medium
medium["EX_o2_e"] = 0.0
model.medium = medium
print(model.slim_optimize())
print(model.slim_optimize())
model.medium
0.21166294973530736
0.8739215069684102
Out[4]:
{'EX_co2_e': 1000.0,
'EX_glc__D_e': 10.0,
'EX_h2o_e': 1000.0,
'EX_h_e': 1000.0,
'EX_nh4_e': 1000.0,
'EX_o2_e': 1000.0,
'EX_pi_e': 1000.0}
So the medium change is only applied within the with
block and
reverted automatically.
10.1. Minimal media¶
In some cases you might be interested in the smallest growth medium that
can maintain a specific growth rate, the so called “minimal medium”. For
this we provide the function minimal_medium
which by default obtains
the medium with the lowest total import flux. This function needs two
arguments: the model and the minimum growth rate (or other objective)
the model has to achieve.
In [5]:
from cobra.medium import minimal_medium
max_growth = model.slim_optimize()
minimal_medium(model, max_growth)
Out[5]:
EX_glc__D_e 10.000000
EX_nh4_e 4.765319
EX_o2_e 21.799493
EX_pi_e 3.214895
dtype: float64
So we see that growth is actually limited by glucose import.
Alternatively you might be interested in a minimal medium with the
smallest number of active imports. This can be achieved by using the
minimize_components
argument (note that this uses a MIP formulation
and will therefore be much slower).
In [6]:
minimal_medium(model, 0.1, minimize_components=True)
Out[6]:
EX_glc__D_e 10.000000
EX_nh4_e 1.042503
EX_pi_e 0.703318
dtype: float64
When minimizing the number of import fluxes there may be many
alternative solutions. To obtain several of those you can also pass a
positive integer to minimize_components
which will give you at most
that many alternative solutions. Let us try that with our model and also
use the open_exchanges
argument which will assign a large upper
bound to all import reactions in the model. The return type will be a
pandas.DataFrame
.
In [7]:
minimal_medium(model, 0.8, minimize_components=8, open_exchanges=True)
Out[7]:
0 | 1 | 2 | 3 | 4 | 5 | |
---|---|---|---|---|---|---|
EX_fru_e | 0.000000 | 0.000000 | 523.104557 | 0.000000 | 0.000000 | 0.000000 |
EX_glc__D_e | 0.000000 | 0.000000 | 0.000000 | 523.104557 | 521.357767 | 519.750758 |
EX_gln__L_e | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 40.698058 | 0.000000 |
EX_glu__L_e | 23.468185 | 348.101944 | 83.995843 | 83.995843 | 0.000000 | 0.000000 |
EX_mal__L_e | 1000.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 |
EX_nh4_e | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 | 81.026921 |
EX_o2_e | 0.000000 | 500.000000 | 0.000000 | 0.000000 | 0.000000 | 0.000000 |
EX_pi_e | 15.667461 | 66.431529 | 56.667310 | 56.667310 | 54.913419 | 54.664344 |
So there are 4 alternative solutions in total. One aerobic and three anaerobic ones using different carbon sources.
10.2. Boundary reactions¶
Apart from exchange reactions there are other types of boundary
reactions such as demand or sink reactions. cobrapy
uses various
heuristics to identify those and they can be accessed by using the
appropriate attribute.
For exchange reactions:
In [8]:
ecoli = create_test_model("ecoli")
ecoli.exchanges[0:5]
Out[8]:
[<Reaction EX_12ppd__R_e at 0x7f3921088fd0>,
<Reaction EX_12ppd__S_e at 0x7f3921078fd0>,
<Reaction EX_14glucan_e at 0x7f3921078f98>,
<Reaction EX_15dap_e at 0x7f3921078eb8>,
<Reaction EX_23camp_e at 0x7f392107e2b0>]
For demand reactions:
In [9]:
ecoli.demands
Out[9]:
[<Reaction DM_4CRSOL at 0x7f3921144b70>,
<Reaction DM_5DRIB at 0x7f3921078b38>,
<Reaction DM_AACALD at 0x7f3921078be0>,
<Reaction DM_AMOB at 0x7f3921078c50>,
<Reaction DM_MTHTHF at 0x7f3921078cf8>,
<Reaction DM_OXAM at 0x7f3921078d68>]
For sink reactions:
In [10]:
ecoli.sinks
Out[10]:
[]
All boundary reactions (any reaction that consumes or introduces mass
into the system) can be obtained with the boundary
attribute:
In [11]:
ecoli.boundary[0:10]
Out[11]:
[<Reaction DM_4CRSOL at 0x7f3921144b70>,
<Reaction DM_5DRIB at 0x7f3921078b38>,
<Reaction DM_AACALD at 0x7f3921078be0>,
<Reaction DM_AMOB at 0x7f3921078c50>,
<Reaction DM_MTHTHF at 0x7f3921078cf8>,
<Reaction DM_OXAM at 0x7f3921078d68>,
<Reaction EX_12ppd__R_e at 0x7f3921088fd0>,
<Reaction EX_12ppd__S_e at 0x7f3921078fd0>,
<Reaction EX_14glucan_e at 0x7f3921078f98>,
<Reaction EX_15dap_e at 0x7f3921078eb8>]