diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index f0632385..a929de94 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -23,10 +23,13 @@ jobs: python: [3.9, "3.10", "3.11"] os: [ubuntu-latest] include: - - python: 3.9 - os: macos-latest - python: "3.10" os: macos-latest + - python: "3.12" + os: macos-latest + pip-flags: "--pre" + name: "Python 3.12 (pre-release)" + env: OS: ${{ matrix.os }} PYTHON: ${{ matrix.python }} diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index c5e9d610..a84270c1 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -7,7 +7,7 @@ default_stages: minimum_pre_commit_version: 2.9.3 repos: - repo: https://github.com/pre-commit/mirrors-mypy - rev: v1.10.0 + rev: v1.10.1 hooks: - id: mypy additional_dependencies: [numpy, pandas, types-requests] @@ -46,7 +46,7 @@ repos: name: Check executable files use .sh extension types: [shell, executable] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.4.7 + rev: v0.5.0 hooks: - id: ruff types_or: [python, pyi, jupyter] diff --git a/src/squidpy/gr/_sepal.py b/src/squidpy/gr/_sepal.py index 6ca6b216..57a44cfd 100644 --- a/src/squidpy/gr/_sepal.py +++ b/src/squidpy/gr/_sepal.py @@ -100,7 +100,7 @@ def sepal( if max_neighs not in (4, 6): raise ValueError(f"Expected `max_neighs` to be either `4` or `6`, found `{max_neighs}`.") - spatial = adata.obsm[spatial_key].astype(np.float_) + spatial = adata.obsm[spatial_key].astype(np.float64) if genes is None: genes = adata.var_names.values @@ -169,8 +169,8 @@ def _score_helper( sat_idx: NDArrayA, unsat: NDArrayA, unsat_idx: NDArrayA, - dt: np.float_, - thresh: np.float_, + dt: float, + thresh: float, queue: SigQueue | None = None, ) -> NDArrayA: if max_neighs == 4: @@ -182,8 +182,8 @@ def _score_helper( score, sparse = [], issparse(vals) for i in ixs: - conc = vals[:, i].A.flatten() if sparse else vals[:, i].copy() # type: ignore[union-attr] - conc = vals[:, i].A.flatten() if sparse else vals[:, i].copy() # type: ignore[union-attr] + conc = vals[:, i].toarray().flatten() if sparse else vals[:, i].copy() # type: ignore[union-attr] + conc = vals[:, i].toarray().flatten() if sparse else vals[:, i].copy() # type: ignore[union-attr] time_iter = _diffusion(conc, fun, n_iter, sat, sat_idx, unsat, unsat_idx, dt=dt, thresh=thresh) score.append(dt * time_iter) @@ -199,7 +199,7 @@ def _score_helper( @njit(fastmath=True) def _diffusion( conc: NDArrayA, - laplacian: Callable[[NDArrayA, NDArrayA, NDArrayA], np.float_], + laplacian: Callable[[NDArrayA, NDArrayA, NDArrayA], float], n_iter: int, sat: NDArrayA, sat_idx: NDArrayA, @@ -320,7 +320,11 @@ def _get_sat_unsat_idx(g_indptr: NDArrayA, g_shape: int, sat_thresh: int) -> tup @njit def _get_nhood_idx( - sat: NDArrayA, unsat: NDArrayA, g_indptr: NDArrayA, g_indices: NDArrayA, sat_thresh: int + sat: NDArrayA, + unsat: NDArrayA, + g_indptr: NDArrayA, + g_indices: NDArrayA, + sat_thresh: int, ) -> tuple[NDArrayA, NDArrayA, NDArrayA]: """Get saturated and unsaturated neighborhood indices.""" # get saturated nhood indices diff --git a/src/squidpy/pl/_var_by_distance.py b/src/squidpy/pl/_var_by_distance.py index f0d511ab..e3a873ff 100644 --- a/src/squidpy/pl/_var_by_distance.py +++ b/src/squidpy/pl/_var_by_distance.py @@ -95,12 +95,17 @@ def var_by_distance( scatterplot_kwargs = dict(scatterplot_kwargs) df = adata.obsm[design_matrix_key] # get design matrix - df[var] = np.array(adata[:, var].X.A) if issparse(adata[:, var].X) else np.array(adata[:, var].X) # add var column + df[var] = ( + np.array(adata[:, var].X.toarray()) if issparse(adata[:, var].X) else np.array(adata[:, var].X) + ) # add var column # if several variables are plotted, make a panel grid if isinstance(var, list): fig, grid = _panel_grid( - hspace=0.25, wspace=0.75 / rcParams["figure.figsize"][0] + 0.02, ncols=4, num_panels=len(var) + hspace=0.25, + wspace=0.75 / rcParams["figure.figsize"][0] + 0.02, + ncols=4, + num_panels=len(var), ) axs = [] else: @@ -168,7 +173,14 @@ def var_by_distance( ) # if variable to plot on color palette is not categorical else: - plt.scatter(data=df, x=anchor_key, y=v, c=color, cmap=scatter_palette, **scatterplot_kwargs) + plt.scatter( + data=df, + x=anchor_key, + y=v, + c=color, + cmap=scatter_palette, + **scatterplot_kwargs, + ) if title is not None: ax.set(title=title) if axis_label is None: diff --git a/tests/graph/test_spatial_neighbors.py b/tests/graph/test_spatial_neighbors.py index c3d69875..73801940 100644 --- a/tests/graph/test_spatial_neighbors.py +++ b/tests/graph/test_spatial_neighbors.py @@ -21,7 +21,14 @@ class TestSpatialNeighbors: ] ) # ground-truth Delaunay graph - _gt_dgraph = np.array([[0.0, 1.0, 0.0, 1.0], [1.0, 0.0, 1.0, 1.0], [0.0, 1.0, 0.0, 1.0], [1.0, 1.0, 1.0, 0.0]]) + _gt_dgraph = np.array( + [ + [0.0, 1.0, 0.0, 1.0], + [1.0, 0.0, 1.0, 1.0], + [0.0, 1.0, 0.0, 1.0], + [1.0, 1.0, 1.0, 0.0], + ] + ) @staticmethod def _adata_concat(adata1, adata2): @@ -54,12 +61,12 @@ def test_spatial_neighbors_visium(self, visium_adata: AnnData, n_rings: int, n_n spatial_neighbors(adata_concat, library_key="library_id", n_rings=n_rings) assert adata_concat.obsp[Key.obsp.spatial_conn()][0].sum() == n_neigh np.testing.assert_array_equal( - adata_concat[adata_concat.obs["library_id"] == batch1].obsp[Key.obsp.spatial_conn()].A, - visium_adata.obsp[Key.obsp.spatial_conn()].A, + adata_concat[adata_concat.obs["library_id"] == batch1].obsp[Key.obsp.spatial_conn()].toarray(), + visium_adata.obsp[Key.obsp.spatial_conn()].toarray(), ) np.testing.assert_array_equal( - adata_concat[adata_concat.obs["library_id"] == batch2].obsp[Key.obsp.spatial_conn()].A, - visium_adata2.obsp[Key.obsp.spatial_conn()].A, + adata_concat[adata_concat.obs["library_id"] == batch2].obsp[Key.obsp.spatial_conn()].toarray(), + visium_adata2.obsp[Key.obsp.spatial_conn()].toarray(), ) @pytest.mark.parametrize(("n_rings", "n_neigh", "sum_neigh"), [(1, 4, 4), (2, 4, 12), (3, 4, 24)]) @@ -76,15 +83,21 @@ def test_spatial_neighbors_squaregrid(self, adata_squaregrid: AnnData, n_rings: adata2 = adata.copy() adata_concat, batch1, batch2 = TestSpatialNeighbors._adata_concat(adata, adata2) spatial_neighbors(adata2, n_neighs=n_neigh, n_rings=n_rings, coord_type="grid") - spatial_neighbors(adata_concat, library_key="library_id", n_neighs=n_neigh, n_rings=n_rings, coord_type="grid") + spatial_neighbors( + adata_concat, + library_key="library_id", + n_neighs=n_neigh, + n_rings=n_rings, + coord_type="grid", + ) assert np.diff(adata_concat.obsp[Key.obsp.spatial_conn()].indptr).max() == sum_neigh np.testing.assert_array_equal( - adata_concat[adata_concat.obs["library_id"] == batch1].obsp[Key.obsp.spatial_conn()].A, - adata.obsp[Key.obsp.spatial_conn()].A, + adata_concat[adata_concat.obs["library_id"] == batch1].obsp[Key.obsp.spatial_conn()].toarray(), + adata.obsp[Key.obsp.spatial_conn()].toarray(), ) np.testing.assert_array_equal( - adata_concat[adata_concat.obs["library_id"] == batch2].obsp[Key.obsp.spatial_conn()].A, - adata2.obsp[Key.obsp.spatial_conn()].A, + adata_concat[adata_concat.obs["library_id"] == batch2].obsp[Key.obsp.spatial_conn()].toarray(), + adata2.obsp[Key.obsp.spatial_conn()].toarray(), ) @pytest.mark.parametrize("type_rings", [("grid", 1), ("grid", 6), ("generic", 1)]) @@ -121,18 +134,18 @@ def test_spatial_neighbors_non_visium(self, non_visium_adata: AnnData): ) spatial_neighbors(non_visium_adata, n_neighs=3, coord_type=None) - spatial_graph = non_visium_adata.obsp[Key.obsp.spatial_conn()].A + spatial_graph = non_visium_adata.obsp[Key.obsp.spatial_conn()].toarray() np.testing.assert_array_equal(spatial_graph, correct_knn_graph) spatial_neighbors(non_visium_adata, radius=5.0, coord_type=None) - spatial_graph = non_visium_adata.obsp[Key.obsp.spatial_conn()].A + spatial_graph = non_visium_adata.obsp[Key.obsp.spatial_conn()].toarray() np.testing.assert_array_equal(spatial_graph, correct_radius_graph) spatial_neighbors(non_visium_adata, delaunay=True, coord_type=None) - spatial_graph = non_visium_adata.obsp[Key.obsp.spatial_conn()].A - spatial_dist = non_visium_adata.obsp[Key.obsp.spatial_dist()].A + spatial_graph = non_visium_adata.obsp[Key.obsp.spatial_conn()].toarray() + spatial_dist = non_visium_adata.obsp[Key.obsp.spatial_dist()].toarray() np.testing.assert_array_equal(spatial_graph, self._gt_dgraph) np.testing.assert_allclose(spatial_dist, self._gt_ddist) @@ -144,12 +157,12 @@ def test_spatial_neighbors_non_visium(self, non_visium_adata: AnnData): spatial_neighbors(non_visium_adata2, delaunay=True, coord_type=None) np.testing.assert_array_equal( - adata_concat[adata_concat.obs["library_id"] == batch1].obsp[Key.obsp.spatial_conn()].A, - non_visium_adata.obsp[Key.obsp.spatial_conn()].A, + adata_concat[adata_concat.obs["library_id"] == batch1].obsp[Key.obsp.spatial_conn()].toarray(), + non_visium_adata.obsp[Key.obsp.spatial_conn()].toarray(), ) np.testing.assert_array_equal( - adata_concat[adata_concat.obs["library_id"] == batch2].obsp[Key.obsp.spatial_conn()].A, - non_visium_adata2.obsp[Key.obsp.spatial_conn()].A, + adata_concat[adata_concat.obs["library_id"] == batch2].obsp[Key.obsp.spatial_conn()].toarray(), + non_visium_adata2.obsp[Key.obsp.spatial_conn()].toarray(), ) @pytest.mark.parametrize("set_diag", [False, True]) @@ -166,9 +179,15 @@ def test_radius_min_max(self, non_visium_adata: AnnData, radius: tuple[float, fl ixs = np.arange(len(gt_dgraph)) gt_dgraph[ixs, ixs] = 1.0 - spatial_neighbors(non_visium_adata, delaunay=True, coord_type=None, radius=radius, set_diag=set_diag) - spatial_dist = non_visium_adata.obsp[Key.obsp.spatial_dist()].A - spatial_graph = non_visium_adata.obsp[Key.obsp.spatial_conn()].A + spatial_neighbors( + non_visium_adata, + delaunay=True, + coord_type=None, + radius=radius, + set_diag=set_diag, + ) + spatial_dist = non_visium_adata.obsp[Key.obsp.spatial_dist()].toarray() + spatial_graph = non_visium_adata.obsp[Key.obsp.spatial_conn()].toarray() np.testing.assert_allclose(spatial_graph, gt_dgraph) np.testing.assert_allclose(spatial_dist, gt_ddist) @@ -180,8 +199,8 @@ def test_copy(self, non_visium_adata: AnnData): assert isspmatrix_csr(dist) assert Key.obsp.spatial_conn() not in non_visium_adata.obsp assert Key.obsp.spatial_dist() not in non_visium_adata.obsp - np.testing.assert_allclose(dist.A, self._gt_ddist) - np.testing.assert_allclose(conn.A, self._gt_dgraph) + np.testing.assert_allclose(dist.toarray(), self._gt_ddist) + np.testing.assert_allclose(conn.toarray(), self._gt_dgraph) @pytest.mark.parametrize("percentile", [99.0, 95.0]) def test_percentile_filtering(self, adata_hne: AnnData, percentile: float, coord_type="generic"): diff --git a/tests/graph/test_utils.py b/tests/graph/test_utils.py index c0eeb364..6cbb3eef 100644 --- a/tests/graph/test_utils.py +++ b/tests/graph/test_utils.py @@ -15,12 +15,12 @@ class TestUtils: def test_shuffle_group(self, cluster_annotations_type: type, library_annotations_type: type, seed: int): size = 6 rng = np.random.default_rng(seed) - if cluster_annotations_type == int: + if isinstance(cluster_annotations_type, int): libraries = pd.Series(rng.choice([1, 2, 3, 4], size=(size,)), dtype="category") else: libraries = pd.Series(rng.choice(["a", "b", "c"], size=(size,)), dtype="category") - if library_annotations_type == int: + if isinstance(library_annotations_type, int): cluster_annotations = rng.choice([1, 2, 3, 4], size=(size,)) else: cluster_annotations = rng.choice(["X", "Y", "Z"], size=(size,)) diff --git a/tests/image/test_container.py b/tests/image/test_container.py index 815360f2..14334287 100644 --- a/tests/image/test_container.py +++ b/tests/image/test_container.py @@ -1060,9 +1060,9 @@ def test_explicit(self, z: int): @pytest.mark.parametrize("typ", [list, dict]) def test_set(self, typ: type, unique: bool): if unique: - new_ids = ["0", "1"] if typ == list else {"a": "0", "b": "1"} + new_ids = ["0", "1"] if isinstance(typ, list) else {"a": "0", "b": "1"} else: - new_ids = ["0", "0"] if typ == list else {"a": "b"} + new_ids = ["0", "0"] if isinstance(typ, list) else {"a": "b"} img = ImageContainer(np.random.normal(size=(2, 3, 4, 5)), dims=["z", "y", "x", "c"], library_id=["a", "b"]) if not unique: