Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,12 @@ lint.pydocstyle.convention = "numpy"
addopts = [
"--import-mode=importlib", # allow using test files with same name
]
filterwarnings = [
"error",
"ignore:Writing zarr v2 data will no longer be the default",
"ignore:Only some AnnData objects have `.raw` attribute",
"ignore::scipy.sparse.SparseEfficiencyWarning",
]
strict = true
testpaths = [ "tests" ]

Expand Down
5 changes: 2 additions & 3 deletions src/mudata/_core/mudata.py
Original file line number Diff line number Diff line change
Expand Up @@ -1405,7 +1405,7 @@ def _pull_attr(

# prepend modality prefix to column names if requested via arguments and there are no skipped modalities with
# the same column name (prefixing those columns may cause problems with future pulls or pushes)
mod_df.rename(
mod_df = mod_df.rename(
columns={
col.derived_name: col.name
for col in modcols
Expand All @@ -1420,8 +1420,7 @@ def _pull_attr(
)
and derived_name_count[col.derived_name] == col.count
)
},
inplace=True,
}
)

# reorder modality DF to conform to global order
Expand Down
4 changes: 2 additions & 2 deletions tests/test_accessors.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import json
from dataclasses import fields
from importlib import resources
from importlib import metadata, resources
from urllib.request import urlopen

import anndata as ad
Expand All @@ -13,7 +13,7 @@

import mudata as md

if Version(ad.__version__) < Version("0.13dev0"):
if Version(metadata.version("anndata")) < Version("0.13dev0"):
pytest.skip("anndata version too old, no accessor support", allow_module_level=True)

from mudata.acc import A
Expand Down
2 changes: 1 addition & 1 deletion tests/test_from_to.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ def test_from_anndata(rng: np.random.Generator):
adata.var["feature_types"] = rng.choice(["mod1", "mod2", "mod3"], size=adata.n_vars)
mdata = MuData(adata)
assert mdata.n_mod == 3
assert sorted(mdata.mod_names) == ["mod1", "mod2", "mod3"]
assert sorted(mdata.mod.keys()) == ["mod1", "mod2", "mod3"]
for m, mod in mdata.mod.items():
assert (mod.var_names == adata.var_names[adata.var.feature_types == m]).all()
2 changes: 1 addition & 1 deletion tests/test_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ def test_h5mu_backed_to_memory(mdata: md.MuData, filepath_h5mu: str | Path):
mdata_.filename = None
assert not mdata_.isbacked

for modname in mdata.mod_names:
for modname in mdata.mod:
assert isinstance(mdata_.mod[modname].X, np.ndarray) or issparse(mdata_.mod[modname].X)
assert (mdata_.mod[modname].X == mdata.mod[modname].X).all()

