Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor analysis vi #371

Open
wants to merge 5 commits into
base: refactor_analysis_V
Choose a base branch
from
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
4 changes: 2 additions & 2 deletions alphastats/DataSet_Preprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
import streamlit as st
from sklearn.experimental import enable_iterative_imputer # noqa

from alphastats.keys import Cols
from alphastats.keys import Cols, ConstantsClass
from alphastats.utils import ignore_warning


class PreprocessingStateKeys:
class PreprocessingStateKeys(metaclass=ConstantsClass):
"""Keys for accessing the dictionary holding the information about preprocessing."""

# TODO disentangle these keys from the human-readably display strings
Expand Down
13 changes: 6 additions & 7 deletions alphastats/gui/pages/04_Analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from alphastats.gui.utils.analysis_helper import (
display_df,
display_plot,
do_analysis,
gather_parameters_and_do_analysis,
)
from alphastats.gui.utils.ui_helper import (
StateKeys,
Expand Down Expand Up @@ -51,29 +51,28 @@
method = st.selectbox(
"Analysis",
options=["<select>"]
+ ["------- plots -------"]
+ ["------- plots ------------"]
+ plotting_options
+ ["------- statistics -------"]
+ statistic_options,
)

if method in plotting_options:
analysis_result, analysis_object, parameters = do_analysis(
method, options_dict=None
analysis_result, analysis_object, parameters = (
gather_parameters_and_do_analysis(method)
)
show_plot = analysis_result is not None

elif method in statistic_options:
analysis_result, *_ = do_analysis(
analysis_result, _, parameters = gather_parameters_and_do_analysis(
method,
options_dict=None,
)
show_df = analysis_result is not None

with c2:
# --- SHOW PLOT -------------------------------------------------------
if show_plot:
display_plot(method, analysis_result)
display_plot(method, analysis_result, parameters)

# --- SHOW STATISTICAL ANALYSIS -------------------------------------------------------
elif show_df:
Expand Down
2 changes: 2 additions & 0 deletions alphastats/gui/pages/06_Results.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@

method = saved_item[0]
plot = saved_item[1]
parameters = saved_item[2]

st.markdown("\n\n\n")
st.markdown(f"#### {method}")
st.write(f"Parameters used for analysis: {parameters}")

if st.button("x remove analysis", key="remove" + method + str(count)):
st.session_state[StateKeys.PLOT_LIST].remove(saved_item)
Expand Down
99 changes: 57 additions & 42 deletions alphastats/gui/utils/analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,10 @@
import streamlit as st

from alphastats.DataSet import DataSet
from alphastats.keys import Cols
from alphastats.keys import Cols, ConstantsClass
from alphastats.plots.VolcanoPlot import VolcanoPlot


class ConstantsClass(type):
"""A metaclass for classes that should only contain string constants."""

def __setattr__(self, name, value):
raise TypeError("Constants class cannot be modified")

def get_values(cls):
"""Get all user-defined string values of the class."""
return [
value
for key, value in cls.__dict__.items()
if not key.startswith("__") and isinstance(value, str)
]


class PlottingOptions(metaclass=ConstantsClass):
"""Keys for the plotting options."""

Expand All @@ -35,16 +20,19 @@ class PlottingOptions(metaclass=ConstantsClass):
SAMPLE_DISTRIBUTION_PLOT = "Sampledistribution Plot"
INTENSITY_PLOT = "Intensity Plot"
CLUSTERMAP = "Clustermap"
DENDROGRAM = "Dendrogram"


class StatisticOptions(metaclass=ConstantsClass):
"""Keys for the statistical options."""

DIFFERENTIAL_EXPRESSION = "Differential Expression Analysis"
TUKEY_TEST = "Tukey-Test"
ANOVA = "ANOVA"
ANCOVA = "ANCOVA"


class Analysis(ABC):
class AbstractAnalysis(ABC):
"""Abstract class for analysis widgets."""

_works_with_nans = True
Expand All @@ -58,22 +46,22 @@ def show_widget(self): # noqa: B027
pass

def do_analysis(self):
"""Perform the analysis.
"""Perform the analysis after an optional check for NaNs.

Returns a tuple(figure, analysis_object, parameters) where figure is the plot,
analysis_object is the underlying object, parameters is a dictionary of the parameters used.
"""
if not self._works_with_nans and self._dataset.mat.isnull().values.any():
st.error("This analysis does not work with NaN values.")
st.stop()
return self._do_analysis()
return *self._do_analysis(), dict(self._parameters)

@abstractmethod
def _do_analysis(self):
pass


class GroupCompareAnalysis(Analysis, ABC):
class AbstractGroupCompareAnalysis(AbstractAnalysis, ABC):
"""Abstract class for group comparison analysis widgets."""

def show_widget(self):
Expand Down Expand Up @@ -130,7 +118,7 @@ def show_widget(self):
self._parameters["column"] = column


class DimensionReductionAnalysis(Analysis, ABC):
class AbstractDimensionReductionAnalysis(AbstractAnalysis, ABC):
"""Abstract class for dimension reduction analysis widgets."""

def show_widget(self):
Expand All @@ -146,7 +134,7 @@ def show_widget(self):
self._parameters.update({"circle": circle, "group": group})


class AbstractIntensityPlot(Analysis, ABC):
class AbstractIntensityPlot(AbstractAnalysis, ABC):
"""Abstract class for intensity plot analysis widgets."""

def show_widget(self):
Expand Down Expand Up @@ -185,7 +173,7 @@ def _do_analysis(self):
method=self._parameters["method"],
group=self._parameters["group"],
)
return intensity_plot, None, self._parameters
return intensity_plot, None


class SampleDistributionPlot(AbstractIntensityPlot, ABC):
Expand All @@ -197,10 +185,10 @@ def _do_analysis(self):
method=self._parameters["method"],
color=self._parameters["group"], # no typo
)
return intensity_plot, None, self._parameters
return intensity_plot, None


class PCAPlotAnalysis(DimensionReductionAnalysis):
class PCAPlotAnalysis(AbstractDimensionReductionAnalysis):
"""Widget for PCA Plot analysis."""

def _do_analysis(self):
Expand All @@ -210,10 +198,10 @@ def _do_analysis(self):
group=self._parameters["group"],
circle=self._parameters["circle"],
)
return pca_plot, None, self._parameters
return pca_plot, None


class UMAPPlotAnalysis(DimensionReductionAnalysis):
class UMAPPlotAnalysis(AbstractDimensionReductionAnalysis):
"""Widget for UMAP Plot analysis."""

def _do_analysis(self):
Expand All @@ -222,10 +210,10 @@ def _do_analysis(self):
group=self._parameters["group"],
circle=self._parameters["circle"],
)
return umap_plot, None, self._parameters
return umap_plot, None


class TSNEPlotAnalysis(DimensionReductionAnalysis):
class TSNEPlotAnalysis(AbstractDimensionReductionAnalysis):
"""Widget for t-SNE Plot analysis."""

def show_widget(self):
Expand Down Expand Up @@ -254,10 +242,10 @@ def _do_analysis(self):
perplexity=self._parameters["perplexity"],
n_iter=self._parameters["n_iter"],
)
return tsne_plot, None, self._parameters
return tsne_plot, None


class VolcanoPlotAnalysis(GroupCompareAnalysis):
class VolcanoPlotAnalysis(AbstractGroupCompareAnalysis):
"""Widget for Volcano Plot analysis."""

def show_widget(self):
Expand Down Expand Up @@ -320,21 +308,32 @@ def _do_analysis(self):
fdr=self._parameters["fdr"],
color_list=self._parameters["color_list"],
)
return volcano_plot.plot, volcano_plot, self._parameters
return volcano_plot.plot, volcano_plot


class ClustermapAnalysis(Analysis):
class ClustermapAnalysis(AbstractAnalysis):
"""Widget for Clustermap analysis."""

_works_with_nans = False

def _do_analysis(self):
"""Draw Clustermap using the Clustermap class."""
clustermap = self._dataset.plot_clustermap()
return clustermap, None, self._parameters
return clustermap, None


class DendrogramAnalysis(AbstractAnalysis):
"""Widget for Dendrogram analysis."""

_works_with_nans = False

def _do_analysis(self):
"""Draw Clustermap using the Clustermap class."""
dendrogram = self._dataset.plot_dendrogram()
return dendrogram, None


class DifferentialExpressionAnalysis(GroupCompareAnalysis):
class DifferentialExpressionAnalysis(AbstractGroupCompareAnalysis):
"""Widget for differential expression analysis."""

def show_widget(self):
Expand All @@ -360,10 +359,10 @@ def _do_analysis(self):
group2=self._parameters["group2"],
column=self._parameters["column"],
)
return diff_exp_analysis, None, self._parameters
return diff_exp_analysis, None


class TukeyTestAnalysis(Analysis):
class TukeyTestAnalysis(AbstractAnalysis):
"""Widget for Tukey-Test analysis."""

def show_widget(self):
Expand All @@ -385,10 +384,10 @@ def _do_analysis(self):
protein_id=self._parameters["protein_id"],
group=self._parameters["group"],
)
return tukey_test_analysis, None, self._parameters
return tukey_test_analysis, None


class AnovaAnalysis(GroupCompareAnalysis):
class AnovaAnalysis(AbstractGroupCompareAnalysis):
"""Widget for ANOVA analysis."""

def show_widget(self):
Expand Down Expand Up @@ -416,10 +415,10 @@ def _do_analysis(self):
protein_ids=self._parameters["protein_ids"],
tukey=self._parameters["tukey"],
)
return anova_analysis, None, self._parameters
return anova_analysis, None


class AncovaAnalysis(Analysis):
class AncovaAnalysis(AbstractAnalysis):
"""Widget for Ancova analysis."""

def show_widget(self):
Expand Down Expand Up @@ -449,4 +448,20 @@ def _do_analysis(self):
covar=self._parameters["covar"],
between=self._parameters["between"],
)
return ancova_analysis, None, self._parameters
return ancova_analysis, None


ANALYSIS_OPTIONS = {
PlottingOptions.VOLCANO_PLOT: VolcanoPlotAnalysis,
PlottingOptions.PCA_PLOT: PCAPlotAnalysis,
PlottingOptions.UMAP_PLOT: UMAPPlotAnalysis,
PlottingOptions.TSNE_PLOT: TSNEPlotAnalysis,
PlottingOptions.SAMPLE_DISTRIBUTION_PLOT: SampleDistributionPlot,
PlottingOptions.INTENSITY_PLOT: IntensityPlot,
PlottingOptions.CLUSTERMAP: ClustermapAnalysis,
PlottingOptions.DENDROGRAM: DendrogramAnalysis,
StatisticOptions.DIFFERENTIAL_EXPRESSION: DifferentialExpressionAnalysis,
StatisticOptions.TUKEY_TEST: TukeyTestAnalysis,
StatisticOptions.ANOVA: AnovaAnalysis,
StatisticOptions.ANCOVA: AncovaAnalysis,
}
Loading
Loading