Skip to content

Metabolism

Metabolism shared by the biology packages: metabolic networks, their standard formats, and their analyses.

BaseNetworkAnalysis(*, network=None)

Bases: BaseAnalysis

Base of the analyses of a system that holds a metabolic network.

Parameters:

Name Type Description Default
network str | None

The label of the network, or None for the first network of the system.

None

Attributes:

Name Type Description
network_

The metabolic network.

Source code in src/skcomplex/systems/biology/common/metabolism/_analyses.py
47
48
def __init__(self, *, network: str | None = None) -> None:
    self.network = network

BiomassElement(label, visual=None, *, x=0.01)

Bases: Element

Biomass of a culture.

Parameters:

Name Type Description Default
label str

The label of the element.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
x Annotated[float, StateSpec()]

The biomass in gDW per L.

0.01

Examples:

>>> from skcomplex.systems.biology.common.metabolism import BiomassElement
>>> BiomassElement('culture', x=0.01).x
0.01
Source code in src/skcomplex/systems/biology/common/metabolism/_culture.py
42
43
44
45
46
47
48
49
50
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    x: Annotated[float, StateSpec()] = 0.01,
) -> None:
    super().__init__(label, visual=visual)
    self.x = x

CobraAnalysis(kind='variability', *, fraction=1.0, target='gene', order=1, knockouts=(), linear=False, network=None)

Bases: BaseNetworkAnalysis

Analysis of a metabolic network with COBRApy, which needs the extra metabolism.

  • 'variability': the range of every flux at a fraction of the optimum.
  • 'parsimonious': the fluxes of the smallest total flux at the optimum.
  • 'deletions': the growth after single or double deletions of genes or reactions.
  • 'moma' and 'room': the fluxes of a knock-out adjusted against the wild-type solution.
  • 'synthetic-lethals': the pairs of genes or reactions lethal together, but not alone.

Parameters:

Name Type Description Default
kind str

The analysis, one of the kinds above.

'variability'
fraction float

The fraction of the optimum for 'variability'.

1.0
target str

'gene' or 'reaction', what 'deletions' and 'synthetic-lethals' delete.

'gene'
order int

1 or 2, the size of the deletions.

1
knockouts Sequence[str]

The genes to knock out for 'moma' and 'room'.

()
linear bool

Whether to solve MoMA and ROOM in their linear forms, rather than the quadratic form of MoMA and the mixed-integer form of ROOM, with delta = 0.03 and epsilon = 0.001 (Raman 2021, Eqs. 9.1 and 9.5).

False
network str | None

The label of the network, or None for the first network of the system.

None

Attributes:

Name Type Description
system_

The cobra.Model of the network.

ranges_

The columns minimum and maximum of every reaction, for 'variability'.

fluxes_

The flux of every reaction, for 'parsimonious', 'moma', and 'room'.

total_

The total absolute flux, for 'parsimonious'.

growth_

The growth of every deletion, by the name of the gene or reaction or by a pair of names, for 'deletions', and the adjusted growth for 'moma' and 'room'.

pairs_

The lethal pairs, for 'synthetic-lethals'.

Raises:

Type Description
AnalysisError

The kind is unknown, raised by prepare.

MissingExtraError

The extra is not installed, raised by prepare.

Examples:

>>> from skcomplex.core.components.spaces import StaticTime
>>> from skcomplex.core.components.system import System
>>> from skcomplex.systems.biology.common.metabolism import CobraAnalysis, load_network
>>> system = System(elements=[load_network('textbook', 'cell')], time=StaticTime())
>>> analysis = CobraAnalysis('parsimonious').prepare(system).run()
>>> round(float(analysis.total_), 3)
518.422
Source code in src/skcomplex/systems/biology/common/metabolism/_analyses.py
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
def __init__(
    self,
    kind: str = 'variability',
    *,
    fraction: float = 1.0,
    target: str = 'gene',
    order: int = 1,
    knockouts: Sequence[str] = (),
    linear: bool = False,
    network: str | None = None,
) -> None:
    super().__init__(network=network)
    self.kind = kind
    self.fraction = fraction
    self.target = target
    self.order = order
    self.knockouts = knockouts
    self.linear = linear

CommunityAnalysis(kind='steadycom', *, fraction=1.0, abundances=None, medium=None)

Bases: BaseNetworkAnalysis

Analysis of a community of metabolic networks that share a medium.

  • 'steadycom': the largest common growth rate of the members, after Chan et al. (2017), by a bisection on the rate with the solve of the core, without the extra. The fluxes of a member scale with its abundance, the abundances sum to at most 1, and a shared exchange of the medium stays above the bound that medium gives.
  • 'tradeoff': the cooperative trade-off of MICOM, which needs the extra metabolism.

Parameters:

Name Type Description Default
kind str

The analysis, one of the kinds above.

'steadycom'
fraction float

The fraction of the community growth rate that the trade-off keeps.

1.0
abundances Sequence[float] | None

The abundance of every member for 'tradeoff', or None for equal ones.

None
medium Mapping[str, float] | None

The lower bound of every shared exchange of the whole community for 'steadycom', by reaction, or None for no shared bound.

None

Attributes:

Name Type Description
growth_

The common growth rate, or the community growth rate of the trade-off.

abundances_

The abundance of every member, by its label, for 'steadycom'.

members_

The growth of every member, by its label, for 'tradeoff'.

Raises:

Type Description
AnalysisError

The kind is unknown, raised by prepare.

MissingExtraError

The kind 'tradeoff' needs the extra, raised by prepare.

Examples:

>>> from skcomplex.core.components.spaces import StaticTime
>>> from skcomplex.core.components.system import System
>>> from skcomplex.systems.biology.common.metabolism import (
...     CommunityAnalysis,
...     ReactionSpec,
...     metabolic_network_type,
... )
>>> reactions = {
...     'EX_a': ReactionSpec({'a': 1.0}, upper=2.0),
...     'grow': ReactionSpec({'a': -1.0}),
... }
>>> element_type = metabolic_network_type('MemberElement', reactions, {'grow': 1.0})
>>> system = System(elements=[element_type('one'), element_type('two')], time=StaticTime())
>>> analysis = CommunityAnalysis().prepare(system).run()
>>> round(analysis.growth_, 6), round(sum(analysis.abundances_.values()), 6)
(2.0, 1.0)
Source code in src/skcomplex/systems/biology/common/metabolism/_community.py
119
120
121
122
123
124
125
126
127
128
129
130
131
def __init__(
    self,
    kind: str = 'steadycom',
    *,
    fraction: float = 1.0,
    abundances: Sequence[float] | None = None,
    medium: Mapping[str, float] | None = None,
) -> None:
    super().__init__()
    self.kind = kind
    self.fraction = fraction
    self.abundances = abundances
    self.medium = medium

CommunityInteraction(label, *, members, medium, abundances=(), exchanges=None, growth='Biomass_Ecoli_core', common_rate=False)

Bases: Interaction

Joint program of a community: the medium balances the exchanges, and its law holds the objective of growth.

Parameters:

Name Type Description Default
label str

The label of the interaction.

required
members Annotated[list[str], RoleSpec(variadic=True)]

The paths of the metabolic networks.

required
medium Annotated[str, RoleSpec()]

The path of the shared medium.

required
abundances Sequence[float]

The abundance of every member, which weighs its exchanges and its growth.

()
exchanges Mapping[str, float] | None

The lower bound of the net exchange of the community, by reaction.

None
growth str

The name of the reaction of growth of every member.

'Biomass_Ecoli_core'
common_rate bool

Whether every member grows at one specific rate, the balanced growth of community FBA (Raman 2021, Section 11.1.3.2), rather than each at its own, as in joint FBA.

False

Examples:

>>> from skcomplex.systems.biology.common.metabolism import CommunityInteraction
>>> CommunityInteraction('joint', members=['a', 'b'], medium='medium', abundances=(0.5, 0.5)).abundances
(0.5, 0.5)
Source code in src/skcomplex/systems/biology/common/metabolism/_culture.py
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
def __init__(
    self,
    label: str,
    *,
    members: Annotated[list[str], RoleSpec(variadic=True)],
    medium: Annotated[str, RoleSpec()],
    abundances: Sequence[float] = (),
    exchanges: Mapping[str, float] | None = None,
    growth: str = 'Biomass_Ecoli_core',
    common_rate: bool = False,
) -> None:
    super().__init__(label)
    self.members = members
    self.medium = medium
    self.abundances = abundances
    self.exchanges = exchanges
    self.growth = growth
    self.common_rate = common_rate

CommunityMediumElement(label, visual=None, *, exchanges=(), variables=None)

Bases: DeclaredElement

Medium that a community shares, with one algebraic state per shared exchange.

The element declares the state u_<reaction> of the net exchange of every reaction.

Parameters:

Name Type Description Default
label str

The label of the element.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
exchanges Sequence[str]

The names of the reactions.

()
variables Mapping[str, DeclaredVariableSpec] | None

The declared states that replace the states of the net exchanges, by name, or None for none.

None

Examples:

>>> from skcomplex.systems.biology.common.metabolism import CommunityMediumElement
>>> CommunityMediumElement.state_name('EX_glc__D_e')
'u_EX_glc__D_e'
Source code in src/skcomplex/systems/biology/common/metabolism/_culture.py
245
246
247
248
249
250
251
252
253
254
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    exchanges: Sequence[str] = (),
    variables: Mapping[str, DeclaredVariableSpec] | None = None,
) -> None:
    super().__init__(label, visual=visual, variables=variables)
    self.exchanges = exchanges

state_name(reaction) staticmethod

Return the name of the state of the net exchange of a reaction.

Parameters:

Name Type Description Default
reaction str

The name of the reaction.

required

Returns:

Name Type Description
name str

The name of the state.

Source code in src/skcomplex/systems/biology/common/metabolism/_culture.py
264
265
266
267
268
269
270
271
272
273
274
275
276
@staticmethod
def state_name(reaction: str) -> str:
    """Return the name of the state of the net exchange of a reaction.

    Args:
        reaction:
            The name of the reaction.

    Returns:
        name:
            The name of the state.
    """
    return f'u_{MetabolicNetworkElement._identifier(reaction)}'

ExchangeInteraction(label, *, cell='cell', biomass='biomass', substrate='substrate', reaction='EX_glc__D_e', vmax=10.0, km=0.015, interval=None, threshold=None)

Bases: Interaction

Exchange of a metabolite between a metabolic network and its medium, bounded by Michaelis-Menten uptake.

The law bounds the uptake, the negative flux of the exchange reaction, by vmax c / (km + c) and, with an interval, by what the medium holds per biomass over the interval (Raman 2021, Section 9.6). The medium changes at the rate dc/dt = v x, and a depleted medium loses nothing more.

Parameters:

Name Type Description Default
label str

The label of the interaction.

required
cell Annotated[str, RoleSpec()]

The path of the metabolic network.

'cell'
biomass Annotated[str, RoleSpec()]

The path of the biomass.

'biomass'
substrate Annotated[str, RoleSpec()]

The path of the metabolite.

'substrate'
reaction str

The name of the exchange reaction.

'EX_glc__D_e'
vmax Annotated[float, ParameterSpec(domain=POSITIVE)]

The largest uptake.

10.0
km Annotated[float, ParameterSpec(domain=POSITIVE)]

The half-saturation concentration.

0.015
interval float | None

The time over which the medium must last, or None for no such bound.

None
threshold float | None

The biomass above which the program solves, or None for always.

None

Examples:

>>> from skcomplex.systems.biology.common.metabolism import ExchangeInteraction
>>> ExchangeInteraction('uptake', reaction='EX_glc__D_e').vmax
10.0
Source code in src/skcomplex/systems/biology/common/metabolism/_culture.py
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
def __init__(
    self,
    label: str,
    *,
    cell: Annotated[str, RoleSpec()] = 'cell',
    biomass: Annotated[str, RoleSpec()] = 'biomass',
    substrate: Annotated[str, RoleSpec()] = 'substrate',
    reaction: str = 'EX_glc__D_e',
    vmax: Annotated[float, ParameterSpec(domain=POSITIVE)] = 10.0,
    km: Annotated[float, ParameterSpec(domain=POSITIVE)] = 0.015,
    interval: float | None = None,
    threshold: float | None = None,
) -> None:
    super().__init__(label)
    self.cell = cell
    self.biomass = biomass
    self.substrate = substrate
    self.reaction = reaction
    self.vmax = vmax
    self.km = km
    self.interval = interval
    self.threshold = threshold

FluxVariabilityAnalysis(fraction=1.0, *, network=None)

Bases: BaseNetworkAnalysis

Range of every flux at an optimum, from the solve of the core, which runs without the extra.

Every flux is maximised and minimised with the objective kept at a fraction of its optimum, c' v >= f (Raman 2021, Eq. 8.11d). A network of a genome's size is faster with CobraAnalysis(kind='variability').

Parameters:

Name Type Description Default
fraction float

The fraction of the optimum to keep.

1.0
network str | None

The label of the network, or None for the first network of the system.

None

Attributes:

Name Type Description
optimum_

The optimum of the objective.

ranges_

The columns minimum and maximum of every reaction.

Examples:

>>> from skcomplex.core.components.spaces import StaticTime
>>> from skcomplex.core.components.system import System
>>> from skcomplex.systems.biology.common.metabolism import (
...     FluxVariabilityAnalysis,
...     ReactionSpec,
...     metabolic_network_type,
... )
>>> reactions = {
...     'in': ReactionSpec({'A': 1.0}, upper=4.0),
...     'one': ReactionSpec({'A': -1.0}),
...     'two': ReactionSpec({'A': -1.0}),
... }
>>> network = metabolic_network_type('TwoWaysElement', reactions, {'in': 1.0})('net')
>>> system = System(elements=[network], time=StaticTime())
>>> FluxVariabilityAnalysis().prepare(system).run().ranges_.loc['one'].tolist()
[0.0, 4.0]
Source code in src/skcomplex/systems/biology/common/metabolism/_analyses.py
193
194
195
def __init__(self, fraction: float = 1.0, *, network: str | None = None) -> None:
    super().__init__(network=network)
    self.fraction = fraction

GrowthInteraction(label, *, cell='cell', biomass='biomass', reaction='Biomass_Ecoli_core')

Bases: Interaction

Growth of biomass at the rate that a reaction of a metabolic network gives, dx/dt = v x.

Parameters:

Name Type Description Default
label str

The label of the interaction.

required
cell Annotated[str, RoleSpec()]

The path of the metabolic network.

'cell'
biomass Annotated[str, RoleSpec()]

The path of the biomass.

'biomass'
reaction str

The name of the reaction of growth.

'Biomass_Ecoli_core'

Examples:

>>> from skcomplex.systems.biology.common.metabolism import GrowthInteraction
>>> GrowthInteraction('growth', cell='cell', biomass='culture', reaction='grow').reaction
'grow'
Source code in src/skcomplex/systems/biology/common/metabolism/_culture.py
105
106
107
108
109
110
111
112
113
114
115
116
def __init__(
    self,
    label: str,
    *,
    cell: Annotated[str, RoleSpec()] = 'cell',
    biomass: Annotated[str, RoleSpec()] = 'biomass',
    reaction: str = 'Biomass_Ecoli_core',
) -> None:
    super().__init__(label)
    self.cell = cell
    self.biomass = biomass
    self.reaction = reaction

MetabolicNetworkElement(label, visual=None, *, objective=None, parsimonious=False, infeasible='raise', name=None, reactions=NO_REACTIONS, default_objective=NO_OBJECTIVE, variables=None)

Bases: DeclaredElement

Metabolic network whose fluxes one linear program sets, with a balance per metabolite.

The element declares one algebraic state v_<reaction> per reaction, one adaptive switch g_<gene> per gene, and the parameters lower_<reaction> and upper_<reaction> of its bounds. The rule of a reaction gates both bounds, so a reaction whose rule is false carries no flux.

Parameters:

Name Type Description Default
label str

The label of the element.

required
visual VisualSpec | None

How the element is drawn, or None for the bars of its program.

None
objective Mapping[str, float] | None

The coefficient of every reaction in the objective, or None for default_objective, or nothing for a network whose objective another law holds.

None
parsimonious bool

Whether to minimise the total absolute flux after the objective.

False
infeasible str

The infeasibility policy of the program.

'raise'
name str | None

The name of the network, or None for none.

None
reactions Mapping[str, ReactionSpec]

The reactions by name.

NO_REACTIONS
default_objective Mapping[str, float]

The objective of the network when objective is None.

NO_OBJECTIVE
variables Mapping[str, DeclaredVariableSpec] | None

The declared states and parameters that replace the ones of the reactions, by name, or None for none.

None

Examples:

