9
9
from .fva import regularFVA
10
10
from .utils import load_dataframe , load_model , set_objective
11
11
from .io import suppress_stdout
12
+ from .vffva import veryFastFVA
12
13
13
14
14
15
def compute_nmpcs (
@@ -27,7 +28,13 @@ def compute_nmpcs(
27
28
force = False ,
28
29
threshold = 1e-5 ,
29
30
write_to_file = True ,
31
+ fva_type = "regular" ,
32
+ obj_optimality = 100 ,
30
33
):
34
+ assert fva_type == "regular" or fva_type == "fast" , (
35
+ "FVA type must be either `regular` or `fast`! Received %s" % fva_type
36
+ )
37
+
31
38
start = time .time ()
32
39
out_dir = out_dir + "/" if out_dir [- 1 ] != "/" else out_dir
33
40
Path (out_dir ).mkdir (exist_ok = True )
@@ -36,9 +43,15 @@ def compute_nmpcs(
36
43
objective_out_file = out_dir + objective_out_file
37
44
fluxes_out_file = out_dir + fluxes_out_file
38
45
39
- nmpcs = pd .DataFrame () if force or not write_to_file else load_dataframe (out_file , return_empty = True )
46
+ nmpcs = (
47
+ pd .DataFrame ()
48
+ if force or not write_to_file
49
+ else load_dataframe (out_file , return_empty = True )
50
+ )
40
51
all_fluxes = (
41
- pd .DataFrame () if force or not write_to_file else load_dataframe (fluxes_out_file , return_empty = True )
52
+ pd .DataFrame ()
53
+ if force or not write_to_file
54
+ else load_dataframe (fluxes_out_file , return_empty = True )
42
55
)
43
56
obj_values = (
44
57
pd .DataFrame ()
@@ -51,6 +64,11 @@ def compute_nmpcs(
51
64
52
65
try :
53
66
models = [load_model (samples )]
67
+
68
+ # Skip models that already exist
69
+ if models [0 ].name in list (nmpcs .columns ) and not force :
70
+ print ("NMPCs for %s already exist in file!" % models [0 ].name )
71
+ return
54
72
except Exception :
55
73
models = (
56
74
samples
@@ -60,12 +78,14 @@ def compute_nmpcs(
60
78
for m in os .listdir (os .path .dirname (samples ))
61
79
]
62
80
)
63
- models = [
64
- f
65
- for f in models
66
- if not isinstance (f , str )
67
- or os .path .basename (f ).split ("." )[0 ] not in list (nmpcs .columns )
68
- ]
81
+
82
+ # Skip models that already exist
83
+ models = [
84
+ f
85
+ for f in models
86
+ if not isinstance (f , str )
87
+ or os .path .basename (f ).split ("." )[0 ] not in list (nmpcs .columns )
88
+ ]
69
89
threads = os .cpu_count () - 1 if threads == - 1 else threads
70
90
71
91
print ("Computing NMPCs on %s models..." % len (models ))
@@ -80,6 +100,11 @@ def compute_nmpcs(
80
100
print ("------------------------------------------" )
81
101
82
102
for s in tqdm .tqdm (models , total = len (models )):
103
+ if fva_type == "fast" :
104
+ assert isinstance (
105
+ s , str
106
+ ), "For fast fva, `samples` param must be directory or list of model paths."
107
+ model_path = s
83
108
with suppress_stdout ():
84
109
m = load_model (path = s , solver = solver )
85
110
if not isinstance (m , optlang .interface .Model ):
@@ -93,43 +118,53 @@ def compute_nmpcs(
93
118
m .variables ["communityBiomass" ].set_bounds (0.4 , 1 )
94
119
set_objective (m , m .variables ["communityBiomass" ], direction = "max" )
95
120
96
- with suppress_stdout ():
97
- m .optimize ()
98
- if m .status == "infeasible" :
99
- logging .warning ("%s model is infeasible!" % m .name )
100
- continue
101
-
102
- obj_val = round (m .objective .value , 5 )
103
- obj_values .loc [m .name ] = obj_val
104
- if "ObjectiveConstraint" in m .constraints :
105
- m .remove (m .constraints ["ObjectiveConstraint" ])
106
- m .update ()
107
- obj_const = m .interface .Constraint (
108
- expression = m .objective .expression ,
109
- lb = obj_val ,
110
- ub = obj_val ,
111
- name = "ObjectiveConstraint" ,
112
- )
113
- m .add (obj_const )
114
- m .update ()
115
-
116
121
# Now perform FVA under constrained objective value
117
- with suppress_stdout ():
118
- try :
122
+ try :
123
+ if fva_type == "regular" :
124
+ with suppress_stdout ():
125
+ m .optimize ()
126
+ if m .status == "infeasible" :
127
+ logging .warning ("%s model is infeasible!" % m .name )
128
+ continue
129
+
130
+ obj_val = round (m .objective .value , 5 )
131
+ obj_values .loc [m .name ] = obj_val
132
+ if "ObjectiveConstraint" in m .constraints :
133
+ m .remove (m .constraints ["ObjectiveConstraint" ])
134
+ m .update ()
135
+ obj_const = m .interface .Constraint (
136
+ expression = m .objective .expression ,
137
+ lb = obj_val * (obj_optimality / 100 ),
138
+ ub = obj_val ,
139
+ name = "ObjectiveConstraint" ,
140
+ )
141
+ m .add (obj_const )
142
+ m .update ()
119
143
res = regularFVA (
120
144
m ,
121
145
reactions = reactions ,
122
146
regex = regex ,
123
147
ex_only = ex_only ,
124
148
solver = solver ,
125
- threads = threads ,
149
+ threads = threads if parallel else 1 ,
126
150
parallel = parallel ,
127
151
write_to_file = False ,
128
- threshold = threshold
152
+ threshold = threshold ,
129
153
)
130
- except Exception :
131
- logging .warning ("Cannot solve %s model!" % m .name )
132
- continue
154
+ elif fva_type == "fast" :
155
+ res = veryFastFVA (
156
+ model = m ,
157
+ path = model_path ,
158
+ reactions = reactions ,
159
+ regex = regex ,
160
+ nCores = threads if parallel else 1 ,
161
+ nThreads = 1 ,
162
+ optPerc = obj_optimality ,
163
+ threshold = threshold ,
164
+ )
165
+ except Exception as e :
166
+ logging .warning (f"Cannot solve { m .name } model!\n { e } " )
167
+ continue
133
168
if res is None :
134
169
return
135
170
res ["sample_id" ] = m .name
@@ -158,9 +193,9 @@ def compute_nmpcs(
158
193
all_fluxes .to_csv (fluxes_out_file )
159
194
160
195
res = namedtuple ("res" , "nmpc objectives fluxes" )
161
-
196
+
162
197
print ("-------------------------------------------------------" )
163
- print (' Finished computing NMPCs!' )
164
- print (' Process took %s minutes to run...' % round ((time .time ()- start )/ 60 ,3 ))
198
+ print (" Finished computing NMPCs!" )
199
+ print (" Process took %s minutes to run..." % round ((time .time () - start ) / 60 , 3 ))
165
200
166
- return res (nmpcs , obj_values , all_fluxes )
201
+ return res (nmpcs , obj_values , all_fluxes )
0 commit comments