Skip to content

Commit c31a26c

Browse files
flying-sheepmeeseeksmachine
authored andcommitted
Backport PR scverse#3980: fix: handle all-zero genes in seurat_v3
1 parent 253825d commit c31a26c

4 files changed

Lines changed: 19 additions & 7 deletions

File tree

docs/release-notes/3980.fix.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Prevent segfault when running {func}`scanpy.pp.highly_variable_genes` with `flavor='seurat_v3{,_paper}'` and some all-zero genes {smaller}`P Angerer`

src/scanpy/_compat.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,8 @@ def warn(
113113
more_file_prefixes: tuple[str, ...] = (),
114114
) -> None:
115115
"""Issue a warning, skipping frames from certain file prefixes."""
116+
__tracebackhide__ = True
117+
116118
if not skip_file_prefixes:
117119
skip_file_prefixes = (*_FILE_PREFIXES, *more_file_prefixes)
118120
elif more_file_prefixes:

src/scanpy/preprocessing/_highly_variable_genes.py

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -183,14 +183,13 @@ def _highly_variable_genes_seurat_v3( # noqa: PLR0912, PLR0915
183183
# These get computed anyway for loess
184184
if isinstance(mean, DaskArray):
185185
mean, var = mean.compute(), var.compute()
186-
not_const = var > 0
187186
estimat_var = np.zeros(data.shape[1], dtype=np.float64)
188-
189-
y = np.log10(var[not_const])
190-
x = np.log10(mean[not_const])
191-
model = loess(x, y, span=span, degree=2)
192-
model.fit()
193-
estimat_var[not_const] = model.outputs.fitted_values
187+
if (not_const := var > 0).any():
188+
y = np.log10(var[not_const])
189+
x = np.log10(mean[not_const])
190+
model = loess(x, y, span=span, degree=2)
191+
model.fit()
192+
estimat_var[not_const] = model.outputs.fitted_values
194193
reg_std = np.sqrt(10**estimat_var)
195194

196195
# clip large values as in Seurat

tests/test_highly_variable_genes.py

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import numpy as np
1111
import pandas as pd
1212
import pytest
13+
import scipy.sparse as sps
1314
from anndata import AnnData
1415
from fast_array_utils import stats
1516
from pandas.testing import assert_frame_equal, assert_index_equal
@@ -522,6 +523,15 @@ def test_seurat_v3_warning():
522523
sc.pp.highly_variable_genes(pbmc, flavor="seurat_v3")
523524

524525

526+
@needs.skmisc
527+
def test_seurat_v3_degenerate() -> None:
528+
"""Tests that the flavor handles all-zero genes."""
529+
adata = AnnData(sps.random(10, 1000, density=0.001, format="csr", dtype="int"))
530+
adata.X.data = np.abs(adata.X.data)
531+
532+
sc.pp.highly_variable_genes(adata, flavor="seurat_v3")
533+
534+
525535
def test_batches():
526536
adata = pbmc68k_reduced()
527537
adata.X[:100, :100] = np.zeros((100, 100))

0 commit comments

Comments
 (0)