Skip to content

Commit 89a84d7

Browse files
committed
resolved conflitcs
2 parents 2eac24a + d65c9c9 commit 89a84d7

File tree

7 files changed

+139
-80
lines changed

7 files changed

+139
-80
lines changed

.github/workflows/ci.yml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,16 +12,20 @@ jobs:
1212
python-version: ["3.11"]
1313
steps:
1414
- uses: actions/checkout@v4
15-
16-
- name: Set up Python ${{ matrix.python-version }}
17-
uses: actions/setup-python@v5
15+
- uses: conda-incubator/setup-miniconda@v3
1816
with:
17+
activate-environment: openms
1918
python-version: ${{ matrix.python-version }}
19+
channels: defaults,bioconda,conda-forge
20+
21+
- name: Install OpenMS
22+
run: |
23+
conda install openms -y
2024
- name: Install dependencies
2125
run: |
2226
python -m pip install --upgrade pip
2327
pip install -r requirements.txt # test with requirements file so can easily bump with dependabot
2428
pip install pytest
2529
- name: Test
2630
run: |
27-
python -m pytest test_gui.py
31+
python -m pytest test_gui.py

app.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,16 @@
11
import streamlit as st
22
from pathlib import Path
3+
import json
34
# For some reason the windows version only works if this is imported here
45
import pyopenms
56

