diff --git a/.bumpversion.cfg b/.bumpversion.cfg index 6a4bd71f..f952ba8d 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.4.1 +current_version = 0.4.2 commit = True tag = False parse = (?P\d+)\.(?P\d+)\.(?P\d+)(\-(?P[a-z]+)(?P\d+))? diff --git a/.github/workflows/python-package.yml b/.github/workflows/python-package.yml index c7919f09..4ad23470 100644 --- a/.github/workflows/python-package.yml +++ b/.github/workflows/python-package.yml @@ -31,6 +31,7 @@ jobs: python -m pip install --upgrade pip pip install coverage pip install wheel + pip install dictdiffer - name: Test installation run: | pip install -e. diff --git a/HISTORY.md b/HISTORY.md index b0a9fec2..bfb51bf7 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -1,5 +1,9 @@ # Changelog +# 0.4.2 +* ADD option compare_preprocessing_modes +* update to streamlit 1.19 with new caching functions + # 0.4.1 * FIX bug when drawing FDR lines * ADD functionionality `dataset.reset_preprocessing()` to reset all preprocessing steps diff --git a/alphastats/DataSet_Plot.py b/alphastats/DataSet_Plot.py index 11fd33dc..9933ddb9 100644 --- a/alphastats/DataSet_Plot.py +++ b/alphastats/DataSet_Plot.py @@ -125,7 +125,8 @@ def plot_volcano( alpha=0.05, draw_line=True, perm=100, - fdr=0.05 + fdr=0.05, + compare_preprocessing_modes=False ): """Plot Volcano Plot @@ -136,31 +137,38 @@ def plot_volcano( method (str): "anova", "wald", "ttest", "SAM" Defaul ttest. labels (bool): Add text labels to significant Proteins, Default False. alpha(float,optional): p-value cut off. - min_fc (float): Minimum fold change + min_fc (float): Minimum fold change. draw_line(boolean): whether to draw cut off lines. perm(float,optional): number of permutations when using SAM as method. Defaults to 100. fdr(float,optional): FDR cut off when using SAM as method. Defaults to 0.05. + compare_preprocessing_modes(bool): Will iterate through normalization and imputation modes and return a list of VolcanoPlots in different settings, Default False. Returns: plotly.graph_objects._figure.Figure: Volcano Plot """ - volcano_plot = VolcanoPlot( - dataset=self, - group1=group1, - group2=group2, - column=column, - method=method, - labels=labels, - min_fc=min_fc, - alpha=alpha, - draw_line=draw_line, - perm=perm, - fdr=fdr - ) + if compare_preprocessing_modes: + params_for_func = locals() + results = self._compare_preprocessing_modes(func=VolcanoPlot,params_for_func=params_for_func) + return results + + else: + volcano_plot = VolcanoPlot( + dataset=self, + group1=group1, + group2=group2, + column=column, + method=method, + labels=labels, + min_fc=min_fc, + alpha=alpha, + draw_line=draw_line, + perm=perm, + fdr=fdr + ) - return volcano_plot.plot + return volcano_plot.plot def plot_correlation_matrix(self, method="pearson"): """Plot Correlation Matrix @@ -224,6 +232,7 @@ def plot_intensity( method="box", add_significance=False, log_scale=False, + compare_preprocessing_modes=False ): """Plot Intensity of individual Protein/ProteinGroup @@ -238,6 +247,11 @@ def plot_intensity( Returns: plotly.graph_objects._figure.Figure: Plotly Plot """ + if compare_preprocessing_modes: + params_for_func = locals() + results = self._compare_preprocessing_modes(func=IntensityPlot,params_for_func=params_for_func) + return results + intensity_plot = IntensityPlot( dataset = self, protein_id=protein_id, diff --git a/alphastats/DataSet_Preprocess.py b/alphastats/DataSet_Preprocess.py index fcb229ef..281559cd 100644 --- a/alphastats/DataSet_Preprocess.py +++ b/alphastats/DataSet_Preprocess.py @@ -7,6 +7,7 @@ import sklearn.impute from alphastats.utils import ignore_warning from sklearn.experimental import enable_iterative_imputer +import itertools class Preprocess: @@ -165,6 +166,34 @@ def reset_preprocessing(self): # reset all preprocessing steps self.create_matrix() print("All preprocessing steps are reset.") + + def _compare_preprocessing_modes(self, func, params_for_func): + dataset = self + imputation_methods = ["mean", "median", "knn"] + normalization_methods = ["zscore", "quantile", "vst"] + preprocessing_modes = list(itertools.product(normalization_methods, imputation_methods)) + + results_list = [] + + del params_for_func["compare_preprocessing_modes"] + params_for_func["dataset"] = params_for_func.pop("self") + + for preprocessing_mode in preprocessing_modes: + # reset preprocessing + dataset.reset_preprocessing() + print(f"Normalization {preprocessing_mode[0]}, Imputation {str(preprocessing_mode[1])}") + + dataset.preprocess( + subset=True, + normalization = preprocessing_mode[0], + imputation = preprocessing_mode[1] + ) + + res = func(**params_for_func) + results_list.append(res) + + return results_list + @ignore_warning(RuntimeWarning) def preprocess( diff --git a/alphastats/__init__.py b/alphastats/__init__.py index 5235f2f0..455eb420 100644 --- a/alphastats/__init__.py +++ b/alphastats/__init__.py @@ -1,5 +1,5 @@ __project__ = "alphastats" -__version__ = "0.4.1" +__version__ = "0.4.2" __license__ = "Apache" __description__ = "An open-source Python package for Mass Spectrometry Analysis" __author__ = "Mann Labs" diff --git a/alphastats/gui/AlphaPeptStats.py b/alphastats/gui/AlphaPeptStats.py index d67bfbed..b9de13b9 100644 --- a/alphastats/gui/AlphaPeptStats.py +++ b/alphastats/gui/AlphaPeptStats.py @@ -10,6 +10,15 @@ # centering with streamlit is not really centered +from streamlit.runtime import get_instance +from streamlit.runtime.scriptrunner.script_run_context import get_script_run_ctx + +runtime = get_instance() +session_id = get_script_run_ctx().session_id +session_info = runtime._session_mgr.get_session_info(session_id) + +user_session_id = session_id +st.session_state["user_session_id"] = user_session_id img_center = """ diff --git a/alphastats/gui/pages/02_Import Data.py b/alphastats/gui/pages/02_Import Data.py index 11b158b3..881734e9 100644 --- a/alphastats/gui/pages/02_Import Data.py +++ b/alphastats/gui/pages/02_Import Data.py @@ -18,6 +18,7 @@ from alphastats import DataSet + import pandas as pd import plotly.express as px @@ -140,15 +141,14 @@ def select_sample_column_metadata(df, software): def upload_softwarefile(software): - st.file_uploader( + softwarefile = st.file_uploader( print_software_import_info(software=software), - key="softwarefile", type=["csv", "tsv", "txt", "hdf"], ) - if st.session_state.softwarefile is not None: + if softwarefile is not None: - softwarefile_df = read_uploaded_file_into_df(st.session_state.softwarefile) + softwarefile_df = read_uploaded_file_into_df(softwarefile) # display head a protein data check_software_file(softwarefile_df, software) @@ -302,6 +302,10 @@ def empty_session_state(): del st.session_state[key] st.empty() + from streamlit.runtime import get_instance + from streamlit.runtime.scriptrunner.script_run_context import get_script_run_ctx + user_session_id = get_script_run_ctx().session_id + st.session_state["user_session_id"] = user_session_id sidebar_info() diff --git a/alphastats/gui/pages/03_Data Overview.py b/alphastats/gui/pages/03_Data Overview.py index 929bf4bf..dcbcccf3 100644 --- a/alphastats/gui/pages/03_Data Overview.py +++ b/alphastats/gui/pages/03_Data Overview.py @@ -3,13 +3,13 @@ import plotly.express as px -@st.cache -def convert_df(df): +@st.cache_data +def convert_df(df, user_session_id = st.session_state.user_session_id): return df.to_csv().encode("utf-8") -@st.cache -def get_display_matrix(): +@st.cache_data +def get_display_matrix(user_session_id = st.session_state.user_session_id): processed_df = pd.DataFrame( st.session_state.dataset.mat.values, diff --git a/alphastats/gui/pages/04_Analysis.py b/alphastats/gui/pages/04_Analysis.py index 9caecaa7..b1f6757d 100644 --- a/alphastats/gui/pages/04_Analysis.py +++ b/alphastats/gui/pages/04_Analysis.py @@ -75,8 +75,8 @@ def download_figure(obj, format, plotting_library="plotly"): st.download_button(label="Download as " + format, data=buffer, file_name=filename) -@st.cache -def convert_df(df): +@st.cache_data +def convert_df(df, user_session_id = st.session_state.user_session_id): return df.to_csv().encode("utf-8") diff --git a/alphastats/gui/pages/06_Results.py b/alphastats/gui/pages/06_Results.py index 1c74916e..c82024c9 100644 --- a/alphastats/gui/pages/06_Results.py +++ b/alphastats/gui/pages/06_Results.py @@ -22,8 +22,8 @@ def save_plotly(plot, format): ) -@st.cache -def convert_df(df): +@st.cache_data +def convert_df(df, user_session_id = st.session_state.user_session_id): return df.to_csv().encode("utf-8") diff --git a/alphastats/gui/pages/07_ Getting Started.py b/alphastats/gui/pages/07_ Getting Started.py deleted file mode 100644 index 0da0f50e..00000000 --- a/alphastats/gui/pages/07_ Getting Started.py +++ /dev/null @@ -1,3 +0,0 @@ -import streamlit as st - -st.markdown("## Getting started") diff --git a/alphastats/plots/VolcanoPlot.py b/alphastats/plots/VolcanoPlot.py index f76cd4c8..3f10d766 100644 --- a/alphastats/plots/VolcanoPlot.py +++ b/alphastats/plots/VolcanoPlot.py @@ -11,7 +11,11 @@ class VolcanoPlot(PlotUtils): def __init__( - self, dataset, group1, group2, column=None, method=None, labels=None, min_fc=None, alpha=None, draw_line=None, plot=True, perm=100, fdr=0.05 + self, dataset, group1, group2, + column=None, method=None, + labels=None, min_fc=None, + alpha=None, draw_line=None, + plot=True, perm=100, fdr=0.05 ): self.dataset = dataset self.group1 = group1 diff --git a/docs/conf.py b/docs/conf.py index fe01ea03..075c7f2c 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -23,7 +23,7 @@ author = "Elena Krismer" # The full version, including alpha/beta/rc tags -release = "0.4.1" +release = "0.4.2" # -- General configuration --------------------------------------------------- diff --git a/package.Dockerfile b/package.Dockerfile new file mode 100644 index 00000000..3373ea79 --- /dev/null +++ b/package.Dockerfile @@ -0,0 +1,20 @@ +FROM python:3.9-slim-buster + +# Set the working directory +WORKDIR /app + +# Install any necessary system dependencies here +RUN apt-get update && apt-get install -y \ + libpq-dev \ + gcc \ + && rm -rf /var/lib/apt/lists/* + +RUN git clone https://github.com/MannLabs/alphapeptstats.git . +# Install Python packages and any other dependencies +RUN pip3 install -e. + +# Copy the Python package files into the container +COPY alphapeptstats /app/alphapeptstats + +# Set the entrypoint command to the package's setup.py file +ENTRYPOINT ["python", "-m", "setup.py"] \ No newline at end of file diff --git a/release/one_click_linux_gui/control b/release/one_click_linux_gui/control index 85574d93..29255a73 100644 --- a/release/one_click_linux_gui/control +++ b/release/one_click_linux_gui/control @@ -1,5 +1,5 @@ Package: alphastats -Version: 0.4.1 +Version: 0.4.2 Architecture: all Maintainer: MannLabs Description: alphastats diff --git a/release/one_click_linux_gui/create_installer_linux.sh b/release/one_click_linux_gui/create_installer_linux.sh index 766631fe..eb5bd0bb 100644 --- a/release/one_click_linux_gui/create_installer_linux.sh +++ b/release/one_click_linux_gui/create_installer_linux.sh @@ -17,7 +17,7 @@ python setup.py sdist bdist_wheel # Setting up the local package cd release/one_click_linux_gui # Make sure you include the required extra packages and always use the stable or very-stable options! -pip install "../../dist/alphastats-0.4.1-py3-none-any.whl" +pip install "../../dist/alphastats-0.4.2-py3-none-any.whl" # Creating the stand-alone pyinstaller folder pip install pyinstaller==5.8 diff --git a/release/one_click_macos_gui/Info.plist b/release/one_click_macos_gui/Info.plist index ec2ff981..d0c0ae7a 100644 --- a/release/one_click_macos_gui/Info.plist +++ b/release/one_click_macos_gui/Info.plist @@ -9,9 +9,9 @@ CFBundleIconFile alphapeptstats_logo.icns CFBundleIdentifier - alphastats.0.4.1 + alphastats.0.4.2 CFBundleShortVersionString - 0.4.1 + 0.4.2 CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/release/one_click_macos_gui/create_installer_macos.sh b/release/one_click_macos_gui/create_installer_macos.sh index cac1b82b..fb0f2674 100755 --- a/release/one_click_macos_gui/create_installer_macos.sh +++ b/release/one_click_macos_gui/create_installer_macos.sh @@ -20,7 +20,7 @@ python setup.py sdist bdist_wheel # Setting up the local package cd release/one_click_macos_gui -pip install "../../dist/alphastats-0.4.1-py3-none-any.whl" +pip install "../../dist/alphastats-0.4.2-py3-none-any.whl" # Creating the stand-alone pyinstaller folder pip install pyinstaller==5.8 diff --git a/release/one_click_windows_gui/alphastats_innoinstaller.iss b/release/one_click_windows_gui/alphastats_innoinstaller.iss index 707b0bbc..7a05b896 100644 --- a/release/one_click_windows_gui/alphastats_innoinstaller.iss +++ b/release/one_click_windows_gui/alphastats_innoinstaller.iss @@ -2,7 +2,7 @@ ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! #define MyAppName "AlphaPeptStats" -#define MyAppVersion "0.4.1" +#define MyAppVersion "0.4.2" #define MyAppPublisher "MannLabs" #define MyAppURL "https://github.com/MannLabs/alphapeptstats" #define MyAppExeName "alphastats_gui.exe" diff --git a/release/one_click_windows_gui/create_installer_windows.sh b/release/one_click_windows_gui/create_installer_windows.sh index 2e42ff89..1ffc4a55 100644 --- a/release/one_click_windows_gui/create_installer_windows.sh +++ b/release/one_click_windows_gui/create_installer_windows.sh @@ -17,7 +17,7 @@ python setup.py sdist bdist_wheel # Setting up the local package cd release/one_click_windows_gui # Make sure you include the required extra packages and always use the stable or very-stable options! -pip install "../../dist/alphastats-0.4.1-py3-none-any.whl" +pip install "../../dist/alphastats-0.4.2-py3-none-any.whl" # Creating the stand-alone pyinstaller folder pip install pyinstaller==5.8 diff --git a/requirements.txt b/requirements.txt index afe2fac3..5ec7bdb2 100644 --- a/requirements.txt +++ b/requirements.txt @@ -12,7 +12,7 @@ tqdm>=4.64.0 diffxpy==0.7.4 anndata==0.8.0 umap-learn==0.5.3 -streamlit==1.17.0 +streamlit==1.19.0 tables==3.7.0 numpy==1.23.5 numba==0.56.4 diff --git a/setup.py b/setup.py index a5fad4fa..74a2cdf3 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,7 @@ def create_pip_wheel(): requirements = get_requirements() setuptools.setup( name="alphastats", - version="0.4.1", + version="0.4.2", license="Apache", description="An open-source Python package for Mass Spectrometry Analysis", long_description=get_long_description(), diff --git a/tests/test_DataSet.py b/tests/test_DataSet.py index db57c0d6..9cbbf931 100644 --- a/tests/test_DataSet.py +++ b/tests/test_DataSet.py @@ -16,6 +16,7 @@ import shutil import os import copy +import dictdiffer # from pandas.api.types import is_object_dtype, is_numeric_dtype, is_bool_dtype from alphastats.loader.BaseLoader import BaseLoader @@ -447,6 +448,22 @@ def test_plot_volcano_with_grouplist_wrong_names(self): group1=["wrong_sample_name", "1_42_D9", "1_57_E8"], group2=["1_71_F10", "1_73_F12"], ) + + def test_plot_volcano_compare_preprocessing_modes(self): + result_list = self.obj.plot_volcano( + method="ttest", + group1=["1_31_C6", "1_32_C7", "1_57_E8"], + group2=["1_71_F10", "1_73_F12"], + compare_preprocessing_modes=True + ) + self.assertEqual(len(result_list), 9) + # check if results are different + # for idx, res in enumerate(result_list): + # for idx2, res2 in enumerate(result_list): + # if idx != idx2: + # difference = dictdiffer.diff(res.to_plotly_json(), res2.to_plotly_json()) + # self.assertNotEqual(len(list(difference)), 0) + def test_preprocess_subset(self): self.obj.preprocess(subset=True)