From bd29b6761a21779802c343255770bbc32a0737e1 Mon Sep 17 00:00:00 2001 From: Walter Baccinelli Date: Fri, 19 Apr 2024 10:46:04 +0200 Subject: [PATCH 01/11] changed button text --- eit_dash/pages/preprocessing.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/eit_dash/pages/preprocessing.py b/eit_dash/pages/preprocessing.py index 7539767..422bcb0 100644 --- a/eit_dash/pages/preprocessing.py +++ b/eit_dash/pages/preprocessing.py @@ -68,7 +68,7 @@ html.P(), dbc.Row( dbc.Button( - "Select stable periods", + "Select periods", id=ids.OPEN_SELECT_PERIODS_BUTTON, disabled=False, ), From 8c6e8fd5272fe4c496a29272b6e0c1a488cba721 Mon Sep 17 00:00:00 2001 From: Walter Baccinelli Date: Fri, 19 Apr 2024 11:35:14 +0200 Subject: [PATCH 02/11] automatic filling in selection method and dataset --- eit_dash/callbacks/preprocessing_callbacks.py | 74 ++++++++++--------- eit_dash/pages/analyze.py | 1 + eit_dash/pages/preprocessing.py | 16 +++- 3 files changed, 55 insertions(+), 36 deletions(-) diff --git a/eit_dash/callbacks/preprocessing_callbacks.py b/eit_dash/callbacks/preprocessing_callbacks.py index 11c4e65..98a56c8 100644 --- a/eit_dash/callbacks/preprocessing_callbacks.py +++ b/eit_dash/callbacks/preprocessing_callbacks.py @@ -65,7 +65,10 @@ def create_resampling_card(loaded_data): for data in loaded_data ] - options = [{"label": f'{data["Name"]}', "value": str(i)} for i, data in enumerate(loaded_data)] + options = [ + {"label": f'{data["Name"]}', "value": str(i)} + for i, data in enumerate(loaded_data) + ] return row, options @@ -76,7 +79,10 @@ def get_loaded_data(): for dataset in loaded_data: name = dataset.label if dataset.continuous_data: - data += [{"Name": name, "Data type": channel} for channel in dataset.continuous_data] + data += [ + {"Name": name, "Data type": channel} + for channel in dataset.continuous_data + ] if dataset.eit_data: data.append( { @@ -212,7 +218,7 @@ def open_periods_modal(open_click, confirm_click) -> bool: @callback( Output(ids.PERIODS_SELECTION_SELECT_DATASET, "children"), Input(ids.PERIODS_METHOD_SELECTOR, "value"), - prevent_initial_call=True, + prevent_initial_call=False, ) def populate_periods_selection_modal(method): """Populate modal body according to the selected method for stable periods selection.""" @@ -220,13 +226,17 @@ def populate_periods_selection_modal(method): if int_value == PeriodsSelectMethods.Manual.value: signals = data_object.get_all_sequences() - options = [{"label": sequence.label, "value": index} for index, sequence in enumerate(signals)] + options = [ + {"label": sequence.label, "value": index} + for index, sequence in enumerate(signals) + ] body = [ html.H6("Select one dataset"), dbc.Select( id=ids.PREPROCESING_DATASET_SELECT, options=options, + value=str(options[0]["value"]), ), ] else: @@ -235,30 +245,6 @@ def populate_periods_selection_modal(method): return body -@callback( - Output(ids.PREPROCESING_SIGNALS_CHECKBOX_ROW, "children"), - Input(ids.PREPROCESING_DATASET_SELECT, "value"), - prevent_initial_call=True, -) -def populate_periods_selection_datasets(dataset): - """Activated when a dataset is selected. Populates signals selection in the manual selection case.""" - if dataset: - options = get_signal_options( - data_object.get_sequence_at(int(dataset)), - show_eit=True, - ) - return [ - html.H6("Select the signals to be displayed"), - dcc.Checklist( - id=ids.PREPROCESING_SIGNALS_CHECKBOX, - inputStyle=styles.CHECKBOX_INPUT, - options=options, - ), - ] - - return [] - - @callback( Output(ids.PERIODS_SELECTION_DIV, "hidden"), Input(ids.PREPROCESING_SIGNALS_CHECKBOX, "value"), @@ -276,6 +262,7 @@ def show_selection_div(signals): [ Output(ids.PREPROCESING_PERIODS_GRAPH, "figure", allow_duplicate=True), Output(ids.PREPROCESING_PERIODS_GRAPH, "style", allow_duplicate=True), + Output(ids.PREPROCESING_SIGNALS_CHECKBOX_ROW, "children"), ], [ Input(ids.PREPROCESING_DATASET_SELECT, "value"), @@ -285,7 +272,7 @@ def show_selection_div(signals): def initialize_figure( dataset, ): - """When the dataset is selected, the figure is initialized.""" + """When the dataset is selected, the figure and the checkbox are initialized.""" # the callback is run also when populating the dataset options. # In this case we don't want to run it if not dataset: @@ -304,10 +291,24 @@ def initialize_figure( if saved_periods := data_object.get_dataset_stable_periods(int(dataset)): current_figure = mark_selected_periods(current_figure, saved_periods) + options = get_signal_options( + data_object.get_sequence_at(int(dataset)), + show_eit=True, + ) + + signals_checkbox = [ + html.H6("Select the signals to be displayed"), + dcc.Checklist( + id=ids.PREPROCESING_SIGNALS_CHECKBOX, + inputStyle=styles.CHECKBOX_INPUT, + options=options, + ), + ] + # THIS IS A TEMPORARY PATCH time.sleep(2) - return current_figure, style + return current_figure, style, signals_checkbox @callback( @@ -458,7 +459,11 @@ def remove_period(n_clicks, container, figure): # remove from the figure (if the figure exists) try: - figure["data"] = [trace for trace in figure["data"] if "meta" not in trace or trace["meta"]["uid"] != input_id] + figure["data"] = [ + trace + for trace in figure["data"] + if "meta" not in trace or trace["meta"]["uid"] != input_id + ] except TypeError: contextlib.suppress(Exception) @@ -564,9 +569,12 @@ def enable_apply_button( if ( (int(filter_selected) == FilterTypes.lowpass.value and co_high and co_high > 0) - or (int(filter_selected) == FilterTypes.highpass.value and co_low and co_low > 0) or ( - int(filter_selected) in [FilterTypes.bandpass.value, FilterTypes.bandstop.value] + int(filter_selected) == FilterTypes.highpass.value and co_low and co_low > 0 + ) + or ( + int(filter_selected) + in [FilterTypes.bandpass.value, FilterTypes.bandstop.value] and co_low and co_low > 0 and co_high diff --git a/eit_dash/pages/analyze.py b/eit_dash/pages/analyze.py index 9df3284..e0c6a74 100644 --- a/eit_dash/pages/analyze.py +++ b/eit_dash/pages/analyze.py @@ -33,6 +33,7 @@ html.P(), html.Div( [ + dbc.Row(html.H6("Select a period to view the results")), dbc.Row(dbc.Select(id=ids.ANALYZE_SELECT_PERIOD_VIEW)), dbc.Row( dcc.Graph(id=ids.EELI_RESULTS_GRAPH, style=styles.EMPTY_ELEMENT), diff --git a/eit_dash/pages/preprocessing.py b/eit_dash/pages/preprocessing.py index 422bcb0..6e75476 100644 --- a/eit_dash/pages/preprocessing.py +++ b/eit_dash/pages/preprocessing.py @@ -100,7 +100,10 @@ [ dbc.Select( id=ids.SYNC_METHOD_SELECTOR, - options=[{"label": method.name, "value": method.value} for method in SynchMethods], + options=[ + {"label": method.name, "value": method.value} + for method in SynchMethods + ], value=str(SynchMethods.manual.value), ), html.P(), @@ -175,7 +178,11 @@ html.H6("Periods selection method"), dbc.Select( id=ids.PERIODS_METHOD_SELECTOR, - options=[{"label": method.name, "value": method.value} for method in PeriodsSelectMethods], + options=[ + {"label": method.name, "value": method.value} + for method in PeriodsSelectMethods + ], + value=str(PeriodsSelectMethods.Manual.value), ), modal_selection_body, ], @@ -301,7 +308,10 @@ html.H6("Select a filter"), dbc.Select( id=ids.FILTER_SELECTOR, - options=[{"label": filt.name, "value": filt.value} for filt in FilterTypes], + options=[ + {"label": filt.name, "value": filt.value} + for filt in FilterTypes + ], ), html.P(), filter_params, From 94dc1ab57951be000dac513469eeff1461ec6517 Mon Sep 17 00:00:00 2001 From: Walter Baccinelli Date: Fri, 19 Apr 2024 14:22:15 +0200 Subject: [PATCH 03/11] all signals pre-selected --- eit_dash/callbacks/load_callbacks.py | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/eit_dash/callbacks/load_callbacks.py b/eit_dash/callbacks/load_callbacks.py index 53b84d6..c4aa992 100644 --- a/eit_dash/callbacks/load_callbacks.py +++ b/eit_dash/callbacks/load_callbacks.py @@ -91,6 +91,7 @@ def load_selected_data( @callback( Output(ids.DATA_SELECTOR_OPTIONS, "hidden"), Output(ids.CHECKBOX_SIGNALS, "options"), + Output(ids.CHECKBOX_SIGNALS, "value"), Output(ids.FILE_LENGTH_SLIDER, "figure"), Input(ids.NFILES_PLACEHOLDER, "children"), Input(ids.LOAD_CANCEL_BUTTON, "n_clicks"), @@ -109,16 +110,18 @@ def open_data_selector(data, cancel_load, sig, file_type, fig): if trigger == ids.LOAD_CANCEL_BUTTON: data = None file_data = None + options = ticked = [] if not data: # this is needed, because a figure object must be returned for the graph, even if empty figure = go.Figure() - return True, [], figure + return True, [], [], figure if trigger in [ids.NFILES_PLACEHOLDER, ids.CHECKBOX_SIGNALS]: if trigger == ids.CHECKBOX_SIGNALS: options = get_signal_options(file_data) figure = fig + ticked = sig else: path = Path(data) file_data = load_eit_data( @@ -134,18 +137,25 @@ def open_data_selector(data, cancel_load, sig, file_type, fig): continuous_data=list(file_data.continuous_data), clickable_legend=True, ) + ticked = [s["value"] for s in options] ok = [RAW_EIT_LABEL] - if sig: - ok += [options[s]["label"] for s in sig] + if ticked: + ok += [options[s]["label"] for s in ticked] for s in figure["data"]: if s["name"] in ok: - s["visible"] = True + # raw signal visible + if s["name"] == RAW_EIT_LABEL: + s["visible"] = True + else: + # other selected signals are included but toggled off + # (the legend item has to be clicked to make the trace visible) + s["visible"] = "legendonly" else: s["visible"] = False - return False, options, figure + return False, options, ticked, figure @callback( @@ -254,7 +264,9 @@ def list_cwd_files(cwd): full_path = Path(cwd) / filepath is_dir = Path(full_path).is_dir() - extension = filepath.suffix if not filepath.name.startswith(".") else filepath.name + extension = ( + filepath.suffix if not filepath.name.startswith(".") else filepath.name + ) if is_dir or extension in [".bin", ".txt", ".zri"]: link = html.A( From c6a6983134c641509b89e232cad3ce342c330868 Mon Sep 17 00:00:00 2001 From: Walter Baccinelli Date: Fri, 19 Apr 2024 15:08:43 +0200 Subject: [PATCH 04/11] axis with the same color of line --- eit_dash/utils/common.py | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/eit_dash/utils/common.py b/eit_dash/utils/common.py index 4183d2e..b271b01 100644 --- a/eit_dash/utils/common.py +++ b/eit_dash/utils/common.py @@ -3,6 +3,7 @@ from typing import TYPE_CHECKING import dash_bootstrap_components as dbc +import plotly.colors import plotly.graph_objects as go from dash import html @@ -36,7 +37,10 @@ def create_filter_results_card(parameters: dict) -> dbc.Card: card_list = [ html.H4("Data filtered", className="card-title"), ] - card_list += [dbc.Row(f"{data}: {value}", style=styles.INFO_CARD) for data, value in parameters.items()] + card_list += [ + dbc.Row(f"{data}: {value}", style=styles.INFO_CARD) + for data, value in parameters.items() + ] return dbc.Card(dbc.CardBody(card_list), id=ids.FILTERING_SAVED_CARD) @@ -61,7 +65,10 @@ def create_info_card(dataset: Sequence) -> dbc.Card: html.H4(dataset.label, className="card-title"), html.H6(dataset.eit_data["raw"].vendor, className="card-subtitle"), ] - card_list += [dbc.Row(f"{data}: {value}", style=styles.INFO_CARD) for data, value in info_data.items()] + card_list += [ + dbc.Row(f"{data}: {value}", style=styles.INFO_CARD) + for data, value in info_data.items() + ] return dbc.Card(dbc.CardBody(card_list), id="card-1") @@ -91,7 +98,10 @@ def create_selected_period_card( card_list = [ html.H4(period.label, className="card-title"), ] - card_list += [dbc.Row(f"{data}: {value}", style=styles.INFO_CARD) for data, value in info_data.items()] + card_list += [ + dbc.Row(f"{data}: {value}", style=styles.INFO_CARD) + for data, value in info_data.items() + ] if remove_button: card_list += [ dbc.Button( @@ -130,8 +140,10 @@ def create_slider_figure( x=dataset.continuous_data[RAW_EIT_LABEL].time, y=dataset.continuous_data[RAW_EIT_LABEL].values, name=RAW_EIT_LABEL, + line=dict(color=plotly.colors.DEFAULT_PLOTLY_COLORS[0]), ), ) + figure.update_yaxes(zerolinecolor=plotly.colors.DEFAULT_PLOTLY_COLORS[0]) for n, cont_signal in enumerate(continuous_data): if cont_signal != RAW_EIT_LABEL: @@ -140,6 +152,7 @@ def create_slider_figure( x=dataset.continuous_data[cont_signal].time, y=dataset.continuous_data[cont_signal].values, name=cont_signal, + line=dict(color=plotly.colors.DEFAULT_PLOTLY_COLORS[n + 1]), opacity=0.5, yaxis=f"y{n + 2}", ), @@ -154,6 +167,7 @@ def create_slider_figure( "overlaying": "y", "side": side, "autoshift": True, + "color": plotly.colors.DEFAULT_PLOTLY_COLORS[n + 1], } # layout parameters for multiple y axis From af8d0f995b5579234c9251e80aab851cb1a87abf Mon Sep 17 00:00:00 2001 From: Walter Baccinelli Date: Fri, 19 Apr 2024 15:16:02 +0200 Subject: [PATCH 05/11] added unit measure to y axis --- eit_dash/utils/common.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/eit_dash/utils/common.py b/eit_dash/utils/common.py index b271b01..b92f722 100644 --- a/eit_dash/utils/common.py +++ b/eit_dash/utils/common.py @@ -143,7 +143,10 @@ def create_slider_figure( line=dict(color=plotly.colors.DEFAULT_PLOTLY_COLORS[0]), ), ) - figure.update_yaxes(zerolinecolor=plotly.colors.DEFAULT_PLOTLY_COLORS[0]) + figure.update_yaxes( + color=plotly.colors.DEFAULT_PLOTLY_COLORS[0], + title=f"{RAW_EIT_LABEL} {dataset.continuous_data[RAW_EIT_LABEL].unit}", + ) for n, cont_signal in enumerate(continuous_data): if cont_signal != RAW_EIT_LABEL: @@ -162,7 +165,7 @@ def create_slider_figure( y_position += 0.1 new_y = { - "title": cont_signal, + "title": f"{cont_signal} {dataset.continuous_data[cont_signal].unit}", "anchor": "free", "overlaying": "y", "side": side, From e79820e639960af2b8f435f97b6f34f4c39838db Mon Sep 17 00:00:00 2001 From: Walter Baccinelli Date: Fri, 19 Apr 2024 16:06:11 +0200 Subject: [PATCH 06/11] fix small bug --- eit_dash/callbacks/preprocessing_callbacks.py | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/eit_dash/callbacks/preprocessing_callbacks.py b/eit_dash/callbacks/preprocessing_callbacks.py index 98a56c8..d766b94 100644 --- a/eit_dash/callbacks/preprocessing_callbacks.py +++ b/eit_dash/callbacks/preprocessing_callbacks.py @@ -231,14 +231,18 @@ def populate_periods_selection_modal(method): for index, sequence in enumerate(signals) ] - body = [ - html.H6("Select one dataset"), - dbc.Select( - id=ids.PREPROCESING_DATASET_SELECT, - options=options, - value=str(options[0]["value"]), - ), - ] + body = ( + [ + html.H6("Select one dataset"), + dbc.Select( + id=ids.PREPROCESING_DATASET_SELECT, + options=options, + value=str(options[0]["value"]), + ), + ] + if options + else [] + ) else: body = [] From 42d629afbef6a031ec3064a53fbddb5338e10627 Mon Sep 17 00:00:00 2001 From: Walter Baccinelli Date: Fri, 19 Apr 2024 16:06:45 +0200 Subject: [PATCH 07/11] adding next page button --- eit_dash/callbacks/preprocessing_callbacks.py | 10 ++++++++++ eit_dash/definitions/element_ids.py | 3 +++ eit_dash/definitions/layout_styles.py | 11 +++++++++++ eit_dash/main.py | 14 ++++++++++++++ 4 files changed, 38 insertions(+) diff --git a/eit_dash/callbacks/preprocessing_callbacks.py b/eit_dash/callbacks/preprocessing_callbacks.py index d766b94..74fcbed 100644 --- a/eit_dash/callbacks/preprocessing_callbacks.py +++ b/eit_dash/callbacks/preprocessing_callbacks.py @@ -138,6 +138,16 @@ def load_datasets(title): return [], [], [], None +@callback( + Output(ids.NEXT_PAGE_BUTTON, "href"), + Input(ids.PREPROCESING_TITLE, "children"), +) +def update_next_page_link(_): + """Updates the lnk of the next page button.""" + + return "/analyze" + + @callback( [ Output(ids.OPEN_SYNCH_BUTTON, "disabled"), diff --git a/eit_dash/definitions/element_ids.py b/eit_dash/definitions/element_ids.py index 36955fe..9c01d5e 100644 --- a/eit_dash/definitions/element_ids.py +++ b/eit_dash/definitions/element_ids.py @@ -1,3 +1,6 @@ +NEXT_PAGE_BUTTON = "next=page-button" +NEXT_PAGE_LINK = "next=page-link" + # load page ADD_DATA_BUTTON = "add-data-button" ALERT_LOAD = "alert-load" diff --git a/eit_dash/definitions/layout_styles.py b/eit_dash/definitions/layout_styles.py index cadd320..a9ab37a 100644 --- a/eit_dash/definitions/layout_styles.py +++ b/eit_dash/definitions/layout_styles.py @@ -7,6 +7,17 @@ GRAPH = {} INFO_CARD = {"margin-left": 10} LOAD_RESULTS = {"textAlign": "center"} +NEXT_PAGE_BUTTON = { + "position": "fixed", + "bottom": "35px", + "right": "35px", + "display": "flex", + "align-items": "center", + "background": "transparent", + "color": "blue", + "border": "none", + "font-size": "70px", +} PAGES_LINK = {"fontWeight": "bold", "color": "blue"} SUMMARY_ELEMENT = {"textAlign": "center"} SECTION_TITLE = {"margin-top": "50px"} diff --git a/eit_dash/main.py b/eit_dash/main.py index 3e995e1..aff8aaf 100644 --- a/eit_dash/main.py +++ b/eit_dash/main.py @@ -8,6 +8,7 @@ preprocessing_callbacks, ) from eit_dash.definitions import layout_styles as styles +from eit_dash.definitions import element_ids as ids app.layout = html.Div( [ @@ -43,6 +44,19 @@ style={"textAlign": "center"}, ), page_container, + html.Div( + [ + dbc.NavLink( + dbc.Button( + className="fa fa-arrow-circle-right", + id=ids.NEXT_PAGE_BUTTON, + style=styles.NEXT_PAGE_BUTTON, + ), + href="/preprocessing", + id=ids.NEXT_PAGE_LINK, + ), + ], + ), ], ) From c1ff324d6b92d3b003e97eaf17bda8e3669ee680 Mon Sep 17 00:00:00 2001 From: Walter Baccinelli Date: Fri, 19 Apr 2024 16:46:15 +0200 Subject: [PATCH 08/11] next and previous page button --- eit_dash/callbacks/preprocessing_callbacks.py | 10 ------ eit_dash/definitions/element_ids.py | 15 ++++++-- eit_dash/definitions/layout_styles.py | 11 ++++++ eit_dash/pages/analyze.py | 28 +++++++++++++++ eit_dash/pages/load.py | 34 +++++++++++++++++-- eit_dash/pages/preprocessing.py | 31 +++++++++++++++++ 6 files changed, 115 insertions(+), 14 deletions(-) diff --git a/eit_dash/callbacks/preprocessing_callbacks.py b/eit_dash/callbacks/preprocessing_callbacks.py index 74fcbed..d766b94 100644 --- a/eit_dash/callbacks/preprocessing_callbacks.py +++ b/eit_dash/callbacks/preprocessing_callbacks.py @@ -138,16 +138,6 @@ def load_datasets(title): return [], [], [], None -@callback( - Output(ids.NEXT_PAGE_BUTTON, "href"), - Input(ids.PREPROCESING_TITLE, "children"), -) -def update_next_page_link(_): - """Updates the lnk of the next page button.""" - - return "/analyze" - - @callback( [ Output(ids.OPEN_SYNCH_BUTTON, "disabled"), diff --git a/eit_dash/definitions/element_ids.py b/eit_dash/definitions/element_ids.py index 9c01d5e..b34e973 100644 --- a/eit_dash/definitions/element_ids.py +++ b/eit_dash/definitions/element_ids.py @@ -1,5 +1,15 @@ -NEXT_PAGE_BUTTON = "next=page-button" -NEXT_PAGE_LINK = "next=page-link" +NEXT_PAGE_BUTTON_LOAD = "next-page-button-load" +NEXT_PAGE_LINK_LOAD = "next-page-link-load" +NEXT_PAGE_BUTTON_PREP = "next-page-button-prep" +NEXT_PAGE_LINK_PREP = "next-page-link-prep" +NEXT_PAGE_BUTTON_ANALYZE = "next-page-button-analyze" +NEXT_PAGE_LINK_ANALYZE = "next-page-link-analyze" +PREV_PAGE_BUTTON_LOAD = "next-page-button-load" +PREV_PAGE_LINK_LOAD = "prev-page-link-load" +PREV_PAGE_BUTTON_PREP = "prev-page-button-prep" +PREV_PAGE_LINK_PREP = "prev-page-link-prep" +PREV_PAGE_BUTTON_ANALYZE = "prev-page-button-analyze" +PREV_PAGE_LINK_ANALYZE = "prev-page-link-analyze" # load page ADD_DATA_BUTTON = "add-data-button" @@ -17,6 +27,7 @@ DATASET_CONTAINER = "dataset-container" LOAD_CONFIRM_BUTTON = "load-confirm-button" LOAD_CANCEL_BUTTON = "load-cancel-button" +LOAD_RESULTS_TITLE = "load-results-title" PARENT_DIR = "parent-dir" STORED_CWD = "stored-cwd" SELECT_CONFIRM_BUTTON = "select-confirm-button" diff --git a/eit_dash/definitions/layout_styles.py b/eit_dash/definitions/layout_styles.py index a9ab37a..00e50aa 100644 --- a/eit_dash/definitions/layout_styles.py +++ b/eit_dash/definitions/layout_styles.py @@ -18,6 +18,17 @@ "border": "none", "font-size": "70px", } +PREV_PAGE_BUTTON = { + "position": "fixed", + "bottom": "35px", + "left": "35px", + "display": "flex", + "align-items": "center", + "background": "transparent", + "color": "blue", + "border": "none", + "font-size": "70px", +} PAGES_LINK = {"fontWeight": "bold", "color": "blue"} SUMMARY_ELEMENT = {"textAlign": "center"} SECTION_TITLE = {"margin-top": "50px"} diff --git a/eit_dash/pages/analyze.py b/eit_dash/pages/analyze.py index e0c6a74..1a0e3d7 100644 --- a/eit_dash/pages/analyze.py +++ b/eit_dash/pages/analyze.py @@ -52,5 +52,33 @@ summary, actions, results, + html.Div( + [ + dbc.NavLink( + dbc.Button( + className="fa fa-arrow-circle-right", + id=ids.NEXT_PAGE_BUTTON_ANALYZE, + style=styles.NEXT_PAGE_BUTTON, + disabled=True, + ), + href="", + id=ids.NEXT_PAGE_LINK_ANALYZE, + ), + ], + ), + html.Div( + [ + dbc.NavLink( + dbc.Button( + className="fa fa-arrow-circle-left", + id=ids.PREV_PAGE_BUTTON_ANALYZE, + style=styles.PREV_PAGE_BUTTON, + disabled=False, + ), + href="/preprocessing", + id=ids.PREV_PAGE_LINK_ANALYZE, + ), + ], + ), ], ) diff --git a/eit_dash/pages/load.py b/eit_dash/pages/load.py index f9dcf91..43625a3 100644 --- a/eit_dash/pages/load.py +++ b/eit_dash/pages/load.py @@ -13,7 +13,7 @@ results = dbc.Col( [ - html.H2("Results", style=styles.COLUMN_TITLE), + html.H2("Results", style=styles.COLUMN_TITLE, id=ids.LOAD_RESULTS_TITLE), html.Div(id=ids.DATASET_CONTAINER, style=styles.LOAD_RESULTS), ], ) @@ -22,7 +22,10 @@ [ dbc.Select( id=ids.INPUT_TYPE_SELECTOR, - options=[{"label": filetype.name, "value": filetype.value} for filetype in InputFiletypes], + options=[ + {"label": filetype.name, "value": filetype.value} + for filetype in InputFiletypes + ], value=str(InputFiletypes.Sentec.value), ), html.P(), @@ -160,5 +163,32 @@ results, placeholder_nfiles, modal_dialog, + html.Div( + [ + dbc.NavLink( + dbc.Button( + className="fa fa-arrow-circle-right", + id=ids.NEXT_PAGE_BUTTON_LOAD, + style=styles.NEXT_PAGE_BUTTON, + ), + href="/preprocessing", + id=ids.NEXT_PAGE_LINK_LOAD, + ), + ], + ), + html.Div( + [ + dbc.NavLink( + dbc.Button( + className="fa fa-arrow-circle-left", + id=ids.PREV_PAGE_BUTTON_LOAD, + style=styles.PREV_PAGE_BUTTON, + disabled=True, + ), + href="/", + id=ids.PREV_PAGE_LINK_LOAD, + ), + ], + ), ], ) diff --git a/eit_dash/pages/preprocessing.py b/eit_dash/pages/preprocessing.py index 6e75476..cb17bf1 100644 --- a/eit_dash/pages/preprocessing.py +++ b/eit_dash/pages/preprocessing.py @@ -346,5 +346,36 @@ modal_synchronization, modal_selection, modal_filtering, + html.Div( + [ + dbc.NavLink( + html.Div( + [ + dbc.Button( + className="fa fa-arrow-circle-right", + id=ids.NEXT_PAGE_BUTTON_PREP, + style=styles.NEXT_PAGE_BUTTON, + ), + ] + ), + href="/analyze", + id=ids.NEXT_PAGE_LINK_PREP, + ), + ], + ), + html.Div( + [ + dbc.NavLink( + dbc.Button( + className="fa fa-arrow-circle-left", + id=ids.PREV_PAGE_BUTTON_PREP, + style=styles.PREV_PAGE_BUTTON, + disabled=False, + ), + href="/", + id=ids.PREV_PAGE_LINK_PREP, + ), + ], + ), ], ) From 3c68e543137c0c9ffa292037f8619e8419ded5a7 Mon Sep 17 00:00:00 2001 From: Walter Baccinelli Date: Fri, 19 Apr 2024 16:49:05 +0200 Subject: [PATCH 09/11] formatting --- eit_dash/callbacks/load_callbacks.py | 4 +-- eit_dash/callbacks/preprocessing_callbacks.py | 28 ++++--------------- eit_dash/main.py | 14 ---------- eit_dash/pages/load.py | 5 +--- eit_dash/pages/preprocessing.py | 17 +++-------- eit_dash/utils/common.py | 19 ++++--------- 6 files changed, 17 insertions(+), 70 deletions(-) diff --git a/eit_dash/callbacks/load_callbacks.py b/eit_dash/callbacks/load_callbacks.py index c4aa992..05b10dd 100644 --- a/eit_dash/callbacks/load_callbacks.py +++ b/eit_dash/callbacks/load_callbacks.py @@ -264,9 +264,7 @@ def list_cwd_files(cwd): full_path = Path(cwd) / filepath is_dir = Path(full_path).is_dir() - extension = ( - filepath.suffix if not filepath.name.startswith(".") else filepath.name - ) + extension = filepath.suffix if not filepath.name.startswith(".") else filepath.name if is_dir or extension in [".bin", ".txt", ".zri"]: link = html.A( diff --git a/eit_dash/callbacks/preprocessing_callbacks.py b/eit_dash/callbacks/preprocessing_callbacks.py index d766b94..79ef8bd 100644 --- a/eit_dash/callbacks/preprocessing_callbacks.py +++ b/eit_dash/callbacks/preprocessing_callbacks.py @@ -65,10 +65,7 @@ def create_resampling_card(loaded_data): for data in loaded_data ] - options = [ - {"label": f'{data["Name"]}', "value": str(i)} - for i, data in enumerate(loaded_data) - ] + options = [{"label": f'{data["Name"]}', "value": str(i)} for i, data in enumerate(loaded_data)] return row, options @@ -79,10 +76,7 @@ def get_loaded_data(): for dataset in loaded_data: name = dataset.label if dataset.continuous_data: - data += [ - {"Name": name, "Data type": channel} - for channel in dataset.continuous_data - ] + data += [{"Name": name, "Data type": channel} for channel in dataset.continuous_data] if dataset.eit_data: data.append( { @@ -226,10 +220,7 @@ def populate_periods_selection_modal(method): if int_value == PeriodsSelectMethods.Manual.value: signals = data_object.get_all_sequences() - options = [ - {"label": sequence.label, "value": index} - for index, sequence in enumerate(signals) - ] + options = [{"label": sequence.label, "value": index} for index, sequence in enumerate(signals)] body = ( [ @@ -463,11 +454,7 @@ def remove_period(n_clicks, container, figure): # remove from the figure (if the figure exists) try: - figure["data"] = [ - trace - for trace in figure["data"] - if "meta" not in trace or trace["meta"]["uid"] != input_id - ] + figure["data"] = [trace for trace in figure["data"] if "meta" not in trace or trace["meta"]["uid"] != input_id] except TypeError: contextlib.suppress(Exception) @@ -573,12 +560,9 @@ def enable_apply_button( if ( (int(filter_selected) == FilterTypes.lowpass.value and co_high and co_high > 0) + or (int(filter_selected) == FilterTypes.highpass.value and co_low and co_low > 0) or ( - int(filter_selected) == FilterTypes.highpass.value and co_low and co_low > 0 - ) - or ( - int(filter_selected) - in [FilterTypes.bandpass.value, FilterTypes.bandstop.value] + int(filter_selected) in [FilterTypes.bandpass.value, FilterTypes.bandstop.value] and co_low and co_low > 0 and co_high diff --git a/eit_dash/main.py b/eit_dash/main.py index aff8aaf..3e995e1 100644 --- a/eit_dash/main.py +++ b/eit_dash/main.py @@ -8,7 +8,6 @@ preprocessing_callbacks, ) from eit_dash.definitions import layout_styles as styles -from eit_dash.definitions import element_ids as ids app.layout = html.Div( [ @@ -44,19 +43,6 @@ style={"textAlign": "center"}, ), page_container, - html.Div( - [ - dbc.NavLink( - dbc.Button( - className="fa fa-arrow-circle-right", - id=ids.NEXT_PAGE_BUTTON, - style=styles.NEXT_PAGE_BUTTON, - ), - href="/preprocessing", - id=ids.NEXT_PAGE_LINK, - ), - ], - ), ], ) diff --git a/eit_dash/pages/load.py b/eit_dash/pages/load.py index 43625a3..37bf49a 100644 --- a/eit_dash/pages/load.py +++ b/eit_dash/pages/load.py @@ -22,10 +22,7 @@ [ dbc.Select( id=ids.INPUT_TYPE_SELECTOR, - options=[ - {"label": filetype.name, "value": filetype.value} - for filetype in InputFiletypes - ], + options=[{"label": filetype.name, "value": filetype.value} for filetype in InputFiletypes], value=str(InputFiletypes.Sentec.value), ), html.P(), diff --git a/eit_dash/pages/preprocessing.py b/eit_dash/pages/preprocessing.py index cb17bf1..ca3c2ef 100644 --- a/eit_dash/pages/preprocessing.py +++ b/eit_dash/pages/preprocessing.py @@ -100,10 +100,7 @@ [ dbc.Select( id=ids.SYNC_METHOD_SELECTOR, - options=[ - {"label": method.name, "value": method.value} - for method in SynchMethods - ], + options=[{"label": method.name, "value": method.value} for method in SynchMethods], value=str(SynchMethods.manual.value), ), html.P(), @@ -178,10 +175,7 @@ html.H6("Periods selection method"), dbc.Select( id=ids.PERIODS_METHOD_SELECTOR, - options=[ - {"label": method.name, "value": method.value} - for method in PeriodsSelectMethods - ], + options=[{"label": method.name, "value": method.value} for method in PeriodsSelectMethods], value=str(PeriodsSelectMethods.Manual.value), ), modal_selection_body, @@ -308,10 +302,7 @@ html.H6("Select a filter"), dbc.Select( id=ids.FILTER_SELECTOR, - options=[ - {"label": filt.name, "value": filt.value} - for filt in FilterTypes - ], + options=[{"label": filt.name, "value": filt.value} for filt in FilterTypes], ), html.P(), filter_params, @@ -356,7 +347,7 @@ id=ids.NEXT_PAGE_BUTTON_PREP, style=styles.NEXT_PAGE_BUTTON, ), - ] + ], ), href="/analyze", id=ids.NEXT_PAGE_LINK_PREP, diff --git a/eit_dash/utils/common.py b/eit_dash/utils/common.py index b92f722..580ecf4 100644 --- a/eit_dash/utils/common.py +++ b/eit_dash/utils/common.py @@ -37,10 +37,7 @@ def create_filter_results_card(parameters: dict) -> dbc.Card: card_list = [ html.H4("Data filtered", className="card-title"), ] - card_list += [ - dbc.Row(f"{data}: {value}", style=styles.INFO_CARD) - for data, value in parameters.items() - ] + card_list += [dbc.Row(f"{data}: {value}", style=styles.INFO_CARD) for data, value in parameters.items()] return dbc.Card(dbc.CardBody(card_list), id=ids.FILTERING_SAVED_CARD) @@ -65,10 +62,7 @@ def create_info_card(dataset: Sequence) -> dbc.Card: html.H4(dataset.label, className="card-title"), html.H6(dataset.eit_data["raw"].vendor, className="card-subtitle"), ] - card_list += [ - dbc.Row(f"{data}: {value}", style=styles.INFO_CARD) - for data, value in info_data.items() - ] + card_list += [dbc.Row(f"{data}: {value}", style=styles.INFO_CARD) for data, value in info_data.items()] return dbc.Card(dbc.CardBody(card_list), id="card-1") @@ -98,10 +92,7 @@ def create_selected_period_card( card_list = [ html.H4(period.label, className="card-title"), ] - card_list += [ - dbc.Row(f"{data}: {value}", style=styles.INFO_CARD) - for data, value in info_data.items() - ] + card_list += [dbc.Row(f"{data}: {value}", style=styles.INFO_CARD) for data, value in info_data.items()] if remove_button: card_list += [ dbc.Button( @@ -140,7 +131,7 @@ def create_slider_figure( x=dataset.continuous_data[RAW_EIT_LABEL].time, y=dataset.continuous_data[RAW_EIT_LABEL].values, name=RAW_EIT_LABEL, - line=dict(color=plotly.colors.DEFAULT_PLOTLY_COLORS[0]), + line={"color": plotly.colors.DEFAULT_PLOTLY_COLORS[0]}, ), ) figure.update_yaxes( @@ -155,7 +146,7 @@ def create_slider_figure( x=dataset.continuous_data[cont_signal].time, y=dataset.continuous_data[cont_signal].values, name=cont_signal, - line=dict(color=plotly.colors.DEFAULT_PLOTLY_COLORS[n + 1]), + line={"color": plotly.colors.DEFAULT_PLOTLY_COLORS[n + 1]}, opacity=0.5, yaxis=f"y{n + 2}", ), From 22d0dd7f64ca4fe885e340bb8e64e67ebaf002ab Mon Sep 17 00:00:00 2001 From: Walter Baccinelli Date: Fri, 19 Apr 2024 17:01:42 +0200 Subject: [PATCH 10/11] added buttons labels --- eit_dash/definitions/layout_styles.py | 12 ++++++++++++ eit_dash/pages/analyze.py | 8 ++++++++ eit_dash/pages/load.py | 9 +++++++++ eit_dash/pages/preprocessing.py | 8 ++++++++ 4 files changed, 37 insertions(+) diff --git a/eit_dash/definitions/layout_styles.py b/eit_dash/definitions/layout_styles.py index 00e50aa..8e225e9 100644 --- a/eit_dash/definitions/layout_styles.py +++ b/eit_dash/definitions/layout_styles.py @@ -18,6 +18,12 @@ "border": "none", "font-size": "70px", } +NEXT_PAGE_SECTION = { + "position": "fixed", + "bottom": "7px", + "right": "35px", + "display": "flex", +} PREV_PAGE_BUTTON = { "position": "fixed", "bottom": "35px", @@ -29,6 +35,12 @@ "border": "none", "font-size": "70px", } +PREV_PAGE_SECTION = { + "position": "fixed", + "bottom": "7px", + "left": "35px", + "display": "flex", +} PAGES_LINK = {"fontWeight": "bold", "color": "blue"} SUMMARY_ELEMENT = {"textAlign": "center"} SECTION_TITLE = {"margin-top": "50px"} diff --git a/eit_dash/pages/analyze.py b/eit_dash/pages/analyze.py index 1a0e3d7..e89bbfb 100644 --- a/eit_dash/pages/analyze.py +++ b/eit_dash/pages/analyze.py @@ -64,6 +64,10 @@ href="", id=ids.NEXT_PAGE_LINK_ANALYZE, ), + html.Div( + "NEXT PAGE", + style=styles.NEXT_PAGE_SECTION, + ), ], ), html.Div( @@ -78,6 +82,10 @@ href="/preprocessing", id=ids.PREV_PAGE_LINK_ANALYZE, ), + html.Div( + "PREVIOUS PAGE", + style=styles.PREV_PAGE_SECTION, + ), ], ), ], diff --git a/eit_dash/pages/load.py b/eit_dash/pages/load.py index 37bf49a..fef036d 100644 --- a/eit_dash/pages/load.py +++ b/eit_dash/pages/load.py @@ -160,6 +160,7 @@ results, placeholder_nfiles, modal_dialog, + # TODO: the following is duplicated in multiple pages. To be refactored html.Div( [ dbc.NavLink( @@ -171,6 +172,10 @@ href="/preprocessing", id=ids.NEXT_PAGE_LINK_LOAD, ), + html.Div( + "NEXT PAGE", + style=styles.NEXT_PAGE_SECTION, + ), ], ), html.Div( @@ -185,6 +190,10 @@ href="/", id=ids.PREV_PAGE_LINK_LOAD, ), + html.Div( + "PREVIOUS PAGE", + style=styles.PREV_PAGE_SECTION, + ), ], ), ], diff --git a/eit_dash/pages/preprocessing.py b/eit_dash/pages/preprocessing.py index ca3c2ef..d8b4df9 100644 --- a/eit_dash/pages/preprocessing.py +++ b/eit_dash/pages/preprocessing.py @@ -352,6 +352,10 @@ href="/analyze", id=ids.NEXT_PAGE_LINK_PREP, ), + html.Div( + "NEXT PAGE", + style=styles.NEXT_PAGE_SECTION, + ), ], ), html.Div( @@ -366,6 +370,10 @@ href="/", id=ids.PREV_PAGE_LINK_PREP, ), + html.Div( + "PREVIOUS PAGE", + style=styles.PREV_PAGE_SECTION, + ), ], ), ], From 2863d33650bbb6d35ed86d733d5c580fb194f549 Mon Sep 17 00:00:00 2001 From: Walter Baccinelli Date: Fri, 19 Apr 2024 17:03:48 +0200 Subject: [PATCH 11/11] removed unnecessary buttons --- eit_dash/pages/analyze.py | 18 ------------------ eit_dash/pages/load.py | 18 ------------------ 2 files changed, 36 deletions(-) diff --git a/eit_dash/pages/analyze.py b/eit_dash/pages/analyze.py index e89bbfb..1928e99 100644 --- a/eit_dash/pages/analyze.py +++ b/eit_dash/pages/analyze.py @@ -52,24 +52,6 @@ summary, actions, results, - html.Div( - [ - dbc.NavLink( - dbc.Button( - className="fa fa-arrow-circle-right", - id=ids.NEXT_PAGE_BUTTON_ANALYZE, - style=styles.NEXT_PAGE_BUTTON, - disabled=True, - ), - href="", - id=ids.NEXT_PAGE_LINK_ANALYZE, - ), - html.Div( - "NEXT PAGE", - style=styles.NEXT_PAGE_SECTION, - ), - ], - ), html.Div( [ dbc.NavLink( diff --git a/eit_dash/pages/load.py b/eit_dash/pages/load.py index fef036d..eacdc23 100644 --- a/eit_dash/pages/load.py +++ b/eit_dash/pages/load.py @@ -178,23 +178,5 @@ ), ], ), - html.Div( - [ - dbc.NavLink( - dbc.Button( - className="fa fa-arrow-circle-left", - id=ids.PREV_PAGE_BUTTON_LOAD, - style=styles.PREV_PAGE_BUTTON, - disabled=True, - ), - href="/", - id=ids.PREV_PAGE_LINK_LOAD, - ), - html.Div( - "PREVIOUS PAGE", - style=styles.PREV_PAGE_SECTION, - ), - ], - ), ], )