7+
if "settings" not in st.session_state:
8+
with open("settings.json", "r") as f:
9+
st.session_state.settings = json.load(f)
10+
611
if __name__ == '__main__':
712
pages = {
8-
"OpenMS Web App" : [
13+
str(st.session_state.settings["app-name"]) : [
914
st.Page(Path("content", "quickstart.py"), title="Quickstart", icon="👋"),
1015
st.Page(Path("content", "documentation.py"), title="Documentation", icon="📖"),
1116
],

environment.yml

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
###### TODO: how use exact version specifiers for all packages ######
22
name: streamlit-env
33
channels:
4-
- conda-forge
4+
- conda-forge
55
dependencies:
6-
- python==3.11
7-
- plotly==5.22.0
8-
- pip==24.0
9-
- numpy==1.26.4 # pandas and numpy are dependencies of pyopenms, however, pyopenms needs numpy<=1.26.4
10-
- mono==6.12.0.90
11-
- pip:
12-
# dependencies only available through pip
13-
# streamlit dependencies
14-
- streamlit>=1.38.0
15-
- captcha==0.5.0
16-
- pyopenms_viz>=0.1.2
17-
- streamlit-js-eval
6+
- python==3.11
7+
- plotly==5.22.0
8+
- pip==24.0
9+
- numpy==1.26.4 # pandas and numpy are dependencies of pyopenms, however, pyopenms needs numpy<=1.26.4
10+
- mono==6.12.0.90
11+
- pip:
12+
# dependencies only available through pip
13+
# streamlit dependencies
14+
- streamlit>=1.38.0
15+
- captcha==0.5.0
16+
- pyopenms_viz==1.0.0
17+
- streamlit-js-eval

requirements.txt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ pyopenms==3.2.0
66
numpy==1.26.4 # pandas and numpy are dependencies of pyopenms, however, pyopenms needs numpy<=1.26.4
77
plotly==5.22.0
88
captcha==0.5.0
9-
pyopenms_viz>=0.1.2
9+
pyopenms_viz==1.0.0
1010
streamlit-js-eval
1111
redis==5.2.1
12-
rq==2.1.0
12+
rq==2.1.0

settings.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"app-name": "OpenMS WebApp Template",
33
"github-user": "OpenMS",
4+
"version": "1.0.2",
45
"repository-name": "streamlit-template",
56
"analytics": {
67
"google-analytics": {
@@ -13,5 +14,6 @@
1314
}
1415
},
1516
"online_deployment": false,
17+
"enable_workspaces": true,
1618
"test": true
1719
}

src/common/common.py

Lines changed: 92 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,11 @@ def load_params(default: bool = False) -> dict[str, Any]:
4141
Returns:
4242
dict[str, Any]: A dictionary containing the parameters.
4343
"""
44+
45+
# Check if workspace is enabled. If not, load default parameters.
46+
if not st.session_state.settings["enable_workspaces"]:
47+
default = True
48+
4449
# Construct the path to the parameter file
4550
path = Path(st.session_state.workspace, "params.json")
4651

@@ -75,6 +80,11 @@ def save_params(params: dict[str, Any]) -> None:
7580
Returns:
7681
dict[str, Any]: Updated parameters.
7782
"""
83+
84+
# Check if the workspace is enabled and if a 'params.json' file exists in the workspace directory
85+
if not st.session_state.settings["enable_workspaces"]:
86+
return
87+
7888
# Update the parameter dictionary with any modified parameters from the current session
7989
for key, value in st.session_state.items():
8090
if key in params.keys():
@@ -199,21 +209,28 @@ def page_setup(page: str = "") -> dict[str, Any]:
199209
os.chdir("../streamlit-template")
200210
# Define the directory where all workspaces will be stored
201211
workspaces_dir = Path("..", "workspaces-" + st.session_state.settings["repository-name"])
202-
if "workspace" in st.query_params:
203-
st.session_state.workspace = Path(workspaces_dir, st.query_params.workspace)
204-
elif st.session_state.location == "online":
205-
workspace_id = str(uuid.uuid1())
206-
st.session_state.workspace = Path(workspaces_dir, workspace_id)
207-
st.query_params.workspace = workspace_id
212+
# Check if workspace logic is enabled
213+
if st.session_state.settings["enable_workspaces"]:
214+
if "workspace" in st.query_params:
215+
st.session_state.workspace = Path(workspaces_dir, st.query_params.workspace)
216+
elif st.session_state.location == "online":
217+
workspace_id = str(uuid.uuid1())
218+
st.session_state.workspace = Path(workspaces_dir, workspace_id)
219+
st.query_params.workspace = workspace_id
220+
else:
221+
st.session_state.workspace = Path(workspaces_dir, "default")
222+
st.query_params.workspace = "default"
223+
208224
else:
225+
# Use default workspace when workspace feature is disabled
209226
st.session_state.workspace = Path(workspaces_dir, "default")
210-
st.query_params.workspace = "default"
211227

212228
if st.session_state.location != "online":
213229
# not any captcha so, controllo should be true
214230
st.session_state["controllo"] = True
215231

216-
if "workspace" not in st.query_params:
232+
# If no workspace is specified and workspace feature is enabled, set default workspace and query param
233+
if "workspace" not in st.query_params and st.session_state.settings["enable_workspaces"]:
217234
st.query_params.workspace = st.session_state.workspace.name
218235

219236
# Make sure the necessary directories exist
@@ -259,51 +276,53 @@ def render_sidebar(page: str = "") -> None:
259276
params = load_params()
260277
with st.sidebar:
261278
# The main page has workspace switcher
262-
with st.expander("🖥️ **Workspaces**"):
263-
# Define workspaces directory outside of repository
264-
workspaces_dir = Path("..", "workspaces-" + st.session_state.settings["repository-name"])
265-
# Online: show current workspace name in info text and option to change to other existing workspace
266-
if st.session_state.location == "local":
267-
# Define callback function to change workspace
268-
def change_workspace():
269-
for key in params.keys():
270-
if key in st.session_state.keys():
271-
del st.session_state[key]
272-
st.session_state.workspace = Path(
273-
workspaces_dir, st.session_state["chosen-workspace"]
279+
# Display workspace switcher if workspace is enabled in local mode
280+
if st.session_state.settings["enable_workspaces"]:
281+
with st.expander("🖥️ **Workspaces**"):
282+
# Define workspaces directory outside of repository
283+
workspaces_dir = Path("..", "workspaces-" + st.session_state.settings["repository-name"])
284+
# Online: show current workspace name in info text and option to change to other existing workspace
285+
if st.session_state.location == "local":
286+
# Define callback function to change workspace
287+
def change_workspace():
288+
for key in params.keys():
289+
if key in st.session_state.keys():
290+
del st.session_state[key]
291+
st.session_state.workspace = Path(
292+
workspaces_dir, st.session_state["chosen-workspace"]
293+
)
294+
st.query_params.workspace = st.session_state["chosen-workspace"]
295+
296+
# Get all available workspaces as options
297+
options = [
298+
file.name for file in workspaces_dir.iterdir() if file.is_dir()
299+
]
300+
# Let user chose an already existing workspace
301+
st.selectbox(
302+
"choose existing workspace",
303+
options,
304+
index=options.index(str(st.session_state.workspace.stem)),
305+
on_change=change_workspace,
306+
key="chosen-workspace",
274307
)
275-
st.query_params.workspace = st.session_state["chosen-workspace"]
276-
277-
# Get all available workspaces as options
278-
options = [
279-
file.name for file in workspaces_dir.iterdir() if file.is_dir()
280-
]
281-
# Let user chose an already existing workspace
282-
st.selectbox(
283-
"choose existing workspace",
284-
options,
285-
index=options.index(str(st.session_state.workspace.stem)),
286-
on_change=change_workspace,
287-
key="chosen-workspace",
288-
)
289-
# Create or Remove workspaces
290-
create_remove = st.text_input("create/remove workspace", "")
291-
path = Path(workspaces_dir, create_remove)
292-
# Create new workspace
293-
if st.button("**Create Workspace**"):
294-
path.mkdir(parents=True, exist_ok=True)
295-
st.session_state.workspace = path
296-
st.query_params.workspace = create_remove
297-
# Temporary as the query update takes a short amount of time
298-
time.sleep(1)
299-
st.rerun()
300-
# Remove existing workspace and fall back to default
301-
if st.button("⚠️ Delete Workspace"):
302-
if path.exists():
303-
shutil.rmtree(path)
304-
st.session_state.workspace = Path(workspaces_dir, "default")
305-
st.query_params.workspace = "default"
308+
# Create or Remove workspaces
309+
create_remove = st.text_input("create/remove workspace", "")
310+
path = Path(workspaces_dir, create_remove)
311+
# Create new workspace
312+
if st.button("**Create Workspace**"):
313+
path.mkdir(parents=True, exist_ok=True)
314+
st.session_state.workspace = path
315+
st.query_params.workspace = create_remove
316+
# Temporary as the query update takes a short amount of time
317+
time.sleep(1)
306318
st.rerun()
319+
# Remove existing workspace and fall back to default
320+
if st.button("⚠️ Delete Workspace"):
321+
if path.exists():
322+
shutil.rmtree(path)
323+
st.session_state.workspace = Path(workspaces_dir, "default")
324+
st.query_params.workspace = "default"
325+
st.rerun()
307326

308327
# All pages have settings, workflow indicator and logo
309328
with st.expander("⚙️ **Settings**"):
@@ -322,6 +341,28 @@ def change_workspace():
322341
)
323342
else:
324343
st.session_state["spectrum_num_bins"] = 50
344+
345+
# Display OpenMS WebApp Template Version from settings.json
346+
with st.container():
347+
st.markdown(
348+
"""
349+
<style>
350+
.version-box {
351+
border: 1px solid #a4a5ad;
352+
padding: 10px;
353+
border-radius: 0.5rem;
354+
text-align: center;
355+
display: flex;
356+
justify-content: center;
357+
align-items: center;
358+
}
359+
</style>
360+
""",
361+
unsafe_allow_html=True
362+
)
363+
version_info = st.session_state.settings["version"]
364+
app_name = st.session_state.settings["app-name"]
365+
st.markdown(f'<div class="version-box">{app_name}<br>Version: {version_info}</div>', unsafe_allow_html=True)
325366
return params
326367

327368

src/view.py

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,10 @@ def get_df(file: Union[str, Path]) -> pd.DataFrame:
3535
else:
3636
precs.append(np.nan)
3737
df_spectra["precursor m/z"] = precs
38+
39+
# Drop spectra without peaks
40+
df_spectra = df_spectra[df_spectra["mzarray"].apply(lambda x: len(x) > 0)]
41+
3842
df_spectra["max intensity m/z"] = df_spectra.apply(
3943
lambda x: x["mzarray"][x["intarray"].argmax()], axis=1
4044
)
@@ -75,13 +79,13 @@ def plot_bpc_tic() -> go.Figure:
7579
fig = df.plot(
7680
backend="ms_plotly",
7781
kind="chromatogram",
78-
fig=fig,
7982
x="RT",
8083
y="inty",
8184
by="type",
82-
line_color="#f24c5c",
85+
color="#f24c5c",
8386
show_plot=False,
8487
grid=False,
88+
aggregate_duplicates=True,
8589
)
8690
if st.session_state.view_bpc:
8791
df = st.session_state.view_ms1.groupby("RT").max().reset_index()
@@ -91,13 +95,13 @@ def plot_bpc_tic() -> go.Figure:
9195
fig = df.plot(
9296
backend="ms_plotly",
9397
kind="chromatogram",
94-
fig=fig,
9598
x="RT",
9699
y="inty",
97100
by="type",
98-
line_color="#2d3a9d",
101+
color="#2d3a9d",
99102
show_plot=False,
100103
grid=False,
104+
aggregate_duplicates=True,
101105
)
102106
if st.session_state.view_eic:
103107
df = st.session_state.view_ms1
@@ -111,21 +115,21 @@ def plot_bpc_tic() -> go.Figure:
111115
df_eic = df[
112116
(df["mz"] >= target_value - tolerance)
113117
& (df["mz"] <= target_value + tolerance)
114-
]
118+
].copy()
115119
if not df_eic.empty:
116-
df_eic["type"] = "XIC"
120+
df_eic.loc[:, "type"] = "XIC"
117121
if df_eic["inty"].max() > max_int:
118122
max_int = df_eic["inty"].max()
119123
fig = df_eic.plot(
120124
backend="ms_plotly",
121125
kind="chromatogram",
122-
fig=fig,
123126
x="RT",
124127
y="inty",
125128
by="type",
126-
line_color="#f6bf26",
129+
color="#f6bf26",
127130
show_plot=False,
128131
grid=False,
132+
aggregate_duplicates=True,
129133
)
130134
except ValueError:
131135
st.error("Invalid m/z value for XIC provided. Please enter a valid number.")
@@ -149,12 +153,13 @@ def plot_ms_spectrum(df, title, bin_peaks, num_x_bins):
149153
backend="ms_plotly",
150154
x="mz",
151155
y="intensity",
152-
line_color="#2d3a9d",
156+
color="#2d3a9d",
153157
title=title,
154158
show_plot=False,
155159
grid=False,
156160
bin_peaks=bin_peaks,
157161
num_x_bins=num_x_bins,
162+
aggregate_duplicates=True,
158163
)
159164
fig.update_layout(
160165
template="plotly_white", dragmode="select", plot_bgcolor="rgb(255,255,255)"
@@ -183,6 +188,7 @@ def view_peak_map():
183188
show_plot=False,
184189
bin_peaks=True,
185190
backend="ms_plotly",
191+
aggregate_duplicates=True,
186192
)
187193
peak_map.update_layout(template="simple_white", dragmode="select")
188194
c1, c2 = st.columns(2)
@@ -212,6 +218,7 @@ def view_peak_map():
212218
num_x_bins=st.session_state.spectrum_num_bins,
213219
height=650,
214220
width=900,
221+
aggregate_duplicates=True,
215222
)
216223
st.plotly_chart(peak_map_3D, use_container_width=True)
217224

0 commit comments

Comments
 (0)