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.
Files changed (192) hide show
  1. {decoupler-2.1.6 → decoupler-2.2.0}/.github/workflows/test.yaml +1 -1
  2. {decoupler-2.1.6 → decoupler-2.2.0}/.pre-commit-config.yaml +3 -3
  3. {decoupler-2.1.6 → decoupler-2.2.0}/CHANGELOG.md +6 -0
  4. {decoupler-2.1.6 → decoupler-2.2.0}/PKG-INFO +18 -6
  5. {decoupler-2.1.6 → decoupler-2.2.0}/README.md +17 -5
  6. {decoupler-2.1.6 → decoupler-2.2.0}/pyproject.toml +8 -7
  7. decoupler-2.2.0/src/decoupler/_skills/__init__.py +6 -0
  8. decoupler-2.2.0/src/decoupler/_skills/data/SKILL.md +85 -0
  9. decoupler-2.2.0/src/decoupler/_skills/data/references/benchmarking.md +59 -0
  10. decoupler-2.2.0/src/decoupler/_skills/data/references/calling-convention.md +91 -0
  11. decoupler-2.2.0/src/decoupler/_skills/data/references/datasets.md +88 -0
  12. decoupler-2.2.0/src/decoupler/_skills/data/references/getting-started.md +82 -0
  13. decoupler-2.2.0/src/decoupler/_skills/data/references/io-and-outputs.md +80 -0
  14. decoupler-2.2.0/src/decoupler/_skills/data/references/methods.md +67 -0
  15. decoupler-2.2.0/src/decoupler/_skills/data/references/multi-method.md +72 -0
  16. decoupler-2.2.0/src/decoupler/_skills/data/references/preprocessing.md +66 -0
  17. decoupler-2.2.0/src/decoupler/_skills/data/references/priors.md +79 -0
  18. decoupler-2.2.0/src/decoupler/_skills/data/references/ranking-and-plotting.md +131 -0
  19. decoupler-2.2.0/src/decoupler/_skills/install.py +143 -0
  20. {decoupler-2.1.6 → decoupler-2.2.0}/tests/pp/test_anndata.py +3 -3
  21. decoupler-2.2.0/tests/test_install_skills.py +158 -0
  22. {decoupler-2.1.6 → decoupler-2.2.0}/.codecov.yaml +0 -0
  23. {decoupler-2.1.6 → decoupler-2.2.0}/.cruft.json +0 -0
  24. {decoupler-2.1.6 → decoupler-2.2.0}/.editorconfig +0 -0
  25. {decoupler-2.1.6 → decoupler-2.2.0}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  26. {decoupler-2.1.6 → decoupler-2.2.0}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  27. {decoupler-2.1.6 → decoupler-2.2.0}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  28. {decoupler-2.1.6 → decoupler-2.2.0}/.github/workflows/build.yaml +0 -0
  29. {decoupler-2.1.6 → decoupler-2.2.0}/.github/workflows/notebooks.yaml +0 -0
  30. {decoupler-2.1.6 → decoupler-2.2.0}/.github/workflows/release.yaml +0 -0
  31. {decoupler-2.1.6 → decoupler-2.2.0}/.gitignore +0 -0
  32. {decoupler-2.1.6 → decoupler-2.2.0}/.gitmodules +0 -0
  33. {decoupler-2.1.6 → decoupler-2.2.0}/.readthedocs.yaml +0 -0
  34. {decoupler-2.1.6 → decoupler-2.2.0}/.vscode/extensions.json +0 -0
  35. {decoupler-2.1.6 → decoupler-2.2.0}/.vscode/launch.json +0 -0
  36. {decoupler-2.1.6 → decoupler-2.2.0}/.vscode/settings.json +0 -0
  37. {decoupler-2.1.6 → decoupler-2.2.0}/LICENSE +0 -0
  38. {decoupler-2.1.6 → decoupler-2.2.0}/biome.jsonc +0 -0
  39. {decoupler-2.1.6 → decoupler-2.2.0}/docs/_static/.gitkeep +0 -0
  40. {decoupler-2.1.6 → decoupler-2.2.0}/docs/_static/css/custom.css +0 -0
  41. {decoupler-2.1.6 → decoupler-2.2.0}/docs/_static/images/logo.png +0 -0
  42. {decoupler-2.1.6 → decoupler-2.2.0}/docs/_static/images/logo.svg +0 -0
  43. {decoupler-2.1.6 → decoupler-2.2.0}/docs/_static/images/mlm.png +0 -0
  44. {decoupler-2.1.6 → decoupler-2.2.0}/docs/_static/images/ora.png +0 -0
  45. {decoupler-2.1.6 → decoupler-2.2.0}/docs/_static/images/ulm.png +0 -0
  46. {decoupler-2.1.6 → decoupler-2.2.0}/docs/_templates/.gitkeep +0 -0
  47. {decoupler-2.1.6 → decoupler-2.2.0}/docs/_templates/autosummary/class.rst +0 -0
  48. {decoupler-2.1.6 → decoupler-2.2.0}/docs/api/bm.md +0 -0
  49. {decoupler-2.1.6 → decoupler-2.2.0}/docs/api/ds.md +0 -0
  50. {decoupler-2.1.6 → decoupler-2.2.0}/docs/api/index.md +0 -0
  51. {decoupler-2.1.6 → decoupler-2.2.0}/docs/api/mt.md +0 -0
  52. {decoupler-2.1.6 → decoupler-2.2.0}/docs/api/op.md +0 -0
  53. {decoupler-2.1.6 → decoupler-2.2.0}/docs/api/pl.md +0 -0
  54. {decoupler-2.1.6 → decoupler-2.2.0}/docs/api/pp.md +0 -0
  55. {decoupler-2.1.6 → decoupler-2.2.0}/docs/api/tl.md +0 -0
  56. {decoupler-2.1.6 → decoupler-2.2.0}/docs/changelog.md +0 -0
  57. {decoupler-2.1.6 → decoupler-2.2.0}/docs/conf.py +0 -0
  58. {decoupler-2.1.6 → decoupler-2.2.0}/docs/extensions/typed_returns.py +0 -0
  59. {decoupler-2.1.6 → decoupler-2.2.0}/docs/index.md +0 -0
  60. {decoupler-2.1.6 → decoupler-2.2.0}/docs/references.bib +0 -0
  61. {decoupler-2.1.6 → decoupler-2.2.0}/docs/references.md +0 -0
  62. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/_Method.py +0 -0
  63. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/_Plotter.py +0 -0
  64. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/__init__.py +0 -0
  65. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/_datatype.py +0 -0
  66. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/_docs.py +0 -0
  67. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/_download.py +0 -0
  68. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/_log.py +0 -0
  69. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/_odeps.py +0 -0
  70. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/__init__.py +0 -0
  71. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/_pp.py +0 -0
  72. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/_run.py +0 -0
  73. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/metric/_Metric.py +0 -0
  74. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/metric/__init__.py +0 -0
  75. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/metric/_auc.py +0 -0
  76. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/metric/_fscore.py +0 -0
  77. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/metric/_hmean.py +0 -0
  78. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/metric/_qrank.py +0 -0
  79. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/pl/__init__.py +0 -0
  80. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/pl/_auc.py +0 -0
  81. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/pl/_bar.py +0 -0
  82. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/pl/_format.py +0 -0
  83. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/pl/_fscore.py +0 -0
  84. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/pl/_qrank.py +0 -0
  85. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/bm/pl/_summary.py +0 -0
  86. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/ds/__init__.py +0 -0
  87. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/ds/_bulk.py +0 -0
  88. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/ds/_scell.py +0 -0
  89. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/ds/_spatial.py +0 -0
  90. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/ds/_toy.py +0 -0
  91. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/ds/_utils.py +0 -0
  92. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/__init__.py +0 -0
  93. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_aucell.py +0 -0
  94. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_consensus.py +0 -0
  95. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_decouple.py +0 -0
  96. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_gsea.py +0 -0
  97. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_gsva.py +0 -0
  98. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_mdt.py +0 -0
  99. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_methods.py +0 -0
  100. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_mlm.py +0 -0
  101. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_ora.py +0 -0
  102. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_pv.py +0 -0
  103. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_query_set.py +0 -0
  104. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_run.py +0 -0
  105. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_udt.py +0 -0
  106. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_ulm.py +0 -0
  107. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_viper.py +0 -0
  108. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_waggr.py +0 -0
  109. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/mt/_zscore.py +0 -0
  110. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/op/__init__.py +0 -0
  111. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/op/_collectri.py +0 -0
  112. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/op/_dorothea.py +0 -0
  113. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/op/_dtype.py +0 -0
  114. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/op/_hallmark.py +0 -0
  115. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/op/_progeny.py +0 -0
  116. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/op/_resource.py +0 -0
  117. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/op/_translate.py +0 -0
  118. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/__init__.py +0 -0
  119. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_barplot.py +0 -0
  120. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_dotplot.py +0 -0
  121. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_filter_by_expr.py +0 -0
  122. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_filter_by_prop.py +0 -0
  123. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_filter_samples.py +0 -0
  124. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_leading_edge.py +0 -0
  125. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_network.py +0 -0
  126. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_obsbar.py +0 -0
  127. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_obsm.py +0 -0
  128. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_order.py +0 -0
  129. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_order_targets.py +0 -0
  130. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_source_targets.py +0 -0
  131. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pl/_volcano.py +0 -0
  132. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pp/__init__.py +0 -0
  133. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pp/anndata.py +0 -0
  134. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pp/data.py +0 -0
  135. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/pp/net.py +0 -0
  136. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/tl/__init__.py +0 -0
  137. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/tl/_rankby_group.py +0 -0
  138. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/tl/_rankby_obsm.py +0 -0
  139. {decoupler-2.1.6 → decoupler-2.2.0}/src/decoupler/tl/_rankby_order.py +0 -0
  140. {decoupler-2.1.6 → decoupler-2.2.0}/tests/bm/test_benchmark.py +0 -0
  141. {decoupler-2.1.6 → decoupler-2.2.0}/tests/bm/test_pl.py +0 -0
  142. {decoupler-2.1.6 → decoupler-2.2.0}/tests/conftest.py +0 -0
  143. {decoupler-2.1.6 → decoupler-2.2.0}/tests/ds/test_bulk.py +0 -0
  144. {decoupler-2.1.6 → decoupler-2.2.0}/tests/ds/test_scell.py +0 -0
  145. {decoupler-2.1.6 → decoupler-2.2.0}/tests/ds/test_spatial.py +0 -0
  146. {decoupler-2.1.6 → decoupler-2.2.0}/tests/ds/test_toy.py +0 -0
  147. {decoupler-2.1.6 → decoupler-2.2.0}/tests/ds/test_utils.py +0 -0
  148. {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_adj.py +0 -0
  149. {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_aucell.py +0 -0
  150. {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_consensus.py +0 -0
  151. {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_decouple.py +0 -0
  152. {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_gsea.py +0 -0
  153. {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_gsva.py +0 -0
  154. {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_mdt.py +0 -0
  155. {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_methods.py +0 -0
  156. {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_mlm.py +0 -0
  157. {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_ora.py +0 -0
  158. {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_query_set.py +0 -0
  159. {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_run.py +0 -0
  160. {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_udt.py +0 -0
  161. {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_ulm.py +0 -0
  162. {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_viper.py +0 -0
  163. {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_waggr.py +0 -0
  164. {decoupler-2.1.6 → decoupler-2.2.0}/tests/mt/test_zscore.py +0 -0
  165. {decoupler-2.1.6 → decoupler-2.2.0}/tests/op/test_collectri.py +0 -0
  166. {decoupler-2.1.6 → decoupler-2.2.0}/tests/op/test_dorothea.py +0 -0
  167. {decoupler-2.1.6 → decoupler-2.2.0}/tests/op/test_dtype.py +0 -0
  168. {decoupler-2.1.6 → decoupler-2.2.0}/tests/op/test_hallmark.py +0 -0
  169. {decoupler-2.1.6 → decoupler-2.2.0}/tests/op/test_progeny.py +0 -0
  170. {decoupler-2.1.6 → decoupler-2.2.0}/tests/op/test_resource.py +0 -0
  171. {decoupler-2.1.6 → decoupler-2.2.0}/tests/op/test_translate.py +0 -0
  172. {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_Plotter.py +0 -0
  173. {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_barplot.py +0 -0
  174. {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_dotplot.py +0 -0
  175. {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_filter_by_expr.py +0 -0
  176. {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_filter_by_prop.py +0 -0
  177. {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_filter_samples.py +0 -0
  178. {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_leading_edge.py +0 -0
  179. {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_network.py +0 -0
  180. {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_obsbar.py +0 -0
  181. {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_obsm.py +0 -0
  182. {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_order.py +0 -0
  183. {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_order_targets.py +0 -0
  184. {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_source_targets.py +0 -0
  185. {decoupler-2.1.6 → decoupler-2.2.0}/tests/pl/test_volcano.py +0 -0
  186. {decoupler-2.1.6 → decoupler-2.2.0}/tests/pp/test_data.py +0 -0
  187. {decoupler-2.1.6 → decoupler-2.2.0}/tests/pp/test_net.py +0 -0
  188. {decoupler-2.1.6 → decoupler-2.2.0}/tests/test_download.py +0 -0
  189. {decoupler-2.1.6 → decoupler-2.2.0}/tests/test_version.py +0 -0
  190. {decoupler-2.1.6 → decoupler-2.2.0}/tests/tl/test_rankby_group.py +0 -0
  191. {decoupler-2.1.6 → decoupler-2.2.0}/tests/tl/test_rankby_obsm.py +0 -0
  192. {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@v5
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.4.10
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.21.0
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.9
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.1.6
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
- methods to extract biologically driven scores
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.10 or newer installed on your system.
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
- methods to extract biologically driven scores
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.10 or newer installed on your system.
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.1.6"
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.hatch-test.dependency-groups = [ "dev", "test" ]
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
- { key = "UV_PRERELEASE", value = "allow", if = [ "pre" ] },
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,6 @@
1
+ """Bundled Claude Code Agent Skill and its installer.
2
+
3
+ This subpackage keeps the decoupler Agent Skill (the ``data/`` directory) and the
4
+ command that installs it (``install.py``) together and out of the main package
5
+ namespace. See ``install.py`` for usage.
6
+ """
@@ -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)