def test_gapfilling(self, salmonella): m = Model() m.add_metabolites([Metabolite(m_id) for m_id in ["a", "b", "c"]]) exa = Reaction("EX_a") exa.add_metabolites({m.metabolites.a: 1}) b2c = Reaction("b2c") b2c.add_metabolites({m.metabolites.b: -1, m.metabolites.c: 1}) dmc = Reaction("DM_c") dmc.add_metabolites({m.metabolites.c: -1}) m.add_reactions([exa, b2c, dmc]) m.objective = 'DM_c' universal = Model() a2b = Reaction("a2b") a2d = Reaction("a2d") universal.add_reactions([a2b, a2d]) a2b.build_reaction_from_string("a --> b", verbose=False) a2d.build_reaction_from_string("a --> d", verbose=False) # # GrowMatch # result = gapfilling.growMatch(m, universal)[0] result = gapfilling.gapfill(m, universal)[0] assert len(result) == 1 assert result[0].id == "a2b" # # SMILEY # result = gapfilling.SMILEY(m, "b", universal)[0] with m: m.objective = m.add_boundary(m.metabolites.b, type='demand') result = gapfilling.gapfill(m, universal)[0] assert len(result) == 1 assert result[0].id == "a2b" # # 2 rounds of GrowMatch with exchange reactions # result = gapfilling.growMatch(m, None, ex_rxns=True, iterations=2) result = gapfilling.gapfill(m, None, exchange_reactions=True, iterations=2) assert len(result) == 2 assert len(result[0]) == 1 assert len(result[1]) == 1 assert {i[0].id for i in result} == {"EX_b", "EX_c"} # somewhat bigger model universal = Model("universal_reactions") with salmonella as model: for i in [i.id for i in model.metabolites.f6p_c.reactions]: reaction = model.reactions.get_by_id(i) universal.add_reactions([reaction.copy()]) model.remove_reactions([reaction]) gf = gapfilling.GapFiller(model, universal, penalties={'TKT2': 1e3}, demand_reactions=False) solution = gf.fill() assert 'TKT2' not in {r.id for r in solution[0]} assert gf.validate(solution[0])
def __init__(self, model, universal=None, lower_bound=0.05, penalties=None, exchange_reactions=False, demand_reactions=True, integer_threshold=1e-6): self.original_model = model self.lower_bound = lower_bound self.model = model.copy() # TODO: adjust once optlang supports integrality constraint settings try: self.model.solver.configuration._iocp.tol_int = integer_threshold except AttributeError: try: self.model.solver.problem.parameters.mip.tolerances. \ integrality.set(integer_threshold) except AttributeError: warn("tried to set integrality constraint, but don't know " "how to do that for " "solver {}".format(self.model.problem.__name__)) self.universal = universal.copy() if universal else Model('universal') self.penalties = dict(universal=1, exchange=100, demand=1) if penalties is not None: self.penalties.update(penalties) self.integer_threshold = integer_threshold self.indicators = list() self.costs = dict() self.extend_model(exchange_reactions, demand_reactions) fix_objective_as_constraint(self.model, bound=lower_bound) self.add_switches_and_objective()
def __init__( self, model, universal=None, lower_bound=0.05, penalties=None, exchange_reactions=False, demand_reactions=True, integer_threshold=1e-6, ): self.original_model = model self.lower_bound = lower_bound self.model = model.copy() tolerances = self.model.solver.configuration.tolerances try: tolerances.integrality = integer_threshold except AttributeError: logger.warning( f"The current solver interface {interface_to_str(self.model.problem)} " f"doesn't support setting the integrality tolerance." ) # TODO (Midnighter): One could debate how useful it is to compare against this # threshold when it is not supported by the chosen solver. self.integer_threshold = integer_threshold self.universal = universal.copy() if universal else Model("universal") self.penalties = dict(universal=1, exchange=100, demand=1) if penalties is not None: self.penalties.update(penalties) self.indicators = list() self.costs = dict() self.extend_model(exchange_reactions, demand_reactions) fix_objective_as_constraint(self.model, bound=lower_bound) self.add_switches_and_objective()
def test_inequality(self, solver_test): solver, old_solution, infeasible_model = solver_test # The space enclosed by the constraints is a 2D triangle with # vertexes as (3, 0), (1, 2), and (0, 1) # c1 encodes y - x > 1 ==> y > x - 1 # c2 encodes y + x < 3 ==> y < 3 - x c1 = Metabolite("c1") c2 = Metabolite("c2") x = Reaction("x") x.lower_bound = 0 y = Reaction("y") y.lower_bound = 0 x.add_metabolites({c1: -1, c2: 1}) y.add_metabolites({c1: 1, c2: 1}) c1._bound = 1 c1._constraint_sense = "G" c2._bound = 3 c2._constraint_sense = "L" m = Model() m.add_reactions([x, y]) # test that optimal values are at the vertices m.objective = "x" assert abs(solver.solve(m).f - 1.0) < 10 ** -3 assert abs(solver.solve(m).x_dict["y"] - 2.0) < 10 ** -3 m.objective = "y" assert abs(solver.solve(m).f - 3.0) < 10 ** -3 assert abs( solver.solve(m, objective_sense="minimize").f - 1.0) < 10 ** -3
def construct_geometric_fba_model(): test_model = Model('geometric_fba_paper_model') test_model.add_metabolites(Metabolite('A')) test_model.add_metabolites(Metabolite('B')) v1 = Reaction('v1', upper_bound=1.0) v1.add_metabolites({test_model.metabolites.A: 1.0}) v2 = Reaction('v2', lower_bound=-1000.0) v2.add_metabolites({ test_model.metabolites.A: -1.0, test_model.metabolites.B: 1.0 }) v3 = Reaction('v3', lower_bound=-1000.0) v3.add_metabolites({ test_model.metabolites.A: -1.0, test_model.metabolites.B: 1.0 }) v4 = Reaction('v4', lower_bound=-1000.0) v4.add_metabolites({ test_model.metabolites.A: -1.0, test_model.metabolites.B: 1.0 }) v5 = Reaction('v5') v5.add_metabolites({ test_model.metabolites.A: 0.0, test_model.metabolites.B: -1.0 }) test_model.add_reactions([v1, v2, v3, v4, v5]) test_model.objective = 'v5' return test_model
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_change_coefficient(self, solver_test): solver, old_solution, infeasible_model = solver_test c = Metabolite("c") c._bound = 6 x = Reaction("x") x.lower_bound = 1. y = Reaction("y") y.lower_bound = 0. x.add_metabolites({c: 1}) z = Reaction("z") z.add_metabolites({c: 1}) z.objective_coefficient = 1 m = Model("test_model") m.add_reactions([x, y, z]) # change an existing coefficient lp = solver.create_problem(m) solver.solve_problem(lp) sol1 = solver.format_solution(lp, m) assert sol1.status == "optimal" solver.change_coefficient(lp, 0, 0, 2) solver.solve_problem(lp) sol2 = solver.format_solution(lp, m) assert sol2.status == "optimal" assert abs(sol1.f - 5.0) < 10 ** -3 assert abs(sol2.f - 4.0) < 10 ** -3 # change a new coefficient z.objective_coefficient = 0. y.objective_coefficient = 1. lp = solver.create_problem(m) solver.change_coefficient(lp, 0, 1, 2) solver.solve_problem(lp) solution = solver.format_solution(lp, m) assert solution.status == "optimal" assert abs(solution.x_dict["y"] - 2.5) < 10 ** -3
def test_gpr(self): model = Model() reaction = Reaction("test") # set a gpr to reaction not in a model reaction.gene_reaction_rule = "(g1 or g2) and g3" assert reaction.gene_reaction_rule == "(g1 or g2) and g3" assert len(reaction.genes) == 3 # adding reaction with a GPR propagates to the model model.add_reaction(reaction) assert len(model.genes) == 3 # ensure the gene objects are the same in the model and reaction reaction_gene = list(reaction.genes)[0] model_gene = model.genes.get_by_id(reaction_gene.id) assert reaction_gene is model_gene # test ability to handle uppercase AND/OR with warnings.catch_warnings(): warnings.simplefilter("ignore") reaction.gene_reaction_rule = "(b1 AND b2) OR (b3 and b4)" assert reaction.gene_reaction_rule == "(b1 and b2) or (b3 and b4)" assert len(reaction.genes) == 4 # ensure regular expressions correctly extract genes from malformed # GPR string with warnings.catch_warnings(): warnings.simplefilter("ignore") reaction.gene_reaction_rule = "(a1 or a2" assert len(reaction.genes) == 2 reaction.gene_reaction_rule = "(forT or " assert len(reaction.genes) == 1
def test_solve_mip(self, solver_test): solver, old_solution, infeasible_model = solver_test if not hasattr(solver, "_SUPPORTS_MILP") or not solver._SUPPORTS_MILP: pytest.skip("no milp support") cobra_model = Model('MILP_implementation_test') constraint = Metabolite("constraint") constraint._bound = 2.5 x = Reaction("x") x.lower_bound = 0. x.objective_coefficient = 1. x.add_metabolites({constraint: 2.5}) y = Reaction("y") y.lower_bound = 0. y.objective_coefficient = 1. y.add_metabolites({constraint: 1.}) cobra_model.add_reactions([x, y]) float_sol = solver.solve(cobra_model) # add an integer constraint y.variable_kind = "integer" int_sol = solver.solve(cobra_model) assert abs(float_sol.f - 2.5) < 10 ** -5 assert abs(float_sol.x_dict["y"] - 2.5) < 10 ** -5 assert int_sol.status == "optimal" assert abs(int_sol.f - 2.2) < 10 ** -3 assert abs(int_sol.x_dict["y"] - 2.0) < 10 ** -3
def test_complicated_model(): """Test a complicated model. 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.bounds = (0, 6) reaction2.bounds = (0, 8) reaction3.bounds = (0, 10) A = Metabolite('A') reaction1.add_metabolites({A: -1}) reaction2.add_metabolites({A: -1}) reaction3.add_metabolites({A: 1}) model.add_reactions([reaction1, reaction2, 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_reverse_reaction(): model = Model() reaction = Reaction('AB') model.add_reaction(reaction) reaction.build_reaction_from_string('a --> b') _reverse_reaction(reaction) assert reaction.reaction == 'b <-- a'
def test_toy_model_tolerance_with_different_default(): """Verify that different default tolerance is respected by Model.""" config = Configuration() config.tolerance = 1e-05 toy_model = Model(name="toy model") assert toy_model.tolerance == 1e-05
def __init__(self, list_of_models=[], identifier=None, name=None): Object.__init__(self, identifier, name) if len(list_of_models) > 1: if not all(isinstance(x, Model) for x in list_of_models): raise AttributeError( "list_of_models may only contain cobra.core.Model objects") if len([model.id for model in list_of_models]) > \ len(set([model.id for model in list_of_models])): raise AssertionError( "Ensemble members cannot have duplicate model ids.") self.features = DictList() self._populate_features_base(list_of_models) self.members = DictList() self._populate_members(list_of_models) else: if len(list_of_models) == 0: self.base_model = Model(id_or_model=identifier+'_base_model',\ name=name) else: if not isinstance(list_of_models[0], Model): raise AttributeError( "list_of_models may only contain cobra.core.Model objects" ) self.base_model = list_of_models[0]
def construct_ll_test_model(): test_model = Model() test_model.add_metabolites(Metabolite("A")) test_model.add_metabolites(Metabolite("B")) test_model.add_metabolites(Metabolite("C")) EX_A = Reaction("EX_A") EX_A.add_metabolites({test_model.metabolites.A: 1}) DM_C = Reaction("DM_C") DM_C.add_metabolites({test_model.metabolites.C: -1}) v1 = Reaction("v1") v1.add_metabolites({ test_model.metabolites.A: -1, test_model.metabolites.B: 1 }) v2 = Reaction("v2") v2.add_metabolites({ test_model.metabolites.B: -1, test_model.metabolites.C: 1 }) v3 = Reaction("v3") v3.add_metabolites({ test_model.metabolites.C: -1, test_model.metabolites.A: 1 }) test_model.add_reactions([EX_A, DM_C, v1, v2, v3]) DM_C.objective_coefficient = 1 return test_model
def test_transfer_objective(self, model): new_mod = Model("new model") new_mod.add_reactions(model.reactions) new_mod.objective = model.objective assert (set(str(x) for x in model.objective.expression.args) == set( str(x) for x in new_mod.objective.expression.args)) new_mod.solver.optimize() assert abs(new_mod.objective.value - 0.874) < 0.001
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_gene_knockout(salmonella: Model) -> None: """Test gene knockout.""" gene_list = ["STM1067", "STM0227"] dependent_reactions = { "3HAD121", "3HAD160", "3HAD80", "3HAD140", "3HAD180", "3HAD100", "3HAD181", "3HAD120", "3HAD60", "3HAD141", "3HAD161", "T2DECAI", "3HAD40", } _gene_knockout_computation(salmonella, gene_list, dependent_reactions) _gene_knockout_computation(salmonella, ["STM4221"], {"PGI"}) _gene_knockout_computation(salmonella, ["STM1746.S"], {"4PEPTabcpp"}) # test cumulative behavior delete_model_genes(salmonella, gene_list[:1]) delete_model_genes(salmonella, gene_list[1:], cumulative_deletions=True) delete_model_genes(salmonella, ["STM4221"], cumulative_deletions=True) dependent_reactions.add("PGI") assert _get_removed(salmonella) == dependent_reactions # non-cumulative following cumulative delete_model_genes(salmonella, ["STM4221"], cumulative_deletions=False) assert _get_removed(salmonella) == {"PGI"} # make sure on reset that the bounds are correct reset_bound = salmonella.reactions.get_by_id("T2DECAI").upper_bound assert reset_bound == 1000.0 # test computation when gene name is a subset of another test_model = Model() test_reaction_1 = Reaction("test1") test_reaction_1.gene_reaction_rule = "eggs or (spam and eggspam)" test_model.add_reactions([test_reaction_1]) _gene_knockout_computation(test_model, ["eggs"], set()) _gene_knockout_computation(test_model, ["eggs", "spam"], {"test1"}) # test computation with nested boolean expression test_reaction_1.gene_reaction_rule = "g1 and g2 and (g3 or g4 or (g5 and g6))" _gene_knockout_computation(test_model, ["g3"], set()) _gene_knockout_computation(test_model, ["g1"], {"test1"}) _gene_knockout_computation(test_model, ["g5"], set()) _gene_knockout_computation(test_model, ["g3", "g4", "g5"], {"test1"}) # test computation when gene names are python expressions test_reaction_1.gene_reaction_rule = "g1 and (for or in)" _gene_knockout_computation(test_model, ["for", "in"], {"test1"}) _gene_knockout_computation(test_model, ["for"], set()) test_reaction_1.gene_reaction_rule = "g1 and g2 and g2.conjugate" _gene_knockout_computation(test_model, ["g2"], {"test1"}) _gene_knockout_computation(test_model, ["g2.conjugate"], {"test1"}) test_reaction_1.gene_reaction_rule = "g1 and (try:' or 'except:1)" _gene_knockout_computation(test_model, ["try:'"], set()) _gene_knockout_computation(test_model, ["try:'", "'except:1"], {"test1"})
def test_compartments(self, model): assert set(model.compartments) == {"c", "e"} model = Model("test", "test") met_c = Metabolite("a_c", compartment="c") met_e = Metabolite("a_e", compartment="e") rxn = Reaction("foo") rxn.add_metabolites({met_e: -1, met_c: 1}) model.add_reactions([rxn]) assert model.compartments == {'c': '', 'e': ''} model.compartments = {'c': 'cytosol'} assert model.compartments == {'c': 'cytosol', 'e': ''}
def test_gapfilling(self): try: get_solver_name(mip=True) except SolverNotFound: pytest.skip("no MILP solver found") m = Model() m.add_metabolites(map(Metabolite, ["a", "b", "c"])) r = Reaction("EX_A") m.add_reaction(r) r.add_metabolites({m.metabolites.a: 1}) r = Reaction("r1") m.add_reaction(r) r.add_metabolites({m.metabolites.b: -1, m.metabolites.c: 1}) r = Reaction("DM_C") m.add_reaction(r) r.add_metabolites({m.metabolites.c: -1}) r.objective_coefficient = 1 U = Model() r = Reaction("a2b") U.add_reaction(r) r.build_reaction_from_string("a --> b", verbose=False) r = Reaction("a2d") U.add_reaction(r) r.build_reaction_from_string("a --> d", verbose=False) # GrowMatch result = gapfilling.growMatch(m, U)[0] assert len(result) == 1 assert result[0].id == "a2b" # SMILEY result = gapfilling.SMILEY(m, "b", U)[0] assert len(result) == 1 assert result[0].id == "a2b" # 2 rounds of GrowMatch with exchange reactions result = gapfilling.growMatch(m, None, ex_rxns=True, iterations=2) assert len(result) == 2 assert len(result[0]) == 1 assert len(result[1]) == 1 assert {i[0].id for i in result} == {"SMILEY_EX_b", "SMILEY_EX_c"}
def test_quadratic(self, solver_test): solver, old_solution, infeasible_model = solver_test if not hasattr(solver, "set_quadratic_objective"): pytest.skip("no qp support") c = Metabolite("c") c._bound = 2 x = Reaction("x") x.objective_coefficient = -0.5 x.lower_bound = 0. y = Reaction("y") y.objective_coefficient = -0.5 y.lower_bound = 0. x.add_metabolites({c: 1}) y.add_metabolites({c: 1}) m = Model() m.add_reactions([x, y]) lp = solver.create_problem(m) quadratic_obj = scipy.sparse.eye(2) * 2 solver.set_quadratic_objective(lp, quadratic_obj) solver.solve_problem(lp, objective_sense="minimize") solution = solver.format_solution(lp, m) assert solution.status == "optimal" # Respecting linear objectives also makes the objective value 1. assert abs(solution.f - 1.) < 10 ** -3 assert abs(solution.x_dict["y"] - 1.) < 10 ** -3 assert abs(solution.x_dict["y"] - 1.) < 10 ** -3 # When the linear objectives are removed the objective value is 2. solver.change_variable_objective(lp, 0, 0.) solver.change_variable_objective(lp, 1, 0.) solver.solve_problem(lp, objective_sense="minimize") solution = solver.format_solution(lp, m) assert solution.status == "optimal" assert abs(solution.f - 2.) < 10 ** -3 # test quadratic from solve function solution = solver.solve(m, quadratic_component=quadratic_obj, objective_sense="minimize") assert solution.status == "optimal" assert abs(solution.f - 1.) < 10 ** -3 c._bound = 6 z = Reaction("z") x.objective_coefficient = 0. y.objective_coefficient = 0. z.lower_bound = 0. z.add_metabolites({c: 1}) m.add_reaction(z) solution = solver.solve(m, quadratic_component=scipy.sparse.eye(3), objective_sense="minimize") # should be 12 not 24 because 1/2 (V^T Q V) assert solution.status == "optimal" assert abs(solution.f - 6) < 10 ** -3 assert abs(solution.x_dict["x"] - 2) < 10 ** -6 assert abs(solution.x_dict["y"] - 2) < 10 ** -6 assert abs(solution.x_dict["z"] - 2) < 10 ** -6
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_custom_hashes(): # These hashes are generated from old IDs in models (in reaction strings), # and they match to these corrected BiGG reaction IDs cases = [ ('39b5f90a1919aef07473e2f835ce63af', 'EX_frmd_e', 'foam_e <=>'), ('92f1047c72db0a36413d822863be514e', 'EX_phllqne_e', 'phyQ_e <=>'), ] model = Model() for reaction_hash, bigg_id, reaction_string in cases: reaction = Reaction(bigg_id) model.add_reaction(reaction) reaction.build_reaction_from_string(reaction_string) lookup_dict = {m.id: m.id for m in model.metabolites} assert hash_reaction(reaction, lookup_dict) == reaction_hash
def geometric_fba_model(): """ Generate geometric FBA model as described in [1]_ References ---------- .. [1] Smallbone, Kieran & Simeonidis, Vangelis. (2009). Flux balance analysis: A geometric perspective. Journal of theoretical biology.258. 311-5. 10.1016/j.jtbi.2009.01.027. """ test_model = Model("geometric_fba_paper_model") test_model.add_metabolites(Metabolite("A")) test_model.add_metabolites(Metabolite("B")) v_1 = Reaction("v1", upper_bound=1.0) v_1.add_metabolites({test_model.metabolites.A: 1.0}) v_2 = Reaction("v2", lower_bound=-1000.0) v_2.add_metabolites({ test_model.metabolites.A: -1.0, test_model.metabolites.B: 1.0 }) v_3 = Reaction("v3", lower_bound=-1000.0) v_3.add_metabolites({ test_model.metabolites.A: -1.0, test_model.metabolites.B: 1.0 }) v_4 = Reaction("v4", lower_bound=-1000.0) v_4.add_metabolites({ test_model.metabolites.A: -1.0, test_model.metabolites.B: 1.0 }) v_5 = Reaction("v5") v_5.add_metabolites({ test_model.metabolites.A: 0.0, test_model.metabolites.B: -1.0 }) test_model.add_reactions([v_1, v_2, v_3, v_4, v_5]) test_model.objective = "v5" return test_model
def model_from_dict(obj): """Build a model from a dict. Models stored in json are first formulated as a dict that can be read to cobra model using this function. Parameters ---------- obj : dict A dictionary with elements, 'genes', 'compartments', 'id', 'metabolites', 'notes' and 'reqctions' where 'metabolites', 'genes' and 'metabolites' are in turn lists with dictionaries holding all attributes to form the corresponding object. Returns ------- cora.core.Model The generated model. See Also -------- cobra.io.json.model_to_dict """ if 'reactions' not in obj: raise Exception('JSON object has no reactions attribute. Cannot load.') model = Model() model.add_metabolites([ metabolite_from_dict(metabolite) for metabolite in obj['metabolites'] ]) model.genes.extend([gene_from_dict(gene) for gene in obj['genes']]) model.add_reactions( [reaction_from_dict(reaction, model) for reaction in obj['reactions']]) objective_reactions = [ rxn for rxn in obj['reactions'] if rxn.get('objective_coefficient', 0) != 0 ] coefficients = { model.reactions.get_by_id(rxn['id']): rxn['objective_coefficient'] for rxn in objective_reactions } set_objective(model, coefficients) for k, v in iteritems(obj): if k in {'id', 'name', 'notes', 'compartments', 'annotation'}: setattr(model, k, v) return model
def __init__(self, model, universal=None, lower_bound=0.05, penalties=None, exchange_reactions=False, demand_reactions=True, integer_threshold=1e-6): self.original_model = model self.lower_bound = lower_bound self.model = model.copy() tolerances = self.model.solver.configuration.tolerances tolerances.integrality = integer_threshold self.universal = universal.copy() if universal else Model('universal') self.penalties = dict(universal=1, exchange=100, demand=1) if penalties is not None: self.penalties.update(penalties) self.integer_threshold = integer_threshold self.indicators = list() self.costs = dict() self.extend_model(exchange_reactions, demand_reactions) fix_objective_as_constraint(self.model, bound=lower_bound) self.add_switches_and_objective()
def create_example_model(self): model = Model('example_model') rs = (r1, r2, r3) = (Reaction('R1'), Reaction('R2'), Reaction('R3')) for r in rs: r.lower_bound = 0. r.upper_bound = 1000. r.objective_coefficient = 0. ACP_c = Metabolite('ACP_c', formula='C11H21N2O7PRS', name='acyl-carrier-protein', compartment='c') r1.add_metabolites({ACP_c: 1.0}) r2.add_metabolites({ACP_c: 1.0}) r3.add_metabolites({ACP_c: -1.0}) model.add_reactions(rs) return model
def test_remove_genes() -> None: """Test gene removal.""" m = Model("test") m.add_reactions([Reaction("r" + str(i + 1)) for i in range(8)]) assert len(m.reactions) == 8 rxns = m.reactions rxns.r1.gene_reaction_rule = "(a and b) or (c and a)" rxns.r2.gene_reaction_rule = "(a and b and d and e)" rxns.r3.gene_reaction_rule = "(a and b) or (b and c)" rxns.r4.gene_reaction_rule = "(f and b) or (b and c)" rxns.r5.gene_reaction_rule = "x" rxns.r6.gene_reaction_rule = "y" rxns.r7.gene_reaction_rule = "x or z" rxns.r8.gene_reaction_rule = "" assert "a" in m.genes assert "x" in m.genes remove_genes(m, ["a"], remove_reactions=False) assert "a" not in m.genes assert "x" in m.genes assert rxns.r1.gene_reaction_rule == "" assert rxns.r2.gene_reaction_rule == "" assert rxns.r3.gene_reaction_rule == "b and c" assert rxns.r4.gene_reaction_rule == "(f and b) or (b and c)" assert rxns.r5.gene_reaction_rule == "x" assert rxns.r6.gene_reaction_rule == "y" assert rxns.r7.genes == {m.genes.x, m.genes.z} assert rxns.r8.gene_reaction_rule == "" remove_genes(m, ["x"], remove_reactions=True) assert len(m.reactions) == 7 assert "r5" not in m.reactions assert "x" not in m.genes assert rxns.r1.gene_reaction_rule == "" assert rxns.r2.gene_reaction_rule == "" assert rxns.r3.gene_reaction_rule == "b and c" assert rxns.r4.gene_reaction_rule == "(f and b) or (b and c)" assert rxns.r6.gene_reaction_rule == "y" assert rxns.r7.gene_reaction_rule == "z" assert rxns.r7.genes == {m.genes.z} assert rxns.r8.gene_reaction_rule == ""
def room_model(): """ Generate ROOM model as described in [1]_ References ---------- .. [1] Tomer Shlomi, Omer Berkman and Eytan Ruppin, "Regulatory on/off minimization of metabolic flux changes after genetic perturbations", PNAS 2005 102 (21) 7695-7700; doi:10.1073/pnas.0406346102 """ test_model = Model("papin_2003") v_1 = Reaction("v1") v_2 = Reaction("v2") v_3 = Reaction("v3") v_4 = Reaction("v4") v_5 = Reaction("v5") v_6 = Reaction("v6", upper_bound=0.0) b_1 = Reaction("b1", upper_bound=10.0, lower_bound=0.0) b_2 = Reaction("b2") b_3 = Reaction("b3") test_model.add_reactions([v_1, v_2, v_3, v_4, v_5, v_6, b_1, b_2, b_3]) v_1.reaction = "A -> B" v_2.reaction = "2 B -> C + byp" v_3.reaction = "2 B + cof -> D" v_4.reaction = "D -> E + cof" v_5.reaction = "C + cof -> D" v_6.reaction = "C -> E" b_1.reaction = "-> A" b_2.reaction = "E ->" b_3.reaction = "byp ->" test_model.objective = 'b2' return test_model
def test_remove_genes(self): m = Model("test") m.add_reactions([Reaction("r" + str(i + 1)) for i in range(8)]) self.assertEqual(len(m.reactions), 8) rxns = m.reactions rxns.r1.gene_reaction_rule = "(a and b) or (c and a)" rxns.r2.gene_reaction_rule = "(a and b and d and e)" rxns.r3.gene_reaction_rule = "(a and b) or (b and c)" rxns.r4.gene_reaction_rule = "(f and b) or (b and c)" rxns.r5.gene_reaction_rule = "x" rxns.r6.gene_reaction_rule = "y" rxns.r7.gene_reaction_rule = "x or z" rxns.r8.gene_reaction_rule = "" self.assertIn("a", m.genes) self.assertIn("x", m.genes) remove_genes(m, ["a"], remove_reactions=False) self.assertNotIn("a", m.genes) self.assertIn("x", m.genes) self.assertEqual(rxns.r1.gene_reaction_rule, "") self.assertEqual(rxns.r2.gene_reaction_rule, "") self.assertEqual(rxns.r3.gene_reaction_rule, "b and c") self.assertEqual(rxns.r4.gene_reaction_rule, "(f and b) or (b and c)") self.assertEqual(rxns.r5.gene_reaction_rule, "x") self.assertEqual(rxns.r6.gene_reaction_rule, "y") self.assertEqual(rxns.r7.genes, {m.genes.x, m.genes.z}) self.assertEqual(rxns.r8.gene_reaction_rule, "") remove_genes(m, ["x"], remove_reactions=True) self.assertEqual(len(m.reactions), 7) self.assertNotIn("r5", m.reactions) self.assertNotIn("x", m.genes) self.assertEqual(rxns.r1.gene_reaction_rule, "") self.assertEqual(rxns.r2.gene_reaction_rule, "") self.assertEqual(rxns.r3.gene_reaction_rule, "b and c") self.assertEqual(rxns.r4.gene_reaction_rule, "(f and b) or (b and c)") self.assertEqual(rxns.r6.gene_reaction_rule, "y") self.assertEqual(rxns.r7.gene_reaction_rule, "z") self.assertEqual(rxns.r7.genes, {m.genes.z}) self.assertEqual(rxns.r8.gene_reaction_rule, "")
def create_example2_model(self): model = Model('example2_model') rs = (r1, r2, r3, r4, r5) = (Reaction('R1'), Reaction('R2'), Reaction('R3'), Reaction('R4'), Reaction('R5')) for r in rs: r.lower_bound = 0. r.upper_bound = 1000. r.objective_coefficient = 0. ms = (m1, m2, m3) = (Metabolite('M1'), Metabolite('M2'), Metabolite('M3')) r1.add_metabolites({m1: 1.0}) r2.add_metabolites({m1: -1.0, m2: 1.0}) r3.add_metabolites({m2: -1.0}) r4.add_metabolites({m1: -1.0, m3: 1.0}) r5.add_metabolites({m3: -1.0}) model.add_reactions(rs) return model