def test_spot_crops_as_array_return_obs(self, adata: AnnData, cont: ImageContainer, as_array: bool, return_obs: bool): cont.add_img(np.random.normal(size=(cont.shape + (4, ))), channel_dim="foobar", layer="baz") diameter = adata.uns["spatial"][Key.uns.library_id( adata, "spatial")]["scalefactors"]["spot_diameter_fullres"] radius = int(round(diameter // 2)) size = (2 * radius + 1, 2 * radius + 1) for crop in cont.generate_spot_crops(adata, as_array=as_array, return_obs=return_obs, spatial_key="spatial"): crop, obs = crop if return_obs else (crop, None) if obs is not None: assert obs in adata.obs_names if not as_array: assert Key.img.obs in crop.data.attrs if as_array is True: assert isinstance(crop, dict), type(crop) for key in cont: assert key in crop assert crop[key].shape == (*size, cont[key].data.shape[-1]) elif isinstance(as_array, str): assert isinstance(crop, np.ndarray) assert crop.shape == (*size, cont[as_array].data.shape[-1]) else: assert isinstance(crop, ImageContainer) assert crop.shape == size
def test_equal_crops_as_array(self, small_cont: ImageContainer, as_array: bool): small_cont.add_img(np.random.normal(size=(small_cont.shape + (1, ))), channel_dim="foobar", layer="baz") for crop in small_cont.generate_equal_crops(size=11, as_array=as_array): if as_array: if isinstance(as_array, bool): assert isinstance(crop, dict) for key in small_cont: assert key in crop assert crop[key].shape == ( 11, 11, small_cont[key].data.shape[-1]) elif isinstance(as_array, str): assert isinstance(crop, np.ndarray) assert crop.shape == (11, 11, small_cont[as_array].data.shape[-1]) else: assert isinstance(crop, tuple) assert len(crop) == len(as_array) for key, data in zip(as_array, crop): assert isinstance(data, np.ndarray) assert data.shape == (11, 11, small_cont[key].data.shape[-1]) else: assert isinstance(crop, ImageContainer) for key in (Key.img.coords, Key.img.padding, Key.img.scale, Key.img.mask_circle): assert key in crop.data.attrs, key assert crop.shape == (11, 11)
def test_uncrop_too_small_requested_shape(self, small_cont_1c: ImageContainer): crops = list(small_cont_1c.generate_equal_crops(size=13)) with pytest.raises(ValueError, match=r"Requested final image shape"): ImageContainer.uncrop(crops, shape=(small_cont_1c.shape[0] - 1, small_cont_1c.shape[1] - 1))
def test_xarray_remapping_spatial_dims(self): cont = ImageContainer(np.empty((100, 10))) cont.add_img(xr.DataArray(np.empty((100, 10)), dims=["foo", "bar"]), layer="baz") assert "baz" in cont assert len(cont) == 2 assert cont["baz"].dims == ("y", "x", "channels")
def test_array_dtypes(self, array: Union[np.ndarray, xr.DataArray]): img = ImageContainer(array) np.testing.assert_array_equal(img["image"].data, array) assert img["image"].data.dtype == array.dtype img = ImageContainer(xr.DataArray(array)) np.testing.assert_array_equal(img["image"].data, array) assert img["image"].data.dtype == array.dtype
def test_image_autoincrement(self, small_cont_1c: ImageContainer): assert len(small_cont_1c) == 1 for _ in range(20): small_cont_1c.add_img(np.empty(small_cont_1c.shape)) assert len(small_cont_1c) == 21 for i in range(20): assert f"image_{i}" in small_cont_1c
def test_add_img_invalid_yx(self, small_cont_1c: ImageContainer): arr = xr.DataArray(np.empty( (small_cont_1c.shape[0] - 1, small_cont_1c.shape[1])), dims=["y", "x"]) with pytest.raises( ValueError, match= r".*be aligned because they have different dimension sizes"): small_cont_1c.add_img(arr)
def test_padding_left_right(self, small_cont_1c: ImageContainer): dim1, dim2, _ = small_cont_1c["image"].data.shape crop = small_cont_1c.crop_center(dim1 // 2, 0, dim1 // 2) data = crop["image"].data np.testing.assert_array_equal(data[:, :dim2 // 2], 0) crop = small_cont_1c.crop_center(dim1 // 2, dim2, dim1 // 2) data = crop["image"].data np.testing.assert_array_equal(data[:, dim2 // 2:], 0)
def _download(self, fpath: PathLike, backup_url: str, **kwargs: Any) -> Any: from squidpy.im import ImageContainer # type: ignore[attr-defined] check_presence_download(Path(fpath), backup_url) img = ImageContainer() img.add_img(fpath, layer="image", **kwargs) return img
def test_repr_html(self, size: int): cont = ImageContainer() for _ in range(size): cont.add_img(np.empty((10, 10))) validator = SimpleHTMLValidator( n_expected_rows=min(size, 10), expected_tags=set() if not size else {"p", "em", "strong"}) validator.feed(cont._repr_html_()) validator.validate()
def test_padding_top_bottom(self, small_cont_1c: ImageContainer): dim1, dim2, _ = small_cont_1c["image"].data.shape crop = small_cont_1c.crop_center(dim1, dim2 // 2, dim1 // 2) data = crop["image"].data np.testing.assert_array_equal(data[dim1 // 2:, :], 0) crop = small_cont_1c.crop_center(0, dim2 // 2, dim1 // 2) data = crop["image"].data np.testing.assert_array_equal(data[:dim2 // 2, :], 0)
def test_get_size(self): cont = ImageContainer(np.empty((10, 10))) ry, rx = cont._get_size(None) assert (ry, rx) == cont.shape ry, rx = cont._get_size((None, 1)) assert (ry, rx) == (cont.shape[0], 1) ry, rx = cont._get_size((-1, None)) assert (ry, rx) == (-1, cont.shape[1])
def test_crop_corner_scale(self, scale: float): shape_img = (50, 50) img = ImageContainer(np.zeros(shape_img)) if scale <= 0: with pytest.raises( ValueError, match=r"Expected `scale` to be positive, found `0`."): img.crop_corner(10, 10, size=20, scale=scale) else: crop = img.crop_corner(10, 10, size=20, scale=scale) assert crop.shape == tuple(int(i * scale) for i in (20, 20))
def test_uncrop_preserves_shape(self, small_cont_1c: ImageContainer): small_cont_1c.add_img(np.random.normal(size=(small_cont_1c.shape + (4, ))), channel_dim="foobar", layer="baz") crops = list(small_cont_1c.generate_equal_crops(size=13)) uncrop = ImageContainer.uncrop(crops) np.testing.assert_array_equal(small_cont_1c.shape, uncrop.shape) for key in small_cont_1c: np.testing.assert_array_equal(uncrop[key], small_cont_1c[key])
def test_crop_scale(self, cont_dot: ImageContainer): # crop with scaling mask = np.random.randint(low=0, high=10, size=cont_dot.shape) cont_dot.add_img(mask, layer="image_1", channel_dim="mask") crop = cont_dot.crop_center(y=50, x=20, radius=10, cval=5, scale=0.5) assert "image_0" in crop assert "image_1" in crop np.testing.assert_array_equal(crop.data["image_0"].shape, (21 // 2, 21 // 2, 10)) np.testing.assert_array_equal(crop.data["image_1"].shape, (21 // 2, 21 // 2, 1))
def test_copy(self, deep: bool): cont = ImageContainer(np.random.normal(size=(10, 10))) sentinel = object() cont.data.attrs["sentinel"] = sentinel copy = cont.copy(deep=deep) if deep: assert not np.shares_memory(copy["image"].values, cont["image"].values) assert copy.data.attrs["sentinel"] is not sentinel else: assert np.shares_memory(copy["image"].values, cont["image"].values) assert copy.data.attrs["sentinel"] is sentinel
def test_plot_add_image(self, qtbot, adata: AnnData, napari_cont: ImageContainer): from napari.layers import Image viewer = napari_cont.interactive(adata) cnt = viewer._controller img = np.zeros((*napari_cont.shape, 3), dtype=np.float32) img[..., 0] = 1.0 # all red image napari_cont.add_img(img, layer="foobar") cnt.add_image("foobar") assert viewer._controller.view.layernames == {"V1_Adult_Mouse_Brain", "foobar"} assert isinstance(viewer._controller.view.layers["foobar"], Image) viewer.screenshot(dpi=DPI)
def test_crop_multiple_images(self, cont_dot: ImageContainer): mask = np.random.randint(low=0, high=10, size=cont_dot.shape) cont_dot.add_img(mask, layer="image_1", channel_dim="mask") crop = cont_dot.crop_center( y=50, x=20, radius=0, cval=5, ) assert "image_0" in crop assert "image_1" in crop np.testing.assert_array_equal(crop.data["image_0"].shape, (1, 1, 10)) np.testing.assert_array_equal(crop.data["image_1"].shape, (1, 1, 1))
def test_save_load_zarr(self, tmpdir): img = ImageContainer(np.random.normal(size=(100, 100, 1))) img.data.attrs["scale"] = 42 img.save(Path(tmpdir) / "foo") img2 = ImageContainer.load(Path(tmpdir) / "foo") np.testing.assert_array_equal(img["image"].values, img2["image"].values) np.testing.assert_array_equal(img.data.dims, img2.data.dims) np.testing.assert_array_equal(sorted(img.data.attrs.keys()), sorted(img2.data.attrs.keys())) for k, v in img.data.attrs.items(): assert type(v) == type(img2.data.attrs[k]) # noqa: E721 assert v == img2.data.attrs[k]
def test_plot_symbol(self, qtbot, adata: AnnData, napari_cont: ImageContainer): viewer = napari_cont.interactive(adata, symbol="square") cnt = viewer._controller cnt.add_points(adata.obs_vector(adata.var_names[42]), layer_name="foo") viewer.screenshot(dpi=DPI)
def test_plot_obs_categorical(self, qtbot, adata: AnnData, napari_cont: ImageContainer): viewer = napari_cont.interactive(adata) cnt = viewer._controller cnt.add_points(adata.obs["leiden"], key="leiden", layer_name="quas") viewer.screenshot(dpi=DPI)
def test_plot_cont_cmap(self, qtbot, adata: AnnData, napari_cont: ImageContainer): viewer = napari_cont.interactive(adata, cmap="inferno") cnt = viewer._controller cnt.add_points(adata.obs_vector(adata.var_names[42]), layer_name="wex") viewer.screenshot(dpi=DPI)
def test_padding_bottom_left(self, small_cont_1c: ImageContainer): crop = small_cont_1c.crop_center(small_cont_1c.shape[1], 0, 10) data = crop["image"].data assert crop.shape == (21, 21) np.testing.assert_array_equal(data[10:, :10], 0) np.testing.assert_array_equal(data[:10, 10:] != 0, True)
def test_plot_obs_continuous(self, qtbot, adata: AnnData, napari_cont: ImageContainer): viewer = napari_cont.interactive(adata) cnt = viewer._controller cnt.add_points(np.random.RandomState(42).normal(size=adata.n_obs), layer_name="quux") viewer.screenshot(dpi=DPI)
def test_add_img(self, shape1: Tuple[int, ...], shape2: Tuple[int, ...]): img_orig = np.random.randint(low=0, high=255, size=shape1, dtype=np.uint8) cont = ImageContainer(img_orig, layer="img_orig") img_new = np.random.randint(low=0, high=255, size=shape2, dtype=np.uint8) cont.add_img(img_new, layer="img_new", channel_dim="mask") assert "img_orig" in cont assert "img_new" in cont np.testing.assert_array_equal(np.squeeze(cont.data["img_new"]), np.squeeze(img_new))
def test_empty_initialization(self): img = ImageContainer() assert not len(img) assert isinstance(img.data, xr.Dataset) assert img.shape == (0, 0) assert str(img) assert repr(img)
def test_add_img_channel_dim(self, small_cont_1c: ImageContainer, channel_dim: str, n_channels: int): arr = np.random.normal(size=(*small_cont_1c.shape, n_channels)) if channel_dim == "channels" and n_channels == 3: with pytest.raises( ValueError, match= r".*be aligned because they have different dimension sizes" ): small_cont_1c.add_img(arr, channel_dim=channel_dim) else: small_cont_1c.add_img(arr, channel_dim=channel_dim, layer="bar") assert len(small_cont_1c) == 2 assert "bar" in small_cont_1c assert small_cont_1c["bar"].dims == ("y", "x", channel_dim) np.testing.assert_array_equal(small_cont_1c["bar"], arr)
def test_crop_center_radius(self, small_cont_1c: ImageContainer, ry: Optional[Union[int, float]], rx: Optional[Union[int, float]]): crop = small_cont_1c.crop_center(0, 0, radius=(ry, rx)) sy = int(ry * small_cont_1c.shape[0]) if isinstance(ry, float) else ry sx = int(rx * small_cont_1c.shape[1]) if isinstance(rx, float) else rx assert crop.shape == (2 * sy + 1, 2 * sx + 1)
def test_plot_crop_corner(self, qtbot, adata: AnnData, napari_cont: ImageContainer): viewer = napari_cont.crop_center(500, 500, radius=250).interactive(adata) bdata = viewer.adata cnt = viewer._controller cnt.add_points(bdata.obs_vector(bdata.var_names[42]), layer_name="foo") viewer.screenshot(dpi=DPI)
def test_spot_crops_obs_names(self, adata: AnnData, cont: ImageContainer, n_names: Optional[int]): obs = adata.obs_names[:n_names] if isinstance(n_names, int) else adata.obs_names crops = list(cont.generate_spot_crops(adata, obs_names=obs)) assert len(crops) == len(obs) for crop, o in zip(crops, obs): assert crop.data.attrs[Key.img.obs] == o