wc_lang/transform/create_implicit_dfba_ex_rxns.py
""" Create implicit exchange reactions for dFBA submodels.
:Author: Arthur Goldberg <Arthur.Goldberg@mssm.edu>
:Author: Jonathan Karr <jonrkarr@gmail.com>
:Date: 2018-11-28
:Copyright: 2017-2018, Karr Lab
:License: MIT
"""
from .core import Transform
from wc_onto import onto
from wc_utils.util.ontology import are_terms_equivalent
from wc_utils.util.units import unit_registry
import wc_lang.config.core
import wc_lang.core
class CreateImplicitDfbaExchangeReactionsTransform(Transform):
""" Create implicit exchange reactions for dFBA submodels.
To enable FBA to represent a closed system, create implicit forward exchange reactions
* Metabolites transported from the extracellular environment (generate a
"-> species_type[e]" reaction for each extracellular species involved in each dFBA submodel)
* TODO: Metabolites recycled from the byproducts of other submodels and products produced for other submodels
"""
class Meta(object):
id = 'CreateImplicitDfbaExchangeReactions'
label = 'Create implicit exchange reactions for dFBA submodels'
def run(self, model):
""" Create implicit exchange reactions for dFBA submodels
Args:
model (:obj:`Model`): model
Returns:
:obj:`Model`: same model, but transformed
"""
config = wc_lang.config.core.get_config()['wc_lang']
create_implicit_exchange_reactions = config['dfba']['create_implicit_exchange_reactions']
if not create_implicit_exchange_reactions:
return model
ext_comp = model.compartments.get_one(id=config['EXTRACELLULAR_COMPARTMENT_ID'])
rxn_id_template = config['dfba']['exchange_reaction_id_template']
rxn_name_template = config['dfba']['exchange_reaction_name_template']
ex_carbon = config['dfba']['flux_bounds']['ex_carbon']
ex_no_carbon = config['dfba']['flux_bounds']['ex_no_carbon']
carbon_flux_bounds = wc_lang.core.FluxBounds()
carbon_flux_bounds.min = -ex_carbon
carbon_flux_bounds.max = ex_carbon
carbon_flux_bounds.units = unit_registry.parse_units('M s^-1')
no_carbon_flux_bounds = wc_lang.core.FluxBounds()
no_carbon_flux_bounds.min = -ex_no_carbon
no_carbon_flux_bounds.max = ex_no_carbon
no_carbon_flux_bounds.units = unit_registry.parse_units('M s^-1')
for submodel in model.submodels:
if are_terms_equivalent(submodel.framework, onto['WC:dynamic_flux_balance_analysis']):
for species in submodel.get_children(kind='submodel', __type=wc_lang.core.Species):
if species.compartment == ext_comp:
id = rxn_id_template.format(submodel.id,
species.species_type.id,
species.compartment.id)
name = rxn_name_template.format(submodel.name or submodel.id,
species.species_type.name or species.species_type.id,
species.compartment.name or species.compartment.id)
participants = [species.species_coefficients.get_or_create(coefficient=1.)]
reversible = True
if species.species_type.structure and species.species_type.structure.has_carbon():
flux_bounds = carbon_flux_bounds
else:
flux_bounds = no_carbon_flux_bounds
rxn = model.reactions.get_one(id=id)
if rxn:
assert rxn.submodel == submodel
assert rxn.name == name
assert rxn.participants == participants
assert rxn.reversible == reversible
assert wc_lang.core.FluxBounds.Meta.attributes['min'].value_equal(
rxn.flux_bounds.min, flux_bounds.min)
assert wc_lang.core.FluxBounds.Meta.attributes['max'].value_equal(
rxn.flux_bounds.max, flux_bounds.max)
assert wc_lang.core.FluxBounds.Meta.attributes['units'].value_equal(
rxn.flux_bounds.units, flux_bounds.units)
else:
rxn = model.reactions.create(id=id)
rxn.submodel = submodel
rxn.name = name
rxn.participants = participants
rxn.reversible = reversible
rxn.flux_bounds = flux_bounds
return model