# -*- coding: utf-8 -*-
from __future__ import absolute_import
import pandas as pd
import pytest
from cobra import Metabolite, Reaction
from cobra import medium as medium
[docs]class TestModelMedium:
[docs] def test_model_medium(self, model):
# Add a dummy 'malformed' import reaction
bad_import = Reaction("bad_import")
bad_import.add_metabolites({model.metabolites.pyr_c: 1})
bad_import.bounds = (0, 42)
model.add_reaction(bad_import)
# Test basic setting and getting methods
medium = model.medium
model.medium = medium
assert model.medium == medium
# Test context management
with model:
# Ensure the bounds are correct beforehand
assert model.reactions.EX_glc__D_e.lower_bound == -10
assert model.reactions.bad_import.upper_bound == 42
assert model.reactions.EX_co2_e.lower_bound == -1000
# Make changes to the media
new_medium = model.medium
new_medium["EX_glc__D_e"] = 20
new_medium["bad_import"] = 24
del new_medium["EX_co2_e"]
# Change the medium, make sure changes work
model.medium = new_medium
assert model.reactions.EX_glc__D_e.lower_bound == -20
assert model.reactions.bad_import.upper_bound == 24
assert model.reactions.EX_co2_e.lower_bound == 0
# Make sure changes revert after the contex
assert model.reactions.EX_glc__D_e.lower_bound == -10
assert model.reactions.bad_import.upper_bound == 42
assert model.reactions.EX_co2_e.lower_bound == -1000
new_medium["bogus_rxn"] = 0
with pytest.raises(KeyError):
model.medium = new_medium
[docs]class TestTypeDetection:
[docs] def test_external_compartment(self, model):
# by name
assert medium.find_external_compartment(model) == "e"
# from boundary counts
for m in model.metabolites:
if m.compartment == "e":
m.compartment = "outside"
for r in model.reactions:
r._compartments = None
assert medium.find_external_compartment(model) == "outside"
# names are always right
model.exchanges[0].reactants[0].compartment = "extracellular"
assert medium.find_external_compartment(model) == "extracellular"
[docs] def test_multi_external(self, model):
for r in model.reactions:
r._compartments = None
model.exchanges[0].reactants[0].compartment = "extracellular"
# still works due to different boundary numbers
assert medium.find_external_compartment(model) == "e"
model.exchanges[1].reactants[0].compartment = "extra cellular"
model.remove_reactions(model.exchanges)
# Now fails because same boundary count
with pytest.raises(RuntimeError):
medium.find_external_compartment(model)
[docs] def test_exchange(self, model):
ex = model.exchanges
assert all(r.id.startswith("EX_") for r in ex)
ex = medium.find_boundary_types(model, "exchange", "e")
assert all(r.id.startswith("EX_") for r in ex)
[docs] def test_demand(self, model):
dm = Reaction("demand")
model.add_reaction(dm)
dm.build_reaction_from_string("atp_c ->")
dm = model.demands
assert len(dm) == 1
assert "demand" in [r.id for r in dm]
[docs] def test_sink(self, model):
sn = Reaction("sink")
model.add_reaction(sn)
sn.build_reaction_from_string("atp_c <->")
sn.bounds = -1000, 1000
sn = model.sinks
assert len(sn) == 1
assert "sink" in [r.id for r in sn]
[docs] def test_sbo_terms(self, model):
assert not medium.is_boundary_type(model.reactions.ATPM, "exchange", "e")
model.reactions.ATPM.annotation["sbo"] = "SBO:0000627"
assert medium.is_boundary_type(model.reactions.ATPM, "exchange", "bla")
model.reactions.ATPM.annotation["sbo"] = "SBO:0000632"
assert not medium.is_boundary_type(model.reactions.ATPM, "exchange", "e")
[docs]class TestErrorsAndExceptions:
[docs] def test_no_boundary_reactions(self, empty_model):
assert medium.find_boundary_types(empty_model, "e", None) == []
[docs] def test_no_names_or_boundary_reactions(self, empty_model):
with pytest.raises(RuntimeError):
medium.find_external_compartment(empty_model)
[docs] def test_bad_exchange(self, model):
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)