decoupler 2.3.0__tar.gz → 2.3.1__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 (185) hide show
  1. {decoupler-2.3.0 → decoupler-2.3.1}/.editorconfig +1 -1
  2. decoupler-2.3.1/.github/workflows/notebooks.yaml +62 -0
  3. {decoupler-2.3.0 → decoupler-2.3.1}/.github/workflows/test.yaml +7 -7
  4. {decoupler-2.3.0 → decoupler-2.3.1}/.pre-commit-config.yaml +3 -3
  5. {decoupler-2.3.0 → decoupler-2.3.1}/CHANGELOG.md +32 -2
  6. {decoupler-2.3.0 → decoupler-2.3.1}/PKG-INFO +8 -6
  7. {decoupler-2.3.0 → decoupler-2.3.1}/README.md +7 -5
  8. {decoupler-2.3.0 → decoupler-2.3.1}/docs/api/ds.md +5 -0
  9. {decoupler-2.3.0 → decoupler-2.3.1}/docs/api/pp.md +3 -0
  10. {decoupler-2.3.0 → decoupler-2.3.1}/pyproject.toml +1 -1
  11. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/_skills/data/SKILL.md +10 -9
  12. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/_skills/data/references/resources.md +8 -8
  13. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/mt/_gsea.py +7 -5
  14. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/mt/_waggr.py +20 -8
  15. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/mt/_zscore.py +2 -2
  16. {decoupler-2.3.0 → decoupler-2.3.1}/tests/mt/test_gsea.py +28 -0
  17. {decoupler-2.3.0 → decoupler-2.3.1}/tests/mt/test_waggr.py +18 -0
  18. decoupler-2.3.1/tests/mt/test_zscore.py +27 -0
  19. decoupler-2.3.0/.github/workflows/notebooks.yaml +0 -61
  20. decoupler-2.3.0/tests/mt/test_zscore.py +0 -16
  21. {decoupler-2.3.0 → decoupler-2.3.1}/.codecov.yaml +0 -0
  22. {decoupler-2.3.0 → decoupler-2.3.1}/.cruft.json +0 -0
  23. {decoupler-2.3.0 → decoupler-2.3.1}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  24. {decoupler-2.3.0 → decoupler-2.3.1}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  25. {decoupler-2.3.0 → decoupler-2.3.1}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  26. {decoupler-2.3.0 → decoupler-2.3.1}/.github/dependabot.yml +0 -0
  27. {decoupler-2.3.0 → decoupler-2.3.1}/.github/workflows/build.yaml +0 -0
  28. {decoupler-2.3.0 → decoupler-2.3.1}/.github/workflows/release.yaml +0 -0
  29. {decoupler-2.3.0 → decoupler-2.3.1}/.gitignore +0 -0
  30. {decoupler-2.3.0 → decoupler-2.3.1}/.gitmodules +0 -0
  31. {decoupler-2.3.0 → decoupler-2.3.1}/.readthedocs.yaml +0 -0
  32. {decoupler-2.3.0 → decoupler-2.3.1}/.vscode/extensions.json +0 -0
  33. {decoupler-2.3.0 → decoupler-2.3.1}/.vscode/launch.json +0 -0
  34. {decoupler-2.3.0 → decoupler-2.3.1}/.vscode/settings.json +0 -0
  35. {decoupler-2.3.0 → decoupler-2.3.1}/LICENSE +0 -0
  36. {decoupler-2.3.0 → decoupler-2.3.1}/biome.jsonc +0 -0
  37. {decoupler-2.3.0 → decoupler-2.3.1}/docs/_static/.gitkeep +0 -0
  38. {decoupler-2.3.0 → decoupler-2.3.1}/docs/_static/css/custom.css +0 -0
  39. {decoupler-2.3.0 → decoupler-2.3.1}/docs/_static/images/logo.png +0 -0
  40. {decoupler-2.3.0 → decoupler-2.3.1}/docs/_static/images/logo.svg +0 -0
  41. {decoupler-2.3.0 → decoupler-2.3.1}/docs/_static/images/mlm.png +0 -0
  42. {decoupler-2.3.0 → decoupler-2.3.1}/docs/_static/images/ora.png +0 -0
  43. {decoupler-2.3.0 → decoupler-2.3.1}/docs/_static/images/ulm.png +0 -0
  44. {decoupler-2.3.0 → decoupler-2.3.1}/docs/_templates/.gitkeep +0 -0
  45. {decoupler-2.3.0 → decoupler-2.3.1}/docs/api/bm.md +1 -1
  46. {decoupler-2.3.0 → decoupler-2.3.1}/docs/api/index.md +0 -0
  47. {decoupler-2.3.0 → decoupler-2.3.1}/docs/api/mt.md +0 -0
  48. {decoupler-2.3.0 → decoupler-2.3.1}/docs/api/op.md +0 -0
  49. {decoupler-2.3.0 → decoupler-2.3.1}/docs/api/pl.md +0 -0
  50. {decoupler-2.3.0 → decoupler-2.3.1}/docs/api/tl.md +0 -0
  51. {decoupler-2.3.0 → decoupler-2.3.1}/docs/changelog.md +0 -0
  52. {decoupler-2.3.0 → decoupler-2.3.1}/docs/conf.py +0 -0
  53. {decoupler-2.3.0 → decoupler-2.3.1}/docs/index.md +0 -0
  54. {decoupler-2.3.0 → decoupler-2.3.1}/docs/references.bib +0 -0
  55. {decoupler-2.3.0 → decoupler-2.3.1}/docs/references.md +0 -0
  56. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/_Method.py +0 -0
  57. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/_Plotter.py +0 -0
  58. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/__init__.py +0 -0
  59. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/_datatype.py +0 -0
  60. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/_docs.py +0 -0
  61. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/_download.py +0 -0
  62. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/_log.py +0 -0
  63. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/_odeps.py +0 -0
  64. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/_skills/__init__.py +0 -0
  65. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/_skills/data/references/contrast.md +0 -0
  66. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/_skills/install.py +0 -0
  67. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/bm/__init__.py +0 -0
  68. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/bm/_pp.py +0 -0
  69. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/bm/_run.py +0 -0
  70. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/bm/metric/_Metric.py +0 -0
  71. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/bm/metric/__init__.py +0 -0
  72. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/bm/metric/_auc.py +0 -0
  73. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/bm/metric/_fscore.py +0 -0
  74. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/bm/metric/_hmean.py +0 -0
  75. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/bm/metric/_qrank.py +0 -0
  76. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/bm/pl/__init__.py +0 -0
  77. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/bm/pl/_auc.py +0 -0
  78. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/bm/pl/_bar.py +0 -0
  79. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/bm/pl/_format.py +0 -0
  80. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/bm/pl/_fscore.py +0 -0
  81. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/bm/pl/_qrank.py +0 -0
  82. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/bm/pl/_summary.py +0 -0
  83. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/ds/__init__.py +0 -0
  84. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/ds/_bulk.py +0 -0
  85. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/ds/_scell.py +0 -0
  86. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/ds/_spatial.py +0 -0
  87. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/ds/_toy.py +0 -0
  88. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/ds/_utils.py +0 -0
  89. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/mt/__init__.py +0 -0
  90. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/mt/_aucell.py +0 -0
  91. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/mt/_consensus.py +0 -0
  92. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/mt/_decouple.py +0 -0
  93. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/mt/_gsva.py +0 -0
  94. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/mt/_mdt.py +0 -0
  95. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/mt/_methods.py +0 -0
  96. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/mt/_mlm.py +0 -0
  97. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/mt/_ora.py +0 -0
  98. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/mt/_pv.py +0 -0
  99. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/mt/_query_set.py +0 -0
  100. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/mt/_run.py +0 -0
  101. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/mt/_udt.py +0 -0
  102. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/mt/_ulm.py +0 -0
  103. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/mt/_viper.py +0 -0
  104. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/op/__init__.py +0 -0
  105. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/op/_collectri.py +0 -0
  106. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/op/_dorothea.py +0 -0
  107. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/op/_dtype.py +0 -0
  108. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/op/_hallmark.py +0 -0
  109. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/op/_progeny.py +0 -0
  110. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/op/_resource.py +0 -0
  111. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/op/_translate.py +0 -0
  112. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/pl/__init__.py +0 -0
  113. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/pl/_barplot.py +0 -0
  114. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/pl/_dotplot.py +0 -0
  115. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/pl/_filter_by_expr.py +0 -0
  116. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/pl/_filter_by_prop.py +0 -0
  117. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/pl/_filter_samples.py +0 -0
  118. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/pl/_leading_edge.py +0 -0
  119. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/pl/_network.py +0 -0
  120. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/pl/_obsbar.py +0 -0
  121. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/pl/_obsm.py +0 -0
  122. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/pl/_order.py +0 -0
  123. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/pl/_order_targets.py +0 -0
  124. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/pl/_source_targets.py +0 -0
  125. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/pl/_volcano.py +0 -0
  126. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/pp/__init__.py +0 -0
  127. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/pp/anndata.py +0 -0
  128. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/pp/data.py +0 -0
  129. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/pp/net.py +0 -0
  130. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/tl/__init__.py +0 -0
  131. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/tl/_rankby_group.py +0 -0
  132. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/tl/_rankby_obsm.py +0 -0
  133. {decoupler-2.3.0 → decoupler-2.3.1}/src/decoupler/tl/_rankby_order.py +0 -0
  134. {decoupler-2.3.0 → decoupler-2.3.1}/tests/bm/test_benchmark.py +0 -0
  135. {decoupler-2.3.0 → decoupler-2.3.1}/tests/bm/test_pl.py +0 -0
  136. {decoupler-2.3.0 → decoupler-2.3.1}/tests/conftest.py +0 -0
  137. {decoupler-2.3.0 → decoupler-2.3.1}/tests/ds/test_bulk.py +0 -0
  138. {decoupler-2.3.0 → decoupler-2.3.1}/tests/ds/test_scell.py +0 -0
  139. {decoupler-2.3.0 → decoupler-2.3.1}/tests/ds/test_spatial.py +0 -0
  140. {decoupler-2.3.0 → decoupler-2.3.1}/tests/ds/test_toy.py +0 -0
  141. {decoupler-2.3.0 → decoupler-2.3.1}/tests/ds/test_utils.py +0 -0
  142. {decoupler-2.3.0 → decoupler-2.3.1}/tests/mt/test_adj.py +0 -0
  143. {decoupler-2.3.0 → decoupler-2.3.1}/tests/mt/test_aucell.py +0 -0
  144. {decoupler-2.3.0 → decoupler-2.3.1}/tests/mt/test_consensus.py +0 -0
  145. {decoupler-2.3.0 → decoupler-2.3.1}/tests/mt/test_decouple.py +0 -0
  146. {decoupler-2.3.0 → decoupler-2.3.1}/tests/mt/test_gsva.py +0 -0
  147. {decoupler-2.3.0 → decoupler-2.3.1}/tests/mt/test_mdt.py +0 -0
  148. {decoupler-2.3.0 → decoupler-2.3.1}/tests/mt/test_methods.py +0 -0
  149. {decoupler-2.3.0 → decoupler-2.3.1}/tests/mt/test_mlm.py +0 -0
  150. {decoupler-2.3.0 → decoupler-2.3.1}/tests/mt/test_ora.py +0 -0
  151. {decoupler-2.3.0 → decoupler-2.3.1}/tests/mt/test_query_set.py +0 -0
  152. {decoupler-2.3.0 → decoupler-2.3.1}/tests/mt/test_run.py +0 -0
  153. {decoupler-2.3.0 → decoupler-2.3.1}/tests/mt/test_udt.py +0 -0
  154. {decoupler-2.3.0 → decoupler-2.3.1}/tests/mt/test_ulm.py +0 -0
  155. {decoupler-2.3.0 → decoupler-2.3.1}/tests/mt/test_viper.py +0 -0
  156. {decoupler-2.3.0 → decoupler-2.3.1}/tests/op/test_collectri.py +0 -0
  157. {decoupler-2.3.0 → decoupler-2.3.1}/tests/op/test_dorothea.py +0 -0
  158. {decoupler-2.3.0 → decoupler-2.3.1}/tests/op/test_dtype.py +0 -0
  159. {decoupler-2.3.0 → decoupler-2.3.1}/tests/op/test_hallmark.py +0 -0
  160. {decoupler-2.3.0 → decoupler-2.3.1}/tests/op/test_progeny.py +0 -0
  161. {decoupler-2.3.0 → decoupler-2.3.1}/tests/op/test_resource.py +0 -0
  162. {decoupler-2.3.0 → decoupler-2.3.1}/tests/op/test_translate.py +0 -0
  163. {decoupler-2.3.0 → decoupler-2.3.1}/tests/pl/test_Plotter.py +0 -0
  164. {decoupler-2.3.0 → decoupler-2.3.1}/tests/pl/test_barplot.py +0 -0
  165. {decoupler-2.3.0 → decoupler-2.3.1}/tests/pl/test_dotplot.py +0 -0
  166. {decoupler-2.3.0 → decoupler-2.3.1}/tests/pl/test_filter_by_expr.py +0 -0
  167. {decoupler-2.3.0 → decoupler-2.3.1}/tests/pl/test_filter_by_prop.py +0 -0
  168. {decoupler-2.3.0 → decoupler-2.3.1}/tests/pl/test_filter_samples.py +0 -0
  169. {decoupler-2.3.0 → decoupler-2.3.1}/tests/pl/test_leading_edge.py +0 -0
  170. {decoupler-2.3.0 → decoupler-2.3.1}/tests/pl/test_network.py +0 -0
  171. {decoupler-2.3.0 → decoupler-2.3.1}/tests/pl/test_obsbar.py +0 -0
  172. {decoupler-2.3.0 → decoupler-2.3.1}/tests/pl/test_obsm.py +0 -0
  173. {decoupler-2.3.0 → decoupler-2.3.1}/tests/pl/test_order.py +0 -0
  174. {decoupler-2.3.0 → decoupler-2.3.1}/tests/pl/test_order_targets.py +0 -0
  175. {decoupler-2.3.0 → decoupler-2.3.1}/tests/pl/test_source_targets.py +0 -0
  176. {decoupler-2.3.0 → decoupler-2.3.1}/tests/pl/test_volcano.py +0 -0
  177. {decoupler-2.3.0 → decoupler-2.3.1}/tests/pp/test_anndata.py +0 -0
  178. {decoupler-2.3.0 → decoupler-2.3.1}/tests/pp/test_data.py +0 -0
  179. {decoupler-2.3.0 → decoupler-2.3.1}/tests/pp/test_net.py +0 -0
  180. {decoupler-2.3.0 → decoupler-2.3.1}/tests/test_download.py +0 -0
  181. {decoupler-2.3.0 → decoupler-2.3.1}/tests/test_install_skills.py +0 -0
  182. {decoupler-2.3.0 → decoupler-2.3.1}/tests/test_version.py +0 -0
  183. {decoupler-2.3.0 → decoupler-2.3.1}/tests/tl/test_rankby_group.py +0 -0
  184. {decoupler-2.3.0 → decoupler-2.3.1}/tests/tl/test_rankby_obsm.py +0 -0
  185. {decoupler-2.3.0 → decoupler-2.3.1}/tests/tl/test_rankby_order.py +0 -0
