seed2lp 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- seed2lp/__init__.py +12 -0
- seed2lp/__main__.py +837 -0
- seed2lp/_version.py +2 -0
- seed2lp/argument.py +717 -0
- seed2lp/asp/atom_for_transfers.lp +7 -0
- seed2lp/asp/community_heuristic.lp +3 -0
- seed2lp/asp/community_search.lp +14 -0
- seed2lp/asp/constraints_targets.lp +15 -0
- seed2lp/asp/definition_atoms.lp +87 -0
- seed2lp/asp/enum-cc.lp +50 -0
- seed2lp/asp/flux.lp +70 -0
- seed2lp/asp/limit_transfers.lp +9 -0
- seed2lp/asp/maximize_flux.lp +2 -0
- seed2lp/asp/maximize_produced_target.lp +7 -0
- seed2lp/asp/minimize.lp +8 -0
- seed2lp/asp/seed-solving.lp +116 -0
- seed2lp/asp/seed_external.lp +1 -0
- seed2lp/asp/show_seeds.lp +2 -0
- seed2lp/asp/show_tranfers.lp +1 -0
- seed2lp/asp/test.lp +61 -0
- seed2lp/clingo_lpx.py +236 -0
- seed2lp/color.py +34 -0
- seed2lp/config.yaml +56 -0
- seed2lp/description.py +424 -0
- seed2lp/file.py +151 -0
- seed2lp/flux.py +365 -0
- seed2lp/linear.py +431 -0
- seed2lp/log_conf.yaml +25 -0
- seed2lp/logger.py +112 -0
- seed2lp/metabolite.py +46 -0
- seed2lp/network.py +1921 -0
- seed2lp/reaction.py +207 -0
- seed2lp/reasoning.py +459 -0
- seed2lp/reasoningcom.py +753 -0
- seed2lp/reasoninghybrid.py +791 -0
- seed2lp/resmod.py +74 -0
- seed2lp/sbml.py +307 -0
- seed2lp/scope.py +124 -0
- seed2lp/solver.py +333 -0
- seed2lp/temp_flux_com.py +74 -0
- seed2lp/utils.py +237 -0
- seed2lp-2.0.0.dist-info/METADATA +404 -0
- seed2lp-2.0.0.dist-info/RECORD +53 -0
- seed2lp-2.0.0.dist-info/WHEEL +5 -0
- seed2lp-2.0.0.dist-info/entry_points.txt +2 -0
- seed2lp-2.0.0.dist-info/licenses/LICENCE.txt +145 -0
- seed2lp-2.0.0.dist-info/top_level.txt +2 -0
- tests/__init__.py +0 -0
- tests/fba.py +147 -0
- tests/full_network.py +166 -0
- tests/normalization.py +188 -0
- tests/target.py +286 -0
- tests/utils.py +181 -0
seed2lp/resmod.py
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
from . import flux
|
|
2
|
+
from cobra.core import Model
|
|
3
|
+
|
|
4
|
+
class Resmod:
|
|
5
|
+
def __init__(self, name:str, objectives:list, solver_type:str, search_mode:str, search_type:str,
|
|
6
|
+
size:int, seeds_list:list, flux_lp:dict, flux_cobra:dict=None, run_mode:str=None,
|
|
7
|
+
accu:bool=False, is_community:bool=False, transferred_list:list=None):
|
|
8
|
+
"""Initialize Object Resmod
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
name (str): Name of the solution
|
|
12
|
+
objectives (list): List of objective reaction names
|
|
13
|
+
solver_type (str): Type of solver (Reasoning / FBA / Hybrid)
|
|
14
|
+
search_mode (str): search mode type (Minimize / Submin)
|
|
15
|
+
search_type (str): search type (enumeration / union /intersection)
|
|
16
|
+
size (int): Size of set of seeds
|
|
17
|
+
seeds_list (list): List of seeds
|
|
18
|
+
flux_lp (dict): Dictionnary of all reaction with their LP flux
|
|
19
|
+
flux_cobra (float, optional): Cobra flux calculated (mode Filter, Guess Check). Defaults to None.
|
|
20
|
+
run_mode (str, optional): Running command used (full or target). Defaults to None.
|
|
21
|
+
accu (bool, optional): Is accumulation allowed. Defaults to False.
|
|
22
|
+
"""
|
|
23
|
+
self.name = name
|
|
24
|
+
self.objectives = objectives
|
|
25
|
+
self.solver_type = solver_type
|
|
26
|
+
self.search_mode = search_mode
|
|
27
|
+
self.search_type = search_type
|
|
28
|
+
self.size = size
|
|
29
|
+
self.seeds_list = seeds_list
|
|
30
|
+
self.flux_lp = flux_lp
|
|
31
|
+
self.chosen_lp = None
|
|
32
|
+
self.tested_objective = None
|
|
33
|
+
self.objective_flux_seeds = None
|
|
34
|
+
self.objective_flux_demands = None
|
|
35
|
+
self.OK_seeds = False
|
|
36
|
+
self.OK_demands = False
|
|
37
|
+
self.OK = False
|
|
38
|
+
self.run_mode = run_mode
|
|
39
|
+
self.accu = accu
|
|
40
|
+
self.flux_cobra = flux_cobra
|
|
41
|
+
self.is_community = is_community
|
|
42
|
+
self.transferred_list = transferred_list
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
######################## METHODS ########################
|
|
47
|
+
def check_flux(self, model_cobra:Model, try_demands:bool=True, equality_flux:bool=False):
|
|
48
|
+
"""Execute flux calculation usng cobra and store data
|
|
49
|
+
|
|
50
|
+
Args:
|
|
51
|
+
model_cobra (Model): Cobra model
|
|
52
|
+
show_messages (bool, optional): Option to show the messages on console.
|
|
53
|
+
Defaults to True. False for hybrid with cobra.
|
|
54
|
+
try_demands (bool, optional): Option to try to add demands if seeds failed.
|
|
55
|
+
Defaults to True. False for hybrid with cobra.
|
|
56
|
+
equality_flux (bool, optional): Community mode otpion to force equality of flux
|
|
57
|
+
between species' biomass
|
|
58
|
+
"""
|
|
59
|
+
with model_cobra as m:
|
|
60
|
+
flux_output, objective, lp_flux = \
|
|
61
|
+
flux.calculate(m, self.objectives, self.seeds_list, self.flux_lp, try_demands,
|
|
62
|
+
self.is_community, self.transferred_list, equality_flux)
|
|
63
|
+
if flux_output:
|
|
64
|
+
self.tested_objective = objective
|
|
65
|
+
self.chosen_lp = lp_flux
|
|
66
|
+
self.objective_flux_seeds = flux_output['objective_flux_seeds']
|
|
67
|
+
self.objective_flux_demands = flux_output['objective_flux_demands']
|
|
68
|
+
self.OK_seeds = flux_output['OK_seeds']
|
|
69
|
+
self.OK_demands = flux_output['OK_demands']
|
|
70
|
+
self.OK = flux_output['OK']
|
|
71
|
+
self.infeasible_seeds = flux_output['infeasible_seeds']
|
|
72
|
+
self.infeasible_demands = flux_output['infeasible_demands']
|
|
73
|
+
|
|
74
|
+
########################################################
|
seed2lp/sbml.py
ADDED
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
"""Routines to extract information from SBML files.
|
|
2
|
+
|
|
3
|
+
"""
|
|
4
|
+
import xml.etree.ElementTree as ET
|
|
5
|
+
from re import sub, match, search
|
|
6
|
+
from . import logger
|
|
7
|
+
|
|
8
|
+
def register_all_namespaces(file:str):
|
|
9
|
+
"""Get namespaces for rewriting SBML file
|
|
10
|
+
|
|
11
|
+
Args:
|
|
12
|
+
file (str): SBML file path
|
|
13
|
+
"""
|
|
14
|
+
namespaces = dict([node for _, node in ET.iterparse(file, events=['start-ns'])])
|
|
15
|
+
for ns in namespaces:
|
|
16
|
+
#print(ns, namespaces[ns])
|
|
17
|
+
ET.register_namespace(ns, namespaces[ns])
|
|
18
|
+
|
|
19
|
+
def get_root(file:str):
|
|
20
|
+
"""Get etree root
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
file (str): SBML file path
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
sbml (etree Element), first_line (str) : Return an etree elemnt of the network, and the first line of the sbml file
|
|
27
|
+
"""
|
|
28
|
+
register_all_namespaces(file)
|
|
29
|
+
with open(file) as f:
|
|
30
|
+
first_line = f.readline()
|
|
31
|
+
xmlstring = f.read()
|
|
32
|
+
f.close()
|
|
33
|
+
|
|
34
|
+
# Remove the default namespace definition (xmlns="http://some/namespace")
|
|
35
|
+
default_namespace = search(r'\sxmlns="[^"]+"', xmlstring).group()
|
|
36
|
+
xmlstring = sub(default_namespace, '', xmlstring, count=1)
|
|
37
|
+
|
|
38
|
+
sbml = ET.fromstring(xmlstring)
|
|
39
|
+
#tree = ET.parse(file)
|
|
40
|
+
#sbml = tree.getroot()
|
|
41
|
+
return sbml, first_line, default_namespace
|
|
42
|
+
|
|
43
|
+
def get_sbml_tag(element:ET.Element) -> str:
|
|
44
|
+
"Return tag associated with given SBML element"
|
|
45
|
+
if element.tag[0] == "{":
|
|
46
|
+
_, tag = element.tag[1:].split("}") # uri is not used
|
|
47
|
+
else:
|
|
48
|
+
tag = element.tag
|
|
49
|
+
return tag
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def get_model(sbml:ET.Element) -> ET.Element:
|
|
53
|
+
"""
|
|
54
|
+
return the model of a SBML
|
|
55
|
+
"""
|
|
56
|
+
model_element = None
|
|
57
|
+
for e in sbml:
|
|
58
|
+
tag = get_sbml_tag(e)
|
|
59
|
+
if tag == "model":
|
|
60
|
+
model_element = e
|
|
61
|
+
break
|
|
62
|
+
return model_element
|
|
63
|
+
|
|
64
|
+
def get_listOfSpecies(model:ET.Element) -> list[ET.Element]:
|
|
65
|
+
"""
|
|
66
|
+
return list of species of a SBML model
|
|
67
|
+
"""
|
|
68
|
+
listOfSpecies = None
|
|
69
|
+
for e in model:
|
|
70
|
+
tag = get_sbml_tag(e)
|
|
71
|
+
if tag == "listOfSpecies":
|
|
72
|
+
listOfSpecies = e
|
|
73
|
+
break
|
|
74
|
+
return listOfSpecies
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def get_listOfReactions(model:ET.Element) -> list[ET.Element]:
|
|
78
|
+
"""return list of reactions of a SBML model"""
|
|
79
|
+
listOfReactions = []
|
|
80
|
+
for e in model:
|
|
81
|
+
tag = get_sbml_tag(e)
|
|
82
|
+
if tag == "listOfReactions":
|
|
83
|
+
listOfReactions = e
|
|
84
|
+
break
|
|
85
|
+
return listOfReactions
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
def get_listOfReactants(reaction:ET.Element, species:str=None, is_community:bool=False) -> list:
|
|
89
|
+
"""return list of reactants of a reaction"""
|
|
90
|
+
listOfReactants = list()
|
|
91
|
+
listOfReactantsNames = list()
|
|
92
|
+
for e in reaction:
|
|
93
|
+
tag = get_sbml_tag(e)
|
|
94
|
+
if tag == "listOfReactants":
|
|
95
|
+
for meta in e:
|
|
96
|
+
meta_id = meta_name = meta.attrib.get('species')
|
|
97
|
+
if is_community:
|
|
98
|
+
meta_id = sub("^M_", f"M_{species}_",meta_id)
|
|
99
|
+
listOfReactants.append([meta_id, meta.attrib.get('stoichiometry'), meta_name])
|
|
100
|
+
|
|
101
|
+
# Create a list of only of meta to determine if a reaction will be transport reaction
|
|
102
|
+
# both list must be the same (same element in reactnats and products)
|
|
103
|
+
listOfReactantsNames.append(meta_name.rsplit('_', 1)[0])
|
|
104
|
+
break
|
|
105
|
+
return listOfReactants, listOfReactantsNames
|
|
106
|
+
|
|
107
|
+
|
|
108
|
+
def get_listOfReactants_from_name(model:ET.Element, reaction_name) -> list[ET.Element]:
|
|
109
|
+
"""return list of reactants of a reaction"""
|
|
110
|
+
reactions_list = get_listOfReactions(model)
|
|
111
|
+
for reaction in reactions_list:
|
|
112
|
+
if reaction_name == reaction.attrib['id']:
|
|
113
|
+
for e in reaction:
|
|
114
|
+
tag = get_sbml_tag(e)
|
|
115
|
+
if tag == "listOfReactants":
|
|
116
|
+
listOfReactants = e
|
|
117
|
+
break
|
|
118
|
+
return listOfReactants
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
def get_listOfProducts(reaction:ET.Element, species:str=None, is_community:bool=False) -> list:
|
|
122
|
+
"""return list of products of a reaction"""
|
|
123
|
+
listOfProducts = list()
|
|
124
|
+
listOfProductsNames = list()
|
|
125
|
+
for e in reaction:
|
|
126
|
+
tag = get_sbml_tag(e)
|
|
127
|
+
if tag == "listOfProducts":
|
|
128
|
+
for meta in e:
|
|
129
|
+
meta_id = meta_name = meta.attrib.get('species')
|
|
130
|
+
if is_community:
|
|
131
|
+
meta_id = sub("^M_", f"M_{species}_",meta_id)
|
|
132
|
+
listOfProducts.append([meta_id, meta.attrib.get('stoichiometry'), meta_name])
|
|
133
|
+
|
|
134
|
+
# Create a list of only of meta to determine if a reaction will be transport reaction
|
|
135
|
+
# both list must be the same (same element in reactnats and products)
|
|
136
|
+
listOfProductsNames.append(meta_name.rsplit('_', 1)[0])
|
|
137
|
+
break
|
|
138
|
+
return listOfProducts, listOfProductsNames
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def get_reaction_from_name(model:ET.Element, reaction_name) -> list[ET.Element]:
|
|
142
|
+
"""return list of reactants of a reaction"""
|
|
143
|
+
reactions_list = get_listOfReactions(model)
|
|
144
|
+
for reaction in reactions_list:
|
|
145
|
+
if reaction_name == reaction.attrib['id']:
|
|
146
|
+
return reaction
|
|
147
|
+
raise ValueError(f"No reaction {reaction_name} found in list of reactions \n")
|
|
148
|
+
|
|
149
|
+
|
|
150
|
+
def get_fbc(sbml:ET.Element):
|
|
151
|
+
"""
|
|
152
|
+
return the fbc namespace of a SBML
|
|
153
|
+
"""
|
|
154
|
+
fbc = None
|
|
155
|
+
for nss in ET._namespaces(sbml):
|
|
156
|
+
for key in nss:
|
|
157
|
+
if key is not None and 'fbc' in key:
|
|
158
|
+
fbc=key
|
|
159
|
+
break
|
|
160
|
+
return fbc
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def get_listOfParameters(model:ET.Element)-> dict:
|
|
164
|
+
"""return list of reactions of a SBML model"""
|
|
165
|
+
listOfParameters = dict()
|
|
166
|
+
for e in model:
|
|
167
|
+
tag = get_sbml_tag(e)
|
|
168
|
+
if tag == "listOfParameters":
|
|
169
|
+
for param in e:
|
|
170
|
+
listOfParameters[param.get('id')]=param.get('value')
|
|
171
|
+
break
|
|
172
|
+
return listOfParameters
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
def get_parameters(model:ET.Element) -> list[ET.Element]:
|
|
176
|
+
"""
|
|
177
|
+
return list of parameters of a SBML model
|
|
178
|
+
"""
|
|
179
|
+
listOfParameters = None
|
|
180
|
+
for e in model:
|
|
181
|
+
tag = get_sbml_tag(e)
|
|
182
|
+
if tag == "listOfParameters":
|
|
183
|
+
listOfParameters = e
|
|
184
|
+
break
|
|
185
|
+
return listOfParameters
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
def get_objectives(model:ET.Element) -> list[ET.Element]:
|
|
189
|
+
"""
|
|
190
|
+
return list of parameters of a SBML model
|
|
191
|
+
"""
|
|
192
|
+
listOfObjective = None
|
|
193
|
+
for e in model:
|
|
194
|
+
tag = get_sbml_tag(e)
|
|
195
|
+
if tag == "listOfObjectives":
|
|
196
|
+
listOfObjective = e
|
|
197
|
+
break
|
|
198
|
+
return listOfObjective
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def get_listOfFluxObjectives(model,fbc)-> list:
|
|
202
|
+
"""return list of objective reactions of a SBML model"""
|
|
203
|
+
listOfFluxObjectives = list()
|
|
204
|
+
|
|
205
|
+
for e in model:
|
|
206
|
+
tag = get_sbml_tag(e)
|
|
207
|
+
if tag == "listOfObjectives":
|
|
208
|
+
for lo in e[0]:
|
|
209
|
+
if lo:
|
|
210
|
+
for o in lo:
|
|
211
|
+
name = o.attrib.get('{'+fbc+'}reaction')
|
|
212
|
+
coef = o.attrib.get('{'+fbc+'}coefficient')
|
|
213
|
+
reaction = get_reaction_from_name(model, name)
|
|
214
|
+
listOfFluxObjectives.append([name,coef,reaction])
|
|
215
|
+
break
|
|
216
|
+
return listOfFluxObjectives
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
def read_SBML_species(filename)-> dict:
|
|
220
|
+
"""Yield names of species listed in given SBML file"""
|
|
221
|
+
model_dict = dict()
|
|
222
|
+
tree = ET.parse(filename)
|
|
223
|
+
sbml = tree.getroot()
|
|
224
|
+
model = get_model(sbml)
|
|
225
|
+
species_list = list()
|
|
226
|
+
reactions_list = list()
|
|
227
|
+
|
|
228
|
+
for species in get_listOfSpecies(model):
|
|
229
|
+
species_list.append(species.attrib['id'])
|
|
230
|
+
for reaction in get_listOfReactions(model):
|
|
231
|
+
reactions_list.append(f"{reaction.attrib['id']}")
|
|
232
|
+
|
|
233
|
+
model_dict['Metabolites'] = species_list
|
|
234
|
+
model_dict['Reactions'] = reactions_list
|
|
235
|
+
return model_dict
|
|
236
|
+
|
|
237
|
+
|
|
238
|
+
def get_used_metabolites(filename, call_log=False)-> set:
|
|
239
|
+
"""Determine from source file the truly used metabolite (and not the list of species)
|
|
240
|
+
Necessary for scripts 10_1_scope_analyse.py and 10_3_iCN718_metabolite_analyses.py
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
filename (str): Path to thie SBML file
|
|
244
|
+
|
|
245
|
+
Returns:
|
|
246
|
+
used_metabolites (set): Set of used metabolites
|
|
247
|
+
"""
|
|
248
|
+
tree = ET.parse(filename)
|
|
249
|
+
sbml = tree.getroot()
|
|
250
|
+
model = get_model(sbml)
|
|
251
|
+
# SBML has species that are never used on any reactions
|
|
252
|
+
# but are present into species list
|
|
253
|
+
# Also, there is some reaction that involves species but
|
|
254
|
+
# having boundaries to [0,0], so we are not taken into account
|
|
255
|
+
# the species of the species of these reactions into the used metabolites
|
|
256
|
+
used_metabolites = set()
|
|
257
|
+
|
|
258
|
+
fbc = get_fbc(get_root(filename)[0])
|
|
259
|
+
parameters = get_listOfParameters(model)
|
|
260
|
+
|
|
261
|
+
for reaction in get_listOfReactions(model):
|
|
262
|
+
ubound = parameters[reaction.attrib.get('{'+fbc+'}upperFluxBound')]
|
|
263
|
+
lbound = parameters[reaction.attrib.get('{'+fbc+'}lowerFluxBound')]
|
|
264
|
+
if float(ubound) == 0 and float(lbound) == 0 and call_log:
|
|
265
|
+
logger.log.warning(f"Reaction {reaction.attrib['id']} deleted, boudaries [0,0]")
|
|
266
|
+
continue
|
|
267
|
+
else:
|
|
268
|
+
reactants,_ = get_listOfReactants(reaction,"",False)
|
|
269
|
+
products,_ = get_listOfProducts(reaction,"",False)
|
|
270
|
+
for reactant in reactants:
|
|
271
|
+
used_metabolites.add(reactant[0])
|
|
272
|
+
for product in products:
|
|
273
|
+
used_metabolites.add(product[0])
|
|
274
|
+
|
|
275
|
+
return used_metabolites
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
def etree_to_string(model) -> str:
|
|
280
|
+
return str(ET.tostring(model, encoding='utf-8', method='xml'),'UTF-8')
|
|
281
|
+
|
|
282
|
+
def create_sub_element(element:ET.Element, sub_element:str):
|
|
283
|
+
ET.SubElement(element,sub_element)
|
|
284
|
+
|
|
285
|
+
def remove_sub_elements(element:ET.Element):
|
|
286
|
+
for metabolite in list(element):
|
|
287
|
+
element.remove(metabolite)
|
|
288
|
+
|
|
289
|
+
def add_metabolites(element:ET.Element, metabolites_list):
|
|
290
|
+
for metabolite in metabolites_list:
|
|
291
|
+
element.append(metabolite)
|
|
292
|
+
|
|
293
|
+
def remove_reaction(model:ET.Element, element:ET.Element):
|
|
294
|
+
for e in model:
|
|
295
|
+
tag = get_sbml_tag(e)
|
|
296
|
+
if tag == "listOfReactions":
|
|
297
|
+
e.remove(element)
|
|
298
|
+
|
|
299
|
+
def check_remove_objective(model:ET.Element, reaction:ET.Element, fbc):
|
|
300
|
+
for e in model:
|
|
301
|
+
tag = get_sbml_tag(e)
|
|
302
|
+
if tag == "listOfObjectives":
|
|
303
|
+
for lo in e[0]:
|
|
304
|
+
if lo:
|
|
305
|
+
for o in lo:
|
|
306
|
+
if o.attrib.get('{'+fbc+'}reaction') == reaction.attrib['id']:
|
|
307
|
+
lo.remove(o)
|
seed2lp/scope.py
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
from .network import Network
|
|
2
|
+
from menetools import run_menescope
|
|
3
|
+
from .file import is_valid_dir, save
|
|
4
|
+
from os.path import join
|
|
5
|
+
#from .sbml import get_used_metabolites
|
|
6
|
+
import libsbml
|
|
7
|
+
from padmet.utils.sbmlPlugin import convert_from_coded_id
|
|
8
|
+
from padmet.utils.connection import sbmlGenerator
|
|
9
|
+
import sys
|
|
10
|
+
from . import logger
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Scope:
|
|
14
|
+
def __init__(self, file:str, network:Network, output_dir:str):
|
|
15
|
+
"""Initialize Object Scope
|
|
16
|
+
|
|
17
|
+
Args:
|
|
18
|
+
file (str): SBML File (Needed to detect source used metabolites on the network)
|
|
19
|
+
network (Network): Corrected Network
|
|
20
|
+
"""
|
|
21
|
+
self.file = file
|
|
22
|
+
self.network = network
|
|
23
|
+
self.output_dir = output_dir
|
|
24
|
+
self.dir_seeds_sbml = is_valid_dir(join(output_dir,'sbml'))
|
|
25
|
+
self.dir_scope = is_valid_dir(join(output_dir,'scope'))
|
|
26
|
+
|
|
27
|
+
######################## METHODS ########################
|
|
28
|
+
def execute(self):
|
|
29
|
+
"""Execute the scope from seeds solution for each solution and save it into file.
|
|
30
|
+
Creates an intermediate seed sbml file.
|
|
31
|
+
"""
|
|
32
|
+
# Get global data on the network
|
|
33
|
+
#set_used_metabolites = get_used_metabolites(self.file, True)
|
|
34
|
+
set_used_metabolites = set(self.network.used_meta.keys())
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# run the scope for each solutions of the result
|
|
38
|
+
for result in self.network.result_seeds:
|
|
39
|
+
#TODO : print better in TABLE
|
|
40
|
+
print(result.run_mode.upper())
|
|
41
|
+
print(result.solver_type)
|
|
42
|
+
print(result.search_mode)
|
|
43
|
+
print(result.name)
|
|
44
|
+
print("Accumulation:", result.accu)
|
|
45
|
+
|
|
46
|
+
if result.accu == True:
|
|
47
|
+
accu="accu"
|
|
48
|
+
else:
|
|
49
|
+
accu="no_accu"
|
|
50
|
+
|
|
51
|
+
run_mode = result.run_mode.lower().replace(" ","_").replace("-", "_")
|
|
52
|
+
solver = result.solver_type.lower().replace(" ","_").replace("-", "_")
|
|
53
|
+
search_mode = result.search_mode.lower().replace(" ","_").replace("-", "_")
|
|
54
|
+
seeds=set(result.seeds_list)
|
|
55
|
+
|
|
56
|
+
seeds_sbml_complete_dir_path = is_valid_dir(join(self.dir_seeds_sbml, run_mode, solver, search_mode, accu))
|
|
57
|
+
seeds_sbml_path=join(seeds_sbml_complete_dir_path, f'{result.name}.sbml')
|
|
58
|
+
scope_dir_path = is_valid_dir(join(self.dir_scope, run_mode, solver, search_mode, accu))
|
|
59
|
+
|
|
60
|
+
# Write the seed into sbl format for each solutions
|
|
61
|
+
create_species_sbml(seeds, seeds_sbml_path)
|
|
62
|
+
logger.log.info(f"Seeds sbml file created: {seeds_sbml_path}")
|
|
63
|
+
|
|
64
|
+
# Run menescope from seed to get the scope
|
|
65
|
+
logger.log.info(f"Scope running for {seeds_sbml_path}...")
|
|
66
|
+
scope_model = run_menescope(self.file, seeds_sbml_path)
|
|
67
|
+
logger.log.info(f"Scope terminated.")
|
|
68
|
+
scope_model["size_scope"] = len(scope_model["scope"])
|
|
69
|
+
scope_model["size_all_metabolites"] = len(set_used_metabolites)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
print("size of scope", scope_model["size_scope"])
|
|
74
|
+
print("size of all metabolites", scope_model["size_all_metabolites"],"\n\n")
|
|
75
|
+
save(f'{result.name}', scope_dir_path, scope_model, "json")
|
|
76
|
+
logger.log.info(f"Scope saved in: {scope_dir_path}/{result.name}.json.")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def create_species_sbml(metabolites, outputfile):
|
|
81
|
+
"""Create a SBML files with a list of species containing metabolites of the input set.
|
|
82
|
+
Check if there are forbidden SBML characters in the metabolite IDs/ If yes, exit.
|
|
83
|
+
|
|
84
|
+
Args:
|
|
85
|
+
metabolites (set): set of metabolites
|
|
86
|
+
outputfile (str): SBML file to be written
|
|
87
|
+
"""
|
|
88
|
+
document = libsbml.SBMLDocument(2, 1)
|
|
89
|
+
model = document.createModel("metabolites")
|
|
90
|
+
forbidden_charlist = ['-', '|', '/', '(', ')',
|
|
91
|
+
"'", '=', '#', '*', '.', ':', '!', '+', '[',
|
|
92
|
+
']', ',', ' ']
|
|
93
|
+
forbidden_character_in_metabolites = None
|
|
94
|
+
issue_trying_to_add_species = None
|
|
95
|
+
for compound in metabolites:
|
|
96
|
+
compound = compound.strip('"')
|
|
97
|
+
_, _, comp = convert_from_coded_id(compound)
|
|
98
|
+
s = model.createSpecies()
|
|
99
|
+
sbmlGenerator.check(s, 'create species')
|
|
100
|
+
forbidden_characters_detacted = [char for char in forbidden_charlist if char in compound]
|
|
101
|
+
if len(forbidden_characters_detacted) > 0:
|
|
102
|
+
logger.log.warning("Forbidden character ({0}) in {1}. SBML creation will failed.".format(' '.join(forbidden_characters_detacted), compound))
|
|
103
|
+
forbidden_character_in_metabolites = True
|
|
104
|
+
try:
|
|
105
|
+
sbmlGenerator.check(s.setId(compound), 'set species id')
|
|
106
|
+
except:
|
|
107
|
+
issue_trying_to_add_species = True
|
|
108
|
+
logger.log.warning("Issue when trying to add compound {0}.".format(compound))
|
|
109
|
+
|
|
110
|
+
if comp is not None:
|
|
111
|
+
sbmlGenerator.check(s.setCompartment(comp), 'set species compartment')
|
|
112
|
+
elif comp is None:
|
|
113
|
+
logger.log.warning("No compartment for " + compound)
|
|
114
|
+
|
|
115
|
+
if issue_trying_to_add_species is True and forbidden_character_in_metabolites is True:
|
|
116
|
+
logger.log.warning("Forbidden character in compound ID, SBML creation will failed.")
|
|
117
|
+
logger.log.warning("Modify the metabolic networks SBMl file by renaming these metabolites and removing the forbidden character.")
|
|
118
|
+
sys.exit(1)
|
|
119
|
+
if issue_trying_to_add_species is True and forbidden_character_in_metabolites is None:
|
|
120
|
+
logger.log.warning("Issue when trying to add metabolite into SBML file, potential issue with SBML format.")
|
|
121
|
+
logger.log.warning("Modify the metabolic networks SBMl file by renaming these metabolites and removing the forbidden character.")
|
|
122
|
+
sys.exit(1)
|
|
123
|
+
|
|
124
|
+
libsbml.writeSBMLToFile(document, outputfile)
|