GERM models and analysis
MEWpy supports the integration of regulatory and metabolic models at the genome-scale.
All tools required to build, simulate, and analyze GEnome-scale Regulatory and Metabolic (GERM) models
are available in the mewpy.germ module.
A GERM model includes a standard Genome-Scale Metabolic (GEM) model. The GEM model comprehends reactions (w/ GPRs), metabolites and genes. It also includes exchange reactions defining the environmental conditions of the system. In addition, GERM models include Transcriptional Regulatory Networks (TRNs). A TRN comprehends interactions (w/ boolean algebra expressions), target genes and regulators. It also includes external stimuli (effectors), regulatory metabolites, and regulatory reactions. GEM models and TRNs are often linked by the target genes of the TRN and the genes of the GEM model.
MEWpy supports several methods to perform phenotype simulations using integrated GERM models.
The following simulation methods are available in mewpy.germ.analysis module:
FBA- Metabolic model onlypFBA- Metabolic model onlyRFBA- Regulatory-Metabolic modelSRFBA- Regulatory-Metabolic modelPROM- Regulatory-Metabolic modelCoRegFlux- Regulatory-Metabolic model

Reading GERM models
In this example, we will be using the integrated E. coli core model published by Orth et al, 2010.
E. coli integrated model is available in two separate files:
metabolic model examples/models/germ/e_coli_core.xml
regulatory model examples/models/germ/e_coli_core_trn.csv
To assemble an integrated GERM model, we use mewpy.io.read_model function.
This function accepts multiple readers having different engines.
MEWpy contains the following engines that can be used in the Reader object:
BooleanRegulatoryCSV- reads a TRN from a CSV file - regulatory interactions:target, (regulator1 and regulator2)CoExpressionRegulatoryCSV- reads a TRN from a CSV file - regulatory interactions:target, co-activator1 co-activator2, co-repressor2TargetRegulatorRegulatoryCSV- reads a TRN from a CSV file - regulatory interactions:target, regulator1RegulatorySBML- reads a TRN from a SBML file using the SBML-QUAL pluginMetabolicSBML- reads a GEM from a SBML fileCobraModel- reads a GEM from a COBRApy modelReframedModel- reads a GEM from a Reframed modelJSON- reads a GERM model from a JSON file
In addition, the Reader accepts other arguments such as the filename, sep, among others.
from mewpy.io import Reader, Engines, read_model
# a reader for the E. coli core GEM model
gem_reader = Reader(Engines.MetabolicSBML, 'e_coli_core.xml')
# a reader for the E. coli core TRN model
# (it accepts specific parameters for reading the TRN CSV file)
trn_reader = Reader(Engines.BooleanRegulatoryCSV, 'e_coli_core_trn.csv',
sep=',', id_col=0, rule_col=2, aliases_cols=[1], header=0)
# reading the integrated regulatory-metabolic model
model = read_model(gem_reader, trn_reader)
model
| Model | e_coli_core |
|---|---|
| Name | E. coli core model - Orth et al 2010 |
| Types | regulatory, metabolic |
| Compartments | e, c |
| Reactions | 95 |
| Metabolites | 72 |
| Genes | 137 |
| Exchanges | 20 |
| Demands | 0 |
| Sinks | 0 |
| Objective | Biomass_Ecoli_core |
| Regulatory interactions | 159 |
| Targets | 159 |
| Regulators | 45 |
| Regulatory reactions | 12 |
| Regulatory metabolites | 11 |
| Environmental stimuli | 0 |
Although mewpy.io.read_model function is the preferred interface for reading models, MEWpy contains other read/write methods available at mewpy.io.
Working with GERM models
A GERM model contains the following metabolic information:
objective- variable/coefficient dictionaryreactions- identifier/reaction dictionarymetabolites- identifier/metabolite dictionarygenes- identifier/gene dictionarygprs- identifier/GPR expression dictionarycompartments- identifier/compartment dictionaryexchanges- identifier/reaction dictionarydemands- identifier/reaction dictionarysinks- identifier/reaction dictionaryexternal_compartment- Compartment with most exchange reactions
A GERM model contains the following regulatory information:
interactions- identifier/interaction dictionarytargets- identifier/target dictionaryregulators- identifier/regulator dictionaryregulatory_reactions- identifier/reaction dictionaryregulatory_metabolites- identifier/metabolite dictionaryenvironmental_stimuli- identifier/regulator dictionary
One can inspect model attributes in Jupyter notebooks:
# read E. coli core model
from mewpy.io import Reader, Engines, read_model
gem_reader = Reader(Engines.MetabolicSBML, 'e_coli_core.xml')
trn_reader = Reader(Engines.BooleanRegulatoryCSV, 'e_coli_core_trn.csv',
sep=',', id_col=0, rule_col=2, aliases_cols=[1], header=0)
model = read_model(gem_reader, trn_reader)
model.objective
{Biomass_Ecoli_core || 1.496 3pg_c + ...
model.reactions
'ACALDt': ACALDt || 1.0 acald_e <-> 1.0 acald_c,
'ACKr': ACKr || 1.0 ac_c + 1.0 atp_c <-> 1.0 actp_c + 1.0 adp_c,
'ACONTa': ACONTa || 1.0 cit_c <-> 1.0 acon_C_c + 1.0 h2o_c,
'ACONTb': ACONTb || 1.0 acon_C_c + 1.0 h2o_c <-> 1.0 icit_c,
'ACt2r': ACt2r || 1.0 ac_e + 1.0 h_e <-> 1.0 ac_c + 1.0 h_c,
'ADK1': ADK1 || 1.0 amp_c + 1.0 atp_c <-> 2.0 adp_c,
'AKGDH': AKGDH || 1.0 akg_c + 1.0 coa_c + 1.0 nad_c -> 1.0 co2_c + 1.0 nadh_c + 1.0 succoa_c,
...
model.interactions
'b0080_interaction': b0080 || 1 = ( ~ surplusFDP),
'b0113_interaction': b0113 || 1 = ( ~ surplusPYR),
'b0114_interaction': b0114 || 1 = (( ~ b0113) | b3261),
'b0115_interaction': b0115 || 1 = (( ~ b0113) | b3261),
...
A GERM model container is a regular Python dictionary. They can be used to access variables in the model (e.g.,
model.reactions['MY_REACTION']).
One can also yield variables from the model using yield_...-like methods, such as model.yield_regulators().
# get PDH reaction from the model
pdh = model.reactions['PDH']
pdh
| Identifier | PDH |
|---|---|
| Name | |
| Aliases | |
| Model | e_coli_core |
| Types | reaction |
| Equation | 1.0 coa_c + 1.0 nad_c + 1.0 pyr_c -> 1.0 accoa_c + 1.0 co2_c + 1.0 nadh_c |
| Bounds | (0.0, 1000.0) |
| Reversibility | False |
| Metabolites | coa_c, nad_c, pyr_c, accoa_c, co2_c, nadh_c |
| Boundary | False |
| GPR | (b0115 & b0114 & b0116) |
| Genes | b0115, b0114, b0116 |
| Compartments | c |
| Charge balance | {'reactants': 6.0, 'products': -6.0} |
| Mass balance | {'C': 0.0, 'H': 0.0, 'N': 0.0, 'O': 0.0, 'P': 0.0, 'S': 0.0} |
# iterate over regulators
for regulator in model.yield_regulators():
print(regulator)
break
b0113 || (0.0, 1.0)
NOTE
It is possible to add variables to the model dictionaries (e.g., model.reactions['MY_REACTION'] = my_reaction),
but this is not recommended. The model dictionaries are used to keep track of the model variables
and should not be modified directly.
To add or remove variables, use the model.add() and model.remove() methods documented bellow. These methods
will perform the required updates in the model.
GERM model operations
A GERM model supports the following operations:
get(identifier, default=None)- It retrieves the variable using its identifieradd(variables)- It adds new variables to the model; variables will be added to model containers according to their typesremove(variables)- It removes variables from the model; variables will be removed from model containers according to their typesupdate(variables, objective, ...)- It updates variables, compartments, objective, etc, in the modelcopy()- It makes a shallow copy of the modeldeepcopy()- It makes a deep copy of the modelto_dict()- It exports the model to a dictionary
# get the Crp regulator
crp = model.get('b3357')
crp
| Identifier | b3357 |
|---|---|
| Name | b3357 |
| Aliases | b3357, Crp |
| Model | e_coli_core |
| Types | regulator, target |
| Coefficients | (0.0, 1.0) |
| Active | True |
| Interactions | b0721_interaction, b0722_interaction, b0723_interaction, b0724_interaction, b0902_interaction, b0903_interaction, b0904_interaction, b1524_interaction, b2492_interaction, b3114_interaction, b3115_interaction, b3870_interaction, b4122_interaction |
| Targets | b0721, b0722, b0723, b0724, b0902, b0903, b0904, b1524, b2492, b3114, b3115, b3870, b4122 |
| Environmental stimulus | False |
| Interaction | b3357 || 1 = CRPnoGLC |
| Regulators | CRPnoGLC |
# remove the regulator from the model
model.remove(crp)
'b3357' in model.regulators
False
# add the regulator back to the model
model.add(crp)
'b3357' in model.regulators
True
# shallow copy only performs a copy of the containers
model_copy = model.copy()
print(model is model_copy)
# but variables are still the same
crp is model_copy.regulators['b3357']
# deep copy performs a copy of the containers and variables
model_copy = model.deepcopy()
crp is model_copy.regulators['b3357']
False
True
False
# export the model to a dictionary
model.to_dict()
A GERM model supports temporary changes using the with model context manager.
In addition, one can manually undo() and redo() the last operations or reset() and restore() a GERM model.
# make a temporary change to the model
pfk = model.get('PFK')
with model:
model.remove(pfk)
print('Is PFK in the model?', 'PFK' in model.reactions)
print('Has PFK removal been reverted?', 'PFK' in model.reactions)
Is PFK in the model? False
Has PFK removal been reverted? True
A GERM model is by default a multi-type model. This means that one can manipulate both a metabolic and regulatory model at the same time. Alternatively, one can manipulate a single regulatory or metabolic model.
MEWpy allows building single- or multi-type models easily:
from mewpy.germ.models import RegulatoryModel
# creating a new regulatory model
reg_model = RegulatoryModel(identifier='my_regulatory_model')
reg_model
| Model | my_regulatory_model |
|---|---|
| Name | my_regulatory_model |
| Types | regulatory |
| Compartments | |
| Regulatory interactions | 0 |
| Targets | 0 |
| Regulators | 0 |
| Regulatory reactions | 0 |
| Regulatory metabolites | 0 |
| Environmental stimuli | 0 |
# check if the model is metabolic
reg_model.is_metabolic()
False
from mewpy.germ.models import Model
pfk = model.get('PFK').deepcopy()
# using types model constructor
met_model = Model.from_types(('metabolic', ),
identifier='my_metabolic_model',
reactions={'pfk': pfk})
met_model
| Model | my_metabolic_model |
|---|---|
| Name | my_metabolic_model |
| Types | metabolic |
| Compartments | |
| Reactions | 1 |
| Metabolites | 5 |
| Genes | 2 |
| Exchanges | 0 |
| Demands | 0 |
| Sinks | 0 |
| Objective | None |
Working with GERM model variables
MEWpy includes the following metabolic and regulatory variables:
Reaction- Object to represent metabolic reactions having bounds, stoichiometry (metabolite/coefficient) and GPRsMetabolite- Object to represent metabolic compounds having charge, compartment, formula and reactionsGene- Object to represent metabolic genes having coefficients and reactions (found in GPR expressions)Interaction- Object to represent regulatory interactions having a target and associated regulatory events (coefficient/boolean rule)Target- Object to represent regulatory targets having coefficients and interactionRegulator- Object to represent regulatory having coefficients and interactions
Variables have different attributes that can be inspected and changed. Variables are often connected to other variables and have special attributes, such as boolean expressions, coefficients and dictionaries of metabolites (stoichiometry).
All GERM model variables support:
copy()- It makes a shallow copy of the modeldeepcopy()- It makes a deep copy of the modelTemporary changes using
with,undo(),redo(),reset(),restore(),yield linked variables, such as
yield_metabolites()
Reactions, Metabolites and Genes
Reactions have the following attributes:
identifier - id of the variable
name - name of the variable
aliases - aliases of the variable
bounds - reaction bounds; it must be a tuple with both values; (-1000, 1000) by default
lower_bound - reaction lower bound
upper_bound - reaction upper bound
reversibility - whether the reaction is reversible
stoichiometry - reaction stoichiometry; a dictionary of metabolite variable-coefficient
gpr - a symbolic expression containing the boolean logic of the gene variables; AND (symbolic &); OR (symbolic |)
gene_protein_reaction_rule - symbolic representation of the GPR expression
metabolites - reaction metabolites; a dictionary of metabolite identifier-metabolite variable
reactants - reaction reactants; a dictionary of metabolite identifier-metabolite variable
products - reaction products; a dictionary of metabolite identifier-metabolite variable
compartments - all compartments associated with the reaction metabolites
boundary - whether the reaction is exchange, demand or sink
equation - notation with reactants, products and reversibility
charge_balance - charge balance of the reaction
mass_balance - mass balance of the reaction
and the following methods:
ko()- reaction deletion; it sets the bounds to zeroadd_metabolites(stoichiometry)- add metabolites to the reactionremove_metabolites(metabolite)- remove metabolites from the reactionadd_gpr(gpr)- add/replacing gpr to the reactionremove_gpr()- remove gpr from the reaction
Metabolites have the following attributes:
identifier - id of the variable
name - name of the variable
aliases - aliases of the variable
charge - metabolite charge
compartment - metabolite compartment
formula - metabolite chemical formula
atoms - frequency of each atom in the chemical formula
molecular_weight - metabolite molecular weight
exchange_reaction - the first exchange reaction associated with the metabolite
exchange_reactions - the list of all exchange reactions associated with the metabolite
reactions - the reactions associated with this metabolite; a dictionary of reaction identifier-reaction variable
Genes have the following attributes:
identifier - id of the variable
name - name of the variable
aliases - aliases of the variable
coefficients - the gene coefficients; all possible values that a gene can take during GPR evaluation; (0, 1) by default
is_active - whether the maximum coefficient is bigger than zero
reactions - the reactions associated with this gene; a dictionary of reaction identifier-reaction variable
and the following methods:
ko()- gene deletion; it sets the coefficients to zero
Bold-italicized properties can be set with new values (e.g., reaction.bounds = (0, 1000)).
# read E. coli core model
from mewpy.io import Reader, Engines, read_model
gem_reader = Reader(Engines.MetabolicSBML, 'e_coli_core.xml')
trn_reader = Reader(Engines.BooleanRegulatoryCSV, 'e_coli_core_trn.csv',
sep=',', id_col=0, rule_col=2, aliases_cols=[1], header=0)
model = read_model(gem_reader, trn_reader)
# inspecting a reaction
ack = model.get('ACKr')
ack
| Identifier | ACKr |
|---|---|
| Name | |
| Aliases | |
| Model | e_coli_core |
| Types | reaction |
| Equation | 1.0 ac_c + 1.0 atp_c <-> 1.0 actp_c + 1.0 adp_c |
| Bounds | (-1000.0, 1000.0) |
| Reversibility | True |
| Metabolites | ac_c, atp_c, actp_c, adp_c |
| Boundary | False |
| GPR | (b2296 | b3115 | b1849) |
| Genes | b2296, b3115, b1849 |
| Compartments | c |
| Charge balance | {'reactants': 5.0, 'products': -5.0} |
| Mass balance | {'C': 0.0, 'H': 0.0, 'O': 0.0, 'N': 0.0, 'P': 0.0} |
One can create Reactions, Metabolites and Genes using the objects mentioned above.
# imports
from mewpy.germ.algebra import Expression, parse_expression
from mewpy.germ.variables import Reaction, Metabolite, Gene
# creating the Genes
g1 = Gene(identifier='b4067', name='actP', coefficients=(0, 1))
g2 = Gene(identifier='b0010', name='satP', coefficients=(0, 1))
# Creating the GPR. A GPR is a boolean algebra expression
boolean_rule = parse_expression('b4067 and b0010')
genes = {'b4067': g1, 'b0010': g2}
gpr = Expression(symbolic=boolean_rule, variables=genes)
# creating the metabolites
m1 = Metabolite(identifier='ac_c', name='acetate cytoplasm', compartment='c', formula='C2H3O2', charge=-1)
m2 = Metabolite(identifier='ac_e', name='acetate extracellular', compartment='e', formula='C2H3O2', charge=-1)
# creating the reaction
stoichiometry = {m1: -1, m2: 1}
rxn = Reaction(identifier='ac_t',
name='acetate transport',
bounds=(0, 1000),
stoichiometry=stoichiometry,
gpr=gpr)
rxn
| Identifier | ac_t |
|---|---|
| Name | acetate transport |
| Aliases | |
| Model | None |
| Types | reaction |
| Equation | 1 ac_c -> 1 ac_e |
| Bounds | (0, 1000) |
| Reversibility | False |
| Metabolites | ac_c, ac_e |
| Boundary | False |
| GPR | (b4067 & b0010) |
| Genes | b4067, b0010 |
| Compartments | c, e |
| Charge balance | {'reactants': 1, 'products': -1} |
| Mass balance | {'C': 0, 'H': 0, 'O': 0} |
Reactions can be created automatically from GPRs in a string format. This avoids creating GPR expressions manually using the boolean expression parser. Note that, Genes are also created automatically using the identifiers in the string.
# from a GPR string
rxn3 = Reaction.from_gpr_string(identifier='ac_t2',
name='a second reaction for acetate transport having different genes',
rule='b0001 and b0002',
bounds=(0, 1000),
stoichiometry=stoichiometry)
A Reaction’s GPR is a boolean algebra expression that can be evaluated using regular boolean operators or custom operators (useful to evaluate gene expression data).
# gpr is a boolean algebra expression that can be evaluated
rxn3.gpr.evaluate(values={'b0001': 1, 'b0002': 1})
True
from mewpy.germ.algebra import And
# using a custom operator for AND
rxn3.gpr.evaluate(values={'b0001': 100, 'b0002': 50}, operators={And: min})
50
Interactions, Targets and Regulators
Interactions have the following attributes:
identifier - id of the variable
name - name of the variable
aliases - aliases of the variable
target - interaction target; Interactions can only have a single target gene!
regulatory_events - a dictionary of coefficient-symbolic expressions. The symbolic expressions contain the boolean logic of regulators to activate or not the target gene; the key of a regulatory event is the expression coefficient that the target can take if the expression is evaluated to True.
regulators - interaction regulators; a dictionary of regulator identifier-regulator variable
regulatory_truth_table - a table with the possible coefficients of the target variable according to the regulatory events and regulators’ coefficients
and the following methods:
add_target(target)- add the target to the interaction. It removes the current target.remove_target(target)- remove the target from the interaction.add_regulatory_event(coefficient, expression)- add a new regulatory event for a target coefficient. It removes the current coefficient if available.remove_regulatory_event(coefficient)- remove the regulatory event for the target coefficient.
Targets have the following attributes:
identifier - id of the variable
name - name of the variable
aliases - aliases of the variable
coefficients - the target coefficients; all possible values that a target can take during expression evaluation; (0, 1) by default
is_active - whether the maximum coefficient is bigger than zero
interaction - the target interaction.
regulators - target regulators; a dictionary of regulator identifier-regulator variable
and the following methods:
ko()- target deletion; it sets the coefficients to zero
Regulators have the following attributes:
identifier - id of the variable
name - name of the variable
aliases - aliases of the variable
coefficients - the regulator coefficients; all possible values that a regulator can take during expression evaluation; (0, 1) by default
is_active - whether the maximum coefficient is bigger than zero
interactions - regulator interactions; a dictionary of interaction identifier-interaction variable
targets - regulator targets; a dictionary of target identifier-target variable
and the following methods:
ko()- regulator deletion; it sets the coefficients to zero
Bold-italicized properties can be set with new values (e.g., regulator.coefficients = (1,)).
# inspecting an interaction
sdhc_interaction = model.get('b0721_interaction')
sdhc_interaction
| Identifier | b0721_interaction |
|---|---|
| Name | b0721_interaction |
| Aliases | b0721 |
| Model | e_coli_core |
| Types | interaction |
| Target | b0721 || 1 = (( ~ (b4401 | b1334)) | b3357 | b3261) |
| Regulators | b4401, b1334, b3357, b3261 |
| Regulatory events | 1 = (( ~ (b4401 | b1334)) | b3357 | b3261) |
The regulatory truth table is a table with the possible coefficients of the target variable according to the regulatory events and regulators’ coefficients.
# inspecting the regulatory truth table
sdhc_interaction.regulatory_truth_table
| result | b4401 | b1334 | b3357 | b3261 | |
|---|---|---|---|---|---|
| b0721 | 0 | NaN | NaN | NaN | NaN |
| b0721 | 1 | 1.0 | 1.0 | 1.0 | 1.0 |
One can create Interactions, Targets and Regulators using the objects mentioned above.
# imports
from mewpy.germ.algebra import Expression, parse_expression
from mewpy.germ.variables import Target, Interaction, Regulator
# creating the regulators
b0001 = Regulator(identifier='b0001', name='thrL', coefficients=(0, 1))
b0002 = Regulator(identifier='b0002', name='thrA', coefficients=(0, 1))
# creating the target
b0003 = Target(identifier='b0003', name='thrB', coefficients=(0, 1))
# creating a regulatory event
b0003_expression = Expression(symbolic=parse_expression('b0002 and not b0001'),
variables={'b0001': b0001, 'b0002': b0002})
# creating the interaction
# it is always a good practice to build the expression of a given interaction first, and then use it in the
# Interaction constructor. Otherwise, interaction has alternative constructors (from_expression or from_string)
b0003_interaction = Interaction(identifier='interaction_b0003',
regulatory_events={1.0: b0003_expression},
target=b0003)
b0003_interaction
| Identifier | interaction_b0003 |
|---|---|
| Name | |
| Aliases | |
| Model | None |
| Types | interaction |
| Target | b0003 || 1.0 = (b0002 & ( ~ b0001)) |
| Regulators | b0001, b0002 |
| Regulatory events | 1.0 = (b0002 & ( ~ b0001)) |
Interactions can be created automatically from a regulatory rule in a string format. This avoids creating regulatory expressions manually using the boolean expression parser. Note that, Regulators are also created automatically using the identifiers in the string.
b0004 = Target(identifier='b0004')
# creating an interaction from string. Note that propositional logic is also accepted
b0004_interaction = Interaction.from_string(identifier='b0004_interaction',
name='interaction from string creates new genes',
rule='(b0005 and b0006) or (b0007 > 0)',
target=b0004)
b0004_interaction
| Identifier | b0004_interaction |
|---|---|
| Name | interaction from string creates new genes |
| Aliases | |
| Model | None |
| Types | interaction |
| Target | b0004 || 1.0 = ((b0005 & b0006) | (b0007 > 0)) |
| Regulators | b0005, b0006, b0007 |
| Regulatory events | 1.0 = ((b0005 & b0006) | (b0007 > 0)) |
One can change the outcome of a regulatory expression by changing the coefficients of the regulators.
# changing the regulatory expression by altering the regulators coefficients
b0005 = b0004_interaction.regulators['b0005']
b0005.coefficients = (0,)
b0007 = b0004_interaction.regulators['b0007']
b0007.coefficients = (0,)
b0004_interaction.regulatory_truth_table
| b0005 | b0006 | b0007 | result | |
|---|---|---|---|---|
| b0004 | 0 | 1.0 | 0 | 0 |
It is also possible to evaluate the regulatory expression with different coefficients without changing the regulators’ coefficients.
# evaluating the regulatory expression with different regulators coefficients
# (it does not change the regulators coefficients though)
b0004_expression = b0004_interaction.regulatory_events.get(1)
b0004_expression.evaluate(values={'b0005': 1})
1
A GERM model variable is by default a multi-type variable. Integrated models often include multi-type variables representing simultaneously regulators and metabolites or targets and metabolic genes, among others. A single GERM model variable can store the information of a multi-type variable. For instance, a single variable object can share attributes and methods of a metabolite and regulator. More importantly, genes associated with reactions in a metabolic model often correspond to target genes having a regulatory interaction in the regulatory model.
MEWpy builds multi-type variables when reading GERM models.
One can check variable.types or use type checkers, such as variable.is_regulator().
# access to a reaction and find all regulators associated
pdh = model.get('PDH')
pdh_regulators = []
for gene in pdh.yield_genes():
if gene.is_target():
pdh_regulators.extend(gene.yield_regulators())
print('PDH regulators: ', ', '.join(reg.id for reg in pdh_regulators))
PDH regulators: b0113, b3261, b0113, b3261
from mewpy.germ.variables import Variable
# one can create multi-type variables as follows
Variable.from_types(types=('target', 'gene'), identifier='b0001')
Working with GERM model analysis
In the mewpy.germ.analysis module, simulation methods are derived from LinearProblem.
A phenotype simulation method includes the following attributes:
method- the name of the simulation methodmodel- the model used to build the linear problemsolver- a MEWpy solver instance having the linear programming implementation of variables and constraints in the selected solver. The following solvers are available: CPLEX; GUROBI; OPTLANGconstraints- The representation of ODE to be implemented in the solver instance using linear programmingvariables- The representation of the system variables to be implemented in the solver instance using linear programmingobjective- A linear representation of the objective function associated with the linear problem
And the following methods:
build- the build method is responsible for retrieving variables and constraints from a GERM model according to the mathematical formulation of each simulation methodoptimize- the optimize method is responsible for solving the linear problem using linear programming or mixed-integer linear programming. This method accepts method-specific arguments (initial state, dynamic, etc) and solver-specific arguments (linear, minimize, constraints, get_values, etc). These arguments can override temporarily some constraints or variables during the optimization.
from mewpy.io import Reader, Engines, read_model
from mewpy.germ.analysis import SRFBA
# reading the E. coli core model
core_gem_reader = Reader(Engines.MetabolicSBML, 'e_coli_core.xml')
core_trn_reader = Reader(Engines.BooleanRegulatoryCSV,
'e_coli_core_trn.csv', sep=',', id_col=0, rule_col=2, aliases_cols=[1], header=0)
model = read_model(core_gem_reader, core_trn_reader)
# initialization does not build the model automatically
srfba = SRFBA(model).build()
srfba
| Method | SRFBA |
| Model | Model e_coli_core - E. coli core model - Orth et al 2010 |
| Variables | 486 |
|---|---|
| Constraints | 326 |
| Objective | {'Biomass_Ecoli_core': 1.0} |
| Solver | CplexSolver |
| Synchronized | True |
The optimize interface creates a ModelSolution output by default containing the objective value,
value of each variable in the solution, among others.
Alternatively, optimize can create a simple solver Solution object.
# optimization creates a ModelSolution object by default
solution = srfba.optimize()
solution
| Method | SRFBA |
| Model | Model e_coli_core - E. coli core model - Orth et al 2010 |
| Objective | Biomass_Ecoli_core |
|---|---|
| Objective value | 0.8739215069684986 |
| Status | optimal |
One can generate a pandas DataFrame using the to_frame() method of the ModelSolution object.
This DataFrame includes coefficients of regulatory environmental stimuli linked to the exchange fluxes.
# a solution can be converted into a df
solution.to_frame()
One can generate a Summary object using the to_summary() method of the ModelSolution object.
This summary contains the following data:
inputs- regulatory and metabolic inputs of the solutionoutputs- regulatory and metabolic inputs of the solutionmetabolic- values of the metabolic variablesregulatory- values of the regulatory variablesobjective- the objective valuedf- the summary of inputs and outputs in the regulatory and metabolic layers
# a solution can be converted into a summary solution
summary = solution.to_summary()
# inputs + outputs of the regulatory-metabolic variables
summary.df
# values of the metabolic variables
summary.metabolic
# values of the regulatory variables
summary.regulatory
All phenotype simulation methods have a fast one-line code function to run the simulation. These functions return only the objective value of the solution.
from mewpy.germ.analysis import slim_fba
# using slim FBA analysis
slim_fba(model)
0.8739215069684303
MEWpy phenotype simulation using GERM models
FBA and pFBA are also available in MEWpy’s Simulator,
which is the common interface to perform simulations using GERM models, COBRApy models, and Reframed models
(see Phenotype Simulation section).
from mewpy.simulation import get_simulator
# using MEWpy simulator
simulator = get_simulator(model)
simulator.simulate()
objective: 0.8739215069684303
Status: OPTIMAL
Constraints: OrderedDict()
Method: SimulationMethod.FBA
GERM model and phenotype simulation workflow
A phenotype simulation method must be initialized with a GERM model. A common workflow to work with GERM models and simulation methods is suggested as follows:
model = read_model(reader1, reader2)- read the modelrfba = RFBA(model)- initialize the simulation methodrfba.build()- build the linear problemsolution = rfba.optimize()- perform the optimizationmodel.reactions['MY_REACTION'].bounds = (0, 0)- make changes to the modelsolution = RFBA(model).build().optimize()- initialize, build and optimize the simulation method
In this workflow, model and rfba instances are not synchronized, as rfba’s optimization will generate the same output even if we make changes to the model.
To address the latest changes in the model, one must initialize, build and optimize RFBA again.
A different workflow consists of attaching phenotype simulation methods to GERM models as follows:
model = read_model(reader1, reader2)- read the modelrfba = RFBA(model, attach=True)- initialize the simulation method and attach it to the modelrfba.build()- build the linear problemsolution = rfba.optimize()- perform the optimizationmodel.reactions['MY_REACTION'].bounds = (0, 0)- make changes to the modelrxn_ko_solution = rfba.optimize()- perform the optimization again but this time with the reaction deletion
The second workflow is simpler and should be used for minor changes in the model. In this workflow, rfba’s optimizations will use the latest state of the model.
# First workflow: build and optimize
srfba = SRFBA(model).build()
solution = srfba.optimize()
print('Wild-type growth rate', solution.objective_value)
# making changes (temporarily) and then build, optimize
with model:
model.regulators['b3261'].ko()
srfba = SRFBA(model).build()
solution = srfba.optimize()
print('KO growth rate', solution.objective_value)
Wild-type growth rate 0.8739215069684303
KO growth rate 1e-10
# second workflow build and optimize
srfba = SRFBA(model, attach=True).build()
solution = srfba.optimize()
print('Wild-type growth rate', solution.objective_value)
# applying the knockout and optimize (no build required)
with model:
model.regulators['b3261'].ko()
solution = srfba.optimize()
print('KO growth rate', solution.objective_value)
Wild-type growth rate 0.8739215069684986
KO growth rate 1e-10
In addition, one can attach as many simulation methods as needed to a single model instance. This behavior eases the comparison between simulation methods.
# many simulation methods attached
fba = FBA(model, attach=True).build()
pfba = pFBA(model, attach=True).build()
rfba = RFBA(model, attach=True).build()
# applying the knockout
model.regulators['b3261'].ko()
print('FBA KO growth rate:', fba.optimize().objective_value)
print('pFBA KO sum of fluxes:', pfba.optimize().objective_value)
print('RFBA KO growth rate:', rfba.optimize().objective_value)
print('SRFBA KO growth rate:', srfba.optimize().objective_value)
print()
# restore the model
model.undo()
print('FBA WT growth rate:', fba.optimize().objective_value)
print('pFBA WT sum of fluxes:', pfba.optimize().objective_value)
print('RFBA WT growth rate:', rfba.optimize().objective_value)
print('SRFBA WT growth rate:', srfba.optimize().objective_value)
FBA KO growth rate: 0.8739215069684303
pFBA KO sum of fluxes: 93768.8478640836
RFBA KO growth rate: 0.8513885233462081
SRFBA KO growth rate: 1e-10
FBA WT growth rate: 0.8739215069684303
pFBA WT sum of fluxes: 93768.8478640836
RFBA WT growth rate: 0.8513885233462081
SRFBA WT growth rate: 0.8739215069684986
FBA and pFBA
FBA and pFBA are both available in the mewpy.germ.analysis package.
Alternatively, one can use the simple and optimized versions slim_fba and slim_pfba.
from mewpy.io import Reader, Engines, read_model
from mewpy.germ.analysis import FBA
# reading the E. coli core model
core_gem_reader = Reader(Engines.MetabolicSBML, 'e_coli_core.xml')
model = read_model(core_gem_reader)
# using FBA analysis
FBA(model).build().optimize()
| Method | FBA |
| Model | Model e_coli_core - E. coli core model - Orth et al 2010 |
| Objective | Biomass_Ecoli_core |
|---|---|
| Objective value | 0.8739215069684303 |
| Status | optimal |
# using pFBA analysis
pFBA(model).build().optimize().objective_value
93768.8478640836
FVA and deletions
The mewpy.germ.analysis module includes FVA method to inspect the solution space of a GEM model.
This module also includes single_gene_deletion and single_reaction_deletion methods to inspect
in silico genetic strategies.
These methods perform an FBA phenotype simulation of a single reaction deletion or gene knockout
for all reactions and genes in the metabolic model.
These methods are faster than iterating through the model reactions or genes using the ko() method.
from mewpy.io import Reader, Engines, read_model
from mewpy.germ.analysis import fva, single_gene_deletion, single_reaction_deletion
# reading the E. coli core model
core_gem_reader = Reader(Engines.MetabolicSBML, 'e_coli_core.xml')
model = read_model(core_gem_reader)
# FVA returns the DataFrame with minium and maximum values of each reaction
fva(model)
# single reaction deletion
single_reaction_deletion(model)
# single gene deletion for specific genes
single_gene_deletion(model, genes=model.reactions['ACONTa'].genes)
| growth | status | |
|---|---|---|
| b0118 | 0.873922 | Optimal |
| b1276 | 0.873922 | Optimal |
Regulatory truth table
The regulatory truth table evaluates all regulatory interactions using their regulatory events (expressions).
A regulatory expression is a boolean expression that evaluates to 1 or 0 depending on the regulatory state.
mewpy.germ.analysis.regulatory_truth_table creates a pandas DataFrame having regulators’ values in the columns
and targets’ outcome in the index.
from mewpy.io import Reader, Engines, read_model
from mewpy.germ.analysis import regulatory_truth_table
# reading the E. coli core model
core_trn_reader = Reader(Engines.BooleanRegulatoryCSV,
'e_coli_core_trn.csv', sep=',', id_col=0, rule_col=2, aliases_cols=[1], header=0)
model = read_model(core_trn_reader)
# regulatory truth table for the regulatory model
model = read_model(core_trn_reader)
regulatory_truth_table(model)
RFBA
RFBA is a phenotype simulation method based on the integration of a GEM model with a TRN at the genome-scale.
RFBA performs first a synchronous evaluation of all regulatory interactions in the regulatory model.
This simulation is used to retrieve the regulatory state (regulators’ coefficients).
Then, the regulatory state is translated into a metabolic state (metabolic genes’ coefficients)
by performing a second synchronous evaluation of all regulatory interactions in the regulatory model.
Finally, the resulting metabolic state is used to decode metabolic constraints upon evaluation of the reactions’ GPRs
with the targets’ state.
RFBA supports steady-state or dynamic phenotype simulations.
Dynamic RFBA simulation performs sequential optimizations while the regulatory state is updated each time
using the reactions and metabolites coefficients of the previous optimization.
Dynamic RFBA simulation stops when two identical solutions are found.
RFBA is available in the mewpy.germ.analysis package.
Alternatively, one can use the simple and optimized version slim_rfba.
For more details consult: https://doi.org/10.1038/nature02456.
In this example we will be using E. coli iMC1010 model available at examples/models/germ/iJR904_srfba.xml and examples/models/germ/iMC1010.csv
The integrated E. coli iMC1010 model was published by Covert et al, 2004. This model consists of the E. coli iJR904 GEM model published by Reed et al, 2003 and E. coli iMC1010 TRN published by Covert et al, 2004. This model includes 904 metabolic genes, 931 unique biochemical reactions, and a TRN having 1010 regulatory interactions (target-regulators using boolean logic).
from mewpy.io import Reader, Engines, read_model
# loading E. coli iMC1010 model
imc1010_gem_reader = Reader(Engines.MetabolicSBML, 'iJR904.xml')
imc1010_trn_reader = Reader(Engines.BooleanRegulatoryCSV,
'iMC1010.csv', sep=',', id_col=0, rule_col=4, aliases_cols=[1, 2, 3], header=0)
model = read_model(imc1010_gem_reader, imc1010_trn_reader)
model
| Model | iJR904 |
|---|---|
| Name | Reed2003 - Genome-scale metabolic network of Escherichia coli (iJR904) |
| Types | regulatory, metabolic |
| Compartments | e, c |
| Reactions | 1083 |
| Metabolites | 768 |
| Genes | 904 |
| Exchanges | 150 |
| Demands | 0 |
| Sinks | 0 |
| Objective | BiomassEcoli |
| Regulatory interactions | 1010 |
| Targets | 1010 |
| Regulators | 232 |
| Regulatory reactions | 22 |
| Regulatory metabolites | 96 |
| Environmental stimuli | 11 |
RFBA can be simulated using an initial regulatory state that will be used
during synchronous evaluation of all regulatory interactions.
However, setting up the regulators’ initial state is a difficult task.
Most of the time, the initial state is not known and hinders feasible solutions during simulation.
If the initial state is not provided to RFBA, this method will consider that all regulators are active.
This initial state is clearly not the best, as many essential reactions can be switched off.
To relax some constraints, the initial state of a regulatory metabolite is inferred from its exchange reaction, namely the absolute value of the lower bound. Likewise, the initial state of a regulatory reaction is inferred from its upper bound. Even so, this initial state is likely to yield infeasible solutions.
Find conflicts
To mitigate conflicts between the regulatory and metabolic states,
one can use the mewpy.germ.analysis.find_conflicts() method.
This method can find regulatory states that lead to knockouts of essential genes and deletion of essential reactions.
Note that, find_conflicts() results should be carefully analyzed, as this method does not detect indirect conflicts.
Please consult the method for more details and the example bellow.
from mewpy.germ.analysis import find_conflicts
# we can see that 3 regulators are affecting the following essential genes: b2574; b1092; b3730
repressed_genes, repressed_reactions = find_conflicts(model)
repressed_genes
| interaction | Stringent | b0676 | b4390 | |
|---|---|---|---|---|
| b1092 | b1092 || 1 = ( ~ Stringent) | 1.0 | NaN | NaN |
| b3730 | b3730 || 1 = b0676 | NaN | 0.0 | NaN |
| b2574 | b2574 || 1 = ( ~ b4390) | NaN | NaN | 1.0 |
find_conflicts() suggests that three essential genes (b2574; b1092; b3730) are being affected
by three regulators (b4390, Stringent, b0676). However, some regulators do not affect growth directly,
as they are being regulated by other regulators, environmental stimuli, metabolites and reactions.
# regulator-target b4390 is active in high-NAD conditions (environmental stimuli)
model.get('b4390')
| Identifier | b4390 |
|---|---|
| Name | b4390 |
| Aliases | nadR, b4390, NadR, nadr |
| Model | iJR904 |
| Types | regulator, target |
| Coefficients | (0.0, 1.0) |
| Active | True |
| Interactions | b0931_interaction, b2574_interaction |
| Targets | b0931, b2574 |
| Environmental stimulus | False |
| Interaction | b4390 || 1 = high-NAD |
| Regulators | high-NAD |
Now, we can infer a feasible initial state for the model and run RFBA.
from mewpy.germ.analysis import RFBA
# initial state inferred from the find_conflicts method.
initial_state = {
'Stringent': 0.0,
'high-NAD': 0.0,
'AGDC': 0.0,
}
# steady-state RFBA
rfba = RFBA(model).build()
solution = rfba.optimize(initial_state=initial_state)
solution
| Method | RFBA |
| Model | Model iJR904 - Reed2003 - Genome-scale metabolic network of Escherichia coli (iJR904) |
| Objective | BiomassEcoli |
|---|---|
| Objective value | 0.8517832811766279 |
| Status | optimal |
SRFBA
SRFBA is a phenotype simulation method based on the integration of a GEM model with a TRN at the genome-scale.
SRFBA performs a single steady-state simulation using both metabolic and regulatory constraints found in the integrated model.
This method uses Mixed-Integer Linear Programming (MILP) to solve nested boolean algebra expressions formulated from
the structure of the regulatory layer (regulatory interactions) and metabolic layer (GPR rules).
For that, SRFBA adds auxiliary variables representing intermediate boolean variables and operators.
The resulting linear problem also includes a boolean variable and constraint for each reaction linking the outcome
of the interactions and GPR constraints to the mass balance constraints.
SRFBA only supports steady-state simulations.
SRFBA is available in the mewpy.germ.analysis package.
Alternatively, one can use the simple and optimized version slim_srfba.
For more details consult: https://doi.org/10.1038%2Fmsb4100141.
In this example we will be using E. coli iMC1010 model available at models/germ/iJR904_srfba.xml and models/germ/iMC1010.csv. This is the model used in the RFBA example.
from mewpy.io import Reader, Engines, read_model
# loading E. coli iMC1010 model
imc1010_gem_reader = Reader(Engines.MetabolicSBML, 'iJR904.xml')
imc1010_trn_reader = Reader(Engines.BooleanRegulatoryCSV,
'iMC1010.csv', sep=',', id_col=0, rule_col=4, aliases_cols=[1, 2, 3], header=0)
model = read_model(imc1010_gem_reader, imc1010_trn_reader)
SRFBA does not need an initial state in most cases, as this method can perform a steady-state simulation using MILP.
The solver tries to find a regulatory state favoring reactions that contribute to faster growth rates.
Accordingly, regulatory variables can take values between zero and one.
from mewpy.analysis import SRFBA
# steady-state SRFBA
srfba = SRFBA(model).build()
solution = srfba.optimize()
solution
| Method | SRFBA |
| Model | Model iJR904 - Reed2003 - Genome-scale metabolic network of Escherichia coli (iJR904) |
| Objective | BiomassEcoli |
|---|---|
| Objective value | 0.8218562176868295 |
| Status | optimal |
iFVA and iDeletions
The mewpy.germ.analysis module includes an integrated version of the FVA method named iFVA.
This method can be used to inspect the solution space of an integrated GERM model.
iFVA computes the minimum and maximum possible fluxes of each reaction in a metabolic model
using one of the integrated analysis mentioned above (RFBA or SRFBA).
This method return a pandas DataFrame with the minium and maximum fluxes (columns) for each reaction (index).
The mewpy.germ.analysis module also includes isingle_gene_deletion, isingle_reaction_deletion,
and isingle_regulator_deletion methods to inspect in silico genetic strategies in integrated GERM models.
from mewpy.io import Reader, Engines, read_model
from mewpy.germ.analysis import ifva
# loading E. coli iMC1010 model
imc1010_gem_reader = Reader(Engines.MetabolicSBML, 'iJR904.xml')
imc1010_trn_reader = Reader(Engines.BooleanRegulatoryCSV,
'iMC1010.csv', sep=',', id_col=0, rule_col=4, aliases_cols=[1, 2, 3], header=0)
model = read_model(imc1010_gem_reader, imc1010_trn_reader)
# iFVA of the first fifteen reactions using srfba (the default method). Fraction inferior to 1 (default) to relax the constraints
reactions_ids = list(model.reactions)[:15]
ifva(model, fraction=0.9, reactions=reactions_ids, method='srfba')
| minimum | maximum | |
|---|---|---|
| 12PPDt | 0.000000e+00 | 0.000000 |
| 2DGLCNRx | 0.000000e+00 | 0.000000 |
| 2DGLCNRy | 0.000000e+00 | 0.000000 |
| 2DGULRx | 0.000000e+00 | 0.000000 |
| 2DGULRy | 0.000000e+00 | 0.000000 |
| 3HCINNMH | 0.000000e+00 | 0.000000 |
| 3HPPPNH | 0.000000e+00 | 0.000000 |
| 4HTHRS | 0.000000e+00 | 0.000000 |
| 5DGLCNR | -1.319152e+00 | 0.000000 |
| A5PISO | 3.106617e-02 | 0.034518 |
| AACPS1 | -7.177128e-12 | 0.055426 |
| AACPS2 | -1.794282e-11 | 0.138565 |
| AACPS3 | -1.291883e-10 | 0.997670 |
| AACPS4 | -2.511995e-11 | 0.193991 |
| AACPS5 | -1.794282e-10 | 1.385652 |
PROM
PROM is a probabilistic-based phenotype simulation method.
This method circumvents discrete constraints created by RFBA and SRFBA using a continuous approach:
reactions’ constraints are proportional to the probabilities of related genes being active.
PROM performs a single steady-state simulation using the probabilistic-based constraints to limit flux through some reactions.
This method cannot perform wild-type phenotype simulations though, as probabilities are calculated for single regulator deletion.
Hence, PROM is adequate to predict the effect of regulator perturbations.
PROM can generate a KOSolution containing the solution of each regulator knock-out.
PROM is available in the mewpy.germ.analysis package.
Alternatively, one can use the simple version mewpy.germ.analysis.slim_prom.
For more details consult: https://doi.org/10.1073/pnas.1005139107.
In this example, we will be using M. tuberculosis iNJ661 model available at examples/models/germ/iNJ661.xml, examples/models/germ/iNJ661_trn.csv, and examples/models/germ/iNJ661_gene_expression.csv.
The integrated M. tuberculosis iNJ661 model was published by Chandrasekaran et al, 2010. This model consists of the M. tuberculosis iNJ661 GEM model published by Jamshidi et al, 2007, M. tuberculosis TRN published by Balazsi et al, 2008, and gene expression dataset published by Chandrasekaran et al, 2010. This model includes 691 metabolic genes, 1028 unique biochemical reactions, and a TRN having 2018 regulatory interactions (target-regulator).
from mewpy.io import Reader, Engines, read_model
# loading M. tuberculosis iNJ661 model
inj661_gem_reader = Reader(Engines.MetabolicSBML, 'iNJ661.xml')
inj661_trn_reader = Reader(Engines.TargetRegulatorRegulatoryCSV,
'iNJ661_trn.csv', sep=';', target_col=0, regulator_col=1, header=None)
model = read_model(inj661_gem_reader, inj661_trn_reader)
model
| Model | iNJ661 |
|---|---|
| Name | M. tuberculosis iNJ661 model - Jamshidi et al 2007 |
| Types | regulatory, metabolic |
| Compartments | c, e |
| Reactions | 1028 |
| Metabolites | 828 |
| Genes | 661 |
| Exchanges | 88 |
| Demands | 0 |
| Sinks | 0 |
| Objective | biomass_Mtb_9_60atp_test_NOF |
| Regulatory interactions | 178 |
| Targets | 178 |
| Regulators | 30 |
| Regulatory reactions | 0 |
| Regulatory metabolites | 0 |
| Environmental stimuli | 29 |
Infer probabilities
PROM phenotype simulation requires an initial state that must be inferred from the TRN and gene expression dataset.
Besides, the format of the initial state is slightly different from RFBA and SRFBA initial states.
PROM’s initial state must be a dictionary in the following format:
keys -> tuple of regulator and target gene identifiers
value -> probability of this regulatory interaction inferred from the gene expression dataset
mewpy.omics package contains the required methods to perform a quantile preprocessing of the gene expression dataset.
Then, one can use the mewpy.germ.analysis.prom.target_regulator_interaction_probability() method to infer PROM’s initial state
from mewpy.omics import ExpressionSet
from mewpy.germ.analysis import target_regulator_interaction_probability
# computing PROM target-regulator interaction probabilities using quantile preprocessing pipeline
expression = ExpressionSet.from_csv(file_path='iNJ661_gene_expression.csv', sep=';', index_col=0, header=None)
quantile_expression, binary_expression = expression.quantile_pipeline()
initial_state, _ = target_regulator_interaction_probability(model,
expression=quantile_expression,
binary_expression=binary_expression)
initial_state
...
('Rv2920c', 'Rv3575c'): 1,
('Rv3275c', 'Rv3575c'): 1,
('Rv3275c', 'Rv3676'): 0.7416666666666667,
('Rv3276c', 'Rv3575c'): 0.5045317220543807,
('Rv3276c', 'Rv3676'): 1,
('Rv0408', 'Rv3676'): 0.55,
...
Now we can perform the PROM simulation.
from mewpy.germ.analysis import PROM
# using PROM
prom = PROM(model).build()
solution = prom.optimize(initial_state=initial_state)
solution.solutions
{'ko_Rv0001': PROM Solution
Objective value: 0.028300772436182654
Status: optimal,
'ko_Rv3575c': PROM Solution
Objective value: 0.052199202493402735
Status: optimal,
'ko_Rv3676': PROM Solution
Objective value: 0.03117434871202209
Status: optimal,
...
CoRegFlux
CoRegFlux is a linear regression-based phenotype simulation method.
This method circumvents discrete constraints created by RFBA and SRFBA using a continuous approach:
reactions’ constraints are proportional (using soft plus activation function) to the predicted expression of related genes.
CoRegFlux performs a single steady-state simulation using predicted gene expression data (estimated with a linear regression model)
to limit flux through some reactions.
Hence, this method can predict the phenotypic behavior of an organism for all environmental conditions of the gene expression dataset.
However, this method must use a different training dataset to infer regulators’ influence scores and train the linear regression models.
CoRegFlux can also perform dynamic simulations for a series of time steps.
At each time step, dynamic CoRegFlux updates metabolite concentrations and biomass yield using the euler function.
These values are then translated into additional constraints to be added to the steady-state simulation.
CoRegFlux can generate a ModelSolution containing the solution for a single environmental condition in the experiment dataset.
In addition, CoRegFlux can generate a DynamicSolution containing time-step solutions for a single environmental condition in the experiment dataset.
CoRegFlux is available in the mewpy.germ.analysis package.
Alternatively, one can use the simple version slim_coregflux.
For more details consult: https://doi.org/10.1186/s12918-017-0507-0.
In this example we will be using the following models and data:
S. cerevisae iMM904 model available at examples/models/germ/iMM904.xml,
S. cerevisae TRN inferred with CoRegNet and available at examples/models/germ/iMM904_trn.csv,
S. cerevisae training gene expression dataset available at examples/models/germ/iMM904_gene_expression.csv,
S. cerevisae influence scores inferred with CoRegNet in the gene expression dataset available at examples/models/germ/iMM904_influence.csv,
S. cerevisae experiments gene expression dataset available at examples/models/germ/iMM904_experiments.csv.
The integrated S. cerevisae iMM904 model was published by Banos et al, 2017. This model consists of the S. cerevisae iMM904 GEM model published by Mo et al, 2009, S. cerevisae TRN inferred by CoRegNet published by Nicolle et al, 2015, and gene expression datasets published by Brauer et al, 2005 and DeRisi et al, 1997. This model includes 904 metabolic genes, 1557 unique biochemical reactions, and a TRN having 3748 regulatory interactions (target-regulators separated in co-activators and co-repressors).
from mewpy.io import Reader, Engines, read_model
# loading S. cerevisae iMM904 model
imm904_gem_reader = Reader(Engines.MetabolicSBML, 'iMM904.xml')
imm904_trn_reader = Reader(Engines.CoExpressionRegulatoryCSV,
'iMM904_trn.csv', sep=',', target_col=2, co_activating_col=3, co_repressing_col=4, header=0)
model = read_model(imm904_gem_reader, imm904_trn_reader)
model
| Model | iMM904 |
|---|---|
| Name | S. cerevisae iMM904 model - Mo et al 2009 |
| Types | regulatory, metabolic |
| Compartments | c, e, m, x, r, v, g, n |
| Reactions | 1577 |
| Metabolites | 1226 |
| Genes | 905 |
| Exchanges | 164 |
| Demands | 0 |
| Sinks | 0 |
| Objective | BIOMASS_SC5_notrace |
| Regulatory interactions | 3748 |
| Targets | 3748 |
| Regulators | 201 |
| Regulatory reactions | 0 |
| Regulatory metabolites | 0 |
| Environmental stimuli | 199 |
Predicting gene expression
CoRegFlux phenotype simulation requires an initial state that must be inferred from the TRN, gene expression dataset,
influence score matrix and experiments gene expression dataset.
This initial state contains the predicted gene expression of target metabolic genes available in the GEM model.
mewpy.germ.analysis.coregflux module includes the tools to infer CoRegFlux’s initial state.
These methods create the linear regression models to predict targets’ expression according to the experiments gene expression dataset.
One just have to load expression, influence and experiments CSV files using mewpy.omics.ExpressionSet.
HINT: the predict_gene_expression method might be time-consuming for some gene expression datasets.
One can save the predictions into a CSV file and then load it afterwards using mewpy.omics.ExpressionSet.from_csv().
from mewpy.omics import ExpressionSet
from mewpy.germ.analysis import predict_gene_expression
# HINT: you can uncomment the following line to load pre-computed gene expression predictions.
# Do not forget to comment the remaining lines in this cell.
# gene_expression_prediction = read_gene_expression_dataset(path.joinpath('iMM904_gene_expression_prediction.csv'),
# sep=',', gene_col=0, header=0)
expression = ExpressionSet.from_csv('iMM904_gene_expression.csv', sep=';', index_col=0, header=0).dataframe
influence = ExpressionSet.from_csv('iMM904_influence.csv', sep=';', index_col=0, header=0).dataframe
experiments = ExpressionSet.from_csv('iMM904_experiments.csv', sep=';', index_col=0, header=0).dataframe
gene_expression_prediction = predict_gene_expression(model=model, influence=influence, expression=expression,
experiments=experiments)
Now we can perform CoRegFlux simulation.
from mewpy.germ.analysis import CoRegFlux
# steady-state simulation only requires the initial state of a given experiment (the first experiment in this case)
initial_state = list(gene_expression_prediction.to_dict().values())
co_reg_flux = CoRegFlux(model).build()
solution = co_reg_flux.optimize(initial_state=initial_state[0])
solution
| Method | CoRegFlux |
| Model | Model iMM904 - S. cerevisae iMM904 model - Mo et al 2009 |
| Objective | BIOMASS_SC5_notrace |
|---|---|
| Objective value | 0.28786570373177145 |
| Status | optimal |