@@ -8,7 +8,7 @@ charset = utf-8
8
8
  trim_trailing_whitespace = true
9
9
  insert_final_newline = true
10
10
 
11
- [{*.{yml,yaml,toml},.cruft.json}]
11
+ [{*.yml,*.yaml,*.toml,.cruft.json}]
12
12
  indent_size = 2
13
13
 
14
14
  [Makefile]
@@ -0,0 +1,62 @@
1
+ name: Test notebooks
2
+
3
+ on:
4
+ push:
5
+ branches: [main]
6
+ pull_request:
7
+ branches: [main]
8
+
9
+ concurrency:
10
+ group: ${{ github.workflow }}-${{ github.ref }}
11
+ cancel-in-progress: true
12
+
13
+ permissions:
14
+ contents: read
15
+
16
+ jobs:
17
+ test:
18
+ runs-on: ubuntu-latest
19
+ defaults:
20
+ run:
21
+ # to fail on error in multiline statements (-e), in pipes (-o pipefail), and on unset variables (-u).
22
+ shell: bash -euo pipefail {0}
23
+
24
+ env:
25
+ NOTEBOOK_PATH: docs/notebooks
26
+
27
+ strategy:
28
+ fail-fast: false
29
+ matrix:
30
+ notebook:
31
+ [
32
+ "example.ipynb",
33
+ "bench/rna.ipynb",
34
+ "bulk/rna.ipynb",
35
+ "omnipath/licenses.ipynb",
36
+ "omnipath/orthologs.ipynb",
37
+ "scell/rna_psbk.ipynb",
38
+ "scell/rna_pstime.ipynb",
39
+ "scell/rna_sc.ipynb",
40
+ "spatial/rna_visium.ipynb",
41
+ ]
42
+
43
+ steps:
44
+ - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
45
+ with:
46
+ filter: blob:none
47
+ fetch-depth: 0
48
+ submodules: "true"
49
+ persist-credentials: false
50
+ - name: Set up Python
51
+ uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
52
+ with:
53
+ python-version: "3.13"
54
+ - name: Install uv
55
+ uses: astral-sh/setup-uv@1c37ad07a6a961277cf70c0d37d6f313000f5884 # v10.3.0
56
+ - name: Install dependencies
57
+ run: |
58
+ uv pip install --system .
59
+ uv pip install --system --group dev --group test
60
+ uv pip install --system nbconvert ipykernel
61
+ - name: Run ${{ matrix.notebook }} Notebook
62
+ run: jupyter nbconvert --to notebook --execute ${{ env.NOTEBOOK_PATH }}/${{ matrix.notebook }}
@@ -54,8 +54,8 @@ jobs:
54
54
  test:
