bfee2 2.5.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.
Potentially problematic release.
This version of bfee2 might be problematic. Click here for more details.
- BFEE2/__init__.py +0 -0
- BFEE2/commonTools/__init__.py +0 -0
- BFEE2/commonTools/commonSlots.py +48 -0
- BFEE2/commonTools/fileParser.py +327 -0
- BFEE2/commonTools/ploter.py +218 -0
- BFEE2/doc/Doc.pdf +0 -0
- BFEE2/doc/__init__.py +1 -0
- BFEE2/gui.py +2136 -0
- BFEE2/inputGenerator.py +2857 -0
- BFEE2/postTreatment.py +502 -0
- BFEE2/templates_gromacs/000.colvars.template +37 -0
- BFEE2/templates_gromacs/000.generate_tpr_sh.template +31 -0
- BFEE2/templates_gromacs/000.mdp.template +70 -0
- BFEE2/templates_gromacs/001.colvars.template +76 -0
- BFEE2/templates_gromacs/001.generate_tpr_sh.template +31 -0
- BFEE2/templates_gromacs/001.mdp.template +70 -0
- BFEE2/templates_gromacs/001.readme.template +1 -0
- BFEE2/templates_gromacs/002.colvars.template +101 -0
- BFEE2/templates_gromacs/002.generate_tpr_sh.template +31 -0
- BFEE2/templates_gromacs/002.mdp.template +70 -0
- BFEE2/templates_gromacs/003.colvars.template +125 -0
- BFEE2/templates_gromacs/003.generate_tpr_sh.template +36 -0
- BFEE2/templates_gromacs/003.mdp.template +70 -0
- BFEE2/templates_gromacs/004.colvars.template +148 -0
- BFEE2/templates_gromacs/004.generate_tpr_sh.template +37 -0
- BFEE2/templates_gromacs/004.mdp.template +70 -0
- BFEE2/templates_gromacs/005.colvars.template +170 -0
- BFEE2/templates_gromacs/005.generate_tpr_sh.template +38 -0
- BFEE2/templates_gromacs/005.mdp.template +70 -0
- BFEE2/templates_gromacs/006.colvars.template +192 -0
- BFEE2/templates_gromacs/006.generate_tpr_sh.template +39 -0
- BFEE2/templates_gromacs/006.mdp.template +70 -0
- BFEE2/templates_gromacs/007.colvars.template +210 -0
- BFEE2/templates_gromacs/007.generate_tpr_sh.template +40 -0
- BFEE2/templates_gromacs/007.mdp.template +69 -0
- BFEE2/templates_gromacs/007_eq.colvars.template +169 -0
- BFEE2/templates_gromacs/007_eq.generate_tpr_sh.template +64 -0
- BFEE2/templates_gromacs/007_min.mdp.template +58 -0
- BFEE2/templates_gromacs/008.colvars.template +42 -0
- BFEE2/templates_gromacs/008.generate_tpr_sh.template +31 -0
- BFEE2/templates_gromacs/008.mdp.template +70 -0
- BFEE2/templates_gromacs/008_eq.generate_tpr_sh.template +31 -0
- BFEE2/templates_gromacs/BFEEGromacs.py +1244 -0
- BFEE2/templates_gromacs/__init__.py +0 -0
- BFEE2/templates_gromacs/find_min_max.awk +27 -0
- BFEE2/templates_namd/__init__.py +0 -0
- BFEE2/templates_namd/configTemplate.py +1094 -0
- BFEE2/templates_namd/fep.tcl +299 -0
- BFEE2/templates_namd/scriptTemplate.py +149 -0
- BFEE2/templates_namd/solvate.tcl +9 -0
- BFEE2/templates_namd/solvate_mem.tcl +9 -0
- BFEE2/templates_namd/updateCenters.py +311 -0
- BFEE2/templates_readme/Readme_Gromacs_Geometrical.txt +25 -0
- BFEE2/templates_readme/Readme_NAMD_Alchemical.txt +20 -0
- BFEE2/templates_readme/Readme_NAMD_Geometrical.txt +34 -0
- BFEE2/templates_readme/__init__.py +1 -0
- BFEE2/third_party/__init__.py +0 -0
- BFEE2/third_party/py_bar.py +335 -0
- BFEE2/version.py +2 -0
- bfee2-2.5.0.data/scripts/BFEE2Gui.py +18 -0
- bfee2-2.5.0.dist-info/LICENSE +677 -0
- bfee2-2.5.0.dist-info/METADATA +76 -0
- bfee2-2.5.0.dist-info/RECORD +65 -0
- bfee2-2.5.0.dist-info/WHEEL +5 -0
- bfee2-2.5.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,335 @@
|
|
|
1
|
+
from typing import List, Literal, Optional, Tuple
|
|
2
|
+
|
|
3
|
+
import numpy as np
|
|
4
|
+
from numpy.typing import NDArray
|
|
5
|
+
|
|
6
|
+
# boltzmann constant
|
|
7
|
+
BOLTZMANN = 0.0019872041
|
|
8
|
+
|
|
9
|
+
# type of FEP files
|
|
10
|
+
fep_type = Literal['forward', 'backward', 'double-wide']
|
|
11
|
+
|
|
12
|
+
class NAMDParser:
|
|
13
|
+
""" parse NAMD .fepout files and get the necessary data
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
def __init__(self, forward_file: str, backward_file: Optional[str] = '') -> None:
|
|
17
|
+
""" Read NAMD .fepout files. The end-user can either provide the bidirectional
|
|
18
|
+
.fepout files, or provide an .fepout file of the double-wide FEP simulation
|
|
19
|
+
|
|
20
|
+
Args:
|
|
21
|
+
forward_file (str): the fepout file for forward or double-wide simulation
|
|
22
|
+
backward_file (Optional[str], optional): the fepout file for backward simulation.
|
|
23
|
+
Defaults to ''.
|
|
24
|
+
"""
|
|
25
|
+
|
|
26
|
+
self._double_wide = False
|
|
27
|
+
if (backward_file == '') or (backward_file is None):
|
|
28
|
+
self._double_wide = True
|
|
29
|
+
|
|
30
|
+
# List[Tuple[float, float]], recording the boundaries of each window
|
|
31
|
+
# List[Tuple[NDArray, NDArray]], recording the deltaU of forward of
|
|
32
|
+
# backward simulations of each window
|
|
33
|
+
if not self._double_wide:
|
|
34
|
+
self._windows, self._deltaU_data = self._pair_bidirectionalData(
|
|
35
|
+
self._read_fepout(forward_file),
|
|
36
|
+
self._read_fepout(backward_file)
|
|
37
|
+
)
|
|
38
|
+
else:
|
|
39
|
+
self._windows, self._deltaU_data = self._read_double_wide_fepout(forward_file)
|
|
40
|
+
|
|
41
|
+
if len(self._windows) != len(self._deltaU_data):
|
|
42
|
+
raise RuntimeError('Internal numbers of windows and deltaU do not match! This is a bug!')
|
|
43
|
+
|
|
44
|
+
def _read_fepout(self, fepout_file: str) -> Tuple[List[Tuple[float, float]], List[NDArray]]:
|
|
45
|
+
""" Read an NAMD fepout file. Return the window and deltaU information
|
|
46
|
+
|
|
47
|
+
Args:
|
|
48
|
+
fepout_file (str): the path of the fepout file
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
Tuple[List[Tuple[float, float]], List[NDArray]]: List[Tuple[float, float]], recording
|
|
52
|
+
the boundaries of each window, and
|
|
53
|
+
List[NDArray], recording the deltaU
|
|
54
|
+
"""
|
|
55
|
+
|
|
56
|
+
windows = []
|
|
57
|
+
deltaU = []
|
|
58
|
+
with open(fepout_file, 'r') as input_fepout:
|
|
59
|
+
while True:
|
|
60
|
+
line = input_fepout.readline()
|
|
61
|
+
if not line:
|
|
62
|
+
break
|
|
63
|
+
|
|
64
|
+
if line.startswith('#NEW FEP WINDOW:'):
|
|
65
|
+
splitedLine = line.strip().split()
|
|
66
|
+
windows.append((float(splitedLine[6]), float(splitedLine[8])))
|
|
67
|
+
continue
|
|
68
|
+
|
|
69
|
+
if line.startswith('#STARTING COLLECTION'):
|
|
70
|
+
# collecting deltaU
|
|
71
|
+
deltaU_per_window = []
|
|
72
|
+
while True:
|
|
73
|
+
line = input_fepout.readline()
|
|
74
|
+
if line.startswith('FepEnergy:'):
|
|
75
|
+
splitedLine = line.strip().split()
|
|
76
|
+
deltaU_per_window.append(float(splitedLine[6]))
|
|
77
|
+
else:
|
|
78
|
+
deltaU.append(np.array(deltaU_per_window))
|
|
79
|
+
break
|
|
80
|
+
|
|
81
|
+
return windows, deltaU
|
|
82
|
+
|
|
83
|
+
def _read_double_wide_fepout(self, fepout_file: str) -> Tuple[List[Tuple[float, float]], List[Tuple[NDArray, NDArray]]]:
|
|
84
|
+
""" Read an NAMD double-wide fepout file. Return the window and bidirectional deltaU information
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
fepout_file (str): the path of the fepout file
|
|
88
|
+
|
|
89
|
+
Returns:
|
|
90
|
+
Tuple[List[Tuple[float, float]], List[Tuple[NDArray, NDArray]]]: recording the boundary and
|
|
91
|
+
deltaU of each window of
|
|
92
|
+
bidirectional simulations
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
windows = []
|
|
96
|
+
deltaU_forward = []
|
|
97
|
+
deltaU_backward = []
|
|
98
|
+
with open(fepout_file, 'r') as input_fepout:
|
|
99
|
+
# The first window samples forward only, the last window backward only
|
|
100
|
+
first_window = True
|
|
101
|
+
last_window = False
|
|
102
|
+
while True:
|
|
103
|
+
line = input_fepout.readline()
|
|
104
|
+
if not line:
|
|
105
|
+
break
|
|
106
|
+
|
|
107
|
+
if line.startswith('#NEW FEP WINDOW: LAMBDA SET TO 1') and windows != []:
|
|
108
|
+
last_window = True
|
|
109
|
+
if line.startswith('#NEW FEP WINDOW: LAMBDA SET TO 0 ') and windows != []:
|
|
110
|
+
last_window = True
|
|
111
|
+
|
|
112
|
+
if not last_window:
|
|
113
|
+
if line.startswith('#NEW FEP WINDOW:'):
|
|
114
|
+
splitedLine = line.strip().split()
|
|
115
|
+
windows.append((float(splitedLine[6]), float(splitedLine[8])))
|
|
116
|
+
continue
|
|
117
|
+
|
|
118
|
+
if line.startswith('#STARTING COLLECTION'):
|
|
119
|
+
# collecting deltaU
|
|
120
|
+
deltaU_forward_per_window = []
|
|
121
|
+
deltaU_backward_per_window = []
|
|
122
|
+
while True:
|
|
123
|
+
line = input_fepout.readline()
|
|
124
|
+
if line.startswith('FepEnergy:'):
|
|
125
|
+
splitedLine = line.strip().split()
|
|
126
|
+
if not last_window:
|
|
127
|
+
deltaU_forward_per_window.append(float(splitedLine[6]))
|
|
128
|
+
else:
|
|
129
|
+
deltaU_backward_per_window.append(float(splitedLine[6]))
|
|
130
|
+
elif line.startswith('FepE_back:'):
|
|
131
|
+
splitedLine = line.strip().split()
|
|
132
|
+
deltaU_backward_per_window.append(float(splitedLine[6]))
|
|
133
|
+
else:
|
|
134
|
+
if deltaU_forward_per_window != []:
|
|
135
|
+
deltaU_forward.append(np.array(deltaU_forward_per_window))
|
|
136
|
+
if deltaU_backward_per_window != []:
|
|
137
|
+
deltaU_backward.append(np.array(deltaU_backward_per_window))
|
|
138
|
+
break
|
|
139
|
+
|
|
140
|
+
if line.startswith('#Free energy change for lambda window'):
|
|
141
|
+
first_window = False
|
|
142
|
+
last_window = False
|
|
143
|
+
|
|
144
|
+
if len(deltaU_forward) != len(deltaU_backward):
|
|
145
|
+
raise RuntimeError('Forward and backward data do not match!')
|
|
146
|
+
|
|
147
|
+
deltaU = []
|
|
148
|
+
for i in range(len(deltaU_forward)):
|
|
149
|
+
deltaU.append((np.array(deltaU_forward[i]), np.array(deltaU_backward[i])))
|
|
150
|
+
|
|
151
|
+
return windows, deltaU
|
|
152
|
+
|
|
153
|
+
def _pair_bidirectionalData(
|
|
154
|
+
self,
|
|
155
|
+
forward_data: Tuple[List[Tuple[float, float]], List[NDArray]],
|
|
156
|
+
backward_data: Tuple[List[Tuple[float, float]], List[NDArray]]
|
|
157
|
+
) -> Tuple[List[Tuple[float, float]], List[Tuple[NDArray, NDArray]]]:
|
|
158
|
+
""" pair data from bidirectional simulations
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
forward_data (Tuple[List[Tuple[float, float]], List[NDArray]]): data from forward simulation
|
|
162
|
+
backward_data (Tuple[List[Tuple[float, float]], List[NDArray]]): data from backward simulation
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
Tuple[List[Tuple[float, float]], List[Tuple[NDArray, NDArray]]]: recording the boundary and
|
|
166
|
+
deltaU of each window of
|
|
167
|
+
bidirectional simulations
|
|
168
|
+
"""
|
|
169
|
+
|
|
170
|
+
merged_data = []
|
|
171
|
+
|
|
172
|
+
for i in range(len(forward_data[0])):
|
|
173
|
+
for j in range(len(backward_data[0])):
|
|
174
|
+
if forward_data[0][i][0] == backward_data[0][j][1] and \
|
|
175
|
+
forward_data[0][i][1] == backward_data[0][j][0]:
|
|
176
|
+
merged_data.append((forward_data[1][i], backward_data[1][j]))
|
|
177
|
+
break
|
|
178
|
+
else:
|
|
179
|
+
raise RuntimeError('Error! the forward and backward files do not match!')
|
|
180
|
+
|
|
181
|
+
return forward_data[0], merged_data
|
|
182
|
+
|
|
183
|
+
def get_data(self) -> Tuple[List[Tuple[float, float]], List[Tuple[NDArray, NDArray]]]:
|
|
184
|
+
""" return the boundary and deltaU of each window
|
|
185
|
+
|
|
186
|
+
Returns:
|
|
187
|
+
Tuple[List[Tuple[float, float]], List[Tuple[NDArray, NDArray]]]: recording the boundary and
|
|
188
|
+
deltaU of each window of
|
|
189
|
+
bidirectional simulations
|
|
190
|
+
"""
|
|
191
|
+
|
|
192
|
+
return self._windows, self._deltaU_data
|
|
193
|
+
|
|
194
|
+
class FEPAnalyzer:
|
|
195
|
+
""" Analyze FEP simulations
|
|
196
|
+
"""
|
|
197
|
+
|
|
198
|
+
def __init__(
|
|
199
|
+
self,
|
|
200
|
+
window_boundaries: List[Tuple[float, float]],
|
|
201
|
+
deltaU_data: List[Tuple[NDArray, NDArray]],
|
|
202
|
+
temperature: float,
|
|
203
|
+
) -> None:
|
|
204
|
+
"""_summary_
|
|
205
|
+
|
|
206
|
+
Args:
|
|
207
|
+
window_boundaries (List[Tuple[float, float]]): boundaries of each window
|
|
208
|
+
deltaU_data (List[Tuple[NDArray, NDArray]]): deltaU for forward and backward simulations
|
|
209
|
+
of each window. The two deltaU should be opposite
|
|
210
|
+
numbers.
|
|
211
|
+
temperature (float): temperature of the simulation
|
|
212
|
+
"""
|
|
213
|
+
self._windows, self._deltaU_data = window_boundaries, deltaU_data
|
|
214
|
+
self._temperature = temperature
|
|
215
|
+
if len(self._windows) != len(self._deltaU_data):
|
|
216
|
+
raise RuntimeError('Internal numbers of windows and deltaU do not match! This is a bug!')
|
|
217
|
+
|
|
218
|
+
def FEP_free_energy(self) -> Tuple[List[Tuple[float, float]], List[NDArray], List[NDArray]]:
|
|
219
|
+
""" Calculate and return the free-energy change using the FEP equation
|
|
220
|
+
|
|
221
|
+
Returns:
|
|
222
|
+
Tuple[List[Tuple[float, float]], List[NDArray], List[NDArray]]: window boundaries, free energies and errors
|
|
223
|
+
"""
|
|
224
|
+
|
|
225
|
+
free_energies = []
|
|
226
|
+
errors = []
|
|
227
|
+
for i in range(len(self._windows)):
|
|
228
|
+
forward_free_energy = -BOLTZMANN * self._temperature * \
|
|
229
|
+
np.log(np.mean(np.exp(-self._deltaU_data[i][0] / (BOLTZMANN * self._temperature))))
|
|
230
|
+
backward_free_energy = -BOLTZMANN * self._temperature * \
|
|
231
|
+
np.log(np.mean(np.exp(-self._deltaU_data[i][1] / (BOLTZMANN * self._temperature))))
|
|
232
|
+
free_energies.append((forward_free_energy - backward_free_energy) / 2)
|
|
233
|
+
errors.append((forward_free_energy + backward_free_energy) / np.sqrt(2))
|
|
234
|
+
return self._windows, free_energies, errors
|
|
235
|
+
|
|
236
|
+
def BAR_free_energy(
|
|
237
|
+
self,
|
|
238
|
+
tolerance: float = 1e-6,
|
|
239
|
+
block_size: int = 20,
|
|
240
|
+
n_bootstrap: int = 20,
|
|
241
|
+
) -> Tuple[List[Tuple[float, float]], List[NDArray], List[NDArray]]:
|
|
242
|
+
""" Calculate and return the free-energy change using the BAR estimator
|
|
243
|
+
|
|
244
|
+
Args:
|
|
245
|
+
tolerance (float): tolerance of the SCF. Default to 1e-6.
|
|
246
|
+
block_size (int): the size of the block in block bootstrap. Default to 10.
|
|
247
|
+
n_bootstrap (int): number of bootstrap samples. Default to 20.
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
Tuple[List[Tuple[float, float]], List[NDArray], List[NDArray]]: window boundaries, free energies and errors
|
|
251
|
+
"""
|
|
252
|
+
|
|
253
|
+
free_energies = []
|
|
254
|
+
errors = []
|
|
255
|
+
for i in range(len(self._windows)):
|
|
256
|
+
dA = self._BAR_estimator(self._deltaU_data[i], tolerance)
|
|
257
|
+
err = self._BAR_error_estimator(self._deltaU_data[i], tolerance, block_size, n_bootstrap)
|
|
258
|
+
|
|
259
|
+
free_energies.append(dA)
|
|
260
|
+
errors.append(err)
|
|
261
|
+
return self._windows, free_energies, errors
|
|
262
|
+
|
|
263
|
+
def _BAR_estimator(self, deltaU: Tuple[NDArray, NDArray], tolerance: float = 1e-6) -> float:
|
|
264
|
+
""" Estimate the free energy of a window using the BAR estimator
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
Tuple[NDArray, NDArray]: deltaU data of forward and backward simulations
|
|
268
|
+
tolerance (float): tolerance of the SCF. Default to 1e-6.
|
|
269
|
+
|
|
270
|
+
Returns:
|
|
271
|
+
float: free energy change
|
|
272
|
+
"""
|
|
273
|
+
|
|
274
|
+
def fermi(x):
|
|
275
|
+
return 1 / (1 + np.exp(x))
|
|
276
|
+
|
|
277
|
+
beta = 1 / (BOLTZMANN * self._temperature)
|
|
278
|
+
c = 0
|
|
279
|
+
# BAR estimator
|
|
280
|
+
exp_beta_dA = np.mean(fermi(beta * (deltaU[0] - c))) / np.mean(fermi(beta * (deltaU[1] + c)))
|
|
281
|
+
dA = np.log(exp_beta_dA) / (-beta) + c
|
|
282
|
+
|
|
283
|
+
while np.abs(c - dA) > tolerance:
|
|
284
|
+
c = dA
|
|
285
|
+
# BAR estimator
|
|
286
|
+
exp_beta_dA = np.mean(fermi(beta * (deltaU[0] - c))) / np.mean(fermi(beta * (deltaU[1] + c)))
|
|
287
|
+
dA = np.log(exp_beta_dA) / (-beta) + c
|
|
288
|
+
|
|
289
|
+
return dA
|
|
290
|
+
|
|
291
|
+
def _BAR_error_estimator(
|
|
292
|
+
self,
|
|
293
|
+
deltaU: Tuple[NDArray, NDArray],
|
|
294
|
+
tolerance: float = 1e-6,
|
|
295
|
+
block_size: int = 20,
|
|
296
|
+
n_bootstrap: int = 20
|
|
297
|
+
) -> float:
|
|
298
|
+
""" Estimate the error of the free energy estimate of a window
|
|
299
|
+
using the BAR estimator and block bootstrap method
|
|
300
|
+
|
|
301
|
+
Args:
|
|
302
|
+
Tuple[NDArray, NDArray]: deltaU data of forward and backward simulations
|
|
303
|
+
tolerance (float): tolerance of the SCF. Default to 1e-6.
|
|
304
|
+
block_size (int): the size of the block in block bootstrap. Default to 10.
|
|
305
|
+
n_bootstrap (int): number of bootstrap samples. Default to 20.
|
|
306
|
+
|
|
307
|
+
Returns:
|
|
308
|
+
float: error of the free-energy estimator
|
|
309
|
+
"""
|
|
310
|
+
|
|
311
|
+
forward_size = len(deltaU[0])
|
|
312
|
+
backward_size = len(deltaU[1])
|
|
313
|
+
bootstrap_samples = int(np.max((forward_size, backward_size)) / block_size)
|
|
314
|
+
|
|
315
|
+
if bootstrap_samples < 1:
|
|
316
|
+
raise RuntimeError('Error! block_size larger than sample size!')
|
|
317
|
+
|
|
318
|
+
# block bootstrap
|
|
319
|
+
estimates = np.zeros(n_bootstrap)
|
|
320
|
+
|
|
321
|
+
for i in range(n_bootstrap):
|
|
322
|
+
forward_bootstrap = np.zeros(bootstrap_samples * block_size, dtype=int)
|
|
323
|
+
for idx, j in enumerate(np.random.randint(0, forward_size - block_size - 1, bootstrap_samples)):
|
|
324
|
+
forward_bootstrap[idx*block_size:idx*block_size+block_size] = j + np.arange(block_size)
|
|
325
|
+
|
|
326
|
+
backward_bootstrap = np.zeros(bootstrap_samples * block_size, dtype=int)
|
|
327
|
+
for idx, j in enumerate(np.random.randint(0, backward_size - block_size - 1, bootstrap_samples)):
|
|
328
|
+
backward_bootstrap[idx*block_size:idx*block_size+block_size] = j + np.arange(block_size)
|
|
329
|
+
|
|
330
|
+
estimates[i] = self._BAR_estimator(
|
|
331
|
+
(deltaU[0][forward_bootstrap], deltaU[1][backward_bootstrap]),
|
|
332
|
+
tolerance
|
|
333
|
+
)
|
|
334
|
+
|
|
335
|
+
return np.std(estimates)
|
BFEE2/version.py
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
#!python
|
|
2
|
+
###################################################
|
|
3
|
+
## binding free energy estimator (BFEE) v2.x
|
|
4
|
+
## by Haohao Fu (fhh2626_at_gmail.com)
|
|
5
|
+
##
|
|
6
|
+
## this is a completely rewritten version of BFEE
|
|
7
|
+
##
|
|
8
|
+
###################################################
|
|
9
|
+
|
|
10
|
+
import sys
|
|
11
|
+
from PySide2.QtWidgets import QApplication
|
|
12
|
+
import BFEE2.gui as gui
|
|
13
|
+
|
|
14
|
+
if __name__ == '__main__':
|
|
15
|
+
|
|
16
|
+
app = QApplication(sys.argv)
|
|
17
|
+
ex = gui.mainUI()
|
|
18
|
+
sys.exit(app.exec_())
|