File: test_minimal_medium.py

package info (click to toggle)
python-cobra 0.29.1-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 11,512 kB
  • sloc: python: 14,703; xml: 12,841; makefile: 137; sh: 32
file content (140 lines) | stat: -rw-r--r-- 4,742 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
"""Test functionalities of minimal medium creation and analysis."""

from typing import Callable

import pandas as pd
import pytest

from cobra.core import Model, Reaction
from cobra.medium import minimal_medium


def test_minimal_medium_linear(model: Model) -> None:
    """Test linear minimal medium."""
    med = minimal_medium(model, 0.8)
    assert len(med) <= 4
    assert all(med > 1e-6)


def test_minimal_medium_linear_benchmark(model: Model, benchmark: Callable) -> None:
    """Benchmark linear minimal medium."""
    benchmark(minimal_medium, model, 0.8)


def test_minimal_medium_mip(model: Model) -> None:
    """Test mixed-integer minimal medium."""
    med = minimal_medium(model, 0.8, minimize_components=True)
    assert len(med) <= 4
    assert all(med > 1e-6)
    # Anaerobic growth
    med = minimal_medium(model, 0.1, minimize_components=True)
    assert len(med) <= 3
    assert all(med > 1e-6)


def test_minimal_medium_mip_benchmark(model: Model, benchmark: Callable) -> None:
    """Benchmark mixed-integer minimal medium."""
    benchmark(minimal_medium, model, 0.8, True)


def test_minimal_medium_alternative_mip(model: Model) -> None:
    """Test alternative mixed-integer minimal medium."""
    med = minimal_medium(model, 0.8, minimize_components=5, open_exchanges=True)
    assert isinstance(med, pd.DataFrame)
    assert med.shape[0] >= 5
    assert med.shape[1] == 5
    assert all((med > 0).sum() == 3)
    assert all(med.sum(axis=1) > 1e-6)


def test_minimal_medium_exports(model: Model) -> None:
    """Test exports of a minimal medium."""
    med = minimal_medium(model, 0.8, exports=True, minimize_components=True)
    assert len(med) > 4
    assert any(med < -1e-6)


def test_minimal_medium_open_exchanges(model: Model) -> None:
    """Test open exchanges of a minimal medium."""
    model.reactions.EX_glc__D_e.bounds = 0, 0
    med = minimal_medium(model, 0.8)
    assert med is None
    med = minimal_medium(model, 0.8, minimize_components=True)
    assert med is None

    med = minimal_medium(model, 0.8, open_exchanges=True)
    assert len(med) >= 3
    med = minimal_medium(model, 0.8, open_exchanges=100)
    assert len(med) >= 3


def test_model_medium(model: Model) -> None:
    """Test proper functioning of model medium manipulations."""
    # 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_reactions([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


def test_medium_does_not_affect_reactant_exports(model: Model) -> None:
    """Test that the medium setter does not overwrite exports defined as reactants."""
    med = model.medium
    # Set a fixed export rate
    model.reactions.EX_ac_e.lower_bound = 0.1
    model.medium = med
    assert model.reactions.EX_ac_e.lower_bound == 0.1

    # should be overwritten if actually in the medium
    med["EX_ac_e"] = 1
    model.medium = med
    assert model.reactions.EX_ac_e.lower_bound == -1


def test_medium_does_not_affect_product_exports(model: Model) -> None:
    """Test that the medium setter does not overwrite exports defined as products."""
    med = model.medium
    # Reverse reaction definition
    model.reactions.EX_ac_e *= -1
    # Set a fixed export rate
    model.reactions.EX_ac_e.bounds = -1, -0.1
    model.medium = med
    assert model.reactions.EX_ac_e.bounds == (-1, -0.1)

    # should be overwritten if actually in the medium
    med["EX_ac_e"] = 1
    model.medium = med
    assert model.reactions.EX_ac_e.upper_bound == 1