Skip to content

Commit d0fd0a3

Browse files
nbjusticeflying-sheep
authored andcommitted
Backport PR #4031: fix: copy connectivities before passing to umap-learn
1 parent 51cfd82 commit d0fd0a3

3 files changed

Lines changed: 17 additions & 1 deletion

File tree

docs/release-notes/4031.fix.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{func}`scanpy.tl.umap` no longer silently mutates `adata.obsp['connectivities']` via a shared sparse buffer {smaller}`N Justice`

src/scanpy/tools/_umap.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ def umap( # noqa: PLR0913, PLR0915
216216
n_epochs = default_epochs if maxiter is None else maxiter
217217
x_umap, _ = simplicial_set_embedding(
218218
data=x,
219-
graph=neighbors["connectivities"].tocoo(),
219+
graph=neighbors["connectivities"].tocoo(copy=True),
220220
n_components=n_components,
221221
initial_alpha=alpha,
222222
a=a,

tests/test_embedding.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,21 @@ def test_umap_init_paga(layout):
7575
sc.tl.umap(pbmc, init_pos="paga")
7676

7777

78+
def test_umap_preserves_connectivities():
79+
# https://github.com/scverse/scanpy/issues/4028
80+
pbmc = pbmc68k_reduced()[:100, :].copy()
81+
conn = pbmc.obsp["connectivities"]
82+
data_before = conn.data.copy()
83+
nnz_before = conn.nnz
84+
85+
sc.tl.umap(pbmc)
86+
87+
assert_array_equal(data_before, conn.data)
88+
assert conn.nnz == nnz_before
89+
assert (conn.data == 0).sum() == 0, "CSR should have no explicit zeros"
90+
assert "X_umap" in pbmc.obsm
91+
92+
7893
def test_diffmap():
7994
pbmc = pbmc68k_reduced()
8095

0 commit comments

Comments
 (0)