55
55
  needs: get-environments
56
56
  permissions:
57
- id-token: write # for codecov OIDC
58
- contents: read
57
+ id-token: write # for codecov OIDC
58
+ contents: read
59
59
 
60
60
  strategy:
61
61
  fail-fast: false
@@ -65,7 +65,7 @@ jobs:
65
65
 
66
66
  name: ${{ matrix.env.label }}
67
67
  runs-on: ${{ matrix.os }}
68
- continue-on-error: ${{ contains(matrix.env.name, 'pre') }} # make "all-green" pass even if pre-release job fails
68
+ continue-on-error: ${{ contains(matrix.env.name, 'pre') }} # make "all-green" pass even if pre-release job fails
69
69
 
70
70
  steps:
71
71
  - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
@@ -109,7 +109,7 @@ jobs:
109
109
  - test
110
110
  runs-on: ubuntu-latest
111
111
  steps:
112
- - uses: re-actors/alls-green@b5b5b37504aa4183270bd3d855c52a67f212be35 # v1.3.0
113
- with:
114
- allowed-failures: ${{ needs.get-environments.outputs.allowed-failures }}
115
- jobs: ${{ toJSON(needs) }}
112
+ - uses: re-actors/alls-green@b5b5b37504aa4183270bd3d855c52a67f212be35 # v1.3.0
113
+ with:
114
+ allowed-failures: ${{ needs.get-environments.outputs.allowed-failures }}
115
+ jobs: ${{ toJSON(needs) }}
@@ -7,7 +7,7 @@ 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.5.15
10
+ rev: v2.6.3
11
11
  hooks:
12
12
  - id: biome-format
13
13
  exclude: ^\.cruft\.json$ # inconsistent indentation with cruft - file never to be modified manually.
@@ -16,7 +16,7 @@ repos:
16
16
  hooks:
17
17
  - id: pyproject-fmt
18
18
  - repo: https://github.com/astral-sh/ruff-pre-commit
19
- rev: v0.17.1
19
+ rev: v0.17.2
20
20
  hooks:
21
21
  - id: ruff-check
22
22
  types_or: [python, pyi, jupyter]
@@ -38,7 +38,7 @@ repos:
38
38
  args: [--assume-in-merge]
39
39
 
40
40
  - repo: https://github.com/zizmorcore/zizmor-pre-commit
41
- rev: v1.24.1
41
+ rev: v1.31.1
42
42
  hooks:
43
43
  - id: zizmor
44
44
  args: [--no-progress, --fix]
@@ -8,9 +8,18 @@ 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.3.1
12
+
13
+ ### Bugfixes
14
+
15
+ - Fixed `mt.zscore` swapping the `KSEA` and `RoKAI` flavors, restoring the behaviour of `decoupler<2`. Scores from the default `RoKAI` flavor change (#382)
16
+ - Fixed `mt.gsea` giving p-values of 0 when no permutation reached the observed score. The observed score is now counted as one of the permutations, as in `mt.waggr` (#383)
17
+ - Fixed `mt.waggr` aborting the Python process with numba's `workqueue` threading layer (default when TBB/OpenMP are unavailable, e.g. macOS arm64) due to nested parallel regions
18
+
11
19
  ## 2.3.0
12
20
 
13
21
  ### Changes
22
+
14
23
  - Updated the bundled decoupler Agent Skill, and `decoupler-install-skills` now supports multiple agent frameworks
15
24
  - `pp.filter_by_prop` now defaults to `min_prop=0.1` (was `0.2`) to match the value used in the vignettes
16
25
  - `ds.msvisium` now returns log-normalized data (`sc.pp.normalize_total` + `sc.pp.log1p`), with the log-normalized matrix also stored in `adata.layers["norm"]`, instead of raw counts
@@ -18,6 +27,7 @@ and this project adheres to [Semantic Versioning][].
18
27
  - Updated to the scverse cookiecutter template v0.8.0 (hash-pinned GitHub Actions checked by zizmor, `prek` instead of `pre-commit`, `sphinx-design` instead of `sphinx-tabs`, shared Sphinx extensions from `scverse-misc`)
19
28
 
20
29
  ### Bugfixes
30
+
21
31
  - Fixed `mt.ora` selecting the bottom `nvar - n_up` features instead of the top `n_up` ones. Ranks are ascending, so the threshold is now `nvar - n_up`, restoring the behaviour of `decoupler<2`. With the default `n_up` (top 5%) this selected 95% of the features as observed, which also made `mt.ora` fail with `invalid contingency table` whenever `nvar - n_up` exceeded `n_bg` (#346)
22
32
  - Fixed `n_bm` in `mt.ora` selecting the bottom `n_bm - 1` features instead of `n_bm`
23
33
  - `mt.ora` now validates that `n_up` and `n_bm` do not overlap and that `n_bg` is large enough for the number of selected features, instead of failing inside the Fisher exact test
@@ -30,12 +40,14 @@ and this project adheres to [Semantic Versioning][].
30
40
  ## 2.2.0
31
41
 
32
42
  ### Added
43
+
33
44
  - 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)
34
45
  - 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)
35
46
 
36
47
  ## 2.1.6
37
48
 
38
49
  ### Bugfixes
50
+
39
51
  - Fixed `op.translate` (and every `op.resource` call for non-human organisms) failing with HTTP 404 after HGNC dropped the `genenames/` subtree from the EBI FTP mirror; the HCOP fifteen-column files are now fetched from the new HGNC Google Cloud Storage bucket (#303)
40
52
  - Removed a redundant `pd.read_csv` call in `op.translate` that re-downloaded the HCOP file a second time and bypassed the retry logic in `_download`
41
53
  - Fixed `bm.benchmark` ground-truth matrix row order not matching score matrix after `pivot`, which silently misaligned perturbation labels when obs names sort differently from their original order (#302)
@@ -43,29 +55,35 @@ and this project adheres to [Semantic Versioning][].
43
55
  ## 2.1.5
44
56
 
45
57
  ### Added
58
+
46
59
  - `pl.volcano` now accepts a gene name (`str`) or list of gene names (`list[str]`) for the `top` parameter to annotate specific features on volcano plots
47
60
 
48
61
  ### Changes
62
+
49
63
  - Refactored `ds.ensmbl_to_symbol` to reuse `_download` and fixed mirror fallback to actually switch between Ensembl mirrors
50
64
  - Made `tqdm` progress bar compact in `_download`
51
65
 
52
66
  ### Bugfixes
67
+
53
68
  - Fixed `pl.dotplot` ignoring `vcenter=0` due to falsy check (#293)
54
69
  - Fixed `_log` setting the root logging level to INFO for all packages (#296)
55
70
 
56
71
  ## 2.1.4
57
72
 
58
73
  ### Changes
74
+
59
75
  - Added `alternative` argument to `decoupler.mt.query_set`. By default `'greater'`, before it was `'two-sided'`
60
76
  - Unpinned `scipy` version limit
61
77
 
62
78
  ### Bugfixes
79
+
63
80
  - Fixed missing progressbar for `decoupler._download._download`
64
81
  - Added missing `decoupler.mt.query_set` documentation
65
82
 
66
83
  ## 2.1.3
67
84
 
68
85
  ### Changes
86
+
69
87
  - `pp.adjmat` now returns the same features as used as input instead of the subset of `net`
70
88
  - `pp.pseudobulk` now returns the same order features as used as input instead of shuffling them
71
89
  - Added a dedicated header and 5 attemps to `_download` to mitigate 429 Client Error from Zenodo downloads
@@ -73,6 +91,7 @@ and this project adheres to [Semantic Versioning][].
73
91
  ## 2.1.2
74
92
 
75
93
  ### Added
94
+
76
95
  - `pp.query_set` to test overlap between a given feature set against a database of sets
77
96
 
78
97
  ### Changes
@@ -84,10 +103,12 @@ and this project adheres to [Semantic Versioning][].
84
103
  ## 2.1.1
85
104
 
86
105
  ### Added
106
+
87
107
  - mypy checks in CI
88
108
  - notebook checks in CI
89
109
 
90
110
  ### Bugfixes
111
+
91
112
  - Fixed error in `decoupler.pp.pseudobulk` when `adata.obs_names` were not unique, now throws verbose error
92
113
  - Fixed corner case in `decoupler.mt.gsea` when p-values were infitite and could not be corrected
93
114
 
@@ -100,41 +121,49 @@ and this project adheres to [Semantic Versioning][].
100
121
  - Enrichment methods and pseudobulking now work with backed AnnData objects, useful when working with big datasets and memory is limited
101
122
 
102
123
  ### Bugfixes
124
+
103
125
  - Fixed error in `pl.obsm` where default value of `cmap_obs` was not properly set.
104
126
 
105
127
  ## 2.0.7
106
128
 
107
129
  ### Changes
130
+
108
131
  - Added `pre-commit` functionality to the repository
109
132
 
110
133
  ## 2.0.6
111
134
 
112
135
  ### Changes
136
+
113
137
  - Modified links and paths to follow scverse's repository
114
138
 
115
139
  ## 2.0.5
116
140
 
117
141
  ### Bugfixes
142
+
118
143
  - Fixed error message when extra dependencies where not installed
119
144
 
120
145
  ## 2.0.4
121
146
 
122
147
  ### Bugfixes
148
+
123
149
  - Fixed `dcor` import bug as an external dependency
124
150
 
125
151
  ## 2.0.3
126
152
 
127
153
  ### Bugfixes
154
+
128
155
  - Fixed error in `pp.pseudobulk` when obs columns were not categorical
129
156
 
130
157
  ## 2.0.2
131
158
 
132
159
  ### Changes
160
+
133
161
  - Allowed ordering functions (`pp.bin_order`, `pl.order` and `pl.order_targets`) not to be bound between 0 and 1
134
162
  - Added ipywidgets as dependency
135
163
  - Silenced xgboost warnings
136
164
 
137
165
  ### Bugfixes
166
+
138
167
  - Handled corner case in `bm.metric.auc` when scores are all 0
139
168
  - Fixed error in `bm.metric.hmean` when metrics were str instead of list
140
169
  - Fixed error when `obs` column is a list in `pp.pseudobulk`
@@ -142,6 +171,7 @@ and this project adheres to [Semantic Versioning][].
142
171
  ## 2.0.1
143
172
 
144
173
  ### Bugfixes
174
+
145
175
  - Fixed an error in `pp.pseudobulk` when handling empty samples or features
146
176
 
147
177
  ## 2.0.0
@@ -168,7 +198,7 @@ All functions have been rewritten to follow the new API, errors when running pre
168
198
  - Fixed `collectri` to the publication version instead of the OmniPath one
169
199
  - Made `progeny` only return significant genes by default instead of the top N genes per pathway
170
200
  - Plots are now in a new `pl` module
171
- - Use `decoupler.pl.<plot_name>` to call a plot
201
+ - Use `decoupler.pl.<plot_name>` to call a plot
172
202
  - They use a common class `Plotter` to make it easier to share arguments between them
173
203
  - `plot_violins` has been deprecated
174
204
  - Names that have changed
@@ -188,7 +218,7 @@ All functions have been rewritten to follow the new API, errors when running pre
188
218
  ### Added
189
219
 
190
220
  - `ds` module with functions to download several datasets at different resolutions
191
- - Bulk: `hsctgfb` and `knocktf`
221
+ - Bulk: `hsctgfb` and `knocktf`
192
222
  - Single-cell: `pbmc3k`, `covid5k` and `erygast1k`
193
223
  - Spatial: `msvisium`
194
224
  - Toy data: `toy` and `toy_bench`
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: decoupler
3
- Version: 2.3.0
3
+ Version: 2.3.1
4
4
  Summary: Python package to perform enrichment analysis from omics data.
5
5
  Project-URL: Documentation, https://decoupler.scverse.org/
6
6
  Project-URL: Homepage, https://github.com/scverse/decoupler
@@ -56,6 +56,7 @@ Requires-Dist: tqdm
56
56
  Description-Content-Type: text/markdown
57
57
 
58
58
  # decoupler - Ensemble of methods to infer enrichment scores
59
+
59
60
  <img src="https://raw.githubusercontent.com/scverse/decoupler/refs/heads/main/docs/_static/images/logo.svg" align="right" width="120" class="no-scaled-link" />
60
61
 
61
62
  [![Tests][badge-tests]][tests]
@@ -86,7 +87,7 @@ Description-Content-Type: text/markdown
86
87
  `decoupler` is a python package containing different enrichment statistical methods to extract biologically driven scores from omics data within a unified framework.
87
88
  This is its faster and memory efficient Python implementation, a deprecated version in R can be found [here](https://github.com/saezlab/decoupler).
88
89
 
89
- [//]: # (numfocus-fiscal-sponsor-attribution)
90
+ [//]: # "numfocus-fiscal-sponsor-attribution"
90
91
 
91
92
  decoupler is part of the scverse® project ([website](https://scverse.org), [governance](https://scverse.org/about/roles)) and is fiscally sponsored by [NumFOCUS](https://numfocus.org/).
92
93
  If you like scverse® and want to support our mission, please consider making a tax-deductible [donation](https://numfocus.org/donate-to-scverse) to help the project pay for developer time, professional services, travel, workshops, and a variety of other needs.
@@ -156,6 +157,7 @@ For questions and help requests, you can reach out in the [scverse discourse][].
156
157
  If you found a bug, please use the [issue tracker][].
157
158
 
158
159
  ## License
160
+
159
161
  Enrichment methods inside decoupler can be used for academic or commercial purposes, except `viper` which holds a non-commercial license.
160
162
 
161
163
  The data redistributed by OmniPath does not have a single license, each original resource has its own. By default, `decoupler`
@@ -165,10 +167,10 @@ assumes an academic license, but commercial or nonprofit licenses can be specifi
165
167
  ## Citation
166
168
 
167
169
  > Badia-i-Mompel P., Vélez Santiago J., Braunger J., Geiss C., Dimitrov D.,
168
- Müller-Dott S., Taus P., Dugourd A., Holland C.H., Ramirez Flores R.O.
169
- and Saez-Rodriguez J. 2022. decoupleR: Ensemble of computational methods
170
- to infer biological activities from omics data. Bioinformatics Advances.
171
- <https://doi.org/10.1093/bioadv/vbac016>
170
+ > Müller-Dott S., Taus P., Dugourd A., Holland C.H., Ramirez Flores R.O.
171
+ > and Saez-Rodriguez J. 2022. decoupleR: Ensemble of computational methods
172
+ > to infer biological activities from omics data. Bioinformatics Advances.
173
+ > <https://doi.org/10.1093/bioadv/vbac016>
172
174
 
173
175
  [uv]: https://github.com/astral-sh/uv
174
176
  [scverse discourse]: https://discourse.scverse.org/
@@ -1,4 +1,5 @@
1
1
  # decoupler - Ensemble of methods to infer enrichment scores
2
+
2
3
  <img src="https://raw.githubusercontent.com/scverse/decoupler/refs/heads/main/docs/_static/images/logo.svg" align="right" width="120" class="no-scaled-link" />
3
4
 
4
5
  [![Tests][badge-tests]][tests]
@@ -29,7 +30,7 @@
29
30
  `decoupler` is a python package containing different enrichment statistical methods to extract biologically driven scores from omics data within a unified framework.
30
31
  This is its faster and memory efficient Python implementation, a deprecated version in R can be found [here](https://github.com/saezlab/decoupler).
31
32
 
32
- [//]: # (numfocus-fiscal-sponsor-attribution)
33
+ [//]: # "numfocus-fiscal-sponsor-attribution"
33
34
 
34
35
  decoupler is part of the scverse® project ([website](https://scverse.org), [governance](https://scverse.org/about/roles)) and is fiscally sponsored by [NumFOCUS](https://numfocus.org/).
35
36
  If you like scverse® and want to support our mission, please consider making a tax-deductible [donation](https://numfocus.org/donate-to-scverse) to help the project pay for developer time, professional services, travel, workshops, and a variety of other needs.
@@ -99,6 +100,7 @@ For questions and help requests, you can reach out in the [scverse discourse][].
99
100
  If you found a bug, please use the [issue tracker][].
100
101
 
101
102
  ## License
103
+
102
104
  Enrichment methods inside decoupler can be used for academic or commercial purposes, except `viper` which holds a non-commercial license.
103
105
 
104
106
  The data redistributed by OmniPath does not have a single license, each original resource has its own. By default, `decoupler`
@@ -108,10 +110,10 @@ assumes an academic license, but commercial or nonprofit licenses can be specifi
108
110
  ## Citation
109
111
 
110
112
  > Badia-i-Mompel P., Vélez Santiago J., Braunger J., Geiss C., Dimitrov D.,
111
- Müller-Dott S., Taus P., Dugourd A., Holland C.H., Ramirez Flores R.O.
112
- and Saez-Rodriguez J. 2022. decoupleR: Ensemble of computational methods
113
- to infer biological activities from omics data. Bioinformatics Advances.
114
- <https://doi.org/10.1093/bioadv/vbac016>
113
+ > Müller-Dott S., Taus P., Dugourd A., Holland C.H., Ramirez Flores R.O.
114
+ > and Saez-Rodriguez J. 2022. decoupleR: Ensemble of computational methods
115
+ > to infer biological activities from omics data. Bioinformatics Advances.
116
+ > <https://doi.org/10.1093/bioadv/vbac016>
115
117
 
116
118
  [uv]: https://github.com/astral-sh/uv
117
119
  [scverse discourse]: https://discourse.scverse.org/
@@ -1,6 +1,7 @@
1
1
  # Datasets
2
2
 
3
3
  ## Bulk
4
+
4
5
  ```{eval-rst}
5
6
  .. module:: decoupler.ds
6
7
  .. currentmodule:: decoupler
@@ -13,6 +14,7 @@
13
14
  ```
14
15
 
15
16
  ## Single-cell
17
+
16
18
  ```{eval-rst}
17
19
  .. autosummary::
18
20
  :toctree: generated
@@ -23,6 +25,7 @@
23
25
  ```
24
26
 
25
27
  ## Spatial
28
+
26
29
  ```{eval-rst}
27
30
  .. autosummary::
28
31
  :toctree: generated
@@ -31,6 +34,7 @@
31
34
  ```
32
35
 
33
36
  ## Toy
37
+
34
38
  ```{eval-rst}
35
39
  .. autosummary::
36
40
  :toctree: generated
@@ -40,6 +44,7 @@
40
44
  ```
41
45
 
42
46
  ## Utils
47
+
43
48
  ```{eval-rst}
44
49
  .. autosummary::
45
50
  :toctree: generated
@@ -1,6 +1,7 @@
1
1
  # Preprocessing
2
2
 
3
3
  ## Data
4
+
4
5
  ```{eval-rst}
5
6
  .. module:: decoupler.pp
6
7
  .. currentmodule:: decoupler
@@ -12,6 +13,7 @@
12
13
  ```
13
14
 
14
15
  ## Network
16
+
15
17
  ```{eval-rst}
16
18
  .. autosummary::
17
19
  :toctree: generated
@@ -25,6 +27,7 @@
25
27
  ```
26
28
 
27
29
  ## AnnData
30
+
28
31
  ```{eval-rst}
29
32
  .. autosummary::
30
33
  :toctree: generated
@@ -4,7 +4,7 @@ requires = [ "hatchling" ]
4
4
 
5
5
  [project]
6
6
  name = "decoupler"
7
- version = "2.3.0"
7
+ version = "2.3.1"
8
8
  description = "Python package to perform enrichment analysis from omics data."
9
9
  readme = "README.md"
10
10
  license = { file = "LICENSE" }
@@ -1,4 +1,5 @@
1
1
  ---
2
+
2
3
  name: decoupler
3
4
  description: Read before any task that mentions decoupler, one of its bundled example datasets, or asks which transcription factors (TFs), pathways, or gene sets are most active, enriched, up or down in expression data - bulk RNA-seq treated vs control, single-cell cell types or clusters, condition contrasts across donors (pseudobulk), spatial transcriptomics regions or niches, and pseudotime or differentiation trajectories - with the exact 2.x workflow (dc.op networks, dc.pp preprocessing, dc.mt scoring, dc.tl ranking) that reproduces the documented results. Also covers decoupler's networks (CollecTRI, PROGENy, DoRothEA, MSigDB), supported organisms/species and ortholog translation, resource licenses, and the conventions for plotting or visualizing its results. Also read for conceptual, best-practice or multiple-choice questions about how an agent should work with decoupler.
4
5
  ---
@@ -48,15 +49,15 @@ columns `source`, `target`, and optionally `weight`. The 2.x API is `dc.pp` (pre
48
49
 
49
50
  ## Pick the recipe from the goal
50
51
 
51
- | Goal | Recipe |
52
- |---|---|
53
- | Activity per cell, cluster or cell type, then "which sources mark group X" | **Per-observation** below |
54
- | Activity per spatial spot, region vs rest | **Spatial** below (smooth first) |
55
- | Sources that change along a trajectory or pseudotime | **Trajectory** below |
56
- | Condition A vs B in bulk RNA-seq (samples) | **Contrast** in `references/contrast.md` |
57
- | Condition A vs B in single-cell with several donors or samples | **Pseudobulk contrast** in `references/contrast.md` |
58
- | Networks, organisms, orthologs, licenses, what resources exist | `references/resources.md` |
59
- | Plotting results | Use `dc.pl.*` or scanpy plotting on the `get_obsm` AnnData, see `references/resources.md` |
52
+ | Goal | Recipe |
53
+ | -------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------- |
54
+ | Activity per cell, cluster or cell type, then "which sources mark group X" | **Per-observation** below |
55
+ | Activity per spatial spot, region vs rest | **Spatial** below (smooth first) |
56
+ | Sources that change along a trajectory or pseudotime | **Trajectory** below |
57
+ | Condition A vs B in bulk RNA-seq (samples) | **Contrast** in `references/contrast.md` |
58
+ | Condition A vs B in single-cell with several donors or samples | **Pseudobulk contrast** in `references/contrast.md` |
59
+ | Networks, organisms, orthologs, licenses, what resources exist | `references/resources.md` |
60
+ | Plotting results | Use `dc.pl.*` or scanpy plotting on the `get_obsm` AnnData, see `references/resources.md` |
60
61
 
61
62
  "Most active TFs in condition X vs Y" with replicate samples or donors means the contrast recipe
62
63
  (differential expression statistic → `ulm`), **not** per-cell scores averaged by condition and
@@ -5,14 +5,14 @@
5
5
  All return a long DataFrame with `source`, `target`, and `weight` (plus extra metadata columns
6
6
  that `dc.mt.*` ignores). Verify by running; downloads come from OmniPath and need network access.
7
7
 
8
- | Function | What | Notes |
9
- |---|---|---|
10
- | `dc.op.collectri(organism="human", remove_complexes=False)` | TF → target regulons (CollecTRI), signed weights | Default TF network in all 2.x vignettes |
11
- | `dc.op.dorothea(organism="human", levels=None)` | Older TF regulons with confidence levels A–E | Only when the user asks for DoRothEA |
12
- | `dc.op.progeny(organism="human", top=inf, thr_padj=0.05)` | 14 signalling pathways, weighted footprint genes | `top` defaults to all significant targets; do not add `top=500` |
13
- | `dc.op.hallmark(organism="human")` | MSigDB hallmark gene sets, unweighted | |
14
- | `dc.op.resource(name, organism="human")` | Any OmniPath annotation resource (e.g. `"PanglaoDB"`, `"SIGNOR"`, `"MSigDB"`) | You must rename columns to `source` and `target` yourself |
15
- | `dc.op.show_resources()` | DataFrame `name, license` of every resource | |
8
+ | Function | What | Notes |
9
+ | ----------------------------------------------------------- | ----------------------------------------------------------------------------- | --------------------------------------------------------------- |
10
+ | `dc.op.collectri(organism="human", remove_complexes=False)` | TF → target regulons (CollecTRI), signed weights | Default TF network in all 2.x vignettes |
11
+ | `dc.op.dorothea(organism="human", levels=None)` | Older TF regulons with confidence levels A–E | Only when the user asks for DoRothEA |
12
+ | `dc.op.progeny(organism="human", top=inf, thr_padj=0.05)` | 14 signalling pathways, weighted footprint genes | `top` defaults to all significant targets; do not add `top=500` |
13
+ | `dc.op.hallmark(organism="human")` | MSigDB hallmark gene sets, unweighted | |
14
+ | `dc.op.resource(name, organism="human")` | Any OmniPath annotation resource (e.g. `"PanglaoDB"`, `"SIGNOR"`, `"MSigDB"`) | You must rename columns to `source` and `target` yourself |
15
+ | `dc.op.show_resources()` | DataFrame `name, license` of every resource | |
16
16
 
17
17
  Custom gene sets: `dc.pp.read_gmt(path)` → `source, target` DataFrame. Any DataFrame with
18
18
  those columns works as `net`.
@@ -102,11 +102,11 @@ def _nesrank(
102
102
  pos_null_sum = pos_null_msk.sum()
103
103
  neg_null_sum = neg_null_msk.sum()
104
104
  if (es >= 0) and (pos_null_sum > 0):
105
- pval = (null[pos_null_msk] >= es).sum() / pos_null_sum
105
+ pval = ((null[pos_null_msk] >= es).sum() + 1) / (pos_null_sum + 1)
106
106
  pos_null_mean = null[pos_null_msk].mean()
107
107
  nes = es / pos_null_mean
108
108
  elif (es < 0) and (neg_null_sum > 0):
109
- pval = (null[neg_null_msk] <= es).sum() / neg_null_sum
109
+ pval = ((null[neg_null_msk] <= es).sum() + 1) / (neg_null_sum + 1)
110
110
  neg_null_mean = null[neg_null_msk].mean()
111
111
  nes = -es / neg_null_mean
112
112
  else:
@@ -199,12 +199,14 @@ def _func_gsea(
199
199
 
200
200
  .. math::
201
201
 
202
- p_{value}=\frac{ES_{rand} \geq ES}{P}
202
+ p_{value} = \begin{cases} \frac{1 + \#\{ES_{rand} \geq ES\}}{1 + P_{+}} & \text{if } ES \geq 0 \\ \frac{1 + \#\{ES_{rand} \leq ES\}}{1 + P_{-}} & \text{if } ES < 0 \end{cases}
203
203
 
204
204
  Where:
205
205
 
206
- - :math:`ES_{rand}` are the enrichment scores of the random permutations
207
- - :math:`P` is the total number of permutations
206
+ - :math:`ES_{rand}` are the enrichment scores of the random permutations with the same sign as :math:`ES`
207
+ - :math:`P_{+}` and :math:`P_{-}` are the numbers of random permutations with positive and negative scores
208
+
209
+ The observed score is counted as one of the permutations, so that :math:`p_{value}` is never 0 :cite:`phipson2010`.
208
210
 
209
211
  Additionaly, :math:`ES` is updated to a normalized enrichment score :math:`NES`.
210
212
 
@@ -33,7 +33,7 @@ def _fun(
33
33
  verbose: bool = False,
34
34
  ):
35
35
  @nb.njit(parallel=True, cache=True)
36
- def _f(mat, adj):
36
+ def _fp(mat, adj):
37
37
  nobs, nvar = mat.shape
38
38
  nvar, nsrc = adj.shape
39
39
  es = np.zeros((nobs, nsrc))
@@ -44,10 +44,22 @@ def _fun(
44
44
  es[i, j] = f(x, w)
45
45
  return es
46
46
 
47
- _f.__name__ = f.__name__
48
- if _f.__name__ not in _cfuncs:
49
- _cfuncs[f.__name__] = _f
50
- m = f"waggr - using {_f.__name__} for the first time, will need to be compiled"
47
+ # Serial version to be called inside parallel regions (e.g. _perm), nested parallelism crashes workqueue
48
+ @nb.njit(cache=True)
49
+ def _fs(mat, adj):
50
+ nobs, nvar = mat.shape
51
+ nvar, nsrc = adj.shape
52
+ es = np.zeros((nobs, nsrc))
53
+ for i in range(nobs):
54
+ x = mat[i]
55
+ for j in range(nsrc):
56
+ w = adj[:, j]
57
+ es[i, j] = f(x, w)
58
+ return es
59
+
60
+ if f.__name__ not in _cfuncs:
61
+ _cfuncs[f.__name__] = (_fp, _fs)
62
+ m = f"waggr - using {f.__name__} for the first time, will need to be compiled"
51
63
  _log(m, level="info", verbose=verbose)
52
64
 
53
65
 
@@ -223,7 +235,7 @@ def _func_waggr(
223
235
  else:
224
236
  f_fun = fun
225
237
  _validate_func(f_fun, verbose=verbose)
226
- vfun = _cfuncs[f_fun.__name__]
238
+ pfun, sfun = _cfuncs[f_fun.__name__]
227
239
  assert isinstance(times, int | float) and times >= 0, "times must be numeric and >= 0"
228
240
  assert isinstance(seed, int | float) and seed >= 0, "seed must be numeric and >= 0"
229
241
  times, seed = int(times), int(seed)
@@ -231,12 +243,12 @@ def _func_waggr(
231
243
  nvar, nsrc = adj.shape
232
244
  m = f"waggr - calculating scores for {nsrc} sources across {nobs} observations"
233
245
  _log(m, level="info", verbose=verbose)
234
- es = vfun(mat, adj)
246
+ es = pfun(mat, adj)
235
247
  if times > 1:
236
248
  m = f"waggr - comparing estimates against {times} random permutations"
237
249
  _log(m, level="info", verbose=verbose)
238
250
  idx = _ridx(times=times, nvar=nvar, seed=seed)
239
- es, pv = _perm(fun=vfun, es=es, mat=mat, adj=adj, idx=idx)
251
+ es, pv = _perm(fun=sfun, es=es, mat=mat, adj=adj, idx=idx)
240
252
  else:
241
253
  pv = np.ones(es.shape)
242
254
  return es, pv
@@ -72,9 +72,9 @@ def _func_zscore(
72
72
  m = f"zscore - calculating {nsrc} scores with flavor={flavor}"
73
73
  _log(m, level="info", verbose=verbose)
74
74
  stds = np.std(mat, axis=1, ddof=1)
75
- if flavor == "RoKAI":
75
+ if flavor == "KSEA":
76
76
  mean_all = np.mean(mat, axis=1)
77
- elif flavor == "KSEA":
77
+ elif flavor == "RoKAI":
78
78
  mean_all = np.zeros(stds.shape)
79
79
  n = np.sqrt(np.count_nonzero(adj, axis=0))
80
80
  mean = mat.dot(adj) / np.sum(np.abs(adj), axis=0)
@@ -59,6 +59,34 @@ def test_nesrank(
59
59
  nes, pval = dc.mt._gsea._nesrank.py_func(ridx=ridx, row=row, rnks=rnks, set_msk=set_msk, dec=dec, es=es)
60
60
  assert isinstance(nes, float)
61
61
  assert isinstance(pval, float)
62
+ # Two of the six permuted scores (0.9, 0, 0, 0, 0, 0.9) reach the observed score
63
+ assert np.isclose(pval, (2 + 1) / (6 + 1))
64
+
65
+
66
+ def test_gsea_pvalues_not_zero():
67
+ rng = np.random.default_rng(0)
68
+ nvar, times = 500, 100
69
+ row = rng.normal(size=nvar)
70
+ row[:20] += 5.0
71
+ cnct = np.arange(20)
72
+ starts, offsets = np.array([0]), np.array([20])
73
+ ridx = dc.mt._gsea._ridx(times=times, nvar=nvar, seed=42)
74
+ es, nes, pv = dc.mt._gsea._stsgsea.py_func(row=row, cnct=cnct, starts=starts, offsets=offsets, ridx=ridx)
75
+ assert es[0] > 0
76
+ # No permutation reaches the observed score, so the p-value is the smallest one the permutations support
77
+ order = np.argsort(-row)
78
+ set_msk = np.zeros(nvar, dtype=bool)
79
+ set_msk[cnct] = True
80
+ set_msk = set_msk[order]
81
+ dec = 1 / (nvar - 20)
82
+ null = np.array(
83
+ [
84
+ dc.mt._gsea._esrank.py_func(row=row[order], rnks=np.arange(nvar), set_msk=set_msk[i], dec=dec)[0]
85
+ for i in ridx
86
+ ]
87
+ )
88
+ assert (null < es[0]).all()
89
+ assert np.isclose(pv[0], 1 / ((null >= 0).sum() + 1))
62
90
 
63
91
 
64
92
  def test_stsgsea(