Esempio n. 1
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. 2
0
def test_iadd(model: Model) -> None:
    """Test in-place addition of reaction."""
    PGI = model.reactions.PGI
    EX_h2o = model.reactions.EX_h2o_e
    original_PGI_gpr = PGI.gene_reaction_rule
    PGI += EX_h2o
    assert PGI.gene_reaction_rule == original_PGI_gpr
    assert PGI.metabolites[model.metabolites.h2o_e] == -1.0
    # Original should not change
    assert EX_h2o.gene_reaction_rule == ""
    assert EX_h2o.metabolites[model.metabolites.h2o_e] == -1.0
    # Add a reaction not in the model
    new_reaction = Reaction("test")
    new_reaction.add_metabolites({Metabolite("A"): -1, Metabolite("B"): 1})
    PGI += new_reaction
    assert PGI.gene_reaction_rule == original_PGI_gpr
    assert len(PGI.gene_reaction_rule) == 5
    # And vice versa
    new_reaction += PGI
    assert len(new_reaction.metabolites) == 5  # not
    assert len(new_reaction.genes) == 1
    assert new_reaction.gene_reaction_rule == original_PGI_gpr
    # Combine two GPRs
    model.reactions.ACKr += model.reactions.ACONTa
    expected_rule = "(b2296 or b3115 or b1849) and (b0118 or b1276)"
    assert model.reactions.ACKr.gene_reaction_rule == expected_rule
    assert len(model.reactions.ACKr.genes) == 5
Esempio n. 3
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. 4
0
    def test_add_reaction_context(self, model):
        old_reaction_count = len(model.reactions)
        old_metabolite_count = len(model.metabolites)
        dummy_metabolite_1 = Metabolite("test_foo_1")
        dummy_metabolite_2 = Metabolite("test_foo_2")
        actual_metabolite = model.metabolites[0]
        copy_metabolite = model.metabolites[1].copy()
        dummy_reaction = Reaction("test_foo_reaction")
        dummy_reaction.add_metabolites({
            dummy_metabolite_1: -1,
            dummy_metabolite_2: 1,
            copy_metabolite: -2,
            actual_metabolite: 1
        })
        dummy_reaction.gene_reaction_rule = 'dummy_gene'

        with model:
            model.add_reaction(dummy_reaction)
            assert model.reactions.get_by_id(dummy_reaction.id) == \
                dummy_reaction
            assert len(model.reactions) == old_reaction_count + 1
            assert len(model.metabolites) == old_metabolite_count + 2
            assert dummy_metabolite_1._model == model
            assert 'dummy_gene' in model.genes

        assert len(model.reactions) == old_reaction_count
        assert len(model.metabolites) == old_metabolite_count
        with pytest.raises(KeyError):
            model.reactions.get_by_id(dummy_reaction.id)
        assert dummy_metabolite_1._model is None
        assert 'dummy_gene' not in model.genes
Esempio n. 5
0
 def test_iadd(self, model):
     PGI = model.reactions.PGI
     EX_h2o = model.reactions.EX_h2o_e
     original_PGI_gpr = PGI.gene_reaction_rule
     PGI += EX_h2o
     assert PGI.gene_reaction_rule == original_PGI_gpr
     assert PGI.metabolites[model.metabolites.h2o_e] == -1.0
     # original should not have changed
     assert EX_h2o.gene_reaction_rule == ''
     assert EX_h2o.metabolites[model.metabolites.h2o_e] == -1.0
     # what about adding a reaction not in the model
     new_reaction = Reaction("test")
     new_reaction.add_metabolites({Metabolite("A"): -1, Metabolite("B"): 1})
     PGI += new_reaction
     assert PGI.gene_reaction_rule == original_PGI_gpr
     assert len(PGI.gene_reaction_rule) == 5
     # and vice versa
     new_reaction += PGI
     assert len(new_reaction.metabolites) == 5  # not
     assert len(new_reaction.genes) == 1
     assert new_reaction.gene_reaction_rule == original_PGI_gpr
     # what about combining 2 gpr's
     model.reactions.ACKr += model.reactions.ACONTa
     expected_rule = '(b2296 or b3115 or b1849) and (b0118 or b1276)'
     assert model.reactions.ACKr.gene_reaction_rule == expected_rule
     assert len(model.reactions.ACKr.genes) == 5
