From 872c1962a751e4dc2850792e1379843bcffa0097 Mon Sep 17 00:00:00 2001 From: Sharon Fitzpatrick Date: Mon, 23 Oct 2023 08:47:33 -0700 Subject: [PATCH] #197 update settings UI --- src/coastseg/models_UI.py | 92 +++++++++++++++++++++++-------------- src/coastseg/settings_UI.py | 64 ++++++++++++++++++++++---- 2 files changed, 113 insertions(+), 43 deletions(-) diff --git a/src/coastseg/models_UI.py b/src/coastseg/models_UI.py index 090bbaef..117dbb57 100644 --- a/src/coastseg/models_UI.py +++ b/src/coastseg/models_UI.py @@ -1,28 +1,24 @@ -# standard python imports -import os import glob import logging +import os -# internal python imports -from coastseg import zoo_model -from coastseg import settings_UI -from coastseg import common -from coastseg import file_utilities +from IPython.display import display +from coastseg import common, file_utilities, settings_UI, zoo_model from coastseg.tide_correction import compute_tidal_corrections from coastseg.upload_feature_widget import FileUploader - -# external python imports -import ipywidgets -from IPython.display import display -from ipywidgets import Button -from ipywidgets import HBox -from ipywidgets import VBox -from ipywidgets import Layout -from ipywidgets import HTML -from ipywidgets import RadioButtons -from ipywidgets import Output from ipyfilechooser import FileChooser -from ipywidgets import FloatText +from ipywidgets import ( + Accordion, + Button, + Dropdown, + FloatText, + HBox, + HTML, + Layout, + Output, + Text, + VBox, +) # icons sourced from https://fontawesome.com/v4/icons/ @@ -152,7 +148,7 @@ def get_shoreline_session_name( def get_shoreline_session_selection(self): output = Output() - self.shoreline_session_name_text = ipywidgets.Text( + self.shoreline_session_name_text = Text( value="", placeholder="Enter name", description="Extracted Shoreline Session Name:", @@ -160,7 +156,7 @@ def get_shoreline_session_selection(self): style={"description_width": "initial"}, ) - enter_button = ipywidgets.Button(description="Enter") + enter_button = Button(description="Enter") @output.capture(clear_output=True) def enter_clicked(btn): @@ -179,7 +175,7 @@ def enter_clicked(btn): def get_session_selection(self): output = Output() - self.session_name_text = ipywidgets.Text( + self.session_name_text = Text( value="", placeholder="Enter a session name", description="Session Name:", @@ -187,7 +183,7 @@ def get_session_selection(self): style={"description_width": "initial"}, ) - enter_button = ipywidgets.Button(description="Enter") + enter_button = Button(description="Enter") @output.capture(clear_output=True) def enter_clicked(btn): @@ -204,12 +200,40 @@ def enter_clicked(btn): session_name_controls = HBox([self.session_name_text, enter_button]) return VBox([session_name_controls, output]) - def create_dashboard(self): - model_choices_box = HBox( - [self.model_input_dropdown, self.model_dropdown, self.model_implementation] + def get_adv_model_settings_section(self): + # declare settings widgets + settings = { + "model_implementation": self.model_implementation, + "otsu": self.otsu_radio, + "tta": self.tta_radio, + } + return VBox([widget for widget_name, widget in settings.items()]) + + def get_basic_model_settings_section(self): + # declare settings widgets + settings = { + "model_input": self.model_input_dropdown, + "model_type": self.model_dropdown, + } + # create settings vbox + return VBox([widget for widget_name, widget in settings.items()]) + + def get_model_settings_accordion(self): + # create settings accordion widget + settings_accordion = Accordion( + children=[ + self.get_basic_model_settings_section(), + self.get_adv_model_settings_section(), + ] ) - checkboxes = HBox([self.otsu_radio, self.tta_radio]) + # settings_accordion.set_title(0, "Settings") + settings_accordion.set_title(0, "Basic Model Settings") + settings_accordion.set_title(1, "Advanced Model Settings") + settings_accordion.selected_index = 0 + return settings_accordion + + def create_dashboard(self): # run model controls run_model_buttons = VBox( [ @@ -244,8 +268,7 @@ def create_dashboard(self): self.tidal_correct_file_row = HBox([]) display( self.settings_dashboard.render(), - checkboxes, - model_choices_box, + self.get_model_settings_accordion(), run_model_buttons, HBox([self.clear_run_model_btn(), UI_Models.run_model_view]), self.file_row, @@ -317,7 +340,7 @@ def tidally_correct_button_clicked(self, button): ) def _create_widgets(self): - self.model_implementation = RadioButtons( + self.model_implementation = Dropdown( options=["ENSEMBLE", "BEST"], value="BEST", description="Select:", @@ -325,7 +348,7 @@ def _create_widgets(self): ) self.model_implementation.observe(self.handle_model_implementation, "value") - self.otsu_radio = RadioButtons( + self.otsu_radio = Dropdown( options=["Enabled", "Disabled"], value="Disabled", description="Otsu Threshold:", @@ -334,7 +357,7 @@ def _create_widgets(self): ) self.otsu_radio.observe(self.handle_otsu, "value") - self.tta_radio = RadioButtons( + self.tta_radio = Dropdown( options=["Enabled", "Disabled"], value="Disabled", description="Test Time Augmentation:", @@ -342,8 +365,7 @@ def _create_widgets(self): style={"description_width": "initial"}, ) self.tta_radio.observe(self.handle_tta, "value") - - self.model_input_dropdown = ipywidgets.RadioButtons( + self.model_input_dropdown = Dropdown( options=["RGB", "MNDWI", "NDWI", "RGB+MNDWI+NDWI"], value="RGB", description="Model Input:", @@ -351,7 +373,7 @@ def _create_widgets(self): ) self.model_input_dropdown.observe(self.handle_model_input_change, names="value") - self.model_dropdown = ipywidgets.RadioButtons( + self.model_dropdown = Dropdown( options=self.RGB_models, value=self.RGB_models[0], description="Select Model:", diff --git a/src/coastseg/settings_UI.py b/src/coastseg/settings_UI.py index e10a95c5..add01e8c 100644 --- a/src/coastseg/settings_UI.py +++ b/src/coastseg/settings_UI.py @@ -6,6 +6,11 @@ from ipywidgets import BoundedFloatText from ipywidgets import Select from ipywidgets import BoundedIntText +from ipywidgets import Accordion + + +def str_to_bool(var: str) -> bool: + return var == "True" class Settings_UI: @@ -23,6 +28,7 @@ def set_settings(self, **kwargs): def get_settings(self) -> dict: settings = { + "apply_cloud_mask": str_to_bool(self.apply_cloud_mask_toggle.value), "max_dist_ref": self.shoreline_buffer_slider.value, "along_dist": self.alongshore_distance_slider.value, "dist_clouds": self.cloud_slider.value, @@ -243,7 +249,7 @@ def get_cloud_slider(self): def get_cloud_threshold_slider(self): instr = HTML( value="Cloud Threshold \ -
- Maximum percetange of cloud pixels allowed" +
- Maximum percentage of cloud pixels allowed" ) self.cloud_threshold_slider = ipywidgets.FloatSlider( value=0.5, @@ -300,23 +306,65 @@ def get_min_chainage_text(self) -> VBox: ) return VBox([label, self.min_chainage_text]) + def get_apply_could_mask_toggle(self): + instr = HTML( + value="Cloud Mask Toggle \ +
- Defaults to True. Switch to False to turn off cloud masking." + ) + self.apply_cloud_mask_toggle = ipywidgets.ToggleButtons( + options=["True", "False"], + description="Apply Cloud Masking", + disabled=False, + tooltips=[ + "Cloud Masking On", + "Cloud Masking Off", + ], + ) + return VBox([instr, self.apply_cloud_mask_toggle]) + def render(self): - # return a vbox of all the settings + # create settings accordion widget + settings_accordion = Accordion( + children=[ + self.get_basic_settings_section(), + self.get_advanced_settings_section(), + ] + ) + # settings_accordion.set_title(0, "Settings") + settings_accordion.set_title(0, "Basic Settings") + settings_accordion.set_title(1, "Advanced Settings") + settings_accordion.selected_index = 0 + + return settings_accordion + + def get_advanced_settings_section(self): + # declare settings widgets settings = { - "min_length_sl_slider": self.get_min_length_sl_slider(), - "beach_area_slider": self.get_beach_area_slider(), - "shoreline_buffer_slider": self.get_shoreline_buffer_slider(), - "cloud_slider": self.get_cloud_slider(), - "cloud_threshold_slider": self.get_cloud_threshold_slider(), "along_dist": self.get_alongshore_distance_slider(), + "min_points": self.get_min_points_text(), "max_std": self.get_max_std_text(), "max_range": self.get_max_range_text(), "min_chainage": self.get_min_chainage_text(), "multiple_inter": self.get_outliers_mode(), "prc_multiple": self.get_prc_multiple_text(), - "percent_no_data": self.get_no_data_slider(), } + + # create settings vbox + settings_vbox = VBox([widget for widget_name, widget in settings.items()]) + return settings_vbox + + def get_basic_settings_section(self): + # declare settings widgets + settings = { + "shoreline_buffer_slider": self.get_shoreline_buffer_slider(), + "min_length_sl_slider": self.get_min_length_sl_slider(), + "beach_area_slider": self.get_beach_area_slider(), + "cloud_slider": self.get_cloud_slider(), + "apply_cloud_mask": self.get_apply_could_mask_toggle(), + "cloud_threshold_slider": self.get_cloud_threshold_slider(), + } + # create settings vbox settings_vbox = VBox([widget for widget_name, widget in settings.items()]) return settings_vbox