diff --git a/.gitignore b/.gitignore index 7467237c..baf5a6b3 100644 --- a/.gitignore +++ b/.gitignore @@ -6,7 +6,7 @@ build.log run_app.spec clean-up-workspaces.log -# FLASHViewer +# FLASHApp workspaces Pipfile workspaces-flashtaggerviewer diff --git a/Dockerfile b/Dockerfile index 86a7c6a0..bd856863 100644 --- a/Dockerfile +++ b/Dockerfile @@ -34,9 +34,9 @@ ARG PORT=8501 ARG GITHUB_TOKEN ENV GH_TOKEN=${GITHUB_TOKEN} # Streamlit app Gihub user name (to download artifact from). -ARG GITHUB_USER=t0mdavid-m +ARG GITHUB_USER=OpenMS # Streamlit app Gihub repository name (to download artifact from). -ARG GITHUB_REPO=FLASHViewer +ARG GITHUB_REPO=FLASHApp # Name of the zip file containing the windows executable ARG ASSET_NAME=OpenMS-App.zip diff --git a/README.md b/README.md index aa441ed1..9f955c83 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# FLASHViewer +# FLASHApp -FLASHViewer for visualizing FLASHDeconv's results \ +FLASHApp for visualizing FLASHDeconv's results \ This app is based on [OpenMS streamlit template project](https://github.com/OpenMS/streamlit-template). ![Overview](https://github.com/user-attachments/assets/35fe2c24-7dbc-40cd-b8b5-b7504768ade1) @@ -28,7 +28,7 @@ for more documentation on submodules ## Build -To build FLASHViewer, you first need to build the `openms-streamlit-vue-component` +To build FLASHApp, you first need to build the `openms-streamlit-vue-component` and copy the build from `./openms-streamlit-vue-component/dist` to `./js-component/dist`. @@ -37,7 +37,7 @@ You then should set streamlit to production in two locations: * in `./.streamlit/config.toml` set `developmentMode` to `false` * in `./src/components.py` set `_RELEASE` to `True` -These steps should be done before building any version of FLASHViewer. +These steps should be done before building any version of FLASHApp. ### Docker @@ -46,7 +46,7 @@ First you need to build an image locally. Prerequisite: `src/components.py` has `RELEASE=True` and `dist/` contains a build of the Vue component. These should be the settings on the `main` branch. -build image with: `docker build -f Dockerfile --no-cache -t flashviewer:latest --build-arg GITHUB_TOKEN= .` +build image with: `docker build -f Dockerfile --no-cache -t flashapp:latest --build-arg GITHUB_TOKEN= .` You should see a successful output, but you can check if an image is built with: @@ -54,6 +54,6 @@ You should see a successful output, but you can check if an image is built with: After it has been built you can run the image with: -`docker run -p 8501:8501 flashviewer:latest` +`docker run -p 8501:8501 flashapp:latest` Navigate to `http://localhost:8501` in your browser. diff --git a/content/FLASHDeconv/FLASHDeconvLayoutManager.py b/content/FLASHDeconv/FLASHDeconvLayoutManager.py index 46b2d13e..02b12673 100644 --- a/content/FLASHDeconv/FLASHDeconvLayoutManager.py +++ b/content/FLASHDeconv/FLASHDeconvLayoutManager.py @@ -1,16 +1,20 @@ +import json + import streamlit as st + from src.common.common import page_setup, v_space, save_params -import json +from src.workflow.FileManager import FileManager +from pathlib import Path COMPONENT_OPTIONS=[ 'MS1 raw heatmap', 'MS1 deconvolved heatmap', 'Scan table', 'Deconvolved spectrum (Scan table needed)', - 'Annotated spectrum (Scan table needed)', + 'Raw spectrum (Scan table needed)', 'Mass table (Scan table needed)', '3D S/N plot (Mass table needed)', - 'QScore ECDF Plot (report_FDR must be enabled)' + 'Score Distribution Plot' # "Sequence view" and "Internal fragment map" is added when "input_sequence" is submitted ] @@ -26,12 +30,37 @@ # "sequence view" and "internal fragment map" added when "input_sequence" is submitted ] +# Setup cache access +file_manager = FileManager( + st.session_state["workspace"], + Path(st.session_state['workspace'], 'flashdeconv', 'cache') +) + +def set_layout(layout, side_by_side=False): + file_manager.store_data('layout', 'layout', + { + 'layout': layout, + 'side_by_side': side_by_side + } + ) + +def get_layout(): + # Check if layout has been set + if not file_manager.result_exists('layout', 'layout'): + return None + # fetch layout from cache + layout = file_manager.get_results('layout', 'layout')['layout'] + + return layout['layout'], layout['side_by_side'] def resetSettingsToDefault(num_of_exp=1): st.session_state["layout_setting"] = [[['']]] # 1D: experiment, 2D: row, 3D: column, element=component name st.session_state["num_of_experiment_to_show"] = num_of_exp for index in range(1, num_of_exp): st.session_state.layout_setting.append([['']]) + if file_manager.result_exists('layout', 'layout'): + file_manager.remove_results('layout') + st.session_state["edit_mode"] = True def containerForNewComponent(exp_index, row_index, col_index): @@ -122,18 +151,31 @@ def getTrimmedLayoutSetting(): trimmed_layout_setting.append(rows) return trimmed_layout_setting +def getExpandedLayoutSetting(trimmed_layout_setting): + expanded_layout_setting = [] + for exp in trimmed_layout_setting: + rows = [] + for row in exp: + cols = [] + for col in row: + if col: + cols.append(COMPONENT_OPTIONS[COMPONENT_NAMES.index(col)]) + if cols: + rows.append(cols) + if rows: + expanded_layout_setting.append(rows) + return expanded_layout_setting def handleEditAndSaveButtons(): # if "Edit" button was clicked, if "edit_btn_clicked" in st.session_state and st.session_state["edit_btn_clicked"]: - # reset variables based on "saved_layout_setting" - st.session_state["num_of_experiment_to_show"] = len(st.session_state["saved_layout_setting"]) + st.session_state["edit_mode"] = True + # reset variables based on saved layout setting + st.session_state["num_of_experiment_to_show"] = len(get_layout()[0]) if get_layout() is not None else 1 st.session_state["layout_setting"] = [[[COMPONENT_OPTIONS[COMPONENT_NAMES.index(col)] for col in row if col] for row in exp if row] - for exp in st.session_state.saved_layout_setting] - # remove saved state, if any - del st.session_state["saved_layout_setting"] + for exp in get_layout()[0]] # if "Save" button was clicked, if "layout_saved" in st.session_state and st.session_state["layout_saved"]: @@ -141,14 +183,13 @@ def handleEditAndSaveButtons(): st.session_state['save_btn_error_message'] = got_error # to show error msg at the end if not got_error: # get only submitted info from "layout_setting" - st.session_state["saved_layout_setting"] = getTrimmedLayoutSetting() + set_layout(getTrimmedLayoutSetting(), side_by_side=st.session_state['side_by_side_view']) + st.session_state["edit_mode"] = False def handleSettingButtons(): if "reset_btn_clicked" in st.session_state and st.session_state.reset_btn_clicked: resetSettingsToDefault() - if "saved_layout_setting" in st.session_state: - del st.session_state["saved_layout_setting"] if "uploaded_json_file" in st.session_state and st.session_state.uploaded_json_file is not None: uploaded_layout = json.load(st.session_state.uploaded_json_file) @@ -179,28 +220,54 @@ def setSequenceView(): setSequenceView() # handles "onclick" of buttons +if st.session_state.get("edit_mode") is None: + st.session_state["edit_mode"] = True handleSettingButtons() handleEditAndSaveButtons() # initialize setting information if "layout_setting" not in st.session_state: - resetSettingsToDefault() + if get_layout() is not None: + # load layout setting from cache + st.session_state['layout_setting'] = getExpandedLayoutSetting(get_layout()[0]) + st.session_state['num_of_experiment_to_show'] = len(st.session_state.layout_setting) + st.session_state['side_by_side_view'] = get_layout()[1] + st.session_state["edit_mode"] = False + else: + resetSettingsToDefault() # the "num_of_experiment_to_show" changed elif "num_of_experiment_to_show" in st.session_state and \ len(st.session_state.layout_setting) != st.session_state.num_of_experiment_to_show: resetSettingsToDefault(st.session_state.num_of_experiment_to_show) ### title and setting buttons -c1, c2, c3, c4 = st.columns([6, 1, 1, 1]) +c1, c2, c3, c4, c5 = st.columns([6, 1, 1, 1, 1]) c1.title("Layout Manager") +# side-by-side view option for 2 experiments +if 'side_by_side_view' not in st.session_state: + st.session_state['side_by_side_view'] = False +if ( + ('num_of_experiment_to_show' in st.session_state + and st.session_state.num_of_experiment_to_show == 2) + or + (not st.session_state.edit_mode + and (get_layout() is not None and len(get_layout()[0]) == 2)) +): + v_space(1, c2) + st.session_state['side_by_side_view'] = c2.checkbox( + "Side-by-Side View", value=st.session_state['side_by_side_view'], + help="If checked, experiments will be shown side-by-side", + disabled=(not st.session_state.edit_mode) + ) + # Load existing layout setting file -v_space(1, c2) -c2.button("Load Setting", key="load_btn_clicked") +v_space(1, c3) +c3.button("Load Setting", key="load_btn_clicked") # Save current layout setting (only after "Saved" button) -v_space(1, c3) -c3.download_button( +v_space(1, c4) +c4.download_button( label="Save Setting", data=json.dumps(getTrimmedLayoutSetting()), file_name='FLASHViewer_layout_settings.json', @@ -209,18 +276,18 @@ def setSequenceView(): ) # Reset settings to default -v_space(1, c4) -c4.button("Reset Setting", key="reset_btn_clicked") +v_space(1, c5) +c5.button("Reset Setting", key="reset_btn_clicked") ### space for File Uploader, when "Load Setting" button is clicked if "load_btn_clicked" in st.session_state and st.session_state.load_btn_clicked: st.file_uploader("Choose a json file", type="json", key="uploaded_json_file") ### Main part -if "saved_layout_setting" in st.session_state: +if (not st.session_state.edit_mode) and (get_layout() is not None): # show saved-mode - for index_of_experiment in range(len(st.session_state.saved_layout_setting)): - layout_info_per_experiment = st.session_state.saved_layout_setting[index_of_experiment] + for index_of_experiment in range(len(get_layout()[0])): + layout_info_per_experiment = get_layout()[0][index_of_experiment] with st.expander("Experiment #%d"%(index_of_experiment+1), expanded=True): for row_index, row in enumerate(layout_info_per_experiment): st_cols = st.columns(len(row)) @@ -238,10 +305,8 @@ def setSequenceView(): ### buttons for edit/save _, edit_btn_col, save_btn_col = st.columns([9, 1, 1]) -edit_btn_col.button("Edit", key="edit_btn_clicked", - disabled=False if "saved_layout_setting" in st.session_state else True) -save_btn_col.button("Save", key="layout_saved", - disabled=True if "saved_layout_setting" in st.session_state else False) +edit_btn_col.button("Edit", key="edit_btn_clicked", disabled=st.session_state.edit_mode) +save_btn_col.button("Save", key="layout_saved", disabled=(not st.session_state.edit_mode)) ### showing error/success message if "save_btn_error_message" in st.session_state and st.session_state.layout_saved: diff --git a/content/FLASHDeconv/FLASHDeconvViewer.py b/content/FLASHDeconv/FLASHDeconvViewer.py index 33a43202..565d59c9 100644 --- a/content/FLASHDeconv/FLASHDeconvViewer.py +++ b/content/FLASHDeconv/FLASHDeconvViewer.py @@ -140,8 +140,8 @@ def setSequenceViewInDefaultView(): def select_experiment(): st.session_state.selected_experiment0 = st.session_state.selected_experiment_dropdown - if "saved_layout_setting" in st.session_state and len(st.session_state["saved_layout_setting"]) > 1: - for exp_index in range(1, len(st.session_state["saved_layout_setting"])): + if len(layout) > 1: + for exp_index in range(1, len(layout)): if st.session_state[f'selected_experiment_dropdown_{exp_index}'] is None: continue st.session_state[f"selected_experiment{exp_index}"] = st.session_state[f'selected_experiment_dropdown_{exp_index}'] @@ -163,6 +163,15 @@ def select_experiment(): ) results = file_manager.get_results_list(['deconv_dfs', 'anno_dfs']) +if file_manager.result_exists('layout', 'layout'): + layout = file_manager.get_results('layout', 'layout')['layout'] + side_by_side = layout['side_by_side'] + layout = layout['layout'] + +else: + layout = [DEFAULT_LAYOUT] + side_by_side = False + ### if no input file is given, show blank page if len(results) == 0: st.error('No results to show yet. Please run a workflow first!') @@ -171,40 +180,60 @@ def select_experiment(): # Map names to index name_to_index = {n : i for i, n in enumerate(results)} -### for only single experiment on one view -st.selectbox( - "choose experiment", results, - key="selected_experiment_dropdown", - index=name_to_index[st.session_state.selected_experiment0] if 'selected_experiment0' in st.session_state else None, - on_change=select_experiment -) +if len(layout) == 2 and side_by_side: + c1, c2 = st.columns(2) + with c1: + st.selectbox( + "choose experiment", results, + key="selected_experiment_dropdown", + index=name_to_index[st.session_state.selected_experiment0] if 'selected_experiment0' in st.session_state else None, + on_change=select_experiment + ) + if 'selected_experiment0' in st.session_state: + with st.spinner('Loading component...'): + sendDataToJS(st.session_state.selected_experiment0, layout[0]) + with c2: + st.selectbox( + "choose experiment", results, + key=f'selected_experiment_dropdown_1', + index = name_to_index[st.session_state[f'selected_experiment1']] if f'selected_experiment1' in st.session_state else None, + on_change=select_experiment + ) + if f"selected_experiment1" in st.session_state: + with st.spinner('Loading component...'): + sendDataToJS(st.session_state["selected_experiment1"], layout[1], 'flash_viewer_grid_1') + +else: + ### for only single experiment on one view + st.selectbox( + "choose experiment", results, + key="selected_experiment_dropdown", + index=name_to_index[st.session_state.selected_experiment0] if 'selected_experiment0' in st.session_state else None, + on_change=select_experiment + ) -if 'selected_experiment0' in st.session_state: - layout_info = DEFAULT_LAYOUT - if "saved_layout_setting" in st.session_state: # when layout manager was used - layout_info = st.session_state["saved_layout_setting"][0] - with st.spinner('Loading component...'): - sendDataToJS(st.session_state.selected_experiment0, layout_info) + if 'selected_experiment0' in st.session_state: + with st.spinner('Loading component...'): + sendDataToJS(st.session_state.selected_experiment0, layout[0]) -### for multiple experiments on one view -if "saved_layout_setting" in st.session_state and len(st.session_state["saved_layout_setting"]) > 1: + ### for multiple experiments on one view + if len(layout) > 1: - for exp_index, exp_layout in enumerate(st.session_state["saved_layout_setting"]): - if exp_index == 0: continue # skip the first experiment + for exp_index, exp_layout in enumerate(layout): + if exp_index == 0: continue # skip the first experiment - st.divider() # horizontal line + st.divider() # horizontal line - st.selectbox( - "choose experiment", results, - key=f'selected_experiment_dropdown_{exp_index}', - index = name_to_index[st.session_state[f'selected_experiment{exp_index}']] if f'selected_experiment{exp_index}' in st.session_state else None, - on_change=select_experiment - ) - # if #experiment input files are less than #layouts, all the pre-selection will be the first experiment - if f"selected_experiment{exp_index}" in st.session_state: - layout_info = st.session_state["saved_layout_setting"][exp_index] - with st.spinner('Loading component...'): - sendDataToJS(st.session_state["selected_experiment%d" % exp_index], layout_info, 'flash_viewer_grid_%d' % exp_index) + st.selectbox( + "choose experiment", results, + key=f'selected_experiment_dropdown_{exp_index}', + index = name_to_index[st.session_state[f'selected_experiment{exp_index}']] if f'selected_experiment{exp_index}' in st.session_state else None, + on_change=select_experiment + ) + # if #experiment input files are less than #layouts, all the pre-selection will be the first experiment + if f"selected_experiment{exp_index}" in st.session_state: + with st.spinner('Loading component...'): + sendDataToJS(st.session_state["selected_experiment%d" % exp_index], layout[exp_index], 'flash_viewer_grid_%d' % exp_index) save_params(params) diff --git a/content/FLASHTnT/FLASHTnTLayoutManager.py b/content/FLASHTnT/FLASHTnTLayoutManager.py index df60a603..386d9fec 100644 --- a/content/FLASHTnT/FLASHTnTLayoutManager.py +++ b/content/FLASHTnT/FLASHTnTLayoutManager.py @@ -1,13 +1,17 @@ +import json + import streamlit as st + from src.common.common import page_setup, v_space, save_params -import json +from src.workflow.FileManager import FileManager +from pathlib import Path COMPONENT_OPTIONS=[ 'Protein table', 'Sequence view (Protein table needed)', 'Internal fragment map (Protein table needed)', 'Tag table (Protein table needed)', - 'Spectrum view (Tag table needed)', + 'Sequence tag view (Tag table needed)', ] COMPONENT_NAMES=[ @@ -18,12 +22,37 @@ 'deconv_spectrum' ] +# Setup cache access +file_manager = FileManager( + st.session_state["workspace"], + Path(st.session_state['workspace'], 'flashtnt', 'cache') +) + +def set_layout(layout, side_by_side=False): + file_manager.store_data('layout', 'layout', + { + 'layout': layout, + 'side_by_side': side_by_side + } + ) + +def get_layout(): + # Check if layout has been set + if not file_manager.result_exists('layout', 'layout'): + return None + # fetch layout from cache + layout = file_manager.get_results('layout', 'layout')['layout'] + + return layout['layout'], layout['side_by_side'] def resetSettingsToDefault(num_of_exp=1): st.session_state["layout_setting_tagger"] = [[['']]] # 1D: experiment, 2D: row, 3D: column, element=component name st.session_state["num_of_experiment_to_show_tagger"] = num_of_exp for index in range(1, num_of_exp): st.session_state.layout_setting_tagger.append([['']]) + if file_manager.result_exists('layout', 'layout'): + file_manager.remove_results('layout') + st.session_state["edit_mode"] = True def containerForNewComponent(exp_index, row_index, col_index): @@ -114,18 +143,31 @@ def getTrimmedLayoutSetting(): trimmed_layout_setting.append(rows) return trimmed_layout_setting +def getExpandedLayoutSetting(trimmed_layout_setting): + expanded_layout_setting = [] + for exp in trimmed_layout_setting: + rows = [] + for row in exp: + cols = [] + for col in row: + if col: + cols.append(COMPONENT_OPTIONS[COMPONENT_NAMES.index(col)]) + if cols: + rows.append(cols) + if rows: + expanded_layout_setting.append(rows) + return expanded_layout_setting def handleEditAndSaveButtons(): # if "Edit" button was clicked, if "edit_btn_clicked" in st.session_state and st.session_state["edit_btn_clicked"]: - # reset variables based on "saved_layout_setting" - st.session_state["num_of_experiment_to_show"] = len(st.session_state["saved_layout_setting_tagger"]) + st.session_state["edit_mode"] = True + # reset variables based on saved layout setting + st.session_state["num_of_experiment_to_show"] = len(get_layout()[0]) if get_layout() is not None else 1 st.session_state["layout_setting_tagger"] = [[[COMPONENT_OPTIONS[COMPONENT_NAMES.index(col)] for col in row if col] for row in exp if row] - for exp in st.session_state.saved_layout_setting_tagger] - # remove saved state, if any - del st.session_state["saved_layout_setting_tagger"] + for exp in get_layout()[0]] # if "Save" button was clicked, if "layout_saved_tagger" in st.session_state and st.session_state["layout_saved_tagger"]: @@ -133,14 +175,13 @@ def handleEditAndSaveButtons(): st.session_state['save_btn_error_message'] = got_error # to show error msg at the end if not got_error: # get only submitted info from "layout_setting" - st.session_state["saved_layout_setting_tagger"] = getTrimmedLayoutSetting() + set_layout(getTrimmedLayoutSetting(), side_by_side=st.session_state['side_by_side_view']) + st.session_state["edit_mode"] = False def handleSettingButtons(): if "reset_btn_clicked" in st.session_state and st.session_state.reset_btn_clicked: resetSettingsToDefault() - if "saved_layout_setting_tagger" in st.session_state: - del st.session_state["saved_layout_setting_tagger"] if "uploaded_json_file" in st.session_state and st.session_state.uploaded_json_file is not None: uploaded_layout = json.load(st.session_state.uploaded_json_file) @@ -171,28 +212,54 @@ def setSequenceView(): #setSequenceView() # handles "onclick" of buttons +if st.session_state.get("edit_mode") is None: + st.session_state["edit_mode"] = True handleSettingButtons() handleEditAndSaveButtons() # initialize setting information if "layout_setting_tagger" not in st.session_state: - resetSettingsToDefault() + if get_layout() is not None: + # load layout setting from cache + st.session_state['layout_setting_tagger'] = getExpandedLayoutSetting(get_layout()[0]) + st.session_state['num_of_experiment_to_show'] = len(st.session_state.layout_setting_tagger) + st.session_state['side_by_side_view'] = get_layout()[1] + st.session_state["edit_mode"] = False + else: + resetSettingsToDefault() # the "num_of_experiment_to_show" changed elif "num_of_experiment_to_show" in st.session_state and \ len(st.session_state.layout_setting_tagger) != st.session_state.num_of_experiment_to_show: resetSettingsToDefault(st.session_state.num_of_experiment_to_show) ### title and setting buttons -c1, c2, c3, c4 = st.columns([6, 1, 1, 1]) +c1, c2, c3, c4, c5 = st.columns([6, 1, 1, 1, 1]) c1.title("Layout Manager") +# side-by-side view option for 2 experiments +if 'side_by_side_view' not in st.session_state: + st.session_state['side_by_side_view'] = False +if ( + ('num_of_experiment_to_show' in st.session_state + and st.session_state.num_of_experiment_to_show == 2) + or + (not st.session_state.edit_mode + and (get_layout() is not None and len(get_layout()[0]) == 2)) +): + v_space(1, c2) + st.session_state['side_by_side_view'] = c2.checkbox( + "Side-by-Side View", value=st.session_state['side_by_side_view'], + help="If checked, experiments will be shown side-by-side", + disabled=(not st.session_state.edit_mode) + ) + # Load existing layout setting file -v_space(1, c2) -c2.button("Load Setting", key="load_btn_clicked") +v_space(1, c3) +c3.button("Load Setting", key="load_btn_clicked") # Save current layout setting (only after "Saved" button) -v_space(1, c3) -c3.download_button( +v_space(1, c4) +c4.download_button( label="Save Setting", data=json.dumps(getTrimmedLayoutSetting()), file_name='FLASHViewer_layout_settings.json', @@ -201,18 +268,18 @@ def setSequenceView(): ) # Reset settings to default -v_space(1, c4) -c4.button("Reset Setting", key="reset_btn_clicked") +v_space(1, c5) +c5.button("Reset Setting", key="reset_btn_clicked") ### space for File Uploader, when "Load Setting" button is clicked if "load_btn_clicked" in st.session_state and st.session_state.load_btn_clicked: st.file_uploader("Choose a json file", type="json", key="uploaded_json_file") ### Main part -if "saved_layout_setting_tagger" in st.session_state: +if (not st.session_state.edit_mode) and (get_layout() is not None): # show saved-mode - for index_of_experiment in range(len(st.session_state.saved_layout_setting_tagger)): - layout_info_per_experiment = st.session_state.saved_layout_setting_tagger[index_of_experiment] + for index_of_experiment in range(len(get_layout()[0])): + layout_info_per_experiment = get_layout()[0][index_of_experiment] with st.expander("Experiment #%d"%(index_of_experiment+1), expanded=True): for row_index, row in enumerate(layout_info_per_experiment): st_cols = st.columns(len(row)) @@ -230,10 +297,8 @@ def setSequenceView(): ### buttons for edit/save _, edit_btn_col, save_btn_col = st.columns([9, 1, 1]) -edit_btn_col.button("Edit", key="edit_btn_clicked", - disabled=False if "saved_layout_setting_tagger" in st.session_state else True) -save_btn_col.button("Save", key="layout_saved_tagger", - disabled=True if "saved_layout_setting_tagger" in st.session_state else False) +edit_btn_col.button("Edit", key="edit_btn_clicked", disabled=st.session_state.edit_mode) +save_btn_col.button("Save", key="layout_saved_tagger", disabled=(not st.session_state.edit_mode)) ### showing error/success message if "save_btn_error_message" in st.session_state and st.session_state.layout_saved_tagger: diff --git a/content/FLASHTnT/FLASHTnTViewer.py b/content/FLASHTnT/FLASHTnTViewer.py index 39f3e29e..82593279 100644 --- a/content/FLASHTnT/FLASHTnTViewer.py +++ b/content/FLASHTnT/FLASHTnTViewer.py @@ -232,8 +232,8 @@ def setSequenceViewInDefaultView(): def select_experiment(): st.session_state.selected_experiment0_tagger = st.session_state.selected_experiment_dropdown_tagger - if "saved_layout_setting_tagger" in st.session_state and len(st.session_state["saved_layout_setting_tagger"]) > 1: - for exp_index in range(1, len(st.session_state["saved_layout_setting_tagger"])): + if len(layout) > 1: + for exp_index in range(1, len(layout)): if st.session_state[f'selected_experiment_dropdown_{exp_index}_tagger'] is None: continue st.session_state[f"selected_experiment{exp_index}_tagger"] = st.session_state[f'selected_experiment_dropdown_{exp_index}_tagger'] @@ -253,6 +253,15 @@ def select_experiment(): ['deconv_dfs', 'anno_dfs', 'tag_dfs', 'protein_dfs'] ) +if file_manager.result_exists('layout', 'layout'): + layout = file_manager.get_results('layout', 'layout')['layout'] + side_by_side = layout['side_by_side'] + layout = layout['layout'] + +else: + layout = [DEFAULT_LAYOUT] + side_by_side = False + ### if no input file is given, show blank page if len(results) == 0: st.error('No results to show yet. Please run a workflow first!') @@ -261,41 +270,60 @@ def select_experiment(): # Map names to index name_to_index = {n : i for i, n in enumerate(results)} -### for only single experiment on one view -st.selectbox( - "choose experiment", results, - key="selected_experiment_dropdown_tagger", - index=name_to_index[st.session_state.selected_experiment0_tagger] if 'selected_experiment0_tagger' in st.session_state else None, - on_change=select_experiment -) - -if 'selected_experiment0_tagger' in st.session_state: - layout_info = DEFAULT_LAYOUT - if "saved_layout_setting_tagger" in st.session_state: # when layout manager was used - layout_info = st.session_state["saved_layout_setting_tagger"][0] - with st.spinner('Loading component...'): - sendDataToJS(st.session_state.selected_experiment0_tagger, layout_info) +if len(layout) == 2 and side_by_side: + c1, c2 = st.columns(2) + with c1: + st.selectbox( + "choose experiment", results, + key="selected_experiment_dropdown_tagger", + index=name_to_index[st.session_state.selected_experiment0_tagger] if 'selected_experiment0_tagger' in st.session_state else None, + on_change=select_experiment + ) + if 'selected_experiment0_tagger' in st.session_state: + with st.spinner('Loading component...'): + sendDataToJS(st.session_state.selected_experiment0_tagger, layout[0]) + with c2: + st.selectbox( + "choose experiment", results, + key=f'selected_experiment_dropdown_1_tagger', + index = name_to_index[st.session_state[f'selected_experiment1_tagger']] if f'selected_experiment1_tagger' in st.session_state else None, + on_change=select_experiment + ) + if f"selected_experiment1_tagger" in st.session_state: + with st.spinner('Loading component...'): + sendDataToJS(st.session_state["selected_experiment1_tagger"], layout[1], 'flash_viewer_grid_1') + +else: + ### for only single experiment on one view + st.selectbox( + "choose experiment", results, + key="selected_experiment_dropdown_tagger", + index=name_to_index[st.session_state.selected_experiment0_tagger] if 'selected_experiment0_tagger' in st.session_state else None, + on_change=select_experiment + ) + if 'selected_experiment0_tagger' in st.session_state: + with st.spinner('Loading component...'): + sendDataToJS(st.session_state.selected_experiment0_tagger, layout[0]) -### for multiple experiments on one view -if "saved_layout_setting_tagger" in st.session_state and len(st.session_state["saved_layout_setting_tagger"]) > 1: + ### for multiple experiments on one view + if len(layout) > 1: - for exp_index, exp_layout in enumerate(st.session_state["saved_layout_setting_tagger"]): - if exp_index == 0: continue # skip the first experiment + for exp_index, exp_layout in enumerate(layout): + if exp_index == 0: continue # skip the first experiment - st.divider() # horizontal line + st.divider() # horizontal line - st.selectbox( - "choose experiment", results, - key=f'selected_experiment_dropdown_{exp_index}_tagger', - index = name_to_index[st.session_state[f'selected_experiment{exp_index}_tagger']] if f'selected_experiment{exp_index}_tagger' in st.session_state else None, - on_change=select_experiment - ) + st.selectbox( + "choose experiment", results, + key=f'selected_experiment_dropdown_{exp_index}_tagger', + index = name_to_index[st.session_state[f'selected_experiment{exp_index}_tagger']] if f'selected_experiment{exp_index}_tagger' in st.session_state else None, + on_change=select_experiment + ) - # if #experiment input files are less than #layouts, all the pre-selection will be the first experiment - if f"selected_experiment{exp_index}_tagger" in st.session_state: - layout_info = st.session_state["saved_layout_setting_tagger"][exp_index] - with st.spinner('Loading component...'): - sendDataToJS(st.session_state["selected_experiment%d_tagger" % exp_index], layout_info, 'flash_viewer_grid_%d' % exp_index) + # if #experiment input files are less than #layouts, all the pre-selection will be the first experiment + if f"selected_experiment{exp_index}_tagger" in st.session_state: + with st.spinner('Loading component...'): + sendDataToJS(st.session_state["selected_experiment%d_tagger" % exp_index], layout[exp_index], 'flash_viewer_grid_%d' % exp_index) save_params(params) \ No newline at end of file diff --git a/settings.json b/settings.json index b84c3a8f..508f8882 100644 --- a/settings.json +++ b/settings.json @@ -1,7 +1,7 @@ { "app-name": "FLASHApp", - "github-user": "t0mdavid-m", - "repository-name": "FLASHViewer", + "github-user": "OpenMS", + "repository-name": "FLASHApp", "analytics": { "google-analytics": { "enabled": false,