Esempio n. 6
0
    def test_get_yield_not_working_if_input_formula_missing(self):
        model = Model("test")
        met1 = Metabolite(id="S7P")
        met2 = Metabolite(id="T3P1", formula="C3H7O6P")
        met3 = Metabolite(id="E4P", formula="C4H9O7P")
        met4 = Metabolite(id="F6P", formula="C6H13O9P")
        model.add_metabolites((met1, met2, met3, met4))

        react1 = Reaction(id="r1", name="Transaldolase")
        react1.add_metabolites({met1: -1, met2: -1, met3: 1, met4: 1})

        react2 = Reaction(id="r2")
        react2.add_metabolites({met1: -1})

        react3 = Reaction(id="r3")
        react3.add_metabolites({met2: -1})

        react4 = Reaction(id="r4")
        react4.add_metabolites({met3: -1})

        react5 = Reaction(id="r5")
        react5.add_metabolites({met4: -1})

        model.add_reactions((react1, react2, react3, react4, react5))

        fluxes = {
            react1.id: 1,
            react2.id: -1,
            react3.id: -1,
            react4.id: 1,
            react5.id: 1
        }

        status, _ = get_yields(fluxes, model)
        assert status is False
 def test_add_reactions(self, model):
     r1 = Reaction('r1')
     r1.add_metabolites({Metabolite('A'): -1, Metabolite('B'): 1})
     r1.lower_bound, r1.upper_bound = -999999., 999999.
     r2 = Reaction('r2')
     r2.add_metabolites({
         Metabolite('A'): -1,
         Metabolite('C'): 1,
         Metabolite('D'): 1
     })
     r2.lower_bound, r2.upper_bound = 0., 999999.
     model.add_reactions([r1, r2])
     r2.objective_coefficient = 3.
     assert r2.objective_coefficient == 3.
     assert model.reactions[-2] == r1
     assert model.reactions[-1] == r2
     assert isinstance(model.reactions[-2].reverse_variable,
                       model.problem.Variable)
     coefficients_dict = model.objective.expression. \
         as_coefficients_dict()
     biomass_r = model.reactions.get_by_id('Biomass_Ecoli_core')
     assert coefficients_dict[biomass_r.forward_variable] == 1.
     assert coefficients_dict[biomass_r.reverse_variable] == -1.
     assert coefficients_dict[model.reactions.r2.forward_variable] == 3.
     assert coefficients_dict[model.reactions.r2.reverse_variable] == -3.
Esempio n. 8
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. 9
0
 def test_assess(self, model, solver):
     with model:
         assert assess(model, model.reactions.GLCpts, solver=solver) is True
         pyr = model.metabolites.pyr_c
         a = Metabolite('a')
         b = Metabolite('b')
         model.add_metabolites([a, b])
         pyr_a2b = Reaction('pyr_a2b')
         pyr_a2b.add_metabolites({pyr: -1, a: -1, b: 1})
         model.add_reactions([pyr_a2b])
         res = assess(model, pyr_a2b, 0.01, solver=solver)
         expected = {
             'precursors': {
                 a: {
                     'required': 0.01,
                     'produced': 0.0
                 }
             },
             'products': {
                 b: {
                     'required': 0.01,
                     'capacity': 0.0
                 }
             }
         }
         assert res == expected
Esempio n. 10
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. 11
0
def test_add_reactions_single_existing(model):
    rxn = model.reactions[0]
    r1 = Reaction(rxn.id)
    r1.add_metabolites({Metabolite("A"): -1, Metabolite("B"): 1})
    r1.lower_bound, r1.upper_bound = -999999.0, 999999.0
    model.add_reactions([r1])
    assert rxn in model.reactions
    assert r1 is not model.reactions.get_by_id(rxn.id)
Esempio n. 12
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. 13
0
 def test_canonical_form(self, model):
     # add G constraint to test
     g_constr = Metabolite("SUCCt2_2__test_G_constraint")
     g_constr._constraint_sense = "G"
     g_constr._bound = 5.0
     model.reactions.get_by_id("SUCCt2_2").add_metabolites({g_constr: 1})
     assert abs(model.optimize("maximize").f - 0.855) < 0.001
     # convert to canonical form
     model = canonical_form(model)
     assert abs(model.optimize("maximize").f - 0.855) < 10 ** -3
Esempio n. 14
0
def test__normalize_pseudoreaction_atpm():
    reaction = Reaction('notATPM')
    reaction.add_metabolites({Metabolite('atp_c'): -1,
                              Metabolite('h2o_c'): -1,
                              Metabolite('pi_c'): 1,
                              Metabolite('h_c'): 1,
                              Metabolite('adp_c'): 1})
    _normalize_pseudoreaction(reaction)
    assert reaction.id == 'ATPM'
    assert reaction.subsystem == 'Biomass and maintenance functions'
 def test_canonical_form(self, model):
     # add G constraint to test
     g_constr = Metabolite("SUCCt2_2__test_G_constraint")
     g_constr._constraint_sense = "G"
     g_constr._bound = 5.0
     model.reactions.get_by_id("SUCCt2_2").add_metabolites({g_constr: 1})
     assert abs(model.optimize("maximize").f - 0.855) < 0.001
     # convert to canonical form
     model = canonical_form(model)
     assert abs(model.optimize("maximize").f - 0.855) < 10**-3
Esempio n. 16
0
def test__normalize_pseudoreaction_atpm_has_gpr():
    reaction = Reaction('NPT1')
    reaction.add_metabolites({Metabolite('atp_c'): -1,
                              Metabolite('h2o_c'): -1,
                              Metabolite('pi_c'): 1,
                              Metabolite('h_c'): 1,
                              Metabolite('adp_c'): 1})
    reaction.gene_reaction_rule = 'b1779'
    _normalize_pseudoreaction(reaction)
    # should not change
    assert reaction.id == 'NPT1'
Esempio n. 17
0
 def test_canonical_form(self):
     model = create_test_model("textbook")
     # add G constraint to test
     g_constr = Metabolite("SUCCt2_2__test_G_constraint")
     g_constr._constraint_sense = "G"
     g_constr._bound = 5.0
     model.reactions.get_by_id("SUCCt2_2").add_metabolites({g_constr: 1})
     self.assertAlmostEqual(model.optimize("maximize").f, 0.855, places=3)
     # convert to canonical form
     model = canonical_form(model)
     self.assertAlmostEqual(model.optimize("maximize").f, 0.855, places=3)
