Esempio n. 1
0
 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
Esempio n. 2
0
    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)
Esempio n. 3
0
def test_gpr():
    model = Model()
    reaction = Reaction("test")

    # Set GPR to a 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_reactions([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
Esempio n. 4
0
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'
Esempio n. 5
0
 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
Esempio n. 6
0
 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
Esempio n. 7
0
 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
Esempio n. 8
0
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
Esempio n. 9
0
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'
Esempio n. 10
0
def test_loopless_solution(ll_test_model: Model) -> None:
    """Test loopless_solution()."""
    solution_feasible = loopless_solution(ll_test_model)
    ll_test_model.reactions.v3.lower_bound = 1
    ll_test_model.optimize()
    solution_infeasible = loopless_solution(ll_test_model)
    assert solution_feasible.fluxes["v3"] == 0.0
    assert solution_infeasible.fluxes["v3"] == 1.0
Esempio n. 11
0
def test_bad_exchange(model: Model) -> None:
    """Test bad exchange reaction identification."""
    with pytest.raises(ValueError):
        m = Metabolite("baddy", compartment="nonsense")
        model.add_boundary(m, type="exchange")
    m = Metabolite("goody", compartment="e")
    rxn = model.add_boundary(m, type="exchange")
    assert isinstance(rxn, Reaction)
Esempio n. 12
0
def test_find_boundary_types_demand(model: Model) -> None:
    """Test boundary type identification for demands."""
    dm = Reaction("demand")
    model.add_reaction(dm)
    dm.build_reaction_from_string("atp_c ->")
    dm = model.demands
    assert len(dm) == 1
    assert "demand" in [r.id for r in dm]
Esempio n. 13
0
 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
Esempio n. 14
0
def test_prune_unused_reactions_output_type(model: Model) -> None:
    """Test the output type of unused reactions pruning."""
    reaction = Reaction("foo")
    model.add_reactions([reaction])
    model_pruned, unused = prune_unused_reactions(model)
    assert isinstance(model_pruned, Model)
    # test that the output contains reaction objects
    assert isinstance(unused[0], Reaction)
Esempio n. 15
0
def test_add_loopless(ll_test_model: Model) -> None:
    """Test add_loopless()."""
    add_loopless(ll_test_model)
    feasible_status = ll_test_model.optimize().status
    ll_test_model.reactions.v3.lower_bound = 1
    ll_test_model.slim_optimize()
    infeasible_status = ll_test_model.solver.status
    assert feasible_status == OPTIMAL
    assert infeasible_status == INFEASIBLE
Esempio n. 16
0
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
Esempio n. 17
0
def test_find_boundary_types_sink(model: Model) -> None:
    """Test boundary type identification for sinks."""
    sn = Reaction("sink")
    model.add_reaction(sn)
    sn.build_reaction_from_string("atp_c <->")
    sn.bounds = -1000, 1000
    sn = model.sinks
    assert len(sn) == 1
    assert "sink" in [r.id for r in sn]
Esempio n. 18
0
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"})
Esempio n. 19
0
def test_inequality_constraint(model: Model) -> None:
    """Test inequality constraint."""
    co = model.problem.Constraint(model.reactions.ACALD.flux_expression, lb=-0.5)
    model.add_cons_vars(co)

    s = sample(model, 10)
    assert all(s.ACALD > -0.5 - 1e-6)

    s = sample(model, 10, method="achr")
    assert all(s.ACALD > -0.5 - 1e-6)
