From 64570f55c896e03d1e805de583b1b5e425496b59 Mon Sep 17 00:00:00 2001 From: chrin Date: Mon, 17 Jul 2023 09:54:41 +0200 Subject: [PATCH] utils.py --- base.py | 196 +++++++++++++------ guiframe.py | 488 +++++++++++++++++++++++++++++++---------------- sendelogframe.py | 8 +- utils.py | 12 ++ 4 files changed, 477 insertions(+), 227 deletions(-) create mode 100644 utils.py diff --git a/base.py b/base.py index 079ba87..dc7a8b0 100644 --- a/base.py +++ b/base.py @@ -25,6 +25,8 @@ from qtpy.QtWidgets import (QAction, QApplication, QDialog, QFrame, QLabel, QProgressBar, QScrollArea, QSizePolicy, QSplashScreen, QVBoxLayout, QWidget) + +from pyqtacc.bdbase.utils import _line from pyqtacc.bdbase.enumkind import Facility, MsgSeverity, UserMode from pyqtacc.bdbase.helpbrowser import HelpBrowser from pyqtacc.bdbase.readjson import ReadJSON @@ -36,6 +38,7 @@ from pyqtacc.bdbase.sendelog import QSendToELOG from pyqtacc.bdbase.screenshot import QScreenshot from pyqtacc.bdbase.guiframe import GUIFrame + from caqtwidgets.pvwidgets import QNoDockWidget import PyCafe @@ -45,18 +48,18 @@ _appname, _appext = _pymodule.split(".") _appversion = "1.0.0" _author = "J. Chrin" -PROGRESS_BAR_THREAD_INIT = 0 -PROGRESS_BAR_THREAD_START = 1 -PROGRESS_BAR_THREAD_ABORTING = 2 -PROGRESS_BAR_THREAD_ABORTED = 3 -PROGRESS_BAR_THREAD_ERROR = 4 -PROGRESS_BAR_THREAD_END = 100 +PROGRESS_THREAD_INIT = 0 +PROGRESS_THREAD_START = 1 +PROGRESS_THREAD_ABORTING = 2 +PROGRESS_THREAD_ABORTED = 3 +PROGRESS_THREAD_ERROR = 4 +PROGRESS_THREAD_END = 100 CENTRAL_WIDGET_MINIMUM_HEIGHT = 840 CENTRAL_WIDGET_MINIMUM_WIDTH = 1240 SLS_CENTRAL_WIDGET_MINIMUM_HEIGHT = 840 SLS_CENTRAL_WIDGET_MINIMUM_WIDTH = 940 - +''' def _line(): """Macro to return the current line number. @@ -67,7 +70,7 @@ def _line(): int: Current line number. """ return inspect.currentframe().f_back.f_lineno - +''' class BaseWindow(QMainWindow): """ BaseWindow @@ -91,14 +94,15 @@ class BaseWindow(QMainWindow): self.reanalysis_time = reanalysis_time self.all_data = self.parent.all_data - #def __del__(self): - # self.wait() + def __del__(self): + self.wait() def run(self): attach_files = [] folder_name = self.folder_name - print("Running SaveFigureThread, folder_name=", folder_name, flush=True) + print("Running SaveFigureThread, folder_name=", folder_name, + flush=True) date_str = self.parent.add_date_to_path( time_in_seconds=self.time_in_seconds, @@ -153,7 +157,7 @@ class BaseWindow(QMainWindow): print("All files attached", flush=True) else: print("No files to attach", flush=True) - time.sleep(0.2) #avoid race condition + time.sleep(0.1) #avoid race condition class HDFSave(QThread): """Thread for hdf analysis @@ -171,23 +175,28 @@ class BaseWindow(QMainWindow): """Run hdf thread """ QApplication.processEvents(QEventLoop.ExcludeUserInputEvents, 5000) + self.all_data = self.parent.all_data #Reanalysis data if self.all_data is not None: ts_in_seconds = self.all_data['Ambient data']['Time in seconds'] - now_in_seconds = self.all_data['Processed data'][ - 'Reanalysis time in seconds'] if \ - self.all_data['Processed data']['Reanalysis time'] else None + now_in_seconds = None + from_hdf = False + if 'Reanalysis time in seconds' in self.all_data['Processed data']: + from_hdf = bool(self.all_data['Processed data']['Reanalysis time']) + if from_hdf: + now_in_seconds = self.all_data['Processed data'][ + 'Reanalysis time in seconds'] + - from_hdf = bool( - self.all_data['Processed data']['Reanalysis time']) - - #print("Parent Thread before ==>", self.parent.hdf_filename) + if self.parent.hdf_filename is None or not self.from_dialog: self.parent.set_new_hdf_filename(ts_in_seconds, now_in_seconds) + + #else: # self.parent.set_new_hdf_filename(ts_in_seconds, # now_in_seconds) @@ -204,9 +213,11 @@ class BaseWindow(QMainWindow): self.parent.add_pvs_to_hdf( dataH5, pv_list=self.parent.pv_machine_list, from_hdf=from_hdf) + self.parent.add_general_to_hdf(dataH5) + self.parent.add_to_hdf(dataH5, proc=True, raw=True) - + self.parent.hdf_save_completed = True _mess = "Processed data saved to {}".format( @@ -240,12 +251,31 @@ class BaseWindow(QMainWindow): """Run hdf thread """ + + if not hasattr(self.analysis_procedure, 'load_hdf_file'): + mess = ("Analysis not configured for HDF analysis! " + + "Missing method: load_hdf_file") + self.parent.trigger_log_message.emit( + MsgSeverity.ERROR.name,_pymodule, _line(), mess, {}) + self.parent.trigger_progressbar.emit(PROGRESS_THREAD_END) + return + self.all_data = self.analysis_procedure.load_hdf_file( self.hdf_filename_loaded) + + if not self.all_data: + self.parent.trigger_progressbar.emit(PROGRESS_THREAD_END) return + if not hasattr(self.analysis_procedure, 'reanalyze'): + mess = ("Analysis not configured for HDF analysis! " + + "Missing method: reanalyze") + self.parent.trigger_log_message.emit( + MsgSeverity.ERROR.name, _pymodule, _line(), mess, {}) + self.parent.trigger_progressbar.emit(PROGRESS_THREAD_END) + return try: expt_dict = self.all_data['experiment'] except KeyError: @@ -283,11 +313,16 @@ class BaseWindow(QMainWindow): """ trigger_thread_event = Signal(dict) - def __init__(self, parent, analysis_procedure, input_parameters): + def __init__(self, parent, analysis_procedure, input_parameters, + messages: dict={ + "success": "Analysis completed", "fail": + "No data returned from analysis procedure"}): + QThread.__init__(self) self.parent = parent self.analysis_procedure = analysis_procedure self.input_parameters = input_parameters + self.messages = messages try: if input_parameters['debug']: print("AnalysisThread", self.input_parameters) @@ -300,7 +335,6 @@ class BaseWindow(QMainWindow): def run(self): """Run thread """ - all_dict = self.analysis_procedure.measure_and_analyze( self.input_parameters) @@ -308,12 +342,11 @@ class BaseWindow(QMainWindow): # Emit results if all_dict: self.trigger_thread_event.emit(all_dict) - - mess = "Analysis completed" + mess = self.messages['success'] self.parent.trigger_log_message.emit( MsgSeverity.INFO.name, _pymodule, _line(), mess, {}) else: - mess = "No data returned from analysis procedure." + mess = self.messages['fail'] self.parent.trigger_log_message.emit( MsgSeverity.WARN.name, _pymodule, _line(), mess, {}) @@ -454,7 +487,7 @@ class BaseWindow(QMainWindow): self.analysis_procedure = AnalysisProcedure(self) except ImportError as e: print(("Base class without user supplied AnalysisProcedure class." - + " mport Error:"), e) + + " import Error:"), e) ##self.trigger_elog_entry.connect(self.receive_elog_notification) ##self.trigger_hdf_save.connect(self.save_to_hdf) @@ -844,14 +877,15 @@ class BaseWindow(QMainWindow): return False if self.daq_analysis_completed and not self.hdf_save_completed: - if not self.all_data['Processed data']['Reanalysis time']: - _mess = ("Are you sure you wish to exit " + - "without saving data to HDF?") - qm = QMessageBox() - reply = qm.warning(self, "Exit", _mess, - QMessageBox.Yes | QMessageBox.No) - if reply == QMessageBox.No: - return False + if 'Reanalysis time' in self.all_data['Processed data']: + if not self.all_data['Processed data']['Reanalysis time']: + _mess = ("Are you sure you wish to exit " + + "without saving data to HDF?") + qm = QMessageBox() + reply = qm.warning(self, "Exit", _mess, + QMessageBox.Yes | QMessageBox.No) + if reply == QMessageBox.No: + return False return True @Slot() @@ -1038,9 +1072,11 @@ class BaseWindow(QMainWindow): return True - def add_to_hdf(self): # dataH5=None, proc=True, raw=False): - """ Abstract method to be overwritten by user + def add_to_hdf(self, dataH5=None, proc=True, raw=False): + """ Abstract method to be overwritten by user. Optional. """ + return + ''' QM = QMessageBox() QM.setText( str(NotImplementedError("add_to_hdf method has not been " + @@ -1049,6 +1085,7 @@ class BaseWindow(QMainWindow): "icon from the application/config file.")) ) QM.exec() + ''' @Slot() def save_to_hdf(self): @@ -1180,9 +1217,11 @@ class BaseWindow(QMainWindow): #input_options['Comment'] = 'Please enter a comment' if self.all_data is not None: ts_in_seconds = self.all_data['Ambient data']['Time in seconds'] - now_in_seconds = self.all_data['Processed data'][ - 'Reanalysis time in seconds'] if \ - self.all_data['Processed data']['Reanalysis time'] else None + now_in_seconds = None + if 'Reanalysis time in seconds' in self.all_data['Processed data']: + if self.all_data['Processed data']['Reanalysis time']: + now_in_seconds = self.all_data['Processed data'][ + 'Reanalysis time in seconds'] self.set_new_hdf_filename(ts_in_seconds, now_in_seconds) input_options['Destination'] = self.hdf_filename @@ -1356,9 +1395,10 @@ class BaseWindow(QMainWindow): """ if self.all_data: #Data from hdf analysis - do not save to epics - if self.all_data['Processed data']['Reanalysis time']: - print("HDF RUN - data not written to epics") - return False + if 'Reanalysis time' in self.all_data['Processed data']: + if self.all_data['Processed data']['Reanalysis time']: + print("HDF RUN - data not written to epics") + return False if self.all_data['Input data']['simulation']: return False else: @@ -1565,8 +1605,8 @@ class BaseWindow(QMainWindow): self.progressbar_abort = "abort" self.progressbar_color = self.progressbar_standard self.progressbar.setObjectName(self.progressbar_color) - self.progressbar.setRange(PROGRESS_BAR_THREAD_START, - PROGRESS_BAR_THREAD_END) + self.progressbar.setRange(PROGRESS_THREAD_START, + PROGRESS_THREAD_END) self.progressbar.setTextVisible(True) self.progressbar.setAlignment(Qt.AlignCenter) self.progressbar.setVisible(False) @@ -1638,7 +1678,7 @@ class BaseWindow(QMainWindow): _mess, QMessageBox.Ok) return - self.hdf_thread_started() + #self.hdf_thread_started() self.statusbar.showMessage("Loading {0}".format( self.hdf_filename_loaded)) self.trigger_progressbar_str.emit( @@ -1728,7 +1768,7 @@ class BaseWindow(QMainWindow): """ self.gui_frame.in_hdf_measurement_procedure() QApplication.processEvents() - #print("Thread Started") + @Slot() def hdf_thread_finished(self): @@ -1742,8 +1782,9 @@ class BaseWindow(QMainWindow): @Slot(dict) def receive_analysis_results(self, all_dict): self.all_data = all_dict - self.gui_frame.canvas_update(all_dict['Figure data']) + self.gui_frame.canvas_update(all_dict['Figure data']) + if self.gui_frame.results_output_wgt_dict: #all_dict['Processed data']['Results']={} #all_dict['Processed data']['Results']['mean'] = 123.23 @@ -1753,9 +1794,48 @@ class BaseWindow(QMainWindow): self.gui_frame.send_to_results_output_wgt(results_data) except: pass + + #print("IDX+++", self.gui_frame.central_tab_widget.indexOf('Emittance'), flush=True) + #print("IDX+++", self.gui_frame.level2_tab_wgt[0].indexOf('Plots')) + #self.gui_frame.central_tab_widget.setCurrentIndex(1) - self.gui_frame.central_tab_widget.setCurrentIndex(1) - self.gui_frame.results_tab_wgt.setCurrentIndex(0) + self.gui_frame.results_tab_wgt.setCurrentIndex(0) + + + if "GUITree" in self.settings.data: + + #for j in range(len(self.gui_frame.level1_tab_wgt)): + j = self.gui_frame.central_tab_widget.currentIndex() + for i in range(self.gui_frame.level1_tab_wgt[j].count()): + print(j, i, self.gui_frame.level1_tab_wgt[j].tabText(i), flush=True) + if self.gui_frame.level1_tab_wgt[j].tabText(i) == "Plots": + self.gui_frame.level1_tab_wgt[j].setCurrentIndex(i) + else: + pass + else: + + for i in range(self.gui_frame.central_tab_widget.count()): + print(i, self.gui_frame.central_tab_widget.tabText(i), flush=True) + if self.gui_frame.central_tab_widget.tabText(i) == "Plots": + self.gui_frame.central_tab_widget.setCurrentIndex(i) + else: + pass + + for i in range(self.gui_frame.measurement_tab_wgt.count()): + print(i, self.gui_frame.measurement_tab_wgt.tabText(i), flush=True) + if self.gui_frame.measurement_tab_wgt.tabText(i) == "Plots": + self.gui_frame.measurement_tab_wgt.setCurrentIndex(i) + else: + pass + + for i in range(self.gui_frame.results_tab_wgt.count()): + print(i, self.gui_frame.results_tab_wgt.tabText(i), flush=True) + if self.gui_frame.results_tab_wgt.tabText(i) == "Plots": + self.gui_frame.results_tab_wgt.setCurrentIndex(i) + else: + pass + + print("receive_analysis_results=========================>", flush=True) @Slot() def receive_abort_analysis(self): @@ -1766,7 +1846,7 @@ class BaseWindow(QMainWindow): self.gui_frame.in_abort_procedure() # Trigger abort signal to the analysis thread self.analysis_procedure.trigger_abort.emit() - #self.trigger_progressbar.emit(PROGRESS_BAR_THREAD_ABORTING) + #self.trigger_progressbar.emit(PROGRESS_THREAD_ABORTING) QApplication.processEvents() @@ -1789,19 +1869,19 @@ class BaseWindow(QMainWindow): except KeyError: pass - if value == PROGRESS_BAR_THREAD_INIT: + if value == PROGRESS_THREAD_INIT: self.progressbar.setVisible(False) self.progressbar.setFormat("") self.progressbar.reset() self.progressbar.setObjectName(self.progressbar_color) self.statusbar.clearMessage() - elif value == PROGRESS_BAR_THREAD_START: + elif value == PROGRESS_THREAD_START: self.statusbar.clearMessage() self.progressbar.setFormat("Measurement started") self.progressbar.setValue(value) self.progressbar.setObjectName(self.progressbar_color) self.daq_analysis_completed = False - elif value == PROGRESS_BAR_THREAD_ABORTING: + elif value == PROGRESS_THREAD_ABORTING: self.progressbar.setFormat( "Aborting procedure at the next available break point") self.progressbar.setObjectName(self.progressbar_abort) @@ -1814,7 +1894,7 @@ class BaseWindow(QMainWindow): self.show_log_message( MsgSeverity.WARN.name, _pymodule, _line(), mess) #self.statusbar.showMessage(mess) - elif value == PROGRESS_BAR_THREAD_ABORTED: + elif value == PROGRESS_THREAD_ABORTED: self.progressbar.setFormat("Procedure aborted") self.progressbar.setObjectName(self.progressbar_abort) mess = "Measurement procedure aborted" @@ -1823,15 +1903,15 @@ class BaseWindow(QMainWindow): self.statusbar.showMessage(mess) self.daq_analysis_completed = False QTimer.singleShot(2000, lambda: self.trigger_progressbar.emit( - PROGRESS_BAR_THREAD_INIT)) - elif value == PROGRESS_BAR_THREAD_ERROR: + PROGRESS_THREAD_INIT)) + elif value == PROGRESS_THREAD_ERROR: mess = "Error in Thread. No data returned! See Log window" self.progressbar.setFormat(mess) self.progressbar.setObjectName(self.progressbar_abort) self.statusbar.showMessage(mess) QTimer.singleShot(10000, lambda: self.trigger_progressbar.emit( - PROGRESS_BAR_THREAD_INIT)) - elif value == PROGRESS_BAR_THREAD_END: + PROGRESS_THREAD_INIT)) + elif value == PROGRESS_THREAD_END: self.progressbar.setFormat("Measurement completed") self.progressbar.setValue(value) self.progressbar.setObjectName(self.progressbar_color) diff --git a/guiframe.py b/guiframe.py index 5f9d8bb..80d85f9 100644 --- a/guiframe.py +++ b/guiframe.py @@ -25,7 +25,6 @@ from caqtwidgets.pvwidgets import ( from apps4ops.bdbase.enumkind import Facility, MsgSeverity, UserMode - _pymodule = os.path.basename(__file__) _appversion = "1.0.0" @@ -75,6 +74,7 @@ class GUIFrame(QWidget): self.all_expert_labels = parent.all_expert_labels self.results_output_wgt_dict = {} + self.results_output_wgt_dict_2 = {} try: self.widget_height = self.settings.data["StyleGuide"][ @@ -128,8 +128,17 @@ class GUIFrame(QWidget): self.results_wgt = QWidget() self.results_layout = QHBoxLayout(self.results_wgt) self.results_tab_wgt = QTabWidget(self.results_wgt) + + self.results_wgt_2 = QWidget() + self.results_layout_2 = QHBoxLayout(self.results_wgt_2) + self.results_tab_wgt_2 = QTabWidget(self.results_wgt_2) + + + self.slicing_group = QGroupBox("Screen: Slicing") + self.good_region_group = QGroupBox("Good Region") self.canvas_fig_dict = {} + self.canvas_fig_dict_2 = {} self.left_arrow_dict = {} self.right_arrow_dict = {} @@ -162,6 +171,30 @@ class GUIFrame(QWidget): self.init_results_tab_wgt() + if "GUI2" in self.settings.data: + if "subResultsTabTitle" in self.settings.data["GUI2"]: + + self.results_tab_wgt_titles_2 = self.settings.data[ + "GUI2"]["subResultsTabTitle"] + + self.sub_results_wgt_2 = [None] * len(self.results_tab_wgt_titles_2) + self.sub_results_layout_2 = [None] * len(self.results_tab_wgt_titles_2) + + for i in range(0, len(self.results_tab_wgt_titles_2)): + self.sub_results_wgt_2[i] = QWidget() #self.results_tab_wgt_2) + + self.canvas_2 = [None] * len(self.results_tab_wgt_titles_2) + self.nav_2 = [None] * len(self.results_tab_wgt_titles_2) + + self.arrow_button_widget_2 = [None] * len(self.results_tab_wgt_titles_2) + self.canvas_current_idx_2 = [0] * len(self.results_tab_wgt_titles_2) + + + self.init_results_tab_wgt_2() + + + + self.slice_orientation = "vertical" #horizontal/vertical for SATMA02 self.init_measurement_tab_wgt() @@ -191,22 +224,39 @@ class GUIFrame(QWidget): _margin = 4 + destination_index = [] + try: + idx = self.settings.data["GUI"]["destinationTreeIndex"] + destination_index.append(idx) + except KeyError: + pass + + try: + idx = self.settings.data["GUI2"]["destinationTreeIndex"] + destination_index.append(idx) + except KeyError: + pass + + def is_destination(a, b, c): + for item in destination_index: + if len(item) != 3: + continue + if item[0] == a and item[1] == b and item[2] == c: + return True + return False if "GUITree" in self.settings.data: - key_list = list(self.settings.data["GUITree"].keys()) - self.level1_wgt = [None] * len(key_list) self.level1_tab_wgt = [None] * len(key_list) self.level2_wgt = {} self.level2_tab_wgt = {} self.level3_wgt = {} self.level3_tab_wgt = {} - - qw7 = {} - qw7_tab = {} - + #qwgt2 = {} + #qwgt2_tab = {} for i, title in enumerate(key_list): + print(i, title, flush=True) self.level1_wgt[i] = QWidget() self.level1_wgt[i].title = title @@ -214,35 +264,29 @@ class GUIFrame(QWidget): self.level1_tab_wgt[i].setMinimumWidth(480) self.level1_tab_wgt[i].setFont(self.font_gui) - - #layout = QGridLayout() #self.level1_wgt[i]) - #layout.setAlignment(Qt.AlignLeft | Qt.AlignTop) - #layout.setSpacing(50) - #layout.setContentsMargins(9,9,9,9) - #layout.addWidget(self.level1_wgt[i]) - - #self.central_tab_widget.addTab(self.level1_wgt[i], title) - key_list2 = list(self.settings.data["GUITree"][title]) self.level2_wgt[i] = [None] * len(key_list2) self.level2_tab_wgt[i] = [None] * len(key_list2) - qw7[i] = [None] * len(key_list2) - qw7_tab[i] = [None] * len(key_list2) + #qwgt2[i] = [None] * len(key_list2) + #qwgt2_tab[i] = [None] * len(key_list2) self.level3_wgt[i] = [None] * len(key_list2) self.level3_tab_wgt[i] = [None] * len(key_list2) for j, title2 in enumerate(key_list2): - + print(j, title2, flush=True) key_list3 = (self.settings.data["GUITree"][title][title2]) is_plot = False if isinstance(key_list3, list): + #if "Plots" in key_list3: + # is_plot = True len_key_list3 = len(key_list3) self.level3_wgt[i][j] = [None] * len_key_list3 self.level3_tab_wgt[i][j] = [None] * len_key_list3 + + elif isinstance(key_list3, dict): - if 'link' in key_list3: #get link link = key_list3['link'] @@ -256,69 +300,82 @@ class GUIFrame(QWidget): len_key_list3 = 0 else: len_key_list3 = 0 - + + else: len_key_list3 = 0 - - - self.level2_wgt[i][j] = QWidget() #self.level1_wgt[i]) self.level2_wgt[i][j].title2 = title2 self.level2_wgt[i][j].setFont(self.font_gui) - #layout = QGridLayout()#self.level2_wgt[i][j]) - #layout.setAlignment(Qt.AlignLeft | Qt.AlignTop) - #layout.setSpacing(50) - #layout.setContentsMargins(9,9,9,9) - #layout.addWidget(self.level2_wgt[i][j]) + #Attaching the correct object to QTabWidget is crucuial! if not is_plot: self.level2_tab_wgt[i][j] = QTabWidget(self.level2_wgt[i][j]) else: - self.level2_tab_wgt[i][j] = QTabWidget(self.results_wgt) + if i == 1: + print("///", i, j, flush=True) + self.level2_tab_wgt[i][j] = QTabWidget() #self.results_wgt_2) + else: + print("//", i, j, flush=True) + self.level2_tab_wgt[i][j] = QTabWidget() #self.results_wgt) + self.level2_tab_wgt[i][j].setMinimumWidth(480) self.level2_tab_wgt[i][j].setFont(self.font_gui) - - + for k in range (0, len_key_list3): - if not is_plot: - title3 = key_list3[k] - self.level3_wgt[i][j][k] = QWidget(self.level2_wgt[i][j]) - self.level3_wgt[i][j][k].title3 = title3 - self.level3_wgt[i][j][k].setFont(self.font_gui) + print("tilt3", key_list3[k], flush=True) + self.level3_tab_wgt[i][j][k] = QTabWidget() + #if "Plots" in key_list3[k]: + # is_plot = True + #if not is_plot: + title3 = key_list3[k] + self.level3_wgt[i][j][k] = QWidget() #self.level2_wgt[i][j]) + self.level3_wgt[i][j][k].title3 = title3 + self.level3_wgt[i][j][k].setFont(self.font_gui) - #self.level3_tab_wgt[i][j][k] = QTabWidget(self.level3_wgt[i][j][k]) - #self.level3_tab_wgt[i][j][k].setMinimumWidth(480) - #self.level3_tab_wgt[i][j][k].setFont(self.font_gui) - - ##layout3 = QGridLayout() #self.level1_wgt[i]) - #layout3.addWidget(self.level3_tab_wgt[i][j][k]) - ##layout3.addWidget(QLabel("TEST")) - ##layout3.setContentsMargins(9,9,9,9) - #self.level3_wgt[i][j][k].setLayout(layout3) + if is_destination(i, j, k): + #is_plot = True + #if i==1 and j==0 and k==1: + print("LEVEL2=============>", i, j, k, title3) + self.level2_tab_wgt[i][j].addTab(self.results_wgt_2, title3) + else: + print("LEVEL2/3=============>", i, j, k, title3) self.level2_tab_wgt[i][j].addTab(self.level3_wgt[i][j][k], title3) if not is_plot: self.level1_tab_wgt[i].addTab(self.level2_wgt[i][j], title2) else: + #if i == 1 and j==0: + # print("////", i, flush=True) + # self.level1_tab_wgt[i].addTab(self.results_wgt_2, title2) + #else: + # print("//=", i, flush=True) + self.level1_tab_wgt[i].addTab(self.results_wgt, title2) layout2 = QGridLayout() #self.level1_wgt[i]) layout2.addWidget(self.level2_tab_wgt[i][j]) layout2.addWidget(QFrame()) #Add to stop streching of Measurement Tab - #layout2.addWidget(QLabel("TEST")) + layout2.setContentsMargins(_margin, _margin, _margin, _margin) self.level2_wgt[i][j].setLayout(layout2) layout = QGridLayout() #self.level1_wgt[i]) - layout.addWidget(self.level1_tab_wgt[i]) + layout.addWidget(self.level1_tab_wgt[i], 1, 0, 1, 20) self.level1_wgt[i].setLayout(layout) layout.setContentsMargins(_margin, _margin, _margin, _margin) self.central_tab_widget.addTab(self.level1_wgt[i], title) + + #***How to get to the widgets within the lowest level tabs*** + #lo = QHBoxLayout() + #lo.addWidget(QLabel('TEST')) + #self.gui_frame.level2_tab_wgt[1][0].widget(0).setLayout(lo) + #self.gui_frame.level3_wgt[1][0][0].setLayout(lo) #if "GUI" in self.settings.data: #self.central_tab_widget.addTab( @@ -326,8 +383,6 @@ class GUIFrame(QWidget): ## self.results_wgt, self.settings.data["GUI"]["resultsTabTitle"]) self.central_tab_widget.addTab(self.log_wgt, "Log") - - self.operator_wgt = self.level3_wgt[0][0][0] self.expert_wgt = self.level3_wgt[0][0][1] self.measurement_tab_wgt = self.level2_tab_wgt[0][0] @@ -351,7 +406,6 @@ class GUIFrame(QWidget): def init_measurement_tab_wgt(self): """ Add tabs to measurement widget """ - self.measurement_tab_wgt.setFont(self.font_gui) self.measurement_tab_wgt.addTab(self.operator_wgt, "Operator") self.measurement_tab_wgt.addTab(self.expert_wgt, "Expert") @@ -361,10 +415,8 @@ class GUIFrame(QWidget): """ Add canvas tabs for plots/results """ - self.results_tab_wgt.setFont(self.font_gui) - for i, (wgt, subtitle) in enumerate(zip(self.sub_results_wgt, self.results_tab_wgt_titles)): @@ -377,13 +429,38 @@ class GUIFrame(QWidget): wgt.setLayout(self.sub_results_layout[i]) top_layout.addWidget(wgt) - + #top_layout.addWidget(QLabel("HERE")) top_widget.setLayout(top_layout) self.results_tab_wgt.addTab(top_widget, subtitle) - self.results_layout.addWidget(self.results_tab_wgt) + + def init_results_tab_wgt_2(self): + """ Add canvas tabs for plots/results + """ + + self.results_tab_wgt_2.setFont(self.font_gui) + + for i, (wgt, subtitle) in enumerate(zip(self.sub_results_wgt_2, + self.results_tab_wgt_titles_2)): + + top_widget = QWidget(self.results_tab_wgt_2) + top_layout = QVBoxLayout() + self.sub_results_layout_2[i] = QVBoxLayout() + + if self.settings.data["GUI2"]["resultsSeq"][i] > 1: + top_layout.addWidget(self.get_arrow_button_widget(i)) + + wgt.setLayout(self.sub_results_layout_2[i]) + + top_layout.addWidget(wgt) + #top_layout.addWidget(QLabel("THERE")) + top_widget.setLayout(top_layout) + self.results_tab_wgt_2.addTab(top_widget, subtitle) + + self.results_layout_2.addWidget(self.results_tab_wgt_2) + def show_log_message(self, severity=None, pymodule="", lineno=0, message="", options=None): @@ -565,7 +642,8 @@ class GUIFrame(QWidget): #print("CB fired") #print(self.input_parameters[key]) #print(self.input_parameters) - + if key == "goodRegion": + self.good_region_group.setEnabled(value) checkbox = QCheckBox(text) checkbox.setToolTip(tip) @@ -585,6 +663,8 @@ class GUIFrame(QWidget): checkbox.setCheckState(checked_value) checkbox.stateChanged.emit(checked_value) + self.line_sender_dict[key] = checkbox + return checkbox def create_label_qdoublespinbox(self, key, label="", min_val=0, max_val=1, @@ -617,6 +697,9 @@ class GUIFrame(QWidget): wgt.valueChanged.connect(callback) wgt.setValue(start_val) wgt.valueChanged.emit(start_val) + + self.line_sender_dict[key] = wgt + return lab, wgt @@ -649,6 +732,9 @@ class GUIFrame(QWidget): wgt.valueChanged.connect(cb) wgt.setValue(start_val) wgt.valueChanged.emit(start_val) + + self.line_sender_dict[key] = wgt + return lab, wgt @@ -659,8 +745,8 @@ class GUIFrame(QWidget): def cb(new_text): self.input_parameters[key] = new_text - print( self.input_parameters) - + #print( self.input_parameters) + widget_height = 26 suggested = "WWW" lab = QLabel(label) @@ -688,117 +774,10 @@ class GUIFrame(QWidget): param_width = max(fm.width(str(value_for_width)), fm.width(suggested)) wgt.setFixedWidth(param_width + 50) - + self.line_sender_dict[key] = wgt return lab, wgt - def image_parameters_group(self): - group_box = QGroupBox("Image Pipeline Expert") - - box = QHBoxLayout() - box.setSpacing(10) - try: - start_val_gr = self.settings.data["Expert"]["pipeline"]["data"][ - "goodRegion"] - start_val_gr = Qt.Checked if start_val_gr else Qt.Unchecked - except KeyError as ex: - start_val_gr = Qt.Unchecked - box.addWidget(self.create_checkbox( - top_key="Expert", key="goodRegion", text="Good region", - tip="Enables good region in pipeline", default_value=start_val_gr)) - try: - start_val_sub = self.settings.data["Expert"]["pipeline"]["data"][ - "subtractBackground"] - start_val_sub = Qt.Checked if start_val_sub else Qt.Unchecked - except KeyError as ex: - start_val_sub = Qt.Unchecked - box.addWidget(self.create_checkbox( - top_key="Expert", key="subtractBackground", - text="Subtract bkgrnd", - tip="Enables background subtraction in pipeline", - default_value=start_val_sub)) - - group_box.setAlignment(Qt.AlignCenter) - group_box.setObjectName("INNERCENTER") - - good_region = QGroupBox("Good Region") - good_region.setObjectName("INNER") - - try: - start_val_grThreshold = self.settings.data["Expert"]["pipeline"][ - "data"]["grThreshold"] - except KeyError as ex: - start_val_grThreshold = 21 - - lab_thresh, thresh = self.create_label_qdoublespinbox( - key="grThreshold", label="Threshold:", start_val=start_val_grThreshold) - try: - start_val_grScale = self.settings.data["Expert"]["pipeline"][ - "data"]["grScale"] - except KeyError as ex: - start_val_grScale = 6 - lab_gfscale, gfscale = self.create_label_qspinbox( - key="grScale", label="Scale:", start_val=start_val_grScale) - - layout = QGridLayout() - layout.addWidget(lab_thresh, 0, 0) - layout.addWidget(thresh, 0, 1) - layout.addWidget(lab_gfscale, 1, 0) - layout.addWidget(gfscale, 1, 1) - good_region.setLayout(layout) - - slicing = QGroupBox("Slicing") - slicing.setObjectName("INNER") - - try: - start_val_nslices = self.settings.data["Expert"]["pipeline"][ - "data"]["slices"] - except KeyError as ex: - start_val_nslices = 21 - lab_slices, slices = self.create_label_qspinbox( - key="slices", label="No. Slices:", start_val=start_val_nslices) - - try: - start_val_slicing_scale = self.settings.data["Expert"]["pipeline"][ - "data"]["slicingScale"] - except KeyError as ex: - start_val_slicing_scale = 5 - lab_scale, scale = self.create_label_qspinbox( - key="slicingScale", label="Scale:", - start_val=start_val_slicing_scale) - - try: - start_val_orientation = self.settings.data["Expert"]["pipeline"][ - "data"]["orientation"] - except KeyError as ex: - start_val_orientation = "vertical" - - lab_orientation, self.slice_orientation = self.create_label_qcombobox( - key="orientation", label="Orientation:", - values=["vertical", "horizontal"], start_val=start_val_orientation) - - layout = QGridLayout() - - layout.addWidget(lab_slices, 0, 0) - layout.addWidget(slices, 0, 1) - layout.addWidget(lab_scale, 1, 0) - layout.addWidget(scale, 1, 1) - layout.addWidget(lab_orientation, 2, 0, 1, 2, Qt.AlignBottom) - layout.addWidget(self.slice_orientation, 3, 0, 1, 2, - Qt.AlignTop | Qt.AlignRight) - slicing.setLayout(layout) - - layout_top = QGridLayout() - layout_top.addLayout(box, 0, 0, 1, 2) - layout_top.addWidget(good_region, 1, 0, 1, 1, - Qt.AlignHCenter | Qt.AlignTop) - layout_top.addWidget(slicing, 1, 1, 1, 1, Qt.AlignCenter | Qt.AlignTop) - layout_top.setHorizontalSpacing(8) - group_box.setLayout(layout_top) - group_box.setFixedHeight(200) - return group_box - - def create_analysis_wgt( self, start_title="Start", start_action=None, start_tooltip="Start measurement and analysis procedure", @@ -1056,6 +1035,119 @@ class GUIFrame(QWidget): return self.save_all_group_box + def image_parameters_group(self): + group_box = QGroupBox("Image Pipeline Expert") + + box = QHBoxLayout() + box.setSpacing(10) + try: + start_val_gr = self.settings.data["Expert"]["pipeline"]["data"][ + "goodRegion"] + start_val_gr = Qt.Checked if start_val_gr else Qt.Unchecked + except KeyError as ex: + start_val_gr = Qt.Unchecked + box.addWidget(self.create_checkbox( + top_key="Expert", key="goodRegion", text="Good region", + tip="Enables good region in pipeline", default_value=start_val_gr)) + try: + start_val_sub = self.settings.data["Expert"]["pipeline"]["data"][ + "subtractBackground"] + start_val_sub = Qt.Checked if start_val_sub else Qt.Unchecked + except KeyError as ex: + start_val_sub = Qt.Unchecked + + box.addWidget(self.create_checkbox( + top_key="Expert", key="subtractBackground", + text="Subtract bkgrnd", + tip="Enables background subtraction in pipeline", + default_value=start_val_sub)) + + group_box.setAlignment(Qt.AlignCenter) + group_box.setObjectName("INNERCENTER") + + self.good_region_group.setObjectName("INNER") + + try: + start_val_grThreshold = self.settings.data["Expert"]["pipeline"][ + "data"]["grThreshold"] + except KeyError as ex: + start_val_grThreshold = 21 + + lab_thresh, thresh = self.create_label_qdoublespinbox( + key="grThreshold", label="Threshold:", + start_val=start_val_grThreshold) + try: + start_val_grScale = self.settings.data["Expert"]["pipeline"][ + "data"]["grScale"] + except KeyError as ex: + start_val_grScale = 6 + lab_gfscale, gfscale = self.create_label_qspinbox( + key="grScale", label="Scale:", start_val=start_val_grScale) + + layout = QGridLayout() + layout.addWidget(lab_thresh, 0, 0) + layout.addWidget(thresh, 0, 1) + layout.addWidget(lab_gfscale, 1, 0) + layout.addWidget(gfscale, 1, 1) + self.good_region_group.setLayout(layout) + + + self.slicing_group.setObjectName("INNER") + + try: + start_val_nslices = self.settings.data["Expert"]["pipeline"][ + "data"]["slices"] + except KeyError as ex: + start_val_nslices = 21 + lab_slices, slices = self.create_label_qspinbox( + key="slices", label="No. Slices:", start_val=start_val_nslices) + + try: + start_val_slicing_scale = self.settings.data["Expert"]["pipeline"][ + "data"]["slicingScale"] + except KeyError as ex: + start_val_slicing_scale = 5 + lab_scale, scale = self.create_label_qspinbox( + key="slicingScale", label="Scale:", + start_val=start_val_slicing_scale) + + try: + start_val_orientation = self.settings.data["Expert"]["pipeline"][ + "data"]["orientation"] + except KeyError as ex: + start_val_orientation = "vertical" + + lab_orientation, self.slice_orientation = self.create_label_qcombobox( + key="orientation", label="Orientation:", + values=["vertical", "horizontal"], start_val=start_val_orientation) + + layout = QGridLayout() + + layout.addWidget(lab_slices, 0, 0) + layout.addWidget(slices, 0, 1) + layout.addWidget(lab_scale, 1, 0) + layout.addWidget(scale, 1, 1) + layout.addWidget(lab_orientation, 2, 0, 1, 2, Qt.AlignBottom) + layout.addWidget(self.slice_orientation, 3, 0, 1, 2, + Qt.AlignTop | Qt.AlignRight) + self.slicing_group.setLayout(layout) + + layout_top = QGridLayout() + layout_top.addLayout(box, 0, 0, 1, 2) + layout_top.addWidget(self.good_region_group, 1, 0, 1, 1, + Qt.AlignHCenter | Qt.AlignTop) + layout_top.addWidget(self.slicing_group, 1, 1, 1, 1, + Qt.AlignCenter | Qt.AlignTop) + layout_top.setHorizontalSpacing(8) + group_box.setLayout(layout_top) + group_box.setFixedHeight(200) + return group_box + + + + + + def checkbox_wgt(self, key: str = "", tooltip: str = "", object_name=None, hline="NONE"): def on_change(state): @@ -1265,7 +1357,11 @@ class GUIFrame(QWidget): for i, key in enumerate(self.multiple_figure_dict.keys()): self.canvas_fig_dict[i] = key - + + print("UPDATE", flush=True) + #print(len(self.canvas), len(self.nav), len(self.sub_results_layout), + # len(self.multiple_figure_dict.keys(), flush=True)) + for i, (canvas, nav, wgt, layout, key) in enumerate( zip(self.canvas, self.nav, self.sub_results_wgt, @@ -1305,6 +1401,59 @@ class GUIFrame(QWidget): self.nav[i] = None + def canvas_update_2(self, fig_data, idx=0): + #place figures in a list + + self.parent.clear_screenshot() + self.multiple_figure_dict_2 = fig_data + + for i, key in enumerate(self.multiple_figure_dict_2.keys()): + self.canvas_fig_dict_2[i] = key + + print("UPDATE==2", flush=True) + #print(len(self.canvas), len(self.nav), len(self.sub_results_layout), + # len(self.multiple_figure_dict.keys(), flush=True)) + + for i, (canvas, nav, wgt, layout, key) in enumerate( + zip(self.canvas_2, self.nav_2, + self.sub_results_wgt_2, + self.sub_results_layout_2, + self.multiple_figure_dict_2.keys())): + + if canvas is not None: + layout.removeWidget(canvas) + canvas.deleteLater() + if nav is not None: + nav.deleteLater() + + if self.multiple_figure_dict_2[key]: #'Figure 1']: + + if not isinstance(self.multiple_figure_dict_2[key], list): + temp_list = [] + temp_list.append(self.multiple_figure_dict_2[key]) + self.multiple_figure_dict_2[key] = temp_list + + + self.canvas_2[i] = FigureCanvasQTAgg( + self.multiple_figure_dict_2[key][idx]) + self.sub_results_layout_2[i].addWidget(self.canvas_2[i]) + self.nav_2[i] = NavigationToolbar( + self.canvas_2[i], self.sub_results_wgt_2[i], + coordinates=False) + self.nav_2[i].setMinimumWidth(400) + self.nav_2[i].setMinimumHeight(50) + #self.nav[i].setContentsMargins(0, 0, 0, 0) + self.nav_2[i].setVisible(True) + self.nav_2[i].setStyleSheet("QToolBar { border: 0px }") + + self.parent.add_screenshot( + title=self.results_tab_wgt_titles_2[i], item=wgt) + + else: + self.canvas_2[i] = None + self.nav_2[i] = None + + def prepare_qlineread(self, line, value): line.setObjectName("Read") line.setFixedHeight(24) @@ -1983,7 +2132,8 @@ class GUIFrame(QWidget): label.setFont(self.font_pts10) label.setContentsMargins(5, 0, 0, 0) label.setToolTip(tooltip) - return self.input_wgt_qcombobox(label, "loggingLevel", value, irow, wgt_grid) + return self.input_wgt_qcombobox(label, "loggingLevel", value, irow, + wgt_grid) def input_wgt_qcombobox(self, label, key, value, irow, wgt_grid): @@ -1997,6 +2147,8 @@ class GUIFrame(QWidget): def combo_cb(new_text): self.input_parameters[key] = new_text + if 'loggingLevel' in key: + self.parent.logger.setLevel(new_text) line = QComboBox() line.clear() diff --git a/sendelogframe.py b/sendelogframe.py index c1af9b6..03438c6 100644 --- a/sendelogframe.py +++ b/sendelogframe.py @@ -307,18 +307,24 @@ class QSendToELOGFrame(QDialog): #find layout items layout_items = [] layout_items_optional = [] + print("logbook", logbook) try: layout_items = list(self.parent.settings.data[ "ElogBooks"][logbook]['Required'].keys()) except KeyError: pass + + print("logbook- items", layout_items) + try: layout_items_optional = list(self.parent.settings.data[ "ElogBooks"][logbook]['Optional'].keys()) except KeyError: pass - layout_items.extend(layout_items_optional) + print("logbook- optional", layout_items_optional) + if layout_items_optional: + layout_items.extend(layout_items_optional) return layout_items diff --git a/utils.py b/utils.py new file mode 100644 index 0000000..0258662 --- /dev/null +++ b/utils.py @@ -0,0 +1,12 @@ +from inspect import currentframe + +def _line(): + """Macro to return the current line number. + + The current line number within the file is used when + reporting messages to the message logging window. + + Returns: + int: Current line number. + """ + return currentframe().f_back.f_lineno