Skip to content

Commit 7652f97

Browse files
committed
Update win_env.yml & added optional GUI QThread API run function
1 parent bb1e7f4 commit 7652f97

File tree

2 files changed

+75
-54
lines changed

2 files changed

+75
-54
lines changed

gui/PyPEFGUIQtWindow.py

Lines changed: 75 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from io import StringIO
88
import os
99
from PySide6 import QtCore, QtWidgets
10-
from PySide6.QtCore import QSize
10+
from PySide6.QtCore import QSize, Signal, QThread
1111
pypef_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))
1212
sys.path.append(pypef_root)
1313
from pypef import __version__
@@ -25,6 +25,21 @@
2525
print('Backend:', EXEC_API_OR_CLI)
2626

2727

28+
class ApiWorker(QThread):
29+
finished = Signal(str)
30+
31+
def __init__(self, cmd: str, parent=None):
32+
super().__init__(parent)
33+
self.cmd = cmd
34+
35+
def run(self):
36+
try:
37+
result = run_main(self.cmd)
38+
except Exception as e:
39+
result = f"Error: {str(e)}"
40+
self.finished.emit(result)
41+
42+
2843
class Capturing(list):
2944
"""https://stackoverflow.com/questions/16571150/how-to-capture-stdout-output-from-a-python-function-call"""
3045
def __enter__(self):
@@ -372,7 +387,34 @@ def __init__(
372387
)
373388
self.button_supervised_predict_onehot.clicked.connect(self.pypef_onehot_supervised_predict)
374389
self.button_supervised_predict_onehot.setStyleSheet(button_style)
375-
390+
# All buttons #######
391+
self.all_buttons = [
392+
self.button_work_dir,
393+
self.button_help,
394+
self.button_mklsts,
395+
self.button_mkps,
396+
self.button_dca_inference_gremlin,
397+
self.button_dca_inference_gremlin_msa_info,
398+
self.button_dca_test_dca,
399+
self.button_dca_predict_dca,
400+
self.button_hybrid_train_dca,
401+
self.button_hybrid_train_test_dca,
402+
self.button_hybrid_test_dca,
403+
self.button_hybrid_predict_dca,
404+
self.button_hybrid_train_dca_llm,
405+
self.button_hybrid_train_test_dca_llm,
406+
self.button_hybrid_test_dca_llm,
407+
self.button_hybrid_predict_dca_llm,
408+
self.button_supervised_train_dca,
409+
self.button_supervised_train_test_dca,
410+
self.button_supervised_test_dca,
411+
self.button_supervised_predict_dca,
412+
self.button_supervised_train_onehot,
413+
self.button_supervised_train_test_onehot,
414+
self.button_supervised_test_onehot,
415+
self.button_supervised_predict_onehot
416+
]
417+
######################
376418

377419
# Layout widgets ####################################################################
378420
# int fromRow, int fromColumn, int rowSpan, int columnSpan
@@ -433,67 +475,28 @@ def __init__(
433475
self.process = QtCore.QProcess(self)
434476
self.process.setProcessChannelMode(QtCore.QProcess.MergedChannels)
435477
self.process.readyReadStandardOutput.connect(self.on_readyReadStandardOutput)
436-
self.process.started.connect(lambda: self.button_work_dir.setEnabled(False))
437-
self.process.finished.connect(lambda: self.button_work_dir.setEnabled(True))
438-
self.process.started.connect(lambda: self.button_help.setEnabled(False))
439-
self.process.finished.connect(lambda: self.button_help.setEnabled(True))
440-
self.process.started.connect(lambda: self.button_mklsts.setEnabled(False))
441-
self.process.finished.connect(lambda: self.button_mklsts.setEnabled(True))
442-
self.process.started.connect(lambda: self.button_mkps.setEnabled(False))
443-
self.process.finished.connect(lambda: self.button_mkps.setEnabled(True))
444-
self.process.started.connect(lambda: self.button_dca_inference_gremlin.setEnabled(False))
445-
self.process.finished.connect(lambda: self.button_dca_inference_gremlin.setEnabled(True))
446-
self.process.started.connect(lambda: self.button_dca_inference_gremlin_msa_info.setEnabled(False))
447-
self.process.finished.connect(lambda: self.button_dca_inference_gremlin_msa_info.setEnabled(True))
448-
self.process.started.connect(lambda: self.button_dca_test_dca.setEnabled(False))
449-
self.process.finished.connect(lambda: self.button_dca_test_dca.setEnabled(True))
450-
self.process.started.connect(lambda: self.button_dca_predict_dca.setEnabled(False))
451-
self.process.finished.connect(lambda: self.button_dca_predict_dca.setEnabled(True))
452-
self.process.started.connect(lambda: self.button_hybrid_train_dca.setEnabled(False))
453-
self.process.finished.connect(lambda: self.button_hybrid_train_dca.setEnabled(True))
454-
self.process.started.connect(lambda: self.button_hybrid_train_test_dca.setEnabled(False))
455-
self.process.finished.connect(lambda: self.button_hybrid_train_test_dca.setEnabled(True))
456-
self.process.started.connect(lambda: self.button_hybrid_test_dca.setEnabled(False))
457-
self.process.finished.connect(lambda: self.button_hybrid_test_dca.setEnabled(True))
458-
self.process.started.connect(lambda: self.button_hybrid_predict_dca.setEnabled(False))
459-
self.process.finished.connect(lambda: self.button_hybrid_predict_dca.setEnabled(True))
460-
self.process.started.connect(lambda: self.button_hybrid_train_dca_llm.setEnabled(False))
461-
self.process.finished.connect(lambda: self.button_hybrid_train_dca_llm.setEnabled(True))
462-
self.process.started.connect(lambda: self.button_hybrid_train_test_dca_llm.setEnabled(False))
463-
self.process.finished.connect(lambda: self.button_hybrid_train_test_dca_llm.setEnabled(True))
464-
self.process.started.connect(lambda: self.button_hybrid_test_dca_llm.setEnabled(False))
465-
self.process.finished.connect(lambda: self.button_hybrid_test_dca_llm.setEnabled(True))
466-
self.process.started.connect(lambda: self.button_hybrid_predict_dca_llm.setEnabled(False))
467-
self.process.finished.connect(lambda: self.button_hybrid_predict_dca_llm.setEnabled(True))
468-
self.process.started.connect(lambda: self.button_supervised_train_dca.setEnabled(False))
469-
self.process.finished.connect(lambda: self.button_supervised_train_dca.setEnabled(True))
470-
self.process.started.connect(lambda: self.button_supervised_train_test_dca.setEnabled(False))
471-
self.process.finished.connect(lambda: self.button_supervised_train_test_dca.setEnabled(True))
472-
self.process.started.connect(lambda: self.button_supervised_test_dca.setEnabled(False))
473-
self.process.finished.connect(lambda: self.button_supervised_test_dca.setEnabled(True))
474-
self.process.started.connect(lambda: self.button_supervised_predict_dca.setEnabled(False))
475-
self.process.finished.connect(lambda: self.button_supervised_predict_dca.setEnabled(True))
476-
self.process.started.connect(lambda: self.button_supervised_train_onehot.setEnabled(False))
477-
self.process.finished.connect(lambda: self.button_supervised_train_onehot.setEnabled(True))
478-
self.process.started.connect(lambda: self.button_supervised_train_test_onehot.setEnabled(False))
479-
self.process.finished.connect(lambda: self.button_supervised_train_test_onehot.setEnabled(True))
480-
self.process.started.connect(lambda: self.button_supervised_test_onehot.setEnabled(False))
481-
self.process.finished.connect(lambda: self.button_supervised_test_onehot.setEnabled(True))
482-
self.process.started.connect(lambda: self.button_supervised_predict_onehot.setEnabled(False))
483-
self.process.finished.connect(lambda: self.button_supervised_predict_onehot.setEnabled(True))
478+
self.process.started.connect(lambda: self.toggle_buttons(False))
479+
self.process.finished.connect(lambda: self.toggle_buttons(True))
484480

485481

482+
483+
def toggle_buttons(self, enabled: bool):
484+
for btn in self.all_buttons:
485+
btn.setEnabled(enabled)
486+
486487
def start_process(self, button):
487488
self.logTextBox.widget.clear()
488489
self.c += 1
489490
self.logTextBox.widget.appendPlainText(f"Current working directory: {str(os.getcwd())}")
490491
self.logTextBox.widget.appendPlainText("Job: " + str(self.c) + " " + "=" * 104)
491492
if EXEC_API_OR_CLI == 'api':
492493
button.setEnabled(False)
494+
self.toggle_buttons(False)
493495

494496
def end_process(self, button):
495497
if EXEC_API_OR_CLI == 'api':
496498
button.setEnabled(True)
499+
self.toggle_buttons(True)
497500
self.version_text.setText("Finished...")
498501
self.textedit_out.append("=" * 104 + " Job: " + str(self.c) + "\n")
499502

@@ -893,9 +896,9 @@ def pypef_onehot_supervised_predict(self):
893896

894897
def exec_pypef(self, cmd):
895898
if EXEC_API_OR_CLI == 'api':
896-
return self.exec_pypef_api(cmd)
899+
self.exec_pypef_api2(cmd)
897900
elif EXEC_API_OR_CLI == 'cli':
898-
return self.exec_pypef_cli(cmd)
901+
self.exec_pypef_cli(cmd)
899902
else:
900903
raise SystemError("Choose between 'api' or 'cli'!")
901904

@@ -904,7 +907,11 @@ def exec_pypef_cli(self, cmd: str):
904907
self.process.start(f'python', ['-u', f'{self.pypef_root}/run.py'] + cmd.split(' '))
905908
self.process.finished.connect(self.process_finished)
906909

907-
def exec_pypef_api(self, cmd: str):
910+
def exec_pypef_api2(self, cmd: str):
911+
"""
912+
Backup function if threading function (exec_pypef_api) does not work.
913+
Freezes during run.
914+
"""
908915
self.textedit_out.append(f'Executing command:\n\t{cmd}')
909916
try:
910917
with Capturing() as captured_output:
@@ -914,8 +921,22 @@ def exec_pypef_api(self, cmd: str):
914921
except Exception as e: # anything
915922
self.textedit_out.append(f"Provided wrong inputs! Error:\n\t{e}")
916923

924+
def exec_pypef_api(self, cmd: str):
925+
"""
926+
Threaded API function.
927+
"""
928+
self.textedit_out.append(f"Executing command:\n\t{cmd}")
929+
self.thread = QThread()
930+
self.worker = ApiWorker(cmd=cmd)
931+
self.worker.moveToThread(self.thread)
932+
self.thread.started.connect(self.worker.run)
933+
self.worker.finished.connect(self.thread.quit)
934+
self.worker.finished.connect(self.worker.deleteLater)
935+
self.thread.finished.connect(self.thread.deleteLater)
936+
self.thread.start()
937+
917938
def process_finished(self):
918-
self.version_text.setText("Finished...")
939+
self.version_text.setText("Finished...")
919940

920941

921942
if __name__ == "__main__":

win_env.yml

-1.42 KB
Binary file not shown.

0 commit comments

Comments
 (0)