Esempio n. 20
0
def test_compartments(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': ''}
Esempio n. 21
0
 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': ''}
Esempio n. 22
0
def test_single_point_space(model: Model) -> None:
    """Test the reduction of the sampling space to one point."""
    pfba_sol = pfba(model)
    pfba_const = model.problem.Constraint(
        sum(model.variables), ub=pfba_sol.objective_value
    )
    model.add_cons_vars(pfba_const)
    model.reactions.Biomass_Ecoli_core.lower_bound = pfba_sol.fluxes.Biomass_Ecoli_core

    with pytest.raises(ValueError):
        sample(model, 1)
Esempio n. 23
0
def test_find_external_compartment_multi(model: Model) -> None:
    """Test multiple external compartment identification."""
    for r in model.reactions:
        r._compartments = None
    model.exchanges[0].reactants[0].compartment = "extracellular"
    # still works due to different boundary numbers
    assert find_external_compartment(model) == "e"
    model.exchanges[1].reactants[0].compartment = "extra cellular"
    model.remove_reactions(model.exchanges)
    # Now fails because same boundary count
    with pytest.raises(RuntimeError):
        find_external_compartment(model)
Esempio n. 24
0
def test_model_less_reaction(model: Model) -> None:
    """Test model without reactions."""
    model.slim_optimize()
    for reaction in model.reactions:
        assert isinstance(reaction.flux, float)
        assert isinstance(reaction.reduced_cost, float)
    for reaction in model.reactions:
        model.remove_reactions([reaction])
        with pytest.raises(RuntimeError):
            reaction.flux
        with pytest.raises(RuntimeError):
            reaction.reduced_cost
Esempio n. 25
0
 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
Esempio n. 26
0
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
Esempio n. 27
0
def test_prune_unused_rxns_functionality(model: Model) -> None:
    """Test the sanity of unused reactions pruning."""
    for x in ["foo1", "foo2", "foo3"]:
        model.add_reactions([Reaction(x)])

    model_pruned, unused = prune_unused_reactions(model)
    assert "foo1" in model.reactions
    assert "foo2" in model.reactions
    assert "foo3" in model.reactions
    # test that the unused reactions are not used in the model
    assert "foo1" not in model_pruned.reactions
    assert "foo2" not in model_pruned.reactions
    assert "foo3" not in model_pruned.reactions
Esempio n. 28
0
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
Esempio n. 29
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
Esempio n. 30
0
def test_sbo_annotation(model: Model) -> None:
    """Test SBO annotation function."""
    rxns = model.reactions
    rxns.EX_o2_e.annotation.clear()
    fake_DM = Reaction("DM_h_c")
    model.add_reactions([fake_DM])
    fake_DM.add_metabolites({model.metabolites.get_by_id("h_c"): -1})
    # this exchange will be set wrong. The function should not overwrite
    # an existing SBO annotation
    rxns.get_by_id("EX_h_e").annotation["sbo"] = "SBO:0000628"
    add_SBO(model)
    assert rxns.EX_o2_e.annotation["sbo"] == "SBO:0000627"
    assert rxns.DM_h_c.annotation["sbo"] == "SBO:0000628"
    assert rxns.EX_h_e.annotation["sbo"] == "SBO:0000628"
Esempio n. 31
0
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
Esempio n. 32
0
def test_add_metabolite(model: Model) -> None:
    """Test metabolite addition to a reaction from an unsolved model."""
    with pytest.raises(ValueError):
        model.add_metabolites(Metabolite())
    with model:
        with model:
            reaction = model.reactions.get_by_id("PGI")
            reaction.add_metabolites({model.metabolites[0]: 1})
            assert model.metabolites[0] in reaction._metabolites
            fake_metabolite = Metabolite("fake")
            reaction.add_metabolites({fake_metabolite: 1})
            assert fake_metabolite in reaction._metabolites
            assert model.metabolites.has_id("fake")
            assert model.metabolites.get_by_id("fake") is fake_metabolite
            assert len(model._contexts[0]._history) == 0

    assert fake_metabolite._model is None
    assert fake_metabolite not in reaction._metabolites
    assert "fake" not in model.metabolites

    # Test adding by string
    with model:
        reaction.add_metabolites({"g6p_c": -1})  # already in reaction
        assert reaction._metabolites[model.metabolites.get_by_id(
            "g6p_c")] == -2
        reaction.add_metabolites({"h_c": 1})
        assert reaction._metabolites[model.metabolites.get_by_id("h_c")] == 1
        with pytest.raises(KeyError):
            reaction.add_metabolites({"missing": 1})

    assert reaction._metabolites[model.metabolites.get_by_id("g6p_c")] == -1
    assert model.metabolites.h_c not in reaction._metabolites

    # Test combine=False
    reaction = model.reactions.get_by_id("ATPM")
    old_stoich = reaction._metabolites[model.metabolites.get_by_id("h2o_c")]
    with model:
        reaction.add_metabolites({"h2o_c": 2.5}, combine=False)
        assert reaction._metabolites[model.metabolites.get_by_id(
            "h2o_c")] == 2.5

    assert reaction._metabolites[model.metabolites.get_by_id(
        "h2o_c")] == old_stoich

    # Test adding to a new Reaction
    reaction = Reaction("test")
    assert len(reaction._metabolites) == 0
    reaction.add_metabolites({Metabolite("test_met"): -1})
    assert len(reaction._metabolites) == 1
Esempio n. 33
0
 def __json_decode__(self, **attrs):
     """build a model from a dict"""
     Model.__init__(self)
     if 'reactions' not in attrs:
         raise Exception('JSON object has no reactions attribute. Cannot load.')
     self.add_metabolites(
             [cobra.io.dict.metabolite_from_dict(metabolite) for metabolite in attrs['metabolites']]
     )
     self.genes = DictList(attrs['genes'])
     self.add_reactions(
             [cobra.io.dict.reaction_from_dict(reaction, self) for reaction in attrs['reactions']]
     )
     for k, v in attrs.items():
         if k in {'id', 'name', 'notes', 'compartments', 'annotation'}:
             setattr(self, k, v)
Esempio n. 34
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()
     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()
Esempio n. 35
0
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
Esempio n. 36
0
    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]
