scPTR / tests /test_deep_data.py
bryan7264's picture
Add files using upload-large-folder tool
9d901ad verified
Raw
History Blame Contribute Delete
3.42 kB
"""Tests for DeepPTR data loading utilities."""
import numpy as np
import pytest
import torch
from anndata import AnnData
from scptr.deep._data import setup_dataloaders
from scptr.deep._utils import get_library_sizes
@pytest.fixture
def simple_adata():
"""AnnData with spliced/unspliced counts."""
rng = np.random.RandomState(42)
n, g = 100, 20
s = rng.poisson(5, size=(n, g)).astype(np.float32)
u = rng.poisson(2, size=(n, g)).astype(np.float32)
adata = AnnData(X=s)
adata.layers["spliced"] = s
adata.layers["unspliced"] = u
adata.obs["cell_type"] = [f"type_{i % 3}" for i in range(n)]
adata.obs["cell_type"] = adata.obs["cell_type"].astype("category")
return adata
class TestGetLibrarySizes:
def test_shapes(self, simple_adata):
l_u, l_s = get_library_sizes(simple_adata)
assert l_u.shape == (simple_adata.n_obs,)
assert l_s.shape == (simple_adata.n_obs,)
def test_positive(self, simple_adata):
l_u, l_s = get_library_sizes(simple_adata)
assert (l_u >= 1.0).all()
assert (l_s >= 1.0).all()
def test_correct_sums(self, simple_adata):
l_u, l_s = get_library_sizes(simple_adata)
expected_s = simple_adata.layers["spliced"].sum(axis=1)
expected_u = simple_adata.layers["unspliced"].sum(axis=1)
np.testing.assert_allclose(l_s, np.clip(expected_s, 1.0, None), rtol=1e-5)
np.testing.assert_allclose(l_u, np.clip(expected_u, 1.0, None), rtol=1e-5)
def test_missing_layer_raises(self):
adata = AnnData(X=np.zeros((5, 3)))
with pytest.raises(KeyError, match="Missing required layer"):
get_library_sizes(adata)
class TestSetupDataloaders:
def test_returns_four(self, simple_adata):
train_dl, val_dl, train_idx, val_idx = setup_dataloaders(
simple_adata, batch_size=16, val_frac=0.2, seed=0
)
assert isinstance(train_dl, torch.utils.data.DataLoader)
assert isinstance(val_dl, torch.utils.data.DataLoader)
assert len(train_idx) + len(val_idx) == simple_adata.n_obs
def test_no_overlap(self, simple_adata):
_, _, train_idx, val_idx = setup_dataloaders(
simple_adata, batch_size=16, val_frac=0.2, seed=0
)
assert len(set(train_idx) & set(val_idx)) == 0
def test_batch_contents(self, simple_adata):
train_dl, _, _, _ = setup_dataloaders(
simple_adata, batch_size=16, val_frac=0.1, seed=0
)
s, u, l_s, l_u = next(iter(train_dl))
assert s.ndim == 2
assert u.ndim == 2
assert l_s.ndim == 1
assert l_u.ndim == 1
assert s.shape[1] == simple_adata.n_vars
def test_stratified_split(self, simple_adata):
_, _, train_idx, val_idx = setup_dataloaders(
simple_adata,
batch_size=16,
val_frac=0.2,
stratify_key="cell_type",
seed=0,
)
# All cell types should appear in both splits
train_types = set(simple_adata.obs["cell_type"].values[train_idx])
val_types = set(simple_adata.obs["cell_type"].values[val_idx])
assert train_types == val_types
def test_reproducible(self, simple_adata):
_, _, idx1, _ = setup_dataloaders(simple_adata, seed=42)
_, _, idx2, _ = setup_dataloaders(simple_adata, seed=42)
np.testing.assert_array_equal(idx1, idx2)