def test_complicated_model(self): """Difficult model since the online mean calculation is numerically unstable so many samples weakly violate the equality constraints.""" model = Model('flux_split') reaction1 = Reaction('V1') reaction2 = Reaction('V2') reaction3 = Reaction('V3') reaction1.lower_bound = 0 reaction2.lower_bound = 0 reaction3.lower_bound = 0 reaction1.upper_bound = 6 reaction2.upper_bound = 8 reaction3.upper_bound = 10 A = Metabolite('A') reaction1.add_metabolites({A: -1}) reaction2.add_metabolites({A: -1}) reaction3.add_metabolites({A: 1}) model.add_reactions([reaction1]) model.add_reactions([reaction2]) model.add_reactions([reaction3]) optgp = OptGPSampler(model, 1, seed=42) achr = ACHRSampler(model, seed=42) optgp_samples = optgp.sample(100) achr_samples = achr.sample(100) assert any(optgp_samples.corr().abs() < 1.0) assert any(achr_samples.corr().abs() < 1.0) # > 95% are valid assert (sum(optgp.validate(optgp_samples) == "v") > 95) assert (sum(achr.validate(achr_samples) == "v") > 95)
def test_complicated_model(self): """Difficult model since the online mean calculation is numerically unstable so many samples weakly violate the equality constraints.""" model = Model('flux_split') reaction1 = Reaction('V1') reaction2 = Reaction('V2') reaction3 = Reaction('V3') reaction1.lower_bound = 0 reaction2.lower_bound = 0 reaction3.lower_bound = 0 reaction1.upper_bound = 6 reaction2.upper_bound = 8 reaction3.upper_bound = 10 A = Metabolite('A') reaction1.add_metabolites({A: -1}) reaction2.add_metabolites({A: -1}) reaction3.add_metabolites({A: 1}) model.add_reactions([reaction1]) model.add_reactions([reaction2]) model.add_reactions([reaction3]) optgp = OptGPSampler(model, 1, seed=42) achr = ACHRSampler(model, seed=42) optgp_samples = optgp.sample(100) achr_samples = achr.sample(100) assert any(optgp_samples.corr().abs() < 1.0) assert any(achr_samples.corr().abs() < 1.0) # > 95% are valid assert(sum(optgp.validate(optgp_samples) == "v") > 95) assert(sum(achr.validate(achr_samples) == "v") > 95)
def constrainSumOfFluxes(cobra_model, rxn2avoid, SFvalue, objvalue): from cobra.core import Metabolite, Reaction temp = cobra_model.copy() SFMet = Metabolite("SFMet", name="Sum of fluxes pseudometabolite", compartment="c2") for rxn in cobra_model.reactions: if not rxn2avoid.__contains__(rxn.id): if rxn.id.__contains__("reverse"): temp.reactions.get_by_id(rxn.id).add_metabolites({SFMet: -1}) else: temp.reactions.get_by_id(rxn.id).add_metabolites({SFMet: 1}) SFRxn = Reaction("SFRxn", name="Sum of fluxes pseudoreaction") SFRxn.add_metabolites({SFMet: -1}) SFRxn.lower_bound = SFvalue SFRxn.upper_bound = SFvalue temp.add_reaction(SFRxn) if (not objvalue == "") and (len( [rxn for rxn in temp.reactions if rxn.objective_coefficient == 1]) == 1): for rxn in [ rxn for rxn in temp.reactions if rxn.objective_coefficient == 1 ]: rxn.lower_bound = float(objvalue) rxn.upper_bound = float(objvalue) return temp
def test__normalize_pseudoreaction_exchange(): reaction = Reaction('EX_gone') reaction.add_metabolites({Metabolite('glu__L_e'): -1}) reaction.lower_bound = -1000 reaction.upper_bound = 0 pseudo_id = _normalize_pseudoreaction(reaction.id, reaction) assert pseudo_id == 'EX_glu__L_e' assert reaction.subsystem == 'Extracellular exchange'
def test__normalize_pseudoreaction_sink(): reaction = Reaction('SInk_gone') reaction.add_metabolites({Metabolite('glu__L_c'): -1}) reaction.lower_bound = -1000 reaction.upper_bound = 0 pseudo_id = _normalize_pseudoreaction(reaction.id, reaction) assert pseudo_id == 'SK_glu__L_c' assert reaction.subsystem == 'Intracellular source/sink'
def test__normalize_pseudoreaction_demand(): reaction = Reaction('DM_gone') reaction.add_metabolites({Metabolite('glu__L_c'): -1}) reaction.lower_bound = 0 reaction.upper_bound = 1000 pseudo_id = _normalize_pseudoreaction(reaction.id, reaction) assert pseudo_id == 'DM_glu__L_c' assert reaction.subsystem == 'Intracellular demand'
def tiny_toy_model(): model = Model("Toy Model") m1 = Metabolite("M1") d1 = Reaction("ex1") d1.add_metabolites({m1: -1}) d1.upper_bound = 0 d1.lower_bound = -1000 model.add_reactions([d1]) return model
def test__normalize_pseudoreaction_demand_reversed(): reaction = Reaction('DM_gone') reaction.add_metabolites({Metabolite('glu__L_c'): 1}) reaction.lower_bound = -1000 reaction.upper_bound = 0 pseudo_id = _normalize_pseudoreaction(reaction.id, reaction) assert list(reaction.metabolites.values()) == [-1] assert reaction.lower_bound == 0 assert reaction.upper_bound == 1000 assert pseudo_id == 'DM_glu__L_c'
def test__normalize_pseudoreaction_demand_reversed_prefer_sink_name(): reaction = Reaction('sink_gone') reaction.add_metabolites({Metabolite('glu__L_c'): 1}) reaction.lower_bound = -1000 reaction.upper_bound = 0 _normalize_pseudoreaction(reaction) assert list(reaction.metabolites.values()) == [-1] assert reaction.lower_bound == 0 assert reaction.upper_bound == 1000 assert reaction.id == 'SK_glu__L_c'
def test__normalize_pseudoreaction_sink_reversed(): reaction = Reaction('Sink_gone') reaction.add_metabolites({Metabolite('glu__L_c'): 1}) reaction.lower_bound = 0 reaction.upper_bound = 50 pseudo_id = _normalize_pseudoreaction(reaction.id, reaction) assert list(reaction.metabolites.values()) == [-1] assert reaction.lower_bound == -50 assert reaction.upper_bound == 0 assert pseudo_id == 'SK_glu__L_c'
def test__normalize_pseudoreaction_exchange_reversed(): reaction = Reaction('EX_gone') reaction.add_metabolites({Metabolite('glu__L_e'): 1}) reaction.lower_bound = 0 reaction.upper_bound = 1000 pseudo_id = _normalize_pseudoreaction(reaction.id, reaction) assert pseudo_id == 'EX_glu__L_e' assert reaction.lower_bound == -1000 assert reaction.upper_bound == 0 assert list(reaction.metabolites.values()) == [-1]
def test_make_lhs_irreversible_reversible(model): rxn = Reaction('test') rxn.add_metabolites({model.metabolites[0]: -1., model.metabolites[1]: 1.}) rxn.lower_bound = -1000. rxn.upper_bound = -100 model.add_reaction(rxn) assert rxn.lower_bound == -1000. assert rxn.upper_bound == -100. assert rxn.forward_variable.lb == 0. assert rxn.forward_variable.ub == 0. assert rxn.reverse_variable.lb == 100. assert rxn.reverse_variable.ub == 1000. rxn.upper_bound = 666. assert rxn.lower_bound == -1000. assert rxn.upper_bound == 666. assert rxn.forward_variable.lb == 0. assert rxn.forward_variable.ub == 666 assert rxn.reverse_variable.lb == 0. assert rxn.reverse_variable.ub == 1000.
def construct_loopless_model(cobra_model): """Construct a loopless model. This adds MILP constraints to prevent flux from proceeding in a loop, as done in http://dx.doi.org/10.1016/j.bpj.2010.12.3707 Please see the documentation for an explanation of the algorithm. This must be solved with an MILP capable solver. """ # copy the model and make it irreversible model = cobra_model.copy() convert_to_irreversible(model) max_ub = max(model.reactions.list_attr("upper_bound")) # a dict for storing S^T thermo_stoic = { "thermo_var_" + metabolite.id: {} for metabolite in model.metabolites } # Slice operator is so that we don't get newly added metabolites original_metabolites = model.metabolites[:] for reaction in model.reactions[:]: # Boundary reactions are not subjected to these constraints if len(reaction._metabolites) == 1: continue # populate the S^T dict bound_id = "thermo_bound_" + reaction.id for met, stoic in iteritems(reaction._metabolites): thermo_stoic["thermo_var_" + met.id][bound_id] = stoic # I * 1000 > v --> I * 1000 - v > 0 reaction_ind = Reaction(reaction.id + "_indicator") reaction_ind.variable_kind = "integer" reaction_ind.upper_bound = 1 reaction_ub = Metabolite(reaction.id + "_ind_ub") reaction_ub._constraint_sense = "G" reaction.add_metabolites({reaction_ub: -1}) reaction_ind.add_metabolites({reaction_ub: max_ub}) # This adds a compensating term for 0 flux reactions, so we get # S^T x - (1 - I) * 1001 < -1 which becomes # S^T x < 1000 for 0 flux reactions and # S^T x < -1 for reactions with nonzero flux. reaction_bound = Metabolite(bound_id) reaction_bound._constraint_sense = "L" reaction_bound._bound = max_ub reaction_ind.add_metabolites({reaction_bound: max_ub + 1}) model.add_reaction(reaction_ind) for metabolite in original_metabolites: metabolite_var = Reaction("thermo_var_" + metabolite.id) metabolite_var.lower_bound = -max_ub model.add_reaction(metabolite_var) metabolite_var.add_metabolites({ model.metabolites.get_by_id(k): v for k, v in iteritems(thermo_stoic[metabolite_var.id]) }) return model
def test_make_lhs_irreversible_reversible(model): rxn = Reaction('test') rxn.add_metabolites( {model.metabolites[0]: -1., model.metabolites[1]: 1.}) rxn.lower_bound = -1000. rxn.upper_bound = -100 model.add_reaction(rxn) assert rxn.lower_bound == -1000. assert rxn.upper_bound == -100. assert rxn.forward_variable.lb == 0. assert rxn.forward_variable.ub == 0. assert rxn.reverse_variable.lb == 100. assert rxn.reverse_variable.ub == 1000. rxn.upper_bound = 666. assert rxn.lower_bound == -1000. assert rxn.upper_bound == 666. assert rxn.forward_variable.lb == 0. assert rxn.forward_variable.ub == 666 assert rxn.reverse_variable.lb == 0. assert rxn.reverse_variable.ub == 1000.
def construct_loopless_model(cobra_model): """Construct a loopless model. This adds MILP constraints to prevent flux from proceeding in a loop, as done in http://dx.doi.org/10.1016/j.bpj.2010.12.3707 Please see the documentation for an explanation of the algorithm. This must be solved with an MILP capable solver. """ # copy the model and make it irreversible model = cobra_model.copy() convert_to_irreversible(model) max_ub = max(model.reactions.list_attr("upper_bound")) # a dict for storing S^T thermo_stoic = {"thermo_var_" + metabolite.id: {} for metabolite in model.metabolites} # Slice operator is so that we don't get newly added metabolites original_metabolites = model.metabolites[:] for reaction in model.reactions[:]: # Boundary reactions are not subjected to these constraints if len(reaction._metabolites) == 1: continue # populate the S^T dict bound_id = "thermo_bound_" + reaction.id for met, stoic in iteritems(reaction._metabolites): thermo_stoic["thermo_var_" + met.id][bound_id] = stoic # I * 1000 > v --> I * 1000 - v > 0 reaction_ind = Reaction(reaction.id + "_indicator") reaction_ind.variable_kind = "integer" reaction_ind.upper_bound = 1 reaction_ub = Metabolite(reaction.id + "_ind_ub") reaction_ub._constraint_sense = "G" reaction.add_metabolites({reaction_ub: -1}) reaction_ind.add_metabolites({reaction_ub: max_ub}) # This adds a compensating term for 0 flux reactions, so we get # S^T x - (1 - I) * 1001 < -1 which becomes # S^T x < 1000 for 0 flux reactions and # S^T x < -1 for reactions with nonzero flux. reaction_bound = Metabolite(bound_id) reaction_bound._constraint_sense = "L" reaction_bound._bound = max_ub reaction_ind.add_metabolites({reaction_bound: max_ub + 1}) model.add_reaction(reaction_ind) for metabolite in original_metabolites: metabolite_var = Reaction("thermo_var_" + metabolite.id) metabolite_var.lower_bound = -max_ub model.add_reaction(metabolite_var) metabolite_var.add_metabolites( {model.metabolites.get_by_id(k): v for k, v in iteritems(thermo_stoic[metabolite_var.id])}) return model
def test__normalize_pseudoreaction_atpm_reversed(): reaction = Reaction('notATPM') reaction.add_metabolites({Metabolite('atp_c'): 1, Metabolite('h2o_c'): 1, Metabolite('pi_c'): -1, Metabolite('h_c'): -1, Metabolite('adp_c'): -1}) reaction.lower_bound = -50 reaction.upper_bound = 100 _normalize_pseudoreaction(reaction) assert reaction.id == 'ATPM' assert reaction.lower_bound == -100 assert reaction.upper_bound == 50
def solver_test(request): solver = solvers.solver_dict[request.param] old_solution = 0.8739215 infeasible_model = Model() metabolite_1 = Metabolite("met1") reaction_1 = Reaction("rxn1") reaction_2 = Reaction("rxn2") reaction_1.add_metabolites({metabolite_1: 1}) reaction_2.add_metabolites({metabolite_1: 1}) reaction_1.lower_bound = 1 reaction_2.upper_bound = 2 infeasible_model.add_reactions([reaction_1, reaction_2]) return solver, old_solution, infeasible_model
def test__normalize_pseudoreaction_atpm_reversed(): reaction = Reaction('notATPM') reaction.add_metabolites({Metabolite('atp_c'): 1, Metabolite('h2o_c'): 1, Metabolite('pi_c'): -1, Metabolite('h_c'): -1, Metabolite('adp_c'): -1}) reaction.lower_bound = -50 reaction.upper_bound = 100 pseudo_id = _normalize_pseudoreaction(reaction.id, reaction) assert pseudo_id == 'ATPM' assert reaction.lower_bound == -100 assert reaction.upper_bound == 50
def construct_difference_model(model_1, model_2, norm_type='euclidean'): """Combine two models into a larger model that is designed to calculate differences between the models """ #Get index mappings common_dict = {} #Using copies of the models so things are modified above combined_model = model_1 = model_1.copy() model_2 = model_2.copy() for reaction_1 in model_1.reactions: try: reaction_2 = model_2.reactions.get_by_id(reaction_1.id) common_dict[reaction_1] = reaction_2 except: continue #Add a prefix in front of the mutant_model metabolites and reactions to prevent #name collisions in DictList for the_dict_list in [model_2.metabolites, model_2.reactions]: [setattr(x, 'id', 'mutant_%s'%x.id) for x in the_dict_list] the_dict_list._generate_index() #Update the DictList.dicts combined_model.add_reactions(model_2.reactions) [setattr(x, 'objective_coefficient', 0.) for x in combined_model.reactions] #Add in the difference reactions. The mutant reactions and metabolites are already added. #This must be a list to maintain the correct order when adding the difference_metabolites difference_reactions = [] #Add the difference reactions at the end to speed things up difference_metabolites = [] for reaction_1, reaction_2 in iteritems(common_dict): reaction_1._difference_partner = reaction_2 reaction_2._difference_partner = reaction_1 difference_reaction = Reaction('difference_%s'%reaction_1.id) difference_reactions.append(difference_reaction) difference_reaction.upper_bound = 100000 difference_reaction.lower_bound = -1* difference_reaction.upper_bound difference_metabolite = Metabolite('difference_%s'%reaction_1.id) difference_metabolites.append(difference_metabolite) if norm_type == 'linear': difference_metabolite._constraint_sense = 'G' reaction_1.add_metabolites({difference_metabolite: -1.}, add_to_container_model=False) reaction_2.add_metabolites({difference_metabolite: 1.}, add_to_container_model=False) difference_reaction.add_metabolites({difference_metabolite: 1.}, add_to_container_model=False) combined_model.add_metabolites(difference_metabolites) combined_model.add_reactions(difference_reactions) return(combined_model)
def convert_to_irreversible(model): """Split reversible reactions into two irreversible reactions These two reactions will proceed in opposite directions. This guarentees that all reactions in the model will only allow positive flux values, which is useful for some modeling problems. Arguments ---------- * model: cobra.Model ~ A Model object which will be modified in place. """ #warn("deprecated, not applicable for optlang solvers", DeprecationWarning) reactions_to_add = [] coefficients = {} for reaction in model.reactions: # If a reaction is reverse only, the forward reaction (which # will be constrained to 0) will be left in the model. if reaction.lower_bound < 0 and reaction.upper_bound > 0: reverse_reaction = Reaction(reaction.id + "_reverse") reverse_reaction.lower_bound = max(0, -reaction.upper_bound) reverse_reaction.upper_bound = -reaction.lower_bound coefficients[ reverse_reaction] = reaction.objective_coefficient * -1 reaction.lower_bound = max(0, reaction.lower_bound) reaction.upper_bound = max(0, reaction.upper_bound) # Make the directions aware of each other reaction.notes["reflection"] = reverse_reaction.id reverse_reaction.notes["reflection"] = reaction.id reaction_dict = { k: v * -1 for k, v in reaction._metabolites.items() } reverse_reaction.add_metabolites(reaction_dict) reverse_reaction._model = reaction._model reverse_reaction._genes = reaction._genes for gene in reaction._genes: gene._reaction.add(reverse_reaction) reverse_reaction.subsystem = reaction.subsystem reverse_reaction._gene_reaction_rule = reaction._gene_reaction_rule reactions_to_add.append(reverse_reaction) model.add_reactions(reactions_to_add) set_objective(model, coefficients, additive=True)
def add_reaction(model, id, name, sparse, lower_bound=0, upper_bound=1000): """ Adds a reaction to the model """ # convert the sparse representation using the metabolites in the model for key in sparse.keys(): if key not in model.metabolites: raise Exception("cannot find the cytoplasmic metabolite %s in the model" % key) r = dict([(model.metabolites[model.metabolites.index(key)], val) for key, val in sparse.iteritems()]) reaction = Reaction(name) reaction.id = id reaction.add_metabolites(r) reaction.lower_bound = lower_bound reaction.upper_bound = upper_bound model.add_reactions([reaction]) return reaction
def test_make_lhs_irreversible_reversible(model: Model) -> None: """Test reaction LHS irreversibility to reversibility.""" rxn = Reaction("test") rxn.add_metabolites({ model.metabolites[0]: -1.0, model.metabolites[1]: 1.0 }) rxn.bounds = (-1000.0, -100) model.add_reaction(rxn) assert rxn.lower_bound == -1000.0 assert rxn.upper_bound == -100.0 assert rxn.forward_variable.lb == 0.0 assert rxn.forward_variable.ub == 0.0 assert rxn.reverse_variable.lb == 100.0 assert rxn.reverse_variable.ub == 1000.0 rxn.upper_bound = 666.0 assert rxn.lower_bound == -1000.0 assert rxn.upper_bound == 666.0 assert rxn.forward_variable.lb == 0.0 assert rxn.forward_variable.ub == 666 assert rxn.reverse_variable.lb == 0.0 assert rxn.reverse_variable.ub == 1000.0
def convert_to_irreversible(cobra_model): """Split reversible reactions into two irreversible reactions These two reactions will proceed in opposite directions. This guarentees that all reactions in the model will only allow positive flux values, which is useful for some modeling problems. cobra_model: A Model object which will be modified in place. """ warn("deprecated, not applicable for optlang solvers", DeprecationWarning) reactions_to_add = [] coefficients = {} for reaction in cobra_model.reactions: # If a reaction is reverse only, the forward reaction (which # will be constrained to 0) will be left in the model. if reaction.lower_bound < 0: reverse_reaction = Reaction(reaction.id + "_reverse") reverse_reaction.lower_bound = max(0, -reaction.upper_bound) reverse_reaction.upper_bound = -reaction.lower_bound coefficients[ reverse_reaction] = reaction.objective_coefficient * -1 reaction.lower_bound = max(0, reaction.lower_bound) reaction.upper_bound = max(0, reaction.upper_bound) # Make the directions aware of each other reaction.notes["reflection"] = reverse_reaction.id reverse_reaction.notes["reflection"] = reaction.id reaction_dict = {k: v * -1 for k, v in iteritems(reaction._metabolites)} reverse_reaction.add_metabolites(reaction_dict) reverse_reaction._model = reaction._model reverse_reaction._genes = reaction._genes for gene in reaction._genes: gene._reaction.add(reverse_reaction) reverse_reaction.subsystem = reaction.subsystem reverse_reaction._gene_reaction_rule = reaction._gene_reaction_rule reactions_to_add.append(reverse_reaction) cobra_model.add_reactions(reactions_to_add) set_objective(cobra_model, coefficients, additive=True)
model.metabolites.GLN_c: 0.1325494187, model.metabolites.GLT_c: 0.2261465373, model.metabolites.GLY_c: 0.2309411553, model.metabolites.HIS_c: 0.1673732646, model.metabolites.ILE_c: 0.1454255314, model.metabolites.LEU_c: 0.0053400685, model.metabolites.LYS_c: 0.3415370304, model.metabolites.MET_c: 0.1420323181, model.metabolites.PHE_c: 0.1980982902, model.metabolites.SER_c: 0.3368402626, model.metabolites.THR_c: 0.2365218861, model.metabolites.TYR_c: 0.2071316851, model.metabolites.VAL_c: 0.158571619 }) rxn.lower_bound = 0 rxn.upper_bound = 1000 model.add_reaction(rxn) #check reactions #print rxn.reaction #If we assume lipid turnover rate is 0.2 hr−1 and a cell's lipid content is # 164.80 ng.cell−1, lipid degradation rate can be assumed to be # 32.96 ng.cell−1.hr−1. Similarly if we assume protein turnover rate is # 0.5 hr−1 and a cell's protien content is 0.057 ng.cell−1, protein degradation # rate can be assumed to be 0.029 ng.cell−1.hr model2 = modelMatureCell(model, proteinDegrdationRate=32.96, lipidDegrdationRate=0.029) #print summary of flux distribution model2.summary()
def from_mat_struct(mat_struct, model_id=None, inf=inf): """create a model from the COBRA toolbox struct The struct will be a dict read in by scipy.io.loadmat """ m = mat_struct if m.dtype.names is None: raise ValueError("not a valid mat struct") if not {"rxns", "mets", "S", "lb", "ub"} <= set(m.dtype.names): raise ValueError("not a valid mat struct") if "c" in m.dtype.names: c_vec = m["c"][0, 0] else: c_vec = None warn("objective vector 'c' not found") model = Model() if model_id is not None: model.id = model_id elif "description" in m.dtype.names: description = m["description"][0, 0][0] if not isinstance(description, string_types) and len(description) > 1: model.id = description[0] warn("Several IDs detected, only using the first.") else: model.id = description else: model.id = "imported_model" for i, name in enumerate(m["mets"][0, 0]): new_metabolite = Metabolite() new_metabolite.id = str(name[0][0]) if all(var in m.dtype.names for var in ['metComps', 'comps', 'compNames']): comp_index = m["metComps"][0, 0][i][0] - 1 new_metabolite.compartment = m['comps'][0, 0][comp_index][0][0] if new_metabolite.compartment not in model.compartments: comp_name = m['compNames'][0, 0][comp_index][0][0] model.compartments[new_metabolite.compartment] = comp_name else: new_metabolite.compartment = _get_id_compartment(new_metabolite.id) if new_metabolite.compartment not in model.compartments: model.compartments[ new_metabolite.compartment] = new_metabolite.compartment try: new_metabolite.name = str(m["metNames"][0, 0][i][0][0]) except (IndexError, ValueError): pass try: new_metabolite.formula = str(m["metFormulas"][0][0][i][0][0]) except (IndexError, ValueError): pass try: new_metabolite.charge = float(m["metCharge"][0, 0][i][0]) int_charge = int(new_metabolite.charge) if new_metabolite.charge == int_charge: new_metabolite.charge = int_charge except (IndexError, ValueError): pass model.add_metabolites([new_metabolite]) new_reactions = [] coefficients = {} for i, name in enumerate(m["rxns"][0, 0]): new_reaction = Reaction() new_reaction.id = str(name[0][0]) new_reaction.lower_bound = float(m["lb"][0, 0][i][0]) new_reaction.upper_bound = float(m["ub"][0, 0][i][0]) if isinf(new_reaction.lower_bound) and new_reaction.lower_bound < 0: new_reaction.lower_bound = -inf if isinf(new_reaction.upper_bound) and new_reaction.upper_bound > 0: new_reaction.upper_bound = inf if c_vec is not None: coefficients[new_reaction] = float(c_vec[i][0]) try: new_reaction.gene_reaction_rule = str(m['grRules'][0, 0][i][0][0]) except (IndexError, ValueError): pass try: new_reaction.name = str(m["rxnNames"][0, 0][i][0][0]) except (IndexError, ValueError): pass try: new_reaction.subsystem = str(m['subSystems'][0, 0][i][0][0]) except (IndexError, ValueError): pass new_reactions.append(new_reaction) model.add_reactions(new_reactions) set_objective(model, coefficients) coo = scipy_sparse.coo_matrix(m["S"][0, 0]) for i, j, v in zip(coo.row, coo.col, coo.data): model.reactions[j].add_metabolites({model.metabolites[i]: v}) return model
def assess_precursors(model, reaction, flux_coefficient_cutoff=0.001, solver=None): """Assesses the ability of the model to provide sufficient precursors for a reaction operating at, or beyond, the specified cutoff. model: A :class:`~cobra.core.Model` object reaction: A :class:`~cobra.core.Reaction` object flux_coefficient_cutoff: Float. The minimum flux that reaction must carry to be considered active. solver : String or solver name. If None, the default solver will be used. returns: True if the precursors can be simultaneously produced at the specified cutoff. False, if the model has the capacity to produce each individual precursor at the specified threshold but not all precursors at the required level simultaneously. Otherwise a dictionary of the required and the produced fluxes for each reactant that is not produced in sufficient quantities. """ model = model.copy() reaction = model.reactions.get_by_id(reaction.id) original_objective = model.objective model.objective = reaction model.optimize(solver=solver) model.objective = original_objective if model.solution.f >= flux_coefficient_cutoff: return True # simulation_results = {} # build the sink reactions and add all at once sink_reactions = {} for the_component in reaction.reactants: # add in a sink reaction for each component sink_reaction = Reaction('test_sink_%s' % the_component.id) # then simulate production ability # then check it can exceed objective cutoff * component stoichiometric # coefficient. coefficient = reaction.get_coefficient(the_component) sink_reaction.add_metabolites({the_component: coefficient}) sink_reaction.upper_bound = 1000 sink_reactions[sink_reaction] = (the_component, coefficient) # First assess whether all precursors can pbe produced simultaneously super_sink = Reaction("super_sink") for reaction in sink_reactions: super_sink += reaction super_sink.id = 'super_sink' model.add_reactions(sink_reactions.keys() + [super_sink]) model.objective = super_sink model.optimize(solver=solver) model.objective = original_objective if flux_coefficient_cutoff <= model.solution.f: return True # Otherwise assess the ability of the model to produce each precursor # individually. Now assess the ability of the model to produce each # reactant for a reaction for sink_reaction, (component, coefficient) in iteritems(sink_reactions): # Calculate the maximum amount of the model.objective = sink_reaction model.optimize(solver=solver) model.objective = original_objective # metabolite that can be produced. if flux_coefficient_cutoff > model.solution.f: # Scale the results to a single unit simulation_results.update({ component: { 'required': flux_coefficient_cutoff / abs(coefficient), 'produced': model.solution.f / abs(coefficient) } }) if len(simulation_results) == 0: simulation_results = False return simulation_results
def parse_xml_into_model(xml, number=float): xml_model = xml.find(ns("sbml:model")) if get_attrib(xml_model, "fbc:strict") != "true": warn('loading SBML model without fbc:strict="true"') model_id = get_attrib(xml_model, "id") model = Model(model_id) model.name = xml_model.get("name") model.compartments = {c.get("id"): c.get("name") for c in xml_model.findall(COMPARTMENT_XPATH)} # add metabolites for species in xml_model.findall(SPECIES_XPATH % 'false'): met = get_attrib(species, "id", require=True) met = Metabolite(clip(met, "M_")) met.name = species.get("name") annotate_cobra_from_sbml(met, species) met.compartment = species.get("compartment") met.charge = get_attrib(species, "fbc:charge", int) met.formula = get_attrib(species, "fbc:chemicalFormula") model.add_metabolites([met]) # Detect boundary metabolites - In case they have been mistakenly # added. They should not actually appear in a model boundary_metabolites = {clip(i.get("id"), "M_") for i in xml_model.findall(SPECIES_XPATH % 'true')} # add genes for sbml_gene in xml_model.iterfind(GENES_XPATH): gene_id = get_attrib(sbml_gene, "fbc:id").replace(SBML_DOT, ".") gene = Gene(clip(gene_id, "G_")) gene.name = get_attrib(sbml_gene, "fbc:name") if gene.name is None: gene.name = get_attrib(sbml_gene, "fbc:label") annotate_cobra_from_sbml(gene, sbml_gene) model.genes.append(gene) def process_gpr(sub_xml): """recursively convert gpr xml to a gpr string""" if sub_xml.tag == OR_TAG: return "( " + ' or '.join(process_gpr(i) for i in sub_xml) + " )" elif sub_xml.tag == AND_TAG: return "( " + ' and '.join(process_gpr(i) for i in sub_xml) + " )" elif sub_xml.tag == GENEREF_TAG: gene_id = get_attrib(sub_xml, "fbc:geneProduct", require=True) return clip(gene_id, "G_") else: raise Exception("unsupported tag " + sub_xml.tag) bounds = {bound.get("id"): get_attrib(bound, "value", type=number) for bound in xml_model.iterfind(BOUND_XPATH)} # add reactions reactions = [] for sbml_reaction in xml_model.iterfind( ns("sbml:listOfReactions/sbml:reaction")): reaction = get_attrib(sbml_reaction, "id", require=True) reaction = Reaction(clip(reaction, "R_")) reaction.name = sbml_reaction.get("name") annotate_cobra_from_sbml(reaction, sbml_reaction) lb_id = get_attrib(sbml_reaction, "fbc:lowerFluxBound", require=True) ub_id = get_attrib(sbml_reaction, "fbc:upperFluxBound", require=True) try: reaction.upper_bound = bounds[ub_id] reaction.lower_bound = bounds[lb_id] except KeyError as e: raise CobraSBMLError("No constant bound with id '%s'" % str(e)) reactions.append(reaction) stoichiometry = defaultdict(lambda: 0) for species_reference in sbml_reaction.findall( ns("sbml:listOfReactants/sbml:speciesReference")): met_name = clip(species_reference.get("species"), "M_") stoichiometry[met_name] -= \ number(species_reference.get("stoichiometry")) for species_reference in sbml_reaction.findall( ns("sbml:listOfProducts/sbml:speciesReference")): met_name = clip(species_reference.get("species"), "M_") stoichiometry[met_name] += \ get_attrib(species_reference, "stoichiometry", type=number, require=True) # needs to have keys of metabolite objects, not ids object_stoichiometry = {} for met_id in stoichiometry: if met_id in boundary_metabolites: warn("Boundary metabolite '%s' used in reaction '%s'" % (met_id, reaction.id)) continue try: metabolite = model.metabolites.get_by_id(met_id) except KeyError: warn("ignoring unknown metabolite '%s' in reaction %s" % (met_id, reaction.id)) continue object_stoichiometry[metabolite] = stoichiometry[met_id] reaction.add_metabolites(object_stoichiometry) # set gene reaction rule gpr_xml = sbml_reaction.find(GPR_TAG) if gpr_xml is not None and len(gpr_xml) != 1: warn("ignoring invalid geneAssociation for " + repr(reaction)) gpr_xml = None gpr = process_gpr(gpr_xml[0]) if gpr_xml is not None else '' # remove outside parenthesis, if any if gpr.startswith("(") and gpr.endswith(")"): gpr = gpr[1:-1].strip() gpr = gpr.replace(SBML_DOT, ".") reaction.gene_reaction_rule = gpr try: model.add_reactions(reactions) except ValueError as e: warn(str(e)) # objective coefficients are handled after all reactions are added obj_list = xml_model.find(ns("fbc:listOfObjectives")) if obj_list is None: warn("listOfObjectives element not found") return model target_objective_id = get_attrib(obj_list, "fbc:activeObjective") target_objective = obj_list.find( ns("fbc:objective[@fbc:id='{}']".format(target_objective_id))) obj_direction_long = get_attrib(target_objective, "fbc:type") obj_direction = LONG_SHORT_DIRECTION[obj_direction_long] obj_query = OBJECTIVES_XPATH % target_objective_id coefficients = {} for sbml_objective in obj_list.findall(obj_query): rxn_id = clip(get_attrib(sbml_objective, "fbc:reaction"), "R_") try: objective_reaction = model.reactions.get_by_id(rxn_id) except KeyError: raise CobraSBMLError("Objective reaction '%s' not found" % rxn_id) try: coefficients[objective_reaction] = get_attrib( sbml_objective, "fbc:coefficient", type=number) except ValueError as e: warn(str(e)) set_objective(model, coefficients) model.solver.objective.direction = obj_direction return model
def create_cobra_model_from_sbml_file(sbml_filename, old_sbml=False, legacy_metabolite=False, print_time=False, use_hyphens=False): """convert an SBML XML file into a cobra.Model object. Supports SBML Level 2 Versions 1 and 4. The function will detect if the SBML fbc package is used in the file and run the converter if the fbc package is used. Parameters ---------- sbml_filename: string old_sbml: bool Set to True if the XML file has metabolite formula appended to metabolite names. This was a poorly designed artifact that persists in some models. legacy_metabolite: bool If True then assume that the metabolite id has the compartment id appended after an underscore (e.g. _c for cytosol). This has not been implemented but will be soon. print_time: bool deprecated use_hyphens: bool If True, double underscores (__) in an SBML ID will be converted to hyphens Returns ------- Model : The parsed cobra model """ if not libsbml: raise ImportError('create_cobra_model_from_sbml_file ' 'requires python-libsbml') __default_lower_bound = -1000 __default_upper_bound = 1000 __default_objective_coefficient = 0 # Ensure that the file exists if not isfile(sbml_filename): raise IOError('Your SBML file is not found: %s' % sbml_filename) # Expressions to change SBML Ids to Palsson Lab Ids metabolite_re = re.compile('^M_') reaction_re = re.compile('^R_') compartment_re = re.compile('^C_') if print_time: warn("print_time is deprecated", DeprecationWarning) model_doc = libsbml.readSBML(sbml_filename) if model_doc.getPlugin("fbc") is not None: from libsbml import ConversionProperties, LIBSBML_OPERATION_SUCCESS conversion_properties = ConversionProperties() conversion_properties.addOption( "convert fbc to cobra", True, "Convert FBC model to Cobra model") result = model_doc.convert(conversion_properties) if result != LIBSBML_OPERATION_SUCCESS: raise Exception("Conversion of SBML+fbc to COBRA failed") sbml_model = model_doc.getModel() sbml_model_id = sbml_model.getId() sbml_species = sbml_model.getListOfSpecies() sbml_reactions = sbml_model.getListOfReactions() sbml_compartments = sbml_model.getListOfCompartments() compartment_dict = dict([(compartment_re.split(x.getId())[-1], x.getName()) for x in sbml_compartments]) if legacy_metabolite: # Deal with the palsson lab appending the compartment id to the # metabolite id new_dict = {} for the_id, the_name in compartment_dict.items(): if the_name == '': new_dict[the_id[0].lower()] = the_id else: new_dict[the_id] = the_name compartment_dict = new_dict legacy_compartment_converter = dict( [(v, k) for k, v in iteritems(compartment_dict)]) cobra_model = Model(sbml_model_id) metabolites = [] metabolite_dict = {} # Convert sbml_metabolites to cobra.Metabolites for sbml_metabolite in sbml_species: # Skip sbml boundary species if sbml_metabolite.getBoundaryCondition(): continue if (old_sbml or legacy_metabolite) and \ sbml_metabolite.getId().endswith('_b'): # Deal with incorrect sbml from bigg.ucsd.edu continue tmp_metabolite = Metabolite() metabolite_id = tmp_metabolite.id = sbml_metabolite.getId() tmp_metabolite.compartment = compartment_re.split( sbml_metabolite.getCompartment())[-1] if legacy_metabolite: if tmp_metabolite.compartment not in compartment_dict: tmp_metabolite.compartment = legacy_compartment_converter[ tmp_metabolite.compartment] tmp_metabolite.id = parse_legacy_id( tmp_metabolite.id, tmp_metabolite.compartment, use_hyphens=use_hyphens) if use_hyphens: tmp_metabolite.id = metabolite_re.split( tmp_metabolite.id)[-1].replace('__', '-') else: # Just in case the SBML ids are ill-formed and use - tmp_metabolite.id = metabolite_re.split( tmp_metabolite.id)[-1].replace('-', '__') tmp_metabolite.name = sbml_metabolite.getName() tmp_formula = '' tmp_metabolite.notes = parse_legacy_sbml_notes( sbml_metabolite.getNotesString()) if sbml_metabolite.isSetCharge(): tmp_metabolite.charge = sbml_metabolite.getCharge() if "CHARGE" in tmp_metabolite.notes: note_charge = tmp_metabolite.notes["CHARGE"][0] try: note_charge = float(note_charge) if note_charge == int(note_charge): note_charge = int(note_charge) except: warn("charge of %s is not a number (%s)" % (tmp_metabolite.id, str(note_charge))) else: if ((tmp_metabolite.charge is None) or (tmp_metabolite.charge == note_charge)): tmp_metabolite.notes.pop("CHARGE") # set charge to the one from notes if not assigend before # the same tmp_metabolite.charge = note_charge else: # tmp_metabolite.charge != note_charge msg = "different charges specified for %s (%d and %d)" msg = msg % (tmp_metabolite.id, tmp_metabolite.charge, note_charge) warn(msg) # Chances are a 0 note charge was written by mistake. We # will default to the note_charge in this case. if tmp_metabolite.charge == 0: tmp_metabolite.charge = note_charge for the_key in tmp_metabolite.notes.keys(): if the_key.lower() == 'formula': tmp_formula = tmp_metabolite.notes.pop(the_key)[0] break if tmp_formula == '' and old_sbml: tmp_formula = tmp_metabolite.name.split('_')[-1] tmp_metabolite.name = tmp_metabolite.name[:-len(tmp_formula) - 1] tmp_metabolite.formula = tmp_formula metabolite_dict.update({metabolite_id: tmp_metabolite}) metabolites.append(tmp_metabolite) cobra_model.add_metabolites(metabolites) # Construct the vectors and matrices for holding connectivity and numerical # info to feed to the cobra toolbox. # Always assume steady state simulations so b is set to 0 cobra_reaction_list = [] coefficients = {} for sbml_reaction in sbml_reactions: if use_hyphens: # Change the ids to match conventions used by the Palsson lab. reaction = Reaction(reaction_re.split( sbml_reaction.getId())[-1].replace('__', '-')) else: # Just in case the SBML ids are ill-formed and use - reaction = Reaction(reaction_re.split( sbml_reaction.getId())[-1].replace('-', '__')) cobra_reaction_list.append(reaction) # reaction.exchange_reaction = 0 reaction.name = sbml_reaction.getName() cobra_metabolites = {} # Use the cobra.Metabolite class here for sbml_metabolite in sbml_reaction.getListOfReactants(): tmp_metabolite_id = sbml_metabolite.getSpecies() # This deals with boundary metabolites if tmp_metabolite_id in metabolite_dict: tmp_metabolite = metabolite_dict[tmp_metabolite_id] cobra_metabolites[tmp_metabolite] = - \ sbml_metabolite.getStoichiometry() for sbml_metabolite in sbml_reaction.getListOfProducts(): tmp_metabolite_id = sbml_metabolite.getSpecies() # This deals with boundary metabolites if tmp_metabolite_id in metabolite_dict: tmp_metabolite = metabolite_dict[tmp_metabolite_id] # Handle the case where the metabolite was specified both # as a reactant and as a product. if tmp_metabolite in cobra_metabolites: warn("%s appears as a reactant and product %s" % (tmp_metabolite_id, reaction.id)) cobra_metabolites[ tmp_metabolite] += sbml_metabolite.getStoichiometry() # if the combined stoichiometry is 0, remove the metabolite if cobra_metabolites[tmp_metabolite] == 0: cobra_metabolites.pop(tmp_metabolite) else: cobra_metabolites[ tmp_metabolite] = sbml_metabolite.getStoichiometry() # check for nan for met, v in iteritems(cobra_metabolites): if isnan(v) or isinf(v): warn("invalid value %s for metabolite '%s' in reaction '%s'" % (str(v), met.id, reaction.id)) reaction.add_metabolites(cobra_metabolites) # Parse the kinetic law info here. parameter_dict = {} # If lower and upper bounds are specified in the Kinetic Law then # they override the sbml reversible attribute. If they are not # specified then the bounds are determined by getReversible. if not sbml_reaction.getKineticLaw(): if sbml_reaction.getReversible(): parameter_dict['lower_bound'] = __default_lower_bound parameter_dict['upper_bound'] = __default_upper_bound else: # Assume that irreversible reactions only proceed from left to # right. parameter_dict['lower_bound'] = 0 parameter_dict['upper_bound'] = __default_upper_bound parameter_dict[ 'objective_coefficient'] = __default_objective_coefficient else: for sbml_parameter in \ sbml_reaction.getKineticLaw().getListOfParameters(): parameter_dict[ sbml_parameter.getId().lower()] = sbml_parameter.getValue() if 'lower_bound' in parameter_dict: reaction.lower_bound = parameter_dict['lower_bound'] elif 'lower bound' in parameter_dict: reaction.lower_bound = parameter_dict['lower bound'] elif sbml_reaction.getReversible(): reaction.lower_bound = __default_lower_bound else: reaction.lower_bound = 0 if 'upper_bound' in parameter_dict: reaction.upper_bound = parameter_dict['upper_bound'] elif 'upper bound' in parameter_dict: reaction.upper_bound = parameter_dict['upper bound'] else: reaction.upper_bound = __default_upper_bound objective_coefficient = parameter_dict.get( 'objective_coefficient', parameter_dict.get( 'objective_coefficient', __default_objective_coefficient)) if objective_coefficient != 0: coefficients[reaction] = objective_coefficient # ensure values are not set to nan or inf if isnan(reaction.lower_bound) or isinf(reaction.lower_bound): reaction.lower_bound = __default_lower_bound if isnan(reaction.upper_bound) or isinf(reaction.upper_bound): reaction.upper_bound = __default_upper_bound reaction_note_dict = parse_legacy_sbml_notes( sbml_reaction.getNotesString()) # Parse the reaction notes. # POTENTIAL BUG: DEALING WITH LEGACY 'SBML' THAT IS NOT IN A # STANDARD FORMAT # TODO: READ IN OTHER NOTES AND GIVE THEM A reaction_ prefix. # TODO: Make sure genes get added as objects if 'GENE ASSOCIATION' in reaction_note_dict: rule = reaction_note_dict['GENE ASSOCIATION'][0] try: rule.encode('ascii') except (UnicodeEncodeError, UnicodeDecodeError): warn("gene_reaction_rule '%s' is not ascii compliant" % rule) if rule.startswith(""") and rule.endswith("""): rule = rule[6:-6] reaction.gene_reaction_rule = rule if 'GENE LIST' in reaction_note_dict: reaction.systematic_names = reaction_note_dict['GENE LIST'][0] elif ('GENES' in reaction_note_dict and reaction_note_dict['GENES'] != ['']): reaction.systematic_names = reaction_note_dict['GENES'][0] elif 'LOCUS' in reaction_note_dict: gene_id_to_object = dict([(x.id, x) for x in reaction._genes]) for the_row in reaction_note_dict['LOCUS']: tmp_row_dict = {} the_row = 'LOCUS:' + the_row.lstrip('_').rstrip('#') for the_item in the_row.split('#'): k, v = the_item.split(':') tmp_row_dict[k] = v tmp_locus_id = tmp_row_dict['LOCUS'] if 'TRANSCRIPT' in tmp_row_dict: tmp_locus_id = tmp_locus_id + \ '.' + tmp_row_dict['TRANSCRIPT'] if 'ABBREVIATION' in tmp_row_dict: gene_id_to_object[tmp_locus_id].name = tmp_row_dict[ 'ABBREVIATION'] if 'SUBSYSTEM' in reaction_note_dict: reaction.subsystem = reaction_note_dict.pop('SUBSYSTEM')[0] reaction.notes = reaction_note_dict # Now, add all of the reactions to the model. cobra_model.id = sbml_model.getId() # Populate the compartment list - This will be done based on # cobra.Metabolites in cobra.Reactions in the future. cobra_model.compartments = compartment_dict cobra_model.add_reactions(cobra_reaction_list) set_objective(cobra_model, coefficients) return cobra_model
tmset = set() for line in tmfile: tmset.add(line.replace("\n", "")) for met in tmset: tempRxn = Reaction(met + "_dielTransfer") tempRxn.add_metabolites({ cobra_model.metabolites.get_by_id(met + "1"): -1, cobra_model.metabolites.get_by_id(met + "2"): 1 }) tempRxn.lower_bound = -1000 if not ((met == "STARCH_p") or (met == "SUCROSE_v") or (met == "MAL_v") or (met == "aMAL_v") or (met == "NITRATE_v") or (met == "CIT_v") or (met == "aCIT_v") or (met == "PROTON_v")): tempRxn.lower_bound = 0 tempRxn.upper_bound = 1000 cobra_model.add_reaction(tempRxn) fractionMets = dict() for rxn in cobra_model.reactions: for met in rxn.metabolites.keys(): a = re.search("^a{1,3}", met.id) anion = "" if a: anion = a.group(0) b = re.search("^b{1,3}", met.id) basic = "" if b: basic = b.group(0) prefix = anion if prefix == "":
def optimize_minimum_flux(model, objective_sense='maximize', tolerance_optimality=1e-8, tolerance_feasibility=1e-8): # return the flux distribution in which the total amount of fluxes is minimum while the growth is maximum #Get the optimal wt objective value and adjust based on optimality tolerances model.optimize() optimal_value = deepcopy(model.solution.f) # print('opt val: %s' % optimal_value) if objective_sense == 'maximize': optimal_value = floor(optimal_value/tolerance_optimality)*tolerance_optimality else: optimal_value = ceil(optimal_value/tolerance_optimality)*tolerance_optimality # print('adjusted opt val: %s' % optimal_value) #Add in the virtual objective metabolite to constrain the wt_model to the space where #the objective was maximal objective_metabolite = Metabolite('objective metabolite') objective_metabolite._bound = optimal_value if objective_sense == 'maximize': objective_metabolite._constraint_sense = 'G' else: objective_metabolite._constraint_sense = 'L' # print('objm const sense: %s, objm bound: %s' % (objective_metabolite._constraint_sense, objective_metabolite._bound)) # construct irreversible model to assure all flux values are positive irreve_model = model.copy() # this is necessary to avoid invalid bound error when model is changed to irreversible for r in irreve_model.reactions: if r.upper_bound < 0: reverse_reaction = Reaction(r.id + "_reverse") reverse_reaction.lower_bound = r.upper_bound * -1 reverse_reaction.upper_bound = r.lower_bound * -1 reverse_reaction.objective_coefficient = r.objective_coefficient * -1 reaction_dict = dict([(k, v*-1) for k, v in r.metabolites.items()]) reverse_reaction.add_metabolites(reaction_dict) irreve_model.add_reaction(reverse_reaction) r.upper_bound, r.lower_bound = 0, 0 cobra.manipulation.modify.convert_to_irreversible(irreve_model) objective_reaction_coefficient_dict = dict([(x.id, x.objective_coefficient) for x in model.reactions if x.objective_coefficient]) # this couples the objective reaction to the virtual metabolite [irreve_model.reactions.get_by_id(k).add_metabolites({objective_metabolite: v}) for k, v in objective_reaction_coefficient_dict.items()] # print('irregular metabolites: %s' % [(m.id, m._constraint_sense, m._bound) # for m in irreve_model.metabolites if m._constraint_sense != 'E' or m._bound != 0]) # minimize the sum of fluxes for r in irreve_model.reactions: r.objective_coefficient = 1 # print([r.id for r in irreve_model.reactions if r.objective_coefficient != 1]) # print(tolerance_feasibility) irreve_model.optimize(objective_sense='minimize', tolerance_feasibility=tolerance_feasibility) # adjust this to the solution of wt_model original_flux = model.solution.x_dict irreve_flux = irreve_model.solution.x_dict for k in original_flux.keys(): original_flux[k] = irreve_flux[k] # if reverse reaction exists and its flux is not zero, assign as a negative flux in wt_flux if k + '_reverse' in irreve_flux.keys() and irreve_flux[k + '_reverse'] != 0: if irreve_flux[k] != 0: print('Attention: non-optimal solution') original_flux[k] = -irreve_flux[k + '_reverse'] model.solution.status = irreve_model.solution.status model.solution.f = sum([irreve_model.reactions.get_by_id(k).x * v for k, v in objective_reaction_coefficient_dict.items()]) return model.solution
def SetupDielModel(core_model, transferMets): from cobra.core import Metabolite, Reaction import re #create two copies of model elements for day and night cobra_model2 = core_model.copy() for met in cobra_model2.metabolites: met.id = met.id + "1" met.compartment = met.compartment + "1" for rxn in cobra_model2.reactions: rxn.id = rxn.id + "1" cobra_model3 = core_model.copy() for met in cobra_model3.metabolites: met.id = met.id + "2" met.compartment = met.compartment + "2" for rxn in cobra_model3.reactions: rxn.id = rxn.id + "2" #merge the day and night model cobra_model = cobra_model2 + cobra_model3 for met in cobra_model3.metabolites: if not cobra_model.metabolites.__contains__(met.id): cobra_model.add_metabolites(met.copy()) met1 = Metabolite("Biomass_t1", name="Biomass during the day") cobra_model.reactions.get_by_id("AraCore_Biomass_tx1").add_metabolites( {met1: 1}) met2 = Metabolite("Biomass_t2", name="Biomass during at night") cobra_model.reactions.get_by_id("AraCore_Biomass_tx2").add_metabolites( {met2: 1}) rxn = Reaction("diel_biomass") rxn.add_metabolites({met1: -3, met2: -1}) #rxn.add_metabolites({met1:-1,met2:-1}) rxn.lower_bound = 0 rxn.upper_bound = 1000 cobra_model.add_reaction(rxn) #Adding reactions to allow for day-night metabolite accumulations tmfile = open(transferMets, "r") tmset = set() for line in tmfile: tmset.add(line.replace("\n", "")) for met in tmset: if met == "AMMONIUM_v" or met == "FRUCTAN_v": continue tempRxn = Reaction(met + "_dielTransfer") tempRxn.add_metabolites({ cobra_model.metabolites.get_by_id(met + "1"): -1, cobra_model.metabolites.get_by_id(met + "2"): 1 }) tempRxn.lower_bound = -1000 if not ((met == "STARCH_p") or (met == "SUCROSE_v") or (met == "MAL_v") or (met == "aMAL_v") or (met == "NITRATE_v") or (met == "CIT_v") or (met == "aCIT_v") or (met == "PROTON_v")): tempRxn.lower_bound = 0 tempRxn.upper_bound = 1000 cobra_model.add_reaction(tempRxn) fractionMets = dict() for rxn in cobra_model.reactions: for met in rxn.metabolites.keys(): prefix = "" a = re.search("^a{1,3}", met.id) anion = "" if a: anion = a.group(0) prefix = anion b = re.search("^b{1,3}", met.id) basic = "" if b: basic = b.group(0) prefix = basic if ((not prefix == "") and met.compartment == "v1"): fractionMets[met] = prefix temp = cobra_model.copy() for met in fractionMets.keys(): for rxn in met.reactions: if rxn.id.__contains__("_dielTransfer"): continue else: mainMet = met.id[len(fractionMets[met]):] coeff1 = temp.reactions.get_by_id(rxn.id).metabolites.get( temp.metabolites.get_by_id(mainMet)) coeff2 = temp.reactions.get_by_id(rxn.id).metabolites.get( temp.metabolites.get_by_id(met.id)) if not coeff1: coeff1 = 0 if not coeff2: coeff2 = 0 total = coeff1 + coeff2 coeff1 = float(coeff1) / total coeff2 = float(coeff2) / total if cobra_model.reactions.has_id(met.id[0:len(met.id) - 1] + "_dielTransfer"): ub = temp.reactions.get_by_id(met.id[0:len(met.id) - 1] + "_dielTransfer").upper_bound lb = temp.reactions.get_by_id(met.id[0:len(met.id) - 1] + "_dielTransfer").lower_bound temp.reactions.get_by_id( met.id[0:len(met.id) - 1] + "_dielTransfer").remove_from_model() temp.reactions.get_by_id( mainMet[0:len(mainMet) - 1] + "_dielTransfer").remove_from_model() Reac = Reaction(mainMet[0:len(mainMet) - 1] + "_dielTransfer", name=mainMet + "_dielTransfer") Reac.add_metabolites({ temp.metabolites.get_by_id(met.id[0:len(met.id) - 1] + "1"): -coeff2, temp.metabolites.get_by_id(met.id[0:len(met.id) - 1] + "2"): coeff2, temp.metabolites.get_by_id(mainMet[0:len(mainMet) - 1] + "1"): -coeff1, temp.metabolites.get_by_id(mainMet[0:len(mainMet) - 1] + "2"): coeff1 }) Reac.lower_bound = lb Reac.upper_bound = ub temp.add_reaction(Reac) print Reac.reaction break ####ADD CONSTRAINTS TO MODEL#### cobra_model = temp.copy() #Leaves - light cobra_model.reactions.get_by_id("Sucrose_tx1").lower_bound = 0 cobra_model.reactions.get_by_id("Sucrose_tx1").upper_bound = 0 cobra_model.reactions.get_by_id("GLC_tx1").lower_bound = 0 cobra_model.reactions.get_by_id("GLC_tx1").upper_bound = 0 cobra_model.reactions.get_by_id("CO2_tx1").lower_bound = 0 cobra_model.reactions.get_by_id("NH4_tx1").lower_bound = 0 cobra_model.reactions.get_by_id("NH4_tx1").upper_bound = 0 #Leaves - dark cobra_model.reactions.get_by_id("Sucrose_tx2").lower_bound = 0 cobra_model.reactions.get_by_id("Sucrose_tx2").upper_bound = 0 cobra_model.reactions.get_by_id("GLC_tx2").lower_bound = 0 cobra_model.reactions.get_by_id("GLC_tx2").upper_bound = 0 cobra_model.reactions.get_by_id("Photon_tx2").lower_bound = 0 cobra_model.reactions.get_by_id("Photon_tx2").upper_bound = 0 cobra_model.reactions.get_by_id("NH4_tx2").lower_bound = 0 cobra_model.reactions.get_by_id("NH4_tx2").upper_bound = 0 cobra_model.reactions.get_by_id("CO2_tx2").upper_bound = 0 #Set pG6P transporter to 0 cobra_model.reactions.get_by_id("G6P_Pi_pc1").lower_bound = 0 cobra_model.reactions.get_by_id("G6P_Pi_pc1").upper_bound = 0 cobra_model.reactions.get_by_id("G6P_Pi_pc2").lower_bound = 0 cobra_model.reactions.get_by_id("G6P_Pi_pc2").upper_bound = 0 #Turn off PTOX cobra_model.reactions.get_by_id("Plastoquinol_Oxidase_p1").lower_bound = 0 cobra_model.reactions.get_by_id("Plastoquinol_Oxidase_p1").upper_bound = 0 #nitrate uptake constrain Nitrate_balance = Metabolite("Nitrate_bal_c", name="Weights to balance nitrate uptake", compartment="c1") cobra_model.reactions.get_by_id("Nitrate_ec1").add_metabolites( {Nitrate_balance: -2}) cobra_model.reactions.get_by_id("Nitrate_ec2").add_metabolites( {Nitrate_balance: 3}) #Rubisco balance Rubisco_balance = Metabolite( "rubisco_bal_p1", name="Weights to balance RuBP carboxygenase oxygenase balance", compartment="p1") cobra_model.reactions.get_by_id("RXN_961_p1").add_metabolites( {Rubisco_balance: 3}) cobra_model.reactions.get_by_id( "RIBULOSE_BISPHOSPHATE_CARBOXYLASE_RXN_p1").add_metabolites( {Rubisco_balance: -1}) #generic ATPase and NADPH oxidase Maintenance_constraint = Metabolite( "ATPase_NADPHoxidase_constraint_c1", name="ATPase_NADPHoxidase_constraint_c1", compartment="c1") Maintenance_constraint2 = Metabolite( "ATPase_NADPHoxidase_constraint_c2", name="ATPase_NADPHoxidase_constraint_c2", compartment="c2") Maintenance_constraint3 = Metabolite( "Light_dark_maintainence_constraint", name="Light_dark_maintainence_constraint", compartment="c1") cobra_model.reactions.get_by_id("ATPase_tx1").add_metabolites({ Maintenance_constraint: 1, Maintenance_constraint3: 1 }) cobra_model.reactions.get_by_id("ATPase_tx2").add_metabolites({ Maintenance_constraint2: 1, Maintenance_constraint3: -1 }) cobra_model.reactions.get_by_id("NADPHoxc_tx1").add_metabolites( {Maintenance_constraint: -3}) cobra_model.reactions.get_by_id("NADPHoxc_tx2").add_metabolites( {Maintenance_constraint2: -3}) cobra_model.reactions.get_by_id("NADPHoxm_tx1").add_metabolites( {Maintenance_constraint: -3}) cobra_model.reactions.get_by_id("NADPHoxm_tx2").add_metabolites( {Maintenance_constraint2: -3}) cobra_model.reactions.get_by_id("NADPHoxp_tx1").add_metabolites( {Maintenance_constraint: -3}) cobra_model.reactions.get_by_id("NADPHoxp_tx2").add_metabolites( {Maintenance_constraint2: -3}) #Plastid enolase was not detected in Arabidopsis mesophyll tissue cobra_model.reactions.get_by_id("2PGADEHYDRAT_RXN_p1").lower_bound = 0 cobra_model.reactions.get_by_id("2PGADEHYDRAT_RXN_p1").upper_bound = 0 cobra_model.reactions.get_by_id("2PGADEHYDRAT_RXN_p2").lower_bound = 0 cobra_model.reactions.get_by_id("2PGADEHYDRAT_RXN_p2").upper_bound = 0 #Setting chloroplastic NADPH dehydrogenase to 0 ((Yamamoto et al., 2011) cobra_model.reactions.get_by_id("NADPH_Dehydrogenase_p1").lower_bound = 0 cobra_model.reactions.get_by_id("NADPH_Dehydrogenase_p1").upper_bound = 0 cobra_model.reactions.get_by_id("NADPH_Dehydrogenase_p2").lower_bound = 0 cobra_model.reactions.get_by_id("NADPH_Dehydrogenase_p2").upper_bound = 0 #Set biomass to zero cobra_model.reactions.get_by_id("Biomass_tx1").lower_bound = 0 cobra_model.reactions.get_by_id("Biomass_tx1").upper_bound = 0 cobra_model.reactions.get_by_id("Biomass_tx2").lower_bound = 0 cobra_model.reactions.get_by_id("Biomass_tx2").upper_bound = 0 #ATP_ADP_Pi constrained to 0 because while there is evidence for its existance, it does not carry high flux cobra_model.reactions.get_by_id("ATP_ADP_Pi_pc1").lower_bound = 0 cobra_model.reactions.get_by_id("ATP_ADP_Pi_pc1").upper_bound = 0 cobra_model.reactions.get_by_id("ATP_ADP_Pi_pc2").lower_bound = 0 cobra_model.reactions.get_by_id("ATP_ADP_Pi_pc2").upper_bound = 0 #turn off chlorophyll a/b cycling for energy dissipation cobra_model.reactions.get_by_id("RXN_7674_p1").lower_bound = 0 cobra_model.reactions.get_by_id("RXN_7674_p1").upper_bound = 0 #turn off cytosolic ferric chelate reductase cycle for NADH dissipation cobra_model.reactions.get_by_id( "FERRIC_CHELATE_REDUCTASE_RXN_c1").lower_bound = 0 cobra_model.reactions.get_by_id( "FERRIC_CHELATE_REDUCTASE_RXN_c1").upper_bound = 0 #Adding a H_mc reaction to allow protons into mitochondria for i in range(1, 3): rxn = Reaction("H_mc" + str(i)) rxn.add_metabolites({ cobra_model.metabolites.get_by_id("PROTON_c" + str(i)): -1, cobra_model.metabolites.get_by_id("PROTON_m" + str(i)): 1 }) rxn.lower_bound = 0 rxn.upper_bound = 1000 cobra_model.add_reactions({rxn}) return cobra_model
def assess_products(model, reaction, flux_coefficient_cutoff=0.001, solver=None): """Assesses whether the model has the capacity to absorb the products of a reaction at a given flux rate. Useful for identifying which components might be blocking a reaction from achieving a specific flux rate. model: A :class:`~cobra.core.Model` object reaction: A :class:`~cobra.core.Reaction` object flux_coefficient_cutoff: Float. The minimum flux that reaction must carry to be considered active. solver : String or solver name. If None, the default solver will be used. returns: True if the model has the capacity to absorb all the reaction products being simultaneously given the specified cutoff. False, if the model has the capacity to absorb each individual product but not all products at the required level simultaneously. Otherwise a dictionary of the required and the capacity fluxes for each product that is not absorbed in sufficient quantities. """ model = model.copy() reaction = model.reactions.get_by_id(reaction.id) original_objective = model.objective model.objective = reaction model.optimize(solver=solver) model.objective = original_objective if model.solution.f >= flux_coefficient_cutoff: return True # simulation_results = {} # build the sink reactions and add all at once source_reactions = {} for the_component in reaction.products: # add in a sink reaction for each component source_reaction = Reaction('test_source_%s' % the_component.id) # then simulate production ability # then check it can exceed objective cutoff * component stoichiometric # coefficient. coefficient = reaction.get_coefficient(the_component) source_reaction.add_metabolites({the_component: coefficient}) source_reaction.upper_bound = 1000 source_reactions[source_reaction] = (the_component, coefficient) # super_source = Reaction('super_source') for reaction in source_reactions: super_source += reaction super_source.id = 'super_source' model.add_reactions(source_reactions.keys() + [super_source]) model.objective = super_source model.optimize(solver=solver) model.objective = original_objective if flux_coefficient_cutoff <= model.solution.f: return True # Now assess the ability of the model to produce each reactant for a # reaction for source_reaction, (component, coefficient) in \ iteritems(source_reactions): # Calculate the maximum amount of the model.objective = source_reaction model.optimize(solver=solver) model.objective = original_objective # metabolite that can be produced. if flux_coefficient_cutoff > model.solution.f: # Scale the results to a single unit simulation_results.update({ component: { 'required': flux_coefficient_cutoff / abs(coefficient), 'capacity': model.solution.f / abs(coefficient) } }) if len(simulation_results) == 0: simulation_results = False return simulation_results
def test_iterative_gapfill_from_binary_phenotypes(): # load the universal model and a test model universal = load_universal_modelseed() model = load_modelseed_model('Staphylococcus aureus') # Load the biolog composition to be used for gapfilling biolog_base_composition = pd.read_csv( './medusa/test/data/biolog_base_composition.csv', sep=',') biolog_base_dict = dict(zip(biolog_base_composition['ID'],\ [1000 for i in range(0,len(biolog_base_composition['ID']))])) biolog_thresholded = pd.read_csv( './medusa/test/data/plata_thresholded.csv', sep='\t', index_col=0) # extract the biolog conditions for Staphylococcus aureus test_mod_pheno = biolog_thresholded.loc['Staphylococcus aureus'] test_mod_pheno = list(test_mod_pheno[test_mod_pheno == True].index) # check for biolog base components in the model add_mets = [] add_exchanges = [] for met in list(biolog_base_dict.keys()): try: model.metabolites.get_by_id(met) except: print('no ' + met) add_met = universal.metabolites.get_by_id(met).copy() add_mets.append(add_met) model.add_metabolites(add_mets) for met in list(biolog_base_dict.keys()): # Search for exchange reactions try: model.reactions.get_by_id('EX_' + met) except: add_met = model.metabolites.get_by_id(met) ex_rxn = Reaction('EX_' + met) ex_rxn.name = "Exchange reaction for " + met ex_rxn.lower_bound = -1000 ex_rxn.upper_bound = 1000 ex_rxn.add_metabolites({add_met: -1}) add_exchanges.append(ex_rxn) model.add_reactions(add_exchanges) # Find metabolites from the biolog data that are missing in the test model # and add them from the universal missing_mets = [] missing_exchanges = [] media_dicts = {} for met_id in test_mod_pheno: try: model.metabolites.get_by_id(met_id) except: print(met_id + " was not in model, adding met and exchange reaction") met = universal.metabolites.get_by_id(met_id).copy() missing_mets.append(met) ex_rxn = Reaction('EX_' + met_id) ex_rxn.name = "Exchange reaction for " + met_id ex_rxn.lower_bound = -1000 ex_rxn.upper_bound = 1000 ex_rxn.add_metabolites({met: -1}) missing_exchanges.append(ex_rxn) media_dicts[met_id] = biolog_base_dict.copy() media_dicts[met_id] = { 'EX_' + k: v for k, v in media_dicts[met_id].items() } media_dicts[met_id]['EX_' + met_id] = 1000 model.add_metabolites(missing_mets) model.add_reactions(missing_exchanges) # identify transporters for each biolog component in the universal model # and pick one that will enable transport in the gapfilling problem. transporters_in_universal = [ rxn for rxn in universal.reactions if len(rxn.compartments) > 1 ] for met in media_dicts.keys(): metabolite = model.metabolites.get_by_id(met) base_met_id = met.split('_')[0] rxns_with_metabolite = metabolite.reactions transport = False for rxn in rxns_with_metabolite: metabolites = [met_in_rxn.id for met_in_rxn in rxn.metabolites] if (base_met_id + '_e' in metabolites and base_met_id + '_c' in metabolites): transport = True pick_transporter = {} if not transport: print("missing transporter for " + metabolite.name) for rxn in transporters_in_universal: metabolites = [met_in_rxn.id for met_in_rxn in rxn.metabolites] if (base_met_id + '_e' in metabolites and base_met_id + '_c' in metabolites): pick_transporter[met] = rxn.id # Add the transporters to the model transporters_to_add = list(pick_transporter.values()) transporter_list = [] for rxn in transporters_to_add: transporter_list.append(universal.reactions.get_by_id(rxn).copy()) model.add_reactions(transporter_list) # remove the added transporters from the universal model universal.remove_reactions( [universal.reactions.get_by_id(rxn) for rxn in transporters_to_add]) # select a subset of the biolog conditions to perform gapfilling with sources = list(media_dicts.keys()) sub_dict = { sources[0]: media_dicts[sources[0]], sources[1]: media_dicts[sources[1]], sources[2]: media_dicts[sources[2]], sources[3]: media_dicts[sources[3]], sources[4]: media_dicts[sources[4]] } num_cycles = 5 lower_bound = 0.05 flux_cutoff = 1E-10 ensemble = expand.iterative_gapfill_from_binary_phenotypes(model,universal,sub_dict,num_cycles,\ lower_bound=lower_bound,\ inclusion_threshold=1E-10,\ exchange_reactions=False,\ demand_reactions=False,\ exchange_prefix='EX') # the number of models in the ensemble should equal the number of cycles # unless a duplicate solution was found; for this test case, this seems # to happen ~25% of the time, so we'll loosen the restriction. assert len(ensemble.members) > num_cycles / 2 # each member of the ensemble should be able to produce biomass in each # biolog condition ex_rxns = [rxn for rxn in ensemble.base_model.reactions \ if rxn.id.startswith('EX_')] for source in sub_dict.keys(): # close all exchange reactions for rxn in ex_rxns: rxn.lower_bound = 0 ensemble.base_model.medium = sub_dict[source] for member in ensemble.members: ensemble.set_state(member) # member should produce the minimum amount of required biomass # flux or more assert ensemble.base_model.slim_optimize() > lower_bound * 0.99
v_specific = 0.73 # mL/g density = 0.34 # g/mL v_molar = M * v_specific * 1000 # mL/mol a = 1 / ECU_pad.mul(kmax_pad,axis=0) a = density * a.mul(v_molar,axis=0) a = a / (3600*1000) c = conds[-4] for r in model.reactions: r.add_metabolites({crowding:a[c][r.id]}) crowding_counter = Reaction(name='crowding_counter') crowding_counter.add_metabolites(metabolites={crowding:-1}) model.add_reaction(crowding_counter) crowding_counter.upper_bound = 1 * 0.5 * 0.44 *6.05 / 21.7# molecular crowding constraint model.optimize() print (0.7 / model.solution.f) * 60 ACU = ECU.mean() plt.figure(figsize=(6,6)) ax = plt.axes() plt.scatter(gr, ACU) x = gr.copy() x[0] = 0 x[1] = 1 plt.plot(x,x,'r') plt.xlim(0,0.9) plt.ylim(0,0.9) plt.show()