Esempio n. 18
0
 def test_set_id(self, solved_model):
     solution, model = solved_model
     met = Metabolite("test")
     with pytest.raises(TypeError):
         setattr(met, 'id', 1)
     model.add_metabolites([met])
     with pytest.raises(ValueError):
         setattr(met, "id", 'g6p_c')
     met.id = "test2"
     assert "test2" in model.metabolites
     assert "test" not in model.metabolites
Esempio n. 19
0
 def test_set_id(self, solved_model):
     solution, model = solved_model
     met = Metabolite("test")
     with pytest.raises(TypeError):
         setattr(met, 'id', 1)
     model.add_metabolites([met])
     with pytest.raises(ValueError):
         setattr(met, "id", 'g6p_c')
     met.id = "test2"
     assert "test2" in model.metabolites
     assert "test" not in model.metabolites
Esempio n. 20
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. 21
0
 def test_canonical_form(self):
     model = create_test_model("textbook")
     # add G constraint to test
     g_constr = Metabolite("SUCCt2_2__test_G_constraint")
     g_constr._constraint_sense = "G"
     g_constr._bound = 5.0
     model.reactions.get_by_id("SUCCt2_2").add_metabolites({g_constr: 1})
     self.assertAlmostEqual(model.optimize("maximize").f, 0.855, places=3)
     # convert to canonical form
     model = canonical_form(model)
     self.assertAlmostEqual(model.optimize("maximize").f, 0.855, places=3)
Esempio n. 22
0
    def test_get_yield(self):
        model = Model("test")
        met1 = Metabolite(id="S7P", formula="C7H15O10P")
        met2 = Metabolite(id="T3P1", formula="C3H7O6P")
        met3 = Metabolite(id="E4P", formula="C4H9O7P")
        met4 = Metabolite(id="F6P", formula="C6H13O9P")
        model.add_metabolites((met1, met2, met3, met4))

        react1 = Reaction(id="r1", name="Transaldolase")
        react1.add_metabolites({met1: -1, met2: -1, met3: 1, met4: 1})

        react2 = Reaction(id="r2")
        react2.add_metabolites({met1: -1})

        react3 = Reaction(id="r3")
        react3.add_metabolites({met2: -1})

        react4 = Reaction(id="r4")
        react4.add_metabolites({met3: -1})

        react5 = Reaction(id="r5")
        react5.add_metabolites({met4: -1})

        model.add_reactions((react1, react2, react3, react4, react5))

        fluxes = {
            react1.id: 1,
            react2.id: -1,
            react3.id: -1,
            react4.id: 1,
            react5.id: 1
        }

        status, yields = get_yields(fluxes, model)
        assert status is True
        assert yields == {
            "C": {
                met3: 0.4,
                met4: 0.6
            },
            "H": {
                met3: 9 / 22,
                met4: 13 / 22
            },
            "O": {
                met3: 7 / 16,
                met4: 9 / 16
            },
            "P": {
                met3: 0.5,
                met4: 0.5
            }
        }
Esempio n. 23
0
def test_add_reactions_duplicate(model):
    rxn = model.reactions[0]
    r1 = Reaction('r1')
    r1.add_metabolites({Metabolite('A'): -1, Metabolite('B'): 1})
    r1.lower_bound, r1.upper_bound = -999999., 999999.
    r2 = Reaction(rxn.id)
    r2.add_metabolites(
        {Metabolite('A'): -1, Metabolite('C'): 1, Metabolite('D'): 1})
    model.add_reactions([r1, r2])
    assert r1 in model.reactions
    assert rxn in model.reactions
    assert r2 is not model.reactions.get_by_id(rxn.id)
Esempio n. 24
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. 25
0
def construct_loopless_model(cobra_model):
    """Construct a loopless model.

    This adds MILP constraints to prevent flux from proceeding in a loop, as
    done in http://dx.doi.org/10.1016/j.bpj.2010.12.3707
    Please see the documentation for an explanation of the algorithm.

    This must be solved with an MILP capable solver.

    """
    # copy the model and make it irreversible
    model = cobra_model.copy()
    convert_to_irreversible(model)
    max_ub = max(model.reactions.list_attr("upper_bound"))
    # a dict for storing S^T
    thermo_stoic = {"thermo_var_" + metabolite.id: {}
                    for metabolite in model.metabolites}
    # Slice operator is so that we don't get newly added metabolites
    original_metabolites = model.metabolites[:]
    for reaction in model.reactions[:]:
        # Boundary reactions are not subjected to these constraints
        if len(reaction._metabolites) == 1:
            continue
        # populate the S^T dict
        bound_id = "thermo_bound_" + reaction.id
        for met, stoic in iteritems(reaction._metabolites):
            thermo_stoic["thermo_var_" + met.id][bound_id] = stoic
        # I * 1000 > v --> I * 1000 - v > 0
        reaction_ind = Reaction(reaction.id + "_indicator")
        reaction_ind.variable_kind = "integer"
        reaction_ind.upper_bound = 1
        reaction_ub = Metabolite(reaction.id + "_ind_ub")
        reaction_ub._constraint_sense = "G"
        reaction.add_metabolites({reaction_ub: -1})
        reaction_ind.add_metabolites({reaction_ub: max_ub})
        # This adds a compensating term for 0 flux reactions, so we get
        # S^T x - (1 - I) * 1001 < -1 which becomes
        # S^T x < 1000 for 0 flux reactions and
        # S^T x < -1 for reactions with nonzero flux.
        reaction_bound = Metabolite(bound_id)
        reaction_bound._constraint_sense = "L"
        reaction_bound._bound = max_ub
        reaction_ind.add_metabolites({reaction_bound: max_ub + 1})
        model.add_reaction(reaction_ind)
    for metabolite in original_metabolites:
        metabolite_var = Reaction("thermo_var_" + metabolite.id)
        metabolite_var.lower_bound = -max_ub
        model.add_reaction(metabolite_var)
        metabolite_var.add_metabolites(
            {model.metabolites.get_by_id(k): v
             for k, v in iteritems(thermo_stoic[metabolite_var.id])})
    return model