Esempio n. 37
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()
Esempio n. 38
0
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 'reactions'; 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.model_to_dict
    """
    if 'reactions' not in obj:
        raise ValueError('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
Esempio n. 39
0
 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.slim_optimize()
     assert abs(new_mod.objective.value - 0.874) < 0.001
Esempio n. 40
0
 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, "")
Esempio n. 41
0
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
Esempio n. 42
0
 def test_remove_genes(self):
     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 == ""
Esempio n. 43
0
def construct_papin_2003_model():
    test_model = Model("papin_2003")
    v1 = Reaction("v1")
    v2 = Reaction("v2")
    v3 = Reaction("v3")
    v4 = Reaction("v4")
    v5 = Reaction("v5")
    v6 = Reaction("v6", upper_bound=0.0)
    b1 = Reaction("b1", upper_bound=10.0, lower_bound=0.0)
    b2 = Reaction("b2")
    b3 = Reaction("b3")
    test_model.add_reactions([v1, v2, v3, v4, v5, v6, b1, b2, b3])
    v1.reaction = "A -> B"
    v2.reaction = "2 B -> C + byp"
    v3.reaction = "2 B + cof -> D"
    v4.reaction = "D -> E + cof"
    v5.reaction = "C + cof -> D"
    v6.reaction = "C -> E"
    b1.reaction = "-> A"
    b2.reaction = "E ->"
    b3.reaction = "byp ->"
    test_model.objective = 'b2'
    return test_model
Esempio n. 44
0
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
Esempio n. 45
0
def create_consisten_model(model,metamodel,consistent_reactions):
    consistent_model = Model()
    consistent_model.id = model.id
    consistent_model.description = model.id
    
    auxiliar_gene = Gene('MODULAR_GAPFILLING')
    auxiliar_gene._model = consistent_model
    consistent_model.genes.append(auxiliar_gene)

    for reaction_id in consistent_reactions:
        new_reaction = metamodel.reactions.get_by_id(reaction_id).copy()
        
        if reaction_id in model.reactions:
            reaction_reference = model.reactions.get_by_id(reaction_id)
            gene_list = []
            
            for gene in reaction_reference.genes:
                if gene.id in consistent_model.genes:
                    gene_list.append(consistent_model.genes.get_by_id(gene.id))
                else:
                    new_gene = Gene(gene.id)
                    new_gene._model = consistent_model
                    consistent_model.genes.append(new_gene)
                    gene_list.append(new_gene)
            
            for gene in gene_list:
                gene._reaction.add(new_reaction)
            new_reaction._genes = gene_list
            new_reaction.gene_reaction_rule = reaction_reference.gene_reaction_rule

        else:
            new_reaction.gene_reaction_rule = auxiliar_gene.name
            auxiliar_gene._reaction.add(new_reaction)

        consistent_model.add_reaction(new_reaction)

    return consistent_model
Esempio n. 46
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
Esempio n. 47
0
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
Esempio n. 48
0
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
Esempio n. 49
0
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("&quot;") and rule.endswith("&quot;"):
                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
Esempio n. 50
0
    def test_gene_knockout_computation(self, salmonella):
        def find_gene_knockout_reactions_fast(cobra_model, gene_list):
            compiled_rules = get_compiled_gene_reaction_rules(
                cobra_model)
            return find_gene_knockout_reactions(
                cobra_model, gene_list,
                compiled_gene_reaction_rules=compiled_rules)

        def get_removed(m):
            return {x.id for x in m._trimmed_reactions}

        def test_computation(m, gene_ids, expected_reaction_ids):
            genes = [m.genes.get_by_id(i) for i in gene_ids]
            expected_reactions = {m.reactions.get_by_id(i)
                                  for i in expected_reaction_ids}
            removed1 = set(find_gene_knockout_reactions(m, genes))
            removed2 = set(find_gene_knockout_reactions_fast(m, genes))
            assert removed1 == expected_reactions
            assert removed2 == expected_reactions
            delete_model_genes(m, gene_ids, cumulative_deletions=False)
            assert get_removed(m) == expected_reaction_ids
            undelete_model_genes(m)

        gene_list = ['STM1067', 'STM0227']
        dependent_reactions = {'3HAD121', '3HAD160', '3HAD80', '3HAD140',
                               '3HAD180', '3HAD100', '3HAD181', '3HAD120',
                               '3HAD60', '3HAD141', '3HAD161', 'T2DECAI',
                               '3HAD40'}
        test_computation(salmonella, gene_list, dependent_reactions)
        test_computation(salmonella, ['STM4221'], {'PGI'})
        test_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.
        # 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_reaction(test_reaction_1)
        test_computation(test_model, ["eggs"], set())
        test_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))"
        test_computation(test_model, ["g3"], set())
        test_computation(test_model, ["g1"], {'test1'})
        test_computation(test_model, ["g5"], set())
        test_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)"
        test_computation(test_model, ["for", "in"], {'test1'})
        test_computation(test_model, ["for"], set())
        test_reaction_1.gene_reaction_rule = "g1 and g2 and g2.conjugate"
        test_computation(test_model, ["g2"], {"test1"})
        test_computation(test_model, ["g2.conjugate"], {"test1"})
        test_reaction_1.gene_reaction_rule = "g1 and (try:' or 'except:1)"
        test_computation(test_model, ["try:'"], set())
        test_computation(test_model, ["try:'", "'except:1"], {"test1"})
Esempio n. 51
0
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
Esempio n. 52
0
    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])
Esempio n. 53
0
def test_gapfilling(salmonella):
    """Test Gapfilling."""
    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 = 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 = 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 = 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"}

    # # Gapfilling solution adds metabolites not present in original model
    # test for when demand = T
    # a demand reaction must be added to clear new metabolite
    universal_noDM = Model()
    a2b = Reaction("a2b")
    universal_noDM.add_reactions([a2b])
    a2b.build_reaction_from_string("a --> b + d", verbose=False)
    result = gapfill(m, universal_noDM,
                     exchange_reactions=False,
                     demand_reactions=True)[0]
    # add reaction a2b and demand reaction to clear met d
    assert len(result) == 2
    assert "a2b" in [x.id for x in result]

    # test for when demand = False
    # test for when metabolites are added to the model and
    # must be cleared by other reactions in universal model
    # (i.e. not necessarily a demand reaction)
    universal_withDM = universal_noDM.copy()
    d_dm = Reaction("d_dm")
    universal_withDM.add_reactions([d_dm])
    d_dm.build_reaction_from_string("d -->", verbose=False)
    result = gapfill(m, universal_withDM,
                     exchange_reactions=False,
                     demand_reactions=False)[0]
    assert len(result) == 2
    assert "a2b" in [x.id for x in result]

    # 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 = 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])
# You should have received a copy of the GNU General Public License along
# with this program; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.

import sys, re, os, glob
from cobra.core import Model
from cobra.io import read_sbml_model,write_sbml_model



folder = sys.argv[1]
metamodel_id = sys.argv[2]

assert os.path.isdir(folder)

metamodel = Model(metamodel_id)
metamodel.description = metamodel_id

reactions = set()
models = []
for fname in glob.glob(os.path.join(folder,"*.xml")):
    model = read_sbml_model(fname)
    models.append(model)
    print "%s loaded" % model.id
    for r in model.reactions:
        r.id = re.sub('_[ec][0-9]','',r.id)
        if r.id in reactions:
            continue
        metamodel.add_reaction(r.copy())
        reactions.add(r.id) 
Esempio n. 55
0
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
Esempio n. 56
0
    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"}