decoupler 1.3.2__tar.gz → 1.9.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- decoupler-1.9.2/PKG-INFO +95 -0
- decoupler-1.3.2/PKG-INFO → decoupler-1.9.2/README.md +18 -22
- decoupler-1.9.2/decoupler/__init__.py +39 -0
- {decoupler-1.3.2 → decoupler-1.9.2}/decoupler/benchmark.py +38 -22
- {decoupler-1.3.2 → decoupler-1.9.2}/decoupler/decouple.py +23 -9
- {decoupler-1.3.2 → decoupler-1.9.2}/decoupler/method_aucell.py +52 -59
- decoupler-1.9.2/decoupler/method_gsea.py +368 -0
- decoupler-1.9.2/decoupler/method_gsva.py +324 -0
- {decoupler-1.3.2 → decoupler-1.9.2}/decoupler/method_mdt.py +13 -15
- {decoupler-1.3.2 → decoupler-1.9.2}/decoupler/method_mlm.py +19 -21
- {decoupler-1.3.2 → decoupler-1.9.2}/decoupler/method_ora.py +97 -70
- {decoupler-1.3.2 → decoupler-1.9.2}/decoupler/method_udt.py +11 -12
- {decoupler-1.3.2 → decoupler-1.9.2}/decoupler/method_ulm.py +41 -45
- {decoupler-1.3.2 → decoupler-1.9.2}/decoupler/method_viper.py +22 -19
- {decoupler-1.3.2 → decoupler-1.9.2}/decoupler/method_wmean.py +30 -31
- {decoupler-1.3.2 → decoupler-1.9.2}/decoupler/method_wsum.py +29 -30
- decoupler-1.9.2/decoupler/method_zscore.py +89 -0
- {decoupler-1.3.2 → decoupler-1.9.2}/decoupler/metrics.py +44 -0
- decoupler-1.9.2/decoupler/omnip.py +440 -0
- decoupler-1.9.2/decoupler/plotting.py +1909 -0
- {decoupler-1.3.2 → decoupler-1.9.2}/decoupler/pre.py +67 -19
- decoupler-1.9.2/decoupler/tests/__init__.py +0 -0
- decoupler-1.9.2/decoupler/tests/test_aucell.py +39 -0
- decoupler-1.9.2/decoupler/tests/test_benchmark.py +89 -0
- decoupler-1.9.2/decoupler/tests/test_consensus.py +31 -0
- decoupler-1.9.2/decoupler/tests/test_decouple.py +64 -0
- decoupler-1.9.2/decoupler/tests/test_gsea.py +49 -0
- decoupler-1.9.2/decoupler/tests/test_gsva.py +96 -0
- decoupler-1.9.2/decoupler/tests/test_mdt.py +52 -0
- decoupler-1.9.2/decoupler/tests/test_metrics.py +122 -0
- decoupler-1.9.2/decoupler/tests/test_mlm.py +33 -0
- decoupler-1.9.2/decoupler/tests/test_omnip.py +62 -0
- decoupler-1.9.2/decoupler/tests/test_ora.py +61 -0
- decoupler-1.9.2/decoupler/tests/test_plotting.py +495 -0
- decoupler-1.9.2/decoupler/tests/test_pre.py +141 -0
- decoupler-1.9.2/decoupler/tests/test_udt.py +53 -0
- decoupler-1.9.2/decoupler/tests/test_ulm.py +84 -0
- decoupler-1.9.2/decoupler/tests/test_utils.py +162 -0
- decoupler-1.9.2/decoupler/tests/test_utilsanndata.py +585 -0
- decoupler-1.9.2/decoupler/tests/test_utilsbenchmark.py +421 -0
- decoupler-1.9.2/decoupler/tests/test_viper.py +43 -0
- decoupler-1.9.2/decoupler/tests/test_wmean.py +33 -0
- decoupler-1.9.2/decoupler/tests/test_wsum.py +33 -0
- decoupler-1.9.2/decoupler/tests/test_zscore.py +52 -0
- {decoupler-1.3.2 → decoupler-1.9.2}/decoupler/utils.py +12 -7
- decoupler-1.9.2/decoupler/utils_anndata.py +1120 -0
- {decoupler-1.3.2 → decoupler-1.9.2}/decoupler/utils_benchmark.py +85 -62
- decoupler-1.9.2/pyproject.toml +105 -0
- decoupler-1.3.2/README.md +0 -45
- decoupler-1.3.2/decoupler/__init__.py +0 -27
- decoupler-1.3.2/decoupler/method_gsea.py +0 -270
- decoupler-1.3.2/decoupler/method_gsva.py +0 -237
- decoupler-1.3.2/decoupler/omnip.py +0 -467
- decoupler-1.3.2/decoupler/plotting.py +0 -710
- decoupler-1.3.2/decoupler/utils_anndata.py +0 -544
- decoupler-1.3.2/decoupler.egg-info/PKG-INFO +0 -59
- decoupler-1.3.2/decoupler.egg-info/SOURCES.txt +0 -30
- decoupler-1.3.2/decoupler.egg-info/dependency_links.txt +0 -1
- decoupler-1.3.2/decoupler.egg-info/requires.txt +0 -4
- decoupler-1.3.2/decoupler.egg-info/top_level.txt +0 -1
- decoupler-1.3.2/setup.cfg +0 -4
- decoupler-1.3.2/setup.py +0 -27
- {decoupler-1.3.2 → decoupler-1.9.2}/LICENSE +0 -0
- {decoupler-1.3.2 → decoupler-1.9.2}/decoupler/consensus.py +0 -0
decoupler-1.9.2/PKG-INFO
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: decoupler
|
|
3
|
+
Version: 1.9.2
|
|
4
|
+
Summary: Ensemble of methods to infer biological activities from omics data
|
|
5
|
+
License: GPL-3.0-only
|
|
6
|
+
Keywords: systems biology,molecular biology,signaling network,transcriptomics,modeling,mechanistic modeling,activity inference,molecular network,omics,biomedicine,molecular footprint,molecular signature
|
|
7
|
+
Author: Pau Badia i Mompel
|
|
8
|
+
Author-email: pau.badia@uni-heidelberg.de
|
|
9
|
+
Requires-Python: >=3.10,<3.12
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: License :: OSI Approved :: GNU General Public License v3 (GPLv3)
|
|
14
|
+
Classifier: Natural Language :: English
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python
|
|
17
|
+
Classifier: Programming Language :: Python :: 3
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
|
|
21
|
+
Provides-Extra: full
|
|
22
|
+
Requires-Dist: adjusttext (>=1.1.1,<2.0.0) ; extra == "full"
|
|
23
|
+
Requires-Dist: igraph (>=0.11.5,<0.12.0) ; extra == "full"
|
|
24
|
+
Requires-Dist: liana (>=1.5.0,<2.0.0) ; extra == "full"
|
|
25
|
+
Requires-Dist: marsilea (>=0.4.5,<0.5.0) ; extra == "full"
|
|
26
|
+
Requires-Dist: numba (>=0.61.0,<0.62.0)
|
|
27
|
+
Requires-Dist: numpy (>=2,<3)
|
|
28
|
+
Requires-Dist: pandas (>=2.2.2,<3.0.0)
|
|
29
|
+
Requires-Dist: pybiomart (>=0.2.0,<0.3.0) ; extra == "full"
|
|
30
|
+
Requires-Dist: pydeseq2 (>=0.4.0,<0.5.0) ; extra == "full"
|
|
31
|
+
Requires-Dist: scikit-learn (>=1.5.0,<2.0.0) ; extra == "full"
|
|
32
|
+
Requires-Dist: tqdm (>=4.66.4,<5.0.0)
|
|
33
|
+
Requires-Dist: typing-extensions (>=4.12.2,<5.0.0)
|
|
34
|
+
Project-URL: Bug Tracker, https://github.com/saezlab/decoupler-py/issues
|
|
35
|
+
Project-URL: Documentation, https://decoupler.readthedocs.io/
|
|
36
|
+
Project-URL: Homepage, https://decoupler.readthedocs.io/
|
|
37
|
+
Project-URL: Repository, https://github.com/saezlab/decoupler-py
|
|
38
|
+
Description-Content-Type: text/markdown
|
|
39
|
+
|
|
40
|
+
# decoupler - Ensemble of methods to infer biological activities <img src="https://github.com/saezlab/decoupleR/blob/master/inst/figures/logo.svg?raw=1" align="right" width="120" class="no-scaled-link" />
|
|
41
|
+
<!-- badges: start -->
|
|
42
|
+
[](https://github.com/saezlab/decoupler-py/actions)
|
|
43
|
+
[](https://github.com/saezlab/decoupler-py/issues/)
|
|
44
|
+
[](https://decoupler-py.readthedocs.io/en/latest/?badge=latest)
|
|
45
|
+
[](https://codecov.io/gh/saezlab/decoupler-py)
|
|
46
|
+
[](https://pepy.tech/project/decoupler)
|
|
47
|
+
|
|
48
|
+
[](https://anaconda.org/conda-forge/decoupler-py)
|
|
49
|
+
[](https://anaconda.org/conda-forge/decoupler-py)
|
|
50
|
+
[](https://anaconda.org/conda-forge/decoupler-py)
|
|
51
|
+
<!-- badges: end -->
|
|
52
|
+
|
|
53
|
+
`decoupler` is a package containing different enrichment statistical methods to extract biologically driven scores from omics data within a unified framework.
|
|
54
|
+
This is its faster and memory efficient Python implementation, for the R version go [here](https://github.com/saezlab/decoupleR).
|
|
55
|
+
|
|
56
|
+
For further information and example tutorials, please check our [documentation](https://decoupler-py.readthedocs.io/en/latest/index.html).
|
|
57
|
+
|
|
58
|
+
If you have any question or problem do not hesitate to open an [issue](https://github.com/saezlab/decoupler-py/issues).
|
|
59
|
+
|
|
60
|
+
## Installation
|
|
61
|
+
|
|
62
|
+
`decoupler` can be installed from `pip` (lightweight installation)::
|
|
63
|
+
```
|
|
64
|
+
pip install decoupler
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
It can also be installed from `conda` and `mamba` (this includes extra dependencies):
|
|
68
|
+
```
|
|
69
|
+
mamba create -n=decoupler conda-forge::decoupler-py
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Alternatively, to stay up-to-date with the newest unreleased version, install from source:
|
|
73
|
+
```
|
|
74
|
+
pip install git+https://github.com/saezlab/decoupler-py.git
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## scverse
|
|
78
|
+
`decoupler` is part of the [scverse](https://scverse.org) ecosystem, a collection of tools for single-cell omics data analysis in python.
|
|
79
|
+
For more information check the link.
|
|
80
|
+
|
|
81
|
+
## License
|
|
82
|
+
Enrichment methods inside decoupler can be used for academic or commercial purposes, except `viper` which holds a non-commercial license.
|
|
83
|
+
|
|
84
|
+
The data redistributed by OmniPath does not have a single license, each original resource has its own. By default, `decoupler`
|
|
85
|
+
assumes an academic license, but commercial or nonprofit licenses can be specified in the `license` parameter of `decoupler`'s OmniPath functions.
|
|
86
|
+
[Here](https://omnipathdb.org/info) one can find the license information of all the resources in OmniPath.
|
|
87
|
+
|
|
88
|
+
## Citation
|
|
89
|
+
|
|
90
|
+
Badia-i-Mompel P., Vélez Santiago J., Braunger J., Geiss C., Dimitrov D.,
|
|
91
|
+
Müller-Dott S., Taus P., Dugourd A., Holland C.H., Ramirez Flores R.O.
|
|
92
|
+
and Saez-Rodriguez J. 2022. decoupleR: Ensemble of computational methods
|
|
93
|
+
to infer biological activities from omics data. Bioinformatics Advances.
|
|
94
|
+
<https://doi.org/10.1093/bioadv/vbac016>
|
|
95
|
+
|
|
@@ -1,27 +1,17 @@
|
|
|
1
|
-
Metadata-Version: 2.1
|
|
2
|
-
Name: decoupler
|
|
3
|
-
Version: 1.3.2
|
|
4
|
-
Summary: Ensemble of methods to infer biological activities from omics data
|
|
5
|
-
Home-page: https://github.com/saezlab/decoupler-py
|
|
6
|
-
Author: Pau Badia i Mompel
|
|
7
|
-
Author-email: pau.badia@uni-heidelberg.de
|
|
8
|
-
Project-URL: Bug Tracker, https://github.com/saezlab/decoupler-py/issues
|
|
9
|
-
Classifier: Programming Language :: Python :: 3
|
|
10
|
-
Classifier: Operating System :: OS Independent
|
|
11
|
-
Requires-Python: >=3.6
|
|
12
|
-
Description-Content-Type: text/markdown
|
|
13
|
-
License-File: LICENSE
|
|
14
|
-
|
|
15
1
|
# decoupler - Ensemble of methods to infer biological activities <img src="https://github.com/saezlab/decoupleR/blob/master/inst/figures/logo.svg?raw=1" align="right" width="120" class="no-scaled-link" />
|
|
16
2
|
<!-- badges: start -->
|
|
17
|
-
[](https://github.com/saezlab/decoupler-py/actions)
|
|
18
4
|
[](https://github.com/saezlab/decoupler-py/issues/)
|
|
19
|
-
[](https://pepy.tech/project/decoupler)
|
|
20
5
|
[](https://decoupler-py.readthedocs.io/en/latest/?badge=latest)
|
|
21
6
|
[](https://codecov.io/gh/saezlab/decoupler-py)
|
|
7
|
+
[](https://pepy.tech/project/decoupler)
|
|
8
|
+
|
|
9
|
+
[](https://anaconda.org/conda-forge/decoupler-py)
|
|
10
|
+
[](https://anaconda.org/conda-forge/decoupler-py)
|
|
11
|
+
[](https://anaconda.org/conda-forge/decoupler-py)
|
|
22
12
|
<!-- badges: end -->
|
|
23
13
|
|
|
24
|
-
|
|
14
|
+
`decoupler` is a package containing different enrichment statistical methods to extract biologically driven scores from omics data within a unified framework.
|
|
25
15
|
This is its faster and memory efficient Python implementation, for the R version go [here](https://github.com/saezlab/decoupleR).
|
|
26
16
|
|
|
27
17
|
For further information and example tutorials, please check our [documentation](https://decoupler-py.readthedocs.io/en/latest/index.html).
|
|
@@ -30,24 +20,30 @@ If you have any question or problem do not hesitate to open an [issue](https://g
|
|
|
30
20
|
|
|
31
21
|
## Installation
|
|
32
22
|
|
|
33
|
-
|
|
23
|
+
`decoupler` can be installed from `pip` (lightweight installation)::
|
|
34
24
|
```
|
|
35
25
|
pip install decoupler
|
|
36
26
|
```
|
|
37
27
|
|
|
38
|
-
|
|
28
|
+
It can also be installed from `conda` and `mamba` (this includes extra dependencies):
|
|
29
|
+
```
|
|
30
|
+
mamba create -n=decoupler conda-forge::decoupler-py
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Alternatively, to stay up-to-date with the newest unreleased version, install from source:
|
|
39
34
|
```
|
|
40
35
|
pip install git+https://github.com/saezlab/decoupler-py.git
|
|
41
36
|
```
|
|
42
37
|
|
|
43
38
|
## scverse
|
|
44
|
-
|
|
39
|
+
`decoupler` is part of the [scverse](https://scverse.org) ecosystem, a collection of tools for single-cell omics data analysis in python.
|
|
45
40
|
For more information check the link.
|
|
46
41
|
|
|
47
42
|
## License
|
|
48
|
-
|
|
43
|
+
Enrichment methods inside decoupler can be used for academic or commercial purposes, except `viper` which holds a non-commercial license.
|
|
49
44
|
|
|
50
|
-
The data redistributed by OmniPath does not have a license, each original resource
|
|
45
|
+
The data redistributed by OmniPath does not have a single license, each original resource has its own. By default, `decoupler`
|
|
46
|
+
assumes an academic license, but commercial or nonprofit licenses can be specified in the `license` parameter of `decoupler`'s OmniPath functions.
|
|
51
47
|
[Here](https://omnipathdb.org/info) one can find the license information of all the resources in OmniPath.
|
|
52
48
|
|
|
53
49
|
## Citation
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
__version__ = '1.9.2' # noqa: F401
|
|
2
|
+
__version_info__ = tuple([int(num) for num in __version__.split('.')]) # noqa: F401
|
|
3
|
+
|
|
4
|
+
from .pre import extract, match, rename_net, get_net_mat, filt_min_n, mask_features, return_data, break_ties # noqa: F401
|
|
5
|
+
from .utils import (
|
|
6
|
+
melt, show_methods, check_corr, get_toy_data, summarize_acts, assign_groups, dense_run, p_adjust_fdr, shuffle_net,
|
|
7
|
+
read_gmt # noqa: F401
|
|
8
|
+
)
|
|
9
|
+
from .utils_anndata import (
|
|
10
|
+
get_acts, swap_layer, get_pseudobulk, get_contrast, rank_sources_groups, get_top_targets, format_contrast_results,
|
|
11
|
+
filter_by_expr, filter_by_prop, get_metadata_associations # noqa: F401
|
|
12
|
+
)
|
|
13
|
+
from .method_wmean import run_wmean # noqa: F401
|
|
14
|
+
from .method_wsum import run_wsum # noqa: F401
|
|
15
|
+
from .method_ulm import run_ulm # noqa: F401
|
|
16
|
+
from .method_mdt import run_mdt # noqa: F401
|
|
17
|
+
from .method_mlm import run_mlm # noqa: F401
|
|
18
|
+
from .method_udt import run_udt # noqa: F401
|
|
19
|
+
from .method_ora import run_ora, test1r, get_ora_df # noqa: F401
|
|
20
|
+
from .method_gsva import run_gsva # noqa: F401
|
|
21
|
+
from .method_gsea import run_gsea, get_gsea_df # noqa: F401
|
|
22
|
+
from .method_viper import run_viper # noqa: F401
|
|
23
|
+
from .method_aucell import run_aucell # noqa: F401
|
|
24
|
+
from .method_zscore import run_zscore # noqa: F401
|
|
25
|
+
from .decouple import decouple, run_consensus # noqa: F401
|
|
26
|
+
from .consensus import cons # noqa: F401
|
|
27
|
+
from .omnip import (
|
|
28
|
+
show_resources, get_resource, get_progeny, get_dorothea, translate_net, get_collectri, get_ksn_omnipath, show_organisms # noqa: F401
|
|
29
|
+
)
|
|
30
|
+
from .plotting import (
|
|
31
|
+
plot_volcano, plot_violins, plot_barplot, plot_metrics_scatter, plot_metrics_boxplot, plot_metrics_scatter_cols,
|
|
32
|
+
plot_psbulk_samples, plot_filter_by_expr, plot_filter_by_prop, plot_volcano_df, plot_targets, plot_running_score,
|
|
33
|
+
plot_dotplot, plot_barplot_df, plot_associations, plot_network # noqa: F401
|
|
34
|
+
)
|
|
35
|
+
from .benchmark import benchmark, format_benchmark_inputs, get_performances # noqa: F401
|
|
36
|
+
from .utils_benchmark import get_toy_benchmark_data, show_metrics # noqa: F401
|
|
37
|
+
from .metrics import (
|
|
38
|
+
metric_auroc, metric_auprc, metric_mcauroc, metric_mcauprc, metric_rank, metric_nrank, metric_recall # noqa: F401
|
|
39
|
+
)
|
|
@@ -9,15 +9,15 @@ import pandas as pd
|
|
|
9
9
|
from .decouple import decouple
|
|
10
10
|
from .utils_anndata import extract_psbulk_inputs
|
|
11
11
|
from .pre import rename_net, filt_min_n
|
|
12
|
-
from .utils_benchmark import format_acts_grts, append_metrics_scores
|
|
12
|
+
from .utils_benchmark import format_acts_grts, append_metrics_scores, adjust_sign
|
|
13
13
|
from .utils_benchmark import validate_metrics, check_groupby, rename_obs
|
|
14
14
|
|
|
15
15
|
|
|
16
|
-
def get_performances(res, obs, groupby, by, metrics, min_exp=5, pi0=0.5,
|
|
17
|
-
seed=42, verbose=False):
|
|
16
|
+
def get_performances(res, obs, groupby, by, metrics, use_pval=None, min_exp=5, pi0=0.5,
|
|
17
|
+
n_iter=1000, seed=42, verbose=False):
|
|
18
18
|
|
|
19
19
|
# Return acts, grts and msks tensors
|
|
20
|
-
acts, grts, msks, srcs, mthds, grpbys, grps = format_acts_grts(res, obs, groupby)
|
|
20
|
+
acts, grts, msks, srcs, mthds, grpbys, grps = format_acts_grts(res, obs, groupby, use_pval)
|
|
21
21
|
|
|
22
22
|
# Init empty df
|
|
23
23
|
df = []
|
|
@@ -90,30 +90,36 @@ def format_benchmark_inputs(mat, obs, perturb, sign, net, groupby, by, f_expr=Tr
|
|
|
90
90
|
srcs = net['source'].values.astype('U')
|
|
91
91
|
for i, src in enumerate(obs['perturb']):
|
|
92
92
|
msk[i] = np.any(np.isin(src, srcs))
|
|
93
|
-
if verbose:
|
|
94
|
-
n = np.sum(~msk)
|
|
95
|
-
print("{0} experiments without sources in net, they will be removed.".format(n))
|
|
96
93
|
mat, obs = mat[msk], obs.loc[msk]
|
|
94
|
+
if verbose:
|
|
95
|
+
n_removed = np.sum(~msk)
|
|
96
|
+
print("Removed {0} experiments without sources in net.".format(n_removed))
|
|
97
97
|
|
|
98
98
|
# Remove sources without experiments in obs
|
|
99
99
|
if f_srcs:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
n = np.sum(~msk)
|
|
103
|
-
print("{0} sources without experiments in obs, they will be removed.".format(n))
|
|
100
|
+
srcs = net.loc[:, 'source'].values
|
|
101
|
+
msk = np.isin(srcs, obs['perturb'].values.ravel())
|
|
104
102
|
net = net.loc[msk]
|
|
103
|
+
if verbose:
|
|
104
|
+
n_removed = np.unique(srcs[~msk]).size
|
|
105
|
+
print("Removed {0} sources without experiments in obs.".format(n_removed))
|
|
105
106
|
|
|
106
107
|
return mat, obs, var, net, groupby
|
|
107
108
|
|
|
108
109
|
|
|
109
110
|
def _benchmark(mat, obs, net, perturb, sign, metrics=['auroc', 'auprc'], groupby=None, by='experiment', f_expr=True,
|
|
110
|
-
f_srcs=False, min_exp=5, pi0=0.5, n_iter=1000, seed=42, verbose=True, use_raw=True,
|
|
111
|
+
f_srcs=False, use_pval=None, min_exp=5, pi0=0.5, n_iter=1000, seed=42, verbose=True, use_raw=True,
|
|
112
|
+
decouple_kws={}):
|
|
111
113
|
|
|
112
114
|
# Format inputs
|
|
113
115
|
mat, obs, var, net, groupby = format_benchmark_inputs(mat, obs, perturb, sign, net, groupby, by, f_expr=f_expr,
|
|
114
116
|
f_srcs=f_srcs, verbose=verbose, use_raw=use_raw,
|
|
115
117
|
decouple_kws=decouple_kws)
|
|
116
118
|
|
|
119
|
+
# Adjust sign
|
|
120
|
+
mat = adjust_sign(mat, obs['sign'].values)
|
|
121
|
+
obs['sign'] = 1
|
|
122
|
+
|
|
117
123
|
# Reset net names args
|
|
118
124
|
decouple_kws['source'] = 'source'
|
|
119
125
|
decouple_kws['target'] = 'target'
|
|
@@ -121,23 +127,31 @@ def _benchmark(mat, obs, net, perturb, sign, metrics=['auroc', 'auprc'], groupby
|
|
|
121
127
|
|
|
122
128
|
# Run prediction
|
|
123
129
|
if verbose:
|
|
130
|
+
srcs = []
|
|
131
|
+
for p in obs.loc[:, 'perturb']:
|
|
132
|
+
if isinstance(p, list):
|
|
133
|
+
srcs.extend(p)
|
|
134
|
+
else:
|
|
135
|
+
srcs.append(p)
|
|
136
|
+
n_src = np.unique(srcs).size
|
|
137
|
+
print("Running {0} experiments for {1} unique sources.".format(mat.shape[0], n_src))
|
|
124
138
|
print('Running methods...')
|
|
125
139
|
res = decouple([mat, obs.index, var.index], net, verbose=verbose, **decouple_kws)
|
|
126
140
|
|
|
127
141
|
# Compute metrics
|
|
128
142
|
if verbose:
|
|
129
143
|
print('Calculating metrics...')
|
|
130
|
-
df = get_performances(res, obs, groupby, by, metrics,
|
|
131
|
-
n_iter=n_iter, seed=seed, verbose=verbose)
|
|
144
|
+
df = get_performances(res, obs, groupby, by, metrics, use_pval=use_pval, min_exp=min_exp,
|
|
145
|
+
pi0=pi0, n_iter=n_iter, seed=seed, verbose=verbose)
|
|
132
146
|
if verbose:
|
|
133
147
|
print('Done.')
|
|
134
148
|
|
|
135
149
|
return df
|
|
136
150
|
|
|
137
151
|
|
|
138
|
-
def benchmark(mat, obs, net, perturb, sign, metrics=['auroc', 'auprc', 'mcauroc', 'mcauprc'
|
|
139
|
-
by='experiment', f_expr=True, f_srcs=False, min_exp=5, pi0=0.5, n_iter=1000,
|
|
140
|
-
verbose=True, use_raw=True, decouple_kws={}):
|
|
152
|
+
def benchmark(mat, obs, net, perturb, sign, metrics=['auroc', 'auprc', 'mcauroc', 'mcauprc', 'rank', 'nrank', 'recall'],
|
|
153
|
+
groupby=None, by='experiment', f_expr=True, f_srcs=False, use_pval=None, min_exp=5, pi0=0.5, n_iter=1000,
|
|
154
|
+
seed=42, verbose=True, use_raw=True, decouple_kws={}):
|
|
141
155
|
"""
|
|
142
156
|
Benchmark methods or networks on a given set of perturbation experiments using activity inference with decoupler.
|
|
143
157
|
|
|
@@ -156,8 +170,7 @@ def benchmark(mat, obs, net, perturb, sign, metrics=['auroc', 'auprc', 'mcauroc'
|
|
|
156
170
|
Column name in obs with sign of the perturbation. Can be set to 1 or -1 if all experiments are overexpression or
|
|
157
171
|
knockouts, respectively.
|
|
158
172
|
metrics : list, str
|
|
159
|
-
Performance metric(s) to compute. See the description of get_performance for more details.
|
|
160
|
-
to ['roc', 'calprc'].
|
|
173
|
+
Performance metric(s) to compute. See the description of get_performance for more details.
|
|
161
174
|
groupby : list, str, None
|
|
162
175
|
Performance metrics(s) can be computed per groups if enough experiments are available.
|
|
163
176
|
by : str
|
|
@@ -166,6 +179,9 @@ def benchmark(mat, obs, net, perturb, sign, metrics=['auroc', 'auprc', 'mcauroc'
|
|
|
166
179
|
Whether to filter out experiments whose perturbed sources are not in the given net. Defaults to True.
|
|
167
180
|
f_srcs : bool
|
|
168
181
|
Whether to fitler out sources in net for which there are not perturbation data. Defaults to False.
|
|
182
|
+
use_pval: None, float
|
|
183
|
+
Whether to fitler out activity scores by a given p-value after FDR correction (BH). Defaults to None. Methods that
|
|
184
|
+
generate no p-value will use the (1 - pvalue) quantile based on activity score as being significant.
|
|
169
185
|
min_exp : int
|
|
170
186
|
Minimum of perturbation experiments per group.
|
|
171
187
|
pi0 : float
|
|
@@ -211,8 +227,8 @@ def benchmark(mat, obs, net, perturb, sign, metrics=['auroc', 'auprc', 'mcauroc'
|
|
|
211
227
|
decouple_kws = {**default_kws, **decouple_kws}
|
|
212
228
|
|
|
213
229
|
# Run benchmark
|
|
214
|
-
df = _benchmark(mat, obs, net, perturb, sign, metrics, groupby, by, f_expr, f_srcs,
|
|
215
|
-
n_iter, seed, verbose, use_raw, decouple_kws)
|
|
230
|
+
df = _benchmark(mat, obs, net, perturb, sign, metrics, groupby, by, f_expr, f_srcs, use_pval, min_exp,
|
|
231
|
+
pi0, n_iter, seed, verbose, use_raw, decouple_kws)
|
|
216
232
|
else:
|
|
217
233
|
df = []
|
|
218
234
|
for net_name in net:
|
|
@@ -226,7 +242,7 @@ def benchmark(mat, obs, net, perturb, sign, metrics=['auroc', 'auprc', 'mcauroc'
|
|
|
226
242
|
|
|
227
243
|
# Run benchmark
|
|
228
244
|
tmp = _benchmark(mat, obs, net[net_name], perturb, sign, metrics, groupby, by, f_expr, f_srcs,
|
|
229
|
-
min_exp, pi0, n_iter, seed, verbose, use_raw, decouple_kws[net_name])
|
|
245
|
+
use_pval, min_exp, pi0, n_iter, seed, verbose, use_raw, decouple_kws[net_name])
|
|
230
246
|
tmp['net'] = net_name
|
|
231
247
|
df.append(tmp)
|
|
232
248
|
|
|
@@ -5,7 +5,7 @@ Code to run methods simultaneously.
|
|
|
5
5
|
|
|
6
6
|
import decoupler as dc
|
|
7
7
|
from anndata import AnnData
|
|
8
|
-
|
|
8
|
+
from .utils import show_methods, dense_run
|
|
9
9
|
from .consensus import cons
|
|
10
10
|
from .pre import extract
|
|
11
11
|
|
|
@@ -21,7 +21,7 @@ def get_wrappers(methods):
|
|
|
21
21
|
return tmp
|
|
22
22
|
|
|
23
23
|
|
|
24
|
-
def run_methods(mat, net, source, target, weight, methods, args, min_n, verbose, use_raw):
|
|
24
|
+
def run_methods(mat, net, source, target, weight, methods, args, min_n, verbose, use_raw, dense):
|
|
25
25
|
|
|
26
26
|
# Retrieve wrapper functions
|
|
27
27
|
wrappers = get_wrappers(methods)
|
|
@@ -45,10 +45,20 @@ def run_methods(mat, net, source, target, weight, methods, args, min_n, verbose,
|
|
|
45
45
|
is_weighted = 'weight' in f.__code__.co_varnames
|
|
46
46
|
|
|
47
47
|
# Run method
|
|
48
|
-
if is_weighted:
|
|
48
|
+
if is_weighted and not dense:
|
|
49
49
|
res = f(mat=mat, net=net, source=source, target=target, weight=weight, **a)
|
|
50
|
-
|
|
50
|
+
elif not is_weighted and not dense:
|
|
51
51
|
res = f(mat=mat, net=net, source=source, target=target, **a)
|
|
52
|
+
else:
|
|
53
|
+
res = dense_run(
|
|
54
|
+
func=f,
|
|
55
|
+
mat=mat,
|
|
56
|
+
net=net,
|
|
57
|
+
source=source,
|
|
58
|
+
target=target,
|
|
59
|
+
weight=weight,
|
|
60
|
+
**a
|
|
61
|
+
)
|
|
52
62
|
|
|
53
63
|
# Extract for AnnData
|
|
54
64
|
if res is None:
|
|
@@ -78,7 +88,7 @@ def parse_methods(methods, cns_metds):
|
|
|
78
88
|
cns_metds = ['mlm_estimate', 'ulm_estimate', 'wsum_norm']
|
|
79
89
|
elif not isinstance(methods, list):
|
|
80
90
|
if methods.lower() == 'all':
|
|
81
|
-
methods = [method.split('run_')[1] for method in
|
|
91
|
+
methods = [method.split('run_')[1] for method in show_methods()['Function'] if method != 'run_consensus']
|
|
82
92
|
else:
|
|
83
93
|
methods = [methods]
|
|
84
94
|
|
|
@@ -86,7 +96,7 @@ def parse_methods(methods, cns_metds):
|
|
|
86
96
|
|
|
87
97
|
|
|
88
98
|
def decouple(mat, net, source='source', target='target', weight='weight', methods=None, args={}, consensus=True,
|
|
89
|
-
cns_metds=None, min_n=5, verbose=True, use_raw=True):
|
|
99
|
+
cns_metds=None, min_n=5, verbose=True, use_raw=True, dense=False):
|
|
90
100
|
"""
|
|
91
101
|
Decouple function.
|
|
92
102
|
|
|
@@ -120,6 +130,8 @@ def decouple(mat, net, source='source', target='target', weight='weight', method
|
|
|
120
130
|
Whether to show progress.
|
|
121
131
|
use_raw : bool
|
|
122
132
|
If mat is AnnData, use its raw attribute.
|
|
133
|
+
dense : bool
|
|
134
|
+
Whether to run methods ignoring zero values per observation. See ``decoupler.dense_run`` for more information.
|
|
123
135
|
|
|
124
136
|
Returns
|
|
125
137
|
-------
|
|
@@ -138,7 +150,7 @@ def decouple(mat, net, source='source', target='target', weight='weight', method
|
|
|
138
150
|
print('Method name {0} in args not found in methods, will be ignored.'.format(methd))
|
|
139
151
|
|
|
140
152
|
# Run methods
|
|
141
|
-
results = run_methods(mat, net, source, target, weight, methods, args, min_n, verbose, use_raw)
|
|
153
|
+
results = run_methods(mat, net, source, target, weight, methods, args, min_n, verbose, use_raw, dense)
|
|
142
154
|
|
|
143
155
|
# Run consensus score
|
|
144
156
|
if consensus:
|
|
@@ -161,7 +173,7 @@ def decouple(mat, net, source='source', target='target', weight='weight', method
|
|
|
161
173
|
return results
|
|
162
174
|
|
|
163
175
|
|
|
164
|
-
def run_consensus(mat, net, source='source', target='target', weight='weight', min_n=5, verbose=False, use_raw=True):
|
|
176
|
+
def run_consensus(mat, net, source='source', target='target', weight='weight', min_n=5, verbose=False, use_raw=True, args={}):
|
|
165
177
|
"""
|
|
166
178
|
Consensus score from top methods.
|
|
167
179
|
|
|
@@ -192,6 +204,8 @@ def run_consensus(mat, net, source='source', target='target', weight='weight', m
|
|
|
192
204
|
Whether to show progress.
|
|
193
205
|
use_raw : bool
|
|
194
206
|
Use raw attribute of mat if present.
|
|
207
|
+
args : dict
|
|
208
|
+
Parameters for the ``decoupler.decouple`` function.
|
|
195
209
|
|
|
196
210
|
Returns
|
|
197
211
|
-------
|
|
@@ -209,7 +223,7 @@ def run_consensus(mat, net, source='source', target='target', weight='weight', m
|
|
|
209
223
|
|
|
210
224
|
# Run top methods
|
|
211
225
|
res = decouple(mat=[m, r, c], net=net, source=source, target=target, weight=weight,
|
|
212
|
-
min_n=min_n, verbose=verbose, use_raw=use_raw)
|
|
226
|
+
min_n=min_n, verbose=verbose, use_raw=use_raw, args=args)
|
|
213
227
|
|
|
214
228
|
# Exctract
|
|
215
229
|
estimate, pvals = res['consensus_estimate'], res['consensus_pvals']
|
|
@@ -5,75 +5,75 @@ Code to run the AUCell method.
|
|
|
5
5
|
|
|
6
6
|
import numpy as np
|
|
7
7
|
import pandas as pd
|
|
8
|
+
from scipy.sparse import csr_matrix
|
|
8
9
|
|
|
9
|
-
from
|
|
10
|
+
from tqdm.auto import tqdm
|
|
10
11
|
|
|
11
|
-
from .pre import extract, rename_net, filt_min_n
|
|
12
|
+
from .pre import extract, rename_net, filt_min_n, return_data, break_ties
|
|
12
13
|
|
|
13
|
-
from anndata import AnnData
|
|
14
14
|
import numba as nb
|
|
15
15
|
|
|
16
16
|
|
|
17
|
-
@nb.njit(nb.f4[
|
|
18
|
-
def nb_aucell(
|
|
17
|
+
@nb.njit(nb.f4[:](nb.f4[:], nb.i8[:], nb.i8[:], nb.i8[:], nb.i8, nb.i8), parallel=True, cache=True)
|
|
18
|
+
def nb_aucell(row, net, starts, offsets, n_up, n_fsets):
|
|
19
19
|
|
|
20
|
-
#
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
# Define starts to subset offsets
|
|
24
|
-
starts = np.zeros(n_fsets, dtype=nb.i8)
|
|
25
|
-
starts[1:] = np.cumsum(offsets)[:-1]
|
|
20
|
+
# Rank row
|
|
21
|
+
row = np.argsort(np.argsort(-row)) + 1
|
|
26
22
|
|
|
27
23
|
# Empty acts
|
|
28
|
-
|
|
24
|
+
es = np.zeros(n_fsets, dtype=nb.f4)
|
|
29
25
|
|
|
30
|
-
# For each
|
|
31
|
-
for
|
|
26
|
+
# For each feature set
|
|
27
|
+
for j in nb.prange(n_fsets):
|
|
32
28
|
|
|
33
|
-
# Extract
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
29
|
+
# Extract feature set
|
|
30
|
+
srt = starts[j]
|
|
31
|
+
off = offsets[j] + srt
|
|
32
|
+
fset = net[srt:off]
|
|
37
33
|
|
|
38
|
-
#
|
|
39
|
-
|
|
34
|
+
# Compute max AUC for fset
|
|
35
|
+
x_th = np.arange(1, stop=fset.shape[0]+1, dtype=nb.i8)
|
|
36
|
+
x_th = x_th[x_th < n_up]
|
|
37
|
+
max_auc = np.sum(np.diff(np.append(x_th, n_up)) * x_th)
|
|
40
38
|
|
|
41
|
-
#
|
|
42
|
-
|
|
39
|
+
# Compute AUC
|
|
40
|
+
x = row[fset]
|
|
41
|
+
x = np.sort(x[x < n_up])
|
|
42
|
+
y = np.arange(x.shape[0]) + 1
|
|
43
|
+
x = np.append(x, n_up)
|
|
43
44
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
off = offsets[j] + srt
|
|
47
|
-
fset = net[srt:off]
|
|
45
|
+
# Update acts matrix
|
|
46
|
+
es[j] = np.sum(np.diff(x) * y) / max_auc
|
|
48
47
|
|
|
49
|
-
|
|
50
|
-
x_th = np.arange(start=1, stop=fset.shape[0]+1, dtype=nb.i8)
|
|
51
|
-
x_th = x_th[x_th < n_up]
|
|
52
|
-
max_auc = np.sum(np.diff(np.append(x_th, n_up)) * x_th)
|
|
48
|
+
return es
|
|
53
49
|
|
|
54
|
-
# Compute AUC
|
|
55
|
-
x = row[fset]
|
|
56
|
-
x = np.sort(x[x < n_up])
|
|
57
|
-
y = np.arange(x.shape[0]) + 1
|
|
58
|
-
x = np.append(x, n_up)
|
|
59
50
|
|
|
60
|
-
|
|
61
|
-
acts[i, j] = np.sum(np.diff(x) * y)/max_auc
|
|
51
|
+
def aucell(mat, net, n_up, verbose):
|
|
62
52
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def aucell(mat, net, n_up):
|
|
53
|
+
# Get dims
|
|
54
|
+
n_samples = mat.shape[0]
|
|
55
|
+
n_fsets = net.shape[0]
|
|
67
56
|
|
|
68
57
|
# Flatten net and get offsets
|
|
69
58
|
offsets = net.apply(lambda x: len(x)).values.astype(np.int64)
|
|
70
59
|
net = np.concatenate(net.values)
|
|
71
60
|
|
|
72
|
-
#
|
|
73
|
-
|
|
74
|
-
|
|
61
|
+
# Define starts to subset offsets
|
|
62
|
+
starts = np.zeros(n_fsets, dtype=np.int64)
|
|
63
|
+
starts[1:] = np.cumsum(offsets)[:-1]
|
|
64
|
+
|
|
65
|
+
es = np.zeros((n_samples, n_fsets), dtype=np.float32)
|
|
66
|
+
for i in tqdm(range(mat.shape[0]), disable=not verbose):
|
|
67
|
+
|
|
68
|
+
if isinstance(mat, csr_matrix):
|
|
69
|
+
row = mat[i].toarray()[0]
|
|
70
|
+
else:
|
|
71
|
+
row = mat[i]
|
|
75
72
|
|
|
76
|
-
|
|
73
|
+
# Compute AUC per row
|
|
74
|
+
es[i] = nb_aucell(row, net, starts, offsets, n_up, n_fsets)
|
|
75
|
+
|
|
76
|
+
return es
|
|
77
77
|
|
|
78
78
|
|
|
79
79
|
def run_aucell(mat, net, source='source', target='target', n_up=None, min_n=5, seed=42, verbose=False, use_raw=True):
|
|
@@ -119,9 +119,10 @@ def run_aucell(mat, net, source='source', target='target', n_up=None, min_n=5, s
|
|
|
119
119
|
|
|
120
120
|
# Set n_up
|
|
121
121
|
if n_up is None:
|
|
122
|
-
n_up = np.ceil(0.05*len(c))
|
|
122
|
+
n_up = int(np.ceil(0.05*len(c)))
|
|
123
123
|
else:
|
|
124
|
-
n_up = np.ceil(n_up)
|
|
124
|
+
n_up = int(np.ceil(n_up))
|
|
125
|
+
n_up = np.min([n_up, c.size]) # Limit n_up to max features
|
|
125
126
|
if not 0 < n_up:
|
|
126
127
|
raise ValueError('n_up needs to be a value higher than 0.')
|
|
127
128
|
|
|
@@ -130,27 +131,19 @@ def run_aucell(mat, net, source='source', target='target', n_up=None, min_n=5, s
|
|
|
130
131
|
net = filt_min_n(c, net, min_n=min_n)
|
|
131
132
|
|
|
132
133
|
# Randomize feature order to break ties randomly
|
|
133
|
-
|
|
134
|
-
idx = np.arange(m.shape[1])
|
|
135
|
-
rng.shuffle(idx)
|
|
136
|
-
m, c = m[:, idx], c[idx]
|
|
134
|
+
m, c = break_ties(m, c, seed)
|
|
137
135
|
|
|
138
136
|
# Transform targets to indxs
|
|
139
137
|
table = {name: i for i, name in enumerate(c)}
|
|
140
138
|
net['target'] = [table[target] for target in net['target']]
|
|
141
|
-
net = net.groupby('source')['target'].apply(lambda x: np.array(x, dtype=np.int64))
|
|
139
|
+
net = net.groupby('source', observed=True)['target'].apply(lambda x: np.array(x, dtype=np.int64))
|
|
142
140
|
|
|
143
141
|
if verbose:
|
|
144
142
|
print('Running aucell on mat with {0} samples and {1} targets for {2} sources.'.format(m.shape[0], len(c), len(net)))
|
|
145
143
|
|
|
146
144
|
# Run AUCell
|
|
147
|
-
estimate = aucell(m, net, n_up)
|
|
145
|
+
estimate = aucell(m, net, n_up, verbose)
|
|
148
146
|
estimate = pd.DataFrame(estimate, index=r, columns=net.index)
|
|
149
147
|
estimate.name = 'aucell_estimate'
|
|
150
148
|
|
|
151
|
-
|
|
152
|
-
if isinstance(mat, AnnData):
|
|
153
|
-
# Update obsm AnnData object
|
|
154
|
-
mat.obsm[estimate.name] = estimate
|
|
155
|
-
else:
|
|
156
|
-
return estimate
|
|
149
|
+
return return_data(mat=mat, results=(estimate, ))
|