Esempio n. 26
0
def test__normalize_pseudoreaction_atpm_reversed():
    reaction = Reaction('notATPM')
    reaction.add_metabolites({Metabolite('atp_c'): 1,
                              Metabolite('h2o_c'): 1,
                              Metabolite('pi_c'): -1,
                              Metabolite('h_c'): -1,
                              Metabolite('adp_c'): -1})
    reaction.lower_bound = -50
    reaction.upper_bound = 100
    _normalize_pseudoreaction(reaction)
    assert reaction.id == 'ATPM'
    assert reaction.lower_bound == -100
    assert reaction.upper_bound == 50
Esempio n. 27
0
    def test_add_metabolite(self, 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. 28
0
def construct_difference_model(model_1, model_2, norm_type='euclidean'):
    """Combine two models into a larger model that is designed to calculate differences
    between the models

    """
    #Get index mappings
    common_dict = {}
    #Using copies of the models so things are modified above
    combined_model = model_1 = model_1.copy()
    model_2 = model_2.copy()
    for reaction_1 in model_1.reactions:
        try:
            reaction_2 = model_2.reactions.get_by_id(reaction_1.id)
            common_dict[reaction_1] = reaction_2
        except:
            continue
            
    #Add a prefix in front of the mutant_model metabolites and reactions to prevent
    #name collisions in DictList
    for the_dict_list in [model_2.metabolites,
                          model_2.reactions]:
        [setattr(x, 'id', 'mutant_%s'%x.id)
         for x in the_dict_list]
        the_dict_list._generate_index() #Update the DictList.dicts

    
    combined_model.add_reactions(model_2.reactions)
    [setattr(x, 'objective_coefficient', 0.)
     for x in combined_model.reactions]
    #Add in the difference reactions.  The mutant reactions and metabolites are already added.
    #This must be a list to maintain the correct order when adding the difference_metabolites
    difference_reactions = [] #Add the difference reactions at the end to speed things up
    difference_metabolites = []
    for reaction_1, reaction_2 in iteritems(common_dict):
        reaction_1._difference_partner = reaction_2
        reaction_2._difference_partner = reaction_1
        difference_reaction = Reaction('difference_%s'%reaction_1.id)
        difference_reactions.append(difference_reaction)
        difference_reaction.upper_bound = 100000
        difference_reaction.lower_bound = -1* difference_reaction.upper_bound
        difference_metabolite = Metabolite('difference_%s'%reaction_1.id)
        difference_metabolites.append(difference_metabolite)
        if norm_type == 'linear':
            difference_metabolite._constraint_sense = 'G'
        reaction_1.add_metabolites({difference_metabolite: -1.}, add_to_container_model=False)
        reaction_2.add_metabolites({difference_metabolite: 1.}, add_to_container_model=False)
        difference_reaction.add_metabolites({difference_metabolite: 1.}, add_to_container_model=False)

    combined_model.add_metabolites(difference_metabolites)
    combined_model.add_reactions(difference_reactions)
    return(combined_model)
Esempio n. 29
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. 30
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. 31
0
def test_add_reactions_duplicate(model):
    rxn = model.reactions[0]
    r1 = Reaction("r1")
    r1.add_metabolites({Metabolite("A"): -1, Metabolite("B"): 1})
    r1.lower_bound, r1.upper_bound = -999999.0, 999999.0
    r2 = Reaction(rxn.id)
    r2.add_metabolites({
        Metabolite("A"): -1,
        Metabolite("C"): 1,
        Metabolite("D"): 1
    })
    model.add_reactions([r1, r2])
    assert r1 in model.reactions
    assert rxn in model.reactions
    assert r2 is not model.reactions.get_by_id(rxn.id)
Esempio n. 32
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. 33
0
def test_model_remove_reaction(model):
    old_reaction_count = len(model.reactions)

    with model:
        model.remove_reactions(["PGI"])
        assert len(model.reactions) == old_reaction_count - 1
        with pytest.raises(KeyError):
            model.reactions.get_by_id("PGI")
        model.remove_reactions(model.reactions[:1])
        assert len(model.reactions) == old_reaction_count - 2

    assert len(model.reactions) == old_reaction_count
    assert "PGI" in model.reactions

    tmp_metabolite = Metabolite("testing")
    model.reactions[0].add_metabolites({tmp_metabolite: 1})
    assert tmp_metabolite in model.metabolites
    model.remove_reactions(model.reactions[:1], remove_orphans=True)
    assert tmp_metabolite not in model.metabolites

    with model:
        model.reactions[0].add_metabolites({tmp_metabolite: 1})
        assert tmp_metabolite in model.metabolites
    assert tmp_metabolite not in model.metabolites

    biomass_before = model.slim_optimize()
    with model:
        model.remove_reactions([model.reactions.Biomass_Ecoli_core])
        assert np.isclose(model.slim_optimize(), 0)

    assert np.isclose(model.slim_optimize(), biomass_before)
Esempio n. 34
0
    def test_reaction_delete(self, model):
        old_reaction_count = len(model.reactions)
        tmp_metabolite = Metabolite("testing")
        # Delete without removing orphan
        model.reactions[0].add_metabolites({tmp_metabolite: 1})
        assert len(tmp_metabolite.reactions) == 1
        model.reactions[0].delete(remove_orphans=False)
        # make sure it's still in the model
        assert tmp_metabolite in model.metabolites
        assert len(tmp_metabolite.reactions) == 0
        assert len(model.reactions) == old_reaction_count - 1

        # Now try it with removing orphans
        model.reactions[0].add_metabolites({tmp_metabolite: 1})
        assert len(tmp_metabolite.reactions) == 1
        model.reactions[0].delete(remove_orphans=True)
        assert tmp_metabolite not in model.metabolites
        assert len(tmp_metabolite.reactions) == 0
        assert len(model.reactions) == old_reaction_count - 2

        # It shouldn't remove orphans if it's in 2 reactions however
        model.reactions[0].add_metabolites({tmp_metabolite: 1})
        model.reactions[1].add_metabolites({tmp_metabolite: 1})
        assert len(tmp_metabolite.reactions) == 2
        model.reactions[0].delete(remove_orphans=False)
        assert tmp_metabolite in model.metabolites
        assert len(tmp_metabolite.reactions) == 1
        assert len(model.reactions) == old_reaction_count - 3
Esempio n. 35
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)
def convert_to_irreversible_with_indicators(cobra_model,reaction_id_list,metabolite_list, mutually_exclusive_directionality_constraint = False,label_model=None):
    #Function modified from the work by : """Schmidt BJ1, Ebrahim A, Metz TO, Adkins JN, Palsson B, Hyduke DR. GIM3E: condition-specific models of cellular metabolism developed from metabolomics and expression data Bioinformatics. 2013 Nov 15;29(22):2900-8. doi: 10.1093/bioinformatics/btt493. Epub 2013 Aug 23."""
    """Will break all of the reversible reactions into two separate irreversible
     reactions with different directions.  This function call modified from
     a version in the core cobra to facilitate the MILP formulation and
     include gene_reaction_rules with the reverse reaction
   
     Arguments:
      cobra_model: A model object which will be modified in place.
      mutually_exclusive_directionality_constraint: Boolean.  If True, turnover 
       reactions are constructed to serve as MILP constraints to prevent loops.
      
     Returns:
      None, cobra_model is modified in place
    
    
    
    
     """
    reactions_to_add = []
    from cobra.core.Reaction import Reaction
    from cobra.core import Metabolite
    reactions_to_make_irreversible=[]
    for x in reaction_id_list:
        reactions_to_make_irreversible.append(cobra_model.reactions.get_by_id(x))
    """for x in lexs:
        reactions_to_make_irreversible.append(cobra_model.reactions.get_by_id(x))"""
    
    #If a label model object  is provided make sure all experimentally measured metabolites (or at least one of the metabolites in the pool) is produced
    full_metabolite_list=copy.copy(metabolite_list)
    print full_metabolite_list
    if label_model!=None:
       emus=[]
       for condition in label_model.experimental_dict:
           for emu in label_model.experimental_dict[condition]:
               if emu not in emus:
                  emus.append(emu)
       measured_metabolite_dict={}
       
       for emu in emus:
           iso_id=str(label_model.emu_dict[emu]["met_id"])
           #print label_model.id_isotopomer_object_dict
           #isotopomer_object=label_model.id_isotopomer_object_dict[iso_id]
           metabolites=label_model.isotopomer_id_metabolite_id_dict[iso_id]
           print [iso_id,label_model.isotopomer_id_metabolite_id_dict[iso_id]]
           if isinstance(metabolites,list):
              for metabolite in metabolites:
                  full_metabolite_list.append(metabolite)
           else:
              full_metabolite_list.append(metabolites)
    
    for metabolites in full_metabolite_list:
       print metabolites
       if not isinstance(metabolites,list):
          metabolites=[metabolites]
       for metabolite in metabolites:
          print metabolite
          the_metabolite=cobra_model.metabolites.get_by_id(metabolite)
          for x in the_metabolite.reactions:
             if x not in reactions_to_make_irreversible:
              reactions_to_make_irreversible.append(x)    
                  
    for reaction in reactions_to_make_irreversible:
        # Potential artifact because a reaction might run backwards naturally
        # and this would result in adding an empty reaction to the
        # model in addition to the reverse reaction.
        if reaction.lower_bound < 0:
            #reverse_reaction = Reaction(reaction.id + "_reverse")
            reverse_reaction = reaction.copy()
            reverse_reaction.id = reaction.id + "_reverse"
            reverse_reaction.lower_bound = max(0,-1*reaction.upper_bound)
            reverse_reaction.upper_bound = reaction.lower_bound * -1.
            reaction.lower_bound = 0
            if reaction.upper_bound<0:
               reaction.upper_bound=0
            # Make the directions aware of each other
            reaction.notes["reflection"] = reverse_reaction.id
            reverse_reaction.notes["reflection"] = reaction.id
            reaction_dict = {}
            current_metabolites = [x for x in reaction.metabolites]
            for the_metabolite in current_metabolites:
                reaction_dict[the_metabolite] = -2 * reaction.get_coefficient(the_metabolite.id)
            reverse_reaction.add_metabolites(reaction_dict)
            reactions_to_add.append(reverse_reaction)
            # Also: GPRs should already copy
            # reverse_reaction.gene_reaction_rule = reaction.gene_reaction_rule
            # reverse_reaction._genes = reaction._genes
            
            if mutually_exclusive_directionality_constraint:
                # A continuous reaction bounded by 0., 1.
                # Serves as a source for the indicator metabolites
                tmp_source = Reaction('IRRMILP_direction_constraint_source_for_%s_and_%s'
                                                           %(reaction.id,
                                                             reverse_reaction.id))
                tmp_source.upper_bound = 1.
                tmp_source.lower_bound = 0.
                # The reverse indicator reaction is
                # an integer-valued reaction bounded by 0,1
                # that activates flux to the reverse reaction
                # and deactivates the forward reaction only when it is
                # turned on to 1
                tmp_indicator = Reaction('IRRMILP_reverse_indicator_for_%s_and_%s'
                                                           %(reaction.id,
                                                             reverse_reaction.id))
                tmp_indicator.upper_bound = 1
                tmp_indicator.lower_bound = 0
                tmp_indicator.variable_kind = 'integer'                    
                flux_constraint_forward = Metabolite(id = 
                     'IRRMILP_direction_constraint_for_%s'%reaction.id)
                flux_constraint_reverse = Metabolite(id = 
                     'IRRMILP_direction_constraint_for_%s'%reverse_reaction.id)
                flux_constraint_reverse._constraint_sense = 'G'
                flux_constraint_reverse._bound = 0.
                
                tmp_source.add_metabolites({flux_constraint_forward: 1})
                
                tmp_indicator.add_metabolites({flux_constraint_forward: -1,
                                      flux_constraint_reverse: 1})
                if reaction.upper_bound != 0:
                        reaction.add_metabolites({flux_constraint_forward: -1./reaction.upper_bound})
                else:
                    # could put 1.01 X the tolerance here,
                    # This is arbitrary.  Use 0.001
                    # since 1000 is a typical upper bound
                    reaction.add_metabolites({flux_constraint_forward: -0.001})
                if reverse_reaction.upper_bound != 0:
                    reverse_reaction.add_metabolites({flux_constraint_reverse: -1./reverse_reaction.upper_bound})
                else:
                    reverse_reaction.add_metabolites({flux_constraint_reverse: -0.001})
                reactions_to_add.append(tmp_indicator)
                reactions_to_add.append(tmp_source)
    cobra_model.add_reactions(reactions_to_add)
