diff --git a/src/napari_lf/_widgetLF.py b/src/napari_lf/_widgetLF.py index 5b8b81a..b7174b6 100644 --- a/src/napari_lf/_widgetLF.py +++ b/src/napari_lf/_widgetLF.py @@ -9,7 +9,7 @@ # Fix for the QPixMap error # https://github.com/PolarizedLightFieldMicroscopy/napari-LF/issues/29 -app = QApplication([]) +# app = QApplication([]) try: from napari_lf import _widgetLF_gui as LFgui @@ -267,14 +267,17 @@ def input_model_change_call(): if "mode_choice" in self.gui.settings["main"] and self.gui.settings["main"]["mode_choice"] == 'NeuralNet': self.gui.LFAnalyze_btn_cont.hide() self.gui.NeuralNet_btn_cont.show() + self.gui.NeuralNet_btn.isButtonActive = True + self.gui.LFAnalyze_btn.isButtonActive = False self.gui.widget_main_bottom_comps0.hide() self.gui.widget_main_bottom_comps1.hide() self.gui.widget_main_bottom_comps2.show() self.gui._cont_btn_processing.hide() self.gui._cont_btn_processing2.show() - self.gui.NeuralNet_btn.toggle() + #self.gui.NeuralNet_btn.toggle() else: - self.gui.LFAnalyze_btn.toggle() + pass + #self.gui.LFAnalyze_btn.toggle() #Layout layout = QVBoxLayout() diff --git a/src/napari_lf/_widgetLF_gui.py b/src/napari_lf/_widgetLF_gui.py index 038749d..95947d4 100644 --- a/src/napari_lf/_widgetLF_gui.py +++ b/src/napari_lf/_widgetLF_gui.py @@ -1,10 +1,11 @@ import os, sys, glob, ntpath, subprocess, traceback, json, time from pathlib import Path from qtpy import QtCore, QtGui -from qtpy.QtGui import QPixmap, QPainter +from qtpy.QtGui import QPixmap, QPainter, QCursor from qtpy.QtCore import Qt, QTimer, QSize from qtpy.QtWidgets import * from magicgui.widgets import * +from napari.qt.threading import thread_worker try: from napari_lf import _widgetLF_vals as LFvals @@ -172,12 +173,13 @@ def __init__(self): self.LFAnalyze_btn = PicButton(QPixmap(LFvals.LFAnalyze_logo_btn_img), QPixmap(LFvals.LFAnalyze_logo_btn_hov_img), QPixmap(LFvals.LFAnalyze_logo_btn_act_img)) self.LFAnalyze_btn_cont = Container(name='LFAnalyze_btn', widgets=()) self.LFAnalyze_btn_cont.native.layout().addWidget(self.LFAnalyze_btn) - + self.LFAnalyze_btn.setMaximumHeight(45) self.LFAnalyze_btn.setMaximumHeight(200) # self.LFAnalyze_btn.setAlignment(Qt.AlignCenter|Qt.AlignVCenter) self.LFAnalyze_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.LFAnalyze_btn.clicked.connect(self.LFAnalyze_btn_call) + self.LFAnalyze_btn.isButtonActive = True self.NeuralNet_btn = PicButton(QPixmap(LFvals.NeuralNet_logo_btn_img),QPixmap(LFvals.NeuralNet_logo_btn_hov_img),QPixmap(LFvals.NeuralNet_logo_btn_act_img)) self.NeuralNet_btn_cont = Container(name='NeuralNet_btn', widgets=()) @@ -188,8 +190,11 @@ def __init__(self): # self.NeuralNet_btn.setAlignment(Qt.AlignCenter|Qt.AlignVCenter) self.NeuralNet_btn.setSizePolicy(QSizePolicy.Fixed, QSizePolicy.Fixed) self.NeuralNet_btn.clicked.connect(self.NeuralNet_btn_call) + self.NeuralNet_btn.isButtonActive = False self.NeuralNet_btn_cont.hide() - + + #self.LFAnalyze_btn.toggle() + #self.NeuralNet_btn.toggle() _toggle_instructions = QWidget() mylabel = QLabel() @@ -333,7 +338,7 @@ def __init__(self): self.cont_btn_status_label.native.setSizePolicy(QSizePolicy.Expanding, QSizePolicy.Fixed) self.cont_btn_status_label.native.setAlignment(Qt.AlignCenter|Qt.AlignVCenter) - self.groupbox = {"calibrate":{"required":{},"optional":{},"inspect":{}},"rectify":{"required":{},"optional":{}},"deconvolve":{"required":{},"optional":{}}, "projections":{}, "lfmnet":{}} + self.groupbox = {"calibrate":{"required":{},"optional":{},"inspect":{}},"rectify":{"required":{},"optional":{}},"deconvolve":{"required":{},"optional":{}}, "projections":{}, "lfmnet":{"deconvolve":{},"training":{}}} # == CALIBATE == _widget_calibrate_req = [] @@ -454,7 +459,7 @@ def __init__(self): @self.btn_cal_req_def.changed.connect def btn_cal_req_defaults(): qm = QMessageBox - ret = qm.question(QWidget(),'', "Reset Values to Default ?", qm.Yes | qm.No) + ret = qm.question(self.logo_label.native, 'napari-LF', "Reset Values to Default ?", qm.Yes | qm.No) if ret == qm.Yes: for key in self.lf_vals["calibrate"]: dict = self.lf_vals["calibrate"][key] @@ -479,7 +484,7 @@ def btn_cal_req_defaults(): @self.btn_cal_opt_def.changed.connect def btn_cal_opt_defaults(): qm = QMessageBox - ret = qm.question(QWidget(),'', "Reset Values to Default ?", qm.Yes | qm.No) + ret = qm.question(self.logo_label.native, 'napari-LF', "Reset Values to Default ?", qm.Yes | qm.No) if ret == qm.Yes: for key in self.lf_vals["calibrate"]: dict = self.lf_vals["calibrate"][key] @@ -602,7 +607,7 @@ def btn_cal_opt_defaults(): @self.btn_rec_req_def.changed.connect def btn_rec_req_defaults(): qm = QMessageBox - ret = qm.question(QWidget(),'', "Reset Values to Default ?", qm.Yes | qm.No) + ret = qm.question(self.logo_label.native, 'napari-LF', "Reset Values to Default ?", qm.Yes | qm.No) if ret == qm.Yes: for key in self.lf_vals["rectify"]: dict = self.lf_vals["rectify"][key] @@ -627,7 +632,7 @@ def btn_rec_req_defaults(): @self.btn_rec_opt_def.changed.connect def btn_rec_opt_defaults(): qm = QMessageBox - ret = qm.question(QWidget(),'', "Reset Values to Default ?", qm.Yes | qm.No) + ret = qm.question(self.logo_label.native, 'napari-LF', "Reset Values to Default ?", qm.Yes | qm.No) if ret == qm.Yes: for key in self.lf_vals["rectify"]: dict = self.lf_vals["rectify"][key] @@ -747,7 +752,7 @@ def btn_rec_opt_defaults(): @self.btn_dec_req_def.changed.connect def btn_dec_req_defaults(): qm = QMessageBox - ret = qm.question(QWidget(),'', "Reset Values to Default ?", qm.Yes | qm.No) + ret = qm.question(self.logo_label.native, 'napari-LF', "Reset Values to Default ?", qm.Yes | qm.No) if ret == qm.Yes: for key in self.lf_vals["deconvolve"]: dict = self.lf_vals["deconvolve"][key] @@ -772,7 +777,7 @@ def btn_dec_req_defaults(): @self.btn_dec_opt_def.changed.connect def btn_dec_opt_defaults(): qm = QMessageBox - ret = qm.question(QWidget(),'', "Reset Values to Default ?", qm.Yes | qm.No) + ret = qm.question(self.logo_label.native, 'napari-LF', "Reset Values to Default ?", qm.Yes | qm.No) if ret == qm.Yes: for key in self.lf_vals["deconvolve"]: dict = self.lf_vals["deconvolve"][key] @@ -851,42 +856,75 @@ def btn_dec_opt_defaults(): # == LFMNET == self.gui_elms["lfmnet"] = {} - self.groupbox["lfmnet"] = {} _widget_lfmnet = [] + _widget_lfmnet_train = [] for key in LFvals.PLUGIN_ARGS['lfmnet']: dict = LFvals.PLUGIN_ARGS["lfmnet"][key] - if "group" in dict and dict["group"] not in self.groupbox["lfmnet"] and self.lf_vals["misc"]["group_params"]["value"] == True: - self.groupbox["lfmnet"][dict["group"]] = QGroupBox(dict["group"]) - vbox = QFormLayout() - vbox.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) - _widget_lfmnet.append(self.groupbox["lfmnet"][dict["group"]]) - self.groupbox["lfmnet"][dict["group"]].setLayout(vbox) - if "label" not in dict: - dict["label"] = dict["dest"] - wid_elm = create_widget(dict) - self.gui_elms["lfmnet"][key] = wid_elm - if "group" in dict: - if self.lf_vals["misc"]["group_params"]["value"] == False: - _widget_lfmnet.append(wid_elm) + + if "cat" in dict and dict["cat"] == "deconvolve": + if "group" in dict and dict["group"] not in self.groupbox["lfmnet"]["deconvolve"] and self.lf_vals["misc"]["group_params"]["value"] == True: + self.groupbox["lfmnet"]["deconvolve"][dict["group"]] = QGroupBox(dict["group"]) + vbox = QFormLayout() + vbox.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) + _widget_lfmnet.append(self.groupbox["lfmnet"]["deconvolve"][dict["group"]]) + self.groupbox["lfmnet"]["deconvolve"][dict["group"]].setLayout(vbox) + if "label" not in dict: + dict["label"] = dict["dest"] + wid_elm = create_widget(dict) + self.gui_elms["lfmnet"][key] = wid_elm + if "group" in dict: + if self.lf_vals["misc"]["group_params"]["value"] == False: + _widget_lfmnet.append(wid_elm) + else: + if "visible" in dict and dict["visible"] == False: + pass + else: + if dict["type"] == "bool": + self.groupbox["lfmnet"]["deconvolve"][dict["group"]].layout().addRow(wid_elm.native) + elif "no_label_layout_style" in dict and dict["no_label_layout_style"] == True: + self.groupbox["lfmnet"]["deconvolve"][dict["group"]].layout().addRow(wid_elm.native) + else: + self.groupbox["lfmnet"]["deconvolve"][dict["group"]].layout().addRow(wid_elm.label, wid_elm.native) else: - if "visible" in dict and dict["visible"] == False: - pass + _widget_lfmnet.append(wid_elm) + elif "cat" in dict and dict["cat"] == "training": + if "group" in dict and dict["group"] not in self.groupbox["lfmnet"]["training"] and self.lf_vals["misc"]["group_params"]["value"] == True: + self.groupbox["lfmnet"]["training"][dict["group"]] = QGroupBox(dict["group"]) + vbox = QFormLayout() + vbox.setFieldGrowthPolicy(QFormLayout.ExpandingFieldsGrow) + _widget_lfmnet_train.append(self.groupbox["lfmnet"]["training"][dict["group"]]) + self.groupbox["lfmnet"]["training"][dict["group"]].setLayout(vbox) + if "label" not in dict: + dict["label"] = dict["dest"] + wid_elm = create_widget(dict) + self.gui_elms["lfmnet"][key] = wid_elm + if "group" in dict: + if self.lf_vals["misc"]["group_params"]["value"] == False: + _widget_lfmnet_train.append(wid_elm) else: - if dict["type"] == "bool": - self.groupbox["lfmnet"][dict["group"]].layout().addRow(wid_elm.native) - elif "no_label_layout_style" in dict and dict["no_label_layout_style"] == True: - self.groupbox["lfmnet"][dict["group"]].layout().addRow(wid_elm.native) + if "visible" in dict and dict["visible"] == False: + pass else: - self.groupbox["lfmnet"][dict["group"]].layout().addRow(wid_elm.label, wid_elm.native) - else: - _widget_lfmnet.append(wid_elm) + if dict["type"] == "bool": + self.groupbox["lfmnet"]["training"][dict["group"]].layout().addRow(wid_elm.native) + elif "no_label_layout_style" in dict and dict["no_label_layout_style"] == True: + self.groupbox["lfmnet"]["training"][dict["group"]].layout().addRow(wid_elm.native) + else: + self.groupbox["lfmnet"]["training"][dict["group"]].layout().addRow(wid_elm.label, wid_elm.native) + else: + _widget_lfmnet_train.append(wid_elm) + if self.lf_vals["misc"]["group_params"]["value"] == False: self.container_lfmnet = Container(name='LFM-NET', widgets=_widget_lfmnet) + self.container_lfmnet_train = Container(name='LFM-NET-Train', widgets=_widget_lfmnet_train) else: self.container_lfmnet = Container(name='LFM-NET', widgets=()) + self.container_lfmnet_train = Container(name='LFM-NET', widgets=()) for wid_elm in _widget_lfmnet: self.container_lfmnet.native.layout().addWidget(wid_elm) + for wid_elm in _widget_lfmnet_train: + self.container_lfmnet_train.native.layout().addWidget(wid_elm.native) # == HARDWARE == @@ -908,7 +946,7 @@ def btn_dec_opt_defaults(): @self.btn_hw_def.changed.connect def btn_hw_defaults(): qm = QMessageBox - ret = qm.question(QWidget(),'', "Reset Values to Default ?", qm.Yes | qm.No) + ret = qm.question(self.logo_label.native, 'napari-LF', "Reset Values to Default ?", qm.Yes | qm.No) if ret == qm.Yes: for key in self.lf_vals["hw"]: dict = self.lf_vals["hw"][key] @@ -966,13 +1004,26 @@ def btn_hw_defaults(): def btn_misc_cls(): os.system('cls' if os.name == 'nt' else 'clear') + @self.gui_elms['lfmnet']['training_btn'].changed.connect + def btn_NN_train(): + os.system('jupyter notebook stop') + os.system('cls' if os.name == 'nt' else 'clear') + worker = btn_NN_train_run() # create "worker" object + worker.start() # start the thread! + + @thread_worker + def btn_NN_train_run(): + training_JNB = str(os.path.join(str(self.gui_elms["misc"]["lib_folder"].value), 'main_train_neural_net.ipynb')) + print('Opening jupyter notebook file: ', training_JNB) + os.system('jupyter notebook ' + training_JNB) + _layout_misc.addRow(self.btn_misc_cls.native) self.btn_misc_def = PushButton(name='RTD', label='Reset to Defaults') @self.btn_misc_def.changed.connect def btn_misc_defaults(): qm = QMessageBox - ret = qm.question(QWidget(),'', "Reset Values to Default ?", qm.Yes | qm.No) + ret = qm.question(self.logo_label.native, 'napari-LF', "Reset Values to Default ?", qm.Yes | qm.No) if ret == qm.Yes: for key in self.lf_vals["misc"]: dict = self.lf_vals["misc"][key] @@ -1002,11 +1053,19 @@ def btn_misc_defaults(): _layout_misc.addRow(self.btn_misc_def.native) + self.btn_proj_def = PushButton(name='RTD', label='Reset Project Directory to Default Examples') + @self.btn_proj_def.changed.connect + def btn_proj_defaults(): + qm = QMessageBox + ret = qm.question(self.logo_label.native, 'napari-LF', "Reset Project Directory to Default Examples ?", qm.Yes | qm.No) + if ret == qm.Yes: + self.gui_elms["main"]["img_folder"].value = LFvals.examples_folder + self.btn_all_def = PushButton(name='RTD', label='Reset ALL Settings to Defaults') @self.btn_all_def.changed.connect def btn_all_defaults(): qm = QMessageBox - ret = qm.question(QWidget(),'', "Reset ALL Values to Default ?", qm.Yes | qm.No) + ret = qm.question(self.logo_label.native, 'napari-LF', "Reset ALL Values to Default ?", qm.Yes | qm.No) if ret == qm.Yes: btn_cal_req_defaults() btn_cal_opt_defaults() @@ -1023,11 +1082,22 @@ def btn_all_defaults(): _line.setMinimumWidth(1) _line.setFixedHeight(2) _line.setFrameShape(QFrame.HLine) - _line.setFrameShadow(QFrame.Sunken) + _line.setFrameShadow(QFrame.Plain) _line.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum) _line.setStyleSheet("margin:1px; padding:1px; border:1px solid rgb(128,128,128); border-width: 1px;") + _line2 = QFrame() + _line2.setMinimumWidth(1) + _line2.setFixedHeight(4) + _line2.setFrameShape(QFrame.HLine) + _line2.setFrameShadow(QFrame.Sunken) + _line2.setSizePolicy(QSizePolicy.Preferred, QSizePolicy.Minimum) + _line2.setStyleSheet("margin:4px; padding:4px; border:4px solid rgb(128,128,128); border-width: 4px;") + _layout_misc.addRow(_line) + _layout_misc.addRow(self.btn_proj_def.native) + + _layout_misc.addRow(_line2) _layout_misc.addRow(self.btn_all_def.native) self.container_lfa = _misc_widget @@ -1232,6 +1302,18 @@ def img_folder_changes(): _lfmnet_tab_layout.setAlignment(Qt.AlignTop) self.lfmnet_tab.setLayout(_lfmnet_tab_layout) self.lfmnet_tab.layout().addWidget(self.container_lfmnet.native) + + self.lfmnet_tab2 = QWidget() + _lfmnet_tab_layout = QVBoxLayout() + _lfmnet_tab_layout.setAlignment(Qt.AlignTop) + self.lfmnet_tab2.setLayout(_lfmnet_tab_layout) + self.lfmnet_tab2.layout().addWidget(self.container_lfmnet_train.native) + + self.qtab_NNet_tabWidget = QTabWidget() + self.qtab_NNet_tabWidget.setTabPosition(QTabWidget.North) + self.qtab_NNet_tabWidget.addTab(self.lfmnet_tab, 'Deconvolve') + self.qtab_NNet_tabWidget.addTab(self.lfmnet_tab2, 'Training') + # self.qtab_widget.addTab(self.lfmnet_tab, 'Neural Net') @@ -1257,6 +1339,7 @@ def img_folder_changes(): vlay = QVBoxLayout() box = CollapsibleBox("Presets && Comments") + box.tooltip = LFvals.PLUGIN_ARGS['main']['presets']['help'] vlay.addWidget(box) lay = QVBoxLayout() lay.addWidget(_cont_preset_list_btn.native) @@ -1265,6 +1348,7 @@ def img_folder_changes(): box.setContentLayout(lay) # vlay.addStretch() _preset_comments_expand = QWidget() + _preset_comments_expand.tooltip = LFvals.PLUGIN_ARGS['main']['presets']['help'] _preset_comments_expand.setLayout(vlay) _preset_comments_expand.layout().setContentsMargins(0,0,0,0) _preset_comments_expand.layout().setSpacing(0) @@ -1282,7 +1366,7 @@ def img_folder_changes(): self.widget_main_bottom_comps1.native.layout().addWidget(self.qtab_widget) self.widget_main_bottom_comps2 = Container(widgets=(), labels=True) - self.widget_main_bottom_comps2.native.layout().addWidget(self.lfmnet_tab) + self.widget_main_bottom_comps2.native.layout().addWidget(self.qtab_NNet_tabWidget) self.widget_main_bottom_comps2.visible = False self._cont_btn_processing2.visible = False @@ -1324,7 +1408,9 @@ def img_folder_changes(): def LFAnalyze_btn_call(self): # print("LFAnalyze_btn_call") - if self.LFAnalyze_btn.isChecked() == True: + self.LFAnalyze_btn.isButtonActive = not self.LFAnalyze_btn.isButtonActive + self.NeuralNet_btn.isButtonActive = not self.NeuralNet_btn.isButtonActive + if self.LFAnalyze_btn.isButtonActive == True: self.widget_main_bottom_comps0.visible = True self.widget_main_bottom_comps1.visible = True self.widget_main_bottom_comps2.visible = False @@ -1342,12 +1428,15 @@ def LFAnalyze_btn_call(self): self.LFAnalyze_btn_cont.visible = False self.NeuralNet_btn_cont.visible = True self.settings["main"]["mode_choice"] = 'NeuralNet' - self.NeuralNet_btn.toggle() + #self.NeuralNet_btn.toggle() + #self.LFAnalyze_btn.toggle() self.save_plugin_prefs() def NeuralNet_btn_call(self): # print("NeuralNet_btn_call") - if self.NeuralNet_btn.isChecked() == True: + self.LFAnalyze_btn.isButtonActive = not self.LFAnalyze_btn.isButtonActive + self.NeuralNet_btn.isButtonActive = not self.NeuralNet_btn.isButtonActive + if self.NeuralNet_btn.isButtonActive == True: self.widget_main_bottom_comps0.visible = False self.widget_main_bottom_comps1.visible = False self.widget_main_bottom_comps2.visible = True @@ -1365,7 +1454,8 @@ def NeuralNet_btn_call(self): self.LFAnalyze_btn_cont.visible = True self.NeuralNet_btn_cont.visible = False self.settings["main"]["mode_choice"] = 'LFAnalyze' - self.LFAnalyze_btn.toggle() + #self.LFAnalyze_btn.toggle() + #self.NeuralNet_btn.toggle() self.save_plugin_prefs() def verify_existing_files(self): @@ -1383,7 +1473,7 @@ def verify_existing_files(self): {"section":"deconvolve","out_file":"output_filename", "sub_section":"required", "group":LFvals.PLUGIN_ARGS['deconvolve']['output_filename']['group']}, {"section":"projections","out_file":"output_filename_lightfield", "group":LFvals.PLUGIN_ARGS['projections']['output_filename_lightfield']['group']}, {"section":"projections","out_file":"output_filename_volume", "group":LFvals.PLUGIN_ARGS['projections']['output_filename_volume']['group']}, - {"section":"lfmnet","out_file":"output_filename", "group":LFvals.PLUGIN_ARGS['lfmnet']['output_filename']['group']} + {"section":"lfmnet","out_file":"output_filename", "sub_section":"deconvolve", "group":LFvals.PLUGIN_ARGS['lfmnet']['output_filename']['group']} ] _alert_symbol = ' ⚠' @@ -1747,7 +1837,7 @@ def write_meta(self): for section in ['calibrate','rectify','deconvolve','hw']: meta_data[section] = {} for prop in LFvals.PLUGIN_ARGS[section]: - if ("exclude_from_settings" in LFvals.PLUGIN_ARGS[section][prop] and LFvals.PLUGIN_ARGS[section][prop]["exclude_from_settings"] == True) or ("exclude_from_settings" in LFvals.PLUGIN_ARGS[section][prop] and LFvals.PLUGIN_ARGS[section][prop]["exclude_from_settings"] == True): + if ("exclude_from_settings" in LFvals.PLUGIN_ARGS[section][prop] and LFvals.PLUGIN_ARGS[section][prop]["exclude_from_settings"] == True): pass else: if LFvals.PLUGIN_ARGS[section][prop]["type"] in ["file","folder","str"]: @@ -1773,16 +1863,19 @@ def read_meta(self): for prop in meta_data[section]: if prop in self.gui_elms[section] and prop in meta_data[section]: try: - if self.gui_elms[section][prop].widget_type == "ComboBox": - if meta_data[section][prop] in self.gui_elms[section][prop].choices: - self.gui_elms[section][prop].value = meta_data[section][prop] - elif len(self.gui_elms[section][prop].choices) == 0: - #self.gui_elms[section][prop].value = "" - pass - else: - self.gui_elms[section][prop].value = self.gui_elms[section][prop].choices[0] + if ("exclude_from_settings" in LFvals.PLUGIN_ARGS[section][prop] and LFvals.PLUGIN_ARGS[section][prop]["exclude_from_settings"] == True): + pass else: - self.gui_elms[section][prop].value = meta_data[section][prop] + if self.gui_elms[section][prop].widget_type == "ComboBox": + if meta_data[section][prop] in self.gui_elms[section][prop].choices: + self.gui_elms[section][prop].value = meta_data[section][prop] + elif len(self.gui_elms[section][prop].choices) == 0: + #self.gui_elms[section][prop].value = "" + pass + else: + self.gui_elms[section][prop].value = self.gui_elms[section][prop].choices[0] + else: + self.gui_elms[section][prop].value = meta_data[section][prop] except Exception as e: print(self.gui_elms[section][prop].widget_type) print(e) @@ -1797,14 +1890,14 @@ def read_meta(self): return False def get_preset_name(self): - text, ok = QInputDialog.getText(QWidget(), 'Input Dialog', 'Enter preset name:') + text, ok = QInputDialog.getText(self.logo_label.native, 'Input Dialog', 'Enter preset name:') if ok: if "preset_choices" in self.settings: for preset in self.settings["preset_choices"]: if preset == text: qm = QMessageBox - ret = qm.question(QWidget(),'', "Preset name already exists, overwirte ?", qm.Yes | qm.No) + ret = qm.question(self.logo_label.native, 'napari-LF', "Preset name already exists, overwirte ?", qm.Yes | qm.No) if ret == qm.Yes: return (str(text)) else: @@ -1873,6 +1966,9 @@ def create_widget(props): widget.min_width = 100 widget.native.setStyleSheet("background-color:black;") + if widget.widget_type == "TextEdit": + widget.native.setPlaceholderText(props['label']) + if widget.widget_type == "SpinBox": if "max" in props: widget.max = props["max"] @@ -1968,13 +2064,18 @@ def setContentLayout(self, layout): content_animation.setEndValue(content_height) class PicButton(QAbstractButton): - def __init__(self, pixmap, pixmap_hover, pixmap_pressed, parent=None): + def __init__(self, pixmap, pixmap_hover, pixmap_pressed, parent=None, use_as_toggle=False): super(PicButton, self).__init__(parent) self.pixmap = pixmap - self.pixmap_hover = pixmap_hover + self.pixmap_hover = pixmap_pressed if not use_as_toggle else pixmap_hover self.pixmap_pressed = pixmap_pressed - self.setCheckable(True) + if use_as_toggle: + self.setCheckable(True) + else: + self.setCheckable(False) self.setVisible(True) + self.isButtonActive = False + self.setCursor(QCursor(QtCore.Qt.PointingHandCursor)) def paintEvent(self, event): pix = self.pixmap_hover if self.underMouse() else self.pixmap diff --git a/src/napari_lf/_widgetLF_vals.py b/src/napari_lf/_widgetLF_vals.py index 0726d47..b5f8968 100644 --- a/src/napari_lf/_widgetLF_vals.py +++ b/src/napari_lf/_widgetLF_vals.py @@ -18,7 +18,7 @@ NeuralNet_logo_btn_act_img = os.path.join(currentdir, 'resources/logos/nn_logo_3d_act.png') loading_img = os.path.join(currentdir, 'resources/loading.gif') -examples_folder = os.path.join(currentdir, 'examples/antleg') +examples_folder = os.path.join(currentdir, 'examples/GUVExperim1') lfa_folder = os.path.join(currentdir, 'lfa') q_icon_img = QIcon(icon_img) @@ -67,7 +67,7 @@ "default":"metadata.txt","label":"Metadata file","help":"Select the name of the metadata file that will be produced for the dataset.","type":"str","enabled":True,"visible":False }, "comments":{ - "default":"","prop":"--comments","label":"Comments","help":"Comments from Acquisition and Processing","type":"str","type":"text" + "default":"","prop":"--comments","label":"Comments from Acquisition and Processing","help":"Comments from Acquisition and Processing","type":"str","type":"text" }, "presets":{ "default":"","label":"Presets","help":"Save/Load parameters from presets.","type":"sel","options":[""] @@ -116,7 +116,7 @@ "prop":"--platform-id","label":"Select platform","dest":"platform_id","type":"int","default":0,"help":"Force lfdeconvolve to use a specific OpenCL Platform on your system." }, "use_single_prec":{ - "prop":"--use-single-precision","label":"Use single precision","action":"store_true","dest":"use_sing_prec","type":"bool","default":False,"help":"Use single precision float instead of double." + "prop":"--use-single-precision","label":"Use single precision","action":"store_true","dest":"use_sing_prec","type":"bool","default":True,"help":"Use single precision float instead of double." }, "disable_gpu":{ "prop":"--disable-gpu","action":"store_true","label":"Disable GPU","dest":"disable_gpu","type":"bool","default":False,"help":"Disable GPU deconvolution and use software implementation instead." @@ -234,7 +234,7 @@ "prop":"--skip-subpixel-alignment","action":"store_true","label":"Skip subpixel alignment","dest":"skip_subpixel_alignment","type":"bool","default":False,"help":"Skip subpixel alignment for determining lenslet centers.","group":"Other Options" }, "num_threads":{ - "prop":"--num-threads","label":"Number of CPU threads","dest":"num_threads","type":"int","default":min(10,multiprocessing.cpu_count()),"help":"Set the number of CPU threads to use when generating the raydb.","group":"Other Options","max":multiprocessing.cpu_count(), "min":1 + "prop":"--num-threads","label":"Number of CPU threads","dest":"num_threads","type":"int","default":min(10,multiprocessing.cpu_count()),"help":"Set the number of CPU threads to use when generating the raydb.","group":"Other Options","max":multiprocessing.cpu_count(), "min":1, "exclude_from_settings":True }, "pinhole_filename":{ "prop":"--pinhole","label":"Pinhole filename","dest":"pinhole_filename","type":"str","default":"","help":"After calibrating save the rectified light field as a rectified sub-aperture image.","group":"Other Options" @@ -387,22 +387,28 @@ # ======= LFMNet ============ # =============================== "input_file":{ - "prop":"input_file","label":"Light field image","dest":"input_file","type":"sel","default":"","options":[""],"help":"Supply at least one light field image to rectify.","cat":"required","img_folder_file":True,"group":"Files" + "prop":"input_file","label":"Light field image","dest":"input_file","type":"sel","default":"","options":[""],"help":"Supply at least one light field image to rectify.","cat":"required","img_folder_file":True,"group":"Files","cat":"deconvolve" }, - # "calibration_file":{ - # "prop":"calibration_file","label":"Calibration file","dest":"calibration_file","type":"sel","default":"","options":[""],"help":"Specify the calibration file to use for rectification.","cat":"required","img_folder_file":True,"group":"Files" - # }, + #"calibration_file":{ + # "prop":"calibration_file","label":"Calibration file","dest":"calibration_file","type":"sel","default":"","options":[""],"help":"Specify the calibration file to use for rectification.","cat":"required","img_folder_file":True,"group":"Files","cat":"deconvolve" + #}, "input_model":{ - "prop":"input_model","label":"Neural net model","dest":"input_model","type":"sel","default":"","options":[""],"help":"","exclude_from_args":True,"exclude_from_settings":True,"group":"Files" + "prop":"input_model","label":"Select Model","dest":"input_model","type":"sel","default":"","options":[""],"help":"","exclude_from_args":True,"exclude_from_settings":True,"group":"Files","cat":"deconvolve" }, "input_model_prop_viewer":{ - "prop":"input_model_prop_viewer","label":"Model Prop Viewer","dest":"input_model_prop_viewer","default":"","options":[""],"help":"","exclude_from_args":True,"exclude_from_settings":True,"group":"Files", "type":"text","group":"Network Model Inspector","exclude_from_settings":True,"exclude_from_args":True,"read_only":True,"no_label_layout_style":True + "prop":"input_model_prop_viewer","label":"","dest":"input_model_prop_viewer","default":"","options":[""],"help":"Model Prop Viewer","exclude_from_args":True,"exclude_from_settings":True,"group":"Files", "type":"text","group":"Network Model Inspector","exclude_from_settings":True,"exclude_from_args":True,"read_only":True,"no_label_layout_style":True,"cat":"deconvolve" }, "output_filename":{ - "prop":"output_file","label":"Output image stack","dest":"output_filename","type":"str","default":"output_network_stack.tif","help":"Specify the output filename.","cat":"required","img_folder_file":True,"group":"Files" + "prop":"output_file","label":"Output image stack","dest":"output_filename","type":"str","default":"output_network_stack.tif","help":"Specify the output filename.","cat":"required","img_folder_file":True,"group":"Files","cat":"deconvolve" }, "input_model_btn":{ - "prop":"input_model_btn","label":"Deconvolve","dest":"input_model_btn","type":"PushButton","help":"","exclude_from_args":True,"exclude_from_settings":True,"group":"Files","visible":dev_true + "prop":"input_model_btn","label":"Deconvolve","dest":"input_model_btn","type":"PushButton","help":"","exclude_from_args":True,"exclude_from_settings":True,"group":"Files","visible":False,"cat":"deconvolve" + }, + "training_label":{ + "prop":"training_label","label":"Neural network training for Napari-LF\n\nNapari-LF neural net integration relies on Pytorch-lightning (PL) workflow. Which provides general functions for loading data, training, inference, etc. That can be used with any neural network. This Jupyter Notebook is intended for preparing a network to use with Napari-LF.","default":"","help":"Neural Net Training text","type":"text","exclude_from_settings":True,"cat":"training","enabled":False + }, + "training_btn":{ + "prop":"training_btn","label":"Start Neural Net (Jupyter Notebook)","dest":"training_btn","type":"PushButton","help":"Start Neural Net (Jupyter Notebook)","exclude_from_args":True,"exclude_from_settings":True,"cat":"training" } } } diff --git a/src/napari_lf/examples/seaurchin/metadata.txt b/src/napari_lf/examples/seaurchin/metadata.txt new file mode 100644 index 0000000..5b0fbc3 --- /dev/null +++ b/src/napari_lf/examples/seaurchin/metadata.txt @@ -0,0 +1,75 @@ +{ + "main": { + "comments": "" + }, + "calibrate": { + "radiometry_frame_file": "radiometry_frame.tif", + "dark_frame_file": "dark_frame.tif", + "output_filename": "calibration.lfc", + "synthetic_lf": false, + "use_ray_optics": false, + "voxels_as_points": false, + "align_radiometry": false, + "ulens_pitch": 125.0, + "pixel_size": 7.4, + "ulens_focal_length": 2500.0, + "ulens_focal_distance": 2433.0, + "objective_magnification": 20, + "objective_na": 0.5, + "tubelens_focal_length": 200.0, + "center_wavelength": 482.0, + "medium_index": 1.33, + "ulens_fill_factor": 1.0, + "pixel_fill_factor": 1.0, + "ulens_profile": "rect", + "num_slices": 10, + "um_per_slice": 5.0, + "supersample": 4, + "z_center": 0.0, + "affine_alignment": false, + "isometry_alignment": false, + "chief_ray_image": false, + "crop_center_lenslets": false, + "skip_alignment": false, + "skip_subpixel_alignment": false, + "pinhole_filename": "", + "lenslet_filename": "", + "debug": false + }, + "rectify": { + "input_file": "light_field.tif", + "calibration_file": null, + "output_filename": "rectified.png", + "subaperture": false, + "output_pixels_per_lenslet": "" + }, + "deconvolve": { + "input_file": "light_field.tif", + "calibration_file": null, + "output_filename": "output_stack.tif", + "solver": "rl", + "alpha": 1.6, + "multiscale_smoothing": false, + "save_multiscale": false, + "regularization_lambda": 0.0, + "regularization_lambda2": 0.0, + "max_iter": 15, + "conv_thresh": 0.0, + "readnoise_variance": 0.0, + "background_level": 1.0, + "focalstack": false, + "remove_grid": false, + "pinhole_filename": "", + "decon_type": "algebraic", + "reg_factor": 100.0, + "h5py_cov_filename": "tests/covariance_blocks.h5", + "benchmark": false, + "log_convergence": false + }, + "hw": { + "gpu_id": "NVIDIA CUDA", + "platform_id": "GeForce GT 650M", + "use_single_prec": false, + "disable_gpu": false + } +} \ No newline at end of file