Skip to content

Commit

Permalink
Merge pull request #7 from domonik/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
domonik authored Aug 21, 2024
2 parents d41e278 + 5a2cfbb commit b4e10b6
Show file tree
Hide file tree
Showing 15 changed files with 561 additions and 225 deletions.
166 changes: 109 additions & 57 deletions RAPDOR/datastructures.py

Large diffs are not rendered by default.

344 changes: 265 additions & 79 deletions RAPDOR/plots.py

Large diffs are not rendered by default.

15 changes: 7 additions & 8 deletions RAPDOR/tests/test_datastructures.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,11 @@ def multi_intensities(intensities):

def drop_replicates(design, rnase_rep, ctrl_rep):
if rnase_rep > 0:
rnase = design[design["Treatment"] == "RNase"].groupby("Replicate").apply(lambda x: list(x.index)).sample(n=rnase_rep).sum()
rnase = design[design["Treatment"] == "RNase"].groupby("Replicate").apply(lambda x: list(x.index), include_groups=False).sample(n=rnase_rep).sum()
else:
rnase = []
if ctrl_rep > 0:
ctrl = design[design["Treatment"] == "Control"].groupby("Replicate").apply(lambda x: list(x.index)).sample(n=ctrl_rep).sum()
ctrl = design[design["Treatment"] == "Control"].groupby("Replicate").apply(lambda x: list(x.index), include_groups=False).sample(n=ctrl_rep).sum()
else:
ctrl = []
rnase = design.loc[rnase]
Expand Down Expand Up @@ -147,14 +147,13 @@ def test_different_columns(intensities, design):


