diff --git a/src/app.py b/src/app.py index 2999600..a0c3461 100644 --- a/src/app.py +++ b/src/app.py @@ -41,13 +41,15 @@ def server(input, output, session: Session): _adata: reactive.Value[ad.AnnData] = reactive.value(None) _adata_meta: reactive.Value[ad.AnnData] = reactive.value(None) + _adata_qc: reactive.Value[ad.AnnData] = reactive.value(None) _adata_filtered: reactive.Value[ad.AnnData] = reactive.value(None) _file_name = reactive.value(None) _distributions = reactive.value({}) _metadata = reactive.value(None) + _calculate_metrics_bool = reactive.value(False) - distributions_server("distributions", _adata_meta, _pretty_names, _distributions) - slider_server("sliders", _adata_meta, _adata_filtered, _pretty_names, _distributions) + distributions_server("distributions", _adata_qc, _pretty_names, _distributions) + slider_server("sliders", _adata_meta, _adata_qc, _adata_filtered, _pretty_names, _distributions, _calculate_metrics_bool) plots_server("plots", _adata_filtered, _pretty_names, _distributions) metadata_server("metadata", _adata, _metadata) @@ -63,8 +65,8 @@ def load_adata(): used_file = file[0] _file_name.set(used_file["name"]) adata = sc.read_h5ad(used_file["datapath"]) - calculate_qc_metrics(adata) _adata.set(adata) + _calculate_metrics_bool.set(True) @reactive.effect def update_adata_meta(): @@ -73,9 +75,9 @@ def update_adata_meta(): if adata is None or metadata is None: return adata_meta = adata.copy() - adata_meta.obs = metadata.copy() - calculate_qc_metrics(adata_meta) + adata_meta.obs = metadata _adata_meta.set(adata_meta) + _calculate_metrics_bool.set(True) @render.download( filename = lambda: _file_name.get().replace(".h5ad", "_filtered.h5ad"), diff --git a/src/sliders.py b/src/sliders.py index 8fd235a..b53a619 100644 --- a/src/sliders.py +++ b/src/sliders.py @@ -2,21 +2,30 @@ import anndata as ad from typing import Dict import numpy as np - +import pandas as pd +from helpers import calculate_qc_metrics +import asyncio +import concurrent.futures +import time +import functools + + @module.ui def slider_ui(): return ui.div( + ui.output_ui("button"), ui.output_ui("slider_sample"), - ui.output_ui("slider_filters") + ui.output_ui("slider_filters") ) - - + @module.server def slider_server(input, output, session, - _adata: reactive.Value[ad.AnnData], + _adata_meta: reactive.Value[ad.AnnData], + _adata_qc: reactive.Value[ad.AnnData], _adata_filtered: reactive.Value[ad.AnnData], _pretty_names: reactive.Value[Dict[str, str]], - _distributions: reactive.Value[Dict[str, Dict[str, float]]] + _distributions: reactive.Value[Dict[str, Dict[str, float]]], + _calculate_metrics_bool: reactive.value[bool], ): _adata_sample = reactive.value(None) _prev_mads = reactive.value({}) @@ -24,16 +33,49 @@ def slider_server(input, output, session, @output @render.ui def slider_sample(): - adata = _adata.get() + adata = _adata_qc.get() if adata is None: return n_obs = adata.n_obs return ui.input_slider('random_sample_size', 'Random sample size', min(100, n_obs), n_obs, min(10000, n_obs), post=" cells") + @output + @render.ui + def button(): + calculate_metrics_bool = _calculate_metrics_bool.get() + if calculate_metrics_bool is None: + return + + if calculate_metrics_bool: + return ui.input_task_button("calculate_button", "Recalculate QC metrics", style="background-color: rgb(153, 0, 255); border-color: rgb(153, 0, 255);") + else: + return None + + @ui.bind_task_button(button_id="calculate_button") + @reactive.extended_task + async def recalc_logic(adata_meta): + adata_meta_copy = adata_meta.copy() + calculate_qc_metrics(adata_meta_copy) + return adata_meta_copy + + @reactive.effect + @reactive.event(input.calculate_button, ignore_none=True) + def handle_click(): + adata_meta = _adata_meta.get() + if adata_meta is None: + return + recalc_logic(adata_meta) + + @reactive.effect + def return_of_adata_meta(): + result = recalc_logic.result() + _adata_qc.set(result) + _calculate_metrics_bool.set(False) + @reactive.effect def random_sample(): - adata = _adata.get() + adata = _adata_qc.get() sample_size = input['random_sample_size'].get() if adata is None: