Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build-windows-executable-app.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,7 @@ jobs:
cp -r src streamlit_exe
cp -r content streamlit_exe
cp -r assets streamlit_exe
cp -r scripts streamlit_exe
cp -r static streamlit_exe
cp -r example-data streamlit_exe
cp openms-bin/*.dll streamlit_exe
Expand Down
2 changes: 1 addition & 1 deletion .streamlit/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ developmentMode = false

[server]
maxUploadSize = 2000 #MB
port = 8501 # should be same as configured in deployment repo
port = 8502 # should be same as configured in deployment repo

[theme]
# The preset Streamlit theme that your custom theme inherits from. One of "light" or "dark".
Expand Down
10 changes: 10 additions & 0 deletions app.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,15 @@
],
}

with open('settings.json', 'r') as f:
settings = json.load(f)
if settings['enable_flashida']:
pages["🧠 FLASHIda"] = ([
st.Page(Path("content", "FLASHIda", "FLASHIdaWorkflow.py"), title="Workflow", icon="⚙️"),
st.Page(Path("content", "FLASHIda", "FLASHIdaViewer.py"), title="Viewer", icon="👀"),
st.Page(Path("content", "FLASHIda", "FLASHIdaSimulatorWorkflow.py"), title="Simulator", icon="⚙️"),
st.Page(Path("content", "FLASHIda", "FLASHIdaSimulatorViewer.py"), title="Viewer", icon="👀"),
])

pg = st.navigation(pages, expanded=True)
pg.run()
126 changes: 126 additions & 0 deletions content/FLASHIda/FLASHIdaSimulatorViewer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
import streamlit as st

from pathlib import Path

from src.common.common import page_setup, save_params
from src.workflow.FileManager import FileManager
from src.render.render import render_grid

DEFAULT_LAYOUT = [['ms1_deconv_heat_map']]

Comment on lines +9 to +10
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix component key mismatch: 'ms1_deconv_heat_map' vs 'ms1_deconv_heatmap'

Parser stores data under 'ms1_deconv_heatmap' (no extra underscore). The default layout uses a different key, so the component won’t render.

Apply this diff:

-DEFAULT_LAYOUT = [['ms1_deconv_heat_map']]
+DEFAULT_LAYOUT = [['ms1_deconv_heatmap']]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
DEFAULT_LAYOUT = [['ms1_deconv_heat_map']]
DEFAULT_LAYOUT = [['ms1_deconv_heatmap']]
🤖 Prompt for AI Agents
In content/FLASHIda/FLASHIdaSimulatorViewer.py around lines 9 to 10, the
DEFAULT_LAYOUT uses the key 'ms1_deconv_heat_map' which does not match the
parser's key 'ms1_deconv_heatmap'. Update the DEFAULT_LAYOUT to use
'ms1_deconv_heatmap' without the extra underscore to ensure the component
renders correctly.

def select_experiment():
st.session_state.selected_experiment0_ida = st.session_state.selected_experiment_dropdown_ida
print(st.session_state.selected_experiment0_ida)
if len(layout) > 1:
for exp_index in range(1, len(layout)):
if st.session_state[f'selected_experiment_dropdown_{exp_index}_ida'] is None:
continue
st.session_state[f"selected_experiment{exp_index}_ida"] = st.session_state[f'selected_experiment_dropdown_{exp_index}_ida']

def validate_selected_index(file_manager, selected_experiment):
results = file_manager.get_results_list(['simulation_dfs'])
if selected_experiment in st.session_state:
if st.session_state[selected_experiment] in results:
return name_to_index[st.session_state[selected_experiment]]
else:
del st.session_state[selected_experiment]
return None

# page initialization
params = page_setup()

# Get available results
file_manager = FileManager(
st.session_state["workspace"],
Path(st.session_state['workspace'], 'flashidasimulator', 'cache')
)

results = file_manager.get_results_list(['simulation_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!')
st.stop()

# Map names to index
name_to_index = {n : i for i, n in enumerate(results)}

if len(layout) == 2 and side_by_side:
c1, c2 = st.columns(2)
with c1:
st.selectbox(
"choose experiment", results,
key="selected_experiment_dropdown_ida",
index=validate_selected_index(file_manager, 'selected_experiment0_ida'),
on_change=select_experiment
)
if 'selected_experiment0_ida' in st.session_state:
Comment on lines +60 to +66
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Selectbox index may be None; Streamlit expects an int

validate_selected_index can return None, which makes selectbox(index=...) raise. Default the index to 0 when None.

-        st.selectbox(
+        st.selectbox(
             "choose experiment", results, 
             key="selected_experiment_dropdown_ida", 
-            index=validate_selected_index(file_manager, 'selected_experiment0_ida'),
+            index=validate_selected_index(file_manager, 'selected_experiment0_ida') or 0,
             on_change=select_experiment
         )
...
-        st.selectbox(
+        st.selectbox(
             "choose experiment", results, 
-            key=f'selected_experiment_dropdown_1_ida',
-            index=validate_selected_index(file_manager, 'selected_experiment1_ida'),
+            key='selected_experiment_dropdown_1_ida',
+            index=validate_selected_index(file_manager, 'selected_experiment1_ida') or 0,
             on_change=select_experiment
         )
...
-    st.selectbox(
+    st.selectbox(
         "choose experiment", results, 
         key="selected_experiment_dropdown_ida", 
-        index=validate_selected_index(file_manager, 'selected_experiment0_ida'),
+        index=validate_selected_index(file_manager, 'selected_experiment0_ida') or 0,
         on_change=select_experiment
     )
...
-            st.selectbox(
+            st.selectbox(
                 "choose experiment", results, 
                 key=f'selected_experiment_dropdown_{exp_index}_ida',
-                index=validate_selected_index(file_manager, f'selected_experiment{exp_index}_ida'),
+                index=validate_selected_index(file_manager, f'selected_experiment{exp_index}_ida') or 0,
                 on_change=select_experiment
             )

Also applies to: 72-78, 88-93, 111-116

🤖 Prompt for AI Agents
In content/FLASHIda/FLASHIdaSimulatorViewer.py around lines 60 to 66, the index
argument passed to st.selectbox can be None because validate_selected_index may
return None, but Streamlit requires an integer index. To fix this, ensure that
if validate_selected_index returns None, you default the index to 0 before
passing it to the selectbox. Apply the same fix to the selectbox calls in lines
72-78, 88-93, and 111-116.

render_grid(
st.session_state.selected_experiment0_ida, layout[0], file_manager,
'flashidasimulator', "selected_experiment0_ida", 'flash_viewer_grid_0_ida'
)
with c2:
st.selectbox(
"choose experiment", results,
key=f'selected_experiment_dropdown_1_ida',
index=validate_selected_index(file_manager, 'selected_experiment1_ida'),
on_change=select_experiment
)
if f"selected_experiment1_ida" in st.session_state:
with st.spinner('Loading component...'):
render_grid(
st.session_state["selected_experiment1_ida"], layout[1],
file_manager, 'flashidasimulator', 'selected_experiment1_ida',
'flash_viewer_grid_1_ida'
)

else:
### for only single experiment on one view
st.selectbox(
"choose experiment", results,
key="selected_experiment_dropdown_ida",
index=validate_selected_index(file_manager, 'selected_experiment0_ida'),
on_change=select_experiment
)


if 'selected_experiment0_ida' in st.session_state:
print('Lets go!')
render_grid(
st.session_state.selected_experiment0_ida, layout[0], file_manager,
'flashidasimulator', 'selected_experiment0_ida'
)
Comment on lines +96 to +101
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

render_grid call missing a stable grid key in single-experiment view

Side-by-side paths pass a grid key; single-view doesn’t. This can cause state/key collisions and inconsistent UI updates.

-        render_grid(
-            st.session_state.selected_experiment0_ida, layout[0], file_manager, 
-            'flashidasimulator', 'selected_experiment0_ida'
-        )
+        render_grid(
+            st.session_state.selected_experiment0_ida, layout[0], file_manager, 
+            'flashidasimulator', 'selected_experiment0_ida', 'flash_viewer_grid_0_ida'
+        )
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if 'selected_experiment0_ida' in st.session_state:
print('Lets go!')
render_grid(
st.session_state.selected_experiment0_ida, layout[0], file_manager,
'flashidasimulator', 'selected_experiment0_ida'
)
if 'selected_experiment0_ida' in st.session_state:
print('Lets go!')
render_grid(
st.session_state.selected_experiment0_ida, layout[0], file_manager,
'flashidasimulator', 'selected_experiment0_ida', 'flash_viewer_grid_0_ida'
)
🤖 Prompt for AI Agents
In content/FLASHIda/FLASHIdaSimulatorViewer.py around lines 96 to 101, the
render_grid call in the single-experiment view is missing a stable grid key,
which can lead to state collisions and inconsistent UI updates. Add a unique and
stable key argument to the render_grid call similar to the side-by-side paths
usage to ensure proper state management and UI consistency.


### for multiple experiments on one view
if len(layout) > 1:

for exp_index, exp_layout in enumerate(layout):
if exp_index == 0: continue # skip the first experiment

st.divider() # horizontal line

st.selectbox(
"choose experiment", results,
key=f'selected_experiment_dropdown_{exp_index}_ida',
index=validate_selected_index(file_manager, f'selected_experiment{exp_index}_ida'),
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}_ida" in st.session_state:
render_grid(
st.session_state["selected_experiment%d_ida" % exp_index],
layout[exp_index], file_manager, 'flashidasimulator',
"selected_experiment%d_ida" % exp_index,
'flash_viewer_grid_%d_ida' % exp_index
)

save_params(params)
21 changes: 21 additions & 0 deletions content/FLASHIda/FLASHIdaSimulatorWorkflow.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import streamlit as st

from src.Workflow import IdaSimulatorWorkflow
from src.common.common import page_setup


params = page_setup()

wf = IdaSimulatorWorkflow()

st.title('FLASHIda - Intelligent Data Acquisition')

t = st.tabs(["📁 **File Upload**", "⚙️ **Configure**", "🚀 **Run**"])
with t[0]:
wf.show_file_upload_section()

with t[1]:
wf.show_parameter_section()

with t[2]:
wf.show_execution_section()
119 changes: 119 additions & 0 deletions content/FLASHIda/FLASHIdaViewer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
import streamlit as st

from pathlib import Path

from src.common.common import page_setup, save_params
from src.workflow.FileManager import FileManager
from src.render.render import render_grid


DEFAULT_LAYOUT = [
['ms2_table'],
['combined_spectrum'],
['anno_spectrum', 'deconv_spectrum']
]



def select_experiment():
st.session_state.selected_experiment0_ida = st.session_state.selected_experiment_dropdown_ida
if len(layout) > 1:
for exp_index in range(1, len(layout)):
if st.session_state[f'selected_experiment_dropdown_{exp_index}_ida'] is None:
continue
st.session_state[f"selected_experiment{exp_index}_ida"] = st.session_state[f'selected_experiment_dropdown_{exp_index}_ida']

def validate_selected_index(file_manager, selected_experiment):
results = file_manager.get_results_list(
['deconv_dfs', 'anno_dfs', 'ms2_dfs']
)
if selected_experiment in st.session_state:
if st.session_state[selected_experiment] in results:
return name_to_index[st.session_state[selected_experiment]]
else:
del st.session_state[selected_experiment]
return None

# page initialization
params = page_setup("IdaViewer")

# Get available results
file_manager = FileManager(
st.session_state["workspace"],
Path(st.session_state['workspace'], 'flashida', 'cache')
)
results = file_manager.get_results_list(
['deconv_dfs', 'anno_dfs', 'ms2_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!')
st.stop()

# Map names to index
name_to_index = {n : i for i, n in enumerate(results)}

if len(layout) == 2 and side_by_side:
c1, c2 = st.columns(2)
with c1:
st.selectbox(
"choose experiment", results,
key="selected_experiment_dropdown_ida",
index=validate_selected_index(file_manager, 'selected_experiment0_ida'),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Update function calls to pass required parameters.

Since the helper functions now need additional parameters, update the function calls accordingly.

-            index=validate_selected_index(file_manager, 'selected_experiment0_ida'),
-            on_change=select_experiment
+            index=validate_selected_index(file_manager, 'selected_experiment0_ida', name_to_index),
+            on_change=lambda: select_experiment(layout)

Apply similar changes to other function calls.

Also applies to: 75-75, 91-91, 114-114

🤖 Prompt for AI Agents
In content/FLASHIda/FLASHIdaViewer.py at lines 63, 75, 91, and 114, the function
calls to helper functions like validate_selected_index need to be updated to
include the new required parameters. Review the function definitions to identify
all required parameters and modify each call to pass these parameters
accordingly, ensuring all calls match the updated function signatures.

on_change=select_experiment
)
if 'selected_experiment0_ida' in st.session_state:
render_grid(st.session_state.selected_experiment0_ida, layout[0], file_manager, 'flashida', 'selected_experiment0_ida')
with c2:
st.selectbox(
"choose experiment", results,
key=f'selected_experiment_dropdown_1_ida',
index=validate_selected_index(file_manager, 'selected_experiment1_ida'),
on_change=select_experiment
)
if f"selected_experiment1_ida" in st.session_state:
render_grid(st.session_state.selected_experiment1_ida, layout[1], file_manager, 'flashida', 'selected_experiment1_ida', 'flash_viewer_grid_1')


else:
### for only single experiment on one view
st.selectbox(
"choose experiment", results,
key="selected_experiment_dropdown_ida",
index=validate_selected_index(file_manager, 'selected_experiment0_ida'),
on_change=select_experiment
)

if 'selected_experiment0_ida' in st.session_state:
render_grid(st.session_state.selected_experiment0_ida, layout[0], file_manager, 'flashida', 'selected_experiment0_ida')

### for multiple experiments on one view
if len(layout) > 1:

for exp_index, exp_layout in enumerate(layout):
if exp_index == 0: continue # skip the first experiment

st.divider() # horizontal line

st.selectbox(
"choose experiment", results,
key=f'selected_experiment_dropdown_{exp_index}_ida',
index=validate_selected_index(file_manager, f'selected_experiment{exp_index}_ida'),
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}_ida" in st.session_state:
render_grid(st.session_state["selected_experiment%d_ida" % exp_index], layout[exp_index], file_manager, 'flashida', f"selected_experiment{exp_index}_ida", 'flash_viewer_grid_%d' % exp_index)

save_params(params)
Loading
Loading