decoupler 2.1.6__tar.gz → 2.2.0__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-2.1.6 → decoupler-2.2.0}/.github/workflows/test.yaml +1 -1
- {decoupler-2.1.6 → decoupler-2.2.0}/.pre-commit-config.yaml +3 -3
- {decoupler-2.1.6 → decoupler-2.2.0}/CHANGELOG.md +6 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/PKG-INFO +18 -6
- {decoupler-2.1.6 → decoupler-2.2.0}/README.md +17 -5
- {decoupler-2.1.6 → decoupler-2.2.0}/pyproject.toml +8 -7
- decoupler-2.2.0/src/decoupler/_skills/__init__.py +6 -0
- decoupler-2.2.0/src/decoupler/_skills/data/SKILL.md +85 -0
- decoupler-2.2.0/src/decoupler/_skills/data/references/benchmarking.md +59 -0
- decoupler-2.2.0/src/decoupler/_skills/data/references/calling-convention.md +91 -0
- decoupler-2.2.0/src/decoupler/_skills/data/references/datasets.md +88 -0
- decoupler-2.2.0/src/decoupler/_skills/data/references/getting-started.md +82 -0
- decoupler-2.2.0/src/decoupler/_skills/data/references/io-and-outputs.md +80 -0
- decoupler-2.2.0/src/decoupler/_skills/data/references/methods.md +67 -0
- decoupler-2.2.0/src/decoupler/_skills/data/references/multi-method.md +72 -0
- decoupler-2.2.0/src/decoupler/_skills/data/references/preprocessing.md +66 -0
- decoupler-2.2.0/src/decoupler/_skills/data/references/priors.md +79 -0
- decoupler-2.2.0/src/decoupler/_skills/data/references/ranking-and-plotting.md +131 -0
- decoupler-2.2.0/src/decoupler/_skills/install.py +143 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/pp/test_anndata.py +3 -3
- decoupler-2.2.0/tests/test_install_skills.py +158 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/.codecov.yaml +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/.cruft.json +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/.editorconfig +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/.github/workflows/build.yaml +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/.github/workflows/notebooks.yaml +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/.github/workflows/release.yaml +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/.gitignore +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/.gitmodules +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/.readthedocs.yaml +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/.vscode/extensions.json +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/.vscode/launch.json +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/.vscode/settings.json +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/LICENSE +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/biome.jsonc +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/_static/.gitkeep +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/_static/css/custom.css +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/_static/images/logo.png +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/_static/images/logo.svg +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/_static/images/mlm.png +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/_static/images/ora.png +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/_static/images/ulm.png +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/_templates/.gitkeep +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/_templates/autosummary/class.rst +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/api/bm.md +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/api/ds.md +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/api/index.md +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/api/mt.md +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/api/op.md +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/api/pl.md +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/api/pp.md +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/api/tl.md +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/changelog.md +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/conf.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/extensions/typed_returns.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/index.md +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/references.bib +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/docs/references.md +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/_Method.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/_Plotter.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/__init__.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/_datatype.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/_docs.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/_download.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/_log.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/_odeps.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/__init__.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/_pp.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/_run.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/metric/_Metric.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/metric/__init__.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/metric/_auc.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/metric/_fscore.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/metric/_hmean.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/metric/_qrank.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/pl/__init__.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/pl/_auc.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/pl/_bar.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/pl/_format.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/pl/_fscore.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/pl/_qrank.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/pl/_summary.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/ds/__init__.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/ds/_bulk.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/ds/_scell.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/ds/_spatial.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/ds/_toy.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/ds/_utils.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/__init__.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_aucell.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_consensus.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_decouple.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_gsea.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_gsva.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_mdt.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_methods.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_mlm.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_ora.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_pv.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_query_set.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_run.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_udt.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_ulm.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_viper.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_waggr.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_zscore.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/op/__init__.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/op/_collectri.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/op/_dorothea.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/op/_dtype.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/op/_hallmark.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/op/_progeny.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/op/_resource.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/op/_translate.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/__init__.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_barplot.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_dotplot.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_filter_by_expr.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_filter_by_prop.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_filter_samples.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_leading_edge.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_network.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_obsbar.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_obsm.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_order.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_order_targets.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_source_targets.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_volcano.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pp/__init__.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pp/anndata.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pp/data.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pp/net.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/tl/__init__.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/tl/_rankby_group.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/tl/_rankby_obsm.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/tl/_rankby_order.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/bm/test_benchmark.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/bm/test_pl.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/conftest.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/ds/test_bulk.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/ds/test_scell.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/ds/test_spatial.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/ds/test_toy.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/ds/test_utils.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_adj.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_aucell.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_consensus.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_decouple.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_gsea.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_gsva.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_mdt.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_methods.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_mlm.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_ora.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_query_set.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_run.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_udt.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_ulm.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_viper.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_waggr.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_zscore.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/op/test_collectri.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/op/test_dorothea.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/op/test_dtype.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/op/test_hallmark.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/op/test_progeny.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/op/test_resource.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/op/test_translate.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_Plotter.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_barplot.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_dotplot.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_filter_by_expr.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_filter_by_prop.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_filter_samples.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_leading_edge.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_network.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_obsbar.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_obsm.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_order.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_order_targets.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_source_targets.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_volcano.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/pp/test_data.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/pp/test_net.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/test_download.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/test_version.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/tl/test_rankby_group.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/tl/test_rankby_obsm.py +0 -0
- {decoupler-2.1.6 → decoupler-2.2.0}/tests/tl/test_rankby_order.py +0 -0
|
@@ -87,7 +87,7 @@ jobs:
|
|
|
87
87
|
uvx hatch run ${{ matrix.env.name }}:cov-report # report visibly
|
|
88
88
|
uvx hatch run ${{ matrix.env.name }}:coverage xml # create report for upload
|
|
89
89
|
- name: Upload coverage
|
|
90
|
-
uses: codecov/codecov-action@
|
|
90
|
+
uses: codecov/codecov-action@v6
|
|
91
91
|
with:
|
|
92
92
|
fail_ci_if_error: true
|
|
93
93
|
use_oidc: true
|
|
@@ -7,16 +7,16 @@ default_stages:
|
|
|
7
7
|
minimum_pre_commit_version: 2.16.0
|
|
8
8
|
repos:
|
|
9
9
|
- repo: https://github.com/biomejs/pre-commit
|
|
10
|
-
rev: v2.
|
|
10
|
+
rev: v2.5.2
|
|
11
11
|
hooks:
|
|
12
12
|
- id: biome-format
|
|
13
13
|
exclude: ^\.cruft\.json$ # inconsistent indentation with cruft - file never to be modified manually.
|
|
14
14
|
- repo: https://github.com/tox-dev/pyproject-fmt
|
|
15
|
-
rev: v2.
|
|
15
|
+
rev: v2.25.1
|
|
16
16
|
hooks:
|
|
17
17
|
- id: pyproject-fmt
|
|
18
18
|
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
19
|
-
rev: v0.15.
|
|
19
|
+
rev: v0.15.20
|
|
20
20
|
hooks:
|
|
21
21
|
- id: ruff-check
|
|
22
22
|
types_or: [python, pyi, jupyter]
|
|
@@ -8,6 +8,12 @@ and this project adheres to [Semantic Versioning][].
|
|
|
8
8
|
[keep a changelog]: https://keepachangelog.com/en/1.0.0/
|
|
9
9
|
[semantic versioning]: https://semver.org/spec/v2.0.0.html
|
|
10
10
|
|
|
11
|
+
## 2.2.0
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
- Bundled a Claude Code [Agent Skill](https://docs.claude.com/en/docs/claude-code/skills) that teaches coding agents to use decoupler correctly (method selection, calling conventions, output locations, priors, datasets, and benchmarking)
|
|
15
|
+
- Added the `decoupler-install-skills` console script to install the skill into `~/.claude/skills/decoupler/` (use `--force` to refresh after upgrading, or `--print-path` to point `CLAUDE_SKILLS_PATH` at the bundled copy in place)
|
|
16
|
+
|
|
11
17
|
## 2.1.6
|
|
12
18
|
|
|
13
19
|
### Bugfixes
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: decoupler
|
|
3
|
-
Version: 2.
|
|
3
|
+
Version: 2.2.0
|
|
4
4
|
Summary: Python package to perform enrichment analysis from omics data.
|
|
5
5
|
Project-URL: Documentation, https://decoupler.readthedocs.io/
|
|
6
6
|
Project-URL: Homepage, https://github.com/scverse/decoupler
|
|
@@ -83,10 +83,8 @@ Description-Content-Type: text/markdown
|
|
|
83
83
|
[badge-adown]: https://static.pepy.tech/badge/decoupler
|
|
84
84
|
[badge-stars]: https://img.shields.io/github/stars/scverse/decoupler?style=flat&logo=github&color=yellow
|
|
85
85
|
|
|
86
|
-
`decoupler` is a python package containing different enrichment statistical
|
|
87
|
-
|
|
88
|
-
from omics data within a unified framework. This is its faster and memory efficient Python implementation,
|
|
89
|
-
a deprecated version in R can be found [here](https://github.com/saezlab/decoupler).
|
|
86
|
+
`decoupler` is a python package containing different enrichment statistical methods to extract biologically driven scores from omics data within a unified framework.
|
|
87
|
+
This is its faster and memory efficient Python implementation, a deprecated version in R can be found [here](https://github.com/saezlab/decoupler).
|
|
90
88
|
|
|
91
89
|
[//]: # (numfocus-fiscal-sponsor-attribution)
|
|
92
90
|
|
|
@@ -109,7 +107,7 @@ in particular, the [API documentation][].
|
|
|
109
107
|
|
|
110
108
|
## Installation
|
|
111
109
|
|
|
112
|
-
You need to have Python 3.
|
|
110
|
+
You need to have Python 3.11 or newer installed on your system.
|
|
113
111
|
If you don't have Python installed, we recommend installing [uv][].
|
|
114
112
|
|
|
115
113
|
There are several alternative options to install decoupler:
|
|
@@ -138,6 +136,20 @@ mamba create -n=dcp conda-forge::decoupler-py
|
|
|
138
136
|
pip install git+https://github.com/scverse/decoupler.git@main
|
|
139
137
|
```
|
|
140
138
|
|
|
139
|
+
## Claude Code Skill
|
|
140
|
+
|
|
141
|
+
decoupler ships an [Agent Skill](https://docs.claude.com/en/docs/claude-code/skills) for [Claude Code](https://claude.com/claude-code) that teaches the agent to use the library correctly. Install it once into your personal skills directory:
|
|
142
|
+
|
|
143
|
+
```bash
|
|
144
|
+
decoupler-install-skills
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
This copies the skill to `~/.claude/skills/decoupler/`, making it available in **every** project (re-run with `--force` after upgrading). Once installed, just ask Claude Code to do decoupler tasks ("find the most active TFs in this cell cluster", "score hallmark gene sets with ora", "build a consensus across methods") and the skill is consulted automatically. To avoid copying into your home directory, point Claude Code at the bundled copy instead:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
export CLAUDE_SKILLS_PATH="$(decoupler-install-skills --print-path)"
|
|
151
|
+
```
|
|
152
|
+
|
|
141
153
|
## Release notes
|
|
142
154
|
|
|
143
155
|
See the [changelog][].
|
|
@@ -26,10 +26,8 @@
|
|
|
26
26
|
[badge-adown]: https://static.pepy.tech/badge/decoupler
|
|
27
27
|
[badge-stars]: https://img.shields.io/github/stars/scverse/decoupler?style=flat&logo=github&color=yellow
|
|
28
28
|
|
|
29
|
-
`decoupler` is a python package containing different enrichment statistical
|
|
30
|
-
|
|
31
|
-
from omics data within a unified framework. This is its faster and memory efficient Python implementation,
|
|
32
|
-
a deprecated version in R can be found [here](https://github.com/saezlab/decoupler).
|
|
29
|
+
`decoupler` is a python package containing different enrichment statistical methods to extract biologically driven scores from omics data within a unified framework.
|
|
30
|
+
This is its faster and memory efficient Python implementation, a deprecated version in R can be found [here](https://github.com/saezlab/decoupler).
|
|
33
31
|
|
|
34
32
|
[//]: # (numfocus-fiscal-sponsor-attribution)
|
|
35
33
|
|
|
@@ -52,7 +50,7 @@ in particular, the [API documentation][].
|
|
|
52
50
|
|
|
53
51
|
## Installation
|
|
54
52
|
|
|
55
|
-
You need to have Python 3.
|
|
53
|
+
You need to have Python 3.11 or newer installed on your system.
|
|
56
54
|
If you don't have Python installed, we recommend installing [uv][].
|
|
57
55
|
|
|
58
56
|
There are several alternative options to install decoupler:
|
|
@@ -81,6 +79,20 @@ mamba create -n=dcp conda-forge::decoupler-py
|
|
|
81
79
|
pip install git+https://github.com/scverse/decoupler.git@main
|
|
82
80
|
```
|
|
83
81
|
|
|
82
|
+
## Claude Code Skill
|
|
83
|
+
|
|
84
|
+
decoupler ships an [Agent Skill](https://docs.claude.com/en/docs/claude-code/skills) for [Claude Code](https://claude.com/claude-code) that teaches the agent to use the library correctly. Install it once into your personal skills directory:
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
decoupler-install-skills
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
This copies the skill to `~/.claude/skills/decoupler/`, making it available in **every** project (re-run with `--force` after upgrading). Once installed, just ask Claude Code to do decoupler tasks ("find the most active TFs in this cell cluster", "score hallmark gene sets with ora", "build a consensus across methods") and the skill is consulted automatically. To avoid copying into your home directory, point Claude Code at the bundled copy instead:
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
export CLAUDE_SKILLS_PATH="$(decoupler-install-skills --print-path)"
|
|
94
|
+
```
|
|
95
|
+
|
|
84
96
|
## Release notes
|
|
85
97
|
|
|
86
98
|
See the [changelog][].
|
|
@@ -4,7 +4,7 @@ requires = [ "hatchling" ]
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "decoupler"
|
|
7
|
-
version = "2.
|
|
7
|
+
version = "2.2.0"
|
|
8
8
|
description = "Python package to perform enrichment analysis from omics data."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { file = "LICENSE" }
|
|
@@ -38,6 +38,7 @@ dependencies = [
|
|
|
38
38
|
urls.Documentation = "https://decoupler.readthedocs.io/"
|
|
39
39
|
urls.Homepage = "https://github.com/scverse/decoupler"
|
|
40
40
|
urls.Source = "https://github.com/scverse/decoupler"
|
|
41
|
+
scripts.decoupler-install-skills = "decoupler._skills.install:main"
|
|
41
42
|
|
|
42
43
|
[dependency-groups]
|
|
43
44
|
dev = [
|
|
@@ -84,11 +85,10 @@ full = [
|
|
|
84
85
|
[tool.hatch]
|
|
85
86
|
envs.default.installer = "uv"
|
|
86
87
|
envs.default.dependency-groups = [ "dev" ]
|
|
87
|
-
envs.docs.dependency-groups = [ "doc" ]
|
|
88
88
|
envs.docs.scripts.build = "sphinx-build -M html docs docs/_build -W {args}"
|
|
89
|
-
envs.docs.scripts.open = "python -m webbrowser -t docs/_build/html/index.html"
|
|
90
89
|
envs.docs.scripts.clean = "git clean -fdX -- {args:docs}"
|
|
91
|
-
envs.
|
|
90
|
+
envs.docs.scripts.open = "python -m webbrowser -t docs/_build/html/index.html"
|
|
91
|
+
envs.docs.dependency-groups = [ "doc" ]
|
|
92
92
|
envs.hatch-test.matrix = [
|
|
93
93
|
# Test the lowest and highest supported Python versions with normal deps
|
|
94
94
|
{ deps = [ "stable" ], python = [ "3.11", "3.14" ] },
|
|
@@ -98,8 +98,9 @@ envs.hatch-test.matrix = [
|
|
|
98
98
|
# If the matrix variable `deps` is set to "pre",
|
|
99
99
|
# set the environment variable `UV_PRERELEASE` to "allow".
|
|
100
100
|
envs.hatch-test.overrides.matrix.deps.env-vars = [
|
|
101
|
-
{
|
|
101
|
+
{ value = "allow", key = "UV_PRERELEASE", if = [ "pre" ] },
|
|
102
102
|
]
|
|
103
|
+
envs.hatch-test.dependency-groups = [ "dev", "test" ]
|
|
103
104
|
|
|
104
105
|
[tool.ruff]
|
|
105
106
|
line-length = 120
|
|
@@ -140,11 +141,11 @@ lint.per-file-ignores."tests/*" = [ "D" ]
|
|
|
140
141
|
lint.pydocstyle.convention = "numpy"
|
|
141
142
|
|
|
142
143
|
[tool.pytest]
|
|
143
|
-
strict = true
|
|
144
|
-
testpaths = [ "tests" ]
|
|
145
144
|
addopts = [
|
|
146
145
|
"--import-mode=importlib", # allow using test files with same name
|
|
147
146
|
]
|
|
147
|
+
strict = true
|
|
148
|
+
testpaths = [ "tests" ]
|
|
148
149
|
|
|
149
150
|
[tool.coverage]
|
|
150
151
|
run.omit = [
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: decoupler
|
|
3
|
+
description: Use for any task involving the decoupler library — inferring biological activity/enrichment scores from omics data (bulk, single-cell, spatial). Triggers on estimating transcription factor (TF) activity, pathway activity, or gene-set enrichment from an AnnData/DataFrame; running ulm, mlm, ora, gsea, gsva, aucell, viper, zscore, waggr, mdt, udt; multi-method consensus; fetching prior knowledge (CollecTRI, DoRothEA, PROGENy, MSigDB hallmarks, OmniPath); pseudobulk and expression filtering; using bundled example datasets (pbmc3k, covid5k, erygast1k, hsctgfb, msvisium, knocktf, toy) and whether they are raw counts or normalized; ranking/plotting activity scores; or benchmarking methods against ground truth. This is a router skill — read the relevant file under references/ before writing decoupler code, because outputs land in different places and several defaults are non-obvious.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# decoupler
|
|
7
|
+
|
|
8
|
+
`decoupler` estimates biological activities (transcription factors, pathways, gene
|
|
9
|
+
sets) from omics data. You give it a **data matrix** (observations × features, e.g.
|
|
10
|
+
cells × genes) and a **prior-knowledge network** (which features belong to which
|
|
11
|
+
biological program), and it returns an **enrichment score per observation per
|
|
12
|
+
program** — all methods sharing one unified interface. Part of scverse; works
|
|
13
|
+
directly on `AnnData`, `pandas.DataFrame`, or raw matrices.
|
|
14
|
+
|
|
15
|
+
This skill is a **router**. Each topic below has a detailed reference file with exact
|
|
16
|
+
signatures and footguns. **Read the relevant reference before writing code** — do not
|
|
17
|
+
rely on memory of the API, because results are written to different places depending
|
|
18
|
+
on the input type and several methods have non-obvious defaults.
|
|
19
|
+
|
|
20
|
+
## Two cross-cutting concepts (read these first if unsure)
|
|
21
|
+
|
|
22
|
+
- **[The unified method call](references/calling-convention.md)** — every method is
|
|
23
|
+
called the same way: `dc.mt.<method>(data, net, tmin=5, ...)`. Covers the accepted
|
|
24
|
+
input types (AnnData / DataFrame / `[matrix, obs, var]` **list**), the shared
|
|
25
|
+
arguments (`tmin`, `raw`, `layer`, `empty`, `bsize`), and the big footguns: input
|
|
26
|
+
must be **normalized (e.g. log1p), not raw counts**, and `net` must be a
|
|
27
|
+
**long-format** `source`/`target`/`weight` table.
|
|
28
|
+
|
|
29
|
+
- **[Where the results go](references/io-and-outputs.md)** — the return type depends
|
|
30
|
+
on the input type. **AnnData → written in place** into `.obsm["score_<method>"]`
|
|
31
|
+
(and `.obsm["padj_<method>"]` if the method tests), returns `None`. **DataFrame /
|
|
32
|
+
list → returns an `(es, pv)` tuple** (`pv` is `None` for non-testing methods). Read
|
|
33
|
+
scores back out of an AnnData with `dc.pp.get_obsm`. **This is the #1 thing agents
|
|
34
|
+
get wrong.**
|
|
35
|
+
|
|
36
|
+
## Task → reference file
|
|
37
|
+
|
|
38
|
+
| If the task is… | Read |
|
|
39
|
+
|---|---|
|
|
40
|
+
| **starting from scratch** — set up an end-to-end run (load data → get a net → score → rank → plot) | [references/getting-started.md](references/getting-started.md) |
|
|
41
|
+
| how to **call a method**, what data/net formats are accepted, `tmin`/`raw`/`layer` semantics | [references/calling-convention.md](references/calling-convention.md) |
|
|
42
|
+
| **where scores land** and how to read them back (`.obsm` vs `(es, pv)` tuple, `get_obsm`) | [references/io-and-outputs.md](references/io-and-outputs.md) |
|
|
43
|
+
| **choosing and configuring a method** — ulm/mlm/ora/gsea/gsva/aucell/viper/zscore/waggr/mdt/udt + their kwargs | [references/methods.md](references/methods.md) |
|
|
44
|
+
| getting **prior knowledge** — TF regulons (CollecTRI, DoRothEA), pathways (PROGENy), gene sets (MSigDB hallmarks), OmniPath, `.gmt`, organism translation | [references/priors.md](references/priors.md) |
|
|
45
|
+
| **preprocessing** — pseudobulk from single cell, expression/sample filtering, layers, spatial kNN | [references/preprocessing.md](references/preprocessing.md) |
|
|
46
|
+
| running **many methods at once** and combining them into a **consensus** | [references/multi-method.md](references/multi-method.md) |
|
|
47
|
+
| **ranking** activity scores by group/ordering and **plotting** them (barplot, dotplot, volcano, network) or overlaying them on a **UMAP / spatial H&E** via scanpy | [references/ranking-and-plotting.md](references/ranking-and-plotting.md) |
|
|
48
|
+
| **benchmarking** methods/nets against a perturbation ground truth | [references/benchmarking.md](references/benchmarking.md) |
|
|
49
|
+
| using a **bundled example dataset** (`dc.ds.*`) — and whether its `.X` is raw counts or already normalized | [references/datasets.md](references/datasets.md) |
|
|
50
|
+
|
|
51
|
+
## Quick orientation (submodule map)
|
|
52
|
+
|
|
53
|
+
decoupler exposes everything through namespaced submodules — canonical import is
|
|
54
|
+
`import decoupler as dc`:
|
|
55
|
+
|
|
56
|
+
- `dc.mt` — **methods**: the enrichment/activity algorithms (`ulm`, `mlm`, `ora`,
|
|
57
|
+
`gsea`, `gsva`, `aucell`, `viper`, `zscore`, `waggr`, `mdt`, `udt`) plus
|
|
58
|
+
`dc.mt.decouple` (run several) and `dc.mt.consensus`. `dc.mt.show()` lists them.
|
|
59
|
+
- `dc.op` — **prior knowledge** (OmniPath): `collectri`, `dorothea`, `progeny`,
|
|
60
|
+
`hallmark`, `resource`, `translate`.
|
|
61
|
+
- `dc.pp` — **preprocessing**: `pseudobulk`, `filter_by_expr`, `filter_by_prop`,
|
|
62
|
+
`filter_samples`, `get_obsm`, `extract`, `swap_layer`, `knn`, `read_gmt`.
|
|
63
|
+
- `dc.ds` — **datasets**: `toy` (used in every example: `adata, net = dc.ds.toy()`),
|
|
64
|
+
`pbmc3k`, `covid5k`, and other real examples. **They differ in normalization state**
|
|
65
|
+
(some raw counts, some already log-normalized) — see
|
|
66
|
+
[datasets.md](references/datasets.md) before scoring one.
|
|
67
|
+
- `dc.tl` — **tools**: `rankby_group`, `rankby_obsm`, `rankby_order`.
|
|
68
|
+
- `dc.pl` — **plotting**: `barplot`, `dotplot`, `volcano`, `network`, `obsm`, etc.
|
|
69
|
+
- `dc.bm` — **benchmarking**: `benchmark`, `metric`, `pl`.
|
|
70
|
+
|
|
71
|
+
## Conventions used throughout
|
|
72
|
+
|
|
73
|
+
- **Data** = observations × features (cells/samples × genes), **normalized** (log1p),
|
|
74
|
+
not raw counts. **Net** = long-format DataFrame: `source` (program), `target`
|
|
75
|
+
(feature), optional signed `weight`.
|
|
76
|
+
- Output score matrices are observations × sources. AnnData results live in `.obsm`
|
|
77
|
+
under `score_<method>` / `padj_<method>`.
|
|
78
|
+
- `tmin` (default 5) silently drops sources with fewer than `tmin` targets present in
|
|
79
|
+
the data — lower it for small/toy nets (examples use `tmin=3`).
|
|
80
|
+
- `verbose=True` on any method prints the pruning/run log — use it to see how many
|
|
81
|
+
sources survived `tmin`.
|
|
82
|
+
- **Plotting**: use `dc.pl.*` for summary plots and scanpy `sc.pl.umap` / `sc.pl.spatial`
|
|
83
|
+
(on a `dc.pp.get_obsm` score AnnData) for embedding/tissue overlays. Never reimplement
|
|
84
|
+
a plot from matplotlib primitives — see
|
|
85
|
+
[ranking-and-plotting.md](references/ranking-and-plotting.md).
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# Benchmarking methods and nets
|
|
2
|
+
|
|
3
|
+
`dc.bm` evaluates how well a method + net recover a known ground truth — typically a
|
|
4
|
+
perturbation dataset where you know which program was up/down in each sample. Use it
|
|
5
|
+
to **choose a method** or **validate a net**, not for routine scoring.
|
|
6
|
+
|
|
7
|
+
## `dc.bm.benchmark`
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
dc.bm.benchmark(
|
|
11
|
+
adata, # AnnData with a perturbation ground truth in .obs
|
|
12
|
+
net, # a net, or a dict of {name: net} to compare several
|
|
13
|
+
metrics=None, # e.g. ["auroc", "auprc"] (None = defaults)
|
|
14
|
+
groupby=None, # obs column(s) to stratify the evaluation
|
|
15
|
+
runby="expr", # evaluate per-observation ("expr") or per-source
|
|
16
|
+
sfilt=False, # filter sources to those with a ground-truth label
|
|
17
|
+
thr=0.1, emin=5,
|
|
18
|
+
kws_decouple=None, # kwargs forwarded to dc.mt.decouple (methods, args, tmin, ...)
|
|
19
|
+
verbose=False,
|
|
20
|
+
)
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
- Internally runs `dc.mt.decouple`, so pass method selection and per-method args via
|
|
24
|
+
`kws_decouple` (e.g. `kws_decouple={"methods": ["ulm", "mlm"], "tmin": 3}`).
|
|
25
|
+
- Pass a **dict of nets** to benchmark several priors head to head.
|
|
26
|
+
- The ground truth (which source is perturbed, and its sign) must be encoded in
|
|
27
|
+
`adata.obs` — see the decoupler benchmarking tutorial for the expected columns.
|
|
28
|
+
|
|
29
|
+
## Metrics and plots
|
|
30
|
+
|
|
31
|
+
- `dc.bm.metric` — the scoring functions: `auc`, `fscore`, `qrank`, `hmean`,
|
|
32
|
+
`dict_metric`.
|
|
33
|
+
- `dc.bm.pl` — plots of benchmark results: `auc`, `bar`, `fscore`, `qrank`, `summary`.
|
|
34
|
+
|
|
35
|
+
```python
|
|
36
|
+
res = dc.bm.benchmark(adata, {"collectri": net_a, "dorothea": net_b},
|
|
37
|
+
kws_decouple={"methods": ["ulm", "mlm"]})
|
|
38
|
+
dc.bm.pl.summary(res) # compare methods × nets
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## When to use
|
|
42
|
+
|
|
43
|
+
- Deciding **which method** to trust for your data/organism.
|
|
44
|
+
- Comparing **candidate nets** (e.g. CollecTRI vs DoRothEA levels).
|
|
45
|
+
- Sanity-checking a **custom net** against a perturbation benchmark
|
|
46
|
+
(`dc.ds.knocktf` and similar provide ground-truth datasets).
|
|
47
|
+
|
|
48
|
+
## Footguns
|
|
49
|
+
|
|
50
|
+
- Benchmarking is only meaningful with a **real ground truth** — a toy net won't tell
|
|
51
|
+
you anything.
|
|
52
|
+
- It re-runs scoring internally; keep `kws_decouple` consistent with how you intend to
|
|
53
|
+
score for real, or the comparison won't transfer.
|
|
54
|
+
|
|
55
|
+
## Related references
|
|
56
|
+
|
|
57
|
+
[multi-method.md](multi-method.md) (`decouple`, which `benchmark` wraps),
|
|
58
|
+
[methods.md](methods.md) (candidate methods),
|
|
59
|
+
[priors.md](priors.md) (candidate nets).
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
# The unified method call
|
|
2
|
+
|
|
3
|
+
Every enrichment method in `dc.mt` is a callable object with the **same signature**.
|
|
4
|
+
Learn it once and it applies to `ulm`, `mlm`, `ora`, `gsea`, `gsva`, `aucell`,
|
|
5
|
+
`viper`, `zscore`, `waggr`, `mdt`, `udt` (and `dc.mt.decouple`).
|
|
6
|
+
|
|
7
|
+
```python
|
|
8
|
+
import decoupler as dc
|
|
9
|
+
|
|
10
|
+
adata, net = dc.ds.toy() # AnnData (obs × var) + long-format net
|
|
11
|
+
dc.mt.ulm(adata, net, tmin=3) # writes adata.obsm["score_ulm"], ["padj_ulm"]
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
## Shared signature
|
|
15
|
+
|
|
16
|
+
```python
|
|
17
|
+
dc.mt.<method>(
|
|
18
|
+
data, # AnnData | pandas.DataFrame | [matrix, obs_names, var_names]
|
|
19
|
+
net, # long-format DataFrame: source, target, [weight]
|
|
20
|
+
tmin=5, # drop sources with < tmin targets present in the data
|
|
21
|
+
raw=False, # use adata.raw instead of adata.X
|
|
22
|
+
layer=None, # use adata.layers[layer] instead of adata.X (passed via kwargs)
|
|
23
|
+
empty=True, # drop all-zero observations/features before scoring
|
|
24
|
+
bsize=250_000, # batch size (rows) for sparse / backed matrices
|
|
25
|
+
verbose=False,
|
|
26
|
+
**kwargs, # method-specific args — see references/methods.md
|
|
27
|
+
)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
`layer=` is accepted even though it is not in the explicit signature — it is forwarded
|
|
31
|
+
through `**kwargs` to the runner. Use `layer=` **or** `raw=`, not both.
|
|
32
|
+
|
|
33
|
+
## Accepted input types (`data`)
|
|
34
|
+
|
|
35
|
+
| Form | What it is | Returns |
|
|
36
|
+
|---|---|---|
|
|
37
|
+
| `AnnData` | scored on `.X` (or `.raw`/`layer`) | **`None`** — results written to `.obsm` in place |
|
|
38
|
+
| `pandas.DataFrame` | observations (rows) × features (cols) | `(es, pv)` tuple of DataFrames |
|
|
39
|
+
| `list` `[matrix, obs_names, var_names]` | numpy/sparse matrix + name arrays | `(es, pv)` tuple of DataFrames |
|
|
40
|
+
|
|
41
|
+
See [io-and-outputs.md](io-and-outputs.md) for the return details.
|
|
42
|
+
|
|
43
|
+
### Footgun — the matrix form must be a `list`, not a `tuple`
|
|
44
|
+
|
|
45
|
+
```python
|
|
46
|
+
# WRONG — a tuple raises "mat must be a list of [matrix, samples, features]"
|
|
47
|
+
es, pv = dc.mt.ulm((X, obs, var), net)
|
|
48
|
+
|
|
49
|
+
# RIGHT — wrap it in a list
|
|
50
|
+
es, pv = dc.mt.ulm([X, obs, var], net)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
## The three footguns that silently give wrong results
|
|
54
|
+
|
|
55
|
+
1. **Input must be normalized, not raw counts.** decoupler expects
|
|
56
|
+
log-normalized expression — the same matrix you would use for differential
|
|
57
|
+
expression. **When normalizing, use `sc.pp.normalize_total(adata, target_sum=1e4)`**
|
|
58
|
+
followed by `sc.pp.log1p(adata)`. Passing raw counts runs without error but produces
|
|
59
|
+
meaningless scores. If your normalized data is in a layer, pass
|
|
60
|
+
`layer="lognorm"`; if in `.raw`, pass `raw=True`. **Check before normalizing:** if
|
|
61
|
+
`.X` is integer-valued with a large max it is raw counts; if it is small floats
|
|
62
|
+
(often with `adata.uns["log1p"]`) it is already normalized — do not normalize twice.
|
|
63
|
+
The bundled datasets differ; see [datasets.md](datasets.md) (e.g. `pbmc3k` is already
|
|
64
|
+
log-normalized, `covid5k` is raw counts).
|
|
65
|
+
|
|
66
|
+
2. **`net` must be long-format** with columns `source`, `target`, and (for weighted
|
|
67
|
+
methods) `weight` — one row per (program, feature) edge. A wide/matrix net or wrong
|
|
68
|
+
column names will fail or misbehave. See [priors.md](priors.md).
|
|
69
|
+
|
|
70
|
+
3. **`tmin` silently prunes.** Sources with fewer than `tmin` (default 5) targets
|
|
71
|
+
present in `data` are dropped *before* scoring — they simply won't appear in the
|
|
72
|
+
output. On small or toy nets this can drop everything; the examples use `tmin=3`.
|
|
73
|
+
Run with `verbose=True` to see `<method> - X sources with < tmin targets` and how
|
|
74
|
+
many survived.
|
|
75
|
+
|
|
76
|
+
## Listing and introspecting methods
|
|
77
|
+
|
|
78
|
+
```python
|
|
79
|
+
dc.mt.show() # DataFrame: name, desc, stype, weight, test, limits, reference
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
- `weight` — whether the method uses signed edge weights (`True` for ulm/mlm/viper/…).
|
|
83
|
+
- `test` — whether it produces p-values (`padj`). `False` for aucell/gsva/mdt/udt.
|
|
84
|
+
- `stype` / `limits` — value type and output range (e.g. aucell `(0, 1)`).
|
|
85
|
+
|
|
86
|
+
## Related references
|
|
87
|
+
|
|
88
|
+
[io-and-outputs.md](io-and-outputs.md) (return types, reading `.obsm` back),
|
|
89
|
+
[methods.md](methods.md) (per-method kwargs and how to choose one),
|
|
90
|
+
[priors.md](priors.md) (building/fetching `net`),
|
|
91
|
+
[preprocessing.md](preprocessing.md) (getting a normalized matrix / layers).
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Bundled example datasets (`dc.ds`)
|
|
2
|
+
|
|
3
|
+
decoupler ships loaders for a toy dataset and several real ones. **They are not all in
|
|
4
|
+
the same state** — some `.X` are raw counts, some are already log-normalized, one is a
|
|
5
|
+
log2FC contrast statistic. Since methods expect **normalized** input (see
|
|
6
|
+
[calling-convention.md](calling-convention.md)), you must know which is which or you
|
|
7
|
+
will either skip a needed normalization or re-normalize already-normalized data.
|
|
8
|
+
|
|
9
|
+
## Rule: inspect `.X` before assuming counts
|
|
10
|
+
|
|
11
|
+
```python
|
|
12
|
+
import numpy as np, scipy.sparse as sps
|
|
13
|
+
X = adata.X.toarray() if sps.issparse(adata.X) else np.asarray(adata.X)
|
|
14
|
+
X.max(), np.allclose(X[:50], np.round(X[:50])), "log1p" in adata.uns
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
- **Integer-valued and large max (hundreds–millions)** → raw counts → normalize first.
|
|
18
|
+
- **Float, small max (roughly ≤ tens), often `adata.uns["log1p"]` present** → already
|
|
19
|
+
log-normalized → **score directly, do not normalize again**.
|
|
20
|
+
- **Signed values (negatives)** → a contrast statistic (e.g. log2FC), not expression →
|
|
21
|
+
score directly.
|
|
22
|
+
|
|
23
|
+
## The datasets
|
|
24
|
+
|
|
25
|
+
| Loader | What it is | `.X` state | Before scoring | Organism |
|
|
26
|
+
|---|---|---|---|---|
|
|
27
|
+
| `dc.ds.toy()` | synthetic AnnData **+ matching net** | synthetic continuous | score directly (`tmin=3`) | — |
|
|
28
|
+
| `dc.ds.toy_bench()` | toy + benchmark ground truth | synthetic continuous | feed to `dc.bm` | — |
|
|
29
|
+
| `dc.ds.pbmc3k()` | 10x PBMCs (~2.6k cells) | **log-normalized** (max ~6) | **score directly** | human |
|
|
30
|
+
| `dc.ds.erygast1k()` | mouse erythroid gastrulation (~800 cells) | **log-normalized** (`uns['log1p']`) | score directly | **mouse** |
|
|
31
|
+
| `dc.ds.covid5k()` | COVID-19 PBMCs (~5k cells) | **raw counts** (max ~1e4) | **normalize + log1p** | human |
|
|
32
|
+
| `dc.ds.hsctgfb()` | bulk RNA-seq, 6 HSC samples | **raw counts** | **filter + normalize** (bulk) | human |
|
|
33
|
+
| `dc.ds.msvisium()` | Visium MS brain slide (spatial) | **raw counts** | **normalize** | human |
|
|
34
|
+
| `dc.ds.knocktf()` | KnockTF TF-perturbation contrasts | **log2FC** (−20…20) | score directly (benchmark) | human |
|
|
35
|
+
|
|
36
|
+
### Ready to score directly (do NOT normalize)
|
|
37
|
+
|
|
38
|
+
```python
|
|
39
|
+
adata = dc.ds.pbmc3k() # already log-normalized
|
|
40
|
+
net = dc.op.collectri(organism="human")
|
|
41
|
+
dc.mt.ulm(adata, net) # -> adata.obsm["score_ulm"], ["padj_ulm"]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
- `erygast1k` is the same, but **mouse** — fetch a mouse net (`organism="mouse"`) or
|
|
45
|
+
translate a human one (`dc.op.translate`, see [priors.md](priors.md)). Its `obs` has
|
|
46
|
+
`celltype`, `stage`.
|
|
47
|
+
- `pbmc3k.obs` has `celltype` and `leiden`; `obsm` has PCA/UMAP/tSNE already.
|
|
48
|
+
|
|
49
|
+
### Raw counts → normalize first
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
import scanpy as sc
|
|
53
|
+
adata = dc.ds.covid5k() # raw integer counts
|
|
54
|
+
sc.pp.normalize_total(adata, target_sum=1e4)
|
|
55
|
+
sc.pp.log1p(adata)
|
|
56
|
+
dc.mt.ulm(adata, dc.op.collectri())
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
- `covid5k.obs`: `individual`, `sex`, `disease`, `celltype`.
|
|
60
|
+
- `hsctgfb` is **bulk** (6 samples, `obs`: `condition`, `sample_id`) — filter lowly
|
|
61
|
+
expressed genes with `dc.pp.filter_by_expr` then normalize; a natural fit for a
|
|
62
|
+
bulk/DE + activity workflow ([preprocessing.md](preprocessing.md)).
|
|
63
|
+
- `msvisium` is **spatial** — normalize, then optionally build a neighbor graph with
|
|
64
|
+
`dc.pp.knn(adata, key="spatial")`. It carries `obsm["spatial"]`, `uns["spatial"]`
|
|
65
|
+
(H&E images), and `obs["niches"]`. To plot activity on the H&E, use `dc.pp.get_obsm` +
|
|
66
|
+
`sc.pl.spatial` (see [ranking-and-plotting.md](ranking-and-plotting.md)).
|
|
67
|
+
|
|
68
|
+
### Benchmark inputs (not for routine scoring)
|
|
69
|
+
|
|
70
|
+
- `dc.ds.knocktf()` — `.X` is already log2FCs; `obs["source"]` is the perturbed TF and
|
|
71
|
+
`obs["logFC"]` its effect. It is the ground truth for `dc.bm.benchmark`, not a matrix
|
|
72
|
+
you normalize. `thr_fc=-1` (default) keeps clearly down-regulated perturbations.
|
|
73
|
+
- `dc.ds.toy_bench()` — toy data with ground truth in `obs["source"]` / `class` /
|
|
74
|
+
`type_p` for exercising the benchmark pipeline ([benchmarking.md](benchmarking.md)).
|
|
75
|
+
|
|
76
|
+
## Gene identifiers
|
|
77
|
+
|
|
78
|
+
Real datasets use gene **symbols** in `var_names` (matching the OmniPath priors). If you
|
|
79
|
+
bring data with Ensembl IDs, convert with `dc.ds.ensmbl_to_symbol(...)` so `net`
|
|
80
|
+
`target`s line up — mismatched namespaces get silently pruned by `tmin`
|
|
81
|
+
(see the identifier footgun in [priors.md](priors.md)).
|
|
82
|
+
|
|
83
|
+
## Related references
|
|
84
|
+
|
|
85
|
+
[calling-convention.md](calling-convention.md) (normalized-input requirement),
|
|
86
|
+
[preprocessing.md](preprocessing.md) (normalize / filter / pseudobulk / spatial kNN),
|
|
87
|
+
[priors.md](priors.md) (matching organism and gene identifiers),
|
|
88
|
+
[benchmarking.md](benchmarking.md) (`knocktf`, `toy_bench`).
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Getting started (end-to-end)
|
|
2
|
+
|
|
3
|
+
A complete decoupler run has four steps: **get a normalized data matrix**, **get a
|
|
4
|
+
prior net**, **score**, then **inspect/rank/plot**. Below are the two most common
|
|
5
|
+
end-to-end shapes.
|
|
6
|
+
|
|
7
|
+
## Minimal, self-contained (toy data)
|
|
8
|
+
|
|
9
|
+
```python
|
|
10
|
+
import decoupler as dc
|
|
11
|
+
|
|
12
|
+
# 1. Data (obs × var, normalized) + 2. a prior net (source/target/weight)
|
|
13
|
+
adata, net = dc.ds.toy()
|
|
14
|
+
|
|
15
|
+
# 3. Score — results written into adata.obsm in place
|
|
16
|
+
dc.mt.ulm(adata, net, tmin=3)
|
|
17
|
+
|
|
18
|
+
# 4. Inspect: scores + adjusted p-values, both obs × sources
|
|
19
|
+
adata.obsm["score_ulm"]
|
|
20
|
+
adata.obsm["padj_ulm"]
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
`dc.ds.toy()` returns a small AnnData and a matching weighted net — use it for any
|
|
24
|
+
quick check or when reproducing behavior.
|
|
25
|
+
|
|
26
|
+
## Single-cell TF activity (realistic shape)
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
import scanpy as sc
|
|
30
|
+
import decoupler as dc
|
|
31
|
+
|
|
32
|
+
# adata: raw counts in a single-cell AnnData
|
|
33
|
+
sc.pp.normalize_total(adata, target_sum=1e4) # when normalizing, use target_sum=1e4
|
|
34
|
+
sc.pp.log1p(adata) # decoupler needs normalized input, not counts
|
|
35
|
+
# NOTE: only normalize raw counts. Data that is already log-normalized (e.g.
|
|
36
|
+
# dc.ds.pbmc3k()) must NOT be normalized again — see references/datasets.md.
|
|
37
|
+
|
|
38
|
+
net = dc.op.collectri(organism="human") # signed TF regulons
|
|
39
|
+
|
|
40
|
+
dc.mt.ulm(adata, net) # -> adata.obsm["score_ulm"], ["padj_ulm"]
|
|
41
|
+
|
|
42
|
+
# Turn scores into an AnnData for downstream scanpy/plotting
|
|
43
|
+
acts = dc.pp.get_obsm(adata, key="score_ulm") # obs × TFs
|
|
44
|
+
|
|
45
|
+
# Which TFs are most active per cell type?
|
|
46
|
+
df = dc.tl.rankby_group(acts, groupby="cell_type")
|
|
47
|
+
# barplot/dotplot take DataFrames (not `acts`) — see ranking-and-plotting.md
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Pathway activity or gene-set enrichment
|
|
51
|
+
|
|
52
|
+
Swap the net (and, for unweighted gene sets, the method):
|
|
53
|
+
|
|
54
|
+
```python
|
|
55
|
+
# Pathways (weighted) — ulm is fine
|
|
56
|
+
prog = dc.op.progeny(organism="human", top=500)
|
|
57
|
+
dc.mt.ulm(adata, prog) # adata.obsm["score_ulm"] = pathway activities
|
|
58
|
+
|
|
59
|
+
# Hallmark gene sets (unweighted) — use a gene-set method
|
|
60
|
+
hall = dc.op.hallmark(organism="human")
|
|
61
|
+
dc.mt.ora(adata, hall) # adata.obsm["score_ora"], ["padj_ora"]
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Bulk / pseudobulk
|
|
65
|
+
|
|
66
|
+
For bulk RNA-seq or pseudobulk from single cell, aggregate and filter first (see
|
|
67
|
+
[preprocessing.md](preprocessing.md)), then score exactly the same way:
|
|
68
|
+
|
|
69
|
+
```python
|
|
70
|
+
pdata = dc.pp.pseudobulk(adata, sample_col="sample", groups_col="cell_type")
|
|
71
|
+
dc.pp.filter_by_expr(pdata) # drop lowly-expressed genes
|
|
72
|
+
# ... normalize pdata (e.g. CPM + log1p) ...
|
|
73
|
+
dc.mt.ulm(pdata, net)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Where to go next
|
|
77
|
+
|
|
78
|
+
- Method choice and kwargs → [methods.md](methods.md)
|
|
79
|
+
- Getting/formatting the net → [priors.md](priors.md)
|
|
80
|
+
- Return types and reading scores back → [io-and-outputs.md](io-and-outputs.md)
|
|
81
|
+
- Running many methods + consensus → [multi-method.md](multi-method.md)
|
|
82
|
+
- Ranking + plotting → [ranking-and-plotting.md](ranking-and-plotting.md)
|