Expand Down
2 changes: 1 addition & 1 deletion tests/test_merge.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def test_merge(mdata_nouniqueobs: md.MuData, filepath_h5mu: str | Path, roundtri
mdata_.write_h5mu(filepath_h5mu)
mdata_ = md.read_h5mu(filepath_h5mu)
assert list(mdata_.mod.keys()) == ["mod1", "mod2"]
for m in mdata_.mod_names:
for m in mdata_.mod:
assert mdata_.mod[m].shape == mdata_nouniqueobs.mod[m].shape
assert np.array_equal(mdata_.mod["mod1"].X, mdata_nouniqueobs.mod["mod1"].X)
assert np.array_equal(mdata_.mod["mod2"].X, mdata_nouniqueobs.mod["mod2"].X)
4 changes: 3 additions & 1 deletion tests/test_obs_var.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def test_set_obs_names(mdata: md.MuData): # https://github.com/scverse/mudata/i
mdata.obs = pd.DataFrame()


@pytest.mark.filterwarnings("ignore:.*obs_vector.*deprecated:FutureWarning")
def test_obs_vector(mdata: md.MuData):
assert (mdata.obs["arange"] == mdata.obs_vector("arange")).all()
with pytest.raises(KeyError, match="There is no key foo in MuData"):
Expand Down Expand Up @@ -97,6 +98,7 @@ def test_set_var_names(mdata: md.MuData): # https://github.com/scverse/mudata/i
mdata.var = pd.DataFrame()


@pytest.mark.filterwarnings("ignore:.*var_vector.*deprecated:FutureWarning")
def test_var_vector(rng: np.random.Generator, mdata: md.MuData):
mdata.var["test"] = rng.uniform(size=mdata.n_vars)
assert (mdata.var["test"] == mdata.var_vector("test")).all()
Expand All @@ -117,7 +119,7 @@ def test_names_make_unique(mdata: md.MuData):
namesattr = f"{oattr}_names"
namesfun = getattr(mdata, f"{oattr}_names_make_unique")

mods = mdata.mod_names
mods = list(mdata.mod.keys())
names = getattr(mdata.mod[mods[0]], namesattr)
nameslist = names.to_list()
nameslist[1] = nameslist[0]
Expand Down
2 changes: 2 additions & 0 deletions tests/test_pull_push.py
Comment thread
flying-sheep marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ def mdata(
i1 = i + 1
m = f"mod{i1}"
mods[m] = AnnData(X=rng.normal(size=1000 * i1).reshape(-1, 10 * i1))
mods[m].obs_names = f"{m}-" + mods[m].obs_names
mods[m].var_names = f"{m}-" + mods[m].var_names
mods[m].obs["mod"] = m
mods[m].var["mod"] = m
mods[m].obs["assert-bool"] = True
Expand Down
4 changes: 2 additions & 2 deletions tests/test_repr.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ def test_repr(mdata: md.MuData):
assert rep[1].lstrip().startswith("obs:")

for col in mdata.obs.columns:
if not any(col.startswith(f"{mod}:") for mod in mdata.mod_names):
if not any(col.startswith(f"{mod}:") for mod in mdata.mod):
assert col in rep[1]
for col in mdata.var.columns:
if not any(col.startswith(f"{mod}:") for mod in mdata.mod_names):
if not any(col.startswith(f"{mod}:") for mod in mdata.mod):
assert col in rep[2]

assert rep[2].strip() == f"{mdata.n_mod} modalities"
Expand Down
47 changes: 26 additions & 21 deletions tests/test_update.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@
type Axis = Literal[0, 1]


pytestmark = [
pytest.mark.filterwarnings(r"ignore:(obs|var)_names.*not unique"),
pytest.mark.filterwarnings(r"ignore:Duplicated (obs|var)_names should not be present in different modalities"),

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe this filter should only be applied if mod != 'unique'?

]


@pytest.fixture(params=(0, 1))
def axis(request: pytest.FixtureRequest) -> Axis:
return request.param
Expand Down Expand Up @@ -60,30 +66,29 @@ def modalities(
if across != "intersecting":
raise NotImplementedError("Tests for non-intersecting obs_names are not implemented")

if mod:
if mod == "duplicated":
obsnames2 = mods["mod2"].obs_names.to_numpy()
obsnames3 = mods["mod3"].obs_names.to_numpy()
varnames2 = mods["mod2"].var_names.to_numpy()
varnames3 = mods["mod3"].var_names.to_numpy()
obsnames2[0] = obsnames2[1] = obsnames3[1] = "testobs"
varnames2[0] = varnames2[1] = varnames3[1] = "testvar"
mods["mod2"].obs_names = obsnames2
mods["mod3"].obs_names = obsnames3
mods["mod2"].var_names = varnames2
mods["mod3"].var_names = varnames3
elif mod == "extreme_duplicated": # integer overflow: https://github.com/scverse/mudata/issues/107
obsnames2 = mods["mod2"].obs_names.to_numpy()
varnames2 = mods["mod2"].var_names.to_numpy()
obsnames2[:-1] = obsnames2[0] = "testobs"
varnames2[:-1] = varnames2[0] = "testvar"
mods["mod2"].obs_names = obsnames2
mods["mod2"].var_names = varnames2
if mod == "duplicated":
obsnames2 = mods["mod2"].obs_names.to_numpy()
obsnames3 = mods["mod3"].obs_names.to_numpy()
varnames2 = mods["mod2"].var_names.to_numpy()
varnames3 = mods["mod3"].var_names.to_numpy()
obsnames2[0] = obsnames2[1] = obsnames3[1] = "testobs"
varnames2[0] = varnames2[1] = varnames3[1] = "testvar"
mods["mod2"].obs_names = obsnames2
mods["mod3"].obs_names = obsnames3
mods["mod2"].var_names = varnames2
mods["mod3"].var_names = varnames3
elif mod == "extreme_duplicated": # integer overflow: https://github.com/scverse/mudata/issues/107
obsnames2 = mods["mod2"].obs_names.to_numpy()
varnames2 = mods["mod2"].var_names.to_numpy()
obsnames2[:-1] = obsnames2[0] = "testobs"
varnames2[:-1] = varnames2[0] = "testvar"
mods["mod2"].obs_names = obsnames2
mods["mod2"].var_names = varnames2

return mods


def add_mdata_global_columns(md: MuData, rng: np.random.Generator):
def add_mdata_global_columns(md: MuData, rng: np.random.Generator) -> MuData:
md.obs["batch"] = rng.choice(["a", "b", "c"], size=md.shape[0])
md.var["batch"] = rng.choice(["d", "e", "f"], size=md.shape[1])

Expand Down Expand Up @@ -130,7 +135,7 @@ def assert_dtypes(df: pd.DataFrame):
assert pd.api.types.is_integer_dtype(df["dtype-int"])
assert pd.api.types.is_float_dtype(df["dtype-float"])
assert pd.api.types.is_bool_dtype(df["dtype-bool"])
assert pd.api.types.is_categorical_dtype(df["dtype-categorical"])
assert isinstance(df["dtype-categorical"].array, pd.Categorical)
assert pd.api.types.is_string_dtype(df["batch"]) or df["batch"].dtype == object


Expand Down
1 change: 1 addition & 0 deletions tests/test_view_copy.py
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ def _test_view_after_setattr(mdata: md.MuData, mdata_ref: md.MuData, skip: Seque
assert (v.columns == mdata_ref.varm[k].columns).all()


@pytest.mark.filterwarnings("ignore::anndata.ImplicitModificationWarning")
def test_view_setattr(mdata_with_obsp: md.MuData):
view = mdata_with_obsp[:42, :]
view.obs_names = [f"foo_{i}" for i in range(len(view))]
Expand Down