scib-metrics 0.5.3__tar.gz → 0.5.4__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 (78) hide show
  1. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/.pre-commit-config.yaml +1 -1
  2. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/CHANGELOG.md +12 -0
  3. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/PKG-INFO +1 -1
  4. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/pyproject.toml +1 -1
  5. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/benchmark/_core.py +2 -2
  6. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/metrics/_kbet.py +47 -46
  7. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/tests/test_benchmarker.py +14 -0
  8. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/.codecov.yaml +0 -0
  9. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/.cruft.json +0 -0
  10. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/.editorconfig +0 -0
  11. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/.github/ISSUE_TEMPLATE/bug_report.yml +0 -0
  12. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  13. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/.github/ISSUE_TEMPLATE/feature_request.yml +0 -0
  14. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/.github/workflows/build.yaml +0 -0
  15. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/.github/workflows/release.yaml +0 -0
  16. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/.github/workflows/test_linux.yaml +0 -0
  17. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/.github/workflows/test_linux_cuda.yaml +0 -0
  18. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/.github/workflows/test_linux_pre.yaml +0 -0
  19. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/.github/workflows/test_macos.yaml +0 -0
  20. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/.github/workflows/test_macos_m1.yaml +0 -0
  21. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/.github/workflows/test_windows.yaml +0 -0
  22. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/.gitignore +0 -0
  23. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/.readthedocs.yaml +0 -0
  24. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/LICENSE +0 -0
  25. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/README.md +0 -0
  26. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/docs/Makefile +0 -0
  27. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/docs/_static/.gitkeep +0 -0
  28. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/docs/_static/css/custom.css +0 -0
  29. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/docs/_templates/.gitkeep +0 -0
  30. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/docs/_templates/autosummary/class.rst +0 -0
  31. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/docs/_templates/class_no_inherited.rst +0 -0
  32. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/docs/api.md +0 -0
  33. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/docs/changelog.md +0 -0
  34. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/docs/conf.py +0 -0
  35. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/docs/contributing.md +0 -0
  36. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/docs/extensions/.gitkeep +0 -0
  37. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/docs/extensions/typed_returns.py +0 -0
  38. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/docs/index.md +0 -0
  39. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/docs/notebooks/large_scale.ipynb +0 -0
  40. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/docs/notebooks/lung_example.ipynb +0 -0
  41. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/docs/references.bib +0 -0
  42. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/docs/references.md +0 -0
  43. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/docs/template_usage.md +0 -0
  44. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/docs/tutorials.md +0 -0
  45. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/setup.py +0 -0
  46. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/__init__.py +0 -0
  47. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/_settings.py +0 -0
  48. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/_types.py +0 -0
  49. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/benchmark/__init__.py +0 -0
  50. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/metrics/__init__.py +0 -0
  51. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/metrics/_graph_connectivity.py +0 -0
  52. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/metrics/_isolated_labels.py +0 -0
  53. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/metrics/_lisi.py +0 -0
  54. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/metrics/_nmi_ari.py +0 -0
  55. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/metrics/_pcr_comparison.py +0 -0
  56. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/metrics/_silhouette.py +0 -0
  57. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/nearest_neighbors/__init__.py +0 -0
  58. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/nearest_neighbors/_dataclass.py +0 -0
  59. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/nearest_neighbors/_jax.py +0 -0
  60. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/nearest_neighbors/_pynndescent.py +0 -0
  61. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/utils/__init__.py +0 -0
  62. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/utils/_diffusion_nn.py +0 -0
  63. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/utils/_dist.py +0 -0
  64. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/utils/_kmeans.py +0 -0
  65. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/utils/_lisi.py +0 -0
  66. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/utils/_pca.py +0 -0
  67. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/utils/_pcr.py +0 -0
  68. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/utils/_silhouette.py +0 -0
  69. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/src/scib_metrics/utils/_utils.py +0 -0
  70. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/tests/__init__.py +0 -0
  71. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/tests/test_metrics.py +0 -0
  72. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/tests/test_neighbors.py +0 -0
  73. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/tests/test_pcr_comparison.py +0 -0
  74. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/tests/utils/__init__.py +0 -0
  75. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/tests/utils/data.py +0 -0
  76. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/tests/utils/sampling.py +0 -0
  77. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/tests/utils/test_pca.py +0 -0
  78. {scib_metrics-0.5.3 → scib_metrics-0.5.4}/tests/utils/test_pcr.py +0 -0
@@ -11,7 +11,7 @@ repos:
11
11
  hooks:
12
12
  - id: prettier
13
13
  - repo: https://github.com/astral-sh/ruff-pre-commit