>>> from skcomplex.systems.biology.common.metabolism import ReactionSpec, metabolic_network_type
>>> reactions = {'uptake': ReactionSpec({'A': 1.0}), 'use': ReactionSpec({'A': -1.0}, upper=4.0)}
>>> network = metabolic_network_type('TwoSteps', reactions, {'use': 1.0})('cell')
>>> network.get_value('upper_use')
4.0
Source code in src/skcomplex/systems/biology/common/metabolism/_metabolic_network.py
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    objective: Mapping[str, float] | None = None,
    parsimonious: bool = False,
    infeasible: str = 'raise',
    name: str | None = None,
    reactions: Mapping[str, ReactionSpec] = NO_REACTIONS,
    default_objective: Mapping[str, float] = NO_OBJECTIVE,
    variables: Mapping[str, DeclaredVariableSpec] | None = None,
) -> None:
    super().__init__(label, visual=visual, variables=variables)
    self.objective = objective
    self.parsimonious = parsimonious
    self.infeasible = infeasible
    self.name = name
    self.reactions = reactions
    self.default_objective = default_objective

flux_name(reaction) classmethod

Return the name of the state of the flux of a reaction.

Parameters:

Name Type Description Default
reaction str

The name of the reaction.

required

Returns:

Name Type Description
name str

The name of the state.

Source code in src/skcomplex/systems/biology/common/metabolism/_metabolic_network.py
129
130
131
132
133
134
135
136
137
138
139
140
141
@classmethod
def flux_name(cls, reaction: str) -> str:
    """Return the name of the state of the flux of a reaction.

    Args:
        reaction:
            The name of the reaction.

    Returns:
        name:
            The name of the state.
    """
    return f'v_{cls._identifier(reaction)}'

gene_name(gene) classmethod

Return the name of the switch of a gene.

Parameters:

Name Type Description Default
gene str

The name of the gene.

required

Returns:

Name Type Description
name str

The name of the switch.

Source code in src/skcomplex/systems/biology/common/metabolism/_metabolic_network.py
143
144
145
146
147
148
149
150
151
152
153
154
155
@classmethod
def gene_name(cls, gene: str) -> str:
    """Return the name of the switch of a gene.

    Args:
        gene:
            The name of the gene.

    Returns:
        name:
            The name of the switch.
    """
    return f'g_{cls._identifier(gene)}'

genes_of()

Return the names of the genes that the rules of the reactions read.

Returns:

Name Type Description
genes tuple[str, ...]

The names, in the order the rules name them.

Source code in src/skcomplex/systems/biology/common/metabolism/_metabolic_network.py
157
158
159
160
161
162
163
164
165
def genes_of(self) -> tuple[str, ...]:
    """Return the names of the genes that the rules of the reactions read.

    Returns:
        genes:
            The names, in the order the rules name them.
    """
    names = [name for reaction in self.reactions.values() for name in _rule_genes(reaction.rule)]
    return tuple(dict.fromkeys(names))

get_number(name)

Return the value of a state or parameter of the network as a number.

Parameters:

Name Type Description Default
name str

The name of the variable, such as upper_<reaction>.

required

Returns:

Name Type Description
number float

The value.

Source code in src/skcomplex/systems/biology/common/metabolism/_metabolic_network.py
167
168
169
170
171
172
173
174
175
176
177
178
def get_number(self, name: str) -> float:
    """Return the value of a state or parameter of the network as a number.

    Args:
        name:
            The name of the variable, such as `upper_<reaction>`.

    Returns:
        number:
            The value.
    """
    return float(cast(float, self.get_value(name)))

ObjectiveFloorInteraction(label, *, cell='cell', weights=None, floor=0.0)

Bases: Interaction

Lower bound of the objective of a metabolic network as a whole, c' v >= f (Raman 2021, Eq. 8.11d).

Parameters:

Name Type Description Default
label str

The label of the interaction.

required
cell Annotated[str, RoleSpec()]

The path of the metabolic network.

'cell'
weights Mapping[str, float] | None

The coefficient of every reaction in the objective.

None
floor float

The value the objective keeps.

0.0

Examples:

>>> from skcomplex.systems.biology.common.metabolism import ObjectiveFloorInteraction
>>> ObjectiveFloorInteraction('kept', weights={'grow': 1.0}, floor=0.5).floor
0.5
Source code in src/skcomplex/systems/biology/common/metabolism/_culture.py
410
411
412
413
414
415
416
417
418
419
420
421
def __init__(
    self,
    label: str,
    *,
    cell: Annotated[str, RoleSpec()] = 'cell',
    weights: Mapping[str, float] | None = None,
    floor: float = 0.0,
) -> None:
    super().__init__(label)
    self.cell = cell
    self.weights = weights
    self.floor = floor

ProductionScanAnalysis(target='', *, steps=10, network=None)

Bases: BaseNetworkAnalysis

Scan of fluxes with enforced objective flux (FSEOF), from the solve of the core, which runs without the extra.

The target flux is enforced at increasing levels from its value at the optimum to its maximum, and every level maximises the objective, with the total absolute flux minimised after it. The analysis reports the reactions whose absolute flux rises with every level.

Parameters:

Name Type Description Default
target str

The reaction whose flux the scan enforces.

''
steps int

The number of levels.

10
network str | None

The label of the network, or None for the first network of the system.

None

Attributes:

Name Type Description
levels_

The enforced flux of every level.

objectives_

The optimum of the objective at every level.

fluxes_

The fluxes by reaction, one row per reaction and one column per level.

reactions_

The reactions whose absolute flux rises with every level.

Examples:

>>> from skcomplex.core.components.spaces import StaticTime
>>> from skcomplex.core.components.system import System
>>> from skcomplex.systems.biology.common.metabolism import (
...     ProductionScanAnalysis,
...     ReactionSpec,
...     metabolic_network_type,
... )
>>> reactions = {
...     'in': ReactionSpec({'A': 1.0}, upper=4.0),
...     'grow': ReactionSpec({'A': -1.0}),
...     'make': ReactionSpec({'A': -1.0, 'P': 1.0}),
...     'out': ReactionSpec({'P': -1.0}),
... }
>>> network = metabolic_network_type('ScanElement', reactions, {'grow': 1.0})('net')
>>> system = System(elements=[network], time=StaticTime())
>>> ProductionScanAnalysis('out', steps=2).prepare(system).run().reactions_
['make', 'out']
Source code in src/skcomplex/systems/biology/common/metabolism/_analyses.py
265
266
267
268
def __init__(self, target: str = '', *, steps: int = 10, network: str | None = None) -> None:
    super().__init__(network=network)
    self.target = target
    self.steps = steps

ReactionSpec(coefficients, lower=0.0, upper=DEFAULT_BOUND, rule='') dataclass

Bases: BaseSpec

Reaction of a metabolic network: its stoichiometry, its bounds, and the genes that gate them.

Parameters:

Name Type Description Default
coefficients Mapping[str, float]

The stoichiometric coefficient of every metabolite, negative for a reactant.

required
lower float

The lower bound of the flux.

0.0
upper float

The upper bound of the flux.

DEFAULT_BOUND
rule str

The gene rule, a Boolean expression of gene names with and, or, and parentheses, or the empty string for a reaction without genes.

''

Raises:

Type Description
ValidationError

The lower bound is above the upper bound, raised by prepare.

Examples:

>>> from skcomplex.systems.biology.common.metabolism import ReactionSpec
>>> ReactionSpec({'A': -1.0, 'B': 1.0}, rule='g1 or g2').upper
1000.0

StrainDesignAnalysis(kind='optknock', *, product='', growth=None, constraints='', interventions=3, solutions=1, network=None)

Bases: BaseNetworkAnalysis

Strain designs of a metabolic network with StrainDesign, which needs the extra metabolism.

  • 'optknock', 'robustknock', and 'optcouple': the knock-outs that couple a product to growth.
  • 'mcs': the minimal cut sets that suppress the flux states of a constraint.

Parameters:

Name Type Description Default
kind str

The design, one of the kinds above.

'optknock'
product str

The reaction of the product, the outer objective.

''
growth str | None

The reaction of growth, the inner objective, or None for the objective of the network.

None
constraints str

The constraints of the design in the syntax of StrainDesign, such as 'Biomass >= 0.1'.

''
interventions int

The largest number of interventions.

3
solutions int

The largest number of designs.

1
network str | None

The label of the network, or None for the first network of the system.

None

Attributes:

Name Type Description
designs_

Every design as a set of reaction names.

Raises:

Type Description
AnalysisError

The kind is unknown, raised by prepare.

MissingExtraError

The extra is not installed, raised by prepare.

Examples:

>>> from skcomplex.systems.biology.common.metabolism import StrainDesignAnalysis
>>> StrainDesignAnalysis('optknock', product='EX_succ_e').interventions
3
Source code in src/skcomplex/systems/biology/common/metabolism/_analyses.py
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
def __init__(
    self,
    kind: str = 'optknock',
    *,
    product: str = '',
    growth: str | None = None,
    constraints: str = '',
    interventions: int = 3,
    solutions: int = 1,
    network: str | None = None,
) -> None:
    super().__init__(network=network)
    self.kind = kind
    self.product = product
    self.growth = growth
    self.constraints = constraints
    self.interventions = interventions
    self.solutions = solutions

SubstrateElement(label, visual=None, *, c=10.0)

Bases: Element

Concentration of a metabolite of a medium.

Parameters:

Name Type Description Default
label str

The label of the element.

required
visual VisualSpec | None

How the element is drawn, or None for default_visual_.

None
c Annotated[float, StateSpec()]

The concentration in mM.

10.0

Examples:

>>> from skcomplex.systems.biology.common.metabolism import SubstrateElement
>>> SubstrateElement('glucose', c=10.0).c
10.0
Source code in src/skcomplex/systems/biology/common/metabolism/_culture.py
72
73
74
75
76
77
78
79
80
def __init__(
    self,
    label: str,
    visual: VisualSpec | None = None,
    *,
    c: Annotated[float, StateSpec()] = 10.0,
) -> None:
    super().__init__(label, visual=visual)
    self.c = c

SwitchInteraction(label, *, node='node', cell='cell', genes=())

Bases: Interaction

Update of the switches of genes from a Boolean node that represses them.

Parameters:

Name Type Description Default
label str

The label of the interaction.

required
node Annotated[str, RoleSpec()]

The path of the Boolean node, whose state x is 1 for on.

'node'
cell Annotated[str, RoleSpec()]

The path of the metabolic network.

'cell'
genes Sequence[str]

The names of the genes the node represses.

()

Examples:

>>> from skcomplex.systems.biology.common.metabolism import SwitchInteraction
>>> SwitchInteraction('repression', node='node', cell='cell', genes=('b2296',)).genes
('b2296',)
Source code in src/skcomplex/systems/biology/common/metabolism/_culture.py
461
462
463
464
465
466
467
468
469
470
471
472
def __init__(
    self,
    label: str,
    *,
    node: Annotated[str, RoleSpec()] = 'node',
    cell: Annotated[str, RoleSpec()] = 'cell',
    genes: Sequence[str] = (),
) -> None:
    super().__init__(label)
    self.node = node
    self.cell = cell
    self.genes = genes

ToyNetworkElement(label, visual=None, *, objective=None, parsimonious=False, infeasible='raise', name='ToyNetwork', reactions=TOY_REACTIONS, default_objective=TOY_OBJECTIVE, variables=None)

Bases: MetabolicNetworkElement

The toy network of Table 8.2 of Raman (2021), which grows on A alone.

Parameters:

Name Type Description Default
label str

The label of the element.

required
visual VisualSpec | None

How the element is drawn, or None for the bars of its program.

None
objective Mapping[str, float] | None

The coefficient of every reaction in the objective, or None for default_objective.

None
parsimonious bool

Whether to minimise the total absolute flux after the objective.

False
infeasible str

The infeasibility policy of the program.

'raise'
name str | None

The name of the network.

'ToyNetwork'
reactions Mapping[str, ReactionSpec]

The reactions by name.

TOY_REACTIONS
default_objective Mapping[str, float]

The objective of the network when objective is None.

TOY_OBJECTIVE
variables Mapping[str, DeclaredVariableSpec] | None

The declared states and parameters that replace the ones of the reactions, by name, or None for none.

None

Examples:

>>> from skcomplex.systems.biology.common.metabolism import ToyNetworkElement
>>> ToyNetworkElement('cell').get_value('upper_v1')
1000.0
Source code in src/skcomplex/systems/biology/common/metabolism/_toy_network.py
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
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,
    )

community_medium_type(exchanges)

Return a function that creates a CommunityMediumElement with the state of the net exchange of some reactions.

Parameters:

Name Type Description Default
exchanges Sequence[str]

The names of the reactions.

required

Returns:

Name Type Description
create_medium Callable[..., CommunityMediumElement]

The function, which takes the label, the visual, and the initial values of the states by name.

Examples:

>>> from skcomplex.systems.biology.common.metabolism import community_medium_type
>>> community_medium_type(['EX_a'])('medium').get_value('u_EX_a')
0.0
Source code in src/skcomplex/systems/biology/common/metabolism/_culture.py
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
def community_medium_type(exchanges: Sequence[str]) -> Callable[..., CommunityMediumElement]:
    """Return a function that creates a `CommunityMediumElement` with the state of the net exchange of some reactions.

    Args:
        exchanges:
            The names of the reactions.

    Returns:
        create_medium:
            The function, which takes the label, the visual, and the initial values of the states by name.

    Examples:
        >>> from skcomplex.systems.biology.common.metabolism import community_medium_type
        >>> community_medium_type(['EX_a'])('medium').get_value('u_EX_a')
        0.0
    """

    def create_medium(label: str, visual: VisualSpec | None = None, **values: float) -> CommunityMediumElement:
        medium = CommunityMediumElement(label, visual, exchanges=tuple(exchanges))
        return medium.set_params(**values)

    return create_medium

from_cobra(system, label='network', *, needed_by='from_cobra')

Return a metabolic network element of a COBRApy model, with its bounds, rules, and objective.

Parameters:

Name Type Description Default
system object

The cobra.Model.

required
label str

The label of the element.

'network'
needed_by str

The name of what needs the extra, for the error.

'from_cobra'

Returns:

Name Type Description
element MetabolicNetworkElement

The element, of a type built for the system.

Raises:

Type Description
MissingExtraError

The extra is not installed.

ValidationError

The system is not a cobra.Model.

Examples:

>>> import cobra
>>> from skcomplex.systems.biology.common.metabolism import from_cobra
>>> system = cobra.Model('one')
>>> reaction = cobra.Reaction('r', upper_bound=5.0)
>>> reaction.add_metabolites({cobra.Metabolite('a', compartment='c'): -1.0})
>>> system.add_reactions([reaction])
>>> from_cobra(system, 'cell').get_value('upper_r')
5.0
Source code in src/skcomplex/systems/biology/common/metabolism/_cobra_io.py
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
def from_cobra(system: object, label: str = 'network', *, needed_by: str = 'from_cobra') -> MetabolicNetworkElement:
    """Return a metabolic network element of a COBRApy model, with its bounds, rules, and objective.

    Args:
        system:
            The `cobra.Model`.

        label:
            The label of the element.

        needed_by:
            The name of what needs the extra, for the error.

    Returns:
        element:
            The element, of a type built for the system.

    Raises:
        MissingExtraError:
            The extra is not installed.

        ValidationError:
            The system is not a `cobra.Model`.

    Examples:
        >>> import cobra
        >>> from skcomplex.systems.biology.common.metabolism import from_cobra
        >>> system = cobra.Model('one')
        >>> reaction = cobra.Reaction('r', upper_bound=5.0)
        >>> reaction.add_metabolites({cobra.Metabolite('a', compartment='c'): -1.0})
        >>> system.add_reactions([reaction])
        >>> from_cobra(system, 'cell').get_value('upper_r')
        5.0
    """
    cobra = load_extra(needed_by)
    if not isinstance(system, cobra.Model):
        error_msg = f'from_cobra converts a `cobra.Model`, not a {type(system).__name__}.'
        raise ValidationError(error_msg)
    reactions = {
        reaction.id: ReactionSpec(
            {metabolite.id: float(value) for metabolite, value in reaction.metabolites.items()},
            float(reaction.lower_bound),
            float(reaction.upper_bound),
            reaction.gene_reaction_rule,
        )
        for reaction in system.reactions
    }
    objective = {
        reaction.id: float(reaction.objective_coefficient)
        for reaction in system.reactions
        if reaction.objective_coefficient != 0
    }
    name = ''.join(part.capitalize() for part in str(system.id or 'network').split('_'))
    return metabolic_network_type(MetabolicNetworkElement._identifier(name), reactions, objective)(label)

load_extra(owner)

Return COBRApy, the first library of the extra metabolism.

Parameters:

Name Type Description Default
owner str

The name of the class, function, or system that needs the extra, for the error.

required

Returns:

Name Type Description
cobra ModuleType

