From 5dd22f492d51077ac255512e5e702fad9f3c1451 Mon Sep 17 00:00:00 2001 From: Soubhagya Mohapatra Date: Fri, 21 Mar 2025 00:14:11 +0530 Subject: [PATCH 1/8] Added feature --- src/view.py | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/view.py b/src/view.py index bb9e9a04d..e33a7526f 100644 --- a/src/view.py +++ b/src/view.py @@ -316,4 +316,27 @@ def view_bpc_tic(): key="view_eic_ppm", ) fig = plot_bpc_tic() - show_fig(fig, f"BPC-TIC-{st.session_state.view_selected_file}") + + fig.update_layout( + xaxis=dict( + rangeslider=dict(visible=True), # Range slider for x-axis zoom + rangeselector=dict( # Zoom buttons + buttons=list([ + dict(count=1, label="1s", step="second", stepmode="backward"), + dict(count=10, label="10s", step="second", stepmode="backward"), + dict(count=1, label="1m", step="minute", stepmode="backward"), + dict(step="all") + ]) + ) + ), + margin=dict(l=0, r=0, t=0, b=0), # Remove margins for full-width display + height=700, # Increase height for better visualization + hovermode="x unified", # Unified hover tooltip + modebar=dict( + orientation='h', # Horizontal toolbar + bgcolor='rgba(255,255,255,0.7)', # Toolbar background color + ) + ) + + # Display full-width chromatogram + st.plotly_chart(fig, use_container_width=True) From 29d64591e6645fb11240c2d04beecf3a12cca95c Mon Sep 17 00:00:00 2001 From: Soubhagya Mohapatra Date: Sat, 22 Mar 2025 08:52:44 +0530 Subject: [PATCH 2/8] did changes --- src/view.py | 106 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 101 insertions(+), 5 deletions(-) diff --git a/src/view.py b/src/view.py index e33a7526f..945fc41a6 100644 --- a/src/view.py +++ b/src/view.py @@ -7,6 +7,7 @@ import pyopenms as poms from src.common.common import show_fig, display_large_dataframe from typing import Union +from plotly.subplots import make_subplots def get_df(file: Union[str, Path]) -> pd.DataFrame: @@ -170,6 +171,8 @@ def plot_ms_spectrum(df, title, bin_peaks, num_x_bins): @st.fragment def view_peak_map(): df = st.session_state.view_ms1 + + # ✅ Apply Box Selection Filtering if "view_peak_map_selection" in st.session_state: box = st.session_state.view_peak_map_selection.selection.box if box: @@ -178,29 +181,111 @@ def view_peak_map(): df = df[df["mz"] > box[0]["y"][1]] df = df[df["mz"] < box[0]["y"][0]] df = df[df["RT"] < box[0]["x"][1]] + + # ✅ Main 2D Peak Map Plot with Correct Y-Axis Label peak_map = df.plot( kind="peakmap", x="RT", y="mz", z="inty", - title=st.session_state.view_selected_file, + xlabel="Retention Time (s)", # ✅ X-axis label + ylabel="m/z", # ✅ Y-axis label for main plot grid=False, show_plot=False, bin_peaks=True, backend="ms_plotly", aggregate_duplicates=True, ) - peak_map.update_layout(template="simple_white", dragmode="select") + + # ✅ Marginal TIC Plot with Correct Y-Axis Label + df_tic = df.groupby("RT").sum().reset_index() + + marginal_tic = go.Figure() + marginal_tic.add_trace( + go.Scatter( + x=df_tic["RT"], + y=df_tic["inty"], + mode="lines", + line=dict(color="#f24c5c", width=2), + name="TIC", + ) + ) + + marginal_tic.update_layout( + height=200, + margin=dict(l=0, r=0, t=0, b=0), + plot_bgcolor="rgb(255,255,255)", + xaxis=dict(title="Retention Time (s)"), # ✅ X-axis label + yaxis=dict(title="TIC") # ✅ Y-axis label for TIC plot + ) + + # ✅ Create subplots with peak map on top and TIC at the bottom + combined_fig = make_subplots( + rows=2, + cols=1, + shared_xaxes=True, + row_heights=[0.7, 0.3], # Peak map gets 70%, TIC gets 30% + vertical_spacing=0.05 + ) + + # ✅ Add main peak map to subplot (first row) + for trace in peak_map.data: + combined_fig.add_trace(trace, row=1, col=1) + + # ✅ Add marginal TIC plot (second row) + for trace in marginal_tic.data: + combined_fig.add_trace(trace, row=2, col=1) + + # ✅ Update layout with range slider only on the bottom x-axis + combined_fig.update_layout( + template="simple_white", + dragmode="zoom", + + # ✅ Top x-axis (no range slider) + xaxis=dict( + showgrid=False, + domain=[0, 1] + ), + + # ✅ Bottom x-axis with range slider + xaxis2=dict( + title="Retention Time (s)", + rangeslider=dict(visible=True), + showgrid=False + ), + + # ✅ Configure Y-axes + yaxis=dict(title="m/z"), # Y-axis for peak map + yaxis2=dict(title="TIC"), # Y-axis for TIC + + # ✅ Styling + height=850, + margin=dict(t=100, b=100), + title=dict( + text=st.session_state.view_selected_file, + x=0.5, + y=0.99, + xanchor="center", + yanchor="top", + font=dict(size=18, family="Arial, sans-serif") + ) + ) + + # ✅ Display the Combined Plot c1, c2 = st.columns(2) + with c1: st.info( - "💡 Zoom in via rectangular selection for more details and 3D plot. Double click plot to zoom back out." + "💡 Zoom in via rectangular selection for more details and 3D plot. " + "Double click plot to zoom back out." ) show_fig( - peak_map, + combined_fig, f"peak_map_{st.session_state.view_selected_file}", selection_session_state_key="view_peak_map_selection", ) + + # ✅ 3D Peak Map (without range slider) with c2: if df.shape[0] < 2500: peak_map_3D = df.plot( @@ -211,6 +296,8 @@ def view_peak_map(): y="mz", z="inty", zlabel="Intensity", + xlabel="Retention Time (s)", + ylabel="m/z", title="", show_plot=False, grid=False, @@ -220,9 +307,18 @@ def view_peak_map(): width=900, aggregate_duplicates=True, ) - st.plotly_chart(peak_map_3D, use_container_width=True) + # ✅ Update 3D plot layout (without range slider) + peak_map_3D.update_layout( + scene=dict( + xaxis=dict(title="Retention Time (s)"), + yaxis=dict(title="m/z"), + zaxis=dict(title="Intensity"), + dragmode="orbit" + ) + ) + st.plotly_chart(peak_map_3D, use_container_width=True) @st.fragment def view_spectrum(): cols = st.columns([0.34, 0.66]) From 8d86a388d41554ce6af4fc6c9b06785b162bba71 Mon Sep 17 00:00:00 2001 From: Soubhagya Mohapatra Date: Sat, 22 Mar 2025 08:55:49 +0530 Subject: [PATCH 3/8] minor changes --- src/view.py | 23 +++++------------------ 1 file changed, 5 insertions(+), 18 deletions(-) diff --git a/src/view.py b/src/view.py index 945fc41a6..1b0f780a1 100644 --- a/src/view.py +++ b/src/view.py @@ -172,7 +172,7 @@ def plot_ms_spectrum(df, title, bin_peaks, num_x_bins): def view_peak_map(): df = st.session_state.view_ms1 - # ✅ Apply Box Selection Filtering + #Apply Box Selection Filtering if "view_peak_map_selection" in st.session_state: box = st.session_state.view_peak_map_selection.selection.box if box: @@ -182,14 +182,13 @@ def view_peak_map(): df = df[df["mz"] < box[0]["y"][0]] df = df[df["RT"] < box[0]["x"][1]] - # ✅ Main 2D Peak Map Plot with Correct Y-Axis Label peak_map = df.plot( kind="peakmap", x="RT", y="mz", z="inty", - xlabel="Retention Time (s)", # ✅ X-axis label - ylabel="m/z", # ✅ Y-axis label for main plot + xlabel="Retention Time (s)", + ylabel="m/z", grid=False, show_plot=False, bin_peaks=True, @@ -197,7 +196,6 @@ def view_peak_map(): aggregate_duplicates=True, ) - # ✅ Marginal TIC Plot with Correct Y-Axis Label df_tic = df.groupby("RT").sum().reset_index() marginal_tic = go.Figure() @@ -215,11 +213,10 @@ def view_peak_map(): height=200, margin=dict(l=0, r=0, t=0, b=0), plot_bgcolor="rgb(255,255,255)", - xaxis=dict(title="Retention Time (s)"), # ✅ X-axis label - yaxis=dict(title="TIC") # ✅ Y-axis label for TIC plot + xaxis=dict(title="Retention Time (s)"), + yaxis=dict(title="TIC") ) - # ✅ Create subplots with peak map on top and TIC at the bottom combined_fig = make_subplots( rows=2, cols=1, @@ -228,37 +225,30 @@ def view_peak_map(): vertical_spacing=0.05 ) - # ✅ Add main peak map to subplot (first row) for trace in peak_map.data: combined_fig.add_trace(trace, row=1, col=1) - # ✅ Add marginal TIC plot (second row) for trace in marginal_tic.data: combined_fig.add_trace(trace, row=2, col=1) - # ✅ Update layout with range slider only on the bottom x-axis combined_fig.update_layout( template="simple_white", dragmode="zoom", - # ✅ Top x-axis (no range slider) xaxis=dict( showgrid=False, domain=[0, 1] ), - # ✅ Bottom x-axis with range slider xaxis2=dict( title="Retention Time (s)", rangeslider=dict(visible=True), showgrid=False ), - # ✅ Configure Y-axes yaxis=dict(title="m/z"), # Y-axis for peak map yaxis2=dict(title="TIC"), # Y-axis for TIC - # ✅ Styling height=850, margin=dict(t=100, b=100), title=dict( @@ -271,7 +261,6 @@ def view_peak_map(): ) ) - # ✅ Display the Combined Plot c1, c2 = st.columns(2) with c1: @@ -285,7 +274,6 @@ def view_peak_map(): selection_session_state_key="view_peak_map_selection", ) - # ✅ 3D Peak Map (without range slider) with c2: if df.shape[0] < 2500: peak_map_3D = df.plot( @@ -308,7 +296,6 @@ def view_peak_map(): aggregate_duplicates=True, ) - # ✅ Update 3D plot layout (without range slider) peak_map_3D.update_layout( scene=dict( xaxis=dict(title="Retention Time (s)"), From 49fb16e3d678440d01d96357f56937f9feb2341f Mon Sep 17 00:00:00 2001 From: Soubhagya Mohapatra Date: Sun, 23 Mar 2025 00:23:23 +0530 Subject: [PATCH 4/8] did changes --- src/view.py | 61 ++++++++++++++++++++++++++++------------------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/src/view.py b/src/view.py index 1b0f780a1..300808c26 100644 --- a/src/view.py +++ b/src/view.py @@ -167,12 +167,11 @@ def plot_ms_spectrum(df, title, bin_peaks, num_x_bins): ) return fig - @st.fragment def view_peak_map(): df = st.session_state.view_ms1 - #Apply Box Selection Filtering + # Apply Box Selection Filtering if "view_peak_map_selection" in st.session_state: box = st.session_state.view_peak_map_selection.selection.box if box: @@ -182,13 +181,14 @@ def view_peak_map(): df = df[df["mz"] < box[0]["y"][0]] df = df[df["RT"] < box[0]["x"][1]] + # ✅ Main Peak Map peak_map = df.plot( kind="peakmap", x="RT", y="mz", z="inty", - xlabel="Retention Time (s)", - ylabel="m/z", + xlabel="Retention Time (s)", + ylabel="m/z", grid=False, show_plot=False, bin_peaks=True, @@ -196,10 +196,11 @@ def view_peak_map(): aggregate_duplicates=True, ) + # ✅ TIC Plot with Selection Mode (Inverted y-axis) df_tic = df.groupby("RT").sum().reset_index() - - marginal_tic = go.Figure() - marginal_tic.add_trace( + + tic_fig = go.Figure() + tic_fig.add_trace( go.Scatter( x=df_tic["RT"], y=df_tic["inty"], @@ -209,14 +210,24 @@ def view_peak_map(): ) ) - marginal_tic.update_layout( + tic_fig.update_layout( height=200, margin=dict(l=0, r=0, t=0, b=0), plot_bgcolor="rgb(255,255,255)", - xaxis=dict(title="Retention Time (s)"), - yaxis=dict(title="TIC") + xaxis=dict( + title="Retention Time (s)", + rangeslider=dict(visible=False), + showgrid=False + ), + yaxis=dict( + title="TIC", + autorange="reversed" # ✅ Invert the y-axis + ), + dragmode="select", # ✅ Horizontal selection mode + selectdirection = "h" ) + # ✅ Combined Figure combined_fig = make_subplots( rows=2, cols=1, @@ -228,27 +239,18 @@ def view_peak_map(): for trace in peak_map.data: combined_fig.add_trace(trace, row=1, col=1) - for trace in marginal_tic.data: + for trace in tic_fig.data: combined_fig.add_trace(trace, row=2, col=1) combined_fig.update_layout( template="simple_white", - dragmode="zoom", - - xaxis=dict( - showgrid=False, - domain=[0, 1] - ), - - xaxis2=dict( - title="Retention Time (s)", - rangeslider=dict(visible=True), - showgrid=False - ), - + dragmode="zoom", # Enable zooming and panning + xaxis=dict(title="Retention Time (s)", showgrid=False), yaxis=dict(title="m/z"), # Y-axis for peak map - yaxis2=dict(title="TIC"), # Y-axis for TIC - + yaxis2=dict( + title="TIC", + autorange="reversed" # ✅ Inverted y-axis for TIC + ), height=850, margin=dict(t=100, b=100), title=dict( @@ -261,12 +263,13 @@ def view_peak_map(): ) ) + # ✅ Display the Plot c1, c2 = st.columns(2) with c1: st.info( - "💡 Zoom in via rectangular selection for more details and 3D plot. " - "Double click plot to zoom back out." + "💡 Select ranges on the TIC plot below for more details. " + "Double click to reset the selection." ) show_fig( combined_fig, @@ -305,7 +308,7 @@ def view_peak_map(): ) ) - st.plotly_chart(peak_map_3D, use_container_width=True) + st.plotly_chart(peak_map_3D, use_container_width=True) @st.fragment def view_spectrum(): cols = st.columns([0.34, 0.66]) From 58dd08ccfb0b6350e2feab32a068f9139f4c9bcf Mon Sep 17 00:00:00 2001 From: Soubhagya Mohapatra Date: Sun, 23 Mar 2025 16:34:03 +0530 Subject: [PATCH 5/8] didchanges --- src/view.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/view.py b/src/view.py index 300808c26..aec24fb32 100644 --- a/src/view.py +++ b/src/view.py @@ -176,10 +176,10 @@ def view_peak_map(): box = st.session_state.view_peak_map_selection.selection.box if box: df = st.session_state.view_ms1.copy() - df = df[df["RT"] > box[0]["x"][0]] + df = df[df["RT"] > max(box[0]["x"][0], 0)] df = df[df["mz"] > box[0]["y"][1]] df = df[df["mz"] < box[0]["y"][0]] - df = df[df["RT"] < box[0]["x"][1]] + df = df[df["RT"] < min(box[0]["x"][1], 1500)] # ✅ Main Peak Map peak_map = df.plot( @@ -221,7 +221,8 @@ def view_peak_map(): ), yaxis=dict( title="TIC", - autorange="reversed" # ✅ Invert the y-axis + autorange="reversed", # ✅ Invert the y-axis + fixedrange=True ), dragmode="select", # ✅ Horizontal selection mode selectdirection = "h" @@ -246,10 +247,11 @@ def view_peak_map(): template="simple_white", dragmode="zoom", # Enable zooming and panning xaxis=dict(title="Retention Time (s)", showgrid=False), - yaxis=dict(title="m/z"), # Y-axis for peak map + yaxis=dict(title="m/z",fixedrange=True), # Y-axis for peak map yaxis2=dict( title="TIC", - autorange="reversed" # ✅ Inverted y-axis for TIC + autorange="reversed", # ✅ Inverted y-axis for TIC + fixedrange=True ), height=850, margin=dict(t=100, b=100), @@ -302,7 +304,7 @@ def view_peak_map(): peak_map_3D.update_layout( scene=dict( xaxis=dict(title="Retention Time (s)"), - yaxis=dict(title="m/z"), + yaxis=dict(title="m/z",fixedrange=True), zaxis=dict(title="Intensity"), dragmode="orbit" ) From 4896e8ca890c377abf5b066e096ae3ae671f51a7 Mon Sep 17 00:00:00 2001 From: Soubhagya Mohapatra Date: Sun, 23 Mar 2025 18:47:19 +0530 Subject: [PATCH 6/8] removed unnecessary code and comments --- src/view.py | 32 +++++++++++--------------------- 1 file changed, 11 insertions(+), 21 deletions(-) diff --git a/src/view.py b/src/view.py index aec24fb32..f812fa0b8 100644 --- a/src/view.py +++ b/src/view.py @@ -171,7 +171,6 @@ def plot_ms_spectrum(df, title, bin_peaks, num_x_bins): def view_peak_map(): df = st.session_state.view_ms1 - # Apply Box Selection Filtering if "view_peak_map_selection" in st.session_state: box = st.session_state.view_peak_map_selection.selection.box if box: @@ -181,7 +180,6 @@ def view_peak_map(): df = df[df["mz"] < box[0]["y"][0]] df = df[df["RT"] < min(box[0]["x"][1], 1500)] - # ✅ Main Peak Map peak_map = df.plot( kind="peakmap", x="RT", @@ -196,7 +194,6 @@ def view_peak_map(): aggregate_duplicates=True, ) - # ✅ TIC Plot with Selection Mode (Inverted y-axis) df_tic = df.groupby("RT").sum().reset_index() tic_fig = go.Figure() @@ -217,23 +214,22 @@ def view_peak_map(): xaxis=dict( title="Retention Time (s)", rangeslider=dict(visible=False), - showgrid=False + showgrid=False, + fixedrange=True, ), yaxis=dict( title="TIC", - autorange="reversed", # ✅ Invert the y-axis + autorange="reversed", fixedrange=True ), - dragmode="select", # ✅ Horizontal selection mode - selectdirection = "h" + dragmode=False # ❌ Disabled brushing ) - # ✅ Combined Figure combined_fig = make_subplots( rows=2, cols=1, shared_xaxes=True, - row_heights=[0.7, 0.3], # Peak map gets 70%, TIC gets 30% + row_heights=[0.7, 0.3], vertical_spacing=0.05 ) @@ -245,14 +241,10 @@ def view_peak_map(): combined_fig.update_layout( template="simple_white", - dragmode="zoom", # Enable zooming and panning - xaxis=dict(title="Retention Time (s)", showgrid=False), - yaxis=dict(title="m/z",fixedrange=True), # Y-axis for peak map - yaxis2=dict( - title="TIC", - autorange="reversed", # ✅ Inverted y-axis for TIC - fixedrange=True - ), + dragmode="zoom", + xaxis=dict(title="Retention Time (s)", showgrid=False, minallowed="0", maxallowed="1000"), + yaxis=dict(title="m/z", fixedrange=True), + yaxis2=dict(title="TIC", autorange="reversed", fixedrange=True), height=850, margin=dict(t=100, b=100), title=dict( @@ -265,7 +257,6 @@ def view_peak_map(): ) ) - # ✅ Display the Plot c1, c2 = st.columns(2) with c1: @@ -291,7 +282,6 @@ def view_peak_map(): zlabel="Intensity", xlabel="Retention Time (s)", ylabel="m/z", - title="", show_plot=False, grid=False, bin_peaks=st.session_state.spectrum_bin_peaks, @@ -303,8 +293,8 @@ def view_peak_map(): peak_map_3D.update_layout( scene=dict( - xaxis=dict(title="Retention Time (s)"), - yaxis=dict(title="m/z",fixedrange=True), + xaxis=dict(title="Retention Time (s)", minallowed="0", maxallowed="1000"), + yaxis=dict(title="m/z", fixedrange=True), zaxis=dict(title="Intensity"), dragmode="orbit" ) From 211d62711192f0ced7eb28017708c78c0fa36cf9 Mon Sep 17 00:00:00 2001 From: Soubhagya Mohapatra Date: Mon, 24 Mar 2025 23:27:53 +0530 Subject: [PATCH 7/8] made the tic plot smaller --- src/view.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/view.py b/src/view.py index f812fa0b8..ee221df58 100644 --- a/src/view.py +++ b/src/view.py @@ -216,20 +216,22 @@ def view_peak_map(): rangeslider=dict(visible=False), showgrid=False, fixedrange=True, + minallowed="0", + maxallowed="1000" ), yaxis=dict( title="TIC", autorange="reversed", fixedrange=True ), - dragmode=False # ❌ Disabled brushing + dragmode=False ) combined_fig = make_subplots( rows=2, cols=1, shared_xaxes=True, - row_heights=[0.7, 0.3], + row_heights=[0.8, 0.2], vertical_spacing=0.05 ) From 703aa745ae17c14a8d7e8a2391281424fc693731 Mon Sep 17 00:00:00 2001 From: Soubhagya Mohapatra Date: Wed, 26 Mar 2025 07:44:50 +0530 Subject: [PATCH 8/8] used ms_plotly for chromatogram --- src/view.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/view.py b/src/view.py index ee221df58..c714583b7 100644 --- a/src/view.py +++ b/src/view.py @@ -195,18 +195,19 @@ def view_peak_map(): ) df_tic = df.groupby("RT").sum().reset_index() - - tic_fig = go.Figure() - tic_fig.add_trace( - go.Scatter( - x=df_tic["RT"], - y=df_tic["inty"], - mode="lines", - line=dict(color="#f24c5c", width=2), - name="TIC", - ) + + tic_fig = df_tic.plot( + kind="chromatogram", + x="RT", + y="inty", + xlabel="Retention Time (s)", + ylabel="TIC", + grid=False, + show_plot=False, + backend="ms_plotly", ) + tic_fig.update_layout( height=200, margin=dict(l=0, r=0, t=0, b=0),