Esempio n. 37
0
def test_metabolite_formula():
    met = Metabolite("water")
    met.formula = "H2O"
    assert met.elements == {"H": 2, "O": 1}
    assert met.formula_weight == 18.01528
Esempio n. 38
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. 39
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. 40
0
def moma(wt_model, mutant_model, objective_sense='maximize', solver=None,
         tolerance_optimality=1e-8, tolerance_feasibility=1e-8,
         minimize_norm=True, norm_flux_dict=None, the_problem='return', lp_method=0,
         combined_model=None, norm_type='euclidean'):
    """Runs the minimization of metabolic adjustment method described in
    Segre et al 2002 PNAS 99(23): 15112-7.

    wt_model: A cobra.Model object
    mutant_model: A cobra.Model object with different reaction bounds vs wt_model.
    objective_sense: 'maximize' or 'minimize'
    solver: 'gurobi', 'cplex', or 'glpk'.  Note: glpk cannot be used with norm_type 'euclidean'
    tolerance_optimality: Solver tolerance for optimality.
    tolerance_feasibility: Solver tolerance for feasibility.
    the_problem: None or a problem object for the specific solver that can be
    used to hot start the next solution.
    lp_method: The method to use for solving the problem.  Depends on the solver.  See
    the cobra.flux_analysis.solvers.py file for more info.
        For norm_type == 'euclidean':
            the primal simplex works best for the test model (gurobi: lp_method=0, cplex: lp_method=1)
    combined_model: an output from moma that represents the combined optimization to be solved.

    """
    if solver is None:
        if norm_type == "euclidean":
            solver = get_solver_name(qp=True)
        else:
            solver = get_solver_name()  # linear is not even implemented yet
    if combined_model is not None or the_problem not in ['return']:
        warn("moma currently does not support reusing models or problems. " +\
             "continuing without them")
        combined_model = None
        the_problem = 'return'
    if solver.lower() == 'cplex' and lp_method == 0:
        #print 'for moma, solver method 0 is very slow for cplex. changing to method 1'
        lp_method = 1
    if solver.lower() == 'glpk' and norm_type == 'euclidean':
        try:
            # from gurobipy import Model
            solver = 'gurobi'
            warn("GLPK can't solve quadratic problems like MOMA.  Switched solver to %s"%solver)
        except:
            warn("GLPK can't solve quadratic problems like MOMA.  Switching to linear MOMA")

    if norm_type == 'euclidean':
        #Reusing the basis can get the solver stuck.
        reuse_basis = False
    if combined_model and combined_model.norm_type != norm_type:
        print('Cannot use combined_model.norm_type = %s with user-specified norm type'%(combined_model.norm_type,
                                                                                        norm_type))
        print('Defaulting to user-specified norm_type')
        combined_model = None


    if norm_type == 'linear':
        raise Exception('linear MOMA is not currently implmented')
        quadratic_component = None

    if minimize_norm:
        if norm_flux_dict is None:
            optimize_minimum_flux(wt_model, objective_sense='maximize',
                                  tolerance_feasibility=tolerance_feasibility)
            norm_flux_dict = wt_model.solution.x_dict

        else:
            # update the solution of wt model according to norm_flux_dict
            wt_model.optimize() # this is just to make sure wt_model.solution and mutant_model.solution refer to different object.
            objective_reaction_coefficient_dict = dict([(x.id, x.objective_coefficient)
                                                        for x in wt_model.reactions
                                                        if x.objective_coefficient])
            try:
                wt_model.solution.f = sum([norm_flux_dict[k] * v for k, v in
                                           objective_reaction_coefficient_dict.items()])
                wt_model.solution.x_dict = norm_flux_dict
            except:
                print('incorrect norm_flux_dict')
                raise

        # formulate qMOMA using wt_flux as reference
        # make a copy not to change the objective coefficients of original mutant model
        mutant_model_moma = mutant_model.copy()
        nRxns = len(mutant_model_moma.reactions)
        quadratic_component = 2 * eye(nRxns, nRxns)
        # linear component
        [setattr(x, 'objective_coefficient', -2 * norm_flux_dict[x.id]) for x in mutant_model_moma.reactions]

        the_problem = mutant_model_moma.optimize(objective_sense='minimize',
                                         quadratic_component=quadratic_component,
                                         solver=solver,
                                         tolerance_optimality=tolerance_optimality,
                                         tolerance_feasibility=tolerance_feasibility,
                                         lp_method=lp_method)
                                         #, reuse_basis=reuse_basis) # this should be commented out when solver is 'cplex'

        if mutant_model_moma.solution.status != 'optimal':
            warn('optimal moma solution not found: solver status %s'%mutant_model_moma.solution.status +\
                 ' returning the problem, the_combined model, and the quadratic component for trouble shooting')
            return(the_problem, mutant_model_moma, quadratic_component)

        solution = mutant_model_moma.solution
        mutant_dict = {}
        mutant_f = sum([mutant_model.reactions.get_by_id(x.id).objective_coefficient * x.x for x in mutant_model_moma.reactions])
        mutant_dict['objective_value'] = mutant_f
        mutant_dict['status'] = solution.status
        #TODO: Deal with maximize / minimize issues for a reversible model that's been converted to irreversible
        mutant_dict['flux_difference'] = flux_difference = sum([(norm_flux_dict[r.id] - mutant_model_moma.solution.x_dict[r.id])**2
                                                                for r in mutant_model_moma.reactions])
        mutant_dict['the_problem'] = the_problem
        mutant_dict['mutant_model'] = mutant_model_moma

        # update the solution of original mutant model
        mutant_model.solution.x_dict = the_problem.x_dict
        mutant_model.solution.status = solution.status
        mutant_model.solution.f = mutant_f

        # del wt_model, mutant_model, quadratic_component, solution
        return(mutant_dict)


    else:
        #Construct a problem that attempts to maximize the objective in the WT model while
        #solving the quadratic problem.  This new problem is constructed to try to find
        #a solution for the WT model that lies close to the mutant model.  There are
        #often multiple equivalent solutions with M matrices and the one returned
        #by a simple cobra_model.optimize call may be too far from the mutant.
        #This only needs to be adjusted if we update mutant_model._S after deleting reactions
        number_of_reactions_in_common = len(set([x.id for x in wt_model.reactions]).intersection([x.id for x in mutant_model.reactions]))
        number_of_reactions = len(wt_model.reactions) + len(mutant_model.reactions)
        #Get the optimal wt objective value and adjust based on optimality tolerances

        wt_model.optimize(solver=solver)
        wt_optimal = deepcopy(wt_model.solution.f)
        if objective_sense == 'maximize':
            wt_optimal = floor(wt_optimal/tolerance_optimality)*tolerance_optimality
        else:
            wt_optimal = ceil(wt_optimal/tolerance_optimality)*tolerance_optimality

        if not combined_model:
            #Collect the set of wt reactions contributing to the objective.
            objective_reaction_coefficient_dict = dict([(x.id, x.objective_coefficient)
                                                        for x in wt_model.reactions
                                                        if x.objective_coefficient])
            
            
            combined_model = construct_difference_model(wt_model, mutant_model, norm_type)
            #Add in the virtual objective metabolite to constrain the wt_model to the space where
            #the objective was maximal
            objective_metabolite = Metabolite('wt_optimal')
            objective_metabolite._bound = wt_optimal
            if objective_sense == 'maximize':
                objective_metabolite._constraint_sense = 'G'
            else:
                objective_metabolite._constraint_sense = 'L'

            #TODO: this couples the wt_model objective reaction to the virtual metabolite
            #Currently, assumes a single objective reaction; however, this may be extended
            [combined_model.reactions.get_by_id(k).add_metabolites({objective_metabolite: v})
             for k, v in objective_reaction_coefficient_dict.items()]
                

        if norm_type == 'euclidean':
            #Makes assumptions about the structure of combined model
            quadratic_component = s_vstack((lil_matrix((number_of_reactions, number_of_reactions + number_of_reactions_in_common )),
                                            s_hstack((lil_matrix((number_of_reactions_in_common, number_of_reactions)),
                                                      eye(number_of_reactions_in_common,number_of_reactions_in_common)))))
    
        elif norm_type == 'linear':
            quadratic_component = None

    combined_model.norm_type = norm_type
    cobra_model = combined_model

    the_problem = combined_model.optimize(objective_sense='minimize',
                                         quadratic_component=quadratic_component,
                                         solver=solver,
                                         tolerance_optimality=tolerance_optimality,
                                         tolerance_feasibility=tolerance_feasibility,
                                         lp_method=lp_method) #, reuse_basis=reuse_basis) # this should be commented out when solver is 'cplex'

    if combined_model.solution.status != 'optimal':
        warn('optimal moma solution not found: solver status %s'%combined_model.solution.status +\
             ' returning the problem, the_combined model, and the quadratic component for trouble shooting')
        return(the_problem, combined_model, quadratic_component)
             
    solution = combined_model.solution
    mutant_dict = {}
    #Might be faster to quey based on mutant_model.reactions with the 'mutant_' prefix added
    _reaction_list = [x for x in combined_model.reactions if x.id.startswith('mutant_')]
    mutant_f = sum([mutant_model.reactions.get_by_id(x.id[len('mutant_'):]).objective_coefficient *
                    x.x for x in _reaction_list])
    mutant_dict['objective_value'] = mutant_f
    wild_type_flux_total = sum([abs(solution.x_dict[x.id]) for x in wt_model.reactions])
    mutant_flux_total = sum(abs(x.x) for x in _reaction_list)
    #Need to use the new solution as there are multiple ways to achieve an optimal solution in
    #simulations with M matrices.
    mutant_dict['status'] = solution.status
    #TODO: Deal with maximize / minimize issues for a reversible model that's been converted to irreversible
    mutant_dict['flux_difference'] = flux_difference = sum([(solution.x_dict[x.id[len('mutant_'):]]
                                                             - x.x)**2 for x in _reaction_list])
    mutant_dict['the_problem'] = the_problem
    mutant_dict['combined_model'] = combined_model
    
    del wt_model, mutant_model, quadratic_component, solution
    return(mutant_dict)