The module.

Raises:

Type Description
MissingExtraError

The extra is not installed.

Examples:

>>> from skcomplex.systems.biology.common.metabolism import load_extra
>>> load_extra('example').__name__
'cobra'
Source code in src/skcomplex/systems/biology/common/metabolism/_cobra_io.py
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
def load_extra(owner: str) -> ModuleType:
    """Return COBRApy, the first library of the extra `metabolism`.

    Args:
        owner:
            The name of the class, function, or system that needs the extra, for the error.

    Returns:
        cobra:
            The module.

    Raises:
        MissingExtraError:
            The extra is not installed.

    Examples:
        >>> from skcomplex.systems.biology.common.metabolism import load_extra
        >>> load_extra('example').__name__
        'cobra'
    """
    if sys.platform == 'linux':
        # Once GAP has run, loading libSBML the usual way binds it to a library of GAP, and its parser crashes.
        flags = sys.getdlopenflags()
        sys.setdlopenflags(flags | os.RTLD_DEEPBIND)
        try:
            import_extra('libsbml', owner, 'metabolism')
        finally:
            sys.setdlopenflags(flags)
    return import_extra('cobra', owner, 'metabolism')

load_network(source=BUNDLED_SYSTEM, label='network', *, needed_by='load_network')

Return the metabolic network element of an SBML or BiGG JSON file, or of a BiGG identifier.

Parameters:

Name Type Description Default
source str | Path

The path of a .xml, .sbml, or .json file, a BiGG identifier, which COBRApy downloads, or 'textbook' for the E. coli core system it bundles.

BUNDLED_SYSTEM
label str

The label of the element.

'network'
needed_by str

The name of what needs the extra, for the error.

'load_network'

Returns:

Name Type Description
element MetabolicNetworkElement

The element.

Raises:

Type Description
MissingExtraError

The extra is not installed.

Examples:

>>> from skcomplex.systems.biology.common.metabolism import load_network
>>> len(load_network('textbook', 'cell').reactions)
95
Source code in src/skcomplex/systems/biology/common/metabolism/_cobra_io.py
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
def load_network(
    source: str | Path = BUNDLED_SYSTEM,
    label: str = 'network',
    *,
    needed_by: str = 'load_network',
) -> MetabolicNetworkElement:
    """Return the metabolic network element of an SBML or BiGG JSON file, or of a BiGG identifier.

    Args:
        source:
            The path of a `.xml`, `.sbml`, or `.json` file, a BiGG identifier, which COBRApy downloads, or `'textbook'`
            for the E. coli core system it bundles.

        label:
            The label of the element.

        needed_by:
            The name of what needs the extra, for the error.

    Returns:
        element:
            The element.

    Raises:
        MissingExtraError:
            The extra is not installed.

    Examples:
        >>> from skcomplex.systems.biology.common.metabolism import load_network
        >>> len(load_network('textbook', 'cell').reactions)
        95
    """
    cobra = load_extra(needed_by)
    path = Path(source)
    if path.suffix == '.json':
        return from_cobra(cobra.io.load_json_model(str(path)), label)
    if path.suffix in {'.xml', '.sbml'}:
        return from_cobra(cobra.io.read_sbml_model(str(path)), label)
    if str(source) == BUNDLED_SYSTEM:
        return from_cobra(cobra.io.load_model(BUNDLED_SYSTEM), label)
    repository = cobra.io.web.load.BiGGModels()
    repository._url = repository.url.copy_with(scheme='https')
    return from_cobra(cobra.io.load_model(str(source), repositories=[repository]), label)

metabolic_network_type(name, reactions, objective=None)

Return a function that creates a MetabolicNetworkElement of a set of reactions.

Parameters:

Name Type Description Default
name str

The name of the network.

required
reactions Mapping[str, ReactionSpec]

The reactions by name.

required
objective Mapping[str, float] | None

The coefficient of every reaction in the objective, or None for none.

None

Returns:

Name Type Description
create_network Callable[..., MetabolicNetworkElement]

The function, which takes the label, the visual, the other arguments of the element, and the values of its states and parameters by name.

Examples:

>>> from skcomplex.systems.biology.common.metabolism import ReactionSpec, metabolic_network_type
>>> create_network = metabolic_network_type('OneStep', {'r': ReactionSpec({'A': -1.0}, rule='g')})
>>> network = create_network('cell', g_g=0.0)
>>> network.flux_name('r'), network.genes_of(), network.get_value('g_g')
('v_r', ('g',), 0.0)
Source code in src/skcomplex/systems/biology/common/metabolism/_metabolic_network.py
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
def metabolic_network_type(
    name: str,
    reactions: Mapping[str, ReactionSpec],
    objective: Mapping[str, float] | None = None,
) -> Callable[..., MetabolicNetworkElement]:
    """Return a function that creates a `MetabolicNetworkElement` of a set of reactions.

    Args:
        name:
            The name of the network.

        reactions:
            The reactions by name.

        objective:
            The coefficient of every reaction in the objective, or `None` for none.

    Returns:
        create_network:
            The function, which takes the label, the visual, the other arguments of the element, and the values of its
            states and parameters by name.

    Examples:
        >>> from skcomplex.systems.biology.common.metabolism import ReactionSpec, metabolic_network_type
        >>> create_network = metabolic_network_type('OneStep', {'r': ReactionSpec({'A': -1.0}, rule='g')})
        >>> network = create_network('cell', g_g=0.0)
        >>> network.flux_name('r'), network.genes_of(), network.get_value('g_g')
        ('v_r', ('g',), 0.0)
    """

    def create_network(label: str, visual: VisualSpec | None = None, **settings: object) -> MetabolicNetworkElement:
        network = MetabolicNetworkElement(
            label,
            visual,
            name=name,
            reactions=dict(reactions),
            default_objective=dict(objective or {}),
        )
        return network.set_params(**settings)

    return create_network

save_network(element, path)

Write a metabolic network element to an SBML or BiGG JSON file, by the suffix of the path.

Parameters:

Name Type Description Default
element MetabolicNetworkElement

The element.

required
path str | Path

The path of a .xml, .sbml, or .json file.

required

Raises:

Type Description
MissingExtraError

The extra is not installed.

ValidationError

The suffix names no format.

Examples:

>>> import tempfile
>>> from pathlib import Path
>>> from skcomplex.systems.biology.common.metabolism import ReactionSpec, metabolic_network_type, save_network
>>> network = metabolic_network_type('SavedElement', {'r': ReactionSpec({'a': -1.0})}, {'r': 1.0})('cell')
>>> with tempfile.TemporaryDirectory() as folder:
...     save_network(network, Path(folder) / 'network.json')
...     (Path(folder) / 'network.json').exists()
True
Source code in src/skcomplex/systems/biology/common/metabolism/_cobra_io.py
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
def save_network(element: MetabolicNetworkElement, path: str | Path) -> None:
    """Write a metabolic network element to an SBML or BiGG JSON file, by the suffix of the path.

    Args:
        element:
            The element.

        path:
            The path of a `.xml`, `.sbml`, or `.json` file.

    Raises:
        MissingExtraError:
            The extra is not installed.

        ValidationError:
            The suffix names no format.

    Examples:
        >>> import tempfile
        >>> from pathlib import Path
        >>> from skcomplex.systems.biology.common.metabolism import ReactionSpec, metabolic_network_type, save_network
        >>> network = metabolic_network_type('SavedElement', {'r': ReactionSpec({'a': -1.0})}, {'r': 1.0})('cell')
        >>> with tempfile.TemporaryDirectory() as folder:
        ...     save_network(network, Path(folder) / 'network.json')
        ...     (Path(folder) / 'network.json').exists()
        True
    """
    cobra = load_extra('save_network')
    target = Path(path)
    if target.suffix == '.json':
        cobra.io.save_json_model(to_cobra(element), str(target))
    elif target.suffix in {'.xml', '.sbml'}:
        cobra.io.write_sbml_model(to_cobra(element), str(target))
    else:
        error_msg = f'The path {target} has the suffix {target.suffix!r}. Use `.xml`, `.sbml`, or `.json`.'
        raise ValidationError(error_msg)

to_cobra(element, *, needed_by='to_cobra')

Return the COBRApy model of a metabolic network element, with its current bounds, rules, and objective.

A switch that is off knocks its gene out, and the system solves with the hybrid interface, which reaches HiGHS.

Parameters:

Name Type Description Default
element MetabolicNetworkElement

The element.

required
needed_by str

The name of what needs the extra, for the error.

'to_cobra'

Returns:

Name Type Description
system object

The cobra.Model.

Raises:

Type Description
MissingExtraError

The extra is not installed.

Examples:

>>> from skcomplex.systems.biology.common.metabolism import ReactionSpec, metabolic_network_type, to_cobra
>>> reactions = {'r': ReactionSpec({'a': -1.0}, upper=3.0, rule='g')}
>>> system = to_cobra(metabolic_network_type('OneElement', reactions, {'r': 1.0})('cell'))
>>> system.reactions.r.upper_bound, system.reactions.r.gene_reaction_rule
(3.0, 'g')
Source code in src/skcomplex/systems/biology/common/metabolism/_cobra_io.py
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
def to_cobra(element: MetabolicNetworkElement, *, needed_by: str = 'to_cobra') -> object:
    """Return the COBRApy model of a metabolic network element, with its current bounds, rules, and objective.

    A switch that is off knocks its gene out, and the system solves with the `hybrid` interface, which reaches HiGHS.

    Args:
        element:
            The element.

        needed_by:
            The name of what needs the extra, for the error.

    Returns:
        system:
            The `cobra.Model`.

    Raises:
        MissingExtraError:
            The extra is not installed.

    Examples:
        >>> from skcomplex.systems.biology.common.metabolism import ReactionSpec, metabolic_network_type, to_cobra
        >>> reactions = {'r': ReactionSpec({'a': -1.0}, upper=3.0, rule='g')}
        >>> system = to_cobra(metabolic_network_type('OneElement', reactions, {'r': 1.0})('cell'))
        >>> system.reactions.r.upper_bound, system.reactions.r.gene_reaction_rule
        (3.0, 'g')
    """
    cobra = load_extra(needed_by)
    system = cobra.Model(element.label)
    metabolites: dict[str, object] = {}
    for spec in element.reactions.values():
        for name in spec.coefficients:
            compartment = name.rpartition('_')[2] if '_' in name else DEFAULT_COMPARTMENT
            metabolites.setdefault(name, cobra.Metabolite(name, compartment=compartment))
    reactions = []
    for name, spec in element.reactions.items():
        identifier = element._identifier(name)
        reaction = cobra.Reaction(name)
        reaction.bounds = (element.get_number(f'lower_{identifier}'), element.get_number(f'upper_{identifier}'))
        reaction.add_metabolites({metabolites[item]: float(value) for item, value in spec.coefficients.items()})
        reaction.gene_reaction_rule = spec.rule
        reactions.append(reaction)
    system.add_reactions(reactions)
    system.solver = SOLVER
    weights = element.default_objective if element.objective is None else element.objective
    system.objective = {system.reactions.get_by_id(name): float(value) for name, value in weights.items()}
    for gene in element.genes_of():
        if element.get_number(element.gene_name(gene)) < 1:
            system.genes.get_by_id(gene).knock_out()
    return system