Source code for test_core_reaction

# -*- coding: utf-8 -*-

"""Test functions of reaction.py"""

from __future__ import absolute_import

import warnings

import numpy as np
import pytest
import six

from cobra.core import Configuration, Metabolite, Model, Reaction


[docs]config = Configuration()
[docs]stable_optlang = ["glpk", "cplex", "gurobi"]
[docs]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
[docs]def test_gpr_modification(model): reaction = model.reactions.get_by_id("PGI") old_gene = list(reaction.genes)[0] new_gene = model.genes.get_by_id("s0001") # Add an existing 'gene' to the GPR reaction.gene_reaction_rule = "s0001" assert new_gene in reaction.genes assert reaction in new_gene.reactions # Remove old gene correctly assert old_gene not in reaction.genes assert reaction not in old_gene.reactions # Add a new 'gene' to the GPR reaction.gene_reaction_rule = "fake_gene" assert model.genes.has_id("fake_gene") fake_gene = model.genes.get_by_id("fake_gene") assert fake_gene in reaction.genes assert reaction in fake_gene.reactions fake_gene.name = "foo_gene" assert reaction.gene_name_reaction_rule == fake_gene.name
[docs]def test_gene_knock_out(model): rxn = Reaction("rxn") rxn.add_metabolites({Metabolite("A"): -1, Metabolite("B"): 1}) rxn.gene_reaction_rule = "A2B1 or A2B2 and A2B3" assert hasattr(list(rxn.genes)[0], "knock_out") model.add_reaction(rxn) with model: model.genes.A2B1.knock_out() assert not model.genes.A2B1.functional model.genes.A2B3.knock_out() assert not rxn.functional assert model.genes.A2B3.functional assert rxn.functional model.genes.A2B1.knock_out() assert not model.genes.A2B1.functional assert model.reactions.rxn.functional model.genes.A2B3.knock_out() assert not model.reactions.rxn.functional
[docs]def test_str(): rxn = Reaction("rxn") rxn.add_metabolites({Metabolite("A"): -1, Metabolite("B"): 1}) assert str(rxn) == "rxn: A --> B"
[docs]def test_str_from_model(model): assert model.reactions[0].__str__().startswith("ACALD")
[docs]def test_add_metabolite_from_solved_model(solved_model): solution, model = solved_model pgi_reaction = model.reactions.PGI test_met = model.metabolites[0] pgi_reaction.add_metabolites({test_met: 42}, combine=False) assert pgi_reaction.metabolites[test_met] == 42.0 assert ( model.constraints[test_met.id].expression.as_coefficients_dict()[ pgi_reaction.forward_variable ] == 42.0 ) assert ( model.constraints[test_met.id].expression.as_coefficients_dict()[ pgi_reaction.reverse_variable ] == -42.0 ) pgi_reaction.add_metabolites({test_met: -10}, combine=True) assert pgi_reaction.metabolites[test_met] == 32.0 assert ( model.constraints[test_met.id].expression.as_coefficients_dict()[ pgi_reaction.forward_variable ] == 32.0 ) assert ( model.constraints[test_met.id].expression.as_coefficients_dict()[ pgi_reaction.reverse_variable ] == -32.0 ) pgi_reaction.add_metabolites({test_met: 0}, combine=False) with pytest.raises(KeyError): pgi_reaction.metabolites[test_met] assert ( model.constraints[test_met.id].expression.as_coefficients_dict()[ pgi_reaction.forward_variable ] == 0 ) assert ( model.constraints[test_met.id].expression.as_coefficients_dict()[ pgi_reaction.reverse_variable ] == 0
) @pytest.mark.parametrize("solver", stable_optlang)
[docs]def test_add_metabolite_benchmark(model, benchmark, solver): reaction = model.reactions.get_by_id("PGI") many_metabolites = dict((m, 1) for m in model.metabolites[0:50]) def add_remove_metabolite(): reaction.add_metabolites(many_metabolites) if not getattr(model, "solver", None): solver_dict[solver].create_problem(model) for m, c in many_metabolites.items(): try: reaction.subtract_metabolites({m: reaction.get_coefficient(m)}) except KeyError: pass benchmark(add_remove_metabolite)
[docs]def test_add_metabolite(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
@pytest.mark.parametrize("solver", stable_optlang)
[docs]def test_subtract_metabolite_benchmark(model, benchmark, solver): benchmark(test_subtract_metabolite, model, solver)
@pytest.mark.parametrize("solver", stable_optlang)
[docs]def test_subtract_metabolite(model, solver): reaction = model.reactions.get_by_id("PGI") reaction.subtract_metabolites(reaction.metabolites) if not getattr(model, "solver", None): solver_dict[solver].create_problem(model) assert len(reaction.metabolites) == 0
[docs]def test_mass_balance(model): reaction = model.reactions.get_by_id("PGI") # Should be balanced now assert len(reaction.check_mass_balance()) == 0 # Should not be balanced after adding a hydrogen reaction.add_metabolites({model.metabolites.get_by_id("h_c"): 1}) imbalance = reaction.check_mass_balance() assert "H" in imbalance assert imbalance["H"] == 1
[docs]def test_build_from_string(model): m = len(model.metabolites) pgi = model.reactions.get_by_id("PGI") old_bounds = pgi.bounds with model: pgi.reaction = "g6p_c --> f6p_c" assert pgi.lower_bound == 0 assert pgi.bounds == old_bounds pgi.bounds = (0, 1000) assert pgi.bounds == (0, 1000) assert not pgi.reversibility pgi.reaction = "g6p_c <== f6p_c" assert pgi.upper_bound == 0 assert pgi.reaction.strip() == "g6p_c <-- f6p_c" pgi.reaction = "g6p_c --> f6p_c + h2o_c" assert model.metabolites.h2o_c, pgi._metabolites with model: pgi.build_reaction_from_string("g6p_c --> f6p_c + foo", verbose=False) assert model.metabolites.h2o_c not in pgi._metabolites assert "foo" in model.metabolites assert model.metabolites.foo in pgi._metabolites assert len(model.metabolites) == m + 1 assert model.metabolites.h2o_c in pgi._metabolites assert "foo" not in model.metabolites with pytest.raises(AttributeError): assert model.metabolites.foo assert len(model.metabolites) == m with model: old_bounds = config.bounds assert old_bounds == (-1000, 1000) config.bounds = (-5, 5) pgi.build_reaction_from_string("g6p_c <--> f6p_c + new", verbose=False) assert pgi.bounds == (-5, 5) config.bounds = old_bounds pgi.build_reaction_from_string("g6p_c --> f6p_c + new", verbose=False) assert pgi.bounds == (0, 1000)
[docs]def test_bounds_setter(model): rxn = model.reactions.get_by_id("PGI") with pytest.raises(ValueError): rxn.bounds = (1, 0)
[docs]def test_copy(model): PGI = model.reactions.PGI copied = PGI.copy() assert PGI is not copied assert PGI._model is model assert copied._model is not model # The copy should refer to different metabolites and genes for met in copied.metabolites: assert met is not model.metabolites.get_by_id(met.id) assert met.model is not model for gene in copied.genes: assert gene is not model.genes.get_by_id(gene.id) assert gene.model is not model assert len(model.get_associated_groups(copied.id)) == 0
[docs]def test_iadd(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 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
[docs]def test_add(model): # Not in place addition should work on a copy new = model.reactions.PGI + model.reactions.EX_h2o_e assert new._model is not model assert len(new.metabolites) == 3 # The copy should refer to different metabolites and genes # This currently fails because add_metabolites does not copy. # Should that be changed? # for met in new.metabolites: # assert met is not model.metabolites.get_by_id(met.id) # assert met.model is not model for gene in new.genes: assert gene is not model.genes.get_by_id(gene.id) assert gene.model is not model
[docs]def test_radd(model): new = sum([model.reactions.PGI, model.reactions.EX_h2o_e]) assert new._model is not model assert len(new.metabolites) == 3
[docs]def test_mul(model): new = model.reactions.PGI * 2 assert set(new.metabolites.values()) == {-2, 2}
[docs]def test_sub(model): new = model.reactions.PGI - model.reactions.EX_h2o_e assert new._model is not model assert len(new.metabolites) == 3
[docs]def test_removal_from_model_retains_bounds(model): model_cp = model.copy() reaction = model_cp.reactions.ACALD assert reaction.model == model_cp assert reaction.lower_bound == -1000.0 assert reaction.upper_bound == 1000.0 assert reaction._lower_bound == -1000.0 assert reaction._upper_bound == 1000.0 model_cp.remove_reactions([reaction]) assert reaction.model is None assert reaction.lower_bound == -1000.0 assert reaction.upper_bound == 1000.0 assert reaction._lower_bound == -1000.0 assert reaction._upper_bound == 1000.0
[docs]def test_set_bounds_scenario_1(model): acald_reaction = model.reactions.ACALD assert acald_reaction.lower_bound == -1000.0 assert acald_reaction.upper_bound == 1000.0 assert acald_reaction.forward_variable.lb == 0.0 assert acald_reaction.forward_variable.ub == 1000.0 assert acald_reaction.reverse_variable.lb == 0 assert acald_reaction.reverse_variable.ub == 1000.0 acald_reaction.upper_bound = acald_reaction.lower_bound - 100 assert acald_reaction.lower_bound == -1100.0 assert acald_reaction.upper_bound == -1100.0 assert acald_reaction.forward_variable.lb == 0 assert acald_reaction.forward_variable.ub == 0 assert acald_reaction.reverse_variable.lb == 1100.0 assert acald_reaction.reverse_variable.ub == 1100.0 acald_reaction.upper_bound = 100 assert acald_reaction.lower_bound == -1100.0 assert acald_reaction.upper_bound == 100 assert acald_reaction.forward_variable.lb == 0 assert acald_reaction.forward_variable.ub == 100 assert acald_reaction.reverse_variable.lb == 0 assert acald_reaction.reverse_variable.ub == 1100.0
[docs]def test_set_bounds_scenario_3(model): reac = model.reactions.ACALD reac.upper_bound = -10 reac.lower_bound = -10 assert reac.lower_bound == -10 assert reac.upper_bound == -10 reac.lower_bound = -9 assert reac.lower_bound == -9 assert reac.upper_bound == -9 reac.lower_bound = 2 assert reac.lower_bound == 2 assert reac.upper_bound == 2 reac.upper_bound = -10 assert reac.lower_bound == -10 assert reac.upper_bound == -10 reac.upper_bound = -11 assert reac.lower_bound == -11 assert reac.upper_bound == -11 reac.upper_bound = 2 assert reac.lower_bound == -11 assert reac.upper_bound == 2
[docs]def test_set_bounds_scenario_4(model): reac = model.reactions.ACALD reac.lower_bound = reac.upper_bound = 0 reac.lower_bound = 2 assert reac.lower_bound == 2 assert reac.upper_bound == 2 assert reac.forward_variable.lb == 2 assert reac.forward_variable.ub == 2 reac.knock_out() reac.upper_bound = -2 assert reac.lower_bound == -2 assert reac.upper_bound == -2 assert reac.reverse_variable.lb == 2 assert reac.reverse_variable.ub == 2
[docs]def test_set_upper_before_lower_bound_to_0(model): model.reactions.GAPD.upper_bound = 0 model.reactions.GAPD.lower_bound = 0 assert model.reactions.GAPD.lower_bound == 0 assert model.reactions.GAPD.upper_bound == 0 assert model.reactions.GAPD.forward_variable.lb == 0 assert model.reactions.GAPD.forward_variable.ub == 0 assert model.reactions.GAPD.reverse_variable.lb == 0 assert model.reactions.GAPD.reverse_variable.ub == 0
[docs]def test_set_bounds_scenario_2(model): acald_reaction = model.reactions.ACALD assert acald_reaction.lower_bound == -1000.0 assert acald_reaction.upper_bound == 1000.0 assert acald_reaction.forward_variable.lb == 0.0 assert acald_reaction.forward_variable.ub == 1000.0 assert acald_reaction.reverse_variable.lb == 0 assert acald_reaction.reverse_variable.ub == 1000.0 acald_reaction.lower_bound = acald_reaction.upper_bound + 100 assert acald_reaction.lower_bound == 1100.0 assert acald_reaction.upper_bound == 1100.0 assert acald_reaction.forward_variable.lb == 1100.0 assert acald_reaction.forward_variable.ub == 1100.0 assert acald_reaction.reverse_variable.lb == 0 assert acald_reaction.reverse_variable.ub == 0 acald_reaction.lower_bound = -100 assert acald_reaction.lower_bound == -100.0 assert acald_reaction.upper_bound == 1100.0 assert acald_reaction.forward_variable.lb == 0 assert acald_reaction.forward_variable.ub == 1100.0 assert acald_reaction.reverse_variable.lb == 0 assert acald_reaction.reverse_variable.ub == 100
[docs]def test_change_bounds(model): reac = model.reactions.ACALD reac.bounds = (2, 2) assert reac.lower_bound == 2 assert reac.upper_bound == 2 with model: reac.bounds = (5, 5) assert reac.lower_bound == 5 assert reac.upper_bound == 5 assert reac.lower_bound == 2 assert reac.upper_bound == 2
[docs]def test_make_irreversible(model): acald_reaction = model.reactions.ACALD assert acald_reaction.lower_bound == -1000.0 assert acald_reaction.upper_bound == 1000.0 assert acald_reaction.forward_variable.lb == 0.0 assert acald_reaction.forward_variable.ub == 1000.0 assert acald_reaction.reverse_variable.lb == 0 assert acald_reaction.reverse_variable.ub == 1000.0 acald_reaction.lower_bound = 0 assert acald_reaction.lower_bound == 0 assert acald_reaction.upper_bound == 1000.0 assert acald_reaction.forward_variable.lb == 0 assert acald_reaction.forward_variable.ub == 1000.0 assert acald_reaction.reverse_variable.lb == 0 assert acald_reaction.reverse_variable.ub == 0 acald_reaction.lower_bound = -100 assert acald_reaction.lower_bound == -100.0 assert acald_reaction.upper_bound == 1000.0 assert acald_reaction.forward_variable.lb == 0 assert acald_reaction.forward_variable.ub == 1000.0 assert acald_reaction.reverse_variable.lb == 0 assert acald_reaction.reverse_variable.ub == 100
[docs]def test_make_reversible(model): pfk_reaction = model.reactions.PFK assert pfk_reaction.lower_bound == 0.0 assert pfk_reaction.upper_bound == 1000.0 assert pfk_reaction.forward_variable.lb == 0.0 assert pfk_reaction.forward_variable.ub == 1000.0 assert pfk_reaction.reverse_variable.lb == 0 assert pfk_reaction.reverse_variable.ub == 0 pfk_reaction.lower_bound = -100.0 assert pfk_reaction.lower_bound == -100.0 assert pfk_reaction.upper_bound == 1000.0 assert pfk_reaction.forward_variable.lb == 0 assert pfk_reaction.forward_variable.ub == 1000.0 assert pfk_reaction.reverse_variable.lb == 0 assert pfk_reaction.reverse_variable.ub == 100.0 pfk_reaction.lower_bound = 0 assert pfk_reaction.lower_bound == 0 assert pfk_reaction.upper_bound == 1000.0 assert pfk_reaction.forward_variable.lb == 0 assert pfk_reaction.forward_variable.ub == 1000.0 assert pfk_reaction.reverse_variable.lb == 0 assert pfk_reaction.reverse_variable.ub == 0
[docs]def test_make_irreversible_irreversible_to_the_other_side(model): pfk_reaction = model.reactions.PFK assert pfk_reaction.lower_bound == 0.0 assert pfk_reaction.upper_bound == 1000.0 assert pfk_reaction.forward_variable.lb == 0.0 assert pfk_reaction.forward_variable.ub == 1000.0 assert pfk_reaction.reverse_variable.lb == 0 assert pfk_reaction.reverse_variable.ub == 0 pfk_reaction.upper_bound = -100.0 assert pfk_reaction.forward_variable.lb == 0 assert pfk_reaction.forward_variable.ub == 0 assert pfk_reaction.reverse_variable.lb == 100 assert pfk_reaction.reverse_variable.ub == 100 pfk_reaction.lower_bound = -1000.0 assert pfk_reaction.lower_bound == -1000.0 assert pfk_reaction.upper_bound == -100.0 assert pfk_reaction.forward_variable.lb == 0 assert pfk_reaction.forward_variable.ub == 0 assert pfk_reaction.reverse_variable.lb == 100 assert pfk_reaction.reverse_variable.ub == 1000.0
[docs]def test_make_lhs_irreversible_reversible(model): rxn = Reaction("test") rxn.add_metabolites({model.metabolites[0]: -1.0, model.metabolites[1]: 1.0}) rxn.lower_bound = -1000.0 rxn.upper_bound = -100 model.add_reaction(rxn) assert rxn.lower_bound == -1000.0 assert rxn.upper_bound == -100.0 assert rxn.forward_variable.lb == 0.0 assert rxn.forward_variable.ub == 0.0 assert rxn.reverse_variable.lb == 100.0 assert rxn.reverse_variable.ub == 1000.0 rxn.upper_bound = 666.0 assert rxn.lower_bound == -1000.0 assert rxn.upper_bound == 666.0 assert rxn.forward_variable.lb == 0.0 assert rxn.forward_variable.ub == 666 assert rxn.reverse_variable.lb == 0.0 assert rxn.reverse_variable.ub == 1000.0
[docs]def test_model_less_reaction(model): 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
[docs]def test_knockout(model): original_bounds = dict() for reaction in model.reactions: original_bounds[reaction.id] = (reaction.lower_bound, reaction.upper_bound) reaction.knock_out() assert reaction.lower_bound == 0 assert reaction.upper_bound == 0 for k, (lb, ub) in six.iteritems(original_bounds): model.reactions.get_by_id(k).lower_bound = lb model.reactions.get_by_id(k).upper_bound = ub for reaction in model.reactions: assert reaction.lower_bound == original_bounds[reaction.id][0] assert reaction.upper_bound == original_bounds[reaction.id][1] with model: for reaction in model.reactions: original_bounds[reaction.id] = (reaction.lower_bound, reaction.upper_bound) reaction.knock_out() assert reaction.lower_bound == 0 assert reaction.upper_bound == 0 for reaction in model.reactions: assert reaction.lower_bound == original_bounds[reaction.id][0] assert reaction.upper_bound == original_bounds[reaction.id][1]
[docs]def test_reaction_without_model(): r = Reaction("blub") assert r.flux_expression is None assert r.forward_variable is None assert r.reverse_variable is None
[docs]def test_weird_left_to_right_reaction_issue(tiny_toy_model): d1 = tiny_toy_model.reactions.get_by_id("ex1") assert not d1.reversibility assert d1.lower_bound == -1000 assert d1._lower_bound == -1000 assert d1.upper_bound == 0 assert d1._upper_bound == 0 with tiny_toy_model: d1.knock_out() assert d1.lower_bound == 0 assert d1._lower_bound == 0 assert d1.upper_bound == 0 assert d1._upper_bound == 0 assert d1.lower_bound == -1000 assert d1._lower_bound == -1000 assert d1.upper_bound == 0 assert d1._upper_bound == 0
[docs]def test_one_left_to_right_reaction_set_positive_ub(tiny_toy_model): d1 = tiny_toy_model.reactions.get_by_id("ex1") assert d1.reverse_variable.lb == 0 assert d1.reverse_variable.ub == 1000 assert d1._lower_bound == -1000 assert d1.lower_bound == -1000 assert d1._upper_bound == 0 assert d1.upper_bound == 0 assert d1.forward_variable.lb == 0 assert d1.forward_variable.ub == 0 d1.upper_bound = 0.1 assert d1.forward_variable.lb == 0 assert d1.forward_variable.ub == 0.1 assert d1.reverse_variable.lb == 0 assert d1.reverse_variable.ub == 1000 assert d1._lower_bound == -1000 assert d1.upper_bound == 0.1 assert d1._lower_bound == -1000 assert d1.upper_bound == 0.1
[docs]def test_irrev_reaction_set_negative_lb(model): assert not model.reactions.PFK.reversibility assert model.reactions.PFK.lower_bound == 0 assert model.reactions.PFK.upper_bound == 1000.0 assert model.reactions.PFK.forward_variable.lb == 0 assert model.reactions.PFK.forward_variable.ub == 1000.0 assert model.reactions.PFK.reverse_variable.lb == 0 assert model.reactions.PFK.reverse_variable.ub == 0 model.reactions.PFK.lower_bound = -1000 assert model.reactions.PFK.lower_bound == -1000 assert model.reactions.PFK.upper_bound == 1000.0 assert model.reactions.PFK.forward_variable.lb == 0 assert model.reactions.PFK.forward_variable.ub == 1000.0 assert model.reactions.PFK.reverse_variable.lb == 0 assert model.reactions.PFK.reverse_variable.ub == 1000
[docs]def test_twist_irrev_right_to_left_reaction_to_left_to_right(model): assert not model.reactions.PFK.reversibility assert model.reactions.PFK.lower_bound == 0 assert model.reactions.PFK.upper_bound == 1000.0 assert model.reactions.PFK.forward_variable.lb == 0 assert model.reactions.PFK.forward_variable.ub == 1000.0 assert model.reactions.PFK.reverse_variable.lb == 0 assert model.reactions.PFK.reverse_variable.ub == 0 model.reactions.PFK.lower_bound = -1000 model.reactions.PFK.upper_bound = 0 assert model.reactions.PFK.lower_bound == -1000 assert model.reactions.PFK.upper_bound == 0 assert model.reactions.PFK.forward_variable.lb == 0 assert model.reactions.PFK.forward_variable.ub == 0 assert model.reactions.PFK.reverse_variable.lb == 0 assert model.reactions.PFK.reverse_variable.ub == 1000
[docs]def test_set_lb_higher_than_ub_sets_ub_to_new_lb(model): for reaction in model.reactions: assert reaction.lower_bound <= reaction.upper_bound reaction.lower_bound = reaction.upper_bound + 100 assert reaction.lower_bound == reaction.upper_bound
[docs]def test_set_ub_lower_than_lb_sets_lb_to_new_ub(model): for reaction in model.reactions: assert reaction.lower_bound <= reaction.upper_bound reaction.upper_bound = reaction.lower_bound - 100 assert reaction.lower_bound == reaction.upper_bound
[docs]def test_add_metabolites_combine_true(model): test_metabolite = Metabolite("test") for reaction in model.reactions: reaction.add_metabolites({test_metabolite: -66}, combine=True) assert reaction.metabolites[test_metabolite] == -66 assert ( model.constraints["test"].get_linear_coefficients( [reaction.forward_variable] )[reaction.forward_variable] == -66 ) assert ( model.constraints["test"].get_linear_coefficients( [reaction.reverse_variable] )[reaction.reverse_variable] == 66 ) already_included_metabolite = list(reaction.metabolites.keys())[0] previous_coefficient = reaction.get_coefficient(already_included_metabolite.id) reaction.add_metabolites({already_included_metabolite: 10}, combine=True) new_coefficient = previous_coefficient + 10 assert reaction.metabolites[already_included_metabolite] == new_coefficient assert ( model.constraints[already_included_metabolite.id].get_linear_coefficients( [reaction.forward_variable] )[reaction.forward_variable] == new_coefficient ) assert ( model.constraints[already_included_metabolite.id].get_linear_coefficients( [reaction.reverse_variable] )[reaction.reverse_variable] == -new_coefficient
) @pytest.mark.xfail(reason="non-deterministic test")
[docs]def test_add_metabolites_combine_false(model): test_metabolite = Metabolite("test") for reaction in model.reactions: reaction.add_metabolites({test_metabolite: -66}, combine=False) assert reaction.metabolites[test_metabolite] == -66 assert model.constraints["test"].expression.has( -66.0 * reaction.forward_variable ) assert model.constraints["test"].expression.has( 66.0 * reaction.reverse_variable ) already_included_metabolite = list(reaction.metabolites.keys())[0] reaction.add_metabolites({already_included_metabolite: 10}, combine=False) assert reaction.metabolites[already_included_metabolite] == 10 assert model.constraints[already_included_metabolite.id].expression.has( 10 * reaction.forward_variable ) assert model.constraints[already_included_metabolite.id].expression.has( -10 * reaction.reverse_variable
)
[docs]def test_reaction_imul(model): with model: model.reactions.EX_glc__D_e *= 100 assert ( model.constraints.glc__D_e.expression.coeff(model.variables.EX_glc__D_e) == -100.0 ) assert model.reactions.EX_glc__D_e.reaction == "100.0 glc__D_e <=> " assert ( model.constraints.glc__D_e.expression.coeff(model.variables.EX_glc__D_e) == -1.0 ) assert model.reactions.EX_glc__D_e.reaction == "glc__D_e <=> " with model: model.reactions.EX_glc__D_e *= -2 assert model.reactions.EX_glc__D_e.bounds == (-1000.0, 10.0) assert model.reactions.EX_glc__D_e.reaction == " <=> 2.0 glc__D_e" assert model.reactions.EX_glc__D_e.bounds == (-10, 1000.0) assert model.reactions.EX_glc__D_e.reaction == "glc__D_e <=> "
# def test_pop(model): # pgi = model.reactions.PGI # g6p = model.metabolites.get_by_id("g6p_c") # f6p = model.metabolites.get_by_id("f6p_c") # g6p_expr = model.solver.constraints["g6p_c"].expression # g6p_coef = pgi.pop("g6p_c") # assert g6p not in pgi.metabolites # actual = model.solver.constraints[ # "g6p_c"].expression.as_coefficients_dict() # expected = (g6p_expr - g6p_coef * pgi.flux_expression # ).as_coefficients_dict() # assert actual == expected # assert pgi.metabolites[f6p] == 1 # # f6p_expr = model.solver.constraints["f6p_c"].expression # f6p_coef = pgi.pop(f6p) # assert f6p not in pgi.metabolites # assert model.solver.constraints[ # "f6p_c"].expression.as_coefficients_dict() == ( # f6p_expr - f6p_coef * pgi.flux_expression # ).as_coefficients_dict()
[docs]def test_remove_from_model(model): pgi = model.reactions.PGI g6p = model.metabolites.g6p_c pgi_flux = model.optimize().fluxes["PGI"] assert abs(pgi_flux) > 1e-6 with model: pgi.remove_from_model() assert pgi.model is None assert "PGI" not in model.reactions assert pgi.id not in model.variables assert pgi.reverse_id not in model.variables assert pgi not in g6p.reactions model.optimize() assert "PGI" in model.reactions assert pgi.id in model.variables assert pgi.reverse_id in model.variables assert pgi.forward_variable.problem is model.solver assert pgi in g6p.reactions assert g6p in pgi.metabolites assert np.isclose(pgi_flux, model.optimize().fluxes["PGI"])
[docs]def test_change_id_is_reflected_in_solver(model): for i, reaction in enumerate(model.reactions): old_reaction_id = reaction.id assert model.variables[old_reaction_id].name == old_reaction_id assert old_reaction_id in model.variables new_reaction_id = reaction.id + "_" + str(i) reaction.id = new_reaction_id assert reaction.id == new_reaction_id assert not (old_reaction_id in model.variables) assert reaction.id in model.variables assert reaction.reverse_id in model.variables name = model.variables[reaction.id].name assert name == reaction.id
[docs]def test_repr_html_(model): assert "<table>" in model.reactions[0]._repr_html_()