1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
|
from __future__ import annotations
import warnings
from importlib.util import find_spec
import numpy as np
import pandas as pd
import pytest
from numba.core.errors import NumbaDeprecationWarning
from anndata import AnnData, ImplicitModificationWarning, read_h5ad
from anndata.io import read_loom
from anndata.tests.helpers import gen_typed_df_t2_size
X_ = np.arange(12).reshape((3, 4))
L = np.arange(12).reshape((3, 4)) + 12
@pytest.fixture(params=[X_, None])
def X(request):
return request.param
def test_creation(X: np.ndarray | None):
adata = AnnData(X=X, layers=dict(L=L.copy()))
assert list(adata.layers.keys()) == ["L"]
assert "L" in adata.layers
assert "X" not in adata.layers
assert "some_other_thing" not in adata.layers
assert (adata.layers["L"] == L).all()
assert adata.shape == L.shape
def test_views():
adata = AnnData(X=X_, layers=dict(L=L.copy()))
adata_view = adata[1:, 1:]
assert adata_view.layers.is_view
assert adata_view.layers.parent_mapping == adata.layers
assert adata_view.layers.keys() == adata.layers.keys()
assert (adata_view.layers["L"] == adata.layers["L"][1:, 1:]).all()
adata.layers["S"] = X_
assert adata_view.layers.keys() == adata.layers.keys()
assert (adata_view.layers["S"] == adata.layers["S"][1:, 1:]).all()
with pytest.warns(ImplicitModificationWarning):
adata_view.layers["T"] = X_[1:, 1:]
assert not adata_view.layers.is_view
assert not adata_view.is_view
@pytest.mark.parametrize(
("df", "homogenous", "dtype"),
[
(lambda: gen_typed_df_t2_size(*X_.shape), True, np.object_),
(lambda: pd.DataFrame(X_**2), False, np.int_),
],
)
def test_set_dataframe(homogenous, df, dtype):
adata = AnnData(X_)
if homogenous:
with pytest.warns(UserWarning, match=r"Layer 'df'.*dtype object"):
adata.layers["df"] = df()
else:
with warnings.catch_warnings():
warnings.simplefilter("error")
adata.layers["df"] = df()
assert isinstance(adata.layers["df"], np.ndarray)
assert np.issubdtype(adata.layers["df"].dtype, dtype)
def test_readwrite(X: np.ndarray | None, backing_h5ad):
adata = AnnData(X=X, layers=dict(L=L.copy()))
adata.write(backing_h5ad)
adata_read = read_h5ad(backing_h5ad)
assert adata.layers.keys() == adata_read.layers.keys()
assert (adata.layers["L"] == adata_read.layers["L"]).all()
@pytest.mark.skipif(find_spec("loompy") is None, reason="loompy not installed")
def test_readwrite_loom(tmp_path):
loom_path = tmp_path / "test.loom"
adata = AnnData(X=X_, layers=dict(L=L.copy()))
with warnings.catch_warnings():
warnings.filterwarnings("ignore", category=NumbaDeprecationWarning)
# loompy uses “is” for ints
warnings.filterwarnings("ignore", category=SyntaxWarning)
warnings.filterwarnings(
"ignore",
message=r"datetime.datetime.utcnow\(\) is deprecated",
category=DeprecationWarning,
)
adata.write_loom(loom_path)
adata_read = read_loom(loom_path, X_name="")
assert adata.layers.keys() == adata_read.layers.keys()
assert (adata.layers["L"] == adata_read.layers["L"]).all()
def test_backed():
# backed mode for layers isn’t implemented, layers stay in memory
pass
def test_copy():
adata = AnnData(X=X_, layers=dict(L=L.copy()))
bdata = adata.copy()
# check that we don’t create too many references
assert bdata._layers is bdata.layers._data
# check that we have a copy
adata.layers["L"] += 10
assert np.all(adata.layers["L"] != bdata.layers["L"]) # 201
def test_shape_error():
adata = AnnData(X=X_)
with pytest.raises(
ValueError,
match=(
r"Value passed for key 'L' is of incorrect shape\. "
r"Values of layers must match dimensions \('obs', 'var'\) of parent\. "
r"Value had shape \(4, 4\) while it should have had \(3, 4\)\."
),
):
adata.layers["L"] = np.zeros((X_.shape[0] + 1, X_.shape[1]))
|