77from io import StringIO
88import os
99from PySide6 import QtCore , QtWidgets
10- from PySide6 .QtCore import QSize
10+ from PySide6 .QtCore import QSize , Signal , QThread
1111pypef_root = os .path .abspath (os .path .join (os .path .dirname (__file__ ), '..' ))
1212sys .path .append (pypef_root )
1313from pypef import __version__
2525print ('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+
2843class 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
921942if __name__ == "__main__" :
0 commit comments