Esempio n. 41
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. 42
0
def optimize_minimum_flux(model, objective_sense='maximize',
                 tolerance_optimality=1e-8, tolerance_feasibility=1e-8):
    # return the flux distribution in which the total amount of fluxes is minimum while the growth is maximum
    #Get the optimal wt objective value and adjust based on optimality tolerances
    model.optimize()
    optimal_value = deepcopy(model.solution.f)
    # print('opt val: %s' % optimal_value)
    if objective_sense == 'maximize':
        optimal_value = floor(optimal_value/tolerance_optimality)*tolerance_optimality
    else:
        optimal_value = ceil(optimal_value/tolerance_optimality)*tolerance_optimality
    # print('adjusted opt val: %s' % optimal_value)
    #Add in the virtual objective metabolite to constrain the wt_model to the space where
    #the objective was maximal
    objective_metabolite = Metabolite('objective metabolite')
    objective_metabolite._bound = optimal_value
    if objective_sense == 'maximize':
        objective_metabolite._constraint_sense = 'G'
    else:
        objective_metabolite._constraint_sense = 'L'
    # print('objm const sense: %s, objm bound: %s' % (objective_metabolite._constraint_sense, objective_metabolite._bound))

    # construct irreversible model to assure all flux values are positive
    irreve_model = model.copy()
    # this is necessary to avoid invalid bound error when model is changed to irreversible
    for r in irreve_model.reactions:
        if r.upper_bound < 0:
            reverse_reaction = Reaction(r.id + "_reverse")
            reverse_reaction.lower_bound = r.upper_bound * -1
            reverse_reaction.upper_bound = r.lower_bound * -1
            reverse_reaction.objective_coefficient = r.objective_coefficient * -1
            reaction_dict = dict([(k, v*-1)
                                  for k, v in r.metabolites.items()])
            reverse_reaction.add_metabolites(reaction_dict)
            irreve_model.add_reaction(reverse_reaction)
            r.upper_bound, r.lower_bound = 0, 0

    cobra.manipulation.modify.convert_to_irreversible(irreve_model)
    objective_reaction_coefficient_dict = dict([(x.id, x.objective_coefficient)
                                                    for x in model.reactions
                                                    if x.objective_coefficient])
    # this couples the objective reaction to the virtual metabolite
    [irreve_model.reactions.get_by_id(k).add_metabolites({objective_metabolite: v})
     for k, v in objective_reaction_coefficient_dict.items()]
    # print('irregular metabolites: %s' % [(m.id, m._constraint_sense, m._bound)
    #                                      for m in irreve_model.metabolites if m._constraint_sense != 'E' or m._bound != 0])

    # minimize the sum of fluxes
    for r in irreve_model.reactions:
        r.objective_coefficient = 1
    # print([r.id for r in irreve_model.reactions if r.objective_coefficient != 1])
    # print(tolerance_feasibility)
    irreve_model.optimize(objective_sense='minimize',
                          tolerance_feasibility=tolerance_feasibility)

    # adjust this to the solution of wt_model
    original_flux = model.solution.x_dict
    irreve_flux = irreve_model.solution.x_dict
    for k in original_flux.keys():
        original_flux[k] = irreve_flux[k]
        # if reverse reaction exists and its flux is not zero, assign as a negative flux in wt_flux
        if k + '_reverse' in irreve_flux.keys() and irreve_flux[k + '_reverse'] != 0:
            if irreve_flux[k] != 0:
                print('Attention: non-optimal solution')
            original_flux[k] = -irreve_flux[k + '_reverse']

    model.solution.status = irreve_model.solution.status
    model.solution.f = sum([irreve_model.reactions.get_by_id(k).x * v for k, v in
                            objective_reaction_coefficient_dict.items()])
    return model.solution