import cobra import copy from commmodelpy.commmodelpy import Community, SingleModel, generate_community_model_with_no_growth from commmodelpy.submodules.helper_general import json_write from typing import Dict S = cobra.Metabolite(id="S_c", compartment="c") A = cobra.Metabolite(id="A_c", compartment="c") B = cobra.Metabolite(id="B_c", compartment="c") C = cobra.Metabolite(id="C_c", compartment="c") P = cobra.Metabolite(id="P_c", compartment="c") X = cobra.Metabolite(id="X_c", compartment="c") nil_to_S = cobra.Reaction(id="EX_A", lower_bound=0, upper_bound=1000) S_to_A = cobra.Reaction(id="S_to_A", lower_bound=0, upper_bound=float("inf")) A_to_B = cobra.Reaction(id="A_to_B", lower_bound=0, upper_bound=float("inf")) B_to_C = cobra.Reaction(id="B_to_C", lower_bound=0, upper_bound=float("inf")) C_to_P = cobra.Reaction(id="C_to_P", lower_bound=0, upper_bound=float("inf")) P__to_nil = cobra.Reaction(id="EX_P", lower_bound=0, upper_bound=float("inf")) nil_to_S.add_metabolites({S: 1}) S_to_A.add_metabolites({ S: -1, A: 1, X: 1, }) A_to_B.add_metabolites({ A: -1, B: 1, X: -1, })
def sum_within_deviation(base): """Metabolites for a superficial, simple toy biomass reaction. The composition will follow the distribution depicted here: Lipid = 10% = 0.1 g/g Protein = 70% = 0.7 g/g RNA = 5% = 0.05 g/g DNA = 3% = 0.03 g/g Ash = 7% = 0.07 g/g Carbohydrates = 5% = 0.05 g/g The arbitrary molar masses for the metabolites used in this toy reaction will be approximated using hydrogen atoms in the formula. """ met_a = cobra.Metabolite("lipid_c", "H744", compartment='c') met_b = cobra.Metabolite("protein_c", "H119", compartment='c') met_c = cobra.Metabolite("rna_c", "H496", compartment='c') met_d = cobra.Metabolite("dna_c", "H483", compartment='c') met_e = cobra.Metabolite("ash_c", "H80", compartment='c') met_f = cobra.Metabolite("cellwall_c", "H177", compartment='c') met_g = cobra.Metabolite("atp_c", "C10H12N5O13P3", compartment='c') met_h = cobra.Metabolite("adp_c", "C10H12N5O10P2", compartment='c') met_i = cobra.Metabolite("h_c", "H", compartment='c') met_j = cobra.Metabolite("h2o_c", "H2O", compartment='c') met_k = cobra.Metabolite("pi_c", "HO4P", compartment='c') # Reactions rxn_1 = cobra.Reaction("BIOMASS_TEST") rxn_1.add_metabolites({met_a: -0.133, met_b: -5.834, met_c: -0.1, met_d: -0.0625, met_e: -0.875, met_f: -0.2778, met_g: -30.0, met_h: 30.0, met_i: 30.0, met_j: -30.0, met_k: 30.0 }) base.add_reactions([rxn_1]) return base
def generate_community_model_with_no_growth( community: Community, fractions: Dict[str, float], biomass_reactions: Dict[str, str] = {}) -> cobra.Model: """Creates a cobrapy-compatible community model from a commmodelpy Community instance. Description ---------- This function uses all information that is given to the Community instance's member variables - and its SingleModel member variables - in order to generate a community model with an exchange compartment, species-specific exchange reactions as well as community-wide exchange reactions as defined by the input and output metabolites of the respective Community instance and its SingleSpecies instances. Herein, the model-specific fractions of all single organisms can be given and for every species-associated function with a minimal/maximal flux which is not equal to inf/-inf/0, the minimal/maximal flux (denoted as v) is set to v*fraction_of_the_reaction's_species. Since only the growth rate is now free, this linearizes the 'problem' of solving a balanced-growth community model for growth, and an FBA on this model will show the theoretical optimal growth with the given fixed organism fractions. Return value ---------- A community model with fixed species ratios and no growth in the form of a cobrapy Model instance. This form of the community model - with its fixed organism ratios - can be e.g. used with the ASTHERISC package. Arguments ---------- * community: Community ~ The Community instance describing the total community. *In order to run with the ASTHERISC package, the community's exchange compartment ID must be set to "exchg" and the community's exchange reaction ID prefix to "EX_C"*. * fractions: Dict[str, float]: float ~ A dictionary containing all species names of the community as keys, and their fractions of the total community biomass as values. For reasonable calculations, the sum of all fractions should be 1.0. * biomass_reactions: Dict[str, str] ~ If not {}, it must denote the biomass reaction IDs (values) for each of the community's species (keys). For these reactions, the mock biomass metabolite community_biomass_$SPECIES_NAME will be added as product and the objective function community_biomass_reaction will be able to consume it. If it is {}, no objective function will be created and the mock biomass metabolites will not be added to the species biomass reaction. Is {} by default. """ # Get number of SingleModel instances in Community instance num_single_models = len(community.single_models) # Check that an actual community is given if num_single_models <= 1: raise ValueError( "ERROR: Less than 2 models in given Community instance!") # Check that the right amount of fractions is given if len(fractions.keys()) != num_single_models: raise ValueError( f"ERROR: Number of given fractions ({len(fractions)}) does not match number of single models ({num_single_models})!" ) # Go through each SingleModel and change their cobra models for single_model in community.single_models: species_fraction = fractions[single_model.species_abbreviation] # Check that no underscores are in the organism IDs if "_" in single_model.species_abbreviation: raise ValueError( f"ERROR: Underscore in the given species abbreviation {single_model.species_abbreviation} D:" ) # Rename metabolites for metabolite in single_model.cobra_model.metabolites: metabolite.id += "_" + single_model.species_abbreviation # Rename reactions and change bounds for reaction in single_model.cobra_model.reactions: reaction.id += "_" + single_model.species_abbreviation if reaction.upper_bound != float("inf"): reaction.upper_bound *= species_fraction if reaction.lower_bound != -float("inf"): reaction.lower_bound *= species_fraction if (reaction.upper_bound == float("inf")) and (species_fraction == 0): reaction.upper_bound = 0 if (reaction.lower_bound == -float("inf")) and (species_fraction == 0): reaction.lower_bound = 0 # Delete standard exchange reactions with default exchange reaction ID prefix standard_exchanges = [ x for x in single_model.cobra_model.reactions if x.id.startswith(single_model.exchange_reaction_id_prefix) ] single_model.cobra_model.remove_reactions(standard_exchanges) # Merge single models into a huge one merged_model = copy.deepcopy(community.single_models[0].cobra_model) for single_model in community.single_models[1:]: merged_model.merge(single_model.cobra_model, inplace=True) # Add whole community exchanges exchange_metabolite_ids = list( set(community.input_metabolite_ids + community.output_metabolite_ids)) for exchange_metabolite_id in exchange_metabolite_ids: # Set reaction instance reaction = cobra.Reaction( id=community.exchange_reaction_id_prefix + exchange_metabolite_id + "_" + community.exchange_compartment_id, name="Community exchange for " + exchange_metabolite_id) # Set reaction bounds is_input = exchange_metabolite_id in community.input_metabolite_ids if is_input: reaction.lower_bound = -float("inf") else: reaction.lower_bound = 0 is_output = exchange_metabolite_id in community.output_metabolite_ids if is_output: reaction.upper_bound = float("inf") else: reaction.upper_bound = 0 # Add metabolite to reaction exchange_metabolite = cobra.Metabolite( exchange_metabolite_id + "_" + community.exchange_compartment_id, name="Exchange compartment metabolite " + exchange_metabolite_id, compartment="exchange") reaction.add_metabolites({ exchange_metabolite: -1, }) # Add reaction to model merged_model.add_reactions([reaction]) # Add mock community biomass metabolites for the ASTHERISC package's species recognition biomass_metabolite = cobra.Metabolite( id="community_biomass", name= "Mock community biomass metabolite for ASTHERISC package species recognition", compartment="exchg") merged_model.add_metabolites([biomass_metabolite]) # Add single species <-> exchange compartment exchanges for single_model in community.single_models: exchange_metabolite_ids = list( set(single_model.input_metabolite_ids + single_model.output_metabolite_ids)) exchange_metabolite_ids = [ x + "_" + single_model.species_abbreviation for x in exchange_metabolite_ids ] # Add mock community biomass metabolites for the ASTHERISC package's species recognition biomass_metabolite = cobra.Metabolite( id="community_biomass_" + single_model.species_abbreviation, name= "Mock community biomass metabolite for ASTHERISC package species recognition", compartment="exchg") merged_model.add_metabolites([biomass_metabolite]) for exchange_metabolite_id in exchange_metabolite_ids: exchange_compartment_metabolite_id = single_model.model_metabolite_to_exchange_id_mapping[ exchange_metabolite_id.replace( "_" + single_model.species_abbreviation, "")] # Set reaction instance reaction = cobra.Reaction( id="EXCHG_" + single_model.species_abbreviation + "_" + exchange_metabolite_id.replace( "_" + single_model.species_abbreviation, "") + "_to_" + exchange_compartment_metabolite_id, name= f"Exchange for {exchange_metabolite_id} from single species {single_model.species_abbreviation} to exchange compartment" ) # Set reaction bounds # is_input = exchange_compartment_metabolite_id in single_model.input_metabolite_ids is_input = exchange_metabolite_id.replace( "_" + single_model.species_abbreviation, "") in single_model.input_metabolite_ids if is_input: reaction.lower_bound = -float("inf") else: reaction.lower_bound = 0 # is_output = exchange_compartment_metabolite_id in single_model.output_metabolite_ids is_output = exchange_metabolite_id.replace( "_" + single_model.species_abbreviation, "") in single_model.output_metabolite_ids if is_output: reaction.upper_bound = float("inf") else: reaction.upper_bound = 0 # Add metabolites to reaction internal_metabolite = merged_model.metabolites.get_by_id( exchange_metabolite_id) exchange_compartment_metabolite = merged_model.metabolites.get_by_id( exchange_compartment_metabolite_id + "_" + community.exchange_compartment_id) reaction.add_metabolites({ internal_metabolite: -1, exchange_compartment_metabolite: 1, }) # Add reaction to model merged_model.add_reactions([reaction]) return merged_model
1339, 1340, 1353, 1370, 1371, 1373, 1374, 1376, 1384, 1387, 1406, 1408, 1410, 1433, 1445, 1448, 1449, 1457, 1480, 1481, 1486, 1510, 1517, 1518, 1537, 1538, 1539, 1541, 1548, 1549, 1583, 1585, 1596, 1600, 1633, 1640, 1645, 1647, 1685, 1686, 1687, 1688, 1689, 1690, 1691, 1692 ] # cobra.io.save_matlab_model(model, 'S_pombe.xml') # CO2 : 516 ; ergosterol: 658 ; H2O : 922 ; ammonium: 1203 ; # oxygen: 1240 ; phosphate: 1343 ; sulphate: 1523 ; zymosterol : 1693 # to find extracelluar transport reactions for i in range(len(model.reactions)): if len(model.reactions[i].reactants) == 0: print("%s : %i" % (model.reactions[i], i)) mant_e = cobra.Metabolite('mant_e', name='Manninotriose', compartment='e') gal_e = cobra.Metabolite('gal_e', name='Galactose', compartment='e') H2O_e = cobra.Metabolite('H2O_e', name='Water', compartment='e') melib_e = cobra.Metabolite('melib_e', name='Melibiose', compartment='e') raffin_e = cobra.Metabolite('raffin_e', name='Raffinose', compartment='e') sta_e = cobra.Metabolite('sta_e', name='Stachyose', compartment='e') GALI_e = cobra.Metabolite('GALI_e', name='Galactinol', compartment='e') inost_e = cobra.Metabolite('inost_e', name='myo-Inositol', compartment='e') emp_e = cobra.Metabolite('emp_e', name='Epimelibioise', compartment='e') man_e = cobra.Metabolite('man_e', name='D-Mannose', compartment='e') ggl_e = cobra.Metabolite('ggl_e', name='Galactosylglycerol', compartment='e') glyc_e = cobra.Metabolite('glyc_e', name='Glycerol', compartment='e') melt_e = cobra.Metabolite('melt_e', name='Melibiitol', compartment='e') sbtD_e = cobra.Metabolite('sbtD_e', name='D-sorbitol', compartment='e') GDP_e = cobra.Metabolite('GDP_e', name='GDP', compartment='e') GMP_e = cobra.Metabolite('GMP_e', name='GMP', compartment='e')
def __init__(self, model, Universal=None, threshold=0.05, penalties={ "Universal": 1, "Exchange": 1, "Demand": 1 }, dm_rxns=False, ex_rxns=True): cobra.Model.__init__(self, "") # store parameters self.threshold = threshold self.penalties = penalties # want to only operate on a copy of Universal so as not to mess up # is this necessary? if Universal is None: Universal = cobra.Model("Universal_Reactions") else: Universal = Universal.copy() # SUX += Exchange (when exchange generator has been written) # For now, adding exchange reactions to Universal - could add to a new model called exchange and allow their addition or not.... if ex_rxns: ex_reactions = [x for x in model.reactions if x.startswith('EX_')] else: ex_reactions = [] # ADD ALL EXCHANGE REACTIONS TO UNIVERSAL MODEL for r in ex_reactions: if r.lower_bound >= 0: rxn = r.copy() #model.remove_reaction(r) rxn.id += "_gapfill" rxn.lower_bound = -1000 Universal.add_reaction(rxn) if dm_rxns: # ADD DEMAND REACTIONS FOR ALL METABOLITES TO UNIVERSAL MODEL for m in model.metabolites: rxn = Reaction('DM_' + m.id) rxn.lower_bound = -1000 rxn.upper_bound = 1000 rxn.add_metabolites({m: -1.0}) Universal.add_reaction(rxn) cobra.manipulation.modify.convert_to_irreversible(Universal) for rxn in Universal.reactions: if rxn.startswith('EX_'): rxn.notes["gapfilling_type"] = "Exchange" elif rxn.startswith('DM_'): rxn.notes["gapfilling_type"] = "Demand" else: rxn.notes["gapfilling_type"] = "Universal" self += model self += Universal # Add MILP dummy reactions v = 1000 # maximum flux in a reaction # threshold = 0.05 dummy_reactions = [] # all reactions with an index < len(model.reactions) were original self.original_reactions = self.reactions[:len(model.reactions)] self.added_reactions = self.reactions[len(model.reactions):] # add in the dummy reactions for each added reaction # a dict will map from each added reaction (the key) to # the dummy reaction (the value) self._dummy_reaction_map = {} for reaction in self.added_reactions: dummy_metabolite = cobra.Metabolite("dummy_met_" + reaction.id) dummy_metabolite._constraint_sense = "L" reaction.add_metabolites({dummy_metabolite: 1}) the_dummy_reaction = cobra.Reaction("dummy_rxn_" + reaction.id) the_dummy_reaction.add_metabolites({dummy_metabolite: -1 * v}) the_dummy_reaction.lower_bound = 0 the_dummy_reaction.upper_bound = 1 the_dummy_reaction.variable_kind = "integer" dummy_reactions.append(the_dummy_reaction) self._dummy_reaction_map[reaction] = the_dummy_reaction self.add_reactions(dummy_reactions) # add in the dummy metabolite for the actual objective function self.objective_metabolite = cobra.Metabolite( "dummy_metabolite_objective_function") self.objective_metabolite._constraint_sense = "G" self.objective_metabolite._bound = self.threshold self._update_objectives() # make .add_reaction(s) call the ._add_reaction(s) functions self.add_reaction = self._add_reaction self.add_reactions = self._add_reactions
def get_m_model(): m = cobra.Model("e_coli_ME_M_portion") m.compartments = {"p": "Periplasm", "e": "Extra-organism", "c": "Cytosol"} compartment_lookup = {v: k for k, v in m.compartments.items()} met_info = pandas.read_csv( join(ecoli_files_dir, "metabolites.txt"), delimiter="\t", header=None, index_col=0, names=["id", "name", "formula", "compartment", "data_source"]) complex_set = \ set(get_complex_subunit_stoichiometry("protein_complexes.txt").keys()) for met_id in met_info.index: fixed_id = fix_id(met_id) for compartment in met_info.compartment[met_id].split("AND"): compartment = compartment.strip() if compartment == "No_Compartment": print("Assigned %s to c" % met_id) compartment = m.compartments["c"] new_met = cobra.Metabolite(fixed_id + "_" + compartment_lookup[compartment]) new_met.name = met_info.name[met_id] new_met.formula = met_info.formula[met_id] m.add_metabolites(new_met) rxn_info = get_reaction_info_frame('reactions.txt') rxn_dict = get_reaction_matrix_dict('reaction_matrix.txt', complex_set=complex_set) for rxn_id in rxn_info.index: reaction = cobra.Reaction(rxn_id) reaction.name = rxn_info.description[rxn_id] for met_id, amount in rxn_dict[rxn_id].items(): try: metabolite = m.metabolites.get_by_id(met_id) except KeyError: metabolite = cobra.Metabolite(met_id) reaction.add_metabolites({metabolite: amount}) reaction.lower_bound = \ -1000. if rxn_info.is_reversible[rxn_id] else 0. reaction.upper_bound = 1000. if rxn_info.is_spontaneous[rxn_id]: reaction.gene_reaction_rule = "s0001" m.add_reaction(reaction) sources_sinks = pandas.read_csv( fixpath("reaction_matrix_sources_and_sinks.txt"), delimiter="\t", header=None, names=["rxn_id", "met_id", "compartment", "stoic"], index_col=1) source_amounts = pandas.read_csv(join(ecoli_files_dir, "exchange_bounds.txt"), delimiter="\t", index_col=0, names=["met_id", "amount"]) sources_sinks.index = [fix_id(i) for i in sources_sinks.index] source_amounts.index = [fix_id(i) for i in source_amounts.index] for met in sources_sinks.index: met_id = met + "_" + compartment_lookup[sources_sinks.compartment[met]] # EX_ or DM_ + met_id reaction_id = sources_sinks.rxn_id[met][:3] + met_id reaction = cobra.Reaction(reaction_id) m.add_reaction(reaction) reaction.add_metabolites({m.metabolites.get_by_id(met_id): -1}) # set bounds on exchanges if reaction.id.startswith("EX_") and met in source_amounts.index: reaction.lower_bound = -source_amounts.amount[met] return m
def one_exchange(base): rxn = cobra.Reaction('EX_abc_e') rxn.add_metabolites({cobra.Metabolite(id="abc_e", compartment='e'): -1}) rxn.bounds = -1, 5 base.add_reactions([rxn]) return base
def add_fake_designs(self): """ Add a fake design with a parent design """ model = self.project.model project = self.project # Phosphoribulokinase reaction stoich = dict( atp_c=-1.0, ru5p__D_c=-1.0, adp_c=1.0, h_c=1.0, rb15bp_c=1.0, ) rb15bp = cobra.Metabolite(id='rb15bp_c', name='D-Ribulose 1,5-bisphosphate', formula='C5H8O11P2', charge=0) model.add_metabolites(rb15bp) pruk = cobra.Reaction(id="PRUK", name="Phosphoribulokinase reaction", lower_bound=-1000, upper_bound=1000) model.add_reactions([pruk]) pruk.add_metabolites(stoich) # Rubisco reaction (Ribulose-bisphosphate carboxylase) stoich = { "3pg_c": 2.0, "rb15bp_c": -1.0, "co2_c": -1.0, "h2o_c": -1.0, "h_c": 2.0 } rubisco = cobra.Reaction(id="RBPC", lower_bound=0, upper_bound=1000.0, name="Ribulose-bisphosphate carboxylase") model.add_reactions([rubisco]) rubisco.add_metabolites(stoich) model.genes.get_by_id("b3916").knock_out() model.genes.get_by_id("b1723").knock_out() model.genes.get_by_id("b1852").knock_out() model.reactions.EX_glc__D_e.lower_bound = -10.0 model.reactions.EX_nh4_e.lower_bound = -1000.0 project.save_design(model, 'cbb_cycle', 'calvin cycle', description='Reactions necissary for the calvin cycle in ecoli', overwrite=True) # Create a child of this design model = project.load_design('cbb_cycle') reaction = cobra.Reaction(id="HMGCOASi", name="Hydroxymethylglutaryl CoA synthase") aacoa = cobra.Metabolite(id="aacoa_c", charge=-4, formula="C25H36N7O18P3S", name="Acetoacetyl-CoA") hmgcoa = cobra.Metabolite(id="hmgcoa_c", charge=-5, formula="C27H40N7O20P3S", name="Hydroxymethylglutaryl CoA") model.add_metabolites([aacoa, hmgcoa]) stoich = dict( aacoa_c=-1.0, accoa_c=-1.0, coa_c=1.0, h_c=1.0, h2o_c=-1.0, hmgcoa_c=1.0, ) model.add_reactions([reaction]) reaction.add_metabolites(stoich) reaction.lower_bound = -1000.0 reaction.upper_bound = 1000.0 mev__r = cobra.Metabolite(id="mev__R_c", name="R Mevalonate", charge=-1, formula="C6H11O4") model.add_metabolites([mev__r]) reaction = cobra.Reaction(id="HMGCOAR", name="Hydroxymethylglutaryl CoA reductase") reaction.lower_bound = -1000.0 reaction.upper_bound = 1000.0 stoich = dict( coa_c=-1.0, h_c=2.0, nadp_c=-2.0, nadph_c=2.0, hmgcoa_c=1.0, mev__R_c=-1.0 ) model.add_reactions([reaction]) reaction.add_metabolites(stoich) model.add_boundary(mev__r, type='sink') # add somewhere for mevalonate to go project.save_design(model, 'mevalonate_cbb', 'mevalonate production', parent='cbb_cycle', description='Reactions for the production of mevalonate', overwrite=True) py_design = """ def gsmdesign_testpy(model, project): reaction = model.reactions.get_by_id("ATPM") reaction.bounds = (-999, 999) return model gsmdesign_testpy.parent = "mevalonate_cbb" """ ndpath = os.path.join(project.design_path, 'design_fake.py') with open(ndpath, 'w+') as desf: desf.write(py_design)
def __init__(self, model, boundary_species, add_biomass=False): """ A class to handle the dynamic optimization based method of dynamic flux analysis from [1]. model: a cobra.Model object. Contains the model to be optimized, reaction bounds and objective vectors will be preserved. boundary_species: a list Contains a list of strings specifying the boundary species which will be explicity tracked in the dynamic optimization. Biomass should be the first entry. add_biomass: bool Whether or not to attempt to add a `biomass` metabolite to the model. If True, will add the metabolite to the reaction specified by the objective function. --- [1] J. L. Hjersted and M. A. Henson, "Optimization of Fed-Batch Saccharomyces cerevisiae Fermentation Using Dynamic Flux Balance Models," Biotechnol Progress, vol. 22, no. 5, pp. 1239-1248, Sep. 2008. """ if add_biomass: biomass = cobra.Metabolite('biomass', compartment='e') biomass_rxn = model.objective.keys()[0] biomass_rxn.add_metabolites({biomass : 1}) EX_biomass = cobra.Reaction('EX_biomass') EX_biomass.add_metabolites({biomass : -1}) model.add_reaction(EX_biomass) self.model = cobra.core.DataframeBasedModel(model) self.model.optimize(minimize_absolute_flux=1.0) # Handle boundary reactions self.boundary_species = boundary_species all_boundary_rxns = model.reactions.query('system_boundary', 'boundary') self.boundary_rxns = [] for bs in boundary_species: rxns = all_boundary_rxns.query(lambda r: r.reactants[0].id in bs) assert len(rxns) == 1, ( "Error finding boundary reactions for {}: ".format(bs) + "{:d} reactions found".format(len(rxns))) self.boundary_rxns += [rxns[0].id] self.nx = len(boundary_species) self.nv = len(self.model.reactions) self.nm = len(self.model.metabolites) # If tf is left as None, it will be a symbolic variable self.tf = None self.death_rate = None # Initialize the base class super(DOAcollocation, self).__init__()
FBA_model.objective = {FBA_model.reactions.test_biomass: 1} FBA_model.solver = 'glpk' solution = FBA_model.optimize() if solution.f > 0.0001: return 'Success!' else: return 'Failed :-(' for component in med_components: try: met = FBA_model.metabolites.get_by_id(component) except: print('model to be filled has no ' + component + ': Adding it!') met = cobra.Metabolite(component) try: exchange = FBA_model.reactions.get_by_id('EX_' + component) except: exchange = FBA_model.add_boundary(met) print('new exchange reaction added: EX_' + component) exch_id = exchange.id med[exch_id] = 300 FBA_model.medium = med ##add a proton leak so we don't need to worry about charge balance for each individual metabolite to be checked ##this is NEVER (and should not be) saved back into the SBML file!! H_extra = FBA_model.metabolites.get_by_id('cpd00067_e0') H_intra = FBA_model.metabolites.get_by_id('cpd00067_c0') H_transport = cobra.Reaction('proton_leak')
def run_test_suite(json_model, update='start'): """ Runs a series of tests to determine if any updates significantly impact the metabolic model :param json_model: COBRApy-compliant model in JSON format :param update: the type of update that is made :return: a tsv file chronicling the model update test results """ model = cobra.io.load_json_model( json_model) # iEK1008.json: Griffin 2011 media pre-set in model model_info = { 'Model_ID': model.id, 'Model_Update': update, 'Total_Metabolites': str(len(model.metabolites)), 'Total_Reactions': str(len(model.reactions)), 'Total_Genes': str(len(model.genes)), 'Total_Compartments': str(len(model.compartments.keys())), 'Metabolic_Coverage': str(len(model.reactions) / len(model.genes)) } try: model.objective = 'BIOMASS__2' except ValueError: try: model.objective = 'biomass_iEK1008_60atp' model.reactions.get_by_id( 'biomass_iEK1008_60atp').upper_bound = 1000 except ValueError: biomass_rxns = [ rxn.id for rxn in model.reactions if 'biomass' in rxn.id.lower() ] model.objective = biomass_rxns[0] to_balance = [ rxn.id for rxn in model.reactions if len(rxn.check_mass_balance()) > 0 if 'EX_' not in rxn.id and 'DM_' not in rxn.id and 'biomass' not in rxn.id.lower() ] mets_no_rxn = [ met.id for met in model.metabolites if len(met.reactions) == 0 ] try: df_fva = cobra.flux_analysis.flux_variability_analysis( model, fraction_of_optimum=1.0) except cobra.exceptions.Infeasible: # needed for models without pre-set media or those that cannot grow model.medium = {} # clears any pre-set media for rxn_id, uptake_rate in media.iEK_griffinEssen.items( ): # loads Griffin media model.reactions.get_by_id(rxn_id).lower_bound = uptake_rate df_fva = cobra.flux_analysis.flux_variability_analysis( model, fraction_of_optimum=1.0) min_value = 0.99999 * df_fva['minimum'].min() max_value = 0.99999 * df_fva['maximum'].max() unbound_rxns = (df_fva[df_fva['minimum'] < min_value] + df_fva[df_fva['maximum'] > max_value]).index.to_list() model_consistency = { 'Imbalanced_Reactions': str(len(to_balance)), 'Disconnected_Metabolites': str(len(mets_no_rxn)), 'Unbound_Reactions_in_Medium': str(len(unbound_rxns)) } blocked_rxns = cobra.flux_analysis.variability.find_blocked_reactions( model, open_exchanges=True) # single_rxn_mets not the same as orphan & dead-end metabolites --> see updated model results in https://memote.io/ single_rxn_mets = [ met.id for met in model.metabolites if len(met.reactions) == 1 ] model_network_topology = { 'Blocked_Reactions': str(len(blocked_rxns)), 'Single_Reaction_Metabolites': str(len(single_rxn_mets)) } # clears model of active exchange reactions (i.e. removes 'preset' media); same as model.medium = {} for rxn in model.reactions: if 'EX_' in rxn.id: rxn.lower_bound = 0 xtps = { 'ATPM': 'Erroneous ATP Flux', 'NTP3': 'Erroneous GTP Flux', 'ctp_c': 'Erroneous CTP Flux', 'utp_c': 'Erroneous UTP Flux' } xtp_yields = 0 model_energy_cycles = {} for rxn_or_met in xtps.keys(): if '_c' not in rxn_or_met: model.reactions.get_by_id( rxn_or_met).lower_bound = 0 # Gsmodutils: = 1 model.objective = rxn_or_met elif '_c' in rxn_or_met: drain_rxn = cobra.Reaction(f'DR_{rxn_or_met}') model.add_reactions([drain_rxn]) drain_rxn.add_metabolites({ cobra.Metabolite(rxn_or_met): -1.0, cobra.Metabolite('h2o_c'): -1.0, cobra.Metabolite('h_c'): 1.0, cobra.Metabolite('pi_c'): 1.0, cobra.Metabolite(rxn_or_met.replace('tp_c', 'dp_c')): 1.0 }) drain_rxn.lower_bound = 0 drain_rxn.upper_bound = 1000 model.objective = f'DR_{rxn_or_met}' xtp_yield = model.optimize( ).objective_value # ATPM: closed bounds = 0 // Griffin = 10.875 mmol ATP gDW-1 hr-1 xtp_yields += xtp_yield model_energy_cycles['Erroneous_xTP_Flux'] = str(xtp_yields) model_growth = {} mtb_media = { 'Biomass_Flux_in_iEK_m7H10': media.iEK_m7H10, 'Biomass_Flux_in_m7H10': media.m7H10, 'ATPM_Flux_in_iEK_m7H10': media.iEK_m7H10, 'ATPM_Flux_in_m7H10': media.m7H10 } for name, mtb_medium in mtb_media.items(): model.medium = {} for ex_rxn_id, uptake_rate in mtb_medium.items(): try: model.reactions.get_by_id(ex_rxn_id).lower_bound = uptake_rate except KeyError: # bypasses exchange reactions in media that are not present in model (e.g. EX_zn2_e) continue if 'Biomass' in name: model.objective = 'BIOMASS__2' model_growth[name] = str(model.optimize().objective_value) elif 'ATPM' in name: model.objective = 'ATPM' model_growth[name] = str(model.optimize().objective_value) model_tests = { **model_info, **model_consistency, **model_network_topology, **model_energy_cycles, **model_growth } header = list(model_tests.keys()) model_results = list(model_tests.values()) file_path = '../results/' file_name = 'iEK1008_test_suite.tsv' # f'{model.id}': will write different files when model ID changes if file_name not in os.listdir(file_path): update_file = open(file_path + file_name, 'w') update_file.write('\t'.join(header) + '\n') update_file.write('\t'.join(model_results) + '\n') else: update_file = open(file_path + file_name, 'a') update_file.write('\t'.join(model_results) + '\n')
def create_metabolite_from_dict(m_dict): metabolite = cobra.Metabolite(m_dict['id']) metabolite.name = m_dict['name'] metabolite.charge = m_dict['charge'] metabolite.compartment = m_dict['compartment'] return metabolite
# TODO: Get the actual number nt_ratios = {'u':0.25, 'a':0.25, 'g':0.25, 'c':0.25, } rna_nucleotides = {'u':'ura_c', 'g':'gua_c', 'a':'ade_c', 'c':'csn_c'} coupling_dict = dict() # Add cystein -> selenocystein transformation for convenience selcys = cobra.Metabolite(id='selcys__L_c', compartment = 'c') selcys_rxn = cobra.Reaction(id='PSEUDO_selenocystein_synthase', name='PSEUDO Selenocystein_Synthase') selcys_rxn.add_metabolites({ecoli.metabolites.cys__L_c:-1, selcys:+1}) ecoli.add_reactions([selcys_rxn]) # Prot degradation # http://www.jbc.org/content/246/22/6956.full.pdf # The total amount of enzyme undergoing degrada- tion (2 to 7%) was the same # during growth and during various kinds of starvation. kdeg_low, kdeg_up = 0.02, 0.07 kdeg_enz = (kdeg_low + kdeg_up)/2 # From : # http://book.bionumbers.org/how-fast-do-rnas-and-proteins-degrade/
def metabolite_registry(): registry = {} registry["g6p_c"] = cobra.Metabolite("g6p_c", compartment="c") registry["g6p_c"].annotation["kegg.compound"] = "C00668" registry["glc__D_c"] = cobra.Metabolite("glc__D_c", compartment="c") registry["glc__D_c"].annotation["kegg.compound"] = "C00267" registry["h2o_c"] = cobra.Metabolite("h2o_c", compartment="c") registry["h2o_c"].annotation["kegg.compound"] = "C00001" registry["pi_c"] = cobra.Metabolite("pi_c", compartment="c") registry["pi_c"].annotation["kegg.compound"] = "C00009" registry["h2o_c_list"] = cobra.Metabolite("h2o_c", compartment="c") registry["h2o_c_list"].annotation["kegg.compound"] = [ 'C00001', 'C01328', 'D00001', 'D03703', 'D06322'] registry["o2_c_list"] = cobra.Metabolite("o2_c", compartment="c") registry["o2_c_list"].annotation["kegg.compound"] = ['C00007', 'D00003'] registry["h2_c_list"] = cobra.Metabolite("h2_c", compartment="c") registry["h2_c_list"].annotation["kegg.compound"] = ['C00282'] registry["h2o_c_name"] = cobra.Metabolite( "h2o_c", name="Water", compartment="c") registry["o2_c_name"] = cobra.Metabolite( "o2_c", name="Oxygen", compartment="c") registry["h2_c_name"] = cobra.Metabolite( "h2_c", name="Hydrogen", compartment="c") registry["whack_c"] = cobra.Metabolite( "whack_c", name="Whack", compartment="c") registry["odd_c"] = cobra.Metabolite("odd_c", name="Odd", compartment="c") registry["unknown_c"] = cobra.Metabolite("unknown_c", compartment="c") return registry
def read_simpheny(baseName, min_lower_bound=-1000, max_upper_bound=1000, maximize_info=True): r"""Imports files exported from a SimPheny simulation as a cobra model. .. warning:: Use with caution. This is a legacy import function, and errors have been observed in the converted gene-reaction rules. Parameters ---------- baseName : str The filepath to the exported SimPheny files without any of the extensions. On Windows, it helps if baseName is a raw string (i.e. r"Path\\to\\files") min_lower_bound, max_upper_bound : float or int, optional The bounds on the lower and upper bounds of fluxes in model. maximize_info : bool, optional An optional boolean keyword argument. If True, then an attempt will be made to parse the gpr and metabolite info files, and the function will take a little bit longer. Returns ------- model : cobra.Model the imported simpheny model """ # check to make sure the files can be read if not (isfile(baseName + ".met") and isfile(baseName + ".rxn") and isfile(baseName + ".sto")): # try again with modifying the baseName baseName = baseName.encode("string-escape") if not (isfile(baseName + ".met") and isfile(baseName + ".rxn") and isfile(baseName + ".sto")): raise (IOError, "Input file(s) not found") model = cobra.Model("SimPheny import from " + baseName) # read in metabolite file metfile = _open_and_skip_header(baseName + ".met") metabolites = [] for line in metfile: if len(line) == 0: break metabolite = cobra.Metabolite(id=line[1], name=line[2], compartment=line[3]) if maximize_info: compartment_search = re.findall("\([a-z]\)$", metabolite.id) if compartment_search != []: metabolite.compartment = compartment_search[0][1] model.compartments[metabolite.compartment] = line[3] metabolites.append(metabolite) model.add_metabolites(metabolites) # scalefunc will limit the maximum and minumum fluxes scalefunc = lambda x: max(min(max_upper_bound, x), min_lower_bound) # read in reaction file reaction_file = _open_and_skip_header(baseName + ".rxn") reactions = [] for line in reaction_file: if len(line) == 0: break the_reaction = cobra.Reaction() the_reaction.id = line[1] the_reaction.name = line[2] if line[3].lower() == "reversible": the_reaction.reversibility = 1 elif line[3].lower() == "irreversible": the_reaction.reversibility = 0 the_reaction.lower_bound = scalefunc(float(line[4])) the_reaction.upper_bound = scalefunc(float(line[5])) the_reaction.objective_coefficient = float(line[6]) reactions.append(the_reaction) model.add_reactions(reactions) # read in S matrix Sfile = _open_and_skip_header(baseName + ".sto") S = [] for i, line in enumerate(Sfile): if len(line) == 0: break the_metabolite = metabolites[i] for j, ns in enumerate(line): n = float(ns) if n != 0: model.reactions[j].add_metabolites({the_metabolite: n}) # attempt to read in more data infofilepath = baseName + "_cmpd.txt" if maximize_info and isfile(infofilepath): infofile = open(infofilepath, "r") infofile.readline() # skip the header infocsv = csv.reader(infofile) for row in infocsv: found = _find_metabolites_by_base(row[0], model.metabolites) for found_metabolite in found: found_metabolite.formula = row[2] found_metabolite.parse_composition() found_metabolite.charge = row[4] found_metabolite.notes = {} found_metabolite.notes["KEGG_id"] = row[8] found_metabolite.notes["CAS"] = row[5] found_metaboltie.notes["review status"] = row[3] infofile.close() gpr_filepath = baseName + "_gpr.txt" if maximize_info and isfile(gpr_filepath): warn("SimPheny export files may have errors in the gpr.") # Using this may be risky gpr_file = open(gpr_filepath, "r") gpr_file.readline() # skip the header gpr_csv = csv.reader(gpr_file) for row in gpr_csv: the_reaction = model.reactions[model.reactions.index(row[0])] the_reaction.gene_reaction_rule = row[5] the_reaction.parse_gene_association() gpr_file.close() # model.update() return model
ex_reaction_ids = [x.id for x in model.reactions if x.id.startswith("EX_")] for ex_reaction_id in ex_reaction_ids: if model.reactions.get_by_id(ex_reaction_id).metabolites == {}: model.remove_reactions([ex_reaction_id]) print( "Add periplasmic metabolite for all metabolties in EX_ reactions ending with _c..." ) ex_c_reaction_ids = [ x.id for x in model.reactions if x.id.startswith("EX_") and x.id.endswith("_c") ] for ex_c_reaction_id in ex_c_reaction_ids: reaction = model.reactions.get_by_id(ex_c_reaction_id) metabolite = list(reaction.metabolites.keys())[0] new_p_metabolite = cobra.Metabolite(id=metabolite.id.replace("_c", "_p"), compartment="p") reaction.add_metabolites({new_p_metabolite: 1}) new_ex_reaction = cobra.Reaction(id="EX_" + new_p_metabolite.id, lower_bound=reaction.lower_bound, upper_bound=reaction.upper_bound) new_ex_reaction.add_metabolites({new_p_metabolite: -1}) model.add_reactions([new_ex_reaction]) reaction.id = "Transport_c_to_p_" + metabolite.id.replace("_c", "") print("Get all reaction IDs ending with Ex and Up...") ex_reaction_ids = [x.id for x in model.reactions if x.id.endswith("Ex")] up_reaction_ids = [x.id for x in model.reactions if x.id.endswith("Up")] all_exchange_ids = ex_reaction_ids + up_reaction_ids class ExchangedMetabolite:
exchg_reaction_ids = [ x.id for x in model.reactions if x.id.startswith("EXCHG_") ] for exchg_reaction_id in exchg_reaction_ids: reaction = model.reactions.get_by_id(exchg_reaction_id) if ("_adp_" in reaction.id) or ("_pi_" in reaction.id) or ( "_h_" in reaction.id) or ("_h2o_" in reaction.id): continue if "ecoli1" in reaction.id: id_addition = "ecoli1" else: id_addition = "ecoli2" if ((reaction.lower_bound == 0) and (reaction.upper_bound == 0)): print(reaction.id) new_pseudo_metabolite = cobra.Metabolite(id=reaction.id + "_PSEUDOMET_REV", compartment="exchg") reaction.add_metabolites({new_pseudo_metabolite: -1}) new_pseudo_reaction_1 = cobra.Reaction(id=reaction.id.replace( "EXCHG_", "").replace("ecoli1_", "").replace("ecoli2_", "") + "_PSEUDOREAC1_REV_" + id_addition, lower_bound=0, upper_bound=float("inf")) new_pseudo_reaction_1.add_metabolites({ new_pseudo_metabolite: 1, }) new_pseudo_reaction_2 = cobra.Reaction(id=reaction.id.replace( "EXCHG_", "").replace("ecoli1_", "").replace("ecoli2_", "") + "_PSEUDOREAC2_REV_" + id_addition,
def add_to_model(self, model, copy=False, add_missing=True): """ Add this design to a given cobra model :param model: :param copy: :param add_missing: add missing metabolites to the model :return: """ if not isinstance(model, cobra.Model): raise TypeError('Expected cobra model') mdl = model if copy: mdl = model.copy() # Load parent design first if self.parent is not None: self.parent.add_to_model(mdl) mdl.design = self if self.is_pydesign: try: mdl = self.design_func(mdl, self.project) except Exception as ex: raise DesignError("Function execution error {}".format(ex)) return mdl # Add new or changed metabolites to model for metabolite in self.metabolites: # create new metabolite object if its not in the model already if metabolite['id'] in mdl.metabolites: metab = mdl.metabolites.get_by_id(metabolite['id']) else: metab = cobra.Metabolite() # Doesn't check any of these properties for differences, just update them metab.id = metabolite['id'] metab.name = metabolite['name'] metab.charge = metabolite['charge'] metab.formula = metabolite['formula'] metab.notes = metabolite['notes'] metab.annotation = metabolite['annotation'] metab.compartment = metabolite['compartment'] if metab.id not in mdl.metabolites: mdl.add_metabolites([metab]) # Add new or changed reactions to model for rct in self.reactions: if rct['id'] in mdl.reactions: reaction = mdl.reactions.get_by_id(rct['id']) reaction.remove_from_model() reaction = cobra.Reaction() reaction.id = rct['id'] reaction.name = rct['name'] reaction.lower_bound = rct['lower_bound'] reaction.upper_bound = rct['upper_bound'] reaction.gene_reaction_rule = rct['gene_reaction_rule'] reaction.subsystem = rct['subsystem'] reaction.name = rct['name'] mdl.add_reactions([reaction]) reaction = mdl.reactions.get_by_id(reaction.id) metabolites = dict([(str(x), v) for x, v in rct['metabolites'].items()]) if add_missing: for mid in metabolites: try: mdl.metabolites.get_by_id(mid) except KeyError: metab = cobra.Metabolite(id=mid) mdl.add_metabolites(metab) reaction.add_metabolites(metabolites) reaction.objective_coefficient = rct['objective_coefficient'] # delete removed metabolites/reactions for rtid in self.removed_reactions: try: reaction = mdl.reactions.get_by_id(rtid) reaction.remove_from_model() except KeyError: pass for metid in self.removed_metabolites: try: met = mdl.metabolites.get_by_id(metid) met.remove_from_model() except KeyError: pass mdl.id += "::{}".format(self.id) # Add gene annotation for gene in self.genes: try: gobj = model.genes.get_by_id(gene['id']) except KeyError: # genes should already be contained in the model if they have a reaction relationship # However, tolerate bad designs continue gobj.name = gene['name'] gobj.functional = gene['functional'] gobj.annotation = gene['annotation'] gobj.notes = gene['notes'] return mdl
def create_smoment_model_reaction_wise( model: cobra.Model, output_sbml_name: str, project_folder: str, project_name: str, excluded_reactions: List[str], type_of_default_kcat_selection: str = "median") -> None: """Adds proteomic constraints according to sMOMENT to the given stoichiometric model and stores it as SBML. Arguments ---------- * model: cobra.Model ~ A cobra Model representation of the metabolic network. This model will be changed using cobrapy functions in order to add the proteomic constraints. * output_sbml_name: str ~ The base name of the created SBML. * project_folder: str ~ The folder in which the spreadsheets and JSONs with the model's supplemental data can be found. * project_name: str ~ The sMOMENTed model creation's name, which will be added at the beginning of the created SBML's name. * excluded_reactions: List[str] ~ A string list of reaction IDs (the 'reverse' and 'forward' name additions must not be added, i.e. for 'ACALD_forward' just 'ACALD' has to be given) to which no kcat shall be added. Typically used for gas exchange reactions such as 'CO2tex'. * type_of_default_kcat_selection: str ~ The type of selection of default kcat values. Can be "mean", "median" or "random". Is "median" by default. Output ---------- An SBML in the given folder with the given name, which describes the given stoichiometric model enhanced by the protein constraint introduction with this function. """ # Standardize project folder project_folder = standardize_folder(project_folder) # Set folder path for newly created SBML and name for the reaction ID addition (added at the end, # and used in order to have a programatically convinient way to separate additions such as 'reverse' # from the 'actual' reaction ID). basepath: str = project_folder + project_name id_addition: str = "_TG_" # READ REACTIONS<->KEGG ID XLSX protein_id_mass_mapping: Dict[str, float] = json_load( basepath + "_protein_id_mass_mapping.json") # Load protein data XLSX protein_id_concentration_mapping, p_total, unmeasured_protein_fraction, mean_saturation = \ read_protein_data_xlsx(basepath) # Read enzyme stoichiometries xlsx reaction_id_gene_rules_mapping, reaction_id_gene_rules_protein_stoichiometry_mapping = \ read_enzyme_stoichiometries_xlsx(basepath) # Calculate p_measured p_measured = get_p_measured(protein_id_concentration_mapping, protein_id_mass_mapping) # Split reactions with measured enzymes model, reaction_id_gene_rules_mapping, reaction_id_gene_rules_protein_stoichiometry_mapping = \ get_model_with_separated_measured_enzyme_reactions(model, protein_id_concentration_mapping, reaction_id_gene_rules_mapping, reaction_id_gene_rules_protein_stoichiometry_mapping, excluded_reactions, protein_id_mass_mapping) # Make model irreversible, separating all reversible reactions to which a gene rule is given # in order to save some reactions. model = get_irreversible_model(model, id_addition) # Add prot_pool reaction according to the given protein pool values model, prot_pool_metabolite = add_prot_pool_reaction( model, id_addition, p_total, p_measured, unmeasured_protein_fraction, mean_saturation) # Read reaction <-> kcat mapping :-) reactions_kcat_mapping_database = json_load( basepath + "_reactions_kcat_mapping_combined.json") # sMOMENT :D # Get all kcats which are not math.nan and calculate the median of them, which will be used as default kcat all_kcats = [x["forward"] for x in reactions_kcat_mapping_database.values()] + \ [x["reverse"] for x in reactions_kcat_mapping_database.values()] all_kcats = [x for x in all_kcats if not math.isnan(x)] if type_of_default_kcat_selection == "median": default_kcat = statistics.median(all_kcats) elif type_of_default_kcat_selection == "mean": default_kcat = statistics.mean(all_kcats) elif type_of_default_kcat_selection == "random": default_kcat = random.choice(all_kcats) else: print( 'ERROR: Argument type_of_default_kcat_selection must be either "median", "mean" or "random".' ) sys.exit(-1) print(f"Default kcat is: {default_kcat}") # Get all reaction IDs of the given model model_reaction_ids = [x.id for x in model.reactions] # Add measured enzyme pseudo-metabolites and pseudo-reactions for protein_id in protein_id_concentration_mapping.keys(): new_metabolite = cobra.Metabolite( id="ENZYME_" + protein_id, name="Pseudo-metabolite of protein " + protein_id, compartment="sMOMENT") max_protein_concentration = protein_id_concentration_mapping[ protein_id] new_reaction = cobra.Reaction( id="ENZYME_DELIVERY_" + protein_id, name="Delivery reaction of pseudo-metabolite " + protein_id, lower_bound=0, upper_bound=max_protein_concentration) new_reaction.add_metabolites({new_metabolite: 1}) model.add_reactions([new_reaction]) # Main loop :D, add enzyme constraints to reactions \o/ for model_reaction_id in model_reaction_ids: # Get the reaction and split the ID at the ID addition reaction = model.reactions.get_by_id(model_reaction_id) splitted_id = reaction.id.split(id_addition) # If the reaction has no name, ignore it if splitted_id[0] == "": continue # Take the reaction ID from the first part of the split reaction_id = splitted_id[0] # Remove GPRSPLIT name addition from reactions with measured protein concentrations if "_GPRSPLIT_" in reaction_id: reaction_id = reaction_id.split("_GPRSPLIT_")[0] # If the reaction has no associated enzyme stoichiometries, ignore it if reaction_id not in list(reaction_id_gene_rules_mapping.keys()): continue # If the reaction has no gene rule, ignore it gene_rule = reaction_id_gene_rules_mapping[reaction_id] if gene_rule == [""]: continue # If the reaction is manually excluded, ignore it if reaction_id in excluded_reactions: continue # Check if all proteins in the reaction's gene rule have a found mass # This is not the case for e.g. spontaneous reactions which often get the pseudo-enzyme 's0001' all_available = True for enzyme in gene_rule: if type(enzyme) == str: if enzyme not in list(protein_id_mass_mapping.keys()): print(enzyme) all_available = False break else: for enzyme_id in enzyme: if enzyme_id not in list(protein_id_mass_mapping.keys()): all_available = False break # If not all of the mass-checked enzymes have a found mass, ignore this reaction if not all_available: continue # Retrieve the reaction's forward and reverse kcats from the given reaction<->kcat database if reaction_id in reactions_kcat_mapping_database.keys(): forward_kcat = reactions_kcat_mapping_database[reaction_id][ "forward"] reverse_kcat = reactions_kcat_mapping_database[reaction_id][ "reverse"] # If the reaction is not in the database, set the default kcat else: forward_kcat = default_kcat reverse_kcat = default_kcat # If the given reaction<->kcat database contains math.nan as the reaction's kcat, # set the default kcat as math.nan means that no kcat could be found. if math.isnan(forward_kcat): forward_kcat = default_kcat if math.isnan(reverse_kcat): reverse_kcat = default_kcat # Add the given forward or reverse kcat is the reaction was # splitted due to its reversibility. # If the reaction is not splitted, add the forward kcat (this # is the only possible direction for non-splitted=non-reversible # reactions) if model_reaction_id.endswith(id_addition + "forward"): reaction_kcat = forward_kcat elif model_reaction_id.endswith(id_addition + "reverse"): reaction_kcat = reverse_kcat else: reaction_kcat = forward_kcat # Add protein pool pseudo-metabolite depending on isozyme complex presence # List of selectable MW/kcat stoichiometries (the most conservative constraint will be chosen) stoichiometries: List[float] = [] # List of enzyme names and stoichiometries (semicolon-separated) for a console report stoichiometry_enzyme_name_list: List[str] = [] for isozyme_id in gene_rule: # If it's not a complex :O... if type(isozyme_id) is str: # ...get the reaction ID without the additions... reaction_id = reaction_id.split("_TG_")[0] # ...get the number of units for this protein... number_units = reaction_id_gene_rules_protein_stoichiometry_mapping[ reaction_id][isozyme_id][isozyme_id] stoichiometry = number_units # ...and determine the protein pool stoichiometry by # 1) Multiplying the number of units for this protein with its mass (converted from kDa to mDa, since the reaction # flux is defined for mmol/(gDW*h) and not mol/(gDW*h)) stoichiometry *= (protein_id_mass_mapping[isozyme_id] / 1000) # 2) Dividing it with the reaction's kcat (converted from 1/s to 1/h) stoichiometry /= (reaction_kcat * 3600) # 3) Setting the right direction (educt) stoichiometry *= -1 stoichiometries.append(stoichiometry) stoichiometry_enzyme_name_list.append(isozyme_id + ";" + str(number_units)) # Add proteomics constraints if isozyme_id in protein_id_concentration_mapping.keys(): enzyme_pseudo_metabolite = model.metabolites.get_by_id( "ENZYME_" + isozyme_id) stoichiometry = reaction_id_gene_rules_protein_stoichiometry_mapping[ reaction_id][isozyme_id][isozyme_id] stoichiometry *= 1 / (reaction_kcat * 3600) stoichiometry *= -1 reaction.add_metabolites( {enzyme_pseudo_metabolite: stoichiometry}) # If it is a complex :O... else: # ...convert the complex IDs to a hashable tuple (used for the stoichiometry selection)... isozyme_id = tuple(isozyme_id) stoichiometry = 0 # ...go through each single ID of the complex... stoichiometry_enzyme_name_list.append("") for single_id in isozyme_id: # ...get the reaction ID without additions... reaction_id = reaction_id.split("_TG_")[0] # ...get the number of units for this protein... number_units = reaction_id_gene_rules_protein_stoichiometry_mapping[ reaction_id][isozyme_id][single_id] single_stoichiometry = number_units # ...and determine the protein pool stoichiometry addition by # 1) Multiplying the number of units for this protein with its mass (converted from kDa to Da) single_stoichiometry *= ( protein_id_mass_mapping[single_id] / 1000) # 2) Dividing it with the reaction's kcat (converted from 1/s to 1/h) single_stoichiometry /= (reaction_kcat * 3600) # 3) Setting the right direction (educt) single_stoichiometry *= -1 # 4) and add it to the complex's stoichiometry stoichiometry += single_stoichiometry # Add name of current single ID stoichiometry_enzyme_name_list[-1] += single_id + \ ";" + str(number_units) + " " stoichiometry_enzyme_name_list[ -1] = stoichiometry_enzyme_name_list[-1].rstrip() # Add to list of stoichiometries stoichiometries.append(stoichiometry) # Add proteomics constraints for single_id in isozyme_id: if single_id in protein_id_concentration_mapping.keys(): enzyme_pseudo_metabolite = model.metabolites.get_by_id( "ENZYME_" + single_id) stoichiometry = reaction_id_gene_rules_protein_stoichiometry_mapping[ reaction_id][isozyme_id][single_id] stoichiometry *= 1 / (reaction_kcat * 3600) stoichiometry *= -1 reaction.add_metabolites( {enzyme_pseudo_metabolite: stoichiometry}) # Take the maximal stoichiometry (i.e., the one with the least cost since this one will usually be prefered # anyway in an FBA). metabolites = {} max_stoichiometry = max(stoichiometries) metabolites[prot_pool_metabolite] = max_stoichiometry reaction.add_metabolites(metabolites) selected_enzyme = stoichiometry_enzyme_name_list[stoichiometries.index( max_stoichiometry)] # Print report of selected kcat and molecular weight for this reaction print("Reaction: ", model_reaction_id) print("Selected kcat: ", reaction_kcat) print("Selected molecular weight (kDa): ", end="") if " " in selected_enzyme: # Multiple enzymes mass_sum = .0 for single_enzyme in selected_enzyme.split(" "): enzyme_name = single_enzyme.split(";")[0] enzyme_unit_number = float(single_enzyme.split(";")[1]) mass_sum += protein_id_mass_mapping[enzyme_name] * \ enzyme_unit_number print(mass_sum) else: # Single enzyme enzyme_name = selected_enzyme.split(";")[0] enzyme_unit_number = float(selected_enzyme.split(";")[1]) print(protein_id_mass_mapping[enzyme_name] * enzyme_unit_number) # Output as SBML (without constraints due to cobrapy limitations) cobra.io.write_sbml_model(model, project_folder + output_sbml_name)
def _make_dictionaries(self): self.cofactor_metabolites_dict = { 'nadph': self.model.metabolites.get_by_id('nadph_c'), 'nadp': self.model.metabolites.get_by_id('nadp_c'), 'h2o': self.model.metabolites.get_by_id('h2o_c'), 'coa': self.model.metabolites.get_by_id('coa_c'), 'co2': self.model.metabolites.get_by_id('co2_c'), 'h+': self.model.metabolites.get_by_id('h_c'), 'sam': self.model.metabolites.get_by_id('amet_c'), 'sah': self.model.metabolites.get_by_id('ahcys_c'), 'mxmal': cobra.Metabolite('mxmal_c', formula='C14H20N6O5S', name='Methoxymalonyl-ACP', compartment='c'), '4hbf': cobra.Metabolite('4hbf_c', formula='X', name='4-hydroxy-benzoyl-formate', compartment='c'), 'hpg': cobra.Metabolite('4hpg_c', formula='X', name='4-hydroxy-phenyl-glycine', compartment='c'), 'dpg': cobra.Metabolite('dpg_c', formula='X', name='dihydroxy-phenyl-glycine', compartment='c'), 'bht': cobra.Metabolite('bht_c', formula='X', name='beta-hydroxy-tyrosine', compartment='c'), 'pip': cobra.Metabolite('Lpipecol_c', formula='X', name='pipecolic acid', compartment='c'), 'fatty_acid_X': cobra.Metabolite( 'fatty_acid_X_c', formula='X', name='generic fatty acid for acylation in NRPS initiation', compartment='c'), 'abu': cobra.Metabolite('2abu_c', formula='X', name='2-aminobutyrate', compartment='c'), 'ahba': cobra.Metabolite( 'ahba_c', formula='C7H7NO3', name='3-Amino-5-hydroxybenzoate', compartment='c' ), # https://www.genome.jp/dbget-bin/www_bget?C12107 'bafA': cobra.Metabolite('bafilomycinA1_c', formula='X', name='Bafilomycin A1', compartment='c'), 'bafB': cobra.Metabolite('bafilomycinB1_c', formula='X', name='Bafilomycin B1', compartment='c'), 'fumamp': cobra.Metabolite('fumamp_c', formula='X', name='Fumaryl-AMP', compartment='c'), 'mxacp': cobra.Metabolite( 'mxacp_c', formula='X', name='methoxymalonate specific acyl carrier protein', compartment='c'), 'c5n': cobra.Metabolite('c5n_c', formula='X', name='2-amino-3-hydroxycyclopent-2-enone', compartment='c'), 'fumamp_pk': cobra.Metabolite('fumamp__pk_c', formula='X', name='Fumaryl-AMP bound to polyketide', compartment='c'), 'final_product': cobra.Metabolite('final_product_c', formula='X', name='Final product', compartment='c'), '3mbm': cobra.Metabolite('3mbmcoa_c', formula='C8H14O4', name='(3-Methylbutyl)malonic acid', compartment='c'), '5m2h': cobra.Metabolite('5m2hcoa__E_c', formula='X', name='5-methyl-trans-hex-2-enoyl-ACP', compartment='c'), '5m3o': cobra.Metabolite('5mhcoa_c', formula='X', name='5-Methyl-3-oxohexanoyl-ACP', compartment='c'), 'i2b2': cobra.Metabolite('i2b2_c', formula='C8H12O4', name='(2E)-2-Isobutyl-2-butenedioic acid', compartment='c'), 'leupyrrin_1': cobra.Metabolite('leupyrrin_1_c', formula='X', name='leupyrrin intermediate', compartment='c') } self.cofactor_reactions_dict = { # reactions that are specific to certain domains 'PKS_KR': {self.cofactor_metabolites_dict['nadph']: -1.0, self.cofactor_metabolites_dict['h+']: -1.0, self.cofactor_metabolites_dict['nadp']: 1.0}, 'cMT': {self.cofactor_metabolites_dict['sam']: -1.0, self.cofactor_metabolites_dict['sah']: 1.0}, 'oMT': {self.cofactor_metabolites_dict['sam']: -1.0, self.cofactor_metabolites_dict['sah']: 1.0}, 'PKS_DH': {self.cofactor_metabolites_dict['h2o']: 1.0}, 'PKS_ER': {self.cofactor_metabolites_dict['nadph']: -1.0, self.cofactor_metabolites_dict['h+']: -1.0, self.cofactor_metabolites_dict['nadp']: 1.0}, 'PKS_TE': {self.cofactor_metabolites_dict['h2o']: -1.0}, 'TD': {self.cofactor_metabolites_dict['nadph']: -1.0, self.cofactor_metabolites_dict['h+']: -1.0, self.cofactor_metabolites_dict['nadp']: 1.0}, 'PKS_AT': {self.cofactor_metabolites_dict['coa']: 1.0, self.cofactor_metabolites_dict['co2']: 1.0}, 'Condensation': {self.cofactor_metabolites_dict['h2o']: -1.0}, 'nMT': {self.cofactor_metabolites_dict['sam']: -1.0, self.cofactor_metabolites_dict['sah']: 1.0}, 'mxmal': { self.cofactor_metabolites_dict['mxacp']: -1.0, self.model.metabolites.get_by_id('13dpg_c'): -1.0, self.model.metabolites.get_by_id('pi_c'): 2.0, self.model.metabolites.get_by_id('nad_c'): -1.0, self.model.metabolites.get_by_id('nadh_c'): 1.0, self.model.metabolites.get_by_id('h_c'): 1.0, self.model.metabolites.get_by_id('amet_c'): -1.0, self.model.metabolites.get_by_id('ahcys_c'): 1.0, self.model.metabolites.get_by_id('fad_c'): -1.0, self.model.metabolites.get_by_id('fadh2_c'): 1.0, self.cofactor_metabolites_dict['mxmal']: 1.0}, 'hpg_1': {self.model.metabolites.get_by_id('pphn_c'): -1, self.model.metabolites.get_by_id('34hpp_c'): 1, self.model.metabolites.get_by_id('co2_c'): 1, self.model.metabolites.get_by_id('h2o_c'): 1}, 'hpg_2': {self.model.metabolites.get_by_id('34hpp_c'): -1, self.model.metabolites.get_by_id('o2_c'): -1, self.model.metabolites.get_by_id('h2o_c'): 1, self.model.metabolites.get_by_id('4hmda_c'): 1}, 'hpg_3': {self.model.metabolites.get_by_id('4hmda_c'): -1, self.model.metabolites.get_by_id('fmn_c'): -1, self.model.metabolites.get_by_id('fmnh2_c'): 1, self.model.metabolites.get_by_id('nadh_c'): -1, self.model.metabolites.get_by_id('nad_c'): 1, self.cofactor_metabolites_dict['4hbf']: 1}, 'hpg_4': {self.cofactor_metabolites_dict['4hbf']: -1, self.model.metabolites.get_by_id('tyr__L_c'): -1, self.model.metabolites.get_by_id('34hpp_c'): 1, self.cofactor_metabolites_dict['hpg']: 1}, 'bht': {self.model.metabolites.get_by_id('tyr__L_c'): -1, self.model.metabolites.get_by_id('o2_c'): -1, self.model.metabolites.get_by_id('nadph_c'): -1, self.model.metabolites.get_by_id('h_c'): -1, self.model.metabolites.get_by_id('nadp_c'): 1, self.cofactor_metabolites_dict['hpg']: 1}, 'dpg': {self.model.metabolites.get_by_id('accoa_c'): -1, self.model.metabolites.get_by_id('malcoa_c'): -3, self.model.metabolites.get_by_id('coa_c'): 4, self.model.metabolites.get_by_id('co2_c'): 3, self.model.metabolites.get_by_id('h2o_c'): 1, self.model.metabolites.get_by_id('tyr__L_c'): -1, self.model.metabolites.get_by_id('34hpp_c'): 1, self.cofactor_metabolites_dict['dpg']: 1}, 'gnat': {self.model.metabolites.get_by_id('malcoa_c'): -1, self.model.metabolites.get_by_id('co2_c'): 1, self.model.metabolites.get_by_id('coa_c'): 1}, 'fkbh': {self.model.metabolites.get_by_id('13dpg_c'): -1.0, self.model.metabolites.get_by_id('pi_c'): 2.0}, # See https://www.genome.jp/kegg-bin/show_pathway?rn01051 and # https://biocyc.org/META/NEW-IMAGE?type=PATHWAY&object=PWY-5979 'ahba-synthesis': {self.model.metabolites.get_by_id('udpg_c'):-1, self.model.metabolites.get_by_id('nad_c'): -1, self.model.metabolites.get_by_id('nadh_c'): 1, self.model.metabolites.get_by_id('h_c'): 3, self.model.metabolites.get_by_id('gln__L_c'): -1, self.model.metabolites.get_by_id('HC00591_c'): 1, self.model.metabolites.get_by_id('udp_c'): 1, self.model.metabolites.get_by_id('atp_c'): -1, self.model.metabolites.get_by_id('adp_c'): 1, self.model.metabolites.get_by_id('r5p_c'): -1, self.model.metabolites.get_by_id('s7p_c') : 1, self.model.metabolites.get_by_id('pep_c'): -1, self.model.metabolites.get_by_id('pi_c'): 2, self.cofactor_metabolites_dict["ahba"]: 1}, 'ahba': {self.cofactor_metabolites_dict["ahba"]: -1, self.model.metabolites.get_by_id('atp_c'): -1, self.model.metabolites.get_by_id('amp_c'): 1, self.model.metabolites.get_by_id('ppi_c'): 1, self.model.metabolites.get_by_id('h2o_c'): 1}, 'acetyl': {self.model.metabolites.get_by_id('accoa_c'): -1, self.model.metabolites.get_by_id('coa_c'): 1, self.model.metabolites.get_by_id('co2_c'): 1}, 'shikimic_acid': {self.model.metabolites.get_by_id('skm_c'): -1, self.model.metabolites.get_by_id('atp_c'): -1, self.model.metabolites.get_by_id('amp_c'): 1, self.model.metabolites.get_by_id('ppi_c'): 1, self.model.metabolites.get_by_id('h2o_c'): 1}, 'fatty_acid': {self.model.metabolites.get_by_id('accoa_c'): -1, self.model.metabolites.get_by_id('malcoa_c'): -3, self.model.metabolites.get_by_id('co2_c'): 4, self.model.metabolites.get_by_id('coa_c'): 4}, 'NH2': {self.model.metabolites.get_by_id('malcoa_c'): -1, self.model.metabolites.get_by_id('co2_c'): 2, self.model.metabolites.get_by_id('gly_c'): -1, self.model.metabolites.get_by_id('coa_c'): 1 }, # https://www.sciencedirect.com/topics/immunology-and-microbiology/ascomycin 'pip': {self.model.metabolites.get_by_id('pyr_c'): -1, self.model.metabolites.get_by_id('lys__L_c'): -1, self.model.metabolites.get_by_id('h2o_c'): 1, self.model.metabolites.get_by_id('nadph_c'): -1, self.model.metabolites.get_by_id('nadp_c'): 1, self.model.metabolites.get_by_id('h_c'): -1, self.cofactor_metabolites_dict['pip']: 1}, 'NRPS_acylating_loader': {self.cofactor_metabolites_dict["fatty_acid_X"]: -1, self.model.metabolites.get_by_id("coa_c"): 1}, # R10992 in KEGG, could also be R10991 'abu': {self.model.metabolites.get_by_id('2obut_c'): -1, self.model.metabolites.get_by_id('ala__L_c'): -1, self.model.metabolites.get_by_id('pyr_c'): 1, self.cofactor_metabolites_dict["abu"]: 1}, } # beta_hydroxy_acids = { # '3hpp': self.model.metabolites.get_by_id("3hpp_c"), # 'bhb': self.model.metabolites.get_by_id("bhb_c"), # } self.fatty_acyl_CoAs = { "3hpcoa": self.model.metabolites.get_by_id("3hpcoa_c"), # "ptpcoa": self.model.metabolites.get_by_id("ptpcoa_c"), "hxcoa": self.model.metabolites.get_by_id("hxcoa_c"), # "hepcoa": self.model.metabolites.get_by_id("hepcoa_c"), "occoa": self.model.metabolites.get_by_id("occoa_c"), "dcacoa": self.model.metabolites.get_by_id("dcacoa_c") } # self.condensation_initiation_cofactors = { # self.model.metabolites.get_by_id('h2o_c'): 1 # } self.tailoring_metabolites_dict = { 'glucose_6_phosphate': self.model.metabolites.get_by_id('g6p_c'), '13biphosphoglycerate': self.model.metabolites.get_by_id('13dpg_c'), 'succinyl_coa': self.model.metabolites.get_by_id('succoa_c'), 'glycine': self.model.metabolites.get_by_id('gly_c'), 'coa': self.model.metabolites.get_by_id('coa_c'), 'co2': self.model.metabolites.get_by_id('co2_c'), 'atp': self.model.metabolites.get_by_id('atp_c'), 'amp': self.model.metabolites.get_by_id('amp_c'), 'ppi': self.model.metabolites.get_by_id('ppi_c'), 'pi': self.model.metabolites.get_by_id('pi_c'), 'nadh': self.model.metabolites.get_by_id('nadph_c'), 'nad': self.model.metabolites.get_by_id('nadp_c'), 'h+': self.model.metabolites.get_by_id('h_c'), 'h2o': self.model.metabolites.get_by_id('h2o_c') } self.tailoring_reactions_dict = { # remember to add the secondary metabolite to these reactions 'glycosyltransferase': { self.tailoring_metabolites_dict['glucose_6_phosphate']: -1, self.tailoring_metabolites_dict['h+']: 1, self.tailoring_metabolites_dict['pi']: 1 }, 'glycerol': { self.tailoring_metabolites_dict['13biphosphoglycerate']: -1.0, self.tailoring_metabolites_dict['pi']: 2.0, self.tailoring_metabolites_dict['h+']: -1.0, self.tailoring_metabolites_dict['nad']: 1.0, self.tailoring_metabolites_dict['nadh']: -1.0, }, 'ALA': { self.tailoring_metabolites_dict['succinyl_coa']: -1.0, self.tailoring_metabolites_dict['glycine']: -1.0, self.tailoring_metabolites_dict['atp']: -1.0, self.tailoring_metabolites_dict['ppi']: 1.0, self.tailoring_metabolites_dict['co2']: 1.0, self.tailoring_metabolites_dict['coa']: 1.0, self.tailoring_metabolites_dict['amp']: 1.0, self.tailoring_metabolites_dict['h2o']: 1.0 } }
def no_compartments(base): """ Provide a model with no compartments. """ base.add_metabolites([cobra.Metabolite('MNXM161')]) return base
def test_design_parent(): """ Design class should throw errors for cyclical parent designs, but accept valid hierarchy""" with FakeProjectContext() as ctx: project = GSMProject(ctx.path) # Create a design model = project.load_model() # Phosphoribulokinase reaction stoich = dict( atp_c=-1.0, ru5p__D_c=-1.0, adp_c=1.0, h_c=1.0, rb15bp_c=1.0, ) rb15bp = cobra.Metabolite(id='rb15bp_c', name='D-Ribulose 1,5-bisphosphate', formula='C5H8O11P2', charge=0) model.add_metabolites(rb15bp) pruk = cobra.Reaction(id="PRUK", name="Phosphoribulokinase reaction", lower_bound=-1000, upper_bound=1000) model.add_reactions([pruk]) pruk.add_metabolites(stoich) # Rubisco reaction (Ribulose-bisphosphate carboxylase) stoich = { "3pg_c": 2.0, "rb15bp_c": -1.0, "co2_c": -1.0, "h2o_c": -1.0, "h_c": 2.0 } rubisco = cobra.Reaction(id="RBPC", lower_bound=0, upper_bound=1000.0, name="Ribulose-bisphosphate carboxylase") model.add_reactions([rubisco]) rubisco.add_metabolites(stoich) model.genes.get_by_id("b3916").knock_out() model.genes.get_by_id("b1723").knock_out() model.genes.get_by_id("b1852").knock_out() model.reactions.EX_glc__D_e.lower_bound = -10.0 model.reactions.EX_nh4_e.lower_bound = -1000.0 design = project.save_design( model, 'cbb_cycle', 'calvin cycle', description='Reactions necissary for the calvin cycle in ecoli', overwrite=True) # Test html string # Test string representation str(design) design._repr_html_() # test jsonschema is valid design.validate_dict(design.to_dict()) # Create a child of this design model = project.load_design('cbb_cycle') reaction = cobra.Reaction(id="HMGCOASi", name="Hydroxymethylglutaryl CoA synthase") aacoa = cobra.Metabolite(id="aacoa_c", charge=-4, formula="C25H36N7O18P3S", name="Acetoacetyl-CoA") hmgcoa = cobra.Metabolite(id="hmgcoa_c", charge=-5, formula="C27H40N7O20P3S", name="Hydroxymethylglutaryl CoA") model.add_metabolites([aacoa, hmgcoa]) stoich = dict( aacoa_c=-1.0, accoa_c=-1.0, coa_c=1.0, h_c=1.0, h2o_c=-1.0, hmgcoa_c=1.0, ) model.add_reactions([reaction]) reaction.add_metabolites(stoich) reaction.lower_bound = -1000.0 reaction.upper_bound = 1000.0 mev__R = cobra.Metabolite(id="mev__R_c", name="R Mevalonate", charge=-1, formula="C6H11O4") model.add_metabolites([mev__R]) reaction = cobra.Reaction(id="HMGCOAR", name="Hydroxymethylglutaryl CoA reductase") reaction.lower_bound = -1000.0 reaction.upper_bound = 1000.0 stoich = dict(coa_c=-1.0, h_c=2.0, nadp_c=-2.0, nadph_c=2.0, hmgcoa_c=1.0, mev__R_c=-1.0) model.add_reactions([reaction]) reaction.add_metabolites(stoich) model.add_boundary(mev__R, type='sink') # add somewhere for mevalonate to go design = project.save_design( model, 'mevalonate_cbb', 'mevalonate production', parent='cbb_cycle', description='Reactions for the production of mevalonate', overwrite=True) des = project.get_design('mevalonate_cbb') inf = des.info pmodel = des.as_pathway_model() # TODO Test reactions are correct (counts should be correct) des.reactions_dataframe() des.genes_dataframe() des.to_dict() des.metabolites_dataframe() des.removed_genes # Check copying models works tmodel = cobra.Model() tmodel.id = 'test' des.add_to_model(tmodel, copy=True) # Requires a cobra model with pytest.raises(TypeError): des.add_to_model(model=None) # try to overwrite with pytest.raises(IOError): path = os.path.join(project._project_path, project.config.design_dir, '{}.json'.format(des.id)) des.to_json(path, overwrite=False) # Try to save a design with a bad parent with pytest.raises(DesignError): des.id = 'fuuuu' project.save_design( model, 'mevalonate_cbbd', 'mevalonate production', parent=des, description='Reactions for the production of mevalonate') _ = project.list_models _ = project.list_conditions
try: coeff = int(coeff_and_name[0]) met_name = ' '.join(coeff_and_name[1:]) except: coeff = 1 met_name = row[col] met_id = met_id_row[col] if met_id.endswith('_e0'): comp = 'e0' else: comp = 'c0' met_id = met_id + '_c0' if met_id in FBA_model.metabolites: met = FBA_model.metabolites.get_by_id(met_id) else: met = cobra.Metabolite(met_id, name=met_name, compartment=comp) if leftside: left_dict[met] = -1*coeff else: right_dict[met] = dir_coeff*coeff if dir_coeff == -1: for key,val in left_dict.items(): left_dict[key] = -1*val new_rxn = cobra.Reaction(rxn_id) FBA_model.add_reaction(new_rxn) new_rxn.add_metabolites(left_dict) new_rxn.add_metabolites(right_dict) print(new_rxn.build_reaction_string(use_metabolite_names = True)) try: row = next(rxn_reader) except:
def test_create_design(): """ Create a design that adds and removes reactions """ with FakeProjectContext() as ctx: project = GSMProject(ctx.path) model = project.model # Growth on xylose instead of glucose model.reactions.EX_xyl__D_e.lower_bound = -8.00 model.reactions.EX_glc__D_e.lower_bound = 0.0 project.save_conditions(model, 'xylose_growth') model.reactions.ATPM.lower_bound = 8.0 # Modified metabolite (all the water turned to hydrogen peroxide!?) model.metabolites.h2o_c.formula = 'H202' # Remove a reaction model.reactions.UDPGD.remove_from_model() # Add a reaction with a hetrologous metabolite metabolite = cobra.Metabolite() metabolite.id = 'test_c' metabolite.name = 'test_metabolite' metabolite.charge = 0 metabolite.formula = '' metabolite.notes = {} metabolite.annotation = {} metabolite.compartment = 'c' model.add_metabolites([metabolite]) reaction = cobra.Reaction() reaction.id = 'test_reaction' reaction.name = 'test' reaction.lower_bound = -1000.0 reaction.upper_bound = 1000.0 model.add_reactions([reaction]) reaction.add_metabolites({ 'h2o_c': -1, 'glx_c': -1, 'test_c': 1, 'o2_c': 1 }) model.add_boundary(metabolite, type='demand') # Add transporter for hetrologous metabolite project.save_design(model, 'test_design', 'test design 01', 'This is a test', conditions='xylose_growth') # Can't save a design twice with pytest.raises(IOError): project.save_design(model, 'test_design', 'test design 01', 'This is a test', conditions='xylose_growth') # Invalid base model with pytest.raises(KeyError): project.save_design(model, 'test_design22', 'test design 0221', 'This is a test', base_model='NONE') del model # assert design has been saved assert 'test_design' in project.list_designs assert os.path.exists( os.path.join(ctx.path, 'designs', 'test_design.json')) # Test loading the design into the default model nmodel = project.load_design('test_design') nmodel.reactions.get_by_id('test_reaction') nmodel.metabolites.get_by_id('test_c') # assert that the reaction is removed with pytest.raises(KeyError): nmodel.reactions.get_by_id('UDPGD') # assert that the metabolite is changed assert nmodel.metabolites.h2o_c.formula == 'H202' # assert that the reaction bounds have been modified assert nmodel.reactions.ATPM.lower_bound == 8.0 # check conditions are loaded assert nmodel.reactions.EX_xyl__D_e.lower_bound == -8.00 assert nmodel.reactions.EX_glc__D_e.lower_bound == 0.0
def make_L1_prob(self, df): """ Make L1-norm minimization problem to fit proteome to measured mass fractions in provided dataframe. Useful as a first step in StressME reconstruction as it identifies blocked proteins and reactions that would prevent simulation of certain stress responses """ me0 = self.me # Make copy of me or not...? me = cp.deepcopy(me0) # Reset obj coeffs for rxn in me.reactions: rxn.objective_coefficient = 0. # Add variable and constrain it to total proteome mass cons_p = cobra.Metabolite('p_eq_proteome_mass') p = cobra.Reaction('proteome_mass') p.lower_bound = 0. p.upper_bound = 1000. p.objective_coefficient = 0. p.add_metabolites({cons_p: 1.}) me.add_reactions([p]) for rxn in me.reactions.query('translation'): rxn.add_metabolites({cons_p: -rxn.translation_data.mass}) # Add constraint & aux var for each proteine mf to fit for ind, row in dfi.iterrows(): # Add constraints cons_l1 = cobra.Metabolite('error_' + row.locus_tag + '_1') cons_l2 = cobra.Metabolite('error_' + row.locus_tag + '_2') # Add auxiliary var s = cobra.Reaction('s_' + row.locus_tag) s.lower_bound = 0. s.upper_bound = 1000. s.add_metabolites({cons_l1: -1., cons_l2: -1.}) s.objective_coefficient = 1. # Add slack vars y1 = cobra.Reaction('y1_' + row.locus_tag) y1.lower_bound = 0. y1.upper_bound = 1000. y1.objective_coefficient = 0. y2 = cobra.Reaction('y2_' + row.locus_tag) y2.lower_bound = 0. y2.upper_bound = 1000. y2.objective_coefficient = 0. y1.add_metabolites({cons_l1: 1.}) y2.add_metabolites({cons_l2: 1.}) # Translation of i. rxn_trsli = me.reactions.get_by_id('translation_' + row.locus_tag) mfi = row.mf mwi = row.mw rxn_trsli.add_metabolites({cons_l1: mwi}) rxn_trsli.add_metabolites({cons_l2: -mwi}) # All proteins: can just use the p variable we made earlier p.add_metabolites({cons_l1: -mfi, cons_l2: mfi}) # Add remaining new columns me.add_reactions([s, y1, y2]) me_nlp_l1 = ME_NLP(me) self.me_nlp_l1 = me_nlp_l1 print 'Finished making L1-norm problem: self.me_nlp_l1' return me_nlp_l1
def load_scrumpy_model(filepath_or_string, name=None, model_id=None, media=None, objective_reactions=None, obj_dir='min', fixed_fluxes=None): """ Specify a base scrumpy structural model file and returns a cobra model. This hasn't be thoroughly tested so expect there to be bugs To get a solution from the returned object you need to specify nice stuff like the atpase reaction and media :param filepath_or_string: filepath or scrumpy string :param name: :param model_id: :param media: :param objective_reactions: :param obj_dir: :param fixed_fluxes: :return: """ if objective_reactions is None: objective_reactions = ['Biomass'] if fixed_fluxes is not None: assert isinstance(fixed_fluxes, dict) if os.path.isfile(filepath_or_string): rel_path = '/'.join( os.path.abspath(filepath_or_string).split('/')[:-1]) fp = os.path.abspath(filepath_or_string).split('/')[-1] reactions, metabolites, externals = parse_file(fp, rel_path=rel_path) else: rel_path = '.' reactions, metabolites, externals = parse_string(filepath_or_string, rel_path=rel_path) model = cobra.Model() for mid in metabolites: compartment = 'e' if mid[:2] == "x_" or mid in externals: compartment = 'e' m = cobra.Metabolite( id=mid, compartment=compartment) # ScrumPy does not use compartments model.add_metabolites([m]) added_reactions = [] for reaction in reactions: if reaction['id'] not in added_reactions: r = cobra.Reaction(reaction['id']) model.add_reactions([r]) r.lower_bound = reaction['bounds'][0] r.upper_bound = reaction['bounds'][1] r.add_metabolites(reaction['metabolites']) added_reactions.append(reaction['id']) # We need to add transporters for external metabolites not defined with the "External" directive for metabolite in model.metabolites: if metabolite.id[:2] == "x_": r = cobra.Reaction("EX_{}".format(metabolite.id[2:])) model.add_reactions([r]) r.lower_bound = -1000.0 r.upper_bound = 1000.0 r.add_metabolites({metabolite.id: -1.0}) added_reactions.append(r.id) if media is not None: for ex_reaction in model.exchanges: ex_reaction.lower_bound = media.get(ex_reaction.id, 0) if fixed_fluxes is not None: for rid, flux in fixed_fluxes.items(): try: reaction = model.reactions.get_by_id(rid) reaction.lower_bound = flux reaction.upper_bound = flux except KeyError: click.echo( 'Error setting fixed flux for reaction id {}, not found'. format(rid)) for oreact in objective_reactions: try: objreac = model.reactions.get_by_id(oreact) objreac.objective_coefficient = 1.0 except KeyError: print('Error setting objective, reaction name {} not found'.format( oreact)) model.objective.direction = obj_dir model.id = model_id model.name = name return model
def sum_outside_of_deviation(base): """ Same as above, yet here H2O is on the wrong side of the equation which will throw off the balance. """ met_a = cobra.Metabolite("lipid_c", "H744") met_b = cobra.Metabolite("protein_c", "H119") met_c = cobra.Metabolite("rna_c", "H496") met_d = cobra.Metabolite("dna_c", "H483") met_e = cobra.Metabolite("ash_c", "H80") met_f = cobra.Metabolite("cellwall_c", "H177") met_g = cobra.Metabolite("atp_c", "C10H12N5O13P3") met_h = cobra.Metabolite("adp_c", "C10H12N5O10P2") met_i = cobra.Metabolite("h_c", "H") met_j = cobra.Metabolite("h2o_c", "H2O") met_k = cobra.Metabolite("pi_c", "HO4P") # Reactions rxn_1 = cobra.Reaction("BIOMASS_TEST") rxn_1.add_metabolites({met_a: -0.133, met_b: -5.834, met_c: -0.1, met_d: -0.0625, met_e: -0.875, met_f: -0.2778, met_g: -30.0, met_h: 30.0, met_i: 30.0, met_j: 30.0, met_k: 30.0 }) base.add_reactions([rxn_1]) return base
def calculate_minspan_column(model_pickle, original_fluxes, column_index, N, cores, timelimit, verbose, solver_name): """calculate a single minspan column This function minimizes the number of nonzero elements in the column given by column_index while ensuring it remains a feasible vector and linearly independent of all other columns. """ solver = cobra.solvers.solver_dict[solver_name] n = N.shape[0] fluxes = original_fluxes.copy() # extract the old column and set it to 0 oldPath = fluxes[:, column_index].copy() # the old columm binOldPath = (oldPath != 0) * 1 # binary version fluxes[:, column_index] = 0 # set the column to 0 # calculate N2, which the new vector must not be orthogonal to a = N.T * fluxes # a = matrix(numpy.linalg.lstsq(N, matrix(fluxes))[0]) N2 = (N * matrix(null(a.T))) # ensure that the current solution is still feasible k = abs(oldPath * N2)[0, 0] # The MILP requires abs(N2 * x) >= 1. If k < 1, we can satisfy this # constraint by setting using x / k. However, we must ensure that by # scaling x we are not violating the lower or upper bounds. If we do, then # we must scale N2 if k < 1: if abs(oldPath).max() / k > default_bound: N2 *= 1.0 / k print "N2 scaled" else: oldPath *= 1.0 / k # construct the MILP problem problem = loads(model_pickle) # already has binary indicators # create constraint that N2 * fluxes != 0 # This will be done by specifying that abs(N2 * fluxes) > 1 fi_plus = cobra.Reaction("fi_plus") # boolean for N2 * fluxes > 1 fi_minus = cobra.Reaction("fi_minus") # boolean for N2 * fluxes < -1 make_binary(fi_plus) make_binary(fi_minus) fi_plus_constraint = cobra.Metabolite(id="fi_plus_constraint") fi_minus_constraint = cobra.Metabolite(id="fi_minus_constraint") fi_plus_constraint._constraint_sense = "G" fi_plus_constraint._bound = -1000 fi_minus_constraint._constraint_sense = "G" fi_minus_constraint._bound = -1000 fi_plus.add_metabolites({fi_plus_constraint: -1001}) fi_minus.add_metabolites({fi_minus_constraint: -1001}) problem.add_reactions([fi_plus, fi_minus]) for i, N2_val in enumerate(N2.T.tolist()[0]): problem.reactions[i].add_metabolites({ fi_plus_constraint: N2_val, fi_minus_constraint: -1 * N2_val }) # constrain either fi+ or fi- must be true or_constraint = cobra.Metabolite(id="or_constraint") or_constraint._bound = 1 or_constraint._constraint_sense = "G" fi_plus.add_metabolites({or_constraint: 1}) fi_minus.add_metabolites({or_constraint: 1}) # problem.update() # create the solver object lp = solver.create_problem(problem, objective_sense="minimize") # seed the variables with the old solution, and set extra arguments if solver_name.startswith("gurobi"): for i, variable in enumerate(lp.getVars()): if i < n: variable.Start = float(oldPath[i]) elif i < 2 * n: variable.Start = float(binOldPath[i - n]) solver.set_parameter(lp, "Method", 2) solver.set_parameter(lp, "Presolve", 2) elif solver_name.startswith("cplex"): # only seed cplex with the integer values # effort_level.solve_fixed tells cplex to solve the problem with these # values set, and then use that as an initial point for the entire # problem lp.MIP_starts.add((range(n, 2 * n), binOldPath.tolist()), lp.MIP_starts.effort_level.repair) # solve the model with the new parameters status = solver.solve_problem(lp, verbose=verbose, threads=cores, time_limit=timelimit, MIP_gap=0.001, MIP_gap_abs=0.999) solution = solver.format_solution(lp, problem) # extract the solution if solution.status in acceptable_status: bin_flux = array(solution.x[n:2 * n]) flux = array(solution.x[:n]) flux[bin_flux < 1e-3] = 0 # round down else: print solution.status if solver_name.startswith("cplex"): status = lp.solution.get_status_string() elif solver_name.startswith("gurobi"): status = lp.status raise Exception("Solver failed with status %s" % status) return flux
def create_community_model_with_balanced_growth( community: Community, growth_rate: float, organism_exchange_bounds: Dict[str, Tuple[float, float]] = {}) -> cobra.Model: """Creates a combined community model with an stoichiometric-matrix-integrated balanced growth approach. Description ---------- *Aim of this function* This method is aimed to generate a community model (as described in the community argument of this function) with a fixed growth rate, where this growth rate is the same for each of the community's species, in a way in which this growth rate constraint is directly integrated into the community model itself so that this model can be used e.g. with common Flux Balace Analysis methods and funtions. *Basic background behind this function* In community models, both the fraction of single species on the total community biomass as well as the growth rate of each single species can be optimized, which would lead to a computaionally quite complex bilinear optimization. Since balanced growth (i.e., no species grows faster or slower than other species so that no species is outcompeted in the long term) requires a fixed growth rate, only the optimization of the species fractions remains and, therefore, a computationally much more efficient linear optimiztaion. As described e.g. in (Koch et al., 2019), the resulting minimal flux of an irreversible reaction j in species i with a minimal flux greater than 0 is min_flux_j*f_i where f is the species's fraction, and, consequently, the resulting maximal flux (if the maximum is smalelr than inf) is max_flux_j*f_i. Usually, a special Flux Balance Analysis function introducing the fraction variables as added variables has to be written in order to run FBA with balanced growth. This unconvenient introduction of extra fraction variables can be ommitted by looking at the meaning of a species's fraction: Since the fractions of single species (if we give them the index i) f_i = µ_i/µ_community, where µ is the growth rate, and µ_community is fixed the only thing one to look at is µ_i, i.e. the "biomass contribution" of each species which is equal to their fraction. Hence, the simplified approach used heirin, which implicitly integrates the fraction variables into the stoichiometric matrix, is as follows: * For reactions with a minimal flux > 0: A new pseudo-metabolite is integrated as where it is produced by the reactions itself with the stoichiometry 1, and this metabolite is consumed by the reaction's species biomass reaction with the stoichiometry min_flux/fixed_growth_rate. Additionally, a pseudo-reaction consuming the pseudo-metabolite is added, too. * For reactions with a maximal flux < inf: A new pseudo-metabolite is integrated as where it is produced by the reactions itself with the stoichiometry 1, and this metabolite is consumed by the reaction's species biomass reaction with the stoichiometry max_flux/fixed_growth_rate. Additionally, a pseudo-reaction producing the pseudo-metabolite is added, too. *Principle of balanced growth constraint integration used herein* 1. All metabolites and reactions of the single species (as defined in the SingleModel instances of the given Community instance) are renamed with the addition of "_"+species_abbreviation (species_abbreviation as defined in the SingleModel instance) at the end of their IDs. 2. A new pseudo-metabolite called "COMMUNITY_BIOMASS" is added as product with stoichiometry 1 to all biomass reactions of the single species. 3. All single species biomass reactions get the lower flux bound of 0 and upper flux bound of infinite. 4. A new pseudo-reaction called "COMMUNITY_BIOMASS" is generated which has the upper and lower (i.e., fixed) flux equal to the given growth rate. This pseudo-reaction has the pseudo-metabolite "COMMUNITY_BIOMASS" as educt with a stoichiometry of 1. 5. The pseudo-reactions (called "Rsnake_UPPER_" for maximal flux bounds and "Rsnake_LOWER_" for minimal flux bounds) and pseudo-metabolites (called "Msnake_UPPER_" for maximal flux bounds and "Msnake_LOWER_" for minimal flux bounds) are introduced into the model as described in the previous section. 6. Exchange reactions between the single species comparments and the exchange compartment for all input/output metabolites from the respective SingleSpecies instances, as well as from the exchange compartment to the environment for all input/output metabolites of the Community instance. All previous standard exchanges of the single models (usually starting with "EX_") are deleted. The new exchange reactions start with EXCHG_in_ for input reactions (input to organism) and EXCHG_out_ for output metabolites (output from organism). Both types of EXCHG_ reactions are irreversible, and EXCHG_in_ reactions get an upper bound of 1000 mmol/(gDW*h) as standard in order to enforce the incorporation of Msnake_UPPER_ upper bound metabolites so that growth is actually enforced for all organisms in which reactions occur (which may not be the case if reactions with lower/upper bounds of inf are used). The principle used herein also means that if another growth rate is to be tested, a new model has to be generated for this specific growth rate. Return value ---------- A community model in the form of a cobrapy Model instance. This form of the community model - with its fixed organism ratios - can be e.g. used with the ASTHERISC package. Arguments ---------- * community: Community ~ A CommModelPy Community instance. * growth_rate: float ~ The growth rate to which the community shall be fixed. * organism_exchange_bounds: Dict[Tuple[float, float]] ~ A dictionary containing reaction IDs (which may also include the EXCHG_ reactions introduced by this function) as keys and, in the float tuple at index 0 a set lower bound and at index 1 a set upper bound. """ # Get number of SingleModel instances in Community instance num_single_models = len(community.single_models) # Check that an actual community is given if num_single_models <= 1: raise ValueError( "ERROR: Less than 2 models in given Community instance!") # Dictionary for later biomass introduction organism_id_biomass_reaction_id_mapping: Dict[str, str] = {} # Go through each SingleModel and change their cobra models for single_model in community.single_models: # Check that no underscores are in the organism IDs if "_" in single_model.species_abbreviation: raise ValueError( f"ERROR: Underscore in the given species abbreviation {single_model.species_abbreviation} D:" ) # Rename metabolites for metabolite in single_model.cobra_model.metabolites: metabolite.id += "_" + single_model.species_abbreviation # Rename reactions and change bounds for reaction in single_model.cobra_model.reactions: reaction.id += "_" + single_model.species_abbreviation # Delete standard exchange reactions with default exchange reaction ID prefix standard_exchanges = [ x for x in single_model.cobra_model.reactions if x.id.startswith(single_model.exchange_reaction_id_prefix) ] single_model.cobra_model.remove_reactions(standard_exchanges) # Add biomass reaction to dictionary organism_id_biomass_reaction_id_mapping[single_model.species_abbreviation] = single_model.objective_reaction_id + \ "_" + single_model.species_abbreviation # Standardize single-organism biomass reaction bounds biomass_reaction = single_model.cobra_model.reactions.get_by_id( organism_id_biomass_reaction_id_mapping[ single_model.species_abbreviation]) biomass_reaction.lower_bound = 0 biomass_reaction.upper_bound = float("inf") # Merge single models into a huge one merged_model = copy.deepcopy(community.single_models[0].cobra_model) for single_model in community.single_models[1:]: merged_model.merge(single_model.cobra_model, inplace=True) # Add community biomass metabolite community_biomass_metabolite = cobra.Metabolite( id="COMMUNITY_BIOMASS", name="Community biomass metabolite", compartment="exchg") merged_model.add_metabolites([community_biomass_metabolite]) for biomass_reaction_id in organism_id_biomass_reaction_id_mapping.values( ): biomass_reaction = merged_model.reactions.get_by_id( biomass_reaction_id) biomass_reaction.add_metabolites({ community_biomass_metabolite: 1, }) # Add whole community exchanges exchange_metabolite_ids = list( set(community.input_metabolite_ids + community.output_metabolite_ids)) for exchange_metabolite_id in exchange_metabolite_ids: # Set reaction instance reaction = cobra.Reaction( id=community.exchange_reaction_id_prefix + exchange_metabolite_id + "_" + community.exchange_compartment_id, name="Community exchange for " + exchange_metabolite_id) # Set reaction bounds is_input = exchange_metabolite_id in community.input_metabolite_ids if is_input: reaction.lower_bound = -float("inf") else: reaction.lower_bound = 0 is_output = exchange_metabolite_id in community.output_metabolite_ids if is_output: reaction.upper_bound = float("inf") else: reaction.upper_bound = 0 # Add metabolite to reaction exchange_metabolite = cobra.Metabolite( exchange_metabolite_id + "_" + community.exchange_compartment_id, name="Exchange compartment metabolite " + exchange_metabolite_id, compartment="exchange") reaction.add_metabolites({ exchange_metabolite: -1, }) # Add reaction to model merged_model.add_reactions([reaction]) # Split reversible reactions merged_model = split_reversible_organism_reactions( merged_model, organism_id_biomass_reaction_id_mapping) # Add community biomass reaction and set it to the given growth rate community_biomass_reaction = cobra.Reaction( id="COMMUNITY_BIOMASS", name="Biomass reaction for the whole community") community_biomass_reaction.lower_bound = growth_rate community_biomass_reaction.upper_bound = growth_rate community_biomass_reaction.add_metabolites({ community_biomass_metabolite: -1, }) # Add single species <-> exchange compartment exchanges for single_model in community.single_models: exchange_metabolite_ids = list( set(single_model.input_metabolite_ids + single_model.output_metabolite_ids)) exchange_metabolite_ids = [ x + "_" + single_model.species_abbreviation for x in exchange_metabolite_ids ] for exchange_metabolite_id in exchange_metabolite_ids: single_model_base_metabolite_id = exchange_metabolite_id.replace( "_" + single_model.species_abbreviation, "") exchange_compartment_metabolite_id = single_model.model_metabolite_to_exchange_id_mapping[ single_model_base_metabolite_id] # Add metabolites to reaction try: internal_metabolite = merged_model.metabolites.get_by_id( exchange_metabolite_id) except: print("ERROR: Internal exchange metabolite ID " + exchange_metabolite_id + "does not exist!") species_exchange_metabolite_id = exchange_compartment_metabolite_id + "_" + community.exchange_compartment_id try: exchange_compartment_metabolite = merged_model.metabolites.get_by_id( species_exchange_metabolite_id) except: new_species_exchange_metabolite = cobra.Metabolite( id=species_exchange_metabolite_id, compartment="exchg") merged_model.add_metabolites(new_species_exchange_metabolite) exchange_compartment_metabolite = merged_model.metabolites.get_by_id( species_exchange_metabolite_id) # Set reaction bounds is_input = single_model_base_metabolite_id in single_model.input_metabolite_ids is_output = single_model_base_metabolite_id in single_model.output_metabolite_ids # Set reaction instance if is_input: reaction_in = cobra.Reaction( id="EXCHG_in_" + single_model.species_abbreviation + "_" + exchange_metabolite_id.replace( "_" + single_model.species_abbreviation, "") + "_to_" + exchange_compartment_metabolite_id, name= f"Input exchange for {exchange_metabolite_id} from single species {single_model.species_abbreviation} to exchange compartment" ) reaction_in.add_metabolites({ exchange_compartment_metabolite: -1, internal_metabolite: 1, }) reaction_in.lower_bound = 0 reaction_in.upper_bound = 1000 merged_model.add_reactions([reaction_in]) if is_output: reaction_out = cobra.Reaction( id="EXCHG_out_" + single_model.species_abbreviation + "_" + exchange_metabolite_id.replace( "_" + single_model.species_abbreviation, "") + "_to_" + exchange_compartment_metabolite_id, name= f"Output exchange for {exchange_metabolite_id} from single species {single_model.species_abbreviation} to exchange compartment" ) reaction_out.add_metabolites({ internal_metabolite: -1, exchange_compartment_metabolite: 1, }) reaction_out.lower_bound = 0 reaction_out.upper_bound = float("inf") merged_model.add_reactions([reaction_out]) # Add organism-specific reaction bounds bound_reaction_ids = [ x.id for x in merged_model.reactions if x.id in list(organism_exchange_bounds.keys()) ] for bound_reaction_id in bound_reaction_ids: lower_bound = organism_exchange_bounds[bound_reaction_id][0] upper_bound = organism_exchange_bounds[bound_reaction_id][1] reaction = merged_model.reactions.get_by_id(bound_reaction_id) reaction.lower_bound = lower_bound reaction.upper_bound = upper_bound # Add minimal and maximal bound constraints using pseudo-metabolites and pseudo-reactions reaction_ids = [x.id for x in merged_model.reactions] for reaction_id in reaction_ids: reaction = merged_model.reactions.get_by_id(reaction_id) # Check organism ID if reaction_id.startswith("EXCHG"): reaction_organism_id = reaction.id.split("_")[2] if reaction_organism_id not in organism_id_biomass_reaction_id_mapping.keys( ): continue else: reaction_organism_id = reaction.id.split("_")[-1] if reaction_organism_id not in organism_id_biomass_reaction_id_mapping.keys( ): continue organism_biomass_reaction = merged_model.reactions.get_by_id( organism_id_biomass_reaction_id_mapping[reaction_organism_id]) # Add maximal bound constraint if reaction.upper_bound != float("inf"): # Add ~M new_metabolite = cobra.Metabolite( id="Msnake_UPPER_" + reaction.id, name="Upper bound enforcing metabolite for " + reaction.id, compartment="exchg") # Add ~r new_reaction = cobra.Reaction( id="Rsnake_UPPER_" + reaction.id, name= "Delivery reaction of upper bound enforcing metabolite for " + reaction.id) # Add ~M to original reaction reaction.add_metabolites({ new_metabolite: 1, }) organism_biomass_reaction.add_metabolites({ new_metabolite: -reaction.upper_bound / growth_rate, }) new_reaction.add_metabolites({ new_metabolite: 1, }) merged_model.add_reactions([new_reaction]) reaction.upper_bound = float("inf") # Add minimal bound constraint if (reaction.lower_bound != -float("inf")) and (reaction.lower_bound != 0.0): # Add ~M new_metabolite = cobra.Metabolite( id="Msnake_LOWER_" + reaction.id, name="Lower bound enforcing metabolite for " + reaction.id, compartment="exchg") # Add ~r new_reaction = cobra.Reaction( id="Rsnake_LOWER_" + reaction.id, name= "Consuming reaction of lower bound enforcing metabolite for " + reaction.id) # Add ~M to original reaction reaction.add_metabolites({ new_metabolite: 1, }) organism_biomass_reaction.add_metabolites({ new_metabolite: -reaction.lower_bound / growth_rate, }) new_reaction.add_metabolites({ new_metabolite: -1, }) merged_model.add_reactions([new_reaction]) reaction.lower_bound = 0 # Set merged model's objective to community biomass merged_model.add_reactions([community_biomass_reaction]) merged_model.objective = "COMMUNITY_BIOMASS" return merged_model
def three_present(base): base.add_metabolites([ cobra.Metabolite(id="M{0:d}".format(i), formula="CH4", charge=-1) for i in range(1, 4) ]) return base