Limit proteins (Python)#

geckopy objects in geckopy.limit_proteins.

Functions#

Function

Summary

apply_flux_data_constraints

Constrain the model's exchange fluxes from a FluxData measurement.

calculate_f_factor

Compute the f-factor for an ec model.

complex_families

Group the enzymes of multi-subunit reactions into complexes.

ComplexFamilies

The complexes of an ecModel and their shared subunits.

constrain_enz_concs

Constrain usage_prot_<enzyme> reactions by model.ec.concs.

fill_enz_concs

Fill model.ec.concs from prot_data.abundances (mg/gDCW).

FlexEnzResult

Information about which enzyme constraints were flexibilized.

flexibilize_enz_concs

Iteratively relax enzyme concentration constraints until the

get_conc_control_coeffs

Compute control coefficients for enzyme concentrations.

GreedyRelaxResult

level_complex_abundances

Level molar abundances to one abundance per complex.

level_complex_concs

Give every complex in model.ec.concs one abundance.

LevelComplexResult

What level_complex_concs changed.

relax_enz_concs

Relax enzyme caps by the least total amount that reaches exp_growth.

relax_proteomics_greedy

Greedy relaxation of proteomics constraints until growth >= minimal_growth.

RelaxationStep

Reference#

apply_flux_data_constraints#

apply_flux_data_constraints(model: 'EcModel', flux_data: 'FluxData', *, condition: int | str=0, max_min_growth: Literal['max', 'min']='max', loose_strict_flux: _LooseStrict='loose', bio_rxn: Optional[str]=None, c_source: Optional[str]=None)

Constrain the model's exchange fluxes from a FluxData measurement.

Sets the biomass reaction bounds to the measured growth rate and each exchange reaction in flux_data.exch_rxn_ids to its measured flux for the chosen condition. Also zeros out the adapter's preferred carbon source so the data drives the choice.

Ported from GECKO MATLAB: src/geckomat/limit_proteins/constrainFluxData.m.

A +/-1000 measured flux means unconstrained, regardless of loose_strict_flux: -1000 -> lb=-1000, ub=0 (free uptake), +1000 -> lb=0, ub=1000 (free excretion).

Parameters

model

EcModel with the exchange reactions referenced by flux_data already in place. Mutated in place.

flux_data

Pre-loaded FluxData (typically from a future load_flux_data utility).

condition

Either the 0-indexed condition number, or the condition name (matched against flux_data.conds).

max_min_growth

"max" sets bio_rxn upper bound to the measured growth rate (and lower bound to 0); "min" sets the lower bound (suitable when minimising prot_pool_exchange).

loose_strict_flux

"loose" keeps one bound at 0 and the other at the measured value (allows zero flux). A numeric percentage p brackets the measured value with hard bounds: lb = val * (1 - p/200), ub = val * (1 + p/200), swapped as needed to keep lb <= ub when val is negative. p=10 allows 10% total variance (i.e. +/-5%).

bio_rxn

Biomass reaction ID. Defaults to the adapter's configured biomass reaction (model.adapter.params.bio_rxn) when None.

c_source

Reaction ID of the preferred carbon-source uptake reaction; its bounds are set to (0, 0) before applying the flux data so that the data alone determines the carbon source used. Defaults to model.adapter.params.c_source (or no blocking if there is no adapter) when None; pass "" to skip blocking any reaction. Silently ignored if the reaction id is not found in the model.

Raises

ValueError

If model.adapter is None, max_min_growth / loose_strict_flux is invalid, condition (as string) is not in flux_data.conds, or any flux_data.exch_rxn_ids is missing from the model.

IndexError

If condition (as int) is out of range.

calculate_f_factor#

calculate_f_factor(model: 'EcModel', prot_data: 'ProtData', *, enzymes: Optional[list[str]]=None)

Compute the f-factor for an ec model.

The f-factor is the mass fraction of total cellular protein that is accounted for by enzymes in the model. It is computed as

f = sum(abundances of in-model enzymes) / sum(all abundances)

where abundances are read from a pre-loaded ProtData (typically populated via load_pax_db).

For 2-D abundances (multiple proteomics samples), the per-protein average is taken first via np.nanmean(axis=1).

Ported from GECKO MATLAB: src/geckomat/limit_proteins/calculateFfactor.m.

Parameters

model

EcModel; only used to default enzymes to model.ec.enzymes.

prot_data

Pre-loaded proteomics data (typically from load_pax_db). There is no implicit fallback when proteomics data is unavailable -- callers without measurements should use a default value such as f = 0.5 directly instead of calling this function.

enzymes

UniProt IDs counted as "in the model". Defaults to model.ec.enzymes.

Returns

float

The f-factor in [0, 1]. Returns 0.0 if the total proteome abundance is zero, or if none of the proteomics UniProt IDs match a model enzyme.

complex_families#

complex_families(model: 'EcModel', min_overlap: float=0.5, min_shared: int=2)

Group the enzymes of multi-subunit reactions into complexes.

Parameters

model

An EcModel with ec.rxn_enz_mat (copies per subunit).

min_overlap

Two enzyme sets are one complex when they share at least this fraction of the larger set's subunits...

min_shared

...and at least this many subunits.

ComplexFamilies#

The complexes of an ecModel and their shared subunits.

Attributes

complexes

One dict per complex, {enzyme: copies} over every subunit that appears in any of its enzyme sets.

owner

For every subunit that belongs to a complex, the index of that complex in complexes.

shared

Subunits of a complex that belong to none: carriers and subunits shared between complexes.

constrain_enz_concs#

constrain_enz_concs(model: 'EcModel', *, remove_constraints: bool=False, restrict_to: list[str] | None=None)

Constrain usage_prot_<enzyme> reactions by model.ec.concs.

For each enzyme in model.ec.enzymes whose entry in model.ec.concs is non-NaN, the corresponding usage_prot_<enzyme> reaction's upper bound is set to that concentration. Enzymes with NaN concentrations have their usage reaction reset to the default upper_bound = 1000, drawing freely from prot_pool. Only the reaction's upper bound is changed; its stoichiometry (as set by add_protein_usage_reactions) is left untouched.

Ported from GECKO MATLAB: src/geckomat/limit_proteins/constrainEnzConcs.m.

Parameters

model

EcModel with model.ec.concs populated (typically by fill_enz_concs) and the protein pool / usage reaction machinery already in place. Mutated in place.

remove_constraints

When True, all usage reactions are reset to their default upper_bound = 1000, regardless of ec.concs. ec.concs itself is left unchanged.

restrict_to

If supplied, only the listed enzyme uniprot IDs are processed (others are left untouched). Useful for incremental updates from Enzyme.concentration setters. Unknown IDs in the list are silently ignored. Default None = process every enzyme in model.ec.enzymes.

Raises

ValueError

If the prot_pool metabolite is missing, or if any usage_prot_<enzyme> reaction is missing for an enzyme in model.ec.enzymes (e.g. because the model is gecko-light, which has no usage reactions).

fill_enz_concs#

fill_enz_concs(model: 'EcModel', prot_data: 'ProtData', *, data_col: int=0)

Fill model.ec.concs from prot_data.abundances (mg/gDCW).

Resets model.ec.concs to all-NaN of length n_enzymes, then writes each (uniprot_id, abundance) pair into the slot matching model.ec.enzymes. UniProt IDs absent from model.ec.enzymes are silently ignored. Enzymes absent from prot_data keep their NaN.

For 2-D prot_data.abundances (multiple conditions / samples), data_col selects which column to use.

Ported from GECKO MATLAB: src/geckomat/limit_proteins/fillEnzConcs.m.

Parameters

model

EcModel; model.ec.concs is replaced in place.

prot_data

Pre-loaded proteomics data (e.g. from load_pax_db or a manual TSV reader). Abundances are expected in mg/gDCW.

data_col

0-indexed column of prot_data.abundances to read. Must be 0 for 1-D abundances.

Raises

IndexError

If data_col is out of range for the supplied abundances.

FlexEnzResult#

Information about which enzyme constraints were flexibilized.

All arrays are sorted by ratio_incr descending. May contain a final entry with uniprot_ids[-1] == "prot_pool" if the protein pool exchange itself was relaxed.

Attributes

uniprot_ids

UniProt IDs of the flexibilized enzymes (plus "prot_pool" as a final entry when the protein pool itself was relaxed).

old_concs

Upper bound of each enzyme's usage reaction (or of prot_pool_exchange for the "prot_pool" entry) before relaxation.

flex_concs

Upper bound after relaxation.

ratio_incr

flex_concs / old_concs; inf where old_concs is 0.

frequence

Number of loop iterations in which each enzyme was picked as the most limiting one.

flexibilize_enz_concs#

flexibilize_enz_concs(model: 'EcModel', *, exp_growth: Optional[float]=None, fold_change: float=2.0, iter_per_enzyme: int=5, bio_rxn: Optional[str]=None, verbose: bool=True, per_complex: bool=False)

Iteratively relax enzyme concentration constraints until the

model reaches exp_growth.

Each iteration uses get_conc_control_coeffs to find the most limiting enzyme, then multiplies its usage_prot_<enzyme> upper bound by (1 + fold_change * iteration_count). If no enzyme is limiting (all control coefficients zero), the function tries relaxing prot_pool_exchange.

After the loop, a refinement pass solves min prot_pool_exchange with bio_rxn constrained to a soft +/-0.25% band around exp_growth (matching MATLAB's flexibilizeEnzConcs.m, which uses RAVEN's setParam('var', bioRxn, expGrowth, 0.5) for the same solve) to find the minimal usage that supports growth. Because minimal protein-pool usage is non-decreasing in growth rate near the optimum, the minimiser typically settles at the band's low edge -- growth ends up about 0.25% below exp_growth, not at it exactly. For each flexibilized enzyme, if the actual usage at this minimum is less than its original concentration, the original constraint is restored (i.e. that enzyme is dropped from the result). This avoids over-relaxing enzymes that the prior iterative pass increased more than necessary.

Ported from GECKO MATLAB: src/geckomat/limit_proteins/flexibilizeEnzConcs.m.

Parameters

model

EcModel with prot_pool_exchange and usage_prot_* reactions installed and model.ec.concs populated for at least some enzymes (typically by fill_enz_concs and constrain_enz_concs). Mutated in place; ec.concs itself is left unchanged.

exp_growth

Target growth rate. Defaults to model.adapter.params.gr_exp.

fold_change

Controls how much the limiting enzyme's usage upper bound grows each time it is picked: on its k-th pick, the bound is set to original_conc * (1 + fold_change * k).

iter_per_enzyme

Maximum number of times the same enzyme may be picked before warning and breaking. 0 means no limit.

bio_rxn

Biomass reaction id. Defaults to params.bio_rxn from the adapter; pass it (with exp_growth) to run without an adapter.

verbose

Whether per-iteration progress is logged at INFO.

per_complex

Treat every complex (see complex_families) as one enzyme: rank enzymes and complexes by the growth gained per fold of raising all their caps together (a levelled complex binds on all subunits at once, so no single subunit shows a gain), raise every measured subunit of the picked complex by the same factor, count iterations per complex, and keep one factor per complex in the refinement pass, so that concentrations levelled by level_complex_concs stay levelled. Off by default.

Returns

FlexEnzResult :

Raises

ValueError

If no enzyme has a measured concentration (nothing to flexibilize), or if model.adapter is None and exp_growth is also None.

get_conc_control_coeffs#

get_conc_control_coeffs(model: 'EcModel', proteins: Optional[list[str]]=None, fold_change: float=2.0, limit: float=0.0)

Compute control coefficients for enzyme concentrations.

For each protein in proteins, the coefficient quantifies how much the LP optimum (typically growth) increases per unit increase in that enzyme's upper bound. Proteins whose usage flux is at most limit times their upper bound are skipped (no sensitivity to expect there).

The default path uses the prot_<id> metabolite shadow price from a single LP solve — equivalent to the per-protein finite-difference probe at the margin, but n times fewer LPs. When the active solver is one that does not expose LP duals (notably optlang's scipy backend), the function automatically falls back to the per-protein finite-difference loop and logs once that it has done so. The fold-change probe size is only used in that fallback.

Ported from GECKO MATLAB: src/geckomat/limit_proteins/getConcControlCoeffs.m.

Parameters

model

EcModel with a defined LP objective (typically a biomass reaction) and usage_prot_<enzyme> reactions for every analysed protein.

proteins

UniProt IDs to analyse. Defaults to model.ec.enzymes.

fold_change

Probe size for the finite-difference fallback (default 2.0). Ignored on the shadow-price path.

limit

Skip proteins whose usage flux is at most limit times their upper bound. Default 0.0 includes any protein with non-zero flux.

Returns

enz_mask

Boolean array of length len(proteins); True where the protein was analysed.

control_coeffs

Float array of length len(proteins); 0.0 where the protein was either skipped or showed no sensitivity.

GreedyRelaxResult#

level_complex_abundances#

level_complex_abundances(model: 'EcModel', uniprot_ids: Sequence[str], abundances: Sequence[float], *, statistic: str='median', fill_missing: bool=True, families: Optional[ComplexFamilies]=None)

Level molar abundances to one abundance per complex.

Parameters

model

The EcModel whose complexes are used.

uniprot_ids, abundances

Measured molar abundances (any molar unit; per subunit, not per complex).

statistic

"median" or "mean" over the measured, non-shared subunits' abundance divided by their copies.

fill_missing

Give unmeasured, non-shared subunits the complex's abundance.

families

Precomputed complex_families(model).

Returns

ids, abundances, result

The levelled data (unmeasured subunits appended when filled) and what changed.

level_complex_concs#

level_complex_concs(model: 'EcModel', *, statistic: str='median', fill_missing: bool=True)

Give every complex in model.ec.concs one abundance.

Run after fill_enz_concs and before constrain_enz_concs. Concentrations (mg/gDCW) are converted to molar amounts with ec.mw for the levelling and back afterwards. Mutates model.ec.concs.

Parameters

model

EcModel with ec.concs filled.

statistic

"median" (default) or "mean".

fill_missing

Give unmeasured, non-shared subunits the complex's concentration.

LevelComplexResult#

What level_complex_concs changed.

Attributes

adjusted

Measured subunits whose concentration was replaced by the complex's.

added

Unmeasured subunits given the complex's concentration.

shared

Subunits left as measured because they belong to more than one complex.

skipped

Complexes (as sorted subunit tuples) without any measured, non-shared subunit.

relax_enz_concs#

relax_enz_concs(model: 'EcModel', *, exp_growth: Optional[float]=None, bio_rxn: Optional[str]=None, per_complex: bool=False, weight: str='relative', pool_weight: float=1000.0, floor: float=1e-09)

Relax enzyme caps by the least total amount that reaches exp_growth.

Parameters

model

EcModel with model.ec.concs filled and the caps applied (fill_enz_concs and constrain_enz_concs). The usage upper bounds (and prot_pool_exchange) are updated in place; ec.concs itself is left unchanged, as in flexibilize_enz_concs.

exp_growth

Target growth rate. Defaults to params.gr_exp.

bio_rxn

Biomass reaction id. Defaults to params.bio_rxn.

per_complex

One fold per complex (its measured, owned subunits; see complex_families) instead of one per enzyme.

weight

"relative" minimises the summed fold increases, so an enzyme measured at almost nothing is not relaxed freely because its absolute cost is small; "absolute" minimises the mg/gDCW added.

pool_weight

Price of one fold of the protein pool relative to one fold of an enzyme (or, with weight="absolute", per mg).

floor

Concentration below which a measured value is treated as this floor when scaling its fold, so a zero measurement can still be relaxed (at a high relative price).

Returns

FlexEnzResult

The relaxed enzymes, as from flexibilize_enz_concs (frequence is 1 for every entry), with a "prot_pool" entry when the pool was raised.

Raises

ValueError

If no enzyme is measured, the weighting is unknown, or no relaxation reaches exp_growth (the target is then not limited by protein).

relax_proteomics_greedy#

relax_proteomics_greedy(model: 'EcModel', *, minimal_growth: float, enzyme_set: Optional[set[str]]=None, max_iterations: int=100, default_upper_bound: float=1000.0)

Greedy relaxation of proteomics constraints until growth >= minimal_growth.

Parameters

model

EcModel with proteomics-constrained enzymes (some usage_prot_<id> reactions have finite upper bounds from constrain_enz_concs).

minimal_growth

Target objective value.

enzyme_set

Subset of uniprot IDs eligible for relaxation. None = all currently proteomics-constrained enzymes.

max_iterations

Safety cap; raises RuntimeError if exceeded without convergence.

default_upper_bound

Value to restore on a relaxed usage reaction. Matches the default set by add_protein_usage_reactions.

Returns

GreedyRelaxResult

relaxed maps uniprot to the original concentration (so the caller can restore if desired); trace records each step; final_growth is the objective value reached at the last iteration attempted; converged is True iff final_growth >= minimal_growth.

Ported from the legacy geckopy package (Carrasco et al., 2023, :

https://doi.org/10.1128/spectrum.01705-23), :

geckopy/experimental/relaxation.py (relax_proteomics_greedy). :

RelaxationStep#