14
- rev: v0.9.6
14
+ rev: v0.11.6
15
15
  hooks:
16
16
  - id: ruff
17
17
  types_or: [python, pyi, jupyter]
@@ -10,6 +10,18 @@ and this project adheres to [Semantic Versioning][].
10
10
 
11
11
  ## 0.6.0 (unreleased)
12
12
 
13
+ ## 0.5.4 (2025-04-23)
14
+
15
+ ### Fixed
16
+
17
+ - Apply default values for benchmarker metrics {pr}`203`.
18
+
19
+ ## 0.5.3 (2025-02-17)
20
+
21
+ ### Removed
22
+
23
+ - Reverted a change that was needed for scib-autotune in scvi-tools {pr}`189`.
24
+
13
25
  ## 0.5.2 (2025-02-13)
14
26
 
15
27
  ### Added
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: scib-metrics
3
- Version: 0.5.3
3
+ Version: 0.5.4
4
4
  Summary: Accelerated and Python-only scIB metrics
5
5
  Project-URL: Documentation, https://scib-metrics.readthedocs.io/
6
6
  Project-URL: Source, https://github.com/yoseflab/scib-metrics
@@ -5,7 +5,7 @@ requires = ["hatchling"]
5
5
 
6
6
  [project]
7
7
  name = "scib-metrics"
8
- version = "0.5.3"
8
+ version = "0.5.4"
9
9
  description = "Accelerated and Python-only scIB metrics"
10
10
  readme = "README.md"
11
11
  requires-python = ">=3.10"
@@ -136,8 +136,8 @@ class Benchmarker:
136
136
  batch_key: str,
137
137
  label_key: str,
138
138
  embedding_obsm_keys: list[str],
139
- bio_conservation_metrics: BioConservation | None,
140
- batch_correction_metrics: BatchCorrection | None,
139
+ bio_conservation_metrics: BioConservation | None = BioConservation(),
140
+ batch_correction_metrics: BatchCorrection | None = BatchCorrection(),
141
141
  pre_integrated_embedding_obsm_key: str | None = None,
142
142
  n_jobs: int = 1,
143
143
  progress_bar: bool = True,
@@ -138,8 +138,14 @@ def kbet_per_label(
138
138
  conn_graph = X.knn_graph_connectivities
139
139
 
140
140
  # prepare call of kBET per cluster
141
- kbet_scores = {"cluster": [], "kBET": []}
142
- for clus in np.unique(labels):
141
+ clusters = []
142
+ clusters, counts = np.unique(labels, return_counts=True)
143
+ skipped = clusters[counts > 10]
144
+ clusters = clusters[counts <= 10]
145
+ kbet_scores = {"cluster": list(skipped), "kBET": [np.nan] * len(skipped)}
146
+ logger.info(f"{len(skipped)} clusters consist of a single batch or are too small. Skip.")
147
+
148
+ for clus in clusters:
143
149
  # subset by label
144
150
  mask = labels == clus
145
151
  conn_graph_sub = conn_graph[mask, :][:, mask]
@@ -147,60 +153,55 @@ def kbet_per_label(
147
153
  n_obs = conn_graph_sub.shape[0]
148
154
  batches_sub = batches[mask]
149
155
 
150
- # check if neighborhood size too small or only one batch in subset
151
- if np.logical_or(n_obs < 10, len(np.unique(batches_sub)) == 1):
152
- logger.info(f"{clus} consists of a single batch or is too small. Skip.")
153
- score = np.nan
154
- else:
155
- quarter_mean = np.floor(np.mean(pd.Series(batches_sub).value_counts()) / 4).astype("int")
156
- k0 = np.min([70, np.max([10, quarter_mean])])
157
- # check k0 for reasonability
158
- if k0 * n_obs >= size_max:
159
- k0 = np.floor(size_max / n_obs).astype("int")
156
+ quarter_mean = np.floor(np.mean(pd.Series(batches_sub).value_counts()) / 4).astype("int")
157
+ k0 = np.min([70, np.max([10, quarter_mean])])
158
+ # check k0 for reasonability
159
+ if k0 * n_obs >= size_max:
160
+ k0 = np.floor(size_max / n_obs).astype("int")
161
+
162
+ n_comp, labs = scipy.sparse.csgraph.connected_components(conn_graph_sub, connection="strong")
163
+
164
+ if n_comp == 1: # a single component to compute kBET on
165
+ try:
166
+ diffusion_n_comps = np.min([diffusion_n_comps, n_obs - 1])
167
+ nn_graph_sub = diffusion_nn(conn_graph_sub, k=k0, n_comps=diffusion_n_comps)
168
+ # call kBET
169
+ score, _, _ = kbet(
170
+ nn_graph_sub,
171
+ batches=batches_sub,
172
+ alpha=alpha,
173
+ )
174
+ except ValueError:
175
+ logger.info("Diffusion distance failed. Skip.")
176
+ score = 0 # i.e. 100% rejection
160
177
 
161
- n_comp, labs = scipy.sparse.csgraph.connected_components(conn_graph_sub, connection="strong")
178
+ else:
179
+ # check the number of components where kBET can be computed upon
180
+ comp_size = pd.Series(labs).value_counts()
181
+ # check which components are small
182
+ comp_size_thresh = 3 * k0
183
+ idx_nonan = np.flatnonzero(np.in1d(labs, comp_size[comp_size >= comp_size_thresh].index))
184
+
185
+ # check if 75% of all cells can be used for kBET run
186
+ if len(idx_nonan) / len(labs) >= 0.75:
187
+ # create another subset of components, assume they are not visited in a diffusion process
188
+ conn_graph_sub_sub = conn_graph_sub[idx_nonan, :][:, idx_nonan]
189
+ conn_graph_sub_sub.sort_indices()
162
190
 
163
- if n_comp == 1: # a single component to compute kBET on
164
191
  try:
165
- diffusion_n_comps = np.min([diffusion_n_comps, n_obs - 1])
166
- nn_graph_sub = diffusion_nn(conn_graph_sub, k=k0, n_comps=diffusion_n_comps)
192
+ diffusion_n_comps = np.min([diffusion_n_comps, conn_graph_sub_sub.shape[0] - 1])
193
+ nn_results_sub_sub = diffusion_nn(conn_graph_sub_sub, k=k0, n_comps=diffusion_n_comps)
167
194
  # call kBET
168
195
  score, _, _ = kbet(
169
- nn_graph_sub,
170
- batches=batches_sub,
196
+ nn_results_sub_sub,
197
+ batches=batches_sub[idx_nonan],
171
198
  alpha=alpha,
172
199
  )
173
200
  except ValueError:
174
201
  logger.info("Diffusion distance failed. Skip.")
175
202
  score = 0 # i.e. 100% rejection
176
-
177
- else:
178
- # check the number of components where kBET can be computed upon
179
- comp_size = pd.Series(labs).value_counts()
180
- # check which components are small
181
- comp_size_thresh = 3 * k0
182
- idx_nonan = np.flatnonzero(np.in1d(labs, comp_size[comp_size >= comp_size_thresh].index))
183
-
184
- # check if 75% of all cells can be used for kBET run
185
- if len(idx_nonan) / len(labs) >= 0.75:
186
- # create another subset of components, assume they are not visited in a diffusion process
187
- conn_graph_sub_sub = conn_graph_sub[idx_nonan, :][:, idx_nonan]
188
- conn_graph_sub_sub.sort_indices()
189
-
190
- try:
191
- diffusion_n_comps = np.min([diffusion_n_comps, conn_graph_sub_sub.shape[0] - 1])
192
- nn_results_sub_sub = diffusion_nn(conn_graph_sub_sub, k=k0, n_comps=diffusion_n_comps)
193
- # call kBET
194
- score, _, _ = kbet(
195
- nn_results_sub_sub,
196
- batches=batches_sub[idx_nonan],
197
- alpha=alpha,
198
- )
199
- except ValueError:
200
- logger.info("Diffusion distance failed. Skip.")
201
- score = 0 # i.e. 100% rejection
202
- else: # if there are too many too small connected components, set kBET score to 0
203
- score = 0 # i.e. 100% rejection
203
+ else: # if there are too many too small connected components, set kBET score to 0
204
+ score = 0 # i.e. 100% rejection
204
205
 
205
206
  kbet_scores["cluster"].append(clus)
206
207
  kbet_scores["kBET"].append(score)
@@ -21,6 +21,20 @@ def test_benchmarker():
21
21
  bm.plot_results_table()
22
22
 
23
23
 
24
+ def test_benchmarker_default():
25
+ ad, emb_keys, batch_key, labels_key = dummy_benchmarker_adata()
26
+ bm = Benchmarker(
27
+ ad,
28
+ batch_key,
29
+ labels_key,
30
+ emb_keys,
31
+ )
32
+ bm.benchmark()
33
+ results = bm.get_results()
34
+ assert isinstance(results, pd.DataFrame)
35
+ bm.plot_results_table()
36
+
37
+
24
38
  def test_benchmarker_custom_metric_booleans():
25
39
  bioc = BioConservation(
26
40
  isolated_labels=False, nmi_ari_cluster_labels_leiden=False, silhouette_label=False, clisi_knn=True
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes