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/linear.py
ADDED
|
@@ -0,0 +1,431 @@
|
|
|
1
|
+
# Object Hybrid, herit from Solver, added properties:
|
|
2
|
+
# - temp_dir (str): temporary directory for saving instance file and clingo outputs
|
|
3
|
+
# - instance_file (str): Path of instance file for solving
|
|
4
|
+
# 1 -> Atom output
|
|
5
|
+
# 2 -> Json output
|
|
6
|
+
|
|
7
|
+
# Object FBA, herit from Hybrid, no property added
|
|
8
|
+
|
|
9
|
+
from seed2lp.network import Network
|
|
10
|
+
from seed2lp.solver import Solver
|
|
11
|
+
from . import clingo_lpx, color, logger
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
###################################################################
|
|
15
|
+
################### Class Hybrid : herit Solver ###################
|
|
16
|
+
###################################################################
|
|
17
|
+
class Hybrid(Solver):
|
|
18
|
+
def __init__(self, run_mode:str, run_solve:str, network:Network,
|
|
19
|
+
time_limit_minute:float=None, number_solution:int=None,
|
|
20
|
+
clingo_configuration:str=None, clingo_strategy:str=None,
|
|
21
|
+
intersection:bool=False, union:bool=False,
|
|
22
|
+
minimize:bool=False, subset_minimal:bool=False,
|
|
23
|
+
maximize_flux:bool=False,
|
|
24
|
+
temp_dir:str=None, short_option:str=None,
|
|
25
|
+
verbose:bool=False):
|
|
26
|
+
"""Initialize Object Hybrid, herit from Solver
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
run_mode (str): Running command used (full or target or fba)
|
|
30
|
+
run_solve (str): Solving command used (Hybrid)
|
|
31
|
+
network (Network): Network constructed
|
|
32
|
+
time_limit_minute (float, optional): Time limit given by user in minutes . Defaults to None.
|
|
33
|
+
number_solution (int, optional): Limit number of solutions to find. Defaults to None.
|
|
34
|
+
clingo_configuration (str, optional): Configuration for clingo resolution . Defaults to None.
|
|
35
|
+
clingo_strategy (str, optional): Strategy for clingo resolution. Defaults to None.
|
|
36
|
+
enumeration (bool, optional): Enumerate the solutions limited by the number of solutions. Defaults to True.
|
|
37
|
+
intersection (bool, optional): Find the intersection of all solutions without limitation (give one solution). Defaults to False.
|
|
38
|
+
union (bool, optional): Find the union of all solutions without limitation (give one solution). Defaults to False.
|
|
39
|
+
minimize (bool, optional): Search the minimal carinality of solutions. Defaults to False.
|
|
40
|
+
subset_minimal (bool, optional): Search the subset minimal solutions. Defaults to False.
|
|
41
|
+
maximize_flux (bool, optional): Use maximization of flux for calculation. Defaults to False.
|
|
42
|
+
temp_dir (str, optional): Temporary directory for saving instance file and clingo outputs. Defaults to None.
|
|
43
|
+
short_option (str, optional): Short way to write option on filename. Defaults to None.
|
|
44
|
+
verbose (bool, optional): Set debug mode. Defaults to False.
|
|
45
|
+
"""
|
|
46
|
+
super().__init__(run_mode, network, time_limit_minute, number_solution, clingo_configuration,
|
|
47
|
+
clingo_strategy, intersection, union, minimize, subset_minimal, temp_dir, short_option, run_solve, verbose)
|
|
48
|
+
|
|
49
|
+
self.is_linear = True
|
|
50
|
+
self.maximize_flux = maximize_flux
|
|
51
|
+
self.temp_dir = temp_dir
|
|
52
|
+
self.short_option = short_option
|
|
53
|
+
self.asp_files.append(self.asp.ASP_SRC_FLUX)
|
|
54
|
+
self.asp_files.append(self.asp.ASP_SRC_SHOW_SEEDS)
|
|
55
|
+
self.get_init_message()
|
|
56
|
+
self._init_clingo_constant()
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
######################## METHODS ########################
|
|
60
|
+
def get_init_message(self):
|
|
61
|
+
"""Get init message to put on terminal
|
|
62
|
+
"""
|
|
63
|
+
title_mess = "\n############################################\n" \
|
|
64
|
+
"############################################\n" \
|
|
65
|
+
f" {color.bold}HYBRID{color.cyan_light}\n"\
|
|
66
|
+
"############################################\n" \
|
|
67
|
+
"############################################\n"
|
|
68
|
+
logger.print_log(title_mess, "info", color.cyan_light)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def _init_clingo_constant(self):
|
|
72
|
+
"""Init the list of ASP constant command for resolution
|
|
73
|
+
"""
|
|
74
|
+
self.init_const()
|
|
75
|
+
|
|
76
|
+
if self.maximize_flux:
|
|
77
|
+
logger.print_log('Flux: MAXIMIZATION', "info")
|
|
78
|
+
else:
|
|
79
|
+
logger.print_log('Flux: NO MAXIMIZATION', "info")
|
|
80
|
+
logger.print_log(f"Time limit: {self.time_limit_minute} minutes", 'info')
|
|
81
|
+
logger.print_log(f"Solution number limit: {self.number_solution}", 'info')
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def search_seed(self):
|
|
85
|
+
"""Launch seed searching
|
|
86
|
+
"""
|
|
87
|
+
if not self.network.objectives:
|
|
88
|
+
self.get_message('optimum error')
|
|
89
|
+
self.get_message('end')
|
|
90
|
+
return
|
|
91
|
+
|
|
92
|
+
files = self.asp_files.copy()
|
|
93
|
+
if self.maximize_flux:
|
|
94
|
+
files.append(self.asp.ASP_SRC_MAXIMIZE_FLUX)
|
|
95
|
+
if self.subset_minimal:
|
|
96
|
+
self.get_message('subsetmin')
|
|
97
|
+
#logger.print_log("GROUNDING...", "info")
|
|
98
|
+
#self.grounded, timer, err_output, error_code, memory = self.ground(files, self.clingo_constant, self.is_linear, self.verbose)
|
|
99
|
+
self.search_subsetmin(files)
|
|
100
|
+
if self.minimize:
|
|
101
|
+
self.get_message('minimize')
|
|
102
|
+
if self.network.is_subseed:
|
|
103
|
+
files.append(self.asp.ASP_SRC_MAXIMIZE_PRODUCED_TARGET)
|
|
104
|
+
logger.print_log('POSSIBLE SEED: Given', "info")
|
|
105
|
+
logger.print_log(' A subset of possible seed is search \n maximising the number of produced target', "info")
|
|
106
|
+
self.clingo_constant.append('-c')
|
|
107
|
+
self.clingo_constant.append('subseed=1')
|
|
108
|
+
files.append(self.asp.ASP_SRC_MINIMIZE)
|
|
109
|
+
#logger.print_log("GROUNDING...", "info")
|
|
110
|
+
#self.grounded, timer, err_output, error_code, memory = self.ground(files, self.clingo_constant, self.is_linear, self.verbose)
|
|
111
|
+
self.search_minimize(files)
|
|
112
|
+
self.get_message('end')
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def search_minimize(self, asp_files):
|
|
116
|
+
"""Launch seed searching with minimze options
|
|
117
|
+
"""
|
|
118
|
+
logger.print_log("Finding optimum...", "info")
|
|
119
|
+
self.solve(asp_files, "minimize-one-model")
|
|
120
|
+
|
|
121
|
+
if self.one_model_unsat:
|
|
122
|
+
return
|
|
123
|
+
|
|
124
|
+
ok_opti = self.optimum_found and (self.opt_size > 0)
|
|
125
|
+
#ok_opti = (self.optimum is not None) and (self.optimum > 0)
|
|
126
|
+
if self.optimum is None:
|
|
127
|
+
opti_message = "Optimum not found."
|
|
128
|
+
elif self.optimum == 0:
|
|
129
|
+
opti_message = "Optimum is 0."
|
|
130
|
+
|
|
131
|
+
if self.enumeration:
|
|
132
|
+
if ok_opti:
|
|
133
|
+
self.get_message('enumeration')
|
|
134
|
+
self.solve(asp_files, "minimize-enumeration")
|
|
135
|
+
else:
|
|
136
|
+
self.get_message('enumeration')
|
|
137
|
+
logger.print_log(f"\nNot computed: {opti_message}", "info")
|
|
138
|
+
|
|
139
|
+
if self.intersection:
|
|
140
|
+
if ok_opti:
|
|
141
|
+
self.get_message('intersection')
|
|
142
|
+
self.solve(asp_files, "minimize-intersection")
|
|
143
|
+
else:
|
|
144
|
+
self.get_message('intersection')
|
|
145
|
+
logger.print_log(f"\nNot computed: {opti_message}", "info")
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
def search_subsetmin(self, asp_files):
|
|
149
|
+
"""Launch seed searching with subset minimal options
|
|
150
|
+
"""
|
|
151
|
+
if self.enumeration:
|
|
152
|
+
self.get_message('enumeration')
|
|
153
|
+
self.solve(asp_files, "submin-enumeration")
|
|
154
|
+
else:
|
|
155
|
+
self.number_solution = 1
|
|
156
|
+
logger.print_log("\n--------------- One solution ---------------", "info")
|
|
157
|
+
self.solve(asp_files, "submin-enumeration")
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
if self.intersection:
|
|
161
|
+
self.get_message('intersection')
|
|
162
|
+
self.solve(asp_files, "submin-intersection")
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def add_result_seeds(self, search_mode:str, model_name:str, len:int, seeds:list, flux_dict:dict):
|
|
166
|
+
"""Add a formated resulted set of seeds into the network object
|
|
167
|
+
|
|
168
|
+
Args:
|
|
169
|
+
search_mode (str): search mode type
|
|
170
|
+
model_name (str): model name
|
|
171
|
+
len (int): length of a set of seed
|
|
172
|
+
seeds (list): list of seeds
|
|
173
|
+
flux_dict(dict): Dictionnary of all reaction with their LP flux
|
|
174
|
+
"""
|
|
175
|
+
self.network.add_result_seeds('HYBRID', search_mode, model_name, len, seeds, flux_dict)
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
def get_objectives_flux(self, flux_list):
|
|
179
|
+
"""From a list of all reaction and associated LP flux, find objective reactions
|
|
180
|
+
and create a dictionnary to stock the LP flux
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
flux_list (list): List of all reaction name and associated LP flux
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
Dict: A dictionnary of Objective reaction with it associated flux
|
|
187
|
+
"""
|
|
188
|
+
obj_flux_dict = dict()
|
|
189
|
+
for line in flux_list:
|
|
190
|
+
reaction = line[0]
|
|
191
|
+
if reaction in self.network.objectives:
|
|
192
|
+
obj_flux_dict[reaction] = line[1]
|
|
193
|
+
return obj_flux_dict
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
|
|
197
|
+
def solve(self, asp_files:list=[], search_mode:str=""):
|
|
198
|
+
"""Solve the seed seraching using the launch mode
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
asp_files (list, optional): List of ASP files used for sovling. Defaults to [].
|
|
202
|
+
search_mode (str, optional): Describe the launch mode. . Defaults to "".
|
|
203
|
+
"""
|
|
204
|
+
logger.print_log("SOLVING...\n", "info")
|
|
205
|
+
results = dict()
|
|
206
|
+
solution_list = dict()
|
|
207
|
+
timer = dict()
|
|
208
|
+
|
|
209
|
+
full_option, _, model_type, output_type = self.get_solutions_infos(search_mode)
|
|
210
|
+
full_option = self.clingo_constant + full_option
|
|
211
|
+
|
|
212
|
+
if self.optimum:
|
|
213
|
+
if self.opt_prod_tgt is not None:
|
|
214
|
+
full_option[-1]=full_option[-1]+f",{self.opt_prod_tgt},{self.opt_size}"
|
|
215
|
+
else:
|
|
216
|
+
full_option[-1]=full_option[-1]+f",{self.opt_size}"
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
match search_mode:
|
|
220
|
+
case "minimize-one-model":
|
|
221
|
+
cmd = clingo_lpx.command(files=asp_files, options=full_option,
|
|
222
|
+
time_limit=self.time_limit)
|
|
223
|
+
cmd_str = ' '.join(cmd)
|
|
224
|
+
proc_output, err, error_code, \
|
|
225
|
+
memory, is_killed = clingo_lpx.solve(cmd, self.time_limit)
|
|
226
|
+
self.get_message("command")
|
|
227
|
+
logger.print_log(f'{cmd_str}', 'debug')
|
|
228
|
+
|
|
229
|
+
self.get_error(error_code, err)
|
|
230
|
+
output_full_list, unsatisfiable, self.optimum_found, full_timers, opt = clingo_lpx.result_convert(proc_output,
|
|
231
|
+
self.network.objectives,
|
|
232
|
+
"", is_killed, False)
|
|
233
|
+
if unsatisfiable:
|
|
234
|
+
logger.print_log('Unsatisfiable problem', "error")
|
|
235
|
+
|
|
236
|
+
elif self.optimum_found:
|
|
237
|
+
logger.print_log("Optimum Found", "info")
|
|
238
|
+
self.one_model_unsat = False
|
|
239
|
+
one_model_list=output_full_list[list(output_full_list.keys())[-1]]
|
|
240
|
+
self.optimum=opt
|
|
241
|
+
self.get_separate_optimum()
|
|
242
|
+
#TODO Corrects the producible targets count
|
|
243
|
+
#if self.network.is_subseed:
|
|
244
|
+
# logger.print_log((f"Number of producible targets: {- self.opt_prod_tgt}"), 'info')
|
|
245
|
+
#TODO END
|
|
246
|
+
logger.print_log(f"Minimal size of seed set is {self.opt_size}\n", 'info')
|
|
247
|
+
if self.optimum is not None and self.network.keep_import_reactions:
|
|
248
|
+
logger.print_log("Try with the option remove import reactions.", "info")
|
|
249
|
+
solution_list[model_type] = one_model_list
|
|
250
|
+
#Get obejctives fluxes and add results seeds to network object
|
|
251
|
+
obj_flux_dict = self.get_objectives_flux(one_model_list[5])
|
|
252
|
+
self.add_result_seeds(search_mode, model_type, one_model_list[1], one_model_list[3], obj_flux_dict)
|
|
253
|
+
# Satisfiable probleme but optimum not found in given time
|
|
254
|
+
else:
|
|
255
|
+
logger.print_log('Optimum not found', "error")
|
|
256
|
+
|
|
257
|
+
case "minimize-enumeration":
|
|
258
|
+
cmd = clingo_lpx.command(files=asp_files, options=full_option, nb_model= self.number_solution,
|
|
259
|
+
time_limit=self.time_limit)
|
|
260
|
+
cmd_str = ' '.join(cmd)
|
|
261
|
+
proc_output, err, error_code, \
|
|
262
|
+
memory, is_killed = clingo_lpx.solve(cmd, self.time_limit)
|
|
263
|
+
self.get_message("command")
|
|
264
|
+
logger.print_log(f'{cmd_str}', 'debug')
|
|
265
|
+
self.get_error(error_code, err)
|
|
266
|
+
solution_list, unsatisfiable, _, full_timers, _ = clingo_lpx.result_convert(proc_output,
|
|
267
|
+
self.network.objectives, "enumeration", is_killed)
|
|
268
|
+
if unsatisfiable:
|
|
269
|
+
logger.print_log('Unsatisfiable problem', "error")
|
|
270
|
+
else:
|
|
271
|
+
for model_name, solution in solution_list.items():
|
|
272
|
+
#Get obejctives fluxes and add results seeds to network object
|
|
273
|
+
obj_flux_dict = self.get_objectives_flux(solution[5])
|
|
274
|
+
self.add_result_seeds(search_mode, model_name, solution[1], solution[3], obj_flux_dict)
|
|
275
|
+
|
|
276
|
+
case "submin-enumeration":
|
|
277
|
+
cmd = clingo_lpx.command(files=asp_files, options=full_option, nb_model= self.number_solution,
|
|
278
|
+
time_limit=self.time_limit)
|
|
279
|
+
cmd_str = ' '.join(cmd)
|
|
280
|
+
proc_output, err, error_code, \
|
|
281
|
+
memory, is_killed = clingo_lpx.solve(cmd, self.time_limit)
|
|
282
|
+
self.get_message("command")
|
|
283
|
+
logger.print_log(f'{cmd_str}', 'debug')
|
|
284
|
+
self.get_error(error_code, err)
|
|
285
|
+
solution_list, unsatisfiable, _, full_timers,_ = clingo_lpx.result_convert(proc_output,
|
|
286
|
+
self.network.objectives, "enumeration", is_killed)
|
|
287
|
+
if unsatisfiable:
|
|
288
|
+
logger.print_log('Unsatisfiable problem', "error")
|
|
289
|
+
else:
|
|
290
|
+
for model_name, solution in solution_list.items():
|
|
291
|
+
#Get obejctives fluxes and add results seeds to network object
|
|
292
|
+
obj_flux_dict = self.get_objectives_flux(solution[5])
|
|
293
|
+
self.add_result_seeds(search_mode, model_name, solution[1], solution[3], obj_flux_dict)
|
|
294
|
+
|
|
295
|
+
case "minimize-intersection":
|
|
296
|
+
cmd = clingo_lpx.command(files=asp_files, options=full_option,
|
|
297
|
+
time_limit=self.time_limit)
|
|
298
|
+
cmd_str = ' '.join(cmd)
|
|
299
|
+
proc_output, err, error_code, \
|
|
300
|
+
memory, is_killed = clingo_lpx.solve(cmd, self.time_limit)
|
|
301
|
+
self.get_message("command")
|
|
302
|
+
logger.print_log(f'{cmd_str}', 'debug')
|
|
303
|
+
self.get_error(error_code, err)
|
|
304
|
+
output_full_list, unsatisfiable, _, full_timers = clingo_lpx.result_convert(proc_output,
|
|
305
|
+
self.network.objectives, 'cautious', is_killed)
|
|
306
|
+
if unsatisfiable:
|
|
307
|
+
logger.print_log('Unsatisfiable problem', "error")
|
|
308
|
+
elif output_full_list:
|
|
309
|
+
model = output_full_list[list(output_full_list.keys())[-1]]
|
|
310
|
+
solution_list[model_type ] = model
|
|
311
|
+
#Get obejctives fluxes and add results seeds to network object
|
|
312
|
+
obj_flux_dict = self.get_objectives_flux(model[5])
|
|
313
|
+
self.add_result_seeds(search_mode, model_type, model[1], model[3], obj_flux_dict)
|
|
314
|
+
|
|
315
|
+
|
|
316
|
+
case "submin-intersection":
|
|
317
|
+
cmd = clingo_lpx.command(files=asp_files, options=full_option,
|
|
318
|
+
time_limit=self.time_limit)
|
|
319
|
+
cmd_str = ' '.join(cmd)
|
|
320
|
+
proc_output, err, error_code, \
|
|
321
|
+
memory, is_killed = clingo_lpx.solve(files=asp_files, options=full_option,
|
|
322
|
+
time_limit=self.time_limit)
|
|
323
|
+
self.get_message("command")
|
|
324
|
+
logger.print_log(f'{cmd_str}', 'debug')
|
|
325
|
+
self.get_error(error_code, err)
|
|
326
|
+
output_full_list, unsatisfiable, _, full_timers = clingo_lpx.result_convert(proc_output,
|
|
327
|
+
self.network.objectives, 'cautious', is_killed)
|
|
328
|
+
if unsatisfiable:
|
|
329
|
+
logger.print_log('Unsatisfiable problem', "error")
|
|
330
|
+
elif output_full_list:
|
|
331
|
+
model = output_full_list[list(output_full_list.keys())[-1]]
|
|
332
|
+
solution_list[model_type] = model
|
|
333
|
+
#Get obejctives fluxes and add results seeds to network object
|
|
334
|
+
obj_flux_dict = self.get_objectives_flux(model[5])
|
|
335
|
+
self.add_result_seeds(search_mode, model_type, model[1], model[3], obj_flux_dict)
|
|
336
|
+
if 'Total' in full_timers:
|
|
337
|
+
timer["Grounding time"] = round(full_timers['Total'] - full_timers['Solve'], 3)
|
|
338
|
+
timer["Solving time"] = round(full_timers['Solve'], 3)
|
|
339
|
+
else:
|
|
340
|
+
timer["Grounding time"] = "Time out"
|
|
341
|
+
timer["Solving time"] = "Time out"
|
|
342
|
+
results ["Timer"] = timer
|
|
343
|
+
results ["Memory (GB)"] = memory
|
|
344
|
+
results['solutions']= solution_list
|
|
345
|
+
self.output[output_type] = results
|
|
346
|
+
|
|
347
|
+
|
|
348
|
+
def get_error(self,error_code:int, err:bytes):
|
|
349
|
+
"""Get and print error
|
|
350
|
+
|
|
351
|
+
Args:
|
|
352
|
+
error_code (int): Code error from Python process
|
|
353
|
+
err (bytes): Error text from python process
|
|
354
|
+
|
|
355
|
+
Raises:
|
|
356
|
+
ValueError: Raise an error and stop the program when value of code < 0
|
|
357
|
+
"""
|
|
358
|
+
if error_code and error_code<0:
|
|
359
|
+
print(f'error_code = {error_code}')
|
|
360
|
+
raise ValueError(err.decode())
|
|
361
|
+
elif err:
|
|
362
|
+
logger.print_log(err.decode(), 'debug')
|
|
363
|
+
|
|
364
|
+
########################################################
|
|
365
|
+
|
|
366
|
+
|
|
367
|
+
###################################################################
|
|
368
|
+
##################### Class FBA : herit Hybrid ####################
|
|
369
|
+
###################################################################
|
|
370
|
+
class FBA(Hybrid):
|
|
371
|
+
def __init__(self, run_mode:str, network:Network,
|
|
372
|
+
time_limit_minute:float=None, number_solution:int=None,
|
|
373
|
+
clingo_configuration:str=None, clingo_strategy:str=None,
|
|
374
|
+
intersection:bool=False, union:bool=False,
|
|
375
|
+
minimize:bool=False, subset_minimal:bool=False,
|
|
376
|
+
maximize_flux:bool=False,
|
|
377
|
+
temp_dir:str=None, short_option:str=None,
|
|
378
|
+
verbose:bool=False):
|
|
379
|
+
"""Initialize Object Hybrid, herit from Solver
|
|
380
|
+
|
|
381
|
+
Args:
|
|
382
|
+
run_mode (str): Running command used (full or target or fba)
|
|
383
|
+
network (Network): Network constructed
|
|
384
|
+
time_limit_minute (float, optional): Time limit given by user in minutes . Defaults to None.
|
|
385
|
+
number_solution (int, optional): Limit number of solutions to find. Defaults to None.
|
|
386
|
+
clingo_configuration (str, optional): Configuration for clingo resolution . Defaults to None.
|
|
387
|
+
clingo_strategy (str, optional): Strategy for clingo resolution. Defaults to None.
|
|
388
|
+
enumeration (bool, optional): Enumerate the solutions limited by the number of solutions. Defaults to True.
|
|
389
|
+
intersection (bool, optional): Find the intersection of all solutions without limitation (give one solution). Defaults to False.
|
|
390
|
+
union (bool, optional): Find the union of all solutions without limitation (give one solution). Defaults to False.
|
|
391
|
+
minimize (bool, optional): Search the minimal carinality of solutions. Defaults to False.
|
|
392
|
+
subset_minimal (bool, optional): Search the subset minimal solutions. Defaults to False.
|
|
393
|
+
maximize_flux (bool, optional): Use maximization of flux for calculation. Defaults to False.
|
|
394
|
+
temp_dir (str, optional): Temporary directory for saving instance file and clingo outputs. Defaults to None.
|
|
395
|
+
short_option (str, optional): Short way to write option on filename. Defaults to None.
|
|
396
|
+
verbose (bool, optional): Set debug mode. Defaults to False.
|
|
397
|
+
"""
|
|
398
|
+
super().__init__(run_mode, None, network,
|
|
399
|
+
time_limit_minute, number_solution,
|
|
400
|
+
clingo_configuration, clingo_strategy,
|
|
401
|
+
intersection, union, minimize,
|
|
402
|
+
subset_minimal, maximize_flux,
|
|
403
|
+
temp_dir, short_option,
|
|
404
|
+
verbose)
|
|
405
|
+
|
|
406
|
+
######################## METHODS ########################
|
|
407
|
+
|
|
408
|
+
def get_init_message(self):
|
|
409
|
+
"""Get init message to put on terminal
|
|
410
|
+
"""
|
|
411
|
+
title_mess = "\n############################################\n" \
|
|
412
|
+
"############################################\n" \
|
|
413
|
+
f" {color.bold}FBA{color.cyan_light}\n"\
|
|
414
|
+
"############################################\n" \
|
|
415
|
+
"############################################\n"
|
|
416
|
+
logger.print_log(title_mess, "info", color.cyan_light)
|
|
417
|
+
|
|
418
|
+
def add_result_seeds(self, search_mode:str, model_name:str, len:int, seeds:list, flux_list:list):
|
|
419
|
+
"""Add a formated resulted set of seeds into the network object
|
|
420
|
+
|
|
421
|
+
Args:
|
|
422
|
+
search_mode (str): search mode type
|
|
423
|
+
model_name (str): model name
|
|
424
|
+
len (int): length of a set of seed
|
|
425
|
+
seeds (list): list of seeds
|
|
426
|
+
"""
|
|
427
|
+
self.network.add_result_seeds('FBA', search_mode, model_name, len, seeds, flux_list)
|
|
428
|
+
########################################################
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
|
seed2lp/log_conf.yaml
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
###############################
|
|
2
|
+
# Logger configuration #
|
|
3
|
+
###############################
|
|
4
|
+
|
|
5
|
+
version: 1
|
|
6
|
+
disable_existing_loggers: False
|
|
7
|
+
formatters:
|
|
8
|
+
simple:
|
|
9
|
+
format: '%(levelname)s : %(message)s'
|
|
10
|
+
() : seed2lp.logger.ColoredFormatter
|
|
11
|
+
use_color: true
|
|
12
|
+
handlers:
|
|
13
|
+
console:
|
|
14
|
+
class: logging.StreamHandler
|
|
15
|
+
level: WARNING
|
|
16
|
+
formatter: simple
|
|
17
|
+
stream: ext://sys.stdout
|
|
18
|
+
loggers:
|
|
19
|
+
s2lp:
|
|
20
|
+
level: DEBUG
|
|
21
|
+
handlers: [console]
|
|
22
|
+
propagate: no
|
|
23
|
+
root:
|
|
24
|
+
level: DEBUG
|
|
25
|
+
handlers: [console]
|
seed2lp/logger.py
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import logging, logging.config
|
|
2
|
+
from os import path
|
|
3
|
+
from . import color, file
|
|
4
|
+
import yaml
|
|
5
|
+
from ._version import __version__
|
|
6
|
+
|
|
7
|
+
ROJECT_DIR = path.dirname(path.abspath(__file__))
|
|
8
|
+
LOG_DIR:str
|
|
9
|
+
log:logging.Logger
|
|
10
|
+
verbose:bool
|
|
11
|
+
|
|
12
|
+
COLORS = {
|
|
13
|
+
"WARNING": color.yellow,
|
|
14
|
+
"INFO": color.grey,
|
|
15
|
+
"DEBUG": color.reverse_colour,
|
|
16
|
+
"CRITICAL": color.orange_back,
|
|
17
|
+
"ERROR": color.red_bright,
|
|
18
|
+
"RESET": color.reset
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ColoredFormatter(logging.Formatter):
|
|
23
|
+
def __init__(self, *, format:str, use_color:bool):
|
|
24
|
+
logging.Formatter.__init__(self, fmt=format)
|
|
25
|
+
self.use_color = use_color
|
|
26
|
+
|
|
27
|
+
def format(self, record):
|
|
28
|
+
msg = super().format(record)
|
|
29
|
+
if self.use_color:
|
|
30
|
+
levelname = record.levelname
|
|
31
|
+
if hasattr(record, "color"):
|
|
32
|
+
return f"{record.color}{msg}{COLORS['RESET']}"
|
|
33
|
+
if levelname in COLORS:
|
|
34
|
+
return f"{COLORS[levelname]}{msg}{COLORS['RESET']}"
|
|
35
|
+
return msg
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
def __init_logger__(log_path:str):
|
|
40
|
+
"""Init logger depending on log_path (and therefor run_mode)
|
|
41
|
+
|
|
42
|
+
Args:
|
|
43
|
+
log_path (str): Full path of logger file
|
|
44
|
+
"""
|
|
45
|
+
global log
|
|
46
|
+
#logging.config.fileConfig(path.join(ROJECT_DIR,'log_conf.yaml'))
|
|
47
|
+
with open(path.join(ROJECT_DIR,'log_conf.yaml'), "rt") as f:
|
|
48
|
+
config = yaml.safe_load(f.read())
|
|
49
|
+
if verbose:
|
|
50
|
+
config['handlers']['console']['level']='DEBUG'
|
|
51
|
+
logging.config.dictConfig(config)
|
|
52
|
+
formatter = logging.Formatter('%(levelname)s %(asctime)s: %(message)s')
|
|
53
|
+
file_handler = logging.FileHandler(log_path)
|
|
54
|
+
|
|
55
|
+
if verbose:
|
|
56
|
+
file_handler.setLevel(logging.DEBUG)
|
|
57
|
+
else:
|
|
58
|
+
file_handler.setLevel(logging.INFO)
|
|
59
|
+
file_handler.setFormatter(formatter)
|
|
60
|
+
|
|
61
|
+
# create logger
|
|
62
|
+
log = logging.getLogger('s2lp')
|
|
63
|
+
log.addHandler(file_handler)
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def print_log(message:str, level:str, col=None):
|
|
67
|
+
"""Print and log messages
|
|
68
|
+
|
|
69
|
+
Args:
|
|
70
|
+
message (str): Message
|
|
71
|
+
level (str): level of the message (info, error or debug)
|
|
72
|
+
"""
|
|
73
|
+
if not verbose and level != "debug":
|
|
74
|
+
if col:
|
|
75
|
+
print(col + message + color.reset)
|
|
76
|
+
else:
|
|
77
|
+
print(message)
|
|
78
|
+
else:
|
|
79
|
+
pass
|
|
80
|
+
|
|
81
|
+
match level:
|
|
82
|
+
case "info":
|
|
83
|
+
if col:
|
|
84
|
+
log.info(message, extra={"color": col})
|
|
85
|
+
else:
|
|
86
|
+
log.info(message)
|
|
87
|
+
case "debug":
|
|
88
|
+
log.debug(message)
|
|
89
|
+
case "warning":
|
|
90
|
+
log.warning(message)
|
|
91
|
+
case "error":
|
|
92
|
+
log.error(message)
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def get_logger(sbml_file:str, short_option:str, debug:bool=False):
|
|
97
|
+
global log
|
|
98
|
+
global verbose
|
|
99
|
+
verbose=debug
|
|
100
|
+
net_name = f'{path.splitext(path.basename(sbml_file))[0]}'
|
|
101
|
+
filename = f'{net_name}_{short_option}.log'
|
|
102
|
+
log_path = path.join(LOG_DIR, filename)
|
|
103
|
+
if file.existing_file(log_path):
|
|
104
|
+
file.delete(log_path)
|
|
105
|
+
__init_logger__(log_path)
|
|
106
|
+
log.info(f"Seed2LP version: {__version__}")
|
|
107
|
+
|
|
108
|
+
|
|
109
|
+
def set_log_dir(value):
|
|
110
|
+
global LOG_DIR
|
|
111
|
+
LOG_DIR = value
|
|
112
|
+
|
seed2lp/metabolite.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# Object Metabolite constitued of:
|
|
2
|
+
# - name (str): Name of the metabolite
|
|
3
|
+
# - stoichiometry (int): Stoiciometry of the metabolite in the reaction eaquation if linked into a reaction
|
|
4
|
+
# (not set for targets or possible seeds or forbidden seeds)
|
|
5
|
+
# - compartment (str): character of the compartment of metabolite
|
|
6
|
+
|
|
7
|
+
class Metabolite:
|
|
8
|
+
def __init__(self, id_meta:str, name:str, stoichiometry:float=None, meta_type:str="",
|
|
9
|
+
species:str=""):
|
|
10
|
+
"""Initialize Object Metabolite
|
|
11
|
+
|
|
12
|
+
Args:
|
|
13
|
+
name (str): Name / ID of the Metabolite
|
|
14
|
+
stoichiometry (int, optional): Stoichiometry of the metabolite if into a reactions. Defaults to None.
|
|
15
|
+
"""
|
|
16
|
+
self.id_meta = id_meta
|
|
17
|
+
self.name = name
|
|
18
|
+
self.stoichiometry = stoichiometry
|
|
19
|
+
self.type = meta_type
|
|
20
|
+
self.species = species
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
######################## METHODS ########################
|
|
24
|
+
def convert_to_facts(self, metabolite_type:str, reaction_name:str=None):
|
|
25
|
+
"""Convert metabolite into ASP facts : an atom reactant or product, associated to a reaction
|
|
26
|
+
and having a stoichiometry value
|
|
27
|
+
|
|
28
|
+
Args:
|
|
29
|
+
metabolite_type (str): Type of metabolite (exchange, transport, other)
|
|
30
|
+
reaction_name (str, optional): Name of the reaction associated to the metabolite. Defaults to None.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
facts (str): The ASP atom created
|
|
34
|
+
"""
|
|
35
|
+
facts = ""
|
|
36
|
+
match metabolite_type:
|
|
37
|
+
case "reactant"|"product":
|
|
38
|
+
|
|
39
|
+
facts += f'{metabolite_type}("{self.id_meta}","{"{:.10f}".format(self.stoichiometry)}","{reaction_name}","{self.type}","{self.name}","{self.species}").\n'
|
|
40
|
+
case "seed":
|
|
41
|
+
facts += f'{metabolite_type}("{self.id_meta}","{self.type}","{self.name}").\n'
|
|
42
|
+
case _:
|
|
43
|
+
facts += f'{metabolite_type}("{self.id_meta}","{"{:.10f}".format(self.stoichiometry)}","{reaction_name}","{self.type}","{self.name}","{self.species}").\n'
|
|
44
|
+
return facts
|
|
45
|
+
|
|
46
|
+
########################################################
|