Utilities (Python)#

geckopy objects in geckopy.utilities.

Functions#

Function

Summary

add_new_rxns_to_ec

Add reactions and their enzymes to an ecModel.

AddNewRxnsResult

IDs of what was actually added (after isozyme/reversibility

ec_fseof

Run Flux-Scanning with Enforced Objective Function on an ecModel.

ec_fva

Flux variability analysis on an ecModel, mapped to conventional rxns.

enzyme_usage

Compute per-enzyme absolute and capacity usage from fluxes.

EnzymeUsageReport

Two human-readable tables summarising enzyme usage.

EnzymeUsageResult

Per-enzyme usage info from a flux distribution.

get_enzyme_bottlenecks

Top-N enzymes by absolute shadow price.

get_subset_ec_model

Trim big_ec_model to the gene/reaction set of small_gem.

load_conventional_gem

Load the starting GEM file pointed to by adapter.

load_ec_model

Load an ecModel from a YAML file.

map_rxns_to_conv

Translate ec-rxn fluxes back to conventional-rxn fluxes.

MapRxnsResult

Output of mapping ec-rxn fluxes back to conventional rxns.

NewEnzyme

An enzyme to add alongside the new reactions.

pfba_enzymes

Parsimonious FBA minimising the L1 norm of usage_prot_* fluxes.

report_enzyme_usage

Summarise enzyme usage as two DataFrames.

save_ec_model

Save an ecModel to a YAML file.

Reference#

add_new_rxns_to_ec#

add_new_rxns_to_ec(model: 'EcModel', new_rxns: list[cobra.Reaction], new_enzymes: list[NewEnzyme])

Add reactions and their enzymes to an ecModel.

For each new reaction, the function:

  • Splits a reversible reaction (lower_bound < 0) into a forward copy plus a _REV copy with negated stoichiometry.

  • Splits an OR-of-ANDs GPR into one _EXP_<n> copy per AND-clause using the same DNF logic as expand_model.

The combination of both splits gives all four variants when applicable (R_EXP_1, R_EXP_2, R_REV_EXP_1, R_REV_EXP_2).

Each new enzyme contributes:

  • a prot_<enzyme> pseudometabolite in the enzyme compartment,

  • a usage_prot_<enzyme> reaction (prot_pool -> prot_<enzyme>, bounds (0, 1000), GPR set to the gene),

  • an entry appended to model.ec.enzymes/genes/mw/ sequence/concs,

  • a new column in model.ec.rxn_enz_mat.

Each new reaction with a non-empty GPR also gets:

  • an entry appended to model.ec.rxns (with kcat=0, source=""),

  • a new row in rxn_enz_mat with 1.0 in the columns of every gene in its (single, post-split) AND-clause.

Ported from GECKO MATLAB: src/geckomat/utilities/addNewRxnsToEC.m.

Parameters

model

Full EcModel (not gecko-light) with the protein pool / usage rxn machinery already installed. Mutated in place.

new_rxns

Reactions to add, as pre-built cobra.Reaction objects. Each must have stoichiometry, gene_reaction_rule, lower_bound, upper_bound set; build one from a string equation with cobra's Reaction.build_reaction_from_string if that's more convenient.

new_enzymes

Enzymes to add (one per UniProt ID). Enzymes already in model.ec.enzymes are silently skipped with a warning.

Returns

AddNewRxnsResult :

Raises

NotImplementedError

If model.ec.gecko_light is True.

ValueError

If a gene referenced in a new rxn's GPR is missing from both model.genes and new_enzymes.

AddNewRxnsResult#

IDs of what was actually added (after isozyme/reversibility

expansion and the dedupe of already-present enzymes).

Attributes

rxns_added

IDs of every cobra reaction actually added to the model, after isozyme (_EXP_<n>) and reversibility (_REV) expansion.

enz_added

UniProt IDs of the enzymes actually added (enzymes already present in model.ec.enzymes are excluded).

ec_fseof#

ec_fseof(model: 'EcModel', prod_target_rxn: str, cs_rxn: Optional[str]=None, *, n_steps: int=10, bio_rxn: Optional[str]=None, max_fraction: float=0.9, correlation_threshold: float=0.9, flux_eps: float=1e-06)

Run Flux-Scanning with Enforced Objective Function on an ecModel.

Enforces an increasing flux toward prod_target_rxn while optimising biomass, runs pFBA at each step, regresses every reaction's flux against the enforced product flux, and returns reactions with strong slope-vs-correlation signal as engineering targets.

Parameters

model

EcModel with the protein-pool / usage-rxn machinery.

prod_target_rxn

Reaction id for the production target (typically a product-exchange).

cs_rxn

Reaction id for the main carbon source. When passed, a warning is emitted if its lower bound is tighter than its uptake at biomass-max (a common mis-configuration). None skips the check.

n_steps

Number of enforced-flux levels in the scan. Default 10.

bio_rxn

Biomass reaction id. Defaults to adapter.params.bio_rxn when model.adapter is set.

max_fraction

Top of the scan range as a fraction of the theoretical maximum product flux. Default 0.9. The floor of the scan range is the production target's flux at biomass-optimum, not a fraction of this ceiling.

correlation_threshold

A reaction is a target when |corr(flux, enforced)| >= this value. Default 0.9.

flux_eps

Minimum |slope| (flux change per enforced-flux step) for a reaction to count as responsive; below this it is treated as flat regardless of correlation, so it cannot become a target. Default 1e-6.

Returns

FSEOFResult

raven-toolbox's FSEOF output dataclass, with usage_prot_* rows filtered out of both scan and targets. See raven_toolbox.analysis.fseof.FSEOFResult for the full field list (scan, enforced, targets, plus the amplification / knockout / gene_targets properties).

ec_fva#

ec_fva(ec_model: 'EcModel', model: 'cobra.Model', *, progress: bool=True, n_proc: Optional[int]=None)

Flux variability analysis on an ecModel, mapped to conventional rxns.

For each canonical reaction (after stripping _REV and _EXP_<N> suffixes), maximises and minimises the combined (forward minus reverse) flux of all its ec variants, and reports the combined flux at each of those two optima as the reaction's max and min — i.e. the exact per-reaction FVA bound (the "diagonal"), not the outer envelope obtained by reducing each ec variant across all reactions' solutions and summing.

Ported from GECKO MATLAB: src/geckomat/utilities/ecFVA.m.

Parameters

ec_model

EcModel with _REV and _EXP_<N> suffixes from expand_model and convert_to_irreversible.

model

The non-ec model to which the fluxes are mapped. Must be the same model that was used to build ec_model.

progress

Show a tqdm progress bar over the per-canonical-rxn LP solves. Defaults to True; set False to silence output.

n_proc

Number of worker processes. Defaults to cobra.Configuration().processes. Set to 1 to run the original serial path; values >= 2 parallelise via cobra.util.ProcessPool, the same pool cobrapy's own flux_variability_analysis/single_reaction_deletion use.

Returns

pandas.DataFrame

Index: rxn_id (in model.reactions order). Columns: min_flux, max_flux.

enzyme_usage#

enzyme_usage(model: 'EcModel', fluxes: Union[pd.Series, Mapping[str, float]], *, include_zero: bool=True)

Compute per-enzyme absolute and capacity usage from fluxes.

For each enzyme in model.ec.enzymes:

  • abs_usage = |fluxes[usage_prot_<enzyme>]| (mg/gDCW).

  • ub = the usage reaction's upper bound.

  • cap_usage = abs_usage / ub (or 0 if ub == 0).

Ported from GECKO MATLAB: src/geckomat/utilities/enzymeUsage.m.

Parameters

model

Full (non-light) EcModel with usage_prot_* reactions installed for every enzyme.

fluxes

Flux distribution. Typically solution.fluxes from model.optimize(); any dict-like keyed by rxn id works.

include_zero

When False, enzymes with zero absolute usage are dropped from the result.

Raises

NotImplementedError

If model.ec.gecko_light is True.

EnzymeUsageReport#

Two human-readable tables summarising enzyme usage.

Attributes

high_cap_usage

DataFrame of enzymes whose cap_usage exceeds the high_cap_usage threshold. For enzymes catalysing multiple flux-carrying reactions, a combined header row (with "===" placeholders) is followed by per-reaction breakdown rows.

top_abs_usage

DataFrame of the top-N enzymes by absolute usage. Same layout but with perc_usage (= abs_usage / total_pool * 100) replacing cap_usage.

total_usage_flux

The protein pool exchange capacity (mg/gDCW) used as the denominator for perc_usage.

EnzymeUsageResult#

Per-enzyme usage info from a flux distribution.

Attributes

prot_id

UniProt IDs (matching model.ec.enzymes order, modulo zero-usage filtering).

abs_usage

Absolute enzyme usage in mg/gDCW (= |flux through the usage_prot_<X> reaction|).

cap_usage

Capacity usage = abs_usage / ub. 0 for enzymes whose usage rxn upper bound is 0.

ub

Upper bound of each usage_prot_<X> reaction.

fluxes

The original input flux distribution (carried through for downstream use, e.g. by report_enzyme_usage).

get_enzyme_bottlenecks#

get_enzyme_bottlenecks(model: 'EcModel', *, top: int=10)

Top-N enzymes by absolute shadow price.

Solves the model, ranks enzymes by |shadow_price|, returns a DataFrame indexed by uniprot id with columns [gene, shadow_price, flux, cap_usage, upper_bound].

Ported from the legacy geckopy package (Carrasco et al., 2023, https://doi.org/10.1128/spectrum.01705-23), geckopy/flux_analysis.py:275-281.

Parameters

model

EcModel to solve.

top

Number of top-ranked enzymes to return. Default 10.

Returns

pandas.DataFrame

Indexed by uniprot id, columns [gene, shadow_price, flux, cap_usage, upper_bound], sorted by descending |shadow_price| and truncated to top rows.

Raises

RuntimeError

If the solve status is not optimal.

get_subset_ec_model#

get_subset_ec_model(big_ec_model: 'EcModel', small_gem: 'cobra.Model')

Trim big_ec_model to the gene/reaction set of small_gem.

Both models must have been derived from the same starting GEM. Reactions in small_gem are matched against canonicalised (suffix-stripped) reaction ids in big_ec_model; if any small_gem reaction is missing, the function raises.

Returns a fresh EcModel; the input big_ec_model is not mutated.

Algorithm (mirrors MATLAB):

  1. Copy big_ec_model.

  2. Compute genes to remove (big.genes minus small_gem.genes, preserving the standard pseudo-gene from assign_standard_kcat).

  3. Remove reactions blocked by that gene removal (cobra's GPR.eval(knockouts=...)).

  4. Remove the genes from model.genes.

  5. Trim the corresponding columns of model.ec.genes/enzymes/mw/sequence/concs/rxn_enz_mat.

  6. Remove reactions whose canonicalised id is not in small_gem.reactions, except usage_prot_* and prot_pool_exchange which are always preserved.

  7. Trim the corresponding rows of model.ec.rxns/kcat/source/notes/eccodes/rxn_enz_mat.

Ported from GECKO MATLAB: src/geckomat/utilities/getSubsetEcModel.m.

If any usage_prot_* reaction's upper bound differs from the default (1000), a warning is logged: protein-concentration constraints on big_ec_model may not carry over meaningfully to the subset.

Parameters

big_ec_model

The full ecModel covering many genes/reactions.

small_gem

The conventional (non-ec) context-specific model whose gene/reaction set is the target.

Returns

EcModel

A new ecModel restricted to small_gem's gene/reaction set, with the protein pool / usage rxn machinery preserved.

Raises

ValueError

If any reaction in small_gem is missing from big_ec_model (after suffix stripping).

load_conventional_gem#

load_conventional_gem(adapter: 'ModelAdapter')

Load the starting GEM file pointed to by adapter.

Parameters

adapter

A ModelAdapter whose params.conv_gem field gives the path to the GEM file. The path is used as-is; the adapter's loader has already resolved it relative to the adapter folder.

Returns

cobra.Model

The loaded model. Use it as the input to make_ec_model.

Raises

FileNotFoundError

If params.conv_gem doesn't point to an existing file.

load_ec_model#

load_ec_model(filename: Optional[Union[str, Path]]=None, adapter: Optional['ModelAdapter']=None)

Load an ecModel from a YAML file.

Parameters

filename

Path to the ecModel file. If None, defaults to ecModel.yml. Relative paths resolve against <adapter.params.path>/models/<filename>; absolute paths are used as-is and adapter may be None.

adapter

A ModelAdapter used to resolve a relative filename and attached to the loaded model as model.adapter. Required when filename is relative.

Returns

EcModel

The loaded ecModel with a populated model.ec. The gecko_light flag, ec arrays, and coupling matrix are all read from the file.

Raises

ValueError

If the extension isn't YAML, the filename is relative without an adapter, or the YAML lacks the GECKO ec-rxns / ec-enzymes sections (in which case it isn't an ecModel).

FileNotFoundError

If the resolved file doesn't exist.

map_rxns_to_conv#

map_rxns_to_conv(ec_model: 'EcModel', model: 'cobra.Model', flux_vect: Union[np.ndarray, pd.Series])

Translate ec-rxn fluxes back to conventional-rxn fluxes.

For each ec_model.reactions entry, the rxn id is canonicalised:

  • _REV suffix or _REV_EXP_ infix -> the flux is negated (reverse direction in geckopy convention) and the suffix stripped.

  • _EXP_<N> suffix -> stripped (isozyme split combined).

Fluxes belonging to the same canonical rxn id are summed, then reordered to match model.reactions. A separate output surfaces protein-usage fluxes (usage_prot_* and prot_pool_exchange) under their stripped labels.

Ported from GECKO MATLAB: src/geckomat/utilities/mapRxnsToConv.m.

Parameters

ec_model

The EcModel from which flux_vect was obtained.

model

The conventional (non-ec) model that ec_model was built from. model.reactions defines the output ordering.

flux_vect

Either a 1-D np.ndarray aligned to ec_model.reactions order, a 2-D np.ndarray with the same row order, or a pd.Series indexed by ec-rxn id (missing entries default to 0).

Returns

MapRxnsResult :

Raises

ValueError

If flux_vect is empty, has the wrong shape, or any conventional rxn ID is missing from the canonicalised set.

MapRxnsResult#

Output of mapping ec-rxn fluxes back to conventional rxns.

Attributes

mapped_flux

1-D or 2-D array of fluxes in the conventional model's model.reactions order. Same number of columns/scenarios as the input (1-D in / 1-D out; 2-D in / 2-D out).

enz_usage_flux

Fluxes of the protein-usage reactions (usage_prot_* and prot_pool_exchange), in usage_enz order.

usage_enz

Labels for enz_usage_flux: protein IDs for usage_prot_* rows, or "pool" for the exchange row.

NewEnzyme#

An enzyme to add alongside the new reactions.

Attributes

enzyme

UniProt ID. Used as the <X> in prot_<X> and usage_prot_<X>.

gene

Gene ID for model.genes and the usage rxn's GPR.

mw

Molecular weight (g/mmol) for model.ec.mw.

pfba_enzymes#

pfba_enzymes(model: 'EcModel', objective: Union[cobra.Reaction, str, None]=None, *, fraction_of_optimum: float=1.0)

Parsimonious FBA minimising the L1 norm of usage_prot_* fluxes.

Sets the objective (if given), fixes it at fraction_of_optimum * optimal_value, then minimises sum(usage_prot_*.forward_variable). Usage reactions are forward-only in the GECKO 3 layout (lb=0); if a user has flipped one to allow reverse flux, its reverse_variable is included automatically.

Ported from the legacy geckopy package (Carrasco et al., 2023, https://doi.org/10.1128/spectrum.01705-23), geckopy/flux_analysis.py:342-386.

Parameters

model

Full EcModel (not gecko-light) with usage_prot_* reactions installed.

objective

Reaction (or reaction id) to optimise before minimising enzyme usage. If None, the model's current objective is used as-is.

fraction_of_optimum

Fraction of the objective's optimal value to fix as a constraint before minimising enzyme usage. 1.0 (default) requires the biomass-optimal solution; a lower value trades some objective value for potentially lower enzyme usage.

Returns

cobra.Solution

Standard cobra solution over all reactions, at the flux distribution that minimises total (mass-weighted) enzyme usage subject to the objective constraint.

Raises

NotImplementedError

If model.ec.gecko_light is True.

ValueError

If model's objective is already the internal pfba_enzymes objective, indicating a nested call.

cobra.exceptions.OptimizationError

If minimising enzyme usage is infeasible at the requested fraction_of_optimum.

report_enzyme_usage#

report_enzyme_usage(model: 'EcModel', usage_data: 'EnzymeUsageResult', *, high_cap_usage: float=0.9, top_abs_usage: int=10)

Summarise enzyme usage as two DataFrames.

  1. High capacity: enzymes whose cap_usage exceeds high_cap_usage. The enzymes catalysing more than one flux-carrying reaction get a combined header row plus one detail row per reaction, where the detail rows split the absolute usage proportionally to -S[prot_<enzyme>, rxn] * flux[rxn]. Combined header rows use the literal "===" placeholder for non-applicable string fields and NaN for kcat.

  2. Top absolute: the top top_abs_usage enzymes by absolute usage, same shape but with perc_usage (a percent of prot_pool_exchange capacity) replacing cap_usage.

Ported from GECKO MATLAB: src/geckomat/utilities/reportEnzymeUsage.m.

Parameters

model

Full EcModel with the protein pool / usage rxn machinery.

usage_data

Result from enzyme_usage on the same model.

high_cap_usage

Capacity-usage threshold for the first report: enzymes whose cap_usage exceeds this fraction are included. Default 0.9 (90% of capacity).

top_abs_usage

Number of top enzymes for the second report. 0 or inf returns all enzymes. Default 10.

Returns

EnzymeUsageReport :

save_ec_model#

save_ec_model(model: EcModel, filename: Optional[Union[str, Path]]=None, adapter: Optional['ModelAdapter']=None)

Save an ecModel to a YAML file.

Parameters

model

The ecModel to save. Must have a populated model.ec (both ec.rxns and ec.enzymes non-empty). Empty ecModels are rejected because they're almost always a bug — you probably forgot to run make_ec_model first.

filename

Destination path. If None, defaults to ecModel.yml. Relative paths resolve against <adapter.params.path>/models/<filename>; absolute paths are used as-is.

adapter

Used to resolve a relative filename. Defaults to model.adapter. Required when filename is relative AND model.adapter is None.

Returns

Path

The absolute path of the file that was written.

Raises

ValueError

If model.ec is empty, if the file extension isn't YAML, or if the filename is relative and no adapter is available.