Flux balance, flux variability, and parsimonious FBA
Flux balance analysis of a metabolic network, which sets its fluxes to maximise growth.
- Name:
flux_balance - Field:
biology/systems_biology - Formalism: static solution
- References: Raman 2021; Orth et al. 2010
Select this system
from skcomplex.systems import create_simulation, create_system, describe
system = create_system('flux_balance')
entry = describe('flux_balance')
trajectory = create_simulation('flux_balance').prepare().run().trajectory_
Factory
@register_system(
field='biology/systems_biology',
tags=('flux balance', 'linear program', 'metabolism', 'static'),
references=('Raman 2021', 'Orth et al. 2010'),
defaults={'until': 0.0},
)
def flux_balance(
network: str = 'toy',
*,
oxygen: float = 1000.0,
parsimonious: bool = False,
) -> System:
"""Return flux balance analysis of a metabolic network, which sets its fluxes to maximise growth.
The steady-state balances of the metabolites and the bounds of the reactions confine the fluxes, and the optimum of
the growth flux sets them (Raman 2021, Section 8.6). The toy network of Table 8.2 reaches growth 50, set by the
bound 1000 on `v6`. The E. coli core system needs the extra `metabolism`, and grows at 0.8739 h^-1 on glucose with
oxygen and at 0.2117 h^-1 without.
Args:
network:
`'toy'` for Raman's toy network or `'ecoli'` for the E. coli core system.
oxygen:
The largest oxygen uptake of the E. coli core system.
parsimonious:
Whether to minimise the total absolute flux after growth.
Returns:
system:
The system.
Raises:
ValidationError:
The network is unknown.
MissingExtraError:
The E. coli core system needs the extra, which is not installed.
Examples:
>>> from skcomplex.core.engine.runtime import Simulation
>>> from skcomplex.systems.biology.systems_biology import flux_balance
>>> trajectory = Simulation(flux_balance()).prepare().run(0.0).trajectory_
>>> round(float(trajectory.values('cell.v_vbio')[0]), 6)
50.0
"""
if network not in NETWORKS:
error_msg = f'Unknown network {network!r}. Use one of {", ".join(NETWORKS)}.'
raise ValidationError(error_msg)
if network == 'toy':
return System(elements=[ToyNetworkElement('cell', parsimonious=parsimonious)], time=StaticTime())
element = load_network('textbook', 'cell', needed_by='flux_balance')
element.parsimonious = parsimonious
identifier = f'lower_{element._identifier(OXYGEN_EXCHANGE)}'
element.set_params(**{identifier: -float(oxygen)})
return System(elements=[element], time=StaticTime())
Components
Elements:
ToyNetworkElement, fromDeclaredElement
class ToyNetworkElement(MetabolicNetworkElement):
"""The toy network of Table 8.2 of Raman (2021), which grows on A alone.
Args:
label:
The label of the element.
visual:
How the element is drawn, or `None` for the bars of its program.
objective:
The coefficient of every reaction in the objective, or `None` for `default_objective`.
parsimonious:
Whether to minimise the total absolute flux after the objective.
infeasible:
The infeasibility policy of the program.
name:
The name of the network.
reactions:
The reactions by name.
default_objective:
The objective of the network when `objective` is `None`.
variables:
The declared states and parameters that replace the ones of the reactions, by name, or `None` for none.
Examples:
>>> from skcomplex.systems.biology.common.metabolism import ToyNetworkElement
>>> ToyNetworkElement('cell').get_value('upper_v1')
1000.0
"""
def __init__(
self,
label: str,
visual: VisualSpec | None = None,
*,
objective: Mapping[str, float] | None = None,
parsimonious: bool = False,
infeasible: str = 'raise',
name: str | None = 'ToyNetwork',
reactions: Mapping[str, ReactionSpec] = TOY_REACTIONS,
default_objective: Mapping[str, float] = TOY_OBJECTIVE,
variables: Mapping[str, DeclaredVariableSpec] | None = None,
) -> None:
super().__init__(
label,
visual,
objective=objective,
parsimonious=parsimonious,
infeasible=infeasible,
name=name,
reactions=reactions,
default_objective=default_objective,
variables=variables,
)