Skip to content

Commit 98e11ee

Browse files
committed
feat: build integration layer for multitfa
1 parent d327e4b commit 98e11ee

File tree

5 files changed

+138
-3
lines changed

5 files changed

+138
-3
lines changed

docs/03-thermodynamics.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ or the thermodynamic constraint, see the
273273
)
274274
# constrain the model objective so that the feashibility relaxation recovers growth
275275
tmodel_prot.reactions.BIOMASS_Ecoli_core_w_GAM.lower_bound = solution.objective_value
276-
iis, status = geckopy.integration.relax_thermo_proteins(
276+
iis, status = geckopy.integration.relaxation.relax_thermo_proteins(
277277
tmodel_prot,
278278
prot_candidates=[prot.id for prot in tmodel_prot.proteins],
279279
objective_rule=geckopy.experimental.relaxation.Objective_rule.MIN_ELASTIC_SUM

geckopy/integration/__init__.py

-1
Original file line numberDiff line numberDiff line change
@@ -11,4 +11,3 @@
1111
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1212
# See the License for the specific language governing permissions and
1313
# limitations under the License.
14-
from .relaxation import relax_thermo_concentrations_proteins, relax_thermo_proteins

geckopy/integration/multitfa.py

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
from copy import copy, deepcopy
2+
3+
import geckopy
4+
from cobra.core.dictlist import DictList
5+
6+
from multitfa.core import tmodel
7+
from multitfa.core import Thermo_met, thermo_reaction
8+
9+
10+
class ThermoProtReaction(thermo_reaction):
11+
"""
12+
Class representation of thermo reaction Object. We calculate the required thermodynamic constraints for performing tMFA. To do the constraints, we need Gibbs energy of reaction and transport.
13+
14+
Parameters
15+
----------
16+
cobra_rxn : cobra.core.Reaction
17+
Cobra reaction object, to copy the attributes from. We copy metabolites and genes.
18+
updated_model : core.tmodel, optional
19+
tmodel object, with updated thermo properties, by default None
20+
21+
"""
22+
23+
def __init__(
24+
self,
25+
cobra_rxn,
26+
updated_model=None,
27+
):
28+
self._model = updated_model
29+
do_not_copy_by_ref = {"_model", "_metabolites", "_genes"}
30+
for attr, value in cobra_rxn.__dict__.items():
31+
if attr not in do_not_copy_by_ref:
32+
self.__dict__[attr] = copy(value)
33+
34+
self._metabolites = {}
35+
for met, stoic in cobra_rxn._metabolites.items():
36+
# this is the only change; also account for proteins
37+
new_met = self.model.metabolites.get_by_id(met.id) if met in self.model.metabolites else self.model.proteins.get_by_id(met.id)
38+
self._metabolites[new_met] = stoic
39+
new_met._reaction.add(self)
40+
self._genes = set()
41+
for gene in cobra_rxn._genes:
42+
new_gene = self.model.genes.get_by_id(gene.id)
43+
self._genes.add(new_gene)
44+
new_gene._reaction.add(self)
45+
46+
47+
class ThermoProtModel(tmodel):
48+
def __init__(
49+
self,
50+
model,
51+
Exclude_list=[],
52+
tolerance_integral=1e-9,
53+
compartment_info=None,
54+
membrane_potential=None,
55+
exclude_metabolites=[],
56+
):
57+
58+
self.compartment_info = compartment_info
59+
self.membrane_potential = membrane_potential
60+
61+
do_not_copy_by_ref = {
62+
"metabolites",
63+
"reactions",
64+
"proteins",
65+
"genes",
66+
"notes",
67+
"annotation",
68+
}
69+
for attr in model.__dict__:
70+
if attr not in do_not_copy_by_ref:
71+
self.__dict__[attr] = model.__dict__[attr]
72+
73+
self.metabolites = DictList()
74+
do_not_copy_by_ref = {"_reaction", "_model"}
75+
for metabolite in model.metabolites:
76+
new_met = Thermo_met(
77+
metabolite=metabolite,
78+
updated_model=self,
79+
)
80+
self.metabolites.append(new_met)
81+
82+
self.genes = DictList()
83+
84+
for gene in model.genes:
85+
new_gene = gene.__class__(None)
86+
for attr, value in gene.__dict__.items():
87+
if attr not in do_not_copy_by_ref:
88+
new_gene.__dict__[attr] = (
89+
copy(value) if attr == "formula" else value
90+
)
91+
new_gene._model = self
92+
self.genes.append(new_gene)
93+
self.proteins = DictList()
94+
for protein in model.proteins:
95+
new_prot = Thermo_met(
96+
metabolite=protein,
97+
updated_model=self,
98+
)
99+
# proteins do not participate in dGf calculations
100+
new_prot.is_ignore = True
101+
self.proteins.append(new_prot)
102+
103+
self.reactions = DictList()
104+
do_not_copy_by_ref = {"_model", "_metabolites", "_genes"}
105+
for reaction in model.reactions:
106+
# this is custom to make the reaction aware of proteins
107+
new_reaction = ThermoProtReaction(
108+
cobra_rxn=reaction,
109+
updated_model=self,
110+
)
111+
self.reactions.append(new_reaction)
112+
113+
try:
114+
self._solver = deepcopy(model.solver)
115+
# Cplex has an issue with deep copies
116+
except Exception: # pragma: no cover
117+
self._solver = copy(model.solver) # pragma: no cover
118+
119+
self.Exclude_list = Exclude_list
120+
self.solver.configuration.tolerances.integrality = tolerance_integral
121+
self._var_update = False
+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
import pytest
2+
from optlang import available_solvers
3+
4+
from geckopy.integration.multitfa import ThermoProtModel
5+
6+
7+
@pytest.mark.skipif(not (available_solvers["GUROBI"] or available_solvers["CPLEX"]))
8+
def test_protein_constrain_affects_multitfa_solution(ec_model_core):
9+
"""Check thermo model returns different solution when protein is constrained."""
10+
thermo_model = ThermoProtModel(ec_model_core.copy())
11+
tsol = thermo_model.slim_optimize()
12+
ec_model_core.proteins.prot_P25516.add_concentration(2e-5)
13+
thermo_model = ThermoProtModel(ec_model_core)
14+
tsol_prot = thermo_model.slim_optimize()
15+
assert pytest.approx(tsol) != tsol_prot

tests/test_integration/test_relaxation.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323

2424
from geckopy.experimental import from_copy_number
2525
from geckopy.experimental.relaxation import Objective_rule
26-
from geckopy.integration import (
26+
from geckopy.integration.relaxation import (
2727
relax_thermo_concentrations_proteins,
2828
relax_thermo_proteins,
2929
)

0 commit comments

Comments
 (0)