@pytest.mark.parametrize(
"normalize,kernel_size,distance,permanova,nr_samples, distance_cutoff",
"normalize,kernel_size,distance,permanova,nr_samples",
[
(True, 3, "Jensen-Shannon-Distance", True, 10, 0.1),
(True, 3, "Jensen-Shannon-Distance", True, 10, 0),
(False, None, None, False, None, None)
(True, 3, "Jensen-Shannon-Distance", True, 10),
(False, None, None, False, None)
]
)
def test_serialization(normalize, kernel_size, distance, permanova, nr_samples, distance_cutoff, rapdordata):
def test_serialization(normalize, kernel_size, distance, permanova, nr_samples, rapdordata):
if normalize:
rapdordata.normalize_array_with_kernel(kernel_size)
if distance:
Expand All @@ -164,7 +163,7 @@ def test_serialization(normalize, kernel_size, distance, permanova, nr_samples,
rapdordata.rank_table(['Mean Distance', "ANOSIM R"], [False, False])


rapdordata.calc_permanova_p_value(10, threads=1, distance_cutoff=distance_cutoff)
rapdordata.calc_permanova_p_value(10, threads=1)
s = rapdordata.to_jsons()
loaded_data = RAPDORData.from_json(s)
assert loaded_data == rapdordata
Expand Down
16 changes: 8 additions & 8 deletions RAPDOR/visualize/assets/additional.js
Original file line number Diff line number Diff line change
Expand Up @@ -854,10 +854,10 @@ window.dash_clientside = Object.assign({}, window.dash_clientside, {
["Figure Creation", null, "/figure_factory", false, simulateClickFormCheckInput(0)],
["Figure Creation", ["ff-tut-preview"], "/figure_factory", false, simulateClickID("ff-default", 1)],
["Figure Creation", ["ff-tut-preview"], "/figure_factory", false, multiClickInOne([simulateClickFormCheckInput(2), simulateClickID("ff-default", null) ])],
["Dimension Reduction", null, "/analysis", true],
["Dimension Reduction", ["distribution-panel", "dim-red-tab", "dim-red-tut"], "/analysis", true, simulateClickID("dim-red-tab", "dim-red-tut")],
["Dimension Reduction", ["dim-red-tut", "distribution-panel", "dim-red-tab", ], "/analysis", true, simulateClickID("dim-red-tab", "dim-red-tut")],
["Dimension Reduction", ["dim-red-tut", "distribution-panel", "dim-red-tab", ], "/analysis", true, simulateClickID("dim-red-tab", "dim-red-tut")],
["Bubble Plot", null, "/analysis", true],
["Bubble Plot", ["distribution-panel", "dim-red-tab", "dim-red-tut"], "/analysis", true, simulateClickID("dim-red-tab", "dim-red-tut")],
["Bubble Plot", ["dim-red-tut", "distribution-panel", "dim-red-tab", ], "/analysis", true, simulateClickID("dim-red-tab", "dim-red-tut")],
["Bubble Plot", ["dim-red-tut", "distribution-panel", "dim-red-tab", ], "/analysis", true, simulateClickID("dim-red-tab", "dim-red-tut")],
["Finish",null, null, false, simulateClickID("dim-red-tab", "dim-red-tut")],


Expand Down Expand Up @@ -901,10 +901,10 @@ window.dash_clientside = Object.assign({}, window.dash_clientside, {
["Figure Creation", null, "/figure_factory", false, simulateClickFormCheckInput(0)],
["Figure Creation", ["ff-tut-preview"], "/figure_factory", false, simulateClickID("ff-default", 1)],
["Figure Creation", ["ff-tut-preview"], "/figure_factory", false, multiClickInOne([simulateClickFormCheckInput(2), simulateClickID("ff-default", null) ])],
["Dimension Reduction", null, "/analysis", true],
["Dimension Reduction", ["distribution-panel", "dim-red-tab", "dim-red-tut"], "/analysis", true, simulateClickID("dim-red-tab", "dim-red-tut")],
["Dimension Reduction", ["dim-red-tut", "distribution-panel", "dim-red-tab", ], "/analysis", true, simulateClickID("dim-red-tab", "dim-red-tut")],
["Dimension Reduction", ["dim-red-tut", "distribution-panel", "dim-red-tab", ], "/analysis", true, simulateClickID("dim-red-tab", "dim-red-tut")],
["Bubble Plot", null, "/analysis", true],
["Bubble Plot", ["distribution-panel", "dim-red-tab", "dim-red-tut"], "/analysis", true, simulateClickID("dim-red-tab", "dim-red-tut")],
["Bubble Plot", ["dim-red-tut", "distribution-panel", "dim-red-tab", ], "/analysis", true, simulateClickID("dim-red-tab", "dim-red-tut")],
["Bubble Plot", ["dim-red-tut", "distribution-panel", "dim-red-tab", ], "/analysis", true, simulateClickID("dim-red-tab", "dim-red-tut")],
["Finish",null, null, false, simulateClickID("dim-red-tab", "dim-red-tut")],

]
Expand Down
8 changes: 4 additions & 4 deletions RAPDOR/visualize/assets/tutorial.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@
"We now select rows to plot from the table. You can also select some more. In the next step we will visit the Figure Factory.",
"Here is the Figure Factory. As you can see the plot contains the distributions from the selected rows. But it does not look nice yet. We can improve that.",
"Usually the default settings are fine for plots. However, you can tweak some settings using the Input fields.",
"This is a dimension reduction plot displaying all rows from the table but highlighting the selected ones. We can also find it on the analysis page. Let`s have a look.",
"Now that we are back at the analysis page we can visit the dimension reduction tab.",
"Here you see the interactive dimension reduction. If you hover over the datapoints, the corresponding distribution is shown in the distribution panel. Just try yourself.",
"The <b>relative fraction shift</b> is an indicator of how many fractions the protein shifted. The <b>relative distribution change</b> shows whether a protein was more uniformly distributed after treatment (positive values) or accumulated in a less fractions (negative values).",
"This is a bubble plot plot displaying all rows from the table but highlighting the selected ones. We can also find it on the analysis page. Let`s have a look.",
"Now that we are back at the analysis page we can visit the bubble plot tab.",
"Here you see the interactive bubble plot. If you hover over the datapoints, the corresponding distribution is shown in the distribution panel. Just try yourself.",
"The <b>relative fraction shift</b> is an indicator of how many fractions the protein shifted. The <b>relative distribution change</b> shows whether a protein was more uniformly distributed after treatment (negative values) or accumulated in a less fractions (positive values).",
"You can also filter this plot via a cutoff at the right. E.g. you can filter for data points with a specific Rank range. Just try yourself. First set the Cutoff Type to Rank and then use the slider to restrict the range.",
"This is it. You finished the tutorial. Now you can go to the upload page and upload your own data."
]
8 changes: 4 additions & 4 deletions RAPDOR/visualize/assets/tutorialDisplayMode.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@
"We now select rows to plot from the table. You can also select some more. In the next step we will visit the Figure Factory.",
"Here is the Figure Factory. As you can see the plot contains the distributions from the selected rows. But it does not look nice yet. We can improve that.",
"Usually the default settings are fine for plots. However, if you want to tweak some settings you need to use a local copy which enables the input fields.",
"This is a dimension reduction plot displaying all rows from the table but highlighting the selected ones. We can also find it on the analysis page. Let`s have a look.",
"Now that we are back at the analysis page we can visit the dimension reduction tab.",
"Here you see the interactive dimension reduction. If you hover over the datapoints, the corresponding distribution is shown in the distribution panel. Just try yourself.",
"The <b>relative fraction shift</b> is an indicator of how many fractions the protein shifted. The <b>relative distribution change</b> shows whether a protein was more uniformly distributed after treatment (positive values) or accumulated in a less fractions (negative values).",
"This is a bubble plot plot displaying all rows from the table but highlighting the selected ones. We can also find it on the analysis page. Let`s have a look.",
"Now that we are back at the analysis page we can visit the bubble plot tab.",
"Here you see the interactive bubble plot. If you hover over the datapoints, the corresponding distribution is shown in the distribution panel. Just try yourself.",
"The <b>relative fraction shift</b> is an indicator of how many fractions the protein shifted. The <b>relative distribution change</b> shows whether a protein was more uniformly distributed after treatment (negative values) or accumulated in a less fractions (positive values).",
"You can also filter this plot via a cutoff at the right. E.g. you can filter for data points with a specific Rank range. Just try yourself. First set the Cutoff Type to Rank and then use the slider to restrict the range.",
"This is it. You finished the tutorial."

Expand Down
125 changes: 89 additions & 36 deletions RAPDOR/visualize/callbacks/plotCallbacks.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from dash.exceptions import PreventUpdate
from plotly import graph_objs as go
from RAPDOR.plots import plot_replicate_distribution, plot_distribution, plot_barcode_plot, plot_heatmap, \
plot_dimension_reduction, empty_figure, DEFAULT_TEMPLATE, DEFAULT_TEMPLATE_DARK, plot_bars
plot_dimension_reduction, empty_figure, DEFAULT_TEMPLATE, DEFAULT_TEMPLATE_DARK, plot_bars, plot_distance_and_var
from dash_extensions.enrich import Serverside, callback
from RAPDOR.datastructures import RAPDORData
import logging
Expand Down Expand Up @@ -56,8 +56,7 @@ def update_distribution_plot(key, recomp, primary_color, secondary_color, replic
if rapdordata.categorical_fraction:
fig = plot_bars(array, rapdordata.internal_design_matrix, x=rapdordata.fractions, offset=i,
colors=colors, yname=yname)
if night_mode:
fig.update_traces(error_y=dict(color="white"), marker=dict(line=dict(width=1, color="white")))
fig.update_traces(error_y=dict(width=15))
else:
fig = plot_distribution(array, rapdordata.internal_design_matrix, offset=i, colors=colors, show_outliers=True, yname=yname)
if not night_mode:
Expand Down Expand Up @@ -106,6 +105,12 @@ def update_distribution_plot(key, recomp, primary_color, secondary_color, replic
legend=dict(font=dict(size=14)),
legend2=dict(font=dict(size=14))
)
if isinstance(rapdordata.fractions[0], str):
fig.update_xaxes(
tickvals=list(range(len(rapdordata.fractions))),
ticktext=[val.replace(" ", "<br>").replace("<br>&<br>", " &<br>") for val in rapdordata.fractions],
tickmode="array"
)

fig.update_xaxes(dtick=1, title=None)
fig.update_xaxes(fixedrange=True)
Expand Down Expand Up @@ -241,7 +246,7 @@ def calc_clusters(
if rapdordata.cluster_features is None:
rapdordata.calc_distribution_features()
logger.info("Calculated Cluster Features")
logger.info("Running Dimension Reduction - because cluster features changed")
logger.info("Running Bubble Plot - because cluster features changed")
if cluster_method is not None:
if cluster_method == "HDBSCAN":
kwargs = dict(min_cluster_size=hdb_min_cluster_size, cluster_selection_epsilon=hdb_epsilon)
Expand All @@ -267,22 +272,33 @@ def calc_clusters(
@callback(
Output("cutoff-type", "value"),
Output("cutoff-type", "options"),
Output("plot-cutoff-name", "children"),
Output("cutoff-type", "clearable"),
Input("data-store", "data"),
Input("dataset-plot-type", "value"),
State("cutoff-type", "value"),
)
def update_cutoff_selection(rapdordata: RAPDORData, current_selection):
def update_cutoff_selection(rapdordata: RAPDORData, plot_type, current_selection):
if rapdordata is None:
raise PreventUpdate
options = [option for option in rapdordata.score_columns if
option in rapdordata.df and is_numeric_dtype(rapdordata.df[option])]
selection = dash.no_update

if plot_type == "Bubble Plot":
name = "Cutoff Type"
clearable = True
else:
name = "Y Axis"
selection = "ANOSIM R" if len(options) > 0 and current_selection not in options else selection
clearable = False
options = [option for option in options if ("p-Value" in option) or option in ("ANOSIM R", "PERMANOVA F")]
if len(options) > 0 and current_selection not in options:
selection = None
elif len(options) == 0:
options = dash.no_update

return selection, options
return selection, options, name, clearable

@callback(
Output("cutoff-range", "min"),
Expand All @@ -291,23 +307,30 @@ def update_cutoff_selection(rapdordata: RAPDORData, current_selection):
Output("cutoff-range", "value"),
Output("cutoff-range", "disabled"),
Input("cutoff-type", "value"),
Input("dataset-plot-type", "value"),
State("data-store", "data")
)
def update_range_slider(cutoff_type, rapdordata: RAPDORData):
def update_range_slider(cutoff_type, plot_type, rapdordata: RAPDORData):
if plot_type != "Bubble Plot":
marks = [0, 1]
marks_t = {i: f"" for i in marks}
marks = []
return 0, 1, marks_t, marks, True
if cutoff_type is not None:
min_v = np.nanmin(rapdordata.df[cutoff_type])
max_v = np.nanmax(rapdordata.df[cutoff_type])
min_v = np.floor(min_v * 100) / 100
max_v = np.ceil(max_v * 100) / 100
if "p-Value" in cutoff_type:
min_v = min(1e-5, min_v)
if min_v == 0:
min_v = 1e-20
max_v = 1
min_v = np.floor(np.log10(min_v))
max_v = np.ceil(np.log10(max_v))
marks = np.linspace(min_v, max_v, 5)
marks = np.floor(marks)

p = np.log10(0.05)
iidx = np.searchsorted(marks, p)
marks = np.insert(marks, iidx, p)
Expand All @@ -329,11 +352,27 @@ def update_range_slider(cutoff_type, rapdordata: RAPDORData):
marks_t = None
d_max = None
disabled = True
logger.info(f"updating range slider: {min_v, max_v, marks_t, d_max, disabled}")
return min_v, max_v, marks_t, (min_v, d_max), disabled




@callback(
Output("showLFC", "on"),
Output("showLFC", "disabled"),
Output("3d-plot", "disabled"),
Input("3d-plot", "on"),
Input("dataset-plot-type", "value"),
)
def disable_lfc_and_3d(tdplot, plot_type):
if plot_type == "Bubble Plot":
if tdplot:
return False, True, False
else:
return dash.no_update, False, False
else:
return dash.no_update, False, True



Expand All @@ -342,6 +381,7 @@ def update_range_slider(cutoff_type, rapdordata: RAPDORData):
@callback(
Output("cluster-graph", "figure"),
Input("night-mode", "on"),
Input("dataset-plot-type", "value"),
Input("primary-color", "data"),
Input("secondary-color", "data"),
Input("plot-dim-red", "data"),
Expand All @@ -350,47 +390,60 @@ def update_range_slider(cutoff_type, rapdordata: RAPDORData):
Input('3d-plot', 'on'),
Input('cutoff-range', 'value'),
Input("additional-header-dd", "value"),
Input("showLFC", "on"),
State('cutoff-type', 'value'),
State('data-store', "data"),
)
def plot_cluster_results(night_mode, color, color2, plotting, selected_rows, marker_size, td_plot, cutoff_range, add_header, cutoff_type, rapdordata: RAPDORData):
def plot_cluster_results(night_mode, plot_type, color, color2, plotting, selected_rows, marker_size, td_plot, cutoff_range, add_header, show_lfc, cutoff_type, rapdordata: RAPDORData):
logger.info(f"running cluster plot triggered via - {ctx.triggered_id}")
dim = 2 if not td_plot else 3
if dim == 3 and ctx.triggered_id == "cluster-marker-slider":
raise PreventUpdate
colors = [color, color2]
if rapdordata is None:
raise PreventUpdate

colors = [color, color2]
dim = 2 if not td_plot else 3
if not plotting:
fig = empty_figure("Data not Calculated<br> Get Scores first")
else:
if selected_rows is not None and len(selected_rows) >= 1:
highlight = rapdordata.df.loc[selected_rows, "RAPDORid"]
else:
highlight = None
logger.info(f"Cutoff - {cutoff_range}")
if cutoff_type is None:
cutoff_range = None
else:
if "p-Value" in cutoff_type:
cutoff_range = 10 ** cutoff_range[0], 10 ** cutoff_range[1]

fig = plot_dimension_reduction(
rapdordata,
dimensions=dim,
colors=colors,
highlight=highlight,
show_cluster=True if "Cluster" in rapdordata.df else False,
marker_max_size=marker_size,
second_bg_color="white" if not night_mode else "#181818",
bubble_legend_color="black" if not night_mode else "white",
title_col=add_header,
cutoff_range=cutoff_range,
cutoff_type=cutoff_type
if plot_type == "Bubble Plot":
if dim == 3 and ctx.triggered_id == "cluster-marker-slider":
raise PreventUpdate

logger.info(f"Cutoff - {cutoff_range}")
logger.info(f"highlight - {highlight}")
if cutoff_type is None:
cutoff_range = None
else:
if "p-Value" in cutoff_type:
cutoff_range = 10 ** cutoff_range[0], 10 ** cutoff_range[1]
if show_lfc:
highlight_color = "white" if night_mode else "black"
else:
highlight_color = None
fig = plot_dimension_reduction(
rapdordata,
dimensions=dim,
colors=colors,
highlight=highlight,
show_cluster=True if "Cluster" in rapdordata.df else False,
marker_max_size=marker_size,
second_bg_color="white" if not night_mode else "#181818",
bubble_legend_color="black" if not night_mode else "white",
title_col=add_header,
cutoff_range=cutoff_range,
cutoff_type=cutoff_type,
highlight_color=highlight_color,
show_lfc=show_lfc

)
)
else:
if cutoff_type is None:
fig = empty_figure("Select Y Axis Type first")
else:
fig = plot_distance_and_var(rapdordata, colors, title_col=add_header, highlight=highlight, var_type=cutoff_type, show_lfc=show_lfc)
fig.update_traces(marker=dict(size=marker_size))
if not night_mode:

fig.layout.template = DEFAULT_TEMPLATE
Expand Down
Loading

0 comments on commit b4e10b6

Please sign in to comment.