3
3
import logging
4
4
from chemicals import periodic_table
5
5
import re
6
+ from cobra .core import Gene , Metabolite , Model , Reaction # !!! Gene, Metabolite, and Model are never used
7
+ from cobra .util import solver as sutil # !!! sutil is never used
6
8
import time
7
- from cobra .core import Gene , Metabolite , Model , Reaction
8
- from cobra .util import solver as sutil
9
9
from modelseedpy .biochem import from_local
10
- from scipy .odr .odrpack import Output
10
+ from scipy .odr .odrpack import Output # !!! Output is never used
11
+ from chemw import ChemMW
12
+ from warnings import warn
11
13
#from Carbon.Aliases import false
12
14
13
15
logger = logging .getLogger (__name__ )
14
16
15
- elementmass = {}
16
- for element in periodic_table :
17
- elementmass [element .symbol ] = element .MW
18
-
19
-
20
17
class FBAHelper :
21
18
22
19
@staticmethod
23
- def add_autodrain_reactions_to_community_model (model ,auto_sink = ["cpd02701" , "cpd11416" , " cpd15302" ]):
20
+ def add_autodrain_reactions_to_community_model (model ,auto_sink = ["cpd02701" , "cpd15302" ]):
24
21
#Adding missing drains in the base model
25
22
drain_reactions = []
26
23
for metabolite in model .metabolites :
27
24
msid = FBAHelper .modelseed_id_from_cobra_metabolite (metabolite )
28
25
if msid in auto_sink :
29
- if msid != "cpd11416" or metabolite .compartment == "c0" :
26
+ if metabolite .compartment == "c0" :
30
27
met_id = metabolite .id
31
- if all (rxn not in model .reactions for rxn in [f"EX_{ met_id } " , f"DM_{ met_id } " , f"SK_{ met_id } " ]):
28
+ if all ([ rxn not in model .reactions for rxn in [f"EX_{ met_id } " , f"DM_{ met_id } " , f"SK_{ met_id } " ] ]):
32
29
drain_reaction = FBAHelper .add_drain_from_metabolite_id (model ,metabolite .id ,0 ,100 ,"DM_" )
33
- if drain_reaction != None :
30
+ if not drain_reaction :
34
31
logger .info ("Adding " + met_id + " DM" )
35
32
drain_reactions .append (drain_reaction )
36
33
model .add_reactions (drain_reactions )
@@ -48,25 +45,26 @@ def add_drain_from_metabolite_id(model, cpd_id, uptake, excretion, prefix='EX_',
48
45
"""
49
46
if cpd_id in model .metabolites :
50
47
cobra_metabolite = model .metabolites .get_by_id (cpd_id )
51
- drain_reaction = Reaction (id = f'{ prefix } { cpd_id } ' ,
52
- name = prefix_name + cobra_metabolite .name ,
53
- lower_bound = - 1 * uptake ,
54
- upper_bound = excretion )
48
+ drain_reaction = Reaction (
49
+ id = f'{ prefix } { cpd_id } ' ,
50
+ name = prefix_name + cobra_metabolite .name ,
51
+ lower_bound = - uptake ,
52
+ upper_bound = excretion )
55
53
drain_reaction .add_metabolites ({cobra_metabolite : - 1 })
56
54
drain_reaction .annotation ["sbo" ] = 'SBO:0000627'
57
55
#model.add_reactions([drain_reaction])
58
56
return drain_reaction
59
57
return None
60
-
58
+
61
59
@staticmethod
62
- def set_reaction_bounds_from_direction (reaction , direction , add = 0 ):
60
+ def set_reaction_bounds_from_direction (reaction , direction , add = False ):
63
61
if direction == "<" :
64
62
reaction .lower_bound = - 100
65
- if add == 0 :
63
+ if not add :
66
64
reaction .upper_bound = 0
67
65
if direction == ">" :
68
66
reaction .upper_bound = 100
69
- if add == 0 :
67
+ if not add :
70
68
reaction .lower_bound = 0
71
69
reaction .update_variable_bounds ()
72
70
@@ -76,9 +74,7 @@ def set_objective_from_target_reaction(model,target_reaction,minimize = False):
76
74
sense = "max"
77
75
if minimize :
78
76
sense = "min"
79
- model .objective = model .problem .Objective (
80
- 1 * target_reaction .flux_expression ,
81
- direction = sense )
77
+ model .objective = model .problem .Objective (target_reaction .flux_expression , direction = sense )
82
78
return target_reaction
83
79
84
80
@staticmethod
@@ -87,8 +83,7 @@ def modelseed_id_from_cobra_metabolite(metabolite):
87
83
m = re .search ('^(cpd\d+)' , metabolite .id )
88
84
return m [1 ]
89
85
#TODO: should check to see if ModelSEED ID is in the annotations for the compound
90
- else :
91
- return None
86
+ return None
92
87
93
88
@staticmethod
94
89
def modelseed_id_from_cobra_reaction (reaction ):
@@ -101,18 +96,16 @@ def modelseed_id_from_cobra_reaction(reaction):
101
96
102
97
@staticmethod
103
98
def metabolite_mw (metabolite ):
104
- mw = 0
105
- elements = metabolite .elements
106
- for element in elements :
107
- if element not in elementmass :
108
- print ("Missing mass for element " + element + " in compound " + metabolite .id + ". Element will be ignored when computing MW" )
109
- else :
110
- mw += elements [element ]* elementmass [element ]
111
- return mw
99
+ try :
100
+ chem_mw = ChemMW ()
101
+ chem_mw .mass (metabolite .formula )
102
+ return chem_mw .raw_mw
103
+ except :
104
+ warn ("The compound " + metabolite .id + " possesses an unconventional formula {metabolite.formula}; hence, the MW cannot be computed." )
112
105
113
106
@staticmethod
114
107
def elemental_mass ():
115
- return elementmass
108
+ return { element . symbol : element . MW for element in periodic_table }
116
109
117
110
@staticmethod
118
111
def get_modelseed_db_api (modelseed_path ):
@@ -131,8 +124,8 @@ def is_biomass(reaction):
131
124
return reaction .id [0 :3 ] == "bio"
132
125
133
126
@staticmethod
134
- def exchange_hash (model ):
135
- exchange_hash = {}
127
+ def exchange_hash (model ): #!!! This function is pointless?
128
+ exchange_hash = {} # !!! this variable is never used
136
129
for reaction in model .reactions :
137
130
if len (reaction .metabolites ) == 1 :
138
131
for metabolite in reaction .metabolites :
@@ -141,102 +134,88 @@ def exchange_hash(model):
141
134
142
135
@staticmethod
143
136
def find_reaction (model ,stoichiometry ):
144
- output = FBAHelper .stoichiometry_to_string (stoichiometry )
145
- atpstring = output [0 ]
137
+ reaction_strings = FBAHelper .stoichiometry_to_string (stoichiometry )
138
+ atpstring = reaction_strings [0 ]
146
139
rxn_hash = FBAHelper .rxn_hash (model )
147
140
if atpstring in rxn_hash :
148
141
return rxn_hash [atpstring ]
149
142
return None
150
143
151
144
@staticmethod
152
- def msid_hash (model ):
145
+ def msid_hash (model ):
153
146
output = {}
154
- for cpd in model .metabolites :
155
- msid = FBAHelper .modelseed_id_from_cobra_metabolite (cpd )
147
+ for met in model .metabolites :
148
+ msid = FBAHelper .modelseed_id_from_cobra_metabolite (met )
156
149
if msid != None :
157
150
if msid not in output :
158
151
output [msid ] = []
159
- output [msid ].append (cpd )
152
+ output [msid ].append (met )
160
153
return output
161
154
162
155
@staticmethod
163
156
def rxn_hash (model ):
164
157
output = {}
165
158
for rxn in model .reactions :
166
- strings = FBAHelper .stoichiometry_to_string (rxn .metabolites )
167
- output [strings [0 ]] = [rxn ,1 ]
168
- output [strings [1 ]] = [rxn ,- 1 ]
159
+ reaction_strings = FBAHelper .stoichiometry_to_string (rxn .metabolites )
160
+ output [reaction_strings [0 ]] = [rxn ,1 ]
161
+ output [reaction_strings [1 ]] = [rxn ,- 1 ]
169
162
return output
170
163
171
164
@staticmethod
172
165
def rxn_compartment (reaction ):
173
166
compartments = list (reaction .compartments )
174
167
if len (compartments ) == 1 :
175
168
return compartments [0 ]
176
- cytosol = None
177
- othercomp = None
169
+ cytosol = othercomp = None
178
170
for comp in compartments :
179
- if comp [0 :1 ] != "e" :
180
- if comp [0 :1 ] == "c" :
181
- cytosol = comp
182
- else :
183
- othercomp = comp
184
- if othercomp is not None :
185
- return othercomp
186
- return cytosol
171
+ if comp [0 :1 ] == "c" :
172
+ cytosol = comp
173
+ elif comp [0 :1 ] != "e" :
174
+ othercomp = comp
175
+ return othercomp or cytosol
187
176
188
177
@staticmethod
189
178
def stoichiometry_to_string (stoichiometry ):
190
- reactants = []
191
- products = []
179
+ reactants , products = [], []
192
180
for met in stoichiometry :
193
- coef = stoichiometry [met ]
181
+ stoich = stoichiometry [met ]
194
182
if not isinstance (met , str ):
195
- if FBAHelper .modelseed_id_from_cobra_metabolite (met ) == "cpd00067" :
196
- met = None
197
- else :
198
- met = met .id
199
- if met != None :
200
- if coef < 0 :
183
+ met = None if FBAHelper .modelseed_id_from_cobra_metabolite (met ) == "cpd00067" else met .id
184
+ if met :
185
+ if stoich < 0 :
201
186
reactants .append (met )
202
187
else :
203
188
products .append (met )
204
- reactants .sort ()
205
- products .sort ()
206
- return ["+" .join (reactants )+ "=" + "+" .join (products ),"+" .join (products )+ "=" + "+" .join (reactants )]
189
+ return ["+" .join (sorted (reactants ))+ "=" + "+" .join (sorted (products )),"+" .join (sorted (products ))+ "=" + "+" .join (sorted (reactants ))]
207
190
208
191
@staticmethod
209
192
def add_atp_hydrolysis (model ,compartment ):
210
- #Searching for ATP hydrolysis compounds
211
- coefs = {"cpd00002" :[- 1 ,compartment ],"cpd00001" :[- 1 ,compartment ],"cpd00008" :[1 ,compartment ],"cpd00009" :[ 1 , compartment ], "cpd00067" :[ 1 , compartment ]}
212
- msids = [ "cpd00002" , "cpd00001" , "cpd00008" , "cpd00009" , " cpd00067"]
193
+ # Searching for ATP hydrolysis compounds
194
+ coefs = {"cpd00002" : [- 1 ,compartment ], "cpd00001" : [- 1 ,compartment ], "cpd00008" : [1 ,compartment ],
195
+ "cpd00009" : [ 1 , compartment ], " cpd00067": [ 1 , compartment ]}
213
196
stoichiometry = {}
214
197
id_hash = FBAHelper .msid_hash (model )
215
- for msid in msids :
198
+ for msid , content in coefs . items () :
216
199
if msid not in id_hash :
217
200
logger .warning ("Compound " + msid + " not found in model!" )
218
201
return None
219
202
else :
220
203
for cpd in id_hash [msid ]:
221
- if cpd .compartment == coefs [ msid ] [1 ]:
222
- stoichiometry [cpd ] = coefs [ msid ] [0 ]
204
+ if cpd .compartment == content [1 ]:
205
+ stoichiometry [cpd ] = content [0 ]
223
206
output = FBAHelper .find_reaction (model ,stoichiometry )
224
- if output != None and output [1 ] == ">" :
207
+ if output and output [1 ] == 1 : # !!! the second element of the output is 1/0 and not a direction string
225
208
return {"reaction" :output [0 ],"direction" :">" ,"new" :False }
226
- cobra_reaction = Reaction ("rxn00062_" + compartment ,
227
- name = "ATP hydrolysis" ,
228
- lower_bound = 0 ,
229
- upper_bound = 1000 )
230
- cobra_reaction .annotation ["sbo" ] = "SBO:0000176" #biochemical reaction
231
- cobra_reaction .annotation ["seed.reaction" ] = "rxn00062"
209
+ cobra_reaction = Reaction ("rxn00062_" + compartment , name = "ATP hydrolysis" , lower_bound = 0 , upper_bound = 1000 )
210
+ cobra_reaction .annotation .update ({"sbo" :"SBO:0000176" , "seed.reaction" :"rxn00062" }) #biochemical reaction
232
211
cobra_reaction .add_metabolites (stoichiometry )
233
212
model .add_reactions ([cobra_reaction ])
234
213
return {"reaction" :cobra_reaction ,"direction" :">" ,"new" :True }
235
214
236
215
@staticmethod
237
- def parse_id (object ):
238
- if re .search ('(.+)_([a-z])(\d+)$' , object .id ) != None :
239
- m = re .search ('(.+)_([a-z])(\d+)$' , object .id )
216
+ def parse_id (cobra_obj ):
217
+ if re .search ('(.+)_([a-z])(\d+)$' , cobra_obj .id ):
218
+ m = re .search ('(.+)_([a-z])(\d+)$' , cobra_obj .id )
240
219
return (m [1 ],m [2 ],int (m [3 ]))
241
220
return None
242
221
@@ -247,11 +226,26 @@ def medianame(media):
247
226
return media .id
248
227
249
228
@staticmethod
250
- def validate_dictionary (dictionary ,required_keys ,optional_keys ):
229
+ def validate_dictionary (dictionary ,required_keys , optional_keys = {} ):
251
230
for item in required_keys :
252
231
if item not in dictionary :
253
232
raise ValueError ('Required key ' + item + ' is missing!' )
254
233
for key in optional_keys :
255
234
if key not in dictionary :
256
- dictionary [key ] = defaults [key ]
235
+ dictionary [key ] = optional_keys [key ]
257
236
return dictionary
237
+
238
+ @staticmethod
239
+ def get_reframed_model (kbase_model ,):
240
+ from reframed import from_cobrapy
241
+
242
+ reframed_model = from_cobrapy (kbase_model )
243
+ if hasattr (kbase_model , 'id' ):
244
+ reframed_model .id = kbase_model .id
245
+ reframed_model .compartments .e0 .external = True
246
+ return reframed_model
247
+
248
+ @staticmethod
249
+ def parse_df (df ):
250
+ from numpy import array
251
+ return array (dtype = object , object = [array (df .index ), array (df .columns ), df .to_numpy ()])
0 commit comments