Skip to content

Commit cec7cf6

Browse files
authored
Merge pull request #61 from weilandtd/master
FIX: Fixing dependencies / getting ready for a new release
2 parents 57961e6 + d1cfaba commit cec7cf6

File tree

11 files changed

+103
-33
lines changed

11 files changed

+103
-33
lines changed

README.rst

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,17 +36,6 @@ properly. The installer should take care of that for you. You might also
3636
want to install a dedicated solver. GLPK, CPLEX and Gurobi are
3737
supported.
3838

39-
Container-based install
40-
-----------------------
41-
42-
You might want to use this program inside of a container. The
43-
|docker|_
44-
subfolder has all the necessary information and source files to set it
45-
up.
46-
47-
.. |docker| replace:: ``docker/``
48-
.. _docker: https://github.com/EPFL-LCSB/pytfa/tree/master/docker
49-
5039
Setup
5140
=====
5241

@@ -109,6 +98,19 @@ You can then generate the documentation with this command:
10998

11099
The resulting HTML files will be located in ``work/pytfa/doc/_build``.
111100

101+
102+
DEPRECATEDL: Container-based install
103+
-----------------------
104+
105+
You might want to use this program inside of a container. The
106+
|docker|_
107+
subfolder has all the necessary information and source files to set it
108+
up.
109+
110+
.. |docker| replace:: ``docker/``
111+
.. _docker: https://github.com/EPFL-LCSB/pytfa/tree/master/docker
112+
113+
112114
Testing the code
113115
----------------
114116

pytfa/analysis/manipulation.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,18 @@ def apply_reaction_variability(tmodel, va, inplace = True):
1818
if this_reaction.id not in va.index:
1919
continue
2020

21-
this_reaction.lower_bound = va.loc[this_reaction.id,'minimum']
22-
this_reaction.upper_bound = va.loc[this_reaction.id,'maximum']
21+
min_bound = va.loc[this_reaction.id,'minimum']
22+
max_bound = va.loc[this_reaction.id,'maximum']
23+
24+
# Handle numerical precision issues where min > max by a tiny amount
25+
if min_bound > max_bound:
26+
# Use the average of the two values
27+
avg_bound = (min_bound + max_bound) / 2
28+
min_bound = avg_bound
29+
max_bound = avg_bound
30+
31+
this_reaction.lower_bound = min_bound
32+
this_reaction.upper_bound = max_bound
2333

2434
return _tmodel
2535

pytfa/io/base.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -260,7 +260,7 @@ def create_thermo_dict(tmodel):
260260
continue
261261

262262
if column == 'metSEEDID':
263-
mat[column] = np.array(the_data, dtype=np.object)
263+
mat[column] = np.array(the_data, dtype=object)
264264
else:
265265
mat[column] = np.array(the_data)
266266

@@ -294,8 +294,8 @@ def create_thermo_dict(tmodel):
294294
CompartmentDB['compMinConc'] = np.array([x['c_min'] for x in compartments])
295295

296296
#Write symbols and names in collumn cell arrays
297-
CompartmentDB['compSymbolList'] = np.zeros((1, len(compartments)), dtype=np.object)
298-
CompartmentDB['compNameList'] = np.zeros((1, len(compartments)), dtype=np.object)
297+
CompartmentDB['compSymbolList'] = np.zeros((1, len(compartments)), dtype=object)
298+
CompartmentDB['compNameList'] = np.zeros((1, len(compartments)), dtype=object)
299299

300300
mat_to_python_string = [('compSymbolList', 'symbol'),
301301
('compNameList', 'name')]
@@ -365,8 +365,8 @@ def create_problem_dict(tmodel):
365365

366366
mat['var_lb'] = np.array([x.lb for x in tmodel.variables]) * 1.
367367
mat['var_ub'] = np.array([x.ub for x in tmodel.variables]) * 1.
368-
vname = np.full(len(tmodel.variables),'', dtype=np.object)
369-
vtype = np.full(len(tmodel.variables),'', dtype=np.object)
368+
vname = np.full(len(tmodel.variables),'', dtype=object)
369+
vtype = np.full(len(tmodel.variables),'', dtype=object)
370370

371371
for e, this_var in enumerate(tmodel.variables):
372372
this_name = this_var.name
@@ -389,8 +389,8 @@ def create_problem_dict(tmodel):
389389
# Constraints
390390

391391
rhs = np.empty(len(tmodel.constraints))
392-
ctype = np.full(len(tmodel.constraints),'', dtype=np.object)
393-
cname = np.full(len(tmodel.constraints),'', dtype=np.object)
392+
ctype = np.full(len(tmodel.constraints),'', dtype=object)
393+
cname = np.full(len(tmodel.constraints),'', dtype=object)
394394

395395
for e,this_cons in enumerate(tmodel.constraints):
396396
if this_cons.lb is None and this_cons.ub is not None:

pytfa/io/json.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,5 +76,7 @@ def json_loads_model(s):
7676
:param s: JSON string
7777
:return:
7878
"""
79+
if s is None:
80+
return None
7981
obj = json.loads(s)
8082
return model_from_dict(obj)

pytfa/redgem/redgem.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ def _extract_inorganics(self):
189189

190190
def add_lump(model, lump_object, id_suffix=''):
191191
new = Reaction(id = lump_object.id_+id_suffix)
192-
model.add_reaction(new)
192+
model.add_reactions([new])
193193
new.add_metabolites(lump_object.metabolites)
194194
new.gene_reaction_rule = lump_object.gene_reaction_rule
195195
new.subnetwork = lump_object.subnetwork

pytfa/thermo/equilibrator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
# triggers the loading of eQuilbrator
1515
from equilibrator_api import ComponentContribution, Q_
1616
from equilibrator_api.phased_reaction import PhasedReaction
17-
from equilibrator_cache import create_compound_cache_from_quilt
17+
from equilibrator_cache import create_compound_cache_from_zenodo
1818
from .std import TEMPERATURE_0
1919
from ..utils.numerics import BIGM_DG
2020
from ..utils.logger import get_bistream_logger
@@ -37,7 +37,7 @@ def build_thermo_from_equilibrator(model, T=TEMPERATURE_0):
3737
"""
3838
global ccache
3939
if ccache is None:
40-
ccache = create_compound_cache_from_quilt()
40+
ccache = create_compound_cache_from_zenodo()
4141
logger.debug("eQuilibrator compound cache is loaded.")
4242

4343
cc = ComponentContribution()

requirements.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,5 +7,4 @@ networkx
77
pytest
88
scipy
99
tqdm
10-
equilibrator-cache==0.2.6
1110
equilibrator_api

tests/settings.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,13 @@
1414

1515
from pytfa.io.enrichment import read_lexicon, annotate_from_lexicon, \
1616
read_compartment_data, apply_compartment_data
17-
from cobra.test import create_test_model
17+
try:
18+
from cobra.test import create_test_model
19+
except ImportError:
20+
# For newer versions of cobra
21+
from cobra.io import load_model
22+
def create_test_model(model_name):
23+
return load_model(model_name)
1824

1925
############
2026
# SETTINGS #
@@ -46,7 +52,6 @@
4652

4753

4854
# Small model for simpler tests
49-
5055
small_model = create_test_model('textbook')
5156

5257
# Make your computations on it

tests/test_equilibrator.py

Lines changed: 45 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44
import pytest
55
import sys
66
from pytfa.io.json import json_dumps_model, json_loads_model
7+
from pytfa.thermo.equilibrator import build_thermo_from_equilibrator
8+
from pytfa import ThermoModel
9+
from settings import small_model
710

811

912

@@ -14,13 +17,11 @@
1417
def test_load_with_equi_thermo(request):
1518
"""Build thermo data structure with equilibrator."""
1619
t_model = request.config.cache.get('model', None)
17-
from pytfa.thermo.equilibrator import build_thermo_from_equilibrator
18-
from pytfa import ThermoModel
19-
from settings import cobra_model
20-
cmodel = cobra_model.copy()
20+
cmodel = small_model.copy()
2121
for met in cmodel.metabolites:
2222
# normalize but don't overwrite
23-
met.annotation["seed.compound"] = met.annotation["seed_id"]
23+
if "seed_id" in met.annotation:
24+
met.annotation["seed.compound"] = met.annotation["seed_id"]
2425
thermo_data = build_thermo_from_equilibrator(cmodel)
2526
t_model = ThermoModel(thermo_data, cmodel)
2627
t_model.solver = "optlang-glpk"
@@ -50,6 +51,45 @@ def test_equilibrator_conversion(request):
5051

5152
@pytest.mark.dependency(depends=['test_equilibrator_conversion'])
5253
@pytest.mark.skipif(sys.version_info < (3, 6), reason="requires >= python3.6")
54+
def test_equilibrator_deltag_loaded(request):
55+
"""Test that deltaG values are actually loaded from equilibrator."""
56+
# Get the original cobra model and rebuild thermo_data to check it directly
57+
58+
cmodel = small_model.copy()
59+
for met in cmodel.metabolites:
60+
# normalize but don't overwrite
61+
if "seed_id" in met.annotation:
62+
met.annotation["seed.compound"] = met.annotation["seed_id"]
63+
64+
# Build thermo data from equilibrator
65+
thermo_data = build_thermo_from_equilibrator(cmodel)
66+
67+
print(f"Thermo data structure: {thermo_data['name']}")
68+
print(f"Units: {thermo_data['units']}")
69+
70+
# Check metabolites in thermo_data
71+
metabolites_with_deltag = 0
72+
sample_mets = []
73+
74+
for met_data in thermo_data['metabolites']:
75+
if 'DeltaGf_tr' in met_data:
76+
metabolites_with_deltag += 1
77+
if len(sample_mets) < 5: # Collect some samples
78+
sample_mets.append((met_data['id'], met_data['DeltaGf_tr']))
79+
80+
print(f"Found {metabolites_with_deltag} metabolites with deltaG formation values from equilibrator")
81+
print("Sample metabolites with deltaG values:")
82+
for met_id, deltag in sample_mets:
83+
print(f" {met_id}: {deltag} {thermo_data['units']}")
84+
85+
# There should be at least some metabolites with deltaG values
86+
assert metabolites_with_deltag > 0, f"No deltaG formation values found in thermo_data! Expected > 0, got {metabolites_with_deltag}"
87+
88+
return metabolites_with_deltag
89+
90+
91+
@pytest.mark.dependency(depends=['test_equilibrator_deltag_loaded'])
92+
@pytest.mark.skipif(sys.version_info < (3, 6), reason="requires >= python3.6")
5393
def test_equilibrator_optim(request):
5494
"""LP optimization by the usual method in `ThermoModel`."""
5595
t_model = json_loads_model(request.config.cache.get('model',None))

tests/test_optim.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,13 @@
1010
1111
"""
1212

13-
from cobra.test import create_test_model
13+
try:
14+
from cobra.test import create_test_model
15+
except ImportError:
16+
# For newer versions of cobra
17+
from cobra.io import load_model
18+
def create_test_model(model_name):
19+
return load_model(model_name)
1420
import os
1521
import sys
1622
import pytfa

0 commit comments

Comments
 (0)