diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index fe11351eb..fa73b526d 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -31,8 +31,8 @@ jobs:
python-version: '3.10'
- name: Cache pre-commit
- uses: actions/cache@v4
if: ${{ matrix.lint-kind == 'code' }}
+ uses: actions/cache@v4
with:
path: ~/.cache/pre-commit
key: pre-commit-${{ env.pythonLocation }}-${{ hashFiles('**/.pre-commit-config.yaml') }}
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 11ceffbf1..0447993dd 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -19,11 +19,11 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest]
- python: ['3.8', '3.10', '3.11']
+ python: ['3.9', '3.10', '3.11', '3.12']
slepc: [noslepc]
include:
- - os: macos-latest
- python: '3.9'
+ - os: macos-14
+ python: '3.10'
slepc: noslepc
- os: ubuntu-latest
python: '3.10'
@@ -41,11 +41,17 @@ jobs:
python -m pip install --upgrade pip
python -m pip install tox
+ - name: Setup Conda
+ if: runner.os == 'macOS'
+ uses: conda-incubator/setup-miniconda@v3
+ with:
+ auto-update-conda: true
+
- name: Test
run: |
- tox -e py${{ matrix.python }}-${{ matrix.slepc }} -vv
+ tox -e py${{ matrix.python }}-${{ matrix.slepc }} -v
env:
- PYTEST_ADDOPTS: -vv
+ PYTEST_ADDOPTS: -v
- name: Upload coverage
uses: codecov/codecov-action@v4
diff --git a/.gitignore b/.gitignore
index 048a0b41c..fe6618f3d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -168,3 +168,6 @@ docs/api/_autosummary
# tests
tests/figures
+
+# Ruff
+.ruff_cache
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index f6fdd2adc..90fe1d785 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -7,22 +7,22 @@ default_stages:
minimum_pre_commit_version: 3.0.0
repos:
- repo: https://github.com/psf/black
- rev: 23.3.0
+ rev: 24.8.0
hooks:
- id: black
additional_dependencies: [toml]
- repo: https://github.com/timothycrosley/isort
- rev: 5.12.0
+ rev: 5.13.2
hooks:
- id: isort
additional_dependencies: [toml]
- repo: https://github.com/macisamuele/language-formatters-pre-commit-hooks
- rev: v2.9.0
+ rev: v2.14.0
hooks:
- id: pretty-format-yaml
args: [--autofix, --indent, '2']
- repo: https://github.com/pre-commit/pre-commit-hooks
- rev: v4.4.0
+ rev: v4.6.0
hooks:
- id: check-merge-conflict
- id: check-ast
@@ -37,27 +37,27 @@ repos:
- id: check-yaml
- id: check-toml
- repo: https://github.com/asottile/pyupgrade
- rev: v3.4.0
+ rev: v3.17.0
hooks:
- id: pyupgrade
args: [--py3-plus, --py38-plus, --keep-runtime-typing]
- repo: https://github.com/asottile/blacken-docs
- rev: 1.13.0
+ rev: 1.18.0
hooks:
- id: blacken-docs
- additional_dependencies: [black==23.1.0]
+ additional_dependencies: [black==24.8.0]
- repo: https://github.com/rstcheck/rstcheck
- rev: v6.1.2
+ rev: v6.2.4
hooks:
- id: rstcheck
additional_dependencies: [tomli]
args: [--config=pyproject.toml]
- repo: https://github.com/PyCQA/doc8
- rev: v1.1.1
+ rev: v1.1.2
hooks:
- id: doc8
-- repo: https://github.com/charliermarsh/ruff-pre-commit
- rev: v0.0.270
+- repo: https://github.com/astral-sh/ruff-pre-commit
+ rev: v0.6.5
hooks:
- id: ruff
args: [--fix, --exit-non-zero-on-fix]
diff --git a/docs/_ext/typed_returns.py b/docs/_ext/typed_returns.py
index 73fa7459c..9e9f8f24b 100644
--- a/docs/_ext/typed_returns.py
+++ b/docs/_ext/typed_returns.py
@@ -1,5 +1,5 @@
import re
-from typing import Iterable, Iterator, List
+from collections.abc import Iterable, Iterator
from sphinx.application import Sphinx
from sphinx.ext.napoleon import NumpyDocstring
@@ -18,9 +18,9 @@ def process_return(lines: Iterable[str]) -> Iterator[str]:
yield line
-def _parse_returns_section(self: NumpyDocstring, section: str) -> List[str]:
+def _parse_returns_section(self: NumpyDocstring, section: str) -> list[str]:
lines_raw = list(process_return(self._dedent(self._consume_to_next_section())))
- lines: List[str] = self._format_block(":returns: ", lines_raw)
+ lines: list[str] = self._format_block(":returns: ", lines_raw)
if lines and lines[-1]:
lines.append("")
return lines
diff --git a/docs/about/cite.rst b/docs/about/cite.rst
index 01af543ca..5640e4e84 100644
--- a/docs/about/cite.rst
+++ b/docs/about/cite.rst
@@ -6,15 +6,12 @@ CellRank's :class:`~cellrank.kernels.VelocityKernel` with classical RNA velocity
.. code-block:: bibtex
@article{lange:22,
- title = {CellRank for directed single-cell fate mapping},
- author = {Lange, Marius and Bergen, Volker and Klein, Michal and Setty, Manu and
- Reuter, Bernhard and Bakhti, Mostafa and Lickert, Heiko and
- Ansari, Meshal and Schniering, Janine and Schiller, Herbert B. and
- Pe'er, Dana and Theis, Fabian J.},
- journal = {Nat. Methods},
- year = {2022},
- doi = {10.1038/s41592-021-01346-6},
- publisher = {Nature Publishing Group}
+ author = {Lange, Marius and Bergen, Volker and Klein, Michal and Setty, Manu and Reuter, Bernhard and Bakhti, Mostafa and Lickert, Heiko and Ansari, Meshal and Schniering, Janine and Schiller, Herbert B. and Pe'er, Dana and Theis, Fabian J.},
+ publisher = {Nature Publishing Group},
+ doi = {10.1038/s41592-021-01346-6},
+ journal = {Nat. Methods},
+ title = {CellRank for directed single-cell fate mapping},
+ year = {2022},
}
If you are using the :class:`~cellrank.kernels.PseudotimeKernel`, :class:`~cellrank.kernels.CytoTRACEKernel`, :class:`~cellrank.kernels.RealTimeKernel`, or the :class:`~cellrank.kernels.VelocityKernel` with velocities inferred
@@ -23,15 +20,18 @@ from metabolic labeling data using the CellRank 2 approach, cite :cite:`weiler:2
.. code-block:: bibtex
@article{weiler:24,
- title = {CellRank 2: unified fate mapping in multiview single-cell data},
- author = {Weiler, Philipp and Lange, Marius and Klein, Michal and Pe{\textquotesingle}er, Dana and Theis, Fabian},
- doi = {10.1038/s41592-024-02303-9},
- url = {https://doi.org/10.1038/s41592-024-02303-9},
- year = {2024},
- journal = {Nature Methods},
- volume = {21},
- number = {7},
- pages = {1196--1205},
+ author = {Weiler, Philipp and Lange, Marius and Klein, Michal and Pe'er, Dana and Theis, Fabian},
+ publisher = {Springer Science and Business Media LLC},
+ url = {https://doi.org/10.1038/s41592-024-02303-9},
+ doi = {10.1038/s41592-024-02303-9},
+ issn = {1548-7105},
+ journal = {Nature Methods},
+ month = jun,
+ number = {7},
+ pages = {1196--1205},
+ title = {CellRank 2: unified fate mapping in multiview single-cell data},
+ volume = {21},
+ year = {2024},
}
In addition, if you use the :class:`~cellrank.estimators.GPCCA` estimator to compute initial, terminal or intermediate
@@ -42,12 +42,12 @@ please cite GPCCA :cite:`reuter:19` as:
.. code-block:: bibtex
@article{reuter:19,
- author = {Reuter,Bernhard and Fackeldey,Konstantin and Weber,Marcus },
- title = {Generalized Markov modeling of nonreversible molecular kinetics},
- journal = {The Journal of Chemical Physics},
- volume = {150},
- number = {17},
- pages = {174103},
- year = {2019},
- doi = {10.1063/1.5064530},
+ author = {Reuter, Bernhard and Fackeldey, Konstantin and Weber, Marcus},
+ doi = {10.1063/1.5064530},
+ journal = {The Journal of Chemical Physics},
+ number = {17},
+ pages = {174103},
+ title = {Generalized Markov modeling of nonreversible molecular kinetics},
+ volume = {150},
+ year = {2019},
}
diff --git a/docs/notebooks b/docs/notebooks
index 6777840bc..5fa07d4b6 160000
--- a/docs/notebooks
+++ b/docs/notebooks
@@ -1 +1 @@
-Subproject commit 6777840bcc146924d208c0b9b02677da63620805
+Subproject commit 5fa07d4b68f14ee9a26506fb56d87cba4f25f505
diff --git a/docs/references.bib b/docs/references.bib
index 2754e6a91..76ae75ea9 100644
--- a/docs/references.bib
+++ b/docs/references.bib
@@ -804,16 +804,16 @@ @article{bastidas:17
}
@article{weiler:24,
- title = {CellRank 2: unified fate mapping in multiview single-cell data},
- volume = {21},
- ISSN = {1548-7105},
- url = {http://dx.doi.org/10.1038/s41592-024-02303-9},
- DOI = {10.1038/s41592-024-02303-9},
- number = {7},
- journal = {Nature Methods},
- publisher = {Springer Science and Business Media LLC},
- author = {Weiler, Philipp and Lange, Marius and Klein, Michal and Pe'er, Dana and Theis, Fabian},
- year = {2024},
- month = jun,
- pages = {1196--1205}
+ author = {Weiler, Philipp and Lange, Marius and Klein, Michal and Pe'er, Dana and Theis, Fabian},
+ publisher = {Springer Science and Business Media LLC},
+ url = {http://dx.doi.org/10.1038/s41592-024-02303-9},
+ doi = {10.1038/s41592-024-02303-9},
+ issn = {1548-7105},
+ journal = {Nature Methods},
+ month = jun,
+ number = {7},
+ pages = {1196--1205},
+ title = {CellRank 2: unified fate mapping in multiview single-cell data},
+ volume = {21},
+ year = {2024},
}
diff --git a/pyproject.toml b/pyproject.toml
index a144f3bb7..1999d7631 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -7,7 +7,7 @@ name = "cellrank"
dynamic = ["version"]
description = "CellRank: dynamics from multi-view single-cell data"
readme = "README.rst"
-requires-python = ">=3.8"
+requires-python = ">=3.9"
license = {file = "LICENSE"}
classifiers = [
"Development Status :: 5 - Production/Stable",
@@ -19,10 +19,10 @@ classifiers = [
"Operating System :: Microsoft :: Windows",
"Typing :: Typed",
"Programming Language :: Python :: 3",
- "Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
+ "Programming Language :: Python :: 3.12",
"Topic :: Scientific/Engineering :: Bio-Informatics",
"Topic :: Scientific/Engineering :: Mathematics",
"Topic :: Scientific/Engineering :: Visualization",
@@ -69,8 +69,7 @@ dev = [
"tox>=4",
]
test = [
- "pytest>=7,<8.1.0",
- "pytest-xdist>=3",
+ "pytest>=8",
"pytest-mock>=3.5.0",
"pytest-cov>=4",
"coverage[toml]>=7",
@@ -106,7 +105,10 @@ include-package-data = true
[tool.setuptools_scm]
[tool.ruff]
-target-version = "py38"
+target-version = "py39"
+line-length = 120
+
+[tool.ruff.lint]
exclude = [
".eggs",
".git",
@@ -136,7 +138,6 @@ ignore = [
# Missing docstring in magic method
"D105",
]
-line-length = 120
select = [
"D", # flake8-docstrings
"E", # pycodestyle
@@ -154,21 +155,21 @@ select = [
"T20", # flake8-print
"RET", # flake8-raise
]
-unfixable = ["B", "UP", "C4", "BLE", "T20", "RET"]
-[tool.ruff.per-file-ignores]
+unfixable = ["B", "C4", "BLE", "T20", "RET"]
+[tool.ruff.lint.per-file-ignores]
"tests/*" = ["D"]
"*/__init__.py" = ["F401"]
"docs/*" = ["D"]
-[tool.ruff.pydocstyle]
+[tool.ruff.lint.pydocstyle]
convention = "numpy"
-[tool.ruff.flake8-tidy-imports]
+[tool.ruff.lint.flake8-tidy-imports]
ban-relative-imports = "all"
-[tool.ruff.flake8-quotes]
+[tool.ruff.lint.flake8-quotes]
inline-quotes = "double"
[tool.black]
line-length = 120
-target-version = ['py38']
+target-version = ['py39']
include = '\.pyi?$'
[tool.isort]
@@ -237,7 +238,7 @@ legacy_tox_ini = """
# TODO(michalk8): upgrade to `tox>=4.0` once `tox-conda` supports it
requires = tox-conda
isolated_build = true
-envlist = lint-code,py{3.8,3.9,3.10,3.11}-{slepc,noslepc}
+envlist = lint-code,py{3.9,3.10,3.11,3.12}-{slepc,noslepc}
skip_missing_interpreters = true
[testenv]
diff --git a/src/cellrank/_utils/_colors.py b/src/cellrank/_utils/_colors.py
index 3ca195e0d..ac16054fa 100644
--- a/src/cellrank/_utils/_colors.py
+++ b/src/cellrank/_utils/_colors.py
@@ -1,4 +1,5 @@
-from typing import Any, List, Optional, Sequence, Tuple, Union
+from collections.abc import Sequence
+from typing import Any, Optional, Union
import numpy as np
import pandas as pd
@@ -11,14 +12,14 @@
def _create_colors(
- base_color: Union[str, Tuple[float, float, float]],
+ base_color: Union[str, tuple[float, float, float]],
n: int,
- hue_range: Optional[Tuple[float, float]] = (-0.1, 0.1),
- saturation_range: Optional[Tuple[float, float]] = (-0.3, 0.3),
- value_range: Optional[Tuple[float, float]] = (-0.3, 0.3),
+ hue_range: Optional[tuple[float, float]] = (-0.1, 0.1),
+ saturation_range: Optional[tuple[float, float]] = (-0.3, 0.3),
+ value_range: Optional[tuple[float, float]] = (-0.3, 0.3),
convert_to_rgb: bool = True,
as_hex: bool = True,
-) -> List[Any]:
+) -> list[Any]:
"""Create variations of colors from base color.
Parameters
@@ -74,7 +75,7 @@ def _create_colors(
return res[::2] # we've created twice as many colors, select every other
-def _convert_to_hex_colors(cols: Sequence[Any]) -> List[str]:
+def _convert_to_hex_colors(cols: Sequence[Any]) -> list[str]:
if not all(colors.is_color_like(c) for c in cols):
raise ValueError("Not all values are color-like.")
@@ -108,7 +109,7 @@ def _create_categorical_colors(n_categories: Optional[int] = None):
raise RuntimeError(f"Unable to create `{n_categories}` colors.")
-def _insert_categorical_colors(seen_colors: Union[np.ndarray, List], n_categories: int):
+def _insert_categorical_colors(seen_colors: Union[np.ndarray, list], n_categories: int):
seen_colors = set(_convert_to_hex_colors(seen_colors))
candidates = list(filter(lambda c: c not in seen_colors, _create_categorical_colors()))[:n_categories]
@@ -135,7 +136,7 @@ def _get_black_or_white(value: float, cmap) -> str:
return _contrasting_color(r, g, b)
-def _get_bg_fg_colors(color, sat_scale: Optional[float] = None) -> Tuple[str, str]:
+def _get_bg_fg_colors(color, sat_scale: Optional[float] = None) -> tuple[str, str]:
if not colors.is_color_like(color):
raise ValueError(f"Value `{color}` is not color-like.")
@@ -155,7 +156,7 @@ def _map_names_and_colors(
series_query: pd.Series,
colors_reference: Optional[np.array] = None,
en_cutoff: Optional[float] = None,
-) -> Union[pd.Series, Tuple[pd.Series, List[Any]]]:
+) -> Union[pd.Series, tuple[pd.Series, list[Any]]]:
"""Map annotations and colors from one series to another.
Parameters
@@ -270,7 +271,7 @@ def _map_names_and_colors(
return (names_query_new, list(_convert_to_hex_colors(colors_query_new))) if process_colors else names_query_new
-def _compute_mean_color(cols: List[str]) -> str:
+def _compute_mean_color(cols: list[str]) -> str:
"""Compute mean color."""
if not all(colors.is_color_like(c) for c in cols):
raise ValueError(f"Not all values are valid colors `{cols}`.")
diff --git a/src/cellrank/_utils/_enum.py b/src/cellrank/_utils/_enum.py
index 4daf7cbe4..fc9a1033c 100644
--- a/src/cellrank/_utils/_enum.py
+++ b/src/cellrank/_utils/_enum.py
@@ -1,7 +1,7 @@
import abc
import enum
import functools
-from typing import Any, Callable, Dict, Literal, Tuple, Type
+from typing import Any, Callable, Literal
__all__ = ["ModeEnum", "DEFAULT_BACKEND"]
@@ -24,7 +24,7 @@ def __str__(self) -> str:
return f"{self.value!s}"
-def _pretty_raise_enum(cls: Type["ErrorFormatterABC"], func: Callable) -> Callable:
+def _pretty_raise_enum(cls: type["ErrorFormatterABC"], func: Callable) -> Callable:
@functools.wraps(func)
def wrapper(*args: Any, **kwargs: Any) -> "ErrorFormatterABC":
try:
@@ -49,13 +49,13 @@ def __call__(cls, *args, **kwargs): # noqa
raise TypeError(f"Can't instantiate class `{cls.__name__}` " f"without `__error_format__` class attribute.")
return super().__call__(*args, **kwargs)
- def __new__(cls, clsname: str, superclasses: Tuple[type], attributedict: Dict[str, Any]): # noqa: D102
+ def __new__(cls, clsname: str, superclasses: tuple[type], attributedict: dict[str, Any]): # noqa: D102
res = super().__new__(cls, clsname, superclasses, attributedict)
res.__new__ = _pretty_raise_enum(res, res.__new__)
return res
-class ErrorFormatterABC(abc.ABC): # noqa: D101
+class ErrorFormatterABC: # noqa: D101
__error_format__ = "Invalid option `{!r}` for `{}`. Valid options are: `{}`."
@classmethod
diff --git a/src/cellrank/_utils/_lineage.py b/src/cellrank/_utils/_lineage.py
index c4776a9d9..cc41cc53b 100644
--- a/src/cellrank/_utils/_lineage.py
+++ b/src/cellrank/_utils/_lineage.py
@@ -5,18 +5,8 @@
import itertools
import pathlib
import types
-from typing import (
- Any,
- Callable,
- Iterable,
- List,
- Literal,
- Mapping,
- Optional,
- Tuple,
- TypeVar,
- Union,
-)
+from collections.abc import Iterable, Mapping
+from typing import Any, Callable, Literal, Optional, TypeVar, Union
import numpy as np
import pandas as pd
@@ -314,13 +304,15 @@ def __getitem__(self, item) -> "Lineage":
def _mix_lineages(self, rows, mixtures: Iterable[Union[str, Any]]) -> "Lineage":
from cellrank._utils._utils import _unique_order_preserving
- def unsplit(names: str) -> Tuple[str, ...]:
+ def unsplit(names: str) -> tuple[str, ...]:
return tuple(sorted({name.strip(" ") for name in names.strip(" ,").split(",")}))
keys = [
- tuple(self._maybe_convert_names(unsplit(mixture), default=mixture))
- if isinstance(mixture, str)
- else (mixture,)
+ (
+ tuple(self._maybe_convert_names(unsplit(mixture), default=mixture))
+ if isinstance(mixture, str)
+ else (mixture,)
+ )
for mixture in mixtures
]
keys = _unique_order_preserving(keys)
@@ -565,7 +557,7 @@ def plot_pie(
title: Optional[str] = None,
legend_loc: Optional[str] = "on data",
legend_kwargs: Mapping = types.MappingProxyType({}),
- figsize: Optional[Tuple[float, float]] = None,
+ figsize: Optional[tuple[float, float]] = None,
dpi: Optional[float] = None,
save: Optional[Union[pathlib.Path, str]] = None,
**kwargs: Any,
@@ -655,7 +647,7 @@ def reduce(
normalize_weights: Literal["scale", "softmax"] = NormWeights.SOFTMAX,
softmax_scale: float = 1.0,
return_weights: bool = False,
- ) -> Union["Lineage", Tuple["Lineage", Optional[pd.DataFrame]]]:
+ ) -> Union["Lineage", tuple["Lineage", Optional[pd.DataFrame]]]:
"""Subset states and normalize them so that they again sum to :math:`1`.
Parameters
@@ -905,9 +897,11 @@ def format_row(r):
)
cells = "".join(
- f"
" f"{self._fmt(self.X[r, c])}" f" | "
- if isinstance(c, int)
- else _DUMMY_CELL
+ (
+ f"" f"{self._fmt(self.X[r, c])}" f" | "
+ if isinstance(c, int)
+ else _DUMMY_CELL
+ )
for c in rng
)
return f"{(names[r] if self._is_transposed else '') + cells}
"
@@ -996,7 +990,7 @@ def copy(self, _="C") -> "Lineage":
def __copy__(self):
return self.copy()
- def _check_axis1_shape(self, array: Iterable[Union[str, ColorLike]], msg: str) -> List[Union[str, ColorLike]]:
+ def _check_axis1_shape(self, array: Iterable[Union[str, ColorLike]], msg: str) -> list[Union[str, ColorLike]]:
"""Check whether the size of the 1D array has the correct length."""
array = list(array)
if len(array) != self._n_lineages:
@@ -1010,7 +1004,7 @@ def _maybe_convert_names(
is_singleton: bool = False,
default: Optional[Union[int, str]] = None,
make_unique: bool = True,
- ) -> Union[int, List[int], List[bool]]:
+ ) -> Union[int, list[int], list[bool]]:
"""Convert string indices to their corresponding int indices."""
from cellrank._utils._utils import _unique_order_preserving
@@ -1041,7 +1035,7 @@ def _maybe_convert_names(
@staticmethod
def _prepare_annotation(
- array: List[str],
+ array: list[str],
checker: Optional[Callable] = None,
transformer: Optional[Callable] = None,
checker_msg: Optional[str] = None,
@@ -1117,7 +1111,7 @@ def copy(self, _="C") -> Lineage:
return obj.T if was_trasposed else obj
-def _remove_zero_rows(a: np.ndarray, b: np.ndarray) -> Tuple[np.ndarray, np.ndarray]:
+def _remove_zero_rows(a: np.ndarray, b: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
if a.shape[0] != b.shape[0]:
raise ValueError("Lineage objects have unequal cell numbers")
diff --git a/src/cellrank/_utils/_linear_solver.py b/src/cellrank/_utils/_linear_solver.py
index b9b32c26c..a310a7091 100644
--- a/src/cellrank/_utils/_linear_solver.py
+++ b/src/cellrank/_utils/_linear_solver.py
@@ -1,5 +1,5 @@
import functools
-from typing import List, Optional, Tuple, TypeVar, Union
+from typing import Optional, TypeVar, Union
import numpy as np
import scipy.sparse as sp
@@ -72,7 +72,7 @@ def _create_solver(
solver: Optional[str],
preconditioner: Optional[str],
tol: float,
-) -> Tuple["petsc4py.PETSc.KSP", "petsc4py.PETSc.Vec", "petsc4py.PETScVec"]: # noqa
+) -> tuple["petsc4py.PETSc.KSP", "petsc4py.PETSc.Vec", "petsc4py.PETScVec"]: # noqa
"""
Create a linear system solver.
@@ -126,7 +126,7 @@ def _solve_many_sparse_problems_petsc(
_preconditioner: Optional[str] = None,
_tol: float = 1e-5,
_queue: Optional[Queue] = None,
-) -> Tuple[np.ndarray, int]:
+) -> tuple[np.ndarray, int]:
raise NotImplementedError(f"Not implemented for type `{type(mat_b).__name__!r}`.")
@@ -138,7 +138,7 @@ def _(
preconditioner: Optional[str] = None,
tol: float = 1e-5,
_queue: Optional[Queue] = None,
-) -> Tuple[np.ndarray, int]:
+) -> tuple[np.ndarray, int]:
if mat_b.ndim not in (1, 2) or (mat_b.ndim == 2 and mat_b.shape[1] != 1):
raise ValueError(f"Expected either a vector or a matrix with `1` column, got `{mat_b.shape}`.")
@@ -163,7 +163,7 @@ def _(
preconditioner: Optional[str],
tol: float,
queue: Queue,
-) -> Tuple[np.ndarray, int]:
+) -> tuple[np.ndarray, int]:
ksp, x, b = _create_solver(mat_a, solver, preconditioner=preconditioner, tol=tol)
xs, converged = [], 0
@@ -194,7 +194,7 @@ def _solve_many_sparse_problems(
solver: LinSolver,
tol: float,
queue: Queue,
-) -> Tuple[np.ndarray, int]:
+) -> tuple[np.ndarray, int]:
"""Solve ``mat_a * x = mat_b`` efficiently using an iterative solver.
This is a utility function which is optimized for the case of ``mat_a`` and ``mat_b`` being sparse,
@@ -382,7 +382,7 @@ def _solve_lin_system(
defined via columns in ``mat_b``.
"""
- def extractor(res_converged: List[Tuple[np.ndarray, int]]) -> Tuple[np.ndarray, int]:
+ def extractor(res_converged: list[tuple[np.ndarray, int]]) -> tuple[np.ndarray, int]:
res, converged = zip(*res_converged)
return np.hstack(res), sum(converged)
diff --git a/src/cellrank/_utils/_parallelize.py b/src/cellrank/_utils/_parallelize.py
index 80a25d2c4..d0545d38d 100644
--- a/src/cellrank/_utils/_parallelize.py
+++ b/src/cellrank/_utils/_parallelize.py
@@ -1,6 +1,7 @@
import multiprocessing
import threading
-from typing import Any, Callable, Optional, Sequence, Union
+from collections.abc import Sequence
+from typing import Any, Callable, Optional, Union
import joblib as jl
diff --git a/src/cellrank/_utils/_utils.py b/src/cellrank/_utils/_utils.py
index 4f0831ccf..4db97651a 100644
--- a/src/cellrank/_utils/_utils.py
+++ b/src/cellrank/_utils/_utils.py
@@ -5,20 +5,8 @@
import os
import types
import warnings
-from typing import (
- Any,
- Callable,
- Dict,
- Hashable,
- Iterable,
- List,
- Literal,
- Optional,
- Sequence,
- Tuple,
- TypeVar,
- Union,
-)
+from collections.abc import Hashable, Iterable, Sequence
+from typing import Any, Callable, Literal, Optional, TypeVar, Union
import wrapt
@@ -153,8 +141,8 @@ def _min_max_scale(x: np.ndarray) -> np.ndarray:
def _process_series(
- series: pd.Series, keys: Optional[List[str]], cols: Optional[np.array] = None
-) -> Union[pd.Series, Tuple[pd.Series, List[str]]]:
+ series: pd.Series, keys: Optional[list[str]], cols: Optional[np.array] = None
+) -> Union[pd.Series, tuple[pd.Series, list[str]]]:
"""Process :class:`~pandas.Series` of categorical objects.
Categories in ``series`` are combined/removed according to ``keys``,
@@ -216,14 +204,14 @@ def _process_series(
# check the `keys` are all proper categories
remaining_cat = [b for a in keys_ for b in a]
- if not np.all(np.in1d(remaining_cat, series_in.cat.categories)):
+ if not np.all(np.isin(remaining_cat, series_in.cat.categories)):
raise ValueError("Not all keys are proper categories. Check for spelling mistakes in `keys`.")
# remove cats and colors according to keys
n_remaining = len(remaining_cat)
removed_cat = list(set(series_in.cat.categories) - set(remaining_cat))
if process_colors:
- mask = np.in1d(series_in.cat.categories, remaining_cat)
+ mask = np.isin(series_in.cat.categories, remaining_cat)
colors_temp = colors_in[mask].copy()
series_temp = series_in.cat.remove_categories(removed_cat)
@@ -243,11 +231,11 @@ def _process_series(
if process_colors:
# apply the same to the colors array. We just append new colors at the end
- color_mask = np.in1d(series_temp.cat.categories[:n_remaining], cat)
+ color_mask = np.isin(series_temp.cat.categories[:n_remaining], cat)
colors_merge = np.array(colors_temp)[:n_remaining][color_mask]
colors_mod[new_cat_name] = _compute_mean_color(colors_merge)
elif process_colors:
- color_mask = np.in1d(series_temp.cat.categories[:n_remaining], cat[0])
+ color_mask = np.isin(series_temp.cat.categories[:n_remaining], cat[0])
colors_mod[cat[0]] = np.array(colors_temp)[:n_remaining][color_mask][0]
# Since we have just appended colors at the end, we must now delete the unused ones
@@ -333,8 +321,8 @@ def _perm_test(
Y: np.ndarray,
seed: Optional[int] = None,
queue=None,
-) -> Tuple[np.ndarray, np.ndarray]:
- rs = np.random.RandomState(None if seed is None else seed + ixs[0])
+) -> tuple[np.ndarray, np.ndarray]:
+ rs = np.random.default_rng(None if seed is None else seed + ixs[0])
cell_ixs = np.arange(X.shape[1])
pvals = np.zeros_like(corr, dtype=np.float64)
corr_bs = np.zeros((len(ixs), X.shape[0], Y.shape[1])) # perms x genes x lineages
@@ -449,7 +437,7 @@ def _correlation_test_helper(
seed: Optional[int] = None,
confidence_level: float = 0.95,
**kwargs: Any,
-) -> Tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
+) -> tuple[np.ndarray, np.ndarray, np.ndarray, np.ndarray]:
"""Compute the correlation between rows in matrix ``X`` columns of matrix ``Y``.
Parameters
@@ -476,7 +464,7 @@ def _correlation_test_helper(
"""
from cellrank._utils._parallelize import parallelize
- def perm_test_extractor(res: Sequence[Tuple[np.ndarray, np.ndarray]]) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
+ def perm_test_extractor(res: Sequence[tuple[np.ndarray, np.ndarray]]) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
pvals, corr_bs = zip(*res)
pvals = np.sum(pvals, axis=0) / float(n_perms)
@@ -545,7 +533,7 @@ def _filter_cells(distances: sp.spmatrix, rc_labels: pd.Series, n_matches_min: i
own_cl = rc_labels[cell]
neighbors = cols[rows == cell]
n_cls = rc_labels[neighbors]
- n_matches = np.sum(np.in1d(n_cls, own_cl))
+ n_matches = np.sum(np.isin(n_cls, own_cl))
if n_matches < n_matches_min:
rc_labels[cell] = None
@@ -566,7 +554,7 @@ def _cluster_X(
method: Literal["leiden", "kmeans"] = "leiden",
n_neighbors: int = 20,
resolution: float = 1.0,
-) -> List[Any]:
+) -> list[Any]:
"""Cluster the rows of ``X``.
Parameters
@@ -596,7 +584,7 @@ def _cluster_X(
elif method == "leiden":
adata_dummy = sc.AnnData(X=X)
sc.pp.neighbors(adata_dummy, use_rep="X", n_neighbors=n_neighbors)
- sc.tl.leiden(adata_dummy, resolution=resolution)
+ sc.tl.leiden(adata_dummy, flavor="igraph", n_iterations=2, directed=False, resolution=resolution)
labels = adata_dummy.obs[method]
else:
raise NotImplementedError(f"Invalid method `{method}`. Valid options are `kmeans` or `leiden`.")
@@ -630,7 +618,7 @@ def _eigengap(evals: np.ndarray, alpha: float) -> int:
def _partition(
conn: Union[DiGraph, np.ndarray, sp.spmatrix], sort: bool = True
-) -> Tuple[List[List[Any]], List[List[Any]]]:
+) -> tuple[list[list[Any]], list[list[Any]]]:
"""Partition a directed graph into its transient and recurrent classes.
In a directed graph *G*, node *j* is accessible from node *i* if there exists a path from *i* to *j*.
@@ -852,7 +840,7 @@ def save_fig(fig, path: Union[str, os.PathLike], make_dir: bool = True, ext: str
def _convert_to_categorical_series(
- term_states: Dict[Union[int, str], Sequence[Union[int, str]]], cell_names: List[str]
+ term_states: dict[Union[int, str], Sequence[Union[int, str]]], cell_names: list[str]
) -> pd.Series:
"""Convert a mapping of terminal states to cells to a :class:`~pandas.Series`.
@@ -900,10 +888,10 @@ def _convert_to_categorical_series(
def _merge_categorical_series(
old: pd.Series,
new: pd.Series,
- colors_old: Union[List[ColorLike], np.ndarray, Dict[Any, ColorLike]] = None,
- colors_new: Union[List[ColorLike], np.ndarray, Dict[Any, ColorLike]] = None,
+ colors_old: Union[list[ColorLike], np.ndarray, dict[Any, ColorLike]] = None,
+ colors_new: Union[list[ColorLike], np.ndarray, dict[Any, ColorLike]] = None,
color_overwrite: bool = False,
-) -> Optional[Union[pd.Series, Tuple[pd.Series, np.ndarray]]]:
+) -> Optional[Union[pd.Series, tuple[pd.Series, np.ndarray]]]:
"""Update categorical :class:`~pandas.Series` with new information.
It **can never remove** old categories, only add to the existing ones.
@@ -930,7 +918,7 @@ def _merge_categorical_series(
def get_color_mapper(
series: pd.Series,
- cols: Union[List[ColorLike], np.ndarray, Dict[Any, ColorLike]],
+ cols: Union[list[ColorLike], np.ndarray, dict[Any, ColorLike]],
):
if len(series.cat.categories) != len(cols):
raise ValueError(f"Series ({len(series.cat.categories)}) and colors ({len(colors_new)}) differ in length.")
@@ -997,7 +985,7 @@ def get_color_mapper(
return old, colors_merged
-def _unique_order_preserving(iterable: Iterable[Hashable]) -> List[Hashable]:
+def _unique_order_preserving(iterable: Iterable[Hashable]) -> list[Hashable]:
"""Remove items from an iterable while preserving the order."""
seen = set()
return [i for i in iterable if i not in seen and not seen.add(i)]
@@ -1022,7 +1010,7 @@ def _fuzzy_to_discrete(
remove_overlap: bool = True,
raise_threshold: Optional[float] = 0.2,
check_row_sums: bool = True,
-) -> Tuple[np.ndarray, np.ndarray]:
+) -> tuple[np.ndarray, np.ndarray]:
"""Map fuzzy clustering to discrete clustering.
Given a fuzzy clustering of `n_samples` samples represented by a matrix ``a_fuzzy`` of shape
@@ -1145,7 +1133,7 @@ def _series_from_one_hot_matrix(
if not np.all(membership.sum(axis=1) <= 1):
raise ValueError("Not all items are one-hot encoded or empty.")
if (membership.sum(0) == 0).any():
- logg.warning(f"Detected {np.sum((membership.sum(0) == 0))} empty categories")
+ logg.warning(f"Detected {np.sum(membership.sum(0) == 0)} empty categories")
if index is None:
index = range(n_samples)
@@ -1165,7 +1153,7 @@ def _series_from_one_hot_matrix(
def _get_cat_and_null_indices(
cat_series: pd.Series,
-) -> Tuple[np.ndarray, np.ndarray, Dict[Any, np.ndarray]]:
+) -> tuple[np.ndarray, np.ndarray, dict[Any, np.ndarray]]:
"""Given a categorical :class:`~pandas.Series`, get the indices corresponding to categories and `NaNs`.
Parameters
@@ -1212,7 +1200,7 @@ def _calculate_absorption_time_moments(
n: int,
calculate_variance: bool = False,
**kwargs: Any,
-) -> Tuple[np.ndarray, Optional[np.ndarray]]:
+) -> tuple[np.ndarray, Optional[np.ndarray]]:
"""Calculate the mean time until absorption and optionally its variance.
Parameters
@@ -1272,7 +1260,7 @@ def _calculate_lineage_absorption_time_means(
Q: sp.csr_matrix,
R: sp.csr_matrix,
trans_indices: np.ndarray,
- ixs: Dict[str, np.ndarray],
+ ixs: dict[str, np.ndarray],
index: pd.Index,
calculate_variance: bool = False,
**kwargs: Any,
@@ -1369,7 +1357,7 @@ def _check_collection(
key_name: str = "Gene",
use_raw: bool = False,
raise_exc: bool = True,
-) -> List[str]:
+) -> list[str]:
"""Check if given collection contains all the keys.
Parameters
@@ -1409,7 +1397,7 @@ def _check_collection(
return res
-def _minmax(data: np.ndarray, perc: Optional[Tuple[float, float]] = None) -> Tuple[float, float]:
+def _minmax(data: np.ndarray, perc: Optional[tuple[float, float]] = None) -> tuple[float, float]:
"""Return minimum and maximum value of the data.
Parameters
@@ -1461,7 +1449,7 @@ def _has_neighs(adata: AnnData, key: Optional[str] = None) -> bool:
return _modify_neigh_key(key) in adata.uns
-def _get_neighs_params(adata: AnnData, key: str = "neighbors") -> Dict[str, Any]:
+def _get_neighs_params(adata: AnnData, key: str = "neighbors") -> dict[str, Any]:
return adata.uns.get(key, {}).get("params", {})
diff --git a/src/cellrank/datasets.py b/src/cellrank/datasets.py
index 3076c12ed..a0faf44a8 100644
--- a/src/cellrank/datasets.py
+++ b/src/cellrank/datasets.py
@@ -1,7 +1,7 @@
import enum
import os
import pathlib
-from typing import Any, Literal, Tuple, Union
+from typing import Any, Literal, Union
from anndata import AnnData
from scanpy import read
@@ -42,7 +42,7 @@ class ReprogrammingSubset(ModeEnum):
def _load_dataset_from_url(
- fpath: Union[str, pathlib.Path], url: str, expected_shape: Tuple[int, int], **kwargs: Any
+ fpath: Union[str, pathlib.Path], url: str, expected_shape: tuple[int, int], **kwargs: Any
) -> AnnData:
fpath = str(fpath)
if not fpath.endswith(".h5ad"):
diff --git a/src/cellrank/estimators/_base_estimator.py b/src/cellrank/estimators/_base_estimator.py
index 76001de8c..0369a1504 100644
--- a/src/cellrank/estimators/_base_estimator.py
+++ b/src/cellrank/estimators/_base_estimator.py
@@ -2,18 +2,8 @@
import contextlib
import copy as copy_
import inspect
-from typing import (
- Any,
- Callable,
- Dict,
- List,
- Literal,
- Mapping,
- Optional,
- Sequence,
- Tuple,
- Union,
-)
+from collections.abc import Mapping, Sequence
+from typing import Any, Callable, Literal, Optional, Union
import numpy as np
import pandas as pd
@@ -67,7 +57,7 @@ def __init__(
object = PrecomputedKernel(object, copy=False, **kwargs)
super().__init__(kernel=object)
- self._params: Dict[str, Any] = {}
+ self._params: dict[str, Any] = {}
self._shadow_adata = AnnData(
X=sp.csr_matrix(self.adata.shape, dtype=self.adata.X.dtype),
obs=self.adata.obs[[]].copy(),
@@ -115,7 +105,7 @@ def _set(
attr: Optional[str] = None,
obj: Optional[Union[pd.DataFrame, Mapping[str, Any]]] = None,
key: Optional[str] = None,
- value: Optional[Union[np.ndarray, pd.Series, pd.DataFrame, Lineage, AnnData, Dict[str, Any]]] = None,
+ value: Optional[Union[np.ndarray, pd.Series, pd.DataFrame, Lineage, AnnData, dict[str, Any]]] = None,
copy: bool = True,
shadow_only: bool = False,
) -> None:
@@ -172,7 +162,7 @@ def _get(
obj: Union[pd.DataFrame, Mapping[str, Any]],
key: str,
shadow_attr: Optional[Literal["obs", "obsm", "var", "varm", "uns"]] = None,
- dtype: Optional[Union[type, Tuple[type, ...]]] = None,
+ dtype: Optional[Union[type, tuple[type, ...]]] = None,
copy: bool = True,
allow_missing: bool = False,
) -> Any:
@@ -250,7 +240,7 @@ def _create_params(
locs: Optional[Mapping[str, Any]] = None,
func: Optional[Callable] = None,
remove: Sequence[str] = (),
- ) -> Dict[str, Any]:
+ ) -> dict[str, Any]:
"""Create parameters of interest from a function call.
Parameters
@@ -298,7 +288,7 @@ def _create_params(
finally:
del frame
- def _read_params(self, key: str) -> Dict[str, Any]:
+ def _read_params(self, key: str) -> dict[str, Any]:
"""Read ``key`` from estimator params in :attr:`adata`.
Usually called in :meth:`_read_adata` during :meth:`from_adata`.
@@ -334,7 +324,7 @@ def to_adata(
Annotated data object.
""" # noqa: D400
- def handle_attribute(attr: Attr_t, keys: List[str], *, copy: bool) -> None:
+ def handle_attribute(attr: Attr_t, keys: list[str], *, copy: bool) -> None:
try:
if attr == "X":
adata.X = copy_.deepcopy(self.adata.X) if copy else self.adata.X
@@ -457,6 +447,6 @@ def __str__(self) -> str:
return repr(self)
@property
- def params(self) -> Dict[str, Any]:
+ def params(self) -> dict[str, Any]:
"""Estimator parameters."""
return self._params
diff --git a/src/cellrank/estimators/mixins/_fate_probabilities.py b/src/cellrank/estimators/mixins/_fate_probabilities.py
index b14326ad9..925bd2e33 100644
--- a/src/cellrank/estimators/mixins/_fate_probabilities.py
+++ b/src/cellrank/estimators/mixins/_fate_probabilities.py
@@ -1,5 +1,6 @@
import types
-from typing import Any, Dict, Literal, Mapping, NamedTuple, Optional, Sequence, Union
+from collections.abc import Mapping, Sequence
+from typing import Any, Literal, NamedTuple, Optional, Union
import numpy as np
import pandas as pd
@@ -37,7 +38,7 @@ class RecTransStates(NamedTuple):
s: Union[np.ndarray, sp.spmatrix]
trans_indices: np.ndarray
rec_indices: np.ndarray
- name_to_ixs: Dict[str, np.ndarray]
+ name_to_ixs: dict[str, np.ndarray]
term_states: pd.Series
term_states_colors: Sequence[Any]
@@ -46,27 +47,21 @@ class FateProbsProtocol(BaseProtocol):
_term_states: StatesHolder
@property
- def transition_matrix(self) -> Union[np.ndarray, sp.spmatrix]:
- ...
+ def transition_matrix(self) -> Union[np.ndarray, sp.spmatrix]: ...
@property
- def terminal_states(self) -> pd.Series:
- ...
+ def terminal_states(self) -> pd.Series: ...
@property
- def fate_probabilities(self) -> Optional[Lineage]:
- ...
+ def fate_probabilities(self) -> Optional[Lineage]: ...
@property
- def absorption_times(self) -> Optional[pd.DataFrame]:
- ...
+ def absorption_times(self) -> Optional[pd.DataFrame]: ...
@property
- def priming_degree(self) -> Optional[pd.Series]:
- ...
+ def priming_degree(self) -> Optional[pd.Series]: ...
- def __len__(self) -> int:
- ...
+ def __len__(self) -> int: ...
def _compute_fate_probabilities(
self,
@@ -81,16 +76,14 @@ def _compute_fate_probabilities(
tol: float,
show_progress_bar: bool,
preconditioner: str,
- ) -> np.ndarray:
- ...
+ ) -> np.ndarray: ...
def _rec_trans_states(
self,
keys: Optional[Sequence[str]],
*,
ctx: Literal["fate_probs", "time_to_absorption"],
- ) -> RecTransStates:
- ...
+ ) -> RecTransStates: ...
def _ensure_lineage_object(
self,
@@ -99,27 +92,23 @@ def _ensure_lineage_object(
kind: Literal["macrostates", "term_states", "fate_probs"],
backward: bool,
**kwargs: Any,
- ) -> Lineage:
- ...
+ ) -> Lineage: ...
def _write_fate_probabilities(
self,
fate_probs: Optional[Lineage],
- ) -> str:
- ...
+ ) -> str: ...
def _write_absorption_times(
self,
abs_times: Optional[pd.DataFrame],
params: Mapping[str, Any] = types.MappingProxyType({}),
- ) -> str:
- ...
+ ) -> str: ...
def _write_lineage_priming(
self,
priming_degree: Optional[pd.Series],
- ) -> str:
- ...
+ ) -> str: ...
def _plot_continuous(
self,
@@ -134,8 +123,7 @@ def _plot_continuous(
same_plot: bool = True,
cmap: str = "viridis",
**kwargs: Any,
- ) -> None:
- ...
+ ) -> None: ...
class FateProbsMixin:
diff --git a/src/cellrank/estimators/mixins/_kernel.py b/src/cellrank/estimators/mixins/_kernel.py
index 1ad0217d7..f972144d0 100644
--- a/src/cellrank/estimators/mixins/_kernel.py
+++ b/src/cellrank/estimators/mixins/_kernel.py
@@ -1,4 +1,4 @@
-from typing import Any, Optional, Tuple, TypeVar, Union
+from typing import Any, Optional, TypeVar, Union
import numpy as np
import scipy.sparse as sp
@@ -29,7 +29,7 @@ def adata(self) -> AnnData:
return self.kernel.adata
@property
- def shape(self) -> Tuple[int, int]:
+ def shape(self) -> tuple[int, int]:
"""Shape of the kernel."""
return self.kernel.shape
diff --git a/src/cellrank/estimators/mixins/_lineage_drivers.py b/src/cellrank/estimators/mixins/_lineage_drivers.py
index 718d06024..722969d0e 100644
--- a/src/cellrank/estimators/mixins/_lineage_drivers.py
+++ b/src/cellrank/estimators/mixins/_lineage_drivers.py
@@ -1,7 +1,8 @@
import contextlib
import pathlib
import types
-from typing import Any, Dict, Literal, Mapping, Optional, Sequence, Tuple, Union
+from collections.abc import Mapping, Sequence
+from typing import Any, Literal, Optional, Union
import scvelo as scv
@@ -34,20 +35,16 @@ def _write_lineage_drivers(
drivers: Optional[pd.DataFrame],
use_raw: bool,
params: Mapping[str, Any] = types.MappingProxyType({}),
- ) -> None:
- ...
+ ) -> None: ...
@property
- def eigendecomposition(self) -> Dict[str, Any]:
- ...
+ def eigendecomposition(self) -> dict[str, Any]: ...
@property
- def fate_probabilities(self) -> Optional[Lineage]:
- ...
+ def fate_probabilities(self) -> Optional[Lineage]: ...
@property
- def lineage_drivers(self) -> Optional[pd.DataFrame]:
- ...
+ def lineage_drivers(self) -> Optional[pd.DataFrame]: ...
class LinDriversMixin(FateProbsMixin):
@@ -144,7 +141,7 @@ def compute_lineage_drivers(
# use `cluster_key` and clusters to subset the data
if clusters is not None:
- if cluster_key not in self.adata.obs.keys():
+ if cluster_key not in self.adata.obs:
raise KeyError(f"Unable to find clusters in `adata.obs[{cluster_key!r}]`.")
if isinstance(clusters, str):
clusters = [clusters]
@@ -157,7 +154,7 @@ def compute_lineage_drivers(
f"Clusters `{list(np.array(clusters)[cluster_mask])}` not found in "
f"`adata.obs[{cluster_key!r}]`."
)
- subset_mask = np.in1d(self.adata.obs[cluster_key], clusters)
+ subset_mask = np.isin(self.adata.obs[cluster_key], clusters)
adata_comp = self.adata[subset_mask]
lin_probs = fate_probs[subset_mask, :]
else:
@@ -211,7 +208,7 @@ def plot_lineage_drivers(
ascending: bool = False,
ncols: Optional[int] = None,
title_fmt: str = "{gene} qval={qval:.4e}",
- figsize: Optional[Tuple[float, float]] = None,
+ figsize: Optional[tuple[float, float]] = None,
dpi: Optional[int] = None,
save: Optional[Union[str, pathlib.Path]] = None,
**kwargs: Any,
@@ -248,8 +245,8 @@ def prepare_format(
pval: Optional[float],
qval: Optional[float],
corr: Optional[float],
- ) -> Dict[str, Any]:
- kwargs: Dict[str, Optional[Union[str, float]]] = {}
+ ) -> dict[str, Any]:
+ kwargs: dict[str, Optional[Union[str, float]]] = {}
if "{gene" in title_fmt:
kwargs["gene"] = gene
if "{pval" in title_fmt:
@@ -319,14 +316,14 @@ def plot_lineage_drivers_correlation(
lineage_x: str,
lineage_y: str,
color: Optional[str] = None,
- gene_sets: Optional[Dict[str, Sequence[str]]] = None,
+ gene_sets: Optional[dict[str, Sequence[str]]] = None,
gene_sets_colors: Optional[Sequence[str]] = None,
use_raw: bool = False,
cmap: str = "RdYlBu_r",
fontsize: int = 12,
adjust_text: bool = False,
legend_loc: Optional[str] = "best",
- figsize: Optional[Tuple[float, float]] = (4, 4),
+ figsize: Optional[tuple[float, float]] = (4, 4),
dpi: Optional[int] = None,
save: Optional[Union[str, pathlib.Path]] = None,
show: bool = True,
diff --git a/src/cellrank/estimators/mixins/_utils.py b/src/cellrank/estimators/mixins/_utils.py
index bc26463cb..2f486e69a 100644
--- a/src/cellrank/estimators/mixins/_utils.py
+++ b/src/cellrank/estimators/mixins/_utils.py
@@ -1,17 +1,13 @@
import copy
import enum
+from collections.abc import Iterable, Mapping, Sequence
from typing import (
Any,
Callable,
- Dict,
- Iterable,
Literal,
- Mapping,
NamedTuple,
Optional,
Protocol,
- Sequence,
- Tuple,
TypeVar,
Union,
)
@@ -61,7 +57,7 @@ def backward(self) -> bool: # noqa: D102
...
@property
- def params(self) -> Dict[str, Any]: # noqa: D102
+ def params(self) -> dict[str, Any]: # noqa: D102
...
def _set(
@@ -69,11 +65,10 @@ def _set(
attr: Optional[str] = None,
obj: Optional[Union[pd.DataFrame, Mapping[str, Any]]] = None,
key: Optional[str] = None,
- value: Optional[Union[np.ndarray, pd.Series, pd.DataFrame, Lineage, AnnData, Dict[str, Any]]] = None,
+ value: Optional[Union[np.ndarray, pd.Series, pd.DataFrame, Lineage, AnnData, dict[str, Any]]] = None,
copy: bool = True,
shadow_only: bool = False,
- ) -> None:
- ...
+ ) -> None: ...
def _get(
self,
@@ -81,26 +76,23 @@ def _get(
obj: Union[pd.DataFrame, Mapping[str, Any]],
key: str,
shadow_attr: Optional[Literal["obs", "obsm", "var", "varm", "uns"]] = None,
- dtype: Optional[Union[type, Tuple[type, ...]]] = None,
+ dtype: Optional[Union[type, tuple[type, ...]]] = None,
copy: bool = True,
allow_missing: bool = False,
- ) -> Any:
- ...
+ ) -> Any: ...
def _create_params(
self,
locs: Optional[Mapping[str, Any]] = None,
func: Optional[Callable] = None,
remove: Sequence[str] = (),
- ) -> Dict[str, Any]:
- ...
+ ) -> dict[str, Any]: ...
- def _read_params(self, key: str) -> Dict[str, Any]:
- ...
+ def _read_params(self, key: str) -> dict[str, Any]: ...
@decorator()
-def logger(wrapped: Callable[..., str], instance: Any, args: Any, kwargs: Dict[str, Any]) -> str:
+def logger(wrapped: Callable[..., str], instance: Any, args: Any, kwargs: dict[str, Any]) -> str:
"""Handle logging for :class:`~anndata.AnnData` writing functions of :class:`~cellrank.estimators.BaseEstimator`."""
log, time = kwargs.pop("log", True), kwargs.pop("time", None)
msg = wrapped(*args, **kwargs)
diff --git a/src/cellrank/estimators/mixins/decomposition/_eigen.py b/src/cellrank/estimators/mixins/decomposition/_eigen.py
index 66f0dcee7..6b95eaf8d 100644
--- a/src/cellrank/estimators/mixins/decomposition/_eigen.py
+++ b/src/cellrank/estimators/mixins/decomposition/_eigen.py
@@ -1,6 +1,7 @@
import pathlib
import types
-from typing import Any, Dict, Literal, Mapping, Optional, Tuple, Union
+from collections.abc import Mapping
+from typing import Any, Literal, Optional, Union
import numpy as np
import scipy.sparse as sp
@@ -23,13 +24,11 @@
class EigenProtocol(BaseProtocol):
@property
- def transition_matrix(self) -> Union[np.ndarray, sp.spmatrix]:
- ...
+ def transition_matrix(self) -> Union[np.ndarray, sp.spmatrix]: ...
def _write_eigendecomposition(
- self, decomp: Dict[str, Any], params: Mapping[str, Any] = types.MappingProxyType({})
- ) -> str:
- ...
+ self, decomp: dict[str, Any], params: Mapping[str, Any] = types.MappingProxyType({})
+ ) -> str: ...
class EigenMixin:
@@ -41,7 +40,7 @@ def __init__(self, **kwargs: Any):
@property
@d.get_summary(base="eigen")
- def eigendecomposition(self) -> Optional[Dict[str, Any]]:
+ def eigendecomposition(self) -> Optional[dict[str, Any]]:
"""Eigendecomposition of the :attr:`transition_matrix`.
For non-symmetric real matrices, left and right eigenvectors will in general be different and complex. We
@@ -157,7 +156,7 @@ def plot_spectrum(
legend_loc: Optional[str] = None,
title: Optional[str] = None,
marker: str = ".",
- figsize: Optional[Tuple[float, float]] = (5, 5),
+ figsize: Optional[tuple[float, float]] = (5, 5),
dpi: int = 100,
save: Optional[Union[str, pathlib.Path]] = None,
**kwargs: Any,
@@ -230,14 +229,14 @@ def _plot_complex_spectrum(
self,
n: int,
dpi: int = 100,
- figsize: Optional[Tuple[float, float]] = None,
+ figsize: Optional[tuple[float, float]] = None,
legend_loc: Optional[str] = None,
title: Optional[str] = None,
marker: str = ".",
**kwargs: Any,
) -> plt.Figure:
# define a function to make the data limits rectangular
- def adapt_range(min_: float, max_: float, range_: float) -> Tuple[float, float]:
+ def adapt_range(min_: float, max_: float, range_: float) -> tuple[float, float]:
return (
min_ + (max_ - min_) / 2 - range_ / 2,
min_ + (max_ - min_) / 2 + range_ / 2,
@@ -288,7 +287,7 @@ def _plot_real_spectrum(
show_eigengap: bool = True,
show_all_xticks: bool = True,
dpi: int = 100,
- figsize: Optional[Tuple[float, float]] = None,
+ figsize: Optional[tuple[float, float]] = None,
legend_loc: Optional[str] = None,
title: Optional[str] = None,
marker: str = ".",
@@ -348,7 +347,7 @@ def _plot_real_spectrum(
@shadow
def _write_eigendecomposition(
self: EigenProtocol,
- decomp: Dict[str, Any],
+ decomp: dict[str, Any],
params: Mapping[str, Any] = types.MappingProxyType({}),
) -> str:
key = Key.uns.eigen(self.backward)
diff --git a/src/cellrank/estimators/mixins/decomposition/_schur.py b/src/cellrank/estimators/mixins/decomposition/_schur.py
index 88142fd28..4fda3ff73 100644
--- a/src/cellrank/estimators/mixins/decomposition/_schur.py
+++ b/src/cellrank/estimators/mixins/decomposition/_schur.py
@@ -2,7 +2,8 @@
import io
import pathlib
import types
-from typing import Any, Dict, Literal, Mapping, Optional, Tuple, Union
+from collections.abc import Mapping
+from typing import Any, Literal, Optional, Union
from pygpcca import GPCCA
from pygpcca._sorted_schur import _check_conj_split
@@ -33,19 +34,17 @@ class SchurProtocol(BaseProtocol):
schur_vectors: Optional[np.ndarray] = None
_schur_matrix: Optional[np.ndarray] = None
- _eigendecomposition: Optional[Dict[str, Any]] = None
+ _eigendecomposition: Optional[dict[str, Any]] = None
- def transition_matrix(self) -> Union[np.ndarray, sp.spmatrix]:
- ...
+ def transition_matrix(self) -> Union[np.ndarray, sp.spmatrix]: ...
def _write_schur_decomposition(
self,
- decomp: Dict[str, Any],
+ decomp: dict[str, Any],
vectors: np.ndarray,
matrix: np.ndarray,
params: Mapping[str, Any] = types.MappingProxyType({}),
- ) -> str:
- ...
+ ) -> str: ...
class SchurMixin:
@@ -58,7 +57,7 @@ def __init__(self, **kwargs: Any):
self._schur_vectors: Optional[np.ndarray] = None
self._schur_matrix: Optional[np.ndarray] = None
- self._eigendecomposition: Optional[Dict[str, Any]] = None
+ self._eigendecomposition: Optional[dict[str, Any]] = None
@property
@d.get_summary(base="schur_vectors")
@@ -87,7 +86,7 @@ def schur_matrix(self) -> Optional[np.ndarray]:
@property
@d.get_summary(base="eigen")
- def eigendecomposition(self) -> Optional[Dict[str, Any]]:
+ def eigendecomposition(self) -> Optional[dict[str, Any]]:
"""Eigendecomposition of the :attr:`transition_matrix`.
For non-symmetric real matrices, left and right eigenvectors will in general be different and complex.
@@ -210,7 +209,7 @@ def plot_schur_matrix(
self,
title: Optional[str] = "schur matrix",
cmap: str = "viridis",
- figsize: Optional[Tuple[float, float]] = None,
+ figsize: Optional[tuple[float, float]] = None,
dpi: Optional[float] = 80,
save: Optional[Union[str, pathlib.Path]] = None,
**kwargs: Any,
@@ -274,7 +273,7 @@ def plot_schur_matrix(
@shadow
def _write_schur_decomposition(
self: SchurProtocol,
- decomp: Dict[str, Any],
+ decomp: dict[str, Any],
vectors: np.ndarray,
matrix: np.ndarray,
params: Mapping[str, Any] = types.MappingProxyType({}),
diff --git a/src/cellrank/estimators/terminal_states/_cflare.py b/src/cellrank/estimators/terminal_states/_cflare.py
index 5e27d055f..82c999253 100644
--- a/src/cellrank/estimators/terminal_states/_cflare.py
+++ b/src/cellrank/estimators/terminal_states/_cflare.py
@@ -1,4 +1,5 @@
-from typing import Any, Dict, List, Literal, Optional, Sequence, Union
+from collections.abc import Sequence
+from typing import Any, Literal, Optional, Union
import numpy as np
import pandas as pd
@@ -122,7 +123,7 @@ def predict(
- :attr:`terminal_states_probabilities` - %(tse_term_states_probs.summary)s
"""
- def convert_use(use: Optional[Union[int, Sequence[int], np.ndarray]]) -> List[int]:
+ def convert_use(use: Optional[Union[int, Sequence[int], np.ndarray]]) -> list[int]:
if method not in ["kmeans", "leiden"]:
raise ValueError(f"Invalid method `{method!r}`. Valid options are `leiden` or `kmeans`.")
@@ -221,7 +222,7 @@ def convert_use(use: Optional[Union[int, Sequence[int], np.ndarray]]) -> List[in
time=start,
)
- def _compute_term_states_probs(self, eig: Dict[str, Any], use: List[int]) -> pd.Series:
+ def _compute_term_states_probs(self, eig: dict[str, Any], use: list[int]) -> pd.Series:
# get the truncated eigendecomposition
V, evals = eig["V_l"].real[:, use], eig["D"].real[use]
diff --git a/src/cellrank/estimators/terminal_states/_gpcca.py b/src/cellrank/estimators/terminal_states/_gpcca.py
index 152bd76de..cc55dd267 100644
--- a/src/cellrank/estimators/terminal_states/_gpcca.py
+++ b/src/cellrank/estimators/terminal_states/_gpcca.py
@@ -3,8 +3,9 @@
import enum
import pathlib
import types
+from collections.abc import Mapping, Sequence
from pathlib import Path
-from typing import Any, Dict, List, Literal, Mapping, Optional, Sequence, Tuple, Union
+from typing import Any, Literal, Optional, Union
import numpy as np
import pandas as pd
@@ -377,7 +378,7 @@ def predict_initial_states(self, n_states: int = 1, n_cells: int = 30, allow_ove
@d.dedent
def set_terminal_states(
self,
- states: Optional[Union[str, Sequence[str], Dict[str, Sequence[str]], pd.Series]] = None,
+ states: Optional[Union[str, Sequence[str], dict[str, Sequence[str]], pd.Series]] = None,
n_cells: int = 30,
allow_overlap: bool = False,
cluster_key: Optional[str] = None,
@@ -458,7 +459,7 @@ def set_terminal_states(
@d.dedent
def set_initial_states(
self,
- states: Optional[Union[str, Sequence[str], Dict[str, Sequence[str]], pd.Series]] = None,
+ states: Optional[Union[str, Sequence[str], dict[str, Sequence[str]], pd.Series]] = None,
n_cells: int = 30,
allow_overlap: bool = False,
cluster_key: Optional[str] = None,
@@ -540,7 +541,7 @@ def set_initial_states(
def tsi(
self,
n_macrostates: int,
- terminal_states: Optional[List[str]] = None,
+ terminal_states: Optional[list[str]] = None,
cluster_key: Optional[str] = None,
**kwargs: Any,
) -> float:
@@ -606,9 +607,9 @@ def tsi(
def plot_tsi(
self,
n_macrostates: Optional[int] = None,
- x_offset: Tuple[float, float] = (0.2, 0.2),
- y_offset: Tuple[float, float] = (0.1, 0.1),
- figsize: Tuple[float, float] = (6, 4),
+ x_offset: tuple[float, float] = (0.2, 0.2),
+ y_offset: tuple[float, float] = (0.1, 0.1),
+ figsize: tuple[float, float] = (6, 4),
dpi: Optional[int] = None,
save: Optional[Union[str, Path]] = None,
**kwargs: Any,
@@ -741,7 +742,7 @@ def plot_coarse_T(
annotate: bool = True,
show_cbar: bool = True,
title: Optional[str] = None,
- figsize: Tuple[float, float] = (8, 8),
+ figsize: tuple[float, float] = (8, 8),
dpi: int = 80,
save: Optional[Union[str, pathlib.Path]] = None,
text_kwargs: Mapping[str, Any] = types.MappingProxyType({}),
@@ -785,7 +786,7 @@ def plot_coarse_T(
def order_matrix(
order: Optional[CoarseTOrder],
- ) -> Tuple[pd.DataFrame, Optional[pd.Series], Optional[pd.Series]]:
+ ) -> tuple[pd.DataFrame, Optional[pd.Series], Optional[pd.Series]]:
coarse_T = self.coarse_T
init_d = self.coarse_initial_distribution
stat_d = self.coarse_stationary_distribution
@@ -1006,7 +1007,7 @@ def plot_macrostate_composition(
title: Optional[str] = None,
labelrot: float = 45,
legend_loc: Optional[str] = "upper right out",
- figsize: Optional[Tuple[float, float]] = None,
+ figsize: Optional[tuple[float, float]] = None,
dpi: Optional[int] = None,
save: Optional[Union[str, pathlib.Path]] = None,
show: bool = True,
@@ -1050,7 +1051,7 @@ def plot_macrostate_composition(
mask = ~macrostates.isnull()
df = (
pd.DataFrame({"macrostates": macrostates, key: self.adata.obs[key]})[mask]
- .groupby([key, "macrostates"])
+ .groupby([key, "macrostates"], observed=False)
.size()
)
try:
@@ -1151,7 +1152,7 @@ def _create_states(
n_cells: int,
check_row_sums: bool = False,
return_not_enough_cells: bool = False,
- ) -> Union[pd.Series, Tuple[pd.Series, np.ndarray]]:
+ ) -> Union[pd.Series, tuple[pd.Series, np.ndarray]]:
if n_cells <= 0:
raise ValueError(f"Expected `n_cells` to be positive, found `{n_cells}`.")
@@ -1212,7 +1213,7 @@ def _set_macrostates(
cluster_key: str = "clusters",
check_row_sums: bool = True,
time: Optional[datetime.datetime] = None,
- params: Dict[str, Any] = types.MappingProxyType({}),
+ params: dict[str, Any] = types.MappingProxyType({}),
) -> None:
"""Map fuzzy clustering to pre-computed annotations to get names and colors.
@@ -1286,7 +1287,7 @@ def _write_macrostates(
macrostates: pd.Series,
colors: np.ndarray,
memberships: Lineage,
- params: Dict[str, Any] = types.MappingProxyType({}),
+ params: dict[str, Any] = types.MappingProxyType({}),
) -> str:
# fmt: off
key = Key.obs.macrostates(self.backward)
@@ -1321,7 +1322,7 @@ def _write_macrostates(
self._set("_coarse_stat_dist", value=stat_dist, shadow_only=True)
self._set(
obj=self.adata.uns, key=Key.uns.coarse(self.backward),
- value=AnnData(tmat, obs=dists),
+ value=AnnData(tmat, obs=dists), copy=False,
)
else:
for attr in ["_schur_vectors", "_schur_matrix", "_coarse_tmat", "_coarse_init_dist", "_coarse_stat_dist"]:
@@ -1350,7 +1351,7 @@ def _write_states(
colors: Optional[np.ndarray],
probs: Optional[pd.Series] = None,
memberships: Optional[Lineage] = None,
- params: Dict[str, Any] = types.MappingProxyType({}),
+ params: dict[str, Any] = types.MappingProxyType({}),
allow_overlap: bool = False,
) -> str:
msg = super()._write_states(
@@ -1412,7 +1413,7 @@ def _read_from_adata(self, adata: AnnData, **kwargs: Any) -> bool:
self._coarse_init_dist = tmat.obs["coarse_init_dist"]
self._coarse_stat_dist = tmat.obs.get("coarse_stat_dist", None)
- self._set(obj=self._shadow_adata.uns, key=Key.uns.coarse(self.backward), value=tmat)
+ self._set(obj=self._shadow_adata.uns, key=Key.uns.coarse(self.backward), value=tmat, copy=False)
if not sg.ok:
return False
diff --git a/src/cellrank/estimators/terminal_states/_term_states_estimator.py b/src/cellrank/estimators/terminal_states/_term_states_estimator.py
index c20db58a0..8898310cc 100644
--- a/src/cellrank/estimators/terminal_states/_term_states_estimator.py
+++ b/src/cellrank/estimators/terminal_states/_term_states_estimator.py
@@ -1,6 +1,7 @@
import abc
import types
-from typing import Any, Dict, Literal, Optional, Sequence, Tuple, Union
+from collections.abc import Sequence
+from typing import Any, Literal, Optional, Union
import scvelo as scv
@@ -92,7 +93,7 @@ def initial_states_probabilities(self) -> Optional[pd.Series]:
@d.dedent
def set_terminal_states(
self,
- states: Union[pd.Series, Dict[str, Sequence[Any]]],
+ states: Union[pd.Series, dict[str, Sequence[Any]]],
cluster_key: Optional[str] = None,
allow_overlap: bool = False,
**kwargs: Any,
@@ -141,7 +142,7 @@ def set_terminal_states(
@d.dedent
def set_initial_states(
self,
- states: Union[pd.Series, Dict[str, Sequence[Any]]],
+ states: Union[pd.Series, dict[str, Sequence[Any]]],
cluster_key: Optional[str] = None,
allow_overlap: bool = False,
**kwargs: Any,
@@ -190,7 +191,7 @@ def set_initial_states(
@d.get_sections(base="tse_rename_term_states", sections=["Parameters", "Returns"])
@d.get_full_description(base="tse_rename_term_states")
@d.dedent
- def rename_terminal_states(self, old_new: Dict[str, str]) -> "TermStatesEstimator":
+ def rename_terminal_states(self, old_new: dict[str, str]) -> "TermStatesEstimator":
"""Rename the :attr:`terminal_states`.
Parameters
@@ -244,7 +245,7 @@ def rename_terminal_states(self, old_new: Dict[str, str]) -> "TermStatesEstimato
return self
@d.dedent
- def rename_initial_states(self, old_new: Dict[str, str]) -> "TermStatesEstimator":
+ def rename_initial_states(self, old_new: dict[str, str]) -> "TermStatesEstimator":
"""Rename the :attr:`initial_states`.
Parameters
@@ -563,10 +564,10 @@ def _plot_continuous(
def _set_categorical_labels(
self,
- categories: Union[pd.Series, Dict[str, Any]],
+ categories: Union[pd.Series, dict[str, Any]],
cluster_key: Optional[str] = None,
existing: Optional[pd.Series] = None,
- ) -> Tuple[pd.Series, np.ndarray]:
+ ) -> tuple[pd.Series, np.ndarray]:
# fmt: off
if isinstance(categories, dict):
key = next(iter(categories.keys()))
@@ -625,7 +626,7 @@ def _write_states(
states: Optional[pd.Series],
colors: Optional[np.ndarray],
probs: Optional[pd.Series] = None,
- params: Dict[str, Any] = types.MappingProxyType({}),
+ params: dict[str, Any] = types.MappingProxyType({}),
allow_overlap: bool = False,
) -> str:
# fmt: off
diff --git a/src/cellrank/kernels/_base_kernel.py b/src/cellrank/kernels/_base_kernel.py
index 792a44132..63871ef32 100644
--- a/src/cellrank/kernels/_base_kernel.py
+++ b/src/cellrank/kernels/_base_kernel.py
@@ -1,7 +1,8 @@
import abc
import copy
import pathlib
-from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union
+from collections.abc import Sequence
+from typing import Any, Callable, Optional, Union
import numpy as np
import scipy.sparse as sp
@@ -34,7 +35,7 @@ def __init__(
self._parent = parent
self._normalize = parent is None
self._transition_matrix = None
- self._params: Dict[str, Any] = {}
+ self._params: dict[str, Any] = {}
self._init_kwargs = kwargs # for `_read_from_adata`
def __init_subclass__(cls, **_: Any) -> None:
@@ -72,12 +73,12 @@ def adata(self, value: Optional[AnnData]) -> None:
@property
@abc.abstractmethod
- def kernels(self) -> Tuple["KernelExpression", ...]:
+ def kernels(self) -> tuple["KernelExpression", ...]:
"""Underlying base kernels."""
@property
@abc.abstractmethod
- def shape(self) -> Tuple[int, int]:
+ def shape(self) -> tuple[int, int]:
"""``(n_cells, n_cells)``."""
@property
@@ -110,7 +111,7 @@ def plot_single_flow(
legend_loc: Optional[str] = "upper right out",
alpha: Optional[float] = 0.8,
xticks_step_size: Optional[int] = 1,
- figsize: Optional[Tuple[float, float]] = None,
+ figsize: Optional[tuple[float, float]] = None,
dpi: Optional[int] = None,
save: Optional[Union[str, pathlib.Path]] = None,
show: bool = True,
@@ -185,7 +186,7 @@ def plot_random_walks(
n_jobs: Optional[int] = None,
backend: str = "loky",
show_progress_bar: bool = True,
- figsize: Optional[Tuple[float, float]] = None,
+ figsize: Optional[tuple[float, float]] = None,
dpi: Optional[int] = None,
save: Optional[Union[str, pathlib.Path]] = None,
**kwargs: Any,
@@ -436,13 +437,13 @@ def should_norm(mat: Tmat_t) -> bool:
self._transition_matrix = matrix
@property
- def params(self) -> Dict[str, Any]:
+ def params(self) -> dict[str, Any]:
"""Parameters which are used to compute the transition matrix."""
if len(self.kernels) == 1:
return self._params
return {f"{k!r}:{i}": k.params for i, k in enumerate(self.kernels)}
- def _reuse_cache(self, expected_params: Dict[str, Any], *, time: Optional[Any] = None) -> bool:
+ def _reuse_cache(self, expected_params: dict[str, Any], *, time: Optional[Any] = None) -> bool:
# fmt: off
try:
if expected_params == self._params:
@@ -463,7 +464,7 @@ def _reuse_cache(self, expected_params: Dict[str, Any], *, time: Optional[Any] =
self._params = expected_params
# fmt: on
- def _get_boundary(self, source: str, target: str, cluster_key: str, graph_key: str = "distances") -> List[int]:
+ def _get_boundary(self, source: str, target: str, cluster_key: str, graph_key: str = "distances") -> list[int]:
"""Identify source observations at boundary to target cluster.
Parameters
@@ -497,7 +498,7 @@ def _get_boundary(self, source: str, target: str, cluster_key: str, graph_key: s
return boundary_ids
def _get_empirical_velocity_field(
- self, boundary_ids: List[int], target_obs_mask, rep: str, graph_key: str = "distances"
+ self, boundary_ids: list[int], target_obs_mask, rep: str, graph_key: str = "distances"
) -> np.ndarray:
"""Compute an emprical estimate of velocity field between two clusters.
@@ -531,9 +532,7 @@ def _get_empirical_velocity_field(
empirical_velo = np.array(empirical_velo)
obs_mask = np.isnan(empirical_velo).any(axis=1)
- empirical_velo = empirical_velo[~obs_mask, :]
-
- return empirical_velo
+ return empirical_velo[~obs_mask, :]
def _get_vector_field_estimate(self, rep: str) -> np.ndarray:
"""Compute estimate of vector field under one step of the transition matrix.
@@ -720,12 +719,12 @@ def transition_matrix(self, matrix: Any) -> None:
KernelExpression.transition_matrix.fset(self, matrix)
@property
- def kernels(self) -> Tuple["KernelExpression", ...]:
+ def kernels(self) -> tuple["KernelExpression", ...]:
"""Underlying base kernels."""
return (self,)
@property
- def shape(self) -> Tuple[int, int]:
+ def shape(self) -> tuple[int, int]:
"""``(n_cells, n_cells)``."""
return self._n_obs, self._n_obs
@@ -875,7 +874,7 @@ def adata(self, adata: Optional[AnnData]) -> None:
kexpr.adata = adata
@property
- def kernels(self) -> Tuple["KernelExpression", ...]:
+ def kernels(self) -> tuple["KernelExpression", ...]:
"""Underlying unique basic kernels."""
kernels = []
for kexpr in self:
@@ -892,7 +891,7 @@ def copy(self, *, deep: bool = False) -> "KernelExpression":
return type(self)(*kexprs, parent=self._parent)
@property
- def shape(self) -> Tuple[int, int]:
+ def shape(self) -> tuple[int, int]:
"""``(n_cells, n_cells)``."""
# all kernels have the same shape
return self[0].shape
@@ -944,7 +943,7 @@ def _maybe_recalculate_constants(self) -> None:
kexpr._normalize = False
@property
- def _bin_consts(self) -> List[KernelExpression]:
+ def _bin_consts(self) -> list[KernelExpression]:
"""Return constant expressions for each binary multiplication children with at least 1 constant."""
return [c for k in self if isinstance(k, KernelMul) for c in k._bin_consts]
@@ -976,7 +975,7 @@ def _format(self, formatter: Callable[[KernelExpression], str]) -> str:
return fmt
@property
- def _bin_consts(self) -> List[KernelExpression]:
+ def _bin_consts(self) -> list[KernelExpression]:
"""Return all constants if this expression contains only 2 subexpressions."""
if len(self) != 2:
return []
@@ -984,7 +983,7 @@ def _bin_consts(self) -> List[KernelExpression]:
return [k for k in self if isinstance(k, Constant)]
@property
- def _split_const(self) -> Tuple[Optional[Constant], Optional[KernelExpression]]:
+ def _split_const(self) -> tuple[Optional[Constant], Optional[KernelExpression]]:
"""Return a constant and the other expression, iff this expression is of length 2 and contains a constant."""
if not self._bin_consts:
return None, None
diff --git a/src/cellrank/kernels/_cytotrace_kernel.py b/src/cellrank/kernels/_cytotrace_kernel.py
index 686045d14..eeb5f0e0b 100644
--- a/src/cellrank/kernels/_cytotrace_kernel.py
+++ b/src/cellrank/kernels/_cytotrace_kernel.py
@@ -1,5 +1,5 @@
import enum
-from typing import Any, List, Literal, Optional, Tuple
+from typing import Any, Literal, Optional
import numpy as np
import pandas as pd
@@ -230,7 +230,7 @@ def _compute_score(
aggregation: CytoTRACEAggregation.MEAN,
ascending: bool = False,
n_genes: int = 200,
- ) -> Tuple[np.ndarray, List[str]]:
+ ) -> tuple[np.ndarray, list[str]]:
from sklearn.utils.sparsefuncs import csc_median_axis_0
# fmt: off
diff --git a/src/cellrank/kernels/_real_time_kernel.py b/src/cellrank/kernels/_real_time_kernel.py
index cc4849f3c..7ede541da 100644
--- a/src/cellrank/kernels/_real_time_kernel.py
+++ b/src/cellrank/kernels/_real_time_kernel.py
@@ -2,18 +2,8 @@
import os
import pathlib
import types
-from typing import (
- TYPE_CHECKING,
- Any,
- Dict,
- Iterable,
- Literal,
- Mapping,
- Optional,
- Sequence,
- Tuple,
- Union,
-)
+from collections.abc import Iterable, Mapping, Sequence
+from typing import TYPE_CHECKING, Any, Literal, Optional, Union
from tqdm.auto import tqdm
@@ -46,7 +36,7 @@ class SelfTransitions(ModeEnum):
ALL = "all"
-Key_t = Tuple[Any, Any]
+Key_t = tuple[Any, Any]
Threshold_t = Union[int, float, Literal["auto", "auto_local"]]
Coupling_t = Union[np.ndarray, sp.spmatrix, AnnData]
@@ -453,7 +443,7 @@ def _restich_couplings(
tmp.var_names = index
tmp = tmp[self.adata.obs_names, :][:, self.adata.obs_names]
- obs = pd.concat([obs.get(ix, None) for ix in range(len(blocks))])
+ obs = pd.concat([obs.get(ix) for ix in range(len(blocks))])
tmp.obs = pd.merge(
tmp.obs,
obs,
@@ -466,7 +456,7 @@ def _restich_couplings(
@d.get_sections(base="tmk_thresh", sections=["Parameters"])
def _sparsify_couplings(
self,
- couplings: Dict[Key_t, AnnData],
+ couplings: dict[Key_t, AnnData],
threshold: Threshold_t,
copy: bool = False,
) -> Optional[Mapping[Key_t, AnnData]]:
@@ -592,7 +582,7 @@ def _get_default_coupling(
self,
couplings: Optional[Mapping[Key_t, Optional[Coupling_t]]],
policy: Literal["sequential", "triu"],
- ) -> Tuple[Dict[Key_t, Optional[Coupling_t]], Any]:
+ ) -> tuple[dict[Key_t, Optional[Coupling_t]], Any]:
cats = self._time.cat.categories
if policy == "sequential":
if couplings is None:
@@ -618,7 +608,7 @@ def time(self) -> pd.Series:
return self._time
@property
- def couplings(self) -> Optional[Dict[Key_t, AnnData]]:
+ def couplings(self) -> Optional[dict[Key_t, AnnData]]:
"""Optimal transport couplings."""
return self._couplings
diff --git a/src/cellrank/kernels/_utils.py b/src/cellrank/kernels/_utils.py
index 7524d85df..783061178 100644
--- a/src/cellrank/kernels/_utils.py
+++ b/src/cellrank/kernels/_utils.py
@@ -126,7 +126,7 @@ def _get_basis(adata: AnnData, basis: str) -> np.ndarray:
def _ensure_numeric_ordered(adata: AnnData, key: str) -> pd.Series:
- if key not in adata.obs.keys():
+ if key not in adata.obs:
raise KeyError(f"Unable to find data in `adata.obs[{key!r}]`.")
exp_time = adata.obs[key].copy()
diff --git a/src/cellrank/kernels/_velocity_kernel.py b/src/cellrank/kernels/_velocity_kernel.py
index 50ec4ecd1..79c721dd6 100644
--- a/src/cellrank/kernels/_velocity_kernel.py
+++ b/src/cellrank/kernels/_velocity_kernel.py
@@ -1,4 +1,5 @@
-from typing import Any, Callable, Literal, Optional, Sequence, Tuple, Union
+from collections.abc import Sequence
+from typing import Any, Callable, Literal, Optional, Union
from scvelo.preprocessing.moments import get_moments
@@ -114,7 +115,7 @@ def compute_transition_matrix(
backward_mode: Literal["transpose", "negate"] = BackwardMode.TRANSPOSE,
similarity: Union[
Literal["correlation", "cosine", "dot_product"],
- Callable[[np.ndarray, np.ndarray, float], Tuple[np.ndarray, np.ndarray]],
+ Callable[[np.ndarray, np.ndarray, float], tuple[np.ndarray, np.ndarray]],
] = Similarity.CORRELATION,
softmax_scale: Optional[float] = None,
n_samples: int = 1000,
diff --git a/src/cellrank/kernels/mixins/_anndata.py b/src/cellrank/kernels/mixins/_anndata.py
index 6d8aedbbc..26869133a 100644
--- a/src/cellrank/kernels/mixins/_anndata.py
+++ b/src/cellrank/kernels/mixins/_anndata.py
@@ -35,12 +35,10 @@ def adata(self) -> AnnData:
@adata.setter
@abc.abstractmethod
- def adata(self, adata: Optional[AnnData]) -> None:
- ...
+ def adata(self, adata: Optional[AnnData]) -> None: ...
@abc.abstractmethod
- def __len__(self) -> int:
- ...
+ def __len__(self) -> int: ...
@abc.abstractmethod
@d.get_full_description(base="to_adata")
diff --git a/src/cellrank/kernels/mixins/_io.py b/src/cellrank/kernels/mixins/_io.py
index 85e777091..812bdc430 100644
--- a/src/cellrank/kernels/mixins/_io.py
+++ b/src/cellrank/kernels/mixins/_io.py
@@ -1,7 +1,7 @@
import contextlib
import pathlib
import pickle
-from typing import Optional, Protocol, Tuple, Union
+from typing import Optional, Protocol, Union
from anndata import AnnData
@@ -12,16 +12,13 @@
class IOMixinProtocol(Protocol):
@property
- def shape(self) -> Tuple[int, ...]:
- ...
+ def shape(self) -> tuple[int, ...]: ...
@property
- def adata(self) -> AnnData:
- ...
+ def adata(self) -> AnnData: ...
@adata.setter
- def adata(self, adata: AnnData) -> None:
- ...
+ def adata(self, adata: AnnData) -> None: ...
class IOMixin:
diff --git a/src/cellrank/kernels/utils/_pseudotime_scheme.py b/src/cellrank/kernels/utils/_pseudotime_scheme.py
index d6c304533..8255cb75c 100644
--- a/src/cellrank/kernels/utils/_pseudotime_scheme.py
+++ b/src/cellrank/kernels/utils/_pseudotime_scheme.py
@@ -1,5 +1,5 @@
import abc
-from typing import Any, Callable, Optional, Tuple
+from typing import Any, Callable, Optional
import numpy as np
import scipy.sparse as sp
@@ -46,7 +46,7 @@ def _bias_knn_helper(
pseudotime: np.ndarray,
queue=None,
**kwargs: Any,
- ) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
+ ) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
i, indices, indptr, data = 0, [], [], []
for i in ixs:
row = conn[i]
diff --git a/src/cellrank/kernels/utils/_random_walk.py b/src/cellrank/kernels/utils/_random_walk.py
index 1eca92b74..358af68e3 100644
--- a/src/cellrank/kernels/utils/_random_walk.py
+++ b/src/cellrank/kernels/utils/_random_walk.py
@@ -1,6 +1,7 @@
import itertools
import pathlib
-from typing import Any, List, Literal, Mapping, Optional, Sequence, Tuple, Union
+from collections.abc import Mapping, Sequence
+from typing import Any, Literal, Optional, Union
import scvelo as scv
@@ -23,7 +24,7 @@
__all__ = ["RandomWalk"]
-Indices_t = Optional[Union[Sequence[str], Mapping[str, Union[str, Sequence[str], Tuple[float, float]]]]]
+Indices_t = Optional[Union[Sequence[str], Mapping[str, Union[str, Sequence[str], tuple[float, float]]]]]
@d.dedent
@@ -101,7 +102,7 @@ def simulate_one(
if successive_hits < 0:
raise ValueError(f"Expected number of successive hits to be positive, found `{successive_hits}`.")
- rs = np.random.RandomState(seed)
+ rs = np.random.default_rng(seed)
ix = rs.choice(self._ixs, p=self._starting_dist)
sim, cnt = [ix], -1
@@ -121,7 +122,7 @@ def _simulate_many(
seed: Optional[int] = None,
successive_hits: int = 0,
queue: Optional[Any] = None,
- ) -> List[np.ndarray]:
+ ) -> list[np.ndarray]:
res = []
for s in sims:
sim = self.simulate_one(
@@ -148,7 +149,7 @@ def simulate_many(
n_jobs: Optional[int] = None,
backend: str = "loky",
show_progress_bar: bool = True,
- ) -> List[np.ndarray]:
+ ) -> list[np.ndarray]:
"""Simulate many random walks.
Parameters
@@ -186,13 +187,13 @@ def simulate_many(
@d.dedent
def plot(
self,
- sims: List[np.ndarray],
+ sims: list[np.ndarray],
basis: str = "umap",
cmap: Union[str, LinearSegmentedColormap] = "gnuplot",
linewidth: float = 1.0,
linealpha: float = 0.3,
ixs_legend_loc: Optional[str] = None,
- figsize: Optional[Tuple[float, float]] = None,
+ figsize: Optional[tuple[float, float]] = None,
dpi: Optional[int] = None,
save: Optional[Union[str, pathlib.Path]] = None,
**kwargs: Any,
@@ -336,7 +337,7 @@ def _normalize_ixs(self, ixs: Indices_t, *, kind: Literal["start", "stop"]) -> O
def _should_stop(self, ix: int) -> bool:
return ix in self._stop_ixs
- def _sample(self, ix: int, *, rs: np.random.RandomState) -> int:
+ def _sample(self, ix: int, *, rs: np.random.Generator) -> int:
return rs.choice(
self._ixs,
p=self._tmat[ix].toarray().squeeze() if self._is_sparse else self._tmat[ix],
diff --git a/src/cellrank/kernels/utils/_similarity.py b/src/cellrank/kernels/utils/_similarity.py
index 384b392db..724654dc0 100644
--- a/src/cellrank/kernels/utils/_similarity.py
+++ b/src/cellrank/kernels/utils/_similarity.py
@@ -1,7 +1,7 @@
import abc
import enum
import functools
-from typing import Any, Tuple
+from typing import Any
import numba as nb
import numpy as np
@@ -73,14 +73,14 @@ def _predict_transition_probabilities_jax(*_args, **_kwargs):
@nb.njit(**jit_kwargs)
-def _softmax(x: np.ndarray, softmax_scale: float) -> Tuple[np.ndarray, np.ndarray]:
+def _softmax(x: np.ndarray, softmax_scale: float) -> tuple[np.ndarray, np.ndarray]:
numerator = x * softmax_scale
numerator = np.exp(numerator - np.max(numerator))
return numerator / np.sum(numerator), x
@nb.njit(**jit_kwargs)
-def _softmax_masked(x: np.ndarray, mask: np.ndarray, softmax_scale: float) -> Tuple[np.ndarray, np.ndarray]:
+def _softmax_masked(x: np.ndarray, mask: np.ndarray, softmax_scale: float) -> tuple[np.ndarray, np.ndarray]:
numerator = x * softmax_scale
numerator = np.exp(numerator - np.nanmax(numerator))
numerator = np.where(mask, 0, numerator) # essential
@@ -95,7 +95,7 @@ def _predict_transition_probabilities_numpy(
softmax_scale: float = 1.0,
center_mean: bool = True,
scale_by_norm: bool = True,
-) -> Tuple[np.ndarray, np.ndarray]:
+) -> tuple[np.ndarray, np.ndarray]:
if center_mean:
# pearson correlation
W -= np.expand_dims(np_mean(W, axis=1), axis=1)
@@ -170,7 +170,7 @@ class SimilarityABC(abc.ABC):
@d.get_full_description(base="sim_scheme")
@d.get_sections(base="sim_scheme", sections=["Parameters", "Returns"])
@abc.abstractmethod
- def __call__(self, v: np.ndarray, D: np.ndarray, softmax_scale: float = 1.0) -> Tuple[np.ndarray, np.ndarray]:
+ def __call__(self, v: np.ndarray, D: np.ndarray, softmax_scale: float = 1.0) -> tuple[np.ndarray, np.ndarray]:
"""Compute transition probability of a cell to its nearest neighbors using RNA velocity.
Parameters
@@ -224,7 +224,7 @@ def __init__(self, center_mean: bool, scale_by_norm: bool):
self._scale_by_norm = scale_by_norm
@d.dedent
- def __call__(self, v: np.ndarray, D: np.ndarray, softmax_scale: float = 1.0) -> Tuple[np.ndarray, np.ndarray]:
+ def __call__(self, v: np.ndarray, D: np.ndarray, softmax_scale: float = 1.0) -> tuple[np.ndarray, np.ndarray]:
"""%(sim_scheme.full_desc)s
Parameters
diff --git a/src/cellrank/kernels/utils/_tmat_flow.py b/src/cellrank/kernels/utils/_tmat_flow.py
index a3c3f05ba..d12c9fd1f 100644
--- a/src/cellrank/kernels/utils/_tmat_flow.py
+++ b/src/cellrank/kernels/utils/_tmat_flow.py
@@ -1,5 +1,6 @@
import dataclasses
-from typing import Any, List, Mapping, Optional, Sequence, Tuple, Union
+from collections.abc import Mapping, Sequence
+from typing import Any, Optional, Union
import numpy as np
import pandas as pd
@@ -143,7 +144,7 @@ def prepare(
def compute_flow(
self,
- time_points: Sequence[Tuple[Numeric_t, Numeric_t]],
+ time_points: Sequence[tuple[Numeric_t, Numeric_t]],
cluster: Optional[str] = None,
) -> pd.DataFrame:
"""Compute outgoing flow.
@@ -179,7 +180,7 @@ def cluster_helper(t1: Numeric_t, t2: Numeric_t) -> pd.DataFrame:
subset, row_cls, col_cls = self._get_time_subset(t1, t2, cluster=cluster)
df = pd.DataFrame(subset.toarray() if sp.issparse(subset) else subset).sum(0)
- df = df.groupby(col_cls).sum()
+ df = df.groupby(col_cls, observed=False).sum()
df = pd.DataFrame([df], index=[cluster], columns=df.index)
res = pd.DataFrame(np.zeros((1, n)), index=[cluster], columns=categories)
@@ -219,7 +220,7 @@ def plot(
alpha: float = 0.8,
xticks_step_size: Optional[int] = 1,
legend_loc: Optional[str] = "upper right out",
- figsize: Optional[Tuple[float, float]] = None,
+ figsize: Optional[tuple[float, float]] = None,
dpi: Optional[int] = None,
) -> plt.Axes:
"""Plot outgoing flow.
@@ -275,7 +276,7 @@ def plot(
def _get_time_subset(
self, t1: Numeric_t, t2: Numeric_t, cluster: Optional[str] = None
- ) -> Tuple[Union[np.ndarray, sp.spmatrix], pd.Series, pd.Series]:
+ ) -> tuple[Union[np.ndarray, sp.spmatrix], pd.Series, pd.Series]:
if cluster is None:
row_ixs = np.where(self.time == t1)[0]
else:
@@ -306,7 +307,7 @@ def _rename_times(self) -> Sequence[Numeric_t]:
self._cmat.columns = tmp
return old_times
- def _order_clusters(self, cluster: str, ascending: Optional[bool] = False) -> Tuple[List[Any], List[Any]]:
+ def _order_clusters(self, cluster: str, ascending: Optional[bool] = False) -> tuple[list[Any], list[Any]]:
if ascending is not None:
tmp = [[], []]
total_flow = self._flow.loc[(slice(None), cluster), :].sum().sort_values(ascending=ascending)
@@ -329,7 +330,7 @@ def _plot_smoothed_proportion(
clusters: Sequence[Any],
y_offset: Mapping[Any, float],
alpha: float = 0.8,
- ) -> Tuple[Mapping[Any, np.ndarray], Mapping[Any, PolyCollection]]:
+ ) -> tuple[Mapping[Any, np.ndarray], Mapping[Any, PolyCollection]]:
start_t, end_t = self._cmat.columns.min(), self._cmat.columns.max()
x = np.array(self._cmat.columns) # fitting
# extrapolation
@@ -362,8 +363,8 @@ def _draw_flow_edge(
x2: Point,
y1: Point,
y2: Point,
- start_color: Tuple[float, float, float],
- end_color: Tuple[float, float, float],
+ start_color: tuple[float, float, float],
+ end_color: tuple[float, float, float],
flow: float,
alpha: float = 0.8,
) -> None:
@@ -416,7 +417,7 @@ def _plot(
alpha: float = 0.8,
xticks_step_size: Optional[int] = 1,
legend_loc: Optional[str] = "upper right out",
- figsize: Optional[Tuple[float, float]] = None,
+ figsize: Optional[tuple[float, float]] = None,
dpi: Optional[int] = None,
) -> plt.Axes:
from cellrank.pl._utils import _position_legend
diff --git a/src/cellrank/kernels/utils/_velocity_model.py b/src/cellrank/kernels/utils/_velocity_model.py
index be442434d..59167767b 100644
--- a/src/cellrank/kernels/utils/_velocity_model.py
+++ b/src/cellrank/kernels/utils/_velocity_model.py
@@ -1,7 +1,7 @@
import abc
import enum
import math
-from typing import Any, Callable, Optional, Tuple, Union
+from typing import Any, Callable, Optional, Union
import numpy as np
import scipy.sparse as sp
@@ -35,7 +35,7 @@ def __init__(
v: np.ndarray,
similarity: Union[
SimilarityABC,
- Callable[[np.ndarray, np.ndarray, float], Tuple[np.ndarray, np.ndarray]],
+ Callable[[np.ndarray, np.ndarray, float], tuple[np.ndarray, np.ndarray]],
],
backward_mode: Optional[BackwardMode] = None,
softmax_scale: float = 1.0,
@@ -50,7 +50,7 @@ def __init__(
self._dtype = dtype
@abc.abstractmethod
- def _compute(self, ix: int, neighs_ixs: np.ndarray, **kwargs: Any) -> Tuple[np.ndarray, np.ndarray]:
+ def _compute(self, ix: int, neighs_ixs: np.ndarray, **kwargs: Any) -> tuple[np.ndarray, np.ndarray]:
pass
def __call__(
@@ -59,7 +59,7 @@ def __call__(
backend: Backend_t = DEFAULT_BACKEND,
show_progress_bar: bool = True,
**kwargs: Any,
- ) -> Tuple[np.ndarray, np.ndarray]:
+ ) -> tuple[np.ndarray, np.ndarray]:
ixs = self._ixs
return parallelize(
self._compute_helper,
@@ -72,7 +72,7 @@ def __call__(
unit=self._unit,
)(**kwargs)
- def _compute_helper(self, ixs: np.ndarray, queue=None, **kwargs) -> Tuple[np.ndarray, np.ndarray]:
+ def _compute_helper(self, ixs: np.ndarray, queue=None, **kwargs) -> tuple[np.ndarray, np.ndarray]:
indptr, indices = self._conn.indptr, self._conn.indices
starts = _calculate_starts(indptr, ixs)
probs_logits = np.empty((2, starts[-1]), dtype=np.float64)
@@ -115,7 +115,7 @@ def _reconstruct_output(
The reconstructed CSR matrix.
"""
- def reconstruct(data: np.ndarray) -> Tuple[sp.csr_matrix, sp.csr_matrix]:
+ def reconstruct(data: np.ndarray) -> tuple[sp.csr_matrix, sp.csr_matrix]:
data = sp.csr_matrix(
(
np.array(data, copy=True),
@@ -152,7 +152,7 @@ def _ixs(self) -> np.ndarray:
rng.shuffle(ixs)
return ixs
- def _uniform(self, n: int) -> Tuple[np.ndarray, np.ndarray]:
+ def _uniform(self, n: int) -> tuple[np.ndarray, np.ndarray]:
"""Uninformative probability vector when velocity is 0."""
return np.ones(n, dtype=self._dtype) / n, np.zeros((n,), dtype=self._dtype)
@@ -165,7 +165,7 @@ def _unit(self) -> str:
class Deterministic(ModelABC):
"""Deterministic model."""
- def _compute(self, ix: int, neigh_ixs: np.ndarray) -> Tuple[np.ndarray, np.ndarray]:
+ def _compute(self, ix: int, neigh_ixs: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
W = self._x[neigh_ixs, :] - self._x[ix, :]
if self._backward_mode not in (None, BackwardMode.NEGATE):
@@ -218,7 +218,7 @@ def _compute(
self,
ix: int,
nbhs_ixs: np.ndarray,
- ) -> Tuple[np.ndarray, np.ndarray]:
+ ) -> tuple[np.ndarray, np.ndarray]:
v = self._v[ix]
n_neigh, n_feat = len(nbhs_ixs), self._x.shape[1]
@@ -308,7 +308,7 @@ def _compute(
self,
ix: int,
nbhs_ixs: np.ndarray,
- ) -> Tuple[np.ndarray, np.ndarray]:
+ ) -> tuple[np.ndarray, np.ndarray]:
n_neigh = len(nbhs_ixs)
W = self._x[nbhs_ixs, :] - self._x[ix, :]
diff --git a/src/cellrank/logging/_logging.py b/src/cellrank/logging/_logging.py
index 43b18fa18..11d3dc70d 100644
--- a/src/cellrank/logging/_logging.py
+++ b/src/cellrank/logging/_logging.py
@@ -1,7 +1,8 @@
import datetime
import functools
import logging
-from typing import Iterable, Optional
+from collections.abc import Iterable
+from typing import Optional
__all__ = [
"print_versions",
diff --git a/src/cellrank/models/_base_model.py b/src/cellrank/models/_base_model.py
index da4efb965..2b506b233 100644
--- a/src/cellrank/models/_base_model.py
+++ b/src/cellrank/models/_base_model.py
@@ -4,7 +4,8 @@
import enum
import re
import warnings
-from typing import Any, Callable, Dict, List, Mapping, Optional, Sequence, Tuple, Union
+from collections.abc import Mapping, Sequence
+from typing import Any, Callable, Optional, Union
import wrapt
@@ -32,7 +33,7 @@
__all__ = ["BaseModel"]
_dup_spaces = re.compile(r" +") # used on repr for underlying model's repr
-ArrayLike = Union[np.ndarray, sp.spmatrix, List, Tuple]
+ArrayLike = Union[np.ndarray, sp.spmatrix, list, tuple]
class UnknownModelError(RuntimeError):
@@ -126,7 +127,7 @@ def _(func: Callable):
class BaseModelMeta(abc.ABCMeta):
"""Metaclass for all base models."""
- def __new__(cls, clsname: str, superclasses: Tuple[type, ...], attributedict: Dict[str, Any]):
+ def __new__(cls, clsname: str, superclasses: tuple[type, ...], attributedict: dict[str, Any]):
"""Create a new instance.
Parameters
@@ -217,7 +218,7 @@ def adata(self, adata: Optional[AnnData]) -> None:
self._adata = adata
@property
- def shape(self) -> Tuple[int]:
+ def shape(self) -> tuple[int]:
"""Number of cells in :attr:`adata`."""
return (self._n_obs,)
@@ -301,11 +302,11 @@ def prepare(
lineage: Optional[str],
time_key: str,
backward: bool = False,
- time_range: Optional[Union[float, Tuple[float, float]]] = None,
+ time_range: Optional[Union[float, tuple[float, float]]] = None,
data_key: Optional[str] = "X",
use_raw: bool = False,
threshold: Optional[float] = None,
- weight_threshold: Union[float, Tuple[float, float]] = (0.01, 0.01),
+ weight_threshold: Union[float, tuple[float, float]] = (0.01, 0.01),
filter_cells: Optional[float] = None,
n_test_points: int = 200,
) -> "BaseModel":
@@ -668,10 +669,10 @@ def default_confidence_interval(
@d.dedent
def plot(
self,
- figsize: Tuple[float, float] = (8, 5),
+ figsize: tuple[float, float] = (8, 5),
same_plot: bool = False,
hide_cells: bool = False,
- perc: Tuple[float, float] = None,
+ perc: tuple[float, float] = None,
fate_prob_cmap: colors.ListedColormap = cm.viridis,
cell_color: Optional[str] = None,
lineage_color: str = "black",
@@ -1053,7 +1054,7 @@ def _get_colors(
key: Optional[str],
*,
same_plot: bool = False,
- ) -> Tuple[Optional[str], Optional[Union[str, np.ndarray]], ColorType, Optional[Dict[str, Any]],]:
+ ) -> tuple[Optional[str], Optional[Union[str, np.ndarray]], ColorType, Optional[dict[str, Any]]]:
"""
Get color array.
@@ -1237,7 +1238,7 @@ def _get_colors(
key: Optional[str],
*,
same_plot: bool = False,
- ) -> Tuple[Optional[str], Optional[Union[str, np.ndarray]], ColorType, Optional[Dict[str, Any]],]:
+ ) -> tuple[Optional[str], Optional[Union[str, np.ndarray]], ColorType, Optional[dict[str, Any]]]:
return None, "black", ColorType.STR, None
def _return_min_max(self, show_conf_int: bool):
@@ -1344,7 +1345,7 @@ def _get_colors(
key: Optional[str],
*,
same_plot: bool = False,
- ) -> Tuple[Optional[str], Optional[Union[str, np.ndarray]], ColorType, Optional[Dict[str, Any]],]:
+ ) -> tuple[Optional[str], Optional[Union[str, np.ndarray]], ColorType, Optional[dict[str, Any]]]:
# w_all does not need to be defined
if same_plot or self.w_all is None or np.allclose(self.w_all, 1.0):
return None, "black", ColorType.STR, None
diff --git a/src/cellrank/models/_gamr_model.py b/src/cellrank/models/_gamr_model.py
index fb072864f..6dd029be5 100644
--- a/src/cellrank/models/_gamr_model.py
+++ b/src/cellrank/models/_gamr_model.py
@@ -1,6 +1,6 @@
import copy
import enum
-from typing import Any, Literal, Optional, Tuple, Union
+from typing import Any, Literal, Optional, Union
import numpy as np
import pandas as pd
@@ -337,7 +337,7 @@ def __setstate__(self, state: dict):
self._lib, self._lib_name = _maybe_import_r_lib(self._lib_name, raise_exc=True)
-def _maybe_import_r_lib(name: str, raise_exc: bool = False) -> Tuple[Optional[Any], Optional[str]]:
+def _maybe_import_r_lib(name: str, raise_exc: bool = False) -> tuple[Optional[Any], Optional[str]]:
global _r_lib, _r_lib_name
if name == _r_lib_name and _r_lib is not None:
diff --git a/src/cellrank/models/_pygam_model.py b/src/cellrank/models/_pygam_model.py
index f7e179cac..0d13b6832 100644
--- a/src/cellrank/models/_pygam_model.py
+++ b/src/cellrank/models/_pygam_model.py
@@ -3,7 +3,8 @@
import enum
import types
import warnings
-from typing import Any, Literal, Mapping, Optional, Union
+from collections.abc import Mapping
+from typing import Any, Literal, Optional, Union
from pygam import GAM as pGAM
from pygam import (
diff --git a/src/cellrank/models/_sklearn_model.py b/src/cellrank/models/_sklearn_model.py
index d362f5de7..6f94c6ce6 100644
--- a/src/cellrank/models/_sklearn_model.py
+++ b/src/cellrank/models/_sklearn_model.py
@@ -1,6 +1,7 @@
import inspect
import warnings
-from typing import Any, Iterable, Optional
+from collections.abc import Iterable
+from typing import Any, Optional
import numpy as np
from sklearn.base import BaseEstimator
diff --git a/src/cellrank/models/_utils.py b/src/cellrank/models/_utils.py
index 38a5c34e8..d32ee07e8 100644
--- a/src/cellrank/models/_utils.py
+++ b/src/cellrank/models/_utils.py
@@ -1,5 +1,6 @@
import enum
-from typing import Any, Optional, Sequence, Union
+from collections.abc import Sequence
+from typing import Any, Optional, Union
import numba as nb
import numpy as np
diff --git a/src/cellrank/pl/_aggregate_fate_probs.py b/src/cellrank/pl/_aggregate_fate_probs.py
index 652aa08ef..d88a310f8 100644
--- a/src/cellrank/pl/_aggregate_fate_probs.py
+++ b/src/cellrank/pl/_aggregate_fate_probs.py
@@ -3,7 +3,8 @@
import math
import pathlib
import types
-from typing import Any, Literal, Mapping, Optional, Sequence, Tuple, Union
+from collections.abc import Mapping, Sequence
+from typing import Any, Literal, Optional, Union
from scvelo.plotting import paga
@@ -60,7 +61,7 @@ def aggregate_fate_probabilities(
fmt: str = "0.2f",
xrot: float = 90,
legend_kwargs: Mapping[str, Any] = types.MappingProxyType({"loc": "best"}),
- figsize: Optional[Tuple[float, float]] = None,
+ figsize: Optional[tuple[float, float]] = None,
dpi: Optional[int] = None,
save: Optional[Union[str, pathlib.Path]] = None,
**kwargs: Any,
diff --git a/src/cellrank/pl/_circular_projection.py b/src/cellrank/pl/_circular_projection.py
index 481db7f24..b467fd934 100644
--- a/src/cellrank/pl/_circular_projection.py
+++ b/src/cellrank/pl/_circular_projection.py
@@ -1,7 +1,8 @@
import enum
import pathlib
import types
-from typing import Any, Callable, Literal, Mapping, Optional, Sequence, Tuple, Union
+from collections.abc import Mapping, Sequence
+from typing import Any, Callable, Literal, Optional, Union
import scvelo as scv
@@ -62,7 +63,7 @@ def _get_distances(data: Union[np.ndarray, Lineage], metric: Metric_T) -> np.nda
return np.asarray(metric, dtype=np.float64)
-def _get_optimal_order(data: Lineage, metric: Metric_T) -> Tuple[float, np.ndarray]:
+def _get_optimal_order(data: Lineage, metric: Metric_T) -> tuple[float, np.ndarray]:
"""Solve the TSP using dynamic programming."""
return _held_karp(_get_distances(data, metric))
@@ -85,7 +86,7 @@ def circular_projection(
label_rot: Union[Literal["default", "best"], float] = "best",
show_edges: bool = True,
key_added: Optional[str] = None,
- figsize: Optional[Tuple[float, float]] = None,
+ figsize: Optional[tuple[float, float]] = None,
dpi: Optional[int] = None,
save: Optional[Union[str, pathlib.Path]] = None,
**kwargs: Any,
diff --git a/src/cellrank/pl/_cluster_trends.py b/src/cellrank/pl/_cluster_trends.py
index a6b2cc764..b133cca4e 100644
--- a/src/cellrank/pl/_cluster_trends.py
+++ b/src/cellrank/pl/_cluster_trends.py
@@ -1,6 +1,7 @@
import pathlib
import types
-from typing import Any, Dict, Optional, Sequence, Tuple, Union
+from collections.abc import Sequence
+from typing import Any, Optional, Union
import numpy as np
from sklearn.preprocessing import StandardScaler
@@ -63,12 +64,12 @@ def cluster_trends(
show_progress_bar: bool = True,
n_jobs: Optional[int] = 1,
backend: Backend_t = DEFAULT_BACKEND,
- figsize: Optional[Tuple[float, float]] = None,
+ figsize: Optional[tuple[float, float]] = None,
dpi: Optional[int] = None,
save: Optional[Union[str, pathlib.Path]] = None,
- pca_kwargs: Dict = types.MappingProxyType({"svd_solver": "arpack"}),
- neighbors_kwargs: Dict = types.MappingProxyType({"use_rep": "X"}),
- clustering_kwargs: Dict = types.MappingProxyType({}),
+ pca_kwargs: dict = types.MappingProxyType({"svd_solver": "arpack"}),
+ neighbors_kwargs: dict = types.MappingProxyType({"use_rep": "X"}),
+ clustering_kwargs: dict = types.MappingProxyType({}),
return_models: bool = False,
**kwargs: Any,
) -> Optional[_return_model_type]:
@@ -231,7 +232,7 @@ def plot_cluster(row: int, col: int, cluster: str, sharey_ax: Optional[str] = No
if trends.n_vars != n_points:
raise RuntimeError(f"Expected to find `{n_points}` points, found `{trends.n_vars}`.")
- random_state = np.random.RandomState(random_state).randint(2**16)
+ random_state = np.random.default_rng(random_state).integers(0, 2**16)
pca_kwargs = dict(pca_kwargs)
pca_kwargs.setdefault("n_comps", min(50, n_points, len(genes)) - 1)
diff --git a/src/cellrank/pl/_gene_trend.py b/src/cellrank/pl/_gene_trend.py
index 3c41107df..2ee2959f0 100644
--- a/src/cellrank/pl/_gene_trend.py
+++ b/src/cellrank/pl/_gene_trend.py
@@ -1,6 +1,7 @@
import pathlib
import types
-from typing import Any, List, Mapping, Optional, Sequence, Tuple, Union
+from collections.abc import Mapping, Sequence
+from typing import Any, Optional, Union
import numpy as np
import pandas as pd
@@ -47,13 +48,13 @@ def gene_trends(
lineages: Optional[Union[str, Sequence[str]]] = None,
backward: bool = False,
data_key: str = "X",
- time_range: Optional[Union[_time_range_type, List[_time_range_type]]] = None,
+ time_range: Optional[Union[_time_range_type, list[_time_range_type]]] = None,
transpose: bool = False,
callback: _callback_type = None,
conf_int: Union[bool, float] = True,
same_plot: bool = False,
hide_cells: bool = False,
- perc: Optional[Union[Tuple[float, float], Sequence[Tuple[float, float]]]] = None,
+ perc: Optional[Union[tuple[float, float], Sequence[tuple[float, float]]]] = None,
lineage_cmap: Optional[matplotlib.colors.ListedColormap] = None,
fate_prob_cmap: matplotlib.colors.ListedColormap = cm.viridis,
cell_color: Optional[str] = None,
@@ -74,7 +75,7 @@ def gene_trends(
n_jobs: Optional[int] = 1,
backend: Backend_t = DEFAULT_BACKEND,
show_progress_bar: bool = True,
- figsize: Optional[Tuple[float, float]] = None,
+ figsize: Optional[tuple[float, float]] = None,
dpi: Optional[int] = None,
save: Optional[Union[str, pathlib.Path]] = None,
return_figure: bool = False,
diff --git a/src/cellrank/pl/_heatmap.py b/src/cellrank/pl/_heatmap.py
index 37f72194a..26a87a0ac 100644
--- a/src/cellrank/pl/_heatmap.py
+++ b/src/cellrank/pl/_heatmap.py
@@ -3,7 +3,8 @@
import math
import os
import pathlib
-from typing import Any, Dict, List, Literal, Optional, Sequence, Tuple, Union
+from collections.abc import Sequence
+from typing import Any, Literal, Optional, Union
import numpy as np
import pandas as pd
@@ -64,7 +65,7 @@ def heatmap(
lineages: Optional[Union[str, Sequence[str]]] = None,
backward: bool = False,
mode: Literal["genes", "lineages"] = HeatmapMode.LINEAGES,
- time_range: Optional[Union[_time_range_type, List[_time_range_type]]] = None,
+ time_range: Optional[Union[_time_range_type, list[_time_range_type]]] = None,
callback: _callback_type = None,
cluster_key: Optional[Union[str, Sequence[str]]] = None,
show_fate_probabilities: bool = False,
@@ -86,12 +87,12 @@ def heatmap(
n_jobs: Optional[int] = 1,
backend: Backend_t = DEFAULT_BACKEND,
show_progress_bar: bool = True,
- figsize: Optional[Tuple[float, float]] = None,
+ figsize: Optional[tuple[float, float]] = None,
dpi: Optional[int] = None,
save: Optional[Union[str, pathlib.Path]] = None,
gene_order: Optional[Sequence[str]] = None,
**kwargs: Any,
-) -> Optional[Union[Dict[str, pd.DataFrame], Tuple[_return_model_type, Dict[str, pd.DataFrame]]]]:
+) -> Optional[Union[dict[str, pd.DataFrame], tuple[_return_model_type, dict[str, pd.DataFrame]]]]:
"""Plot a heatmap of smoothed gene expression along specified lineages.
.. seealso::
@@ -173,7 +174,7 @@ def heatmap(
- If ``return_figure = True``, returns a tuple containing the figure and genes.
"""
- def find_indices(series: pd.Series, values) -> List[int]:
+ def find_indices(series: pd.Series, values) -> list[int]:
def find_nearest(array: np.ndarray, value: float) -> int:
ix = np.searchsorted(array, value, side="left")
if ix > 0 and (ix == len(array) or math.fabs(value - array[ix - 1]) < math.fabs(value - array[ix])):
@@ -192,7 +193,7 @@ def subset_lineage(lname: str, rng: np.ndarray) -> np.ndarray:
return lin.copy()
return convolve(lin, np.ones(n_convolve) / n_convolve, mode="nearest")
- def create_col_colors(lname: str, rng: np.ndarray) -> Tuple[np.ndarray, colors.Colormap, colors.Normalize]:
+ def create_col_colors(lname: str, rng: np.ndarray) -> tuple[np.ndarray, colors.Colormap, colors.Normalize]:
color = probs[lname].colors[0]
lin = subset_lineage(lname, rng)
@@ -246,7 +247,7 @@ def _plot_heatmap(mode: HeatmapMode) -> plt.Figure:
raise NotImplementedError(mode.value)
@_plot_heatmap.register(HeatmapMode.GENES)
- def _() -> Tuple[plt.Figure, None]:
+ def _() -> tuple[plt.Figure, None]:
def color_fill_rec(ax, xs, y1, y2, colors=None, cmap=cmap, **kwargs) -> None:
colors = colors if cmap is None else cmap(colors)
@@ -349,7 +350,7 @@ def color_fill_rec(ax, xs, y1, y2, colors=None, cmap=cmap, **kwargs) -> None:
return fig, None
@_plot_heatmap.register(HeatmapMode.LINEAGES)
- def _(gene_order: Optional[Sequence[str]] = None) -> Tuple[List[plt.Figure], pd.DataFrame]:
+ def _(gene_order: Optional[Sequence[str]] = None) -> tuple[list[plt.Figure], pd.DataFrame]:
data_t = collections.defaultdict(dict) # transpose
for gene, lns in data.items():
for ln, y in lns.items():
diff --git a/src/cellrank/pl/_log_odds.py b/src/cellrank/pl/_log_odds.py
index 2f778dec8..85147bfdd 100644
--- a/src/cellrank/pl/_log_odds.py
+++ b/src/cellrank/pl/_log_odds.py
@@ -1,6 +1,7 @@
import copy
import pathlib
-from typing import Any, Iterable, List, Optional, Sequence, Tuple, Union
+from collections.abc import Iterable, Sequence
+from typing import Any, Optional, Union
import numpy as np
import pandas as pd
@@ -43,7 +44,7 @@ def log_odds(
legend_loc: Optional[str] = "best",
jitter: Union[bool, float] = True,
seed: Optional[int] = None,
- figsize: Optional[Tuple[float, float]] = None,
+ figsize: Optional[tuple[float, float]] = None,
dpi: Optional[int] = None,
save: Optional[Union[str, pathlib.Path]] = None,
show: bool = True,
@@ -120,7 +121,7 @@ def decorate(ax: Axes, *, title: Optional[str] = None, show_ylabel: bool = True)
ax.set_xticks(np.arange(0, n_cats, step))
ax.set_xticklabels(df[time_key].cat.categories[::step])
- def cont_palette(values: np.ndarray) -> Tuple[List[str], ScalarMappable]:
+ def cont_palette(values: np.ndarray) -> tuple[list[str], ScalarMappable]:
cm = copy.copy(plt.get_cmap(cmap))
cm.set_bad("grey")
sm = ScalarMappable(cmap=cm, norm=Normalize(vmin=np.nanmin(values), vmax=np.nanmax(values)))
@@ -129,7 +130,7 @@ def cont_palette(values: np.ndarray) -> Tuple[List[str], ScalarMappable]:
def get_data(
key: str,
thresh: Optional[float] = None,
- ) -> Tuple[Optional[str], Optional[np.ndarray], Optional[np.ndarray], ScalarMappable]:
+ ) -> tuple[Optional[str], Optional[np.ndarray], Optional[np.ndarray], ScalarMappable]:
try:
_, palette = _get_categorical_colors(adata, key)
df[key] = adata.obs[key].values[mask]
diff --git a/src/cellrank/pl/_utils.py b/src/cellrank/pl/_utils.py
index a58f286af..d4291d0b9 100644
--- a/src/cellrank/pl/_utils.py
+++ b/src/cellrank/pl/_utils.py
@@ -2,19 +2,8 @@
import copy
import itertools
import pathlib
-from typing import (
- Any,
- Callable,
- Dict,
- List,
- Mapping,
- NamedTuple,
- Optional,
- Sequence,
- Tuple,
- TypeVar,
- Union,
-)
+from collections.abc import Mapping, Sequence
+from typing import Any, Callable, NamedTuple, Optional, TypeVar, Union
import numpy as np
import pandas as pd
@@ -43,7 +32,7 @@
_ERROR_INCOMPLETE_SPEC = "No options were specified for {}. " "Consider specifying a fallback model using '*'."
-_time_range_type = Optional[Union[float, Tuple[Optional[float], Optional[float]]]]
+_time_range_type = Optional[Union[float, tuple[Optional[float], Optional[float]]]]
_return_model_type = Mapping[str, Mapping[str, BaseModel]]
_input_model_type = Union[BaseModel, _return_model_type]
_callback_type = Optional[Union[Callable, Mapping[str, Mapping[str, Callable]]]]
@@ -54,7 +43,7 @@ class BulkRes(NamedTuple):
y_test: np.ndarray
-def _is_any_gam_mgcv(models: Union[BaseModel, Dict[str, Dict[str, BaseModel]]]) -> bool:
+def _is_any_gam_mgcv(models: Union[BaseModel, dict[str, dict[str, BaseModel]]]) -> bool:
"""Return whether any models to be fit are from R's `mgcv` package.
Parameters
@@ -88,7 +77,7 @@ def _create_models(
The created models.
"""
- def process_lineages(obs_name: str, lin_names: Union[BaseModel, Dict[Optional[str], Any]]):
+ def process_lineages(obs_name: str, lin_names: Union[BaseModel, dict[Optional[str], Any]]):
if isinstance(lin_names, BaseModel):
# sharing the same models for all lineages
for lin_name in lineages:
@@ -181,11 +170,11 @@ def _fit_bulk_helper(
models: _input_model_type,
callbacks: _callback_type,
lineages: Sequence[Optional[str]],
- time_range: Sequence[Union[float, Tuple[float, float]]],
+ time_range: Sequence[Union[float, tuple[float, float]]],
return_models: bool = False,
queue: Optional[Queue] = None,
**kwargs,
-) -> Dict[str, Dict[str, BaseModel]]:
+) -> dict[str, dict[str, BaseModel]]:
"""Fit model for given genes and lineages.
Parameters
@@ -262,7 +251,7 @@ def _fit_bulk(
return_models: bool = False,
filter_all_failed: bool = True,
**kwargs,
-) -> Tuple[_return_model_type, _return_model_type, Sequence[str], Sequence[str]]:
+) -> tuple[_return_model_type, _return_model_type, Sequence[str], Sequence[str]]:
"""Fit models for given genes and lineages.
Parameters
@@ -333,7 +322,7 @@ def _fit_bulk(
def _filter_models(
models, return_models: bool = False, filter_all_failed: bool = True
-) -> Tuple[_return_model_type, _return_model_type, Sequence[str], Sequence[str]]:
+) -> tuple[_return_model_type, _return_model_type, Sequence[str], Sequence[str]]:
def is_valid(x: Union[BaseModel, BulkRes]) -> bool:
if return_models:
assert isinstance(x, BaseModel), f"Expected `BaseModel`, found `{type(x).__name__!r}`."
@@ -381,7 +370,7 @@ def is_valid(x: Union[BaseModel, BulkRes]) -> bool:
@d.dedent
def _trends_helper(
- models: Dict[str, Dict[str, Any]],
+ models: dict[str, dict[str, Any]],
gene: str,
transpose: bool = False,
lineage_names: Optional[Sequence[str]] = None,
@@ -700,7 +689,7 @@ def _create_callbacks(
lineages: Sequence[Optional[str]],
perform_sanity_check: Optional[bool] = None,
**kwargs,
-) -> Dict[str, Dict[str, Callable]]:
+) -> dict[str, dict[str, Callable]]:
"""Create models for each gene and lineage.
Parameters
@@ -724,7 +713,7 @@ def _create_callbacks(
The created callbacks.
"""
- def process_lineages(obs_name: str, lin_names: Optional[Union[Callable, Dict[Optional[str], Any]]]) -> None:
+ def process_lineages(obs_name: str, lin_names: Optional[Union[Callable, dict[Optional[str], Any]]]) -> None:
if lin_names is None:
lin_names = _default_model_callback
@@ -759,7 +748,7 @@ def process_lineages(obs_name: str, lin_names: Optional[Union[Callable, Dict[Opt
for lin_name in lineages - set(callbacks[obs_name].keys()):
callbacks[obs_name][lin_name] = lin_rest_callback
- def maybe_sanity_check(callbacks: Dict[str, Dict[str, Callable]]) -> None:
+ def maybe_sanity_check(callbacks: dict[str, dict[str, Callable]]) -> None:
if not perform_sanity_check:
return
@@ -869,7 +858,7 @@ def composition(
adata: AnnData,
key: str,
fontsize: Optional[str] = None,
- figsize: Optional[Tuple[float, float]] = None,
+ figsize: Optional[tuple[float, float]] = None,
dpi: Optional[float] = None,
save: Optional[Union[str, pathlib.Path]] = None,
**kwargs: Any,
@@ -916,7 +905,7 @@ def composition(
# modified from: https://github.com/CarlEkerot/held-karp
-def _held_karp(dists: np.ndarray) -> Tuple[float, np.ndarray]:
+def _held_karp(dists: np.ndarray) -> tuple[float, np.ndarray]:
"""Held-Karp algorithm solves the Traveling Salesman Problem.
This algorithm uses dynamic programming with memoization.
@@ -984,7 +973,7 @@ def _held_karp(dists: np.ndarray) -> Tuple[float, np.ndarray]:
return opt, np.array(path)[::-1]
-def _get_categorical_colors(adata: AnnData, cluster_key: str) -> Tuple[np.ndarray, Mapping[str, str]]:
+def _get_categorical_colors(adata: AnnData, cluster_key: str) -> tuple[np.ndarray, Mapping[str, str]]:
if cluster_key not in adata.obs:
raise KeyError(f"Unable to find data in `adata.obs[{cluster_key!r}].`")
if not isinstance(adata.obs[cluster_key].dtype, pd.CategoricalDtype):
@@ -1010,7 +999,7 @@ def _get_sorted_colors(
time_key: Optional[str] = None,
tmin: float = -np.inf,
tmax: float = np.inf,
-) -> List[np.ndarray]:
+) -> list[np.ndarray]:
if time_key is not None:
if time_key not in adata.obs:
raise KeyError(f"Unable to find time in `adata.obs[{time_key!r}]`.")
diff --git a/tests/_ground_truth_figures/all_models_for_1_gene_failed.png b/tests/_ground_truth_figures/all_models_for_1_gene_failed.png
index 32e5ddd55..3ac087d3e 100644
Binary files a/tests/_ground_truth_figures/all_models_for_1_gene_failed.png and b/tests/_ground_truth_figures/all_models_for_1_gene_failed.png differ
diff --git a/tests/_ground_truth_figures/all_models_for_1_gene_failed_same_plot.png b/tests/_ground_truth_figures/all_models_for_1_gene_failed_same_plot.png
index 05b828fcf..919fe84c5 100644
Binary files a/tests/_ground_truth_figures/all_models_for_1_gene_failed_same_plot.png and b/tests/_ground_truth_figures/all_models_for_1_gene_failed_same_plot.png differ
diff --git a/tests/_ground_truth_figures/all_models_for_1_lineage_failed.png b/tests/_ground_truth_figures/all_models_for_1_lineage_failed.png
index 7cdbbaafd..5cbe30401 100644
Binary files a/tests/_ground_truth_figures/all_models_for_1_lineage_failed.png and b/tests/_ground_truth_figures/all_models_for_1_lineage_failed.png differ
diff --git a/tests/_ground_truth_figures/bar.png b/tests/_ground_truth_figures/bar.png
index 3c987de22..7d40b52c0 100644
Binary files a/tests/_ground_truth_figures/bar.png and b/tests/_ground_truth_figures/bar.png differ
diff --git a/tests/_ground_truth_figures/bar_bwd.png b/tests/_ground_truth_figures/bar_bwd.png
index 7561d2dc2..045280570 100644
Binary files a/tests/_ground_truth_figures/bar_bwd.png and b/tests/_ground_truth_figures/bar_bwd.png differ
diff --git a/tests/_ground_truth_figures/bar_cluster_subset.png b/tests/_ground_truth_figures/bar_cluster_subset.png
index 9bad274b7..1b0d407fe 100644
Binary files a/tests/_ground_truth_figures/bar_cluster_subset.png and b/tests/_ground_truth_figures/bar_cluster_subset.png differ
diff --git a/tests/_ground_truth_figures/bar_cluster_subset_violin.png b/tests/_ground_truth_figures/bar_cluster_subset_violin.png
index 4a4a39c97..39ccfe6f4 100644
Binary files a/tests/_ground_truth_figures/bar_cluster_subset_violin.png and b/tests/_ground_truth_figures/bar_cluster_subset_violin.png differ
diff --git a/tests/_ground_truth_figures/bar_lineage_subset.png b/tests/_ground_truth_figures/bar_lineage_subset.png
index 2a623cb71..c1f78854b 100644
Binary files a/tests/_ground_truth_figures/bar_lineage_subset.png and b/tests/_ground_truth_figures/bar_lineage_subset.png differ
diff --git a/tests/_ground_truth_figures/cluster_lineage.png b/tests/_ground_truth_figures/cluster_lineage.png
index b7958e5e7..b762bc2ec 100644
Binary files a/tests/_ground_truth_figures/cluster_lineage.png and b/tests/_ground_truth_figures/cluster_lineage.png differ
diff --git a/tests/_ground_truth_figures/cluster_lineage_2_failed_genes.png b/tests/_ground_truth_figures/cluster_lineage_2_failed_genes.png
index 9604b9d03..2d464997e 100644
Binary files a/tests/_ground_truth_figures/cluster_lineage_2_failed_genes.png and b/tests/_ground_truth_figures/cluster_lineage_2_failed_genes.png differ
diff --git a/tests/_ground_truth_figures/cluster_lineage_bwd.png b/tests/_ground_truth_figures/cluster_lineage_bwd.png
index d1458493e..197133a42 100644
Binary files a/tests/_ground_truth_figures/cluster_lineage_bwd.png and b/tests/_ground_truth_figures/cluster_lineage_bwd.png differ
diff --git a/tests/_ground_truth_figures/cluster_lineage_covariates.png b/tests/_ground_truth_figures/cluster_lineage_covariates.png
index 44d56903e..e7f5afc1a 100644
Binary files a/tests/_ground_truth_figures/cluster_lineage_covariates.png and b/tests/_ground_truth_figures/cluster_lineage_covariates.png differ
diff --git a/tests/_ground_truth_figures/cluster_lineage_covariates_cmap.png b/tests/_ground_truth_figures/cluster_lineage_covariates_cmap.png
index ef654ad84..d8c3c44a0 100644
Binary files a/tests/_ground_truth_figures/cluster_lineage_covariates_cmap.png and b/tests/_ground_truth_figures/cluster_lineage_covariates_cmap.png differ
diff --git a/tests/_ground_truth_figures/cluster_lineage_covariates_ratio.png b/tests/_ground_truth_figures/cluster_lineage_covariates_ratio.png
index d9a8b6689..5aa99952d 100644
Binary files a/tests/_ground_truth_figures/cluster_lineage_covariates_ratio.png and b/tests/_ground_truth_figures/cluster_lineage_covariates_ratio.png differ
diff --git a/tests/_ground_truth_figures/cluster_lineage_data_key.png b/tests/_ground_truth_figures/cluster_lineage_data_key.png
index e71e36066..8f6ed48f7 100644
Binary files a/tests/_ground_truth_figures/cluster_lineage_data_key.png and b/tests/_ground_truth_figures/cluster_lineage_data_key.png differ
diff --git a/tests/_ground_truth_figures/cluster_lineage_gene_symbols.png b/tests/_ground_truth_figures/cluster_lineage_gene_symbols.png
index b7958e5e7..b762bc2ec 100644
Binary files a/tests/_ground_truth_figures/cluster_lineage_gene_symbols.png and b/tests/_ground_truth_figures/cluster_lineage_gene_symbols.png differ
diff --git a/tests/_ground_truth_figures/cluster_lineage_leiden.png b/tests/_ground_truth_figures/cluster_lineage_leiden.png
index b7958e5e7..b762bc2ec 100644
Binary files a/tests/_ground_truth_figures/cluster_lineage_leiden.png and b/tests/_ground_truth_figures/cluster_lineage_leiden.png differ
diff --git a/tests/_ground_truth_figures/cluster_lineage_no_norm.png b/tests/_ground_truth_figures/cluster_lineage_no_norm.png
index 155d5149d..81da5d7fa 100644
Binary files a/tests/_ground_truth_figures/cluster_lineage_no_norm.png and b/tests/_ground_truth_figures/cluster_lineage_no_norm.png differ
diff --git a/tests/_ground_truth_figures/cluster_lineage_random_state.png b/tests/_ground_truth_figures/cluster_lineage_random_state.png
index b7958e5e7..b762bc2ec 100644
Binary files a/tests/_ground_truth_figures/cluster_lineage_random_state.png and b/tests/_ground_truth_figures/cluster_lineage_random_state.png differ
diff --git a/tests/_ground_truth_figures/cluster_lineage_raw.png b/tests/_ground_truth_figures/cluster_lineage_raw.png
index e0ce86e25..318f038cf 100644
Binary files a/tests/_ground_truth_figures/cluster_lineage_raw.png and b/tests/_ground_truth_figures/cluster_lineage_raw.png differ
diff --git a/tests/_ground_truth_figures/composition.png b/tests/_ground_truth_figures/composition.png
index 135bd30fd..dc45a57ee 100644
Binary files a/tests/_ground_truth_figures/composition.png and b/tests/_ground_truth_figures/composition.png differ
diff --git a/tests/_ground_truth_figures/composition_kwargs_autopct.png b/tests/_ground_truth_figures/composition_kwargs_autopct.png
index 0433e24d7..b5cfb4a3c 100644
Binary files a/tests/_ground_truth_figures/composition_kwargs_autopct.png and b/tests/_ground_truth_figures/composition_kwargs_autopct.png differ
diff --git a/tests/_ground_truth_figures/driver_corr.png b/tests/_ground_truth_figures/driver_corr.png
index cc8734b38..f02566806 100644
Binary files a/tests/_ground_truth_figures/driver_corr.png and b/tests/_ground_truth_figures/driver_corr.png differ
diff --git a/tests/_ground_truth_figures/driver_corr_adjust_text.png b/tests/_ground_truth_figures/driver_corr_adjust_text.png
index dad583a49..68b597917 100644
Binary files a/tests/_ground_truth_figures/driver_corr_adjust_text.png and b/tests/_ground_truth_figures/driver_corr_adjust_text.png differ
diff --git a/tests/_ground_truth_figures/driver_corr_cmap.png b/tests/_ground_truth_figures/driver_corr_cmap.png
index fe4272456..0ce31701c 100644
Binary files a/tests/_ground_truth_figures/driver_corr_cmap.png and b/tests/_ground_truth_figures/driver_corr_cmap.png differ
diff --git a/tests/_ground_truth_figures/driver_corr_color.png b/tests/_ground_truth_figures/driver_corr_color.png
index f77888611..81ec9f24a 100644
Binary files a/tests/_ground_truth_figures/driver_corr_color.png and b/tests/_ground_truth_figures/driver_corr_color.png differ
diff --git a/tests/_ground_truth_figures/driver_corr_fontsize.png b/tests/_ground_truth_figures/driver_corr_fontsize.png
index 2ab2182ad..8bd39c266 100644
Binary files a/tests/_ground_truth_figures/driver_corr_fontsize.png and b/tests/_ground_truth_figures/driver_corr_fontsize.png differ
diff --git a/tests/_ground_truth_figures/driver_corr_gene_sets.png b/tests/_ground_truth_figures/driver_corr_gene_sets.png
index 5f1fa84b7..66883a8ee 100644
Binary files a/tests/_ground_truth_figures/driver_corr_gene_sets.png and b/tests/_ground_truth_figures/driver_corr_gene_sets.png differ
diff --git a/tests/_ground_truth_figures/driver_corr_gene_sets_colors.png b/tests/_ground_truth_figures/driver_corr_gene_sets_colors.png
index dbbf1da90..bb9fee2fc 100644
Binary files a/tests/_ground_truth_figures/driver_corr_gene_sets_colors.png and b/tests/_ground_truth_figures/driver_corr_gene_sets_colors.png differ
diff --git a/tests/_ground_truth_figures/driver_corr_legend_loc.png b/tests/_ground_truth_figures/driver_corr_legend_loc.png
index 210ce2c24..f8704e1b8 100644
Binary files a/tests/_ground_truth_figures/driver_corr_legend_loc.png and b/tests/_ground_truth_figures/driver_corr_legend_loc.png differ
diff --git a/tests/_ground_truth_figures/driver_corr_return_ax.png b/tests/_ground_truth_figures/driver_corr_return_ax.png
index 8915412c8..ec6289388 100644
Binary files a/tests/_ground_truth_figures/driver_corr_return_ax.png and b/tests/_ground_truth_figures/driver_corr_return_ax.png differ
diff --git a/tests/_ground_truth_figures/driver_corr_use_raw.png b/tests/_ground_truth_figures/driver_corr_use_raw.png
index 8cb5bb48d..c9c394d43 100644
Binary files a/tests/_ground_truth_figures/driver_corr_use_raw.png and b/tests/_ground_truth_figures/driver_corr_use_raw.png differ
diff --git a/tests/_ground_truth_figures/drivers_ascending.png b/tests/_ground_truth_figures/drivers_ascending.png
index 3130c22ba..0e7d62740 100644
Binary files a/tests/_ground_truth_figures/drivers_ascending.png and b/tests/_ground_truth_figures/drivers_ascending.png differ
diff --git a/tests/_ground_truth_figures/drivers_backward.png b/tests/_ground_truth_figures/drivers_backward.png
index fed53fcee..248f0ed17 100644
Binary files a/tests/_ground_truth_figures/drivers_backward.png and b/tests/_ground_truth_figures/drivers_backward.png differ
diff --git a/tests/_ground_truth_figures/drivers_cmap.png b/tests/_ground_truth_figures/drivers_cmap.png
index 77510a6ad..1efb8d0d6 100644
Binary files a/tests/_ground_truth_figures/drivers_cmap.png and b/tests/_ground_truth_figures/drivers_cmap.png differ
diff --git a/tests/_ground_truth_figures/drivers_n_genes.png b/tests/_ground_truth_figures/drivers_n_genes.png
index ec226e621..a9f363525 100644
Binary files a/tests/_ground_truth_figures/drivers_n_genes.png and b/tests/_ground_truth_figures/drivers_n_genes.png differ
diff --git a/tests/_ground_truth_figures/drivers_title_fmt.png b/tests/_ground_truth_figures/drivers_title_fmt.png
index 979b16d2e..b1499d6a8 100644
Binary files a/tests/_ground_truth_figures/drivers_title_fmt.png and b/tests/_ground_truth_figures/drivers_title_fmt.png differ
diff --git a/tests/_ground_truth_figures/failed_only_main_diagonal.png b/tests/_ground_truth_figures/failed_only_main_diagonal.png
index ce31a3724..4830c908e 100644
Binary files a/tests/_ground_truth_figures/failed_only_main_diagonal.png and b/tests/_ground_truth_figures/failed_only_main_diagonal.png differ
diff --git a/tests/_ground_truth_figures/failed_only_off_diagonal.png b/tests/_ground_truth_figures/failed_only_off_diagonal.png
index bc91efc07..ea350f39a 100644
Binary files a/tests/_ground_truth_figures/failed_only_off_diagonal.png and b/tests/_ground_truth_figures/failed_only_off_diagonal.png differ
diff --git a/tests/_ground_truth_figures/fitted_cluster_fates.png b/tests/_ground_truth_figures/fitted_cluster_fates.png
index 6da02b19e..0f3e80e3a 100644
Binary files a/tests/_ground_truth_figures/fitted_cluster_fates.png and b/tests/_ground_truth_figures/fitted_cluster_fates.png differ
diff --git a/tests/_ground_truth_figures/fitted_empty_model.png b/tests/_ground_truth_figures/fitted_empty_model.png
index f3e326419..adf950b78 100644
Binary files a/tests/_ground_truth_figures/fitted_empty_model.png and b/tests/_ground_truth_figures/fitted_empty_model.png differ
diff --git a/tests/_ground_truth_figures/fitted_gene_trends.png b/tests/_ground_truth_figures/fitted_gene_trends.png
index bc219f660..3df98e202 100644
Binary files a/tests/_ground_truth_figures/fitted_gene_trends.png and b/tests/_ground_truth_figures/fitted_gene_trends.png differ
diff --git a/tests/_ground_truth_figures/fitted_heatmap/lineage_0.png b/tests/_ground_truth_figures/fitted_heatmap/lineage_0.png
index fbcf61c5b..54d0d376b 100644
Binary files a/tests/_ground_truth_figures/fitted_heatmap/lineage_0.png and b/tests/_ground_truth_figures/fitted_heatmap/lineage_0.png differ
diff --git a/tests/_ground_truth_figures/fitted_heatmap/lineage_1.png b/tests/_ground_truth_figures/fitted_heatmap/lineage_1.png
index 251bb10d2..e55b68e45 100644
Binary files a/tests/_ground_truth_figures/fitted_heatmap/lineage_1.png and b/tests/_ground_truth_figures/fitted_heatmap/lineage_1.png differ
diff --git a/tests/_ground_truth_figures/fitted_heatmap/lineage_2.png b/tests/_ground_truth_figures/fitted_heatmap/lineage_2.png
index 35b42fe7a..9daae28a5 100644
Binary files a/tests/_ground_truth_figures/fitted_heatmap/lineage_2.png and b/tests/_ground_truth_figures/fitted_heatmap/lineage_2.png differ
diff --git a/tests/_ground_truth_figures/fitted_ignore_plot_smoothed_lineage.png b/tests/_ground_truth_figures/fitted_ignore_plot_smoothed_lineage.png
index 85101424e..430afea59 100644
Binary files a/tests/_ground_truth_figures/fitted_ignore_plot_smoothed_lineage.png and b/tests/_ground_truth_figures/fitted_ignore_plot_smoothed_lineage.png differ
diff --git a/tests/_ground_truth_figures/fitted_model_cells_with_weights.png b/tests/_ground_truth_figures/fitted_model_cells_with_weights.png
index 009730d49..60023c9de 100644
Binary files a/tests/_ground_truth_figures/fitted_model_cells_with_weights.png and b/tests/_ground_truth_figures/fitted_model_cells_with_weights.png differ
diff --git a/tests/_ground_truth_figures/fitted_model_conf_int.png b/tests/_ground_truth_figures/fitted_model_conf_int.png
index 6ba11ad4f..ee6059851 100644
Binary files a/tests/_ground_truth_figures/fitted_model_conf_int.png and b/tests/_ground_truth_figures/fitted_model_conf_int.png differ
diff --git a/tests/_ground_truth_figures/fitted_model_conf_int_no_conf_int_computed.png b/tests/_ground_truth_figures/fitted_model_conf_int_no_conf_int_computed.png
index bcdccee00..c539fa041 100644
Binary files a/tests/_ground_truth_figures/fitted_model_conf_int_no_conf_int_computed.png and b/tests/_ground_truth_figures/fitted_model_conf_int_no_conf_int_computed.png differ
diff --git a/tests/_ground_truth_figures/fitted_model_weights.png b/tests/_ground_truth_figures/fitted_model_weights.png
index 78115ef59..12381d49d 100644
Binary files a/tests/_ground_truth_figures/fitted_model_weights.png and b/tests/_ground_truth_figures/fitted_model_weights.png differ
diff --git a/tests/_ground_truth_figures/flow_alpha.png b/tests/_ground_truth_figures/flow_alpha.png
index 4806b89cd..6858e6f1b 100644
Binary files a/tests/_ground_truth_figures/flow_alpha.png and b/tests/_ground_truth_figures/flow_alpha.png differ
diff --git a/tests/_ground_truth_figures/flow_cluster_ascending.png b/tests/_ground_truth_figures/flow_cluster_ascending.png
index 019c27616..4493ea38a 100644
Binary files a/tests/_ground_truth_figures/flow_cluster_ascending.png and b/tests/_ground_truth_figures/flow_cluster_ascending.png differ
diff --git a/tests/_ground_truth_figures/flow_cluster_descending.png b/tests/_ground_truth_figures/flow_cluster_descending.png
index e582b098b..ecb15f4da 100644
Binary files a/tests/_ground_truth_figures/flow_cluster_descending.png and b/tests/_ground_truth_figures/flow_cluster_descending.png differ
diff --git a/tests/_ground_truth_figures/flow_clusters_subset.png b/tests/_ground_truth_figures/flow_clusters_subset.png
index 13a68ac2d..781477469 100644
Binary files a/tests/_ground_truth_figures/flow_clusters_subset.png and b/tests/_ground_truth_figures/flow_clusters_subset.png differ
diff --git a/tests/_ground_truth_figures/flow_explicit_cluster_order.png b/tests/_ground_truth_figures/flow_explicit_cluster_order.png
index 21ae53b15..9830ec7c1 100644
Binary files a/tests/_ground_truth_figures/flow_explicit_cluster_order.png and b/tests/_ground_truth_figures/flow_explicit_cluster_order.png differ
diff --git a/tests/_ground_truth_figures/flow_legend_loc.png b/tests/_ground_truth_figures/flow_legend_loc.png
index ea6d16793..54f5baf33 100644
Binary files a/tests/_ground_truth_figures/flow_legend_loc.png and b/tests/_ground_truth_figures/flow_legend_loc.png differ
diff --git a/tests/_ground_truth_figures/flow_min_flow_keep_empty_clusters.png b/tests/_ground_truth_figures/flow_min_flow_keep_empty_clusters.png
index fcb4db4d3..b48fba5bc 100644
Binary files a/tests/_ground_truth_figures/flow_min_flow_keep_empty_clusters.png and b/tests/_ground_truth_figures/flow_min_flow_keep_empty_clusters.png differ
diff --git a/tests/_ground_truth_figures/flow_min_flow_remove_empty_clusters.png b/tests/_ground_truth_figures/flow_min_flow_remove_empty_clusters.png
index 320e83d72..4e53f8ae2 100644
Binary files a/tests/_ground_truth_figures/flow_min_flow_remove_empty_clusters.png and b/tests/_ground_truth_figures/flow_min_flow_remove_empty_clusters.png differ
diff --git a/tests/_ground_truth_figures/flow_no_xticks.png b/tests/_ground_truth_figures/flow_no_xticks.png
index e34fb5c7a..9af572e45 100644
Binary files a/tests/_ground_truth_figures/flow_no_xticks.png and b/tests/_ground_truth_figures/flow_no_xticks.png differ
diff --git a/tests/_ground_truth_figures/flow_return_ax.png b/tests/_ground_truth_figures/flow_return_ax.png
index e582b098b..ecb15f4da 100644
Binary files a/tests/_ground_truth_figures/flow_return_ax.png and b/tests/_ground_truth_figures/flow_return_ax.png differ
diff --git a/tests/_ground_truth_figures/flow_source_clusters.png b/tests/_ground_truth_figures/flow_source_clusters.png
index 9476a5bb8..1b97911b2 100644
Binary files a/tests/_ground_truth_figures/flow_source_clusters.png and b/tests/_ground_truth_figures/flow_source_clusters.png differ
diff --git a/tests/_ground_truth_figures/flow_time_categories_too_close.png b/tests/_ground_truth_figures/flow_time_categories_too_close.png
index a413ef1a8..b1dd21335 100644
Binary files a/tests/_ground_truth_figures/flow_time_categories_too_close.png and b/tests/_ground_truth_figures/flow_time_categories_too_close.png differ
diff --git a/tests/_ground_truth_figures/gamr_ci_50.png b/tests/_ground_truth_figures/gamr_ci_50.png
index 51435064a..95312d01a 100644
Binary files a/tests/_ground_truth_figures/gamr_ci_50.png and b/tests/_ground_truth_figures/gamr_ci_50.png differ
diff --git a/tests/_ground_truth_figures/gamr_default.png b/tests/_ground_truth_figures/gamr_default.png
index 1d066cc85..e3cfeb9e7 100644
Binary files a/tests/_ground_truth_figures/gamr_default.png and b/tests/_ground_truth_figures/gamr_default.png differ
diff --git a/tests/_ground_truth_figures/gamr_lineage_prob.png b/tests/_ground_truth_figures/gamr_lineage_prob.png
index 4f6c9476a..7e5e03f3b 100644
Binary files a/tests/_ground_truth_figures/gamr_lineage_prob.png and b/tests/_ground_truth_figures/gamr_lineage_prob.png differ
diff --git a/tests/_ground_truth_figures/gamr_no_cbar.png b/tests/_ground_truth_figures/gamr_no_cbar.png
index dad431d9a..794f01b51 100644
Binary files a/tests/_ground_truth_figures/gamr_no_cbar.png and b/tests/_ground_truth_figures/gamr_no_cbar.png differ
diff --git a/tests/_ground_truth_figures/gamr_no_ci.png b/tests/_ground_truth_figures/gamr_no_ci.png
index 1d066cc85..e3cfeb9e7 100644
Binary files a/tests/_ground_truth_figures/gamr_no_ci.png and b/tests/_ground_truth_figures/gamr_no_ci.png differ
diff --git a/tests/_ground_truth_figures/gpcca_coarse_T.png b/tests/_ground_truth_figures/gpcca_coarse_T.png
index 08dce566f..705d1dd2c 100644
Binary files a/tests/_ground_truth_figures/gpcca_coarse_T.png and b/tests/_ground_truth_figures/gpcca_coarse_T.png differ
diff --git a/tests/_ground_truth_figures/gpcca_coarse_T_cmap.png b/tests/_ground_truth_figures/gpcca_coarse_T_cmap.png
index fc52ed698..d859a2af3 100644
Binary files a/tests/_ground_truth_figures/gpcca_coarse_T_cmap.png and b/tests/_ground_truth_figures/gpcca_coarse_T_cmap.png differ
diff --git a/tests/_ground_truth_figures/gpcca_coarse_T_init_dist.png b/tests/_ground_truth_figures/gpcca_coarse_T_init_dist.png
index e05ef7cf1..dc0d7e181 100644
Binary files a/tests/_ground_truth_figures/gpcca_coarse_T_init_dist.png and b/tests/_ground_truth_figures/gpcca_coarse_T_init_dist.png differ
diff --git a/tests/_ground_truth_figures/gpcca_coarse_T_no_annot.png b/tests/_ground_truth_figures/gpcca_coarse_T_no_annot.png
index 0a78da6bf..8f3e30177 100644
Binary files a/tests/_ground_truth_figures/gpcca_coarse_T_no_annot.png and b/tests/_ground_truth_figures/gpcca_coarse_T_no_annot.png differ
diff --git a/tests/_ground_truth_figures/gpcca_coarse_T_no_cbar.png b/tests/_ground_truth_figures/gpcca_coarse_T_no_cbar.png
index 86beae235..a60b066b1 100644
Binary files a/tests/_ground_truth_figures/gpcca_coarse_T_no_cbar.png and b/tests/_ground_truth_figures/gpcca_coarse_T_no_cbar.png differ
diff --git a/tests/_ground_truth_figures/gpcca_coarse_T_no_order.png b/tests/_ground_truth_figures/gpcca_coarse_T_no_order.png
index 366d88cab..ca9531e0f 100644
Binary files a/tests/_ground_truth_figures/gpcca_coarse_T_no_order.png and b/tests/_ground_truth_figures/gpcca_coarse_T_no_order.png differ
diff --git a/tests/_ground_truth_figures/gpcca_coarse_T_stat_dist.png b/tests/_ground_truth_figures/gpcca_coarse_T_stat_dist.png
index 366d88cab..ca9531e0f 100644
Binary files a/tests/_ground_truth_figures/gpcca_coarse_T_stat_dist.png and b/tests/_ground_truth_figures/gpcca_coarse_T_stat_dist.png differ
diff --git a/tests/_ground_truth_figures/gpcca_coarse_T_stat_init_dist.png b/tests/_ground_truth_figures/gpcca_coarse_T_stat_init_dist.png
index 209eeef5e..3610ee765 100644
Binary files a/tests/_ground_truth_figures/gpcca_coarse_T_stat_init_dist.png and b/tests/_ground_truth_figures/gpcca_coarse_T_stat_init_dist.png differ
diff --git a/tests/_ground_truth_figures/gpcca_coarse_T_xtick_rot.png b/tests/_ground_truth_figures/gpcca_coarse_T_xtick_rot.png
index e01f14919..cfc2052b2 100644
Binary files a/tests/_ground_truth_figures/gpcca_coarse_T_xtick_rot.png and b/tests/_ground_truth_figures/gpcca_coarse_T_xtick_rot.png differ
diff --git a/tests/_ground_truth_figures/gpcca_complex_spectrum.png b/tests/_ground_truth_figures/gpcca_complex_spectrum.png
index 7d549a203..298be848d 100644
Binary files a/tests/_ground_truth_figures/gpcca_complex_spectrum.png and b/tests/_ground_truth_figures/gpcca_complex_spectrum.png differ
diff --git a/tests/_ground_truth_figures/gpcca_real_spectrum.png b/tests/_ground_truth_figures/gpcca_real_spectrum.png
index 8a7ab9d1e..0ba696b12 100644
Binary files a/tests/_ground_truth_figures/gpcca_real_spectrum.png and b/tests/_ground_truth_figures/gpcca_real_spectrum.png differ
diff --git a/tests/_ground_truth_figures/gpcca_real_spectrum_hide_eigengap.png b/tests/_ground_truth_figures/gpcca_real_spectrum_hide_eigengap.png
index 7950420a6..38db2e21b 100644
Binary files a/tests/_ground_truth_figures/gpcca_real_spectrum_hide_eigengap.png and b/tests/_ground_truth_figures/gpcca_real_spectrum_hide_eigengap.png differ
diff --git a/tests/_ground_truth_figures/gpcca_schur_matrix.png b/tests/_ground_truth_figures/gpcca_schur_matrix.png
index fb39bd63e..749880946 100644
Binary files a/tests/_ground_truth_figures/gpcca_schur_matrix.png and b/tests/_ground_truth_figures/gpcca_schur_matrix.png differ
diff --git a/tests/_ground_truth_figures/gpcca_schur_matrix_cmap.png b/tests/_ground_truth_figures/gpcca_schur_matrix_cmap.png
index 80f44d33e..72a76a43f 100644
Binary files a/tests/_ground_truth_figures/gpcca_schur_matrix_cmap.png and b/tests/_ground_truth_figures/gpcca_schur_matrix_cmap.png differ
diff --git a/tests/_ground_truth_figures/gpcca_schur_matrix_title.png b/tests/_ground_truth_figures/gpcca_schur_matrix_title.png
index 5bd651368..7995f02f6 100644
Binary files a/tests/_ground_truth_figures/gpcca_schur_matrix_title.png and b/tests/_ground_truth_figures/gpcca_schur_matrix_title.png differ
diff --git a/tests/_ground_truth_figures/gpcca_spectrum_evals.png b/tests/_ground_truth_figures/gpcca_spectrum_evals.png
index 4df2e30aa..05e1f3f75 100644
Binary files a/tests/_ground_truth_figures/gpcca_spectrum_evals.png and b/tests/_ground_truth_figures/gpcca_spectrum_evals.png differ
diff --git a/tests/_ground_truth_figures/gpcca_spectrum_evals_complex.png b/tests/_ground_truth_figures/gpcca_spectrum_evals_complex.png
index 27e26e135..054bbd82b 100644
Binary files a/tests/_ground_truth_figures/gpcca_spectrum_evals_complex.png and b/tests/_ground_truth_figures/gpcca_spectrum_evals_complex.png differ
diff --git a/tests/_ground_truth_figures/gpcca_spectrum_title.png b/tests/_ground_truth_figures/gpcca_spectrum_title.png
index 1903276a5..420756f70 100644
Binary files a/tests/_ground_truth_figures/gpcca_spectrum_title.png and b/tests/_ground_truth_figures/gpcca_spectrum_title.png differ
diff --git a/tests/_ground_truth_figures/heatmap_cluster_genes.png b/tests/_ground_truth_figures/heatmap_cluster_genes.png
index 726562141..ec80b3405 100644
Binary files a/tests/_ground_truth_figures/heatmap_cluster_genes.png and b/tests/_ground_truth_figures/heatmap_cluster_genes.png differ
diff --git a/tests/_ground_truth_figures/heatmap_cluster_key_fate_probs/lineage_0.png b/tests/_ground_truth_figures/heatmap_cluster_key_fate_probs/lineage_0.png
index 3ae10cf95..678030743 100644
Binary files a/tests/_ground_truth_figures/heatmap_cluster_key_fate_probs/lineage_0.png and b/tests/_ground_truth_figures/heatmap_cluster_key_fate_probs/lineage_0.png differ
diff --git a/tests/_ground_truth_figures/heatmap_cluster_key_fate_probs/lineage_1.png b/tests/_ground_truth_figures/heatmap_cluster_key_fate_probs/lineage_1.png
index 16b52fc7e..fa308138e 100644
Binary files a/tests/_ground_truth_figures/heatmap_cluster_key_fate_probs/lineage_1.png and b/tests/_ground_truth_figures/heatmap_cluster_key_fate_probs/lineage_1.png differ
diff --git a/tests/_ground_truth_figures/heatmap_cluster_key_fate_probs/lineage_2.png b/tests/_ground_truth_figures/heatmap_cluster_key_fate_probs/lineage_2.png
index 4d15c8670..bc4d73ce3 100644
Binary files a/tests/_ground_truth_figures/heatmap_cluster_key_fate_probs/lineage_2.png and b/tests/_ground_truth_figures/heatmap_cluster_key_fate_probs/lineage_2.png differ
diff --git a/tests/_ground_truth_figures/heatmap_cluster_key_no_fate_probs/lineage_0.png b/tests/_ground_truth_figures/heatmap_cluster_key_no_fate_probs/lineage_0.png
index c9dae9631..433688400 100644
Binary files a/tests/_ground_truth_figures/heatmap_cluster_key_no_fate_probs/lineage_0.png and b/tests/_ground_truth_figures/heatmap_cluster_key_no_fate_probs/lineage_0.png differ
diff --git a/tests/_ground_truth_figures/heatmap_cluster_key_no_fate_probs/lineage_1.png b/tests/_ground_truth_figures/heatmap_cluster_key_no_fate_probs/lineage_1.png
index 11229e05e..58788305e 100644
Binary files a/tests/_ground_truth_figures/heatmap_cluster_key_no_fate_probs/lineage_1.png and b/tests/_ground_truth_figures/heatmap_cluster_key_no_fate_probs/lineage_1.png differ
diff --git a/tests/_ground_truth_figures/heatmap_cluster_key_no_fate_probs/lineage_2.png b/tests/_ground_truth_figures/heatmap_cluster_key_no_fate_probs/lineage_2.png
index f96d45903..1b0d84c6d 100644
Binary files a/tests/_ground_truth_figures/heatmap_cluster_key_no_fate_probs/lineage_2.png and b/tests/_ground_truth_figures/heatmap_cluster_key_no_fate_probs/lineage_2.png differ
diff --git a/tests/_ground_truth_figures/heatmap_cluster_no_scale.png b/tests/_ground_truth_figures/heatmap_cluster_no_scale.png
index 75ae28224..58fb80c44 100644
Binary files a/tests/_ground_truth_figures/heatmap_cluster_no_scale.png and b/tests/_ground_truth_figures/heatmap_cluster_no_scale.png differ
diff --git a/tests/_ground_truth_figures/heatmap_cmap.png b/tests/_ground_truth_figures/heatmap_cmap.png
index c21cfbacf..88093ec76 100644
Binary files a/tests/_ground_truth_figures/heatmap_cmap.png and b/tests/_ground_truth_figures/heatmap_cmap.png differ
diff --git a/tests/_ground_truth_figures/heatmap_fate_probs_genes.png b/tests/_ground_truth_figures/heatmap_fate_probs_genes.png
index e6fc69ade..2b0f88f08 100644
Binary files a/tests/_ground_truth_figures/heatmap_fate_probs_genes.png and b/tests/_ground_truth_figures/heatmap_fate_probs_genes.png differ
diff --git a/tests/_ground_truth_figures/heatmap_fate_probs_lineages/lineage_0.png b/tests/_ground_truth_figures/heatmap_fate_probs_lineages/lineage_0.png
index 8b528d6dc..28870a43e 100644
Binary files a/tests/_ground_truth_figures/heatmap_fate_probs_lineages/lineage_0.png and b/tests/_ground_truth_figures/heatmap_fate_probs_lineages/lineage_0.png differ
diff --git a/tests/_ground_truth_figures/heatmap_fate_probs_lineages/lineage_1.png b/tests/_ground_truth_figures/heatmap_fate_probs_lineages/lineage_1.png
index 8608bb336..b58c499dd 100644
Binary files a/tests/_ground_truth_figures/heatmap_fate_probs_lineages/lineage_1.png and b/tests/_ground_truth_figures/heatmap_fate_probs_lineages/lineage_1.png differ
diff --git a/tests/_ground_truth_figures/heatmap_fate_probs_lineages/lineage_2.png b/tests/_ground_truth_figures/heatmap_fate_probs_lineages/lineage_2.png
index ae8edde39..dfc372838 100644
Binary files a/tests/_ground_truth_figures/heatmap_fate_probs_lineages/lineage_2.png and b/tests/_ground_truth_figures/heatmap_fate_probs_lineages/lineage_2.png differ
diff --git a/tests/_ground_truth_figures/heatmap_gene_symbols/lineage_0.png b/tests/_ground_truth_figures/heatmap_gene_symbols/lineage_0.png
index b187bd5c5..5be19cbb4 100644
Binary files a/tests/_ground_truth_figures/heatmap_gene_symbols/lineage_0.png and b/tests/_ground_truth_figures/heatmap_gene_symbols/lineage_0.png differ
diff --git a/tests/_ground_truth_figures/heatmap_gene_symbols/lineage_1.png b/tests/_ground_truth_figures/heatmap_gene_symbols/lineage_1.png
index ab52baf08..7be4324df 100644
Binary files a/tests/_ground_truth_figures/heatmap_gene_symbols/lineage_1.png and b/tests/_ground_truth_figures/heatmap_gene_symbols/lineage_1.png differ
diff --git a/tests/_ground_truth_figures/heatmap_gene_symbols/lineage_2.png b/tests/_ground_truth_figures/heatmap_gene_symbols/lineage_2.png
index 435df54d6..45fa79272 100644
Binary files a/tests/_ground_truth_figures/heatmap_gene_symbols/lineage_2.png and b/tests/_ground_truth_figures/heatmap_gene_symbols/lineage_2.png differ
diff --git a/tests/_ground_truth_figures/heatmap_genes.png b/tests/_ground_truth_figures/heatmap_genes.png
index 1a26d86f6..e38fec718 100644
Binary files a/tests/_ground_truth_figures/heatmap_genes.png and b/tests/_ground_truth_figures/heatmap_genes.png differ
diff --git a/tests/_ground_truth_figures/heatmap_genes_1_gene_failed.png b/tests/_ground_truth_figures/heatmap_genes_1_gene_failed.png
index c0ecd595d..603c180d5 100644
Binary files a/tests/_ground_truth_figures/heatmap_genes_1_gene_failed.png and b/tests/_ground_truth_figures/heatmap_genes_1_gene_failed.png differ
diff --git a/tests/_ground_truth_figures/heatmap_keep_gene_order/lineage_0.png b/tests/_ground_truth_figures/heatmap_keep_gene_order/lineage_0.png
index 6909dbb97..2ffa4db9a 100644
Binary files a/tests/_ground_truth_figures/heatmap_keep_gene_order/lineage_0.png and b/tests/_ground_truth_figures/heatmap_keep_gene_order/lineage_0.png differ
diff --git a/tests/_ground_truth_figures/heatmap_keep_gene_order/lineage_1.png b/tests/_ground_truth_figures/heatmap_keep_gene_order/lineage_1.png
index d44f344ce..82f63c615 100644
Binary files a/tests/_ground_truth_figures/heatmap_keep_gene_order/lineage_1.png and b/tests/_ground_truth_figures/heatmap_keep_gene_order/lineage_1.png differ
diff --git a/tests/_ground_truth_figures/heatmap_keep_gene_order/lineage_2.png b/tests/_ground_truth_figures/heatmap_keep_gene_order/lineage_2.png
index 96ce5a428..525386011 100644
Binary files a/tests/_ground_truth_figures/heatmap_keep_gene_order/lineage_2.png and b/tests/_ground_truth_figures/heatmap_keep_gene_order/lineage_2.png differ
diff --git a/tests/_ground_truth_figures/heatmap_lineage_height/lineage_0.png b/tests/_ground_truth_figures/heatmap_lineage_height/lineage_0.png
index 6909dbb97..2ffa4db9a 100644
Binary files a/tests/_ground_truth_figures/heatmap_lineage_height/lineage_0.png and b/tests/_ground_truth_figures/heatmap_lineage_height/lineage_0.png differ
diff --git a/tests/_ground_truth_figures/heatmap_lineage_height/lineage_1.png b/tests/_ground_truth_figures/heatmap_lineage_height/lineage_1.png
index ab781198d..8dc73eddf 100644
Binary files a/tests/_ground_truth_figures/heatmap_lineage_height/lineage_1.png and b/tests/_ground_truth_figures/heatmap_lineage_height/lineage_1.png differ
diff --git a/tests/_ground_truth_figures/heatmap_lineage_height/lineage_2.png b/tests/_ground_truth_figures/heatmap_lineage_height/lineage_2.png
index 96818fd27..121e9a2f1 100644
Binary files a/tests/_ground_truth_figures/heatmap_lineage_height/lineage_2.png and b/tests/_ground_truth_figures/heatmap_lineage_height/lineage_2.png differ
diff --git a/tests/_ground_truth_figures/heatmap_lineages/lineage_0.png b/tests/_ground_truth_figures/heatmap_lineages/lineage_0.png
index 6909dbb97..2ffa4db9a 100644
Binary files a/tests/_ground_truth_figures/heatmap_lineages/lineage_0.png and b/tests/_ground_truth_figures/heatmap_lineages/lineage_0.png differ
diff --git a/tests/_ground_truth_figures/heatmap_lineages/lineage_1.png b/tests/_ground_truth_figures/heatmap_lineages/lineage_1.png
index ab781198d..8dc73eddf 100644
Binary files a/tests/_ground_truth_figures/heatmap_lineages/lineage_1.png and b/tests/_ground_truth_figures/heatmap_lineages/lineage_1.png differ
diff --git a/tests/_ground_truth_figures/heatmap_lineages/lineage_2.png b/tests/_ground_truth_figures/heatmap_lineages/lineage_2.png
index 96818fd27..121e9a2f1 100644
Binary files a/tests/_ground_truth_figures/heatmap_lineages/lineage_2.png and b/tests/_ground_truth_figures/heatmap_lineages/lineage_2.png differ
diff --git a/tests/_ground_truth_figures/heatmap_lineages_1_lineage_failed/lineage_1.png b/tests/_ground_truth_figures/heatmap_lineages_1_lineage_failed/lineage_1.png
index ab781198d..7f02e6b94 100644
Binary files a/tests/_ground_truth_figures/heatmap_lineages_1_lineage_failed/lineage_1.png and b/tests/_ground_truth_figures/heatmap_lineages_1_lineage_failed/lineage_1.png differ
diff --git a/tests/_ground_truth_figures/heatmap_lineages_1_lineage_failed/lineage_2.png b/tests/_ground_truth_figures/heatmap_lineages_1_lineage_failed/lineage_2.png
index 96818fd27..121e9a2f1 100644
Binary files a/tests/_ground_truth_figures/heatmap_lineages_1_lineage_failed/lineage_2.png and b/tests/_ground_truth_figures/heatmap_lineages_1_lineage_failed/lineage_2.png differ
diff --git a/tests/_ground_truth_figures/heatmap_lineages_bwd/lineage_0.png b/tests/_ground_truth_figures/heatmap_lineages_bwd/lineage_0.png
index 39b5b77e6..1d1ceecb1 100644
Binary files a/tests/_ground_truth_figures/heatmap_lineages_bwd/lineage_0.png and b/tests/_ground_truth_figures/heatmap_lineages_bwd/lineage_0.png differ
diff --git a/tests/_ground_truth_figures/heatmap_lineages_bwd/lineage_1.png b/tests/_ground_truth_figures/heatmap_lineages_bwd/lineage_1.png
index 18a6832e9..112b3158f 100644
Binary files a/tests/_ground_truth_figures/heatmap_lineages_bwd/lineage_1.png and b/tests/_ground_truth_figures/heatmap_lineages_bwd/lineage_1.png differ
diff --git a/tests/_ground_truth_figures/heatmap_lineages_raw/lineage_0.png b/tests/_ground_truth_figures/heatmap_lineages_raw/lineage_0.png
index d5cda0628..5d6e19093 100644
Binary files a/tests/_ground_truth_figures/heatmap_lineages_raw/lineage_0.png and b/tests/_ground_truth_figures/heatmap_lineages_raw/lineage_0.png differ
diff --git a/tests/_ground_truth_figures/heatmap_lineages_raw/lineage_1.png b/tests/_ground_truth_figures/heatmap_lineages_raw/lineage_1.png
index 750491245..107423fc4 100644
Binary files a/tests/_ground_truth_figures/heatmap_lineages_raw/lineage_1.png and b/tests/_ground_truth_figures/heatmap_lineages_raw/lineage_1.png differ
diff --git a/tests/_ground_truth_figures/heatmap_lineages_raw/lineage_2.png b/tests/_ground_truth_figures/heatmap_lineages_raw/lineage_2.png
index 6d836b6ee..a78f1e2f9 100644
Binary files a/tests/_ground_truth_figures/heatmap_lineages_raw/lineage_2.png and b/tests/_ground_truth_figures/heatmap_lineages_raw/lineage_2.png differ
diff --git a/tests/_ground_truth_figures/heatmap_multiple_cluster_keys/lineage_0.png b/tests/_ground_truth_figures/heatmap_multiple_cluster_keys/lineage_0.png
index 7d6b12a73..8900b470d 100644
Binary files a/tests/_ground_truth_figures/heatmap_multiple_cluster_keys/lineage_0.png and b/tests/_ground_truth_figures/heatmap_multiple_cluster_keys/lineage_0.png differ
diff --git a/tests/_ground_truth_figures/heatmap_multiple_cluster_keys/lineage_1.png b/tests/_ground_truth_figures/heatmap_multiple_cluster_keys/lineage_1.png
index c07d21df0..dc32fbd86 100644
Binary files a/tests/_ground_truth_figures/heatmap_multiple_cluster_keys/lineage_1.png and b/tests/_ground_truth_figures/heatmap_multiple_cluster_keys/lineage_1.png differ
diff --git a/tests/_ground_truth_figures/heatmap_multiple_cluster_keys/lineage_2.png b/tests/_ground_truth_figures/heatmap_multiple_cluster_keys/lineage_2.png
index 2a91af9fb..e4ffe9594 100644
Binary files a/tests/_ground_truth_figures/heatmap_multiple_cluster_keys/lineage_2.png and b/tests/_ground_truth_figures/heatmap_multiple_cluster_keys/lineage_2.png differ
diff --git a/tests/_ground_truth_figures/heatmap_multiple_cluster_keys_show_all_genes/lineage_0.png b/tests/_ground_truth_figures/heatmap_multiple_cluster_keys_show_all_genes/lineage_0.png
index 6909dbb97..2ffa4db9a 100644
Binary files a/tests/_ground_truth_figures/heatmap_multiple_cluster_keys_show_all_genes/lineage_0.png and b/tests/_ground_truth_figures/heatmap_multiple_cluster_keys_show_all_genes/lineage_0.png differ
diff --git a/tests/_ground_truth_figures/heatmap_multiple_cluster_keys_show_all_genes/lineage_1.png b/tests/_ground_truth_figures/heatmap_multiple_cluster_keys_show_all_genes/lineage_1.png
index ab781198d..8dc73eddf 100644
Binary files a/tests/_ground_truth_figures/heatmap_multiple_cluster_keys_show_all_genes/lineage_1.png and b/tests/_ground_truth_figures/heatmap_multiple_cluster_keys_show_all_genes/lineage_1.png differ
diff --git a/tests/_ground_truth_figures/heatmap_multiple_cluster_keys_show_all_genes/lineage_2.png b/tests/_ground_truth_figures/heatmap_multiple_cluster_keys_show_all_genes/lineage_2.png
index 96818fd27..121e9a2f1 100644
Binary files a/tests/_ground_truth_figures/heatmap_multiple_cluster_keys_show_all_genes/lineage_2.png and b/tests/_ground_truth_figures/heatmap_multiple_cluster_keys_show_all_genes/lineage_2.png differ
diff --git a/tests/_ground_truth_figures/heatmap_no_cbar_genes.png b/tests/_ground_truth_figures/heatmap_no_cbar_genes.png
index 4c4c76dd3..c1787c617 100644
Binary files a/tests/_ground_truth_figures/heatmap_no_cbar_genes.png and b/tests/_ground_truth_figures/heatmap_no_cbar_genes.png differ
diff --git a/tests/_ground_truth_figures/heatmap_no_cbar_lineages/lineage_0.png b/tests/_ground_truth_figures/heatmap_no_cbar_lineages/lineage_0.png
index bd46f6ba2..2bdaaa352 100644
Binary files a/tests/_ground_truth_figures/heatmap_no_cbar_lineages/lineage_0.png and b/tests/_ground_truth_figures/heatmap_no_cbar_lineages/lineage_0.png differ
diff --git a/tests/_ground_truth_figures/heatmap_no_cbar_lineages/lineage_1.png b/tests/_ground_truth_figures/heatmap_no_cbar_lineages/lineage_1.png
index 4362ed6ee..990f04a42 100644
Binary files a/tests/_ground_truth_figures/heatmap_no_cbar_lineages/lineage_1.png and b/tests/_ground_truth_figures/heatmap_no_cbar_lineages/lineage_1.png differ
diff --git a/tests/_ground_truth_figures/heatmap_no_cbar_lineages/lineage_2.png b/tests/_ground_truth_figures/heatmap_no_cbar_lineages/lineage_2.png
index e127bdc02..ee1664a85 100644
Binary files a/tests/_ground_truth_figures/heatmap_no_cbar_lineages/lineage_2.png and b/tests/_ground_truth_figures/heatmap_no_cbar_lineages/lineage_2.png differ
diff --git a/tests/_ground_truth_figures/heatmap_no_cluster/lineage_0.png b/tests/_ground_truth_figures/heatmap_no_cluster/lineage_0.png
index 709fbbde7..d05be698f 100644
Binary files a/tests/_ground_truth_figures/heatmap_no_cluster/lineage_0.png and b/tests/_ground_truth_figures/heatmap_no_cluster/lineage_0.png differ
diff --git a/tests/_ground_truth_figures/heatmap_no_cluster/lineage_1.png b/tests/_ground_truth_figures/heatmap_no_cluster/lineage_1.png
index 841ce852d..a2202da4e 100644
Binary files a/tests/_ground_truth_figures/heatmap_no_cluster/lineage_1.png and b/tests/_ground_truth_figures/heatmap_no_cluster/lineage_1.png differ
diff --git a/tests/_ground_truth_figures/heatmap_no_cluster/lineage_2.png b/tests/_ground_truth_figures/heatmap_no_cluster/lineage_2.png
index 8449a82d8..e3af37fb2 100644
Binary files a/tests/_ground_truth_figures/heatmap_no_cluster/lineage_2.png and b/tests/_ground_truth_figures/heatmap_no_cluster/lineage_2.png differ
diff --git a/tests/_ground_truth_figures/heatmap_no_cluster_genes/lineage_0.png b/tests/_ground_truth_figures/heatmap_no_cluster_genes/lineage_0.png
index 6909dbb97..2ffa4db9a 100644
Binary files a/tests/_ground_truth_figures/heatmap_no_cluster_genes/lineage_0.png and b/tests/_ground_truth_figures/heatmap_no_cluster_genes/lineage_0.png differ
diff --git a/tests/_ground_truth_figures/heatmap_no_cluster_genes/lineage_1.png b/tests/_ground_truth_figures/heatmap_no_cluster_genes/lineage_1.png
index ab781198d..8dc73eddf 100644
Binary files a/tests/_ground_truth_figures/heatmap_no_cluster_genes/lineage_1.png and b/tests/_ground_truth_figures/heatmap_no_cluster_genes/lineage_1.png differ
diff --git a/tests/_ground_truth_figures/heatmap_no_cluster_genes/lineage_2.png b/tests/_ground_truth_figures/heatmap_no_cluster_genes/lineage_2.png
index 96818fd27..121e9a2f1 100644
Binary files a/tests/_ground_truth_figures/heatmap_no_cluster_genes/lineage_2.png and b/tests/_ground_truth_figures/heatmap_no_cluster_genes/lineage_2.png differ
diff --git a/tests/_ground_truth_figures/heatmap_no_convolve/lineage_0.png b/tests/_ground_truth_figures/heatmap_no_convolve/lineage_0.png
index 709fbbde7..d05be698f 100644
Binary files a/tests/_ground_truth_figures/heatmap_no_convolve/lineage_0.png and b/tests/_ground_truth_figures/heatmap_no_convolve/lineage_0.png differ
diff --git a/tests/_ground_truth_figures/heatmap_no_convolve/lineage_1.png b/tests/_ground_truth_figures/heatmap_no_convolve/lineage_1.png
index 841ce852d..a2202da4e 100644
Binary files a/tests/_ground_truth_figures/heatmap_no_convolve/lineage_1.png and b/tests/_ground_truth_figures/heatmap_no_convolve/lineage_1.png differ
diff --git a/tests/_ground_truth_figures/heatmap_no_convolve/lineage_2.png b/tests/_ground_truth_figures/heatmap_no_convolve/lineage_2.png
index 8449a82d8..e3af37fb2 100644
Binary files a/tests/_ground_truth_figures/heatmap_no_convolve/lineage_2.png and b/tests/_ground_truth_figures/heatmap_no_convolve/lineage_2.png differ
diff --git a/tests/_ground_truth_figures/heatmap_no_scale_genes.png b/tests/_ground_truth_figures/heatmap_no_scale_genes.png
index ea20120ce..a673dca23 100644
Binary files a/tests/_ground_truth_figures/heatmap_no_scale_genes.png and b/tests/_ground_truth_figures/heatmap_no_scale_genes.png differ
diff --git a/tests/_ground_truth_figures/heatmap_no_scale_lineages/lineage_0.png b/tests/_ground_truth_figures/heatmap_no_scale_lineages/lineage_0.png
index 767e46c91..a783146f0 100644
Binary files a/tests/_ground_truth_figures/heatmap_no_scale_lineages/lineage_0.png and b/tests/_ground_truth_figures/heatmap_no_scale_lineages/lineage_0.png differ
diff --git a/tests/_ground_truth_figures/heatmap_no_scale_lineages/lineage_1.png b/tests/_ground_truth_figures/heatmap_no_scale_lineages/lineage_1.png
index 329d9bf29..afe2fe4ed 100644
Binary files a/tests/_ground_truth_figures/heatmap_no_scale_lineages/lineage_1.png and b/tests/_ground_truth_figures/heatmap_no_scale_lineages/lineage_1.png differ
diff --git a/tests/_ground_truth_figures/heatmap_no_scale_lineages/lineage_2.png b/tests/_ground_truth_figures/heatmap_no_scale_lineages/lineage_2.png
index 3ccf43235..ac9cadf80 100644
Binary files a/tests/_ground_truth_figures/heatmap_no_scale_lineages/lineage_2.png and b/tests/_ground_truth_figures/heatmap_no_scale_lineages/lineage_2.png differ
diff --git a/tests/_ground_truth_figures/heatmap_show_dendrogram.png b/tests/_ground_truth_figures/heatmap_show_dendrogram.png
index 726562141..ec80b3405 100644
Binary files a/tests/_ground_truth_figures/heatmap_show_dendrogram.png and b/tests/_ground_truth_figures/heatmap_show_dendrogram.png differ
diff --git a/tests/_ground_truth_figures/heatmap_time_range/lineage_0.png b/tests/_ground_truth_figures/heatmap_time_range/lineage_0.png
index e4da0d181..f9147fd10 100644
Binary files a/tests/_ground_truth_figures/heatmap_time_range/lineage_0.png and b/tests/_ground_truth_figures/heatmap_time_range/lineage_0.png differ
diff --git a/tests/_ground_truth_figures/heatmap_time_range/lineage_1.png b/tests/_ground_truth_figures/heatmap_time_range/lineage_1.png
index cd1b05d5c..a1a50878e 100644
Binary files a/tests/_ground_truth_figures/heatmap_time_range/lineage_1.png and b/tests/_ground_truth_figures/heatmap_time_range/lineage_1.png differ
diff --git a/tests/_ground_truth_figures/heatmap_time_range/lineage_2.png b/tests/_ground_truth_figures/heatmap_time_range/lineage_2.png
index 229d0933b..fd742fc70 100644
Binary files a/tests/_ground_truth_figures/heatmap_time_range/lineage_2.png and b/tests/_ground_truth_figures/heatmap_time_range/lineage_2.png differ
diff --git a/tests/_ground_truth_figures/kernel_random_walk_basis.png b/tests/_ground_truth_figures/kernel_random_walk_basis.png
index 935205760..2b267b4aa 100644
Binary files a/tests/_ground_truth_figures/kernel_random_walk_basis.png and b/tests/_ground_truth_figures/kernel_random_walk_basis.png differ
diff --git a/tests/_ground_truth_figures/kernel_random_walk_cmap.png b/tests/_ground_truth_figures/kernel_random_walk_cmap.png
index 2665b5ff0..fafe9906f 100644
Binary files a/tests/_ground_truth_figures/kernel_random_walk_cmap.png and b/tests/_ground_truth_figures/kernel_random_walk_cmap.png differ
diff --git a/tests/_ground_truth_figures/kernel_random_walk_ixs_legend_loc.png b/tests/_ground_truth_figures/kernel_random_walk_ixs_legend_loc.png
index 8ccc1739d..63f6c52a4 100644
Binary files a/tests/_ground_truth_figures/kernel_random_walk_ixs_legend_loc.png and b/tests/_ground_truth_figures/kernel_random_walk_ixs_legend_loc.png differ
diff --git a/tests/_ground_truth_figures/kernel_random_walk_kwargs.png b/tests/_ground_truth_figures/kernel_random_walk_kwargs.png
index 414994224..d9732e114 100644
Binary files a/tests/_ground_truth_figures/kernel_random_walk_kwargs.png and b/tests/_ground_truth_figures/kernel_random_walk_kwargs.png differ
diff --git a/tests/_ground_truth_figures/kernel_random_walk_line_alpha.png b/tests/_ground_truth_figures/kernel_random_walk_line_alpha.png
index 172917b9d..aab843f37 100644
Binary files a/tests/_ground_truth_figures/kernel_random_walk_line_alpha.png and b/tests/_ground_truth_figures/kernel_random_walk_line_alpha.png differ
diff --git a/tests/_ground_truth_figures/kernel_random_walk_line_width.png b/tests/_ground_truth_figures/kernel_random_walk_line_width.png
index 8575b32ec..65caaaa82 100644
Binary files a/tests/_ground_truth_figures/kernel_random_walk_line_width.png and b/tests/_ground_truth_figures/kernel_random_walk_line_width.png differ
diff --git a/tests/_ground_truth_figures/kernel_random_walk_params.png b/tests/_ground_truth_figures/kernel_random_walk_params.png
index 9f2ce6e80..a731ee7c4 100644
Binary files a/tests/_ground_truth_figures/kernel_random_walk_params.png and b/tests/_ground_truth_figures/kernel_random_walk_params.png differ
diff --git a/tests/_ground_truth_figures/kernel_random_walk_start_ixs_range.png b/tests/_ground_truth_figures/kernel_random_walk_start_ixs_range.png
index 437b07ccc..ccdd4d5fa 100644
Binary files a/tests/_ground_truth_figures/kernel_random_walk_start_ixs_range.png and b/tests/_ground_truth_figures/kernel_random_walk_start_ixs_range.png differ
diff --git a/tests/_ground_truth_figures/log_odds.png b/tests/_ground_truth_figures/log_odds.png
index ad4d7f2cf..f8f31350b 100644
Binary files a/tests/_ground_truth_figures/log_odds.png and b/tests/_ground_truth_figures/log_odds.png differ
diff --git a/tests/_ground_truth_figures/log_odds_alpha.png b/tests/_ground_truth_figures/log_odds_alpha.png
index b06ccc18a..07d1574ca 100644
Binary files a/tests/_ground_truth_figures/log_odds_alpha.png and b/tests/_ground_truth_figures/log_odds_alpha.png differ
diff --git a/tests/_ground_truth_figures/log_odds_bwd.png b/tests/_ground_truth_figures/log_odds_bwd.png
index 9c16b5987..8fe7c2d07 100644
Binary files a/tests/_ground_truth_figures/log_odds_bwd.png and b/tests/_ground_truth_figures/log_odds_bwd.png differ
diff --git a/tests/_ground_truth_figures/log_odds_categorical_keys.png b/tests/_ground_truth_figures/log_odds_categorical_keys.png
index 05ae6552d..625f41b1a 100644
Binary files a/tests/_ground_truth_figures/log_odds_categorical_keys.png and b/tests/_ground_truth_figures/log_odds_categorical_keys.png differ
diff --git a/tests/_ground_truth_figures/log_odds_cmap.png b/tests/_ground_truth_figures/log_odds_cmap.png
index 63c6939cb..9011414ff 100644
Binary files a/tests/_ground_truth_figures/log_odds_cmap.png and b/tests/_ground_truth_figures/log_odds_cmap.png differ
diff --git a/tests/_ground_truth_figures/log_odds_continuous_keys.png b/tests/_ground_truth_figures/log_odds_continuous_keys.png
index 86b93fa0d..d188cd7a6 100644
Binary files a/tests/_ground_truth_figures/log_odds_continuous_keys.png and b/tests/_ground_truth_figures/log_odds_continuous_keys.png differ
diff --git a/tests/_ground_truth_figures/log_odds_fontsize.png b/tests/_ground_truth_figures/log_odds_fontsize.png
index 08939d304..4aba70934 100644
Binary files a/tests/_ground_truth_figures/log_odds_fontsize.png and b/tests/_ground_truth_figures/log_odds_fontsize.png differ
diff --git a/tests/_ground_truth_figures/log_odds_jitter.png b/tests/_ground_truth_figures/log_odds_jitter.png
index 56ed3cd44..67a0dae94 100644
Binary files a/tests/_ground_truth_figures/log_odds_jitter.png and b/tests/_ground_truth_figures/log_odds_jitter.png differ
diff --git a/tests/_ground_truth_figures/log_odds_kwargs.png b/tests/_ground_truth_figures/log_odds_kwargs.png
index 5b752a79a..1c5507068 100644
Binary files a/tests/_ground_truth_figures/log_odds_kwargs.png and b/tests/_ground_truth_figures/log_odds_kwargs.png differ
diff --git a/tests/_ground_truth_figures/log_odds_kwargs_return_ax.png b/tests/_ground_truth_figures/log_odds_kwargs_return_ax.png
index 39b135d41..dd8405547 100644
Binary files a/tests/_ground_truth_figures/log_odds_kwargs_return_ax.png and b/tests/_ground_truth_figures/log_odds_kwargs_return_ax.png differ
diff --git a/tests/_ground_truth_figures/log_odds_kwargs_return_axes.png b/tests/_ground_truth_figures/log_odds_kwargs_return_axes.png
index 218d56fab..e38229624 100644
Binary files a/tests/_ground_truth_figures/log_odds_kwargs_return_axes.png and b/tests/_ground_truth_figures/log_odds_kwargs_return_axes.png differ
diff --git a/tests/_ground_truth_figures/log_odds_layer.png b/tests/_ground_truth_figures/log_odds_layer.png
index a983f6683..08e5c3db8 100644
Binary files a/tests/_ground_truth_figures/log_odds_layer.png and b/tests/_ground_truth_figures/log_odds_layer.png differ
diff --git a/tests/_ground_truth_figures/log_odds_legend_loc.png b/tests/_ground_truth_figures/log_odds_legend_loc.png
index 11ed6c4ac..c6cd2fb27 100644
Binary files a/tests/_ground_truth_figures/log_odds_legend_loc.png and b/tests/_ground_truth_figures/log_odds_legend_loc.png differ
diff --git a/tests/_ground_truth_figures/log_odds_multiple_threshold.png b/tests/_ground_truth_figures/log_odds_multiple_threshold.png
index 4f4304348..914914f81 100644
Binary files a/tests/_ground_truth_figures/log_odds_multiple_threshold.png and b/tests/_ground_truth_figures/log_odds_multiple_threshold.png differ
diff --git a/tests/_ground_truth_figures/log_odds_ncols.png b/tests/_ground_truth_figures/log_odds_ncols.png
index c701177e8..e9da637fd 100644
Binary files a/tests/_ground_truth_figures/log_odds_ncols.png and b/tests/_ground_truth_figures/log_odds_ncols.png differ
diff --git a/tests/_ground_truth_figures/log_odds_rest.png b/tests/_ground_truth_figures/log_odds_rest.png
index 91626cf50..7b2ce3e1a 100644
Binary files a/tests/_ground_truth_figures/log_odds_rest.png and b/tests/_ground_truth_figures/log_odds_rest.png differ
diff --git a/tests/_ground_truth_figures/log_odds_size.png b/tests/_ground_truth_figures/log_odds_size.png
index fa372446e..ca63f1ff0 100644
Binary files a/tests/_ground_truth_figures/log_odds_size.png and b/tests/_ground_truth_figures/log_odds_size.png differ
diff --git a/tests/_ground_truth_figures/log_odds_threshold.png b/tests/_ground_truth_figures/log_odds_threshold.png
index e203a4ddc..c1f1e06fd 100644
Binary files a/tests/_ground_truth_figures/log_odds_threshold.png and b/tests/_ground_truth_figures/log_odds_threshold.png differ
diff --git a/tests/_ground_truth_figures/log_odds_threshold_color.png b/tests/_ground_truth_figures/log_odds_threshold_color.png
index cd5c565fd..919f6437d 100644
Binary files a/tests/_ground_truth_figures/log_odds_threshold_color.png and b/tests/_ground_truth_figures/log_odds_threshold_color.png differ
diff --git a/tests/_ground_truth_figures/log_odds_use_raw.png b/tests/_ground_truth_figures/log_odds_use_raw.png
index 7f0f3827f..42a1fac06 100644
Binary files a/tests/_ground_truth_figures/log_odds_use_raw.png and b/tests/_ground_truth_figures/log_odds_use_raw.png differ
diff --git a/tests/_ground_truth_figures/log_odds_xticks_steps_size.png b/tests/_ground_truth_figures/log_odds_xticks_steps_size.png
index 6ddc9a338..f439f8535 100644
Binary files a/tests/_ground_truth_figures/log_odds_xticks_steps_size.png and b/tests/_ground_truth_figures/log_odds_xticks_steps_size.png differ
diff --git a/tests/_ground_truth_figures/mc_complex_spectrum.png b/tests/_ground_truth_figures/mc_complex_spectrum.png
index 7d549a203..298be848d 100644
Binary files a/tests/_ground_truth_figures/mc_complex_spectrum.png and b/tests/_ground_truth_figures/mc_complex_spectrum.png differ
diff --git a/tests/_ground_truth_figures/mc_kwargs_linewidths.png b/tests/_ground_truth_figures/mc_kwargs_linewidths.png
index b434e8d33..41741a0b6 100644
Binary files a/tests/_ground_truth_figures/mc_kwargs_linewidths.png and b/tests/_ground_truth_figures/mc_kwargs_linewidths.png differ
diff --git a/tests/_ground_truth_figures/mc_marker.png b/tests/_ground_truth_figures/mc_marker.png
index bb7a21021..6bc9f08f5 100644
Binary files a/tests/_ground_truth_figures/mc_marker.png and b/tests/_ground_truth_figures/mc_marker.png differ
diff --git a/tests/_ground_truth_figures/mc_real_spectrum.png b/tests/_ground_truth_figures/mc_real_spectrum.png
index 8a7ab9d1e..0ba696b12 100644
Binary files a/tests/_ground_truth_figures/mc_real_spectrum.png and b/tests/_ground_truth_figures/mc_real_spectrum.png differ
diff --git a/tests/_ground_truth_figures/mc_real_spectrum_hide_eigengap.png b/tests/_ground_truth_figures/mc_real_spectrum_hide_eigengap.png
index 7950420a6..38db2e21b 100644
Binary files a/tests/_ground_truth_figures/mc_real_spectrum_hide_eigengap.png and b/tests/_ground_truth_figures/mc_real_spectrum_hide_eigengap.png differ
diff --git a/tests/_ground_truth_figures/mc_real_spectrum_hide_xticks.png b/tests/_ground_truth_figures/mc_real_spectrum_hide_xticks.png
index 2ee05491d..f6e24d03f 100644
Binary files a/tests/_ground_truth_figures/mc_real_spectrum_hide_xticks.png and b/tests/_ground_truth_figures/mc_real_spectrum_hide_xticks.png differ
diff --git a/tests/_ground_truth_figures/mc_spectrum.png b/tests/_ground_truth_figures/mc_spectrum.png
index 8a7ab9d1e..0ba696b12 100644
Binary files a/tests/_ground_truth_figures/mc_spectrum.png and b/tests/_ground_truth_figures/mc_spectrum.png differ
diff --git a/tests/_ground_truth_figures/mc_spectrum_evals.png b/tests/_ground_truth_figures/mc_spectrum_evals.png
index 4df2e30aa..05e1f3f75 100644
Binary files a/tests/_ground_truth_figures/mc_spectrum_evals.png and b/tests/_ground_truth_figures/mc_spectrum_evals.png differ
diff --git a/tests/_ground_truth_figures/mc_spectrum_evals_complex.png b/tests/_ground_truth_figures/mc_spectrum_evals_complex.png
index 27e26e135..054bbd82b 100644
Binary files a/tests/_ground_truth_figures/mc_spectrum_evals_complex.png and b/tests/_ground_truth_figures/mc_spectrum_evals_complex.png differ
diff --git a/tests/_ground_truth_figures/mc_spectrum_title.png b/tests/_ground_truth_figures/mc_spectrum_title.png
index fea7bbaaf..4b76a14ec 100644
Binary files a/tests/_ground_truth_figures/mc_spectrum_title.png and b/tests/_ground_truth_figures/mc_spectrum_title.png differ
diff --git a/tests/_ground_truth_figures/mode_clustermap.png b/tests/_ground_truth_figures/mode_clustermap.png
index 73d0df2a3..299204ee0 100644
Binary files a/tests/_ground_truth_figures/mode_clustermap.png and b/tests/_ground_truth_figures/mode_clustermap.png differ
diff --git a/tests/_ground_truth_figures/mode_clustermap_format.png b/tests/_ground_truth_figures/mode_clustermap_format.png
index d225a7d76..f74dcd6f2 100644
Binary files a/tests/_ground_truth_figures/mode_clustermap_format.png and b/tests/_ground_truth_figures/mode_clustermap_format.png differ
diff --git a/tests/_ground_truth_figures/mode_heatmap.png b/tests/_ground_truth_figures/mode_heatmap.png
index 3a87af70a..ed20b55c9 100644
Binary files a/tests/_ground_truth_figures/mode_heatmap.png and b/tests/_ground_truth_figures/mode_heatmap.png differ
diff --git a/tests/_ground_truth_figures/mode_heatmap_clusters.png b/tests/_ground_truth_figures/mode_heatmap_clusters.png
index 4a016b20e..a4e49c1d6 100644
Binary files a/tests/_ground_truth_figures/mode_heatmap_clusters.png and b/tests/_ground_truth_figures/mode_heatmap_clusters.png differ
diff --git a/tests/_ground_truth_figures/mode_heatmap_cmap.png b/tests/_ground_truth_figures/mode_heatmap_cmap.png
index a2266608e..cbe3931ad 100644
Binary files a/tests/_ground_truth_figures/mode_heatmap_cmap.png and b/tests/_ground_truth_figures/mode_heatmap_cmap.png differ
diff --git a/tests/_ground_truth_figures/mode_heatmap_format.png b/tests/_ground_truth_figures/mode_heatmap_format.png
index 50ea661de..f87504aaa 100644
Binary files a/tests/_ground_truth_figures/mode_heatmap_format.png and b/tests/_ground_truth_figures/mode_heatmap_format.png differ
diff --git a/tests/_ground_truth_figures/mode_heatmap_lineages.png b/tests/_ground_truth_figures/mode_heatmap_lineages.png
index 6beea5bed..64d2e2bc9 100644
Binary files a/tests/_ground_truth_figures/mode_heatmap_lineages.png and b/tests/_ground_truth_figures/mode_heatmap_lineages.png differ
diff --git a/tests/_ground_truth_figures/mode_heatmap_title.png b/tests/_ground_truth_figures/mode_heatmap_title.png
index 118219029..b6ba542bf 100644
Binary files a/tests/_ground_truth_figures/mode_heatmap_title.png and b/tests/_ground_truth_figures/mode_heatmap_title.png differ
diff --git a/tests/_ground_truth_figures/mode_heatmap_xticks_rotation.png b/tests/_ground_truth_figures/mode_heatmap_xticks_rotation.png
index 35f24be7c..f8aea0f82 100644
Binary files a/tests/_ground_truth_figures/mode_heatmap_xticks_rotation.png and b/tests/_ground_truth_figures/mode_heatmap_xticks_rotation.png differ
diff --git a/tests/_ground_truth_figures/model_1_lineage.png b/tests/_ground_truth_figures/model_1_lineage.png
index a651f0f43..94445bb33 100644
Binary files a/tests/_ground_truth_figures/model_1_lineage.png and b/tests/_ground_truth_figures/model_1_lineage.png differ
diff --git a/tests/_ground_truth_figures/model_default.png b/tests/_ground_truth_figures/model_default.png
index 6105b7a3a..b9c3b5692 100644
Binary files a/tests/_ground_truth_figures/model_default.png and b/tests/_ground_truth_figures/model_default.png differ
diff --git a/tests/_ground_truth_figures/model_default_bwd.png b/tests/_ground_truth_figures/model_default_bwd.png
index d9ed8ccaa..0ba919678 100644
Binary files a/tests/_ground_truth_figures/model_default_bwd.png and b/tests/_ground_truth_figures/model_default_bwd.png differ
diff --git a/tests/_ground_truth_figures/model_no_legend.png b/tests/_ground_truth_figures/model_no_legend.png
index 6105b7a3a..b9c3b5692 100644
Binary files a/tests/_ground_truth_figures/model_no_legend.png and b/tests/_ground_truth_figures/model_no_legend.png differ
diff --git a/tests/_ground_truth_figures/model_no_lineage.png b/tests/_ground_truth_figures/model_no_lineage.png
index 913db3e4e..be558463c 100644
Binary files a/tests/_ground_truth_figures/model_no_lineage.png and b/tests/_ground_truth_figures/model_no_lineage.png differ
diff --git a/tests/_ground_truth_figures/model_no_lineage_show_lin_probs.png b/tests/_ground_truth_figures/model_no_lineage_show_lin_probs.png
index d13609002..94835a96c 100644
Binary files a/tests/_ground_truth_figures/model_no_lineage_show_lin_probs.png and b/tests/_ground_truth_figures/model_no_lineage_show_lin_probs.png differ
diff --git a/tests/_ground_truth_figures/model_obs_data_key.png b/tests/_ground_truth_figures/model_obs_data_key.png
index 0a883fc69..92b37b0ef 100644
Binary files a/tests/_ground_truth_figures/model_obs_data_key.png and b/tests/_ground_truth_figures/model_obs_data_key.png differ
diff --git a/tests/_ground_truth_figures/model_show_lin_prob_cells_ci.png b/tests/_ground_truth_figures/model_show_lin_prob_cells_ci.png
index 485b2dc02..4cafe2561 100644
Binary files a/tests/_ground_truth_figures/model_show_lin_prob_cells_ci.png and b/tests/_ground_truth_figures/model_show_lin_prob_cells_ci.png differ
diff --git a/tests/_ground_truth_figures/model_show_lin_prob_cells_lineage_ci.png b/tests/_ground_truth_figures/model_show_lin_prob_cells_lineage_ci.png
index fca113a60..766036c5e 100644
Binary files a/tests/_ground_truth_figures/model_show_lin_prob_cells_lineage_ci.png and b/tests/_ground_truth_figures/model_show_lin_prob_cells_lineage_ci.png differ
diff --git a/tests/_ground_truth_figures/msc_default.png b/tests/_ground_truth_figures/msc_default.png
index 76805e214..d7a937689 100644
Binary files a/tests/_ground_truth_figures/msc_default.png and b/tests/_ground_truth_figures/msc_default.png differ
diff --git a/tests/_ground_truth_figures/msc_labelrot.png b/tests/_ground_truth_figures/msc_labelrot.png
index 23fe3c24f..e621075fb 100644
Binary files a/tests/_ground_truth_figures/msc_labelrot.png and b/tests/_ground_truth_figures/msc_labelrot.png differ
diff --git a/tests/_ground_truth_figures/msc_legend_loc.png b/tests/_ground_truth_figures/msc_legend_loc.png
index ccf7ea0ca..d0a1b06d3 100644
Binary files a/tests/_ground_truth_figures/msc_legend_loc.png and b/tests/_ground_truth_figures/msc_legend_loc.png differ
diff --git a/tests/_ground_truth_figures/msc_title.png b/tests/_ground_truth_figures/msc_title.png
index 026d7818d..935c52fd8 100644
Binary files a/tests/_ground_truth_figures/msc_title.png and b/tests/_ground_truth_figures/msc_title.png differ
diff --git a/tests/_ground_truth_figures/msc_width.png b/tests/_ground_truth_figures/msc_width.png
index fca3b9f5b..4edafe16a 100644
Binary files a/tests/_ground_truth_figures/msc_width.png and b/tests/_ground_truth_figures/msc_width.png differ
diff --git a/tests/_ground_truth_figures/paga.png b/tests/_ground_truth_figures/paga.png
index facf3b8eb..d776a4164 100644
Binary files a/tests/_ground_truth_figures/paga.png and b/tests/_ground_truth_figures/paga.png differ
diff --git a/tests/_ground_truth_figures/paga_lineage_subset.png b/tests/_ground_truth_figures/paga_lineage_subset.png
index ea9b3cf5d..add86f5e7 100644
Binary files a/tests/_ground_truth_figures/paga_lineage_subset.png and b/tests/_ground_truth_figures/paga_lineage_subset.png differ
diff --git a/tests/_ground_truth_figures/paga_pie.png b/tests/_ground_truth_figures/paga_pie.png
index 410421beb..3f11f67bf 100644
Binary files a/tests/_ground_truth_figures/paga_pie.png and b/tests/_ground_truth_figures/paga_pie.png differ
diff --git a/tests/_ground_truth_figures/paga_pie_embedding.png b/tests/_ground_truth_figures/paga_pie_embedding.png
index d7471b51a..1d9793f1a 100644
Binary files a/tests/_ground_truth_figures/paga_pie_embedding.png and b/tests/_ground_truth_figures/paga_pie_embedding.png differ
diff --git a/tests/_ground_truth_figures/paga_pie_legend_position.png b/tests/_ground_truth_figures/paga_pie_legend_position.png
index 6d9c80f76..61efb69ce 100644
Binary files a/tests/_ground_truth_figures/paga_pie_legend_position.png and b/tests/_ground_truth_figures/paga_pie_legend_position.png differ
diff --git a/tests/_ground_truth_figures/paga_pie_legend_position_out.png b/tests/_ground_truth_figures/paga_pie_legend_position_out.png
index 4cc13caa1..1cdaea9a1 100644
Binary files a/tests/_ground_truth_figures/paga_pie_legend_position_out.png and b/tests/_ground_truth_figures/paga_pie_legend_position_out.png differ
diff --git a/tests/_ground_truth_figures/paga_pie_legend_simple.png b/tests/_ground_truth_figures/paga_pie_legend_simple.png
index 410421beb..15995f433 100644
Binary files a/tests/_ground_truth_figures/paga_pie_legend_simple.png and b/tests/_ground_truth_figures/paga_pie_legend_simple.png differ
diff --git a/tests/_ground_truth_figures/paga_pie_no_legend.png b/tests/_ground_truth_figures/paga_pie_no_legend.png
index ea63e5428..8c33af2c1 100644
Binary files a/tests/_ground_truth_figures/paga_pie_no_legend.png and b/tests/_ground_truth_figures/paga_pie_no_legend.png differ
diff --git a/tests/_ground_truth_figures/paga_pie_only_clusters.png b/tests/_ground_truth_figures/paga_pie_only_clusters.png
index e078f6abc..904a676ed 100644
Binary files a/tests/_ground_truth_figures/paga_pie_only_clusters.png and b/tests/_ground_truth_figures/paga_pie_only_clusters.png differ
diff --git a/tests/_ground_truth_figures/paga_pie_only_fate_prob.png b/tests/_ground_truth_figures/paga_pie_only_fate_prob.png
index 7e5eda3b7..71eee1063 100644
Binary files a/tests/_ground_truth_figures/paga_pie_only_fate_prob.png and b/tests/_ground_truth_figures/paga_pie_only_fate_prob.png differ
diff --git a/tests/_ground_truth_figures/paga_pie_title.png b/tests/_ground_truth_figures/paga_pie_title.png
index 18aa8dd0e..bf5a27cfc 100644
Binary files a/tests/_ground_truth_figures/paga_pie_title.png and b/tests/_ground_truth_figures/paga_pie_title.png differ
diff --git a/tests/_ground_truth_figures/pie.png b/tests/_ground_truth_figures/pie.png
index 622426e20..d598854aa 100644
Binary files a/tests/_ground_truth_figures/pie.png and b/tests/_ground_truth_figures/pie.png differ
diff --git a/tests/_ground_truth_figures/pie_autopct_none.png b/tests/_ground_truth_figures/pie_autopct_none.png
index 22026b011..341be25d4 100644
Binary files a/tests/_ground_truth_figures/pie_autopct_none.png and b/tests/_ground_truth_figures/pie_autopct_none.png differ
diff --git a/tests/_ground_truth_figures/pie_legend_kwargs.png b/tests/_ground_truth_figures/pie_legend_kwargs.png
index b58e1ff26..5f2338f3b 100644
Binary files a/tests/_ground_truth_figures/pie_legend_kwargs.png and b/tests/_ground_truth_figures/pie_legend_kwargs.png differ
diff --git a/tests/_ground_truth_figures/pie_legend_loc.png b/tests/_ground_truth_figures/pie_legend_loc.png
index 760c757cc..0773b8940 100644
Binary files a/tests/_ground_truth_figures/pie_legend_loc.png and b/tests/_ground_truth_figures/pie_legend_loc.png differ
diff --git a/tests/_ground_truth_figures/pie_legend_loc_one.png b/tests/_ground_truth_figures/pie_legend_loc_one.png
index 65c92d541..c2bd138c8 100644
Binary files a/tests/_ground_truth_figures/pie_legend_loc_one.png and b/tests/_ground_truth_figures/pie_legend_loc_one.png differ
diff --git a/tests/_ground_truth_figures/pie_reduction.png b/tests/_ground_truth_figures/pie_reduction.png
index c0afd5910..1fdf65b18 100644
Binary files a/tests/_ground_truth_figures/pie_reduction.png and b/tests/_ground_truth_figures/pie_reduction.png differ
diff --git a/tests/_ground_truth_figures/pie_t.png b/tests/_ground_truth_figures/pie_t.png
index 622426e20..d598854aa 100644
Binary files a/tests/_ground_truth_figures/pie_t.png and b/tests/_ground_truth_figures/pie_t.png differ
diff --git a/tests/_ground_truth_figures/pie_title.png b/tests/_ground_truth_figures/pie_title.png
index 28764dbeb..342658cbb 100644
Binary files a/tests/_ground_truth_figures/pie_title.png and b/tests/_ground_truth_figures/pie_title.png differ
diff --git a/tests/_ground_truth_figures/plot_tsi.png b/tests/_ground_truth_figures/plot_tsi.png
index d84e18a5a..071a5d684 100644
Binary files a/tests/_ground_truth_figures/plot_tsi.png and b/tests/_ground_truth_figures/plot_tsi.png differ
diff --git a/tests/_ground_truth_figures/proj_default_ordering.png b/tests/_ground_truth_figures/proj_default_ordering.png
index a4c197a6b..9f108bdd9 100644
Binary files a/tests/_ground_truth_figures/proj_default_ordering.png and b/tests/_ground_truth_figures/proj_default_ordering.png differ
diff --git a/tests/_ground_truth_figures/proj_dont_normalize_by_mean.png b/tests/_ground_truth_figures/proj_dont_normalize_by_mean.png
index 4c511676f..953c14b06 100644
Binary files a/tests/_ground_truth_figures/proj_dont_normalize_by_mean.png and b/tests/_ground_truth_figures/proj_dont_normalize_by_mean.png differ
diff --git a/tests/_ground_truth_figures/proj_duplicate_keys.png b/tests/_ground_truth_figures/proj_duplicate_keys.png
index a4c197a6b..9f108bdd9 100644
Binary files a/tests/_ground_truth_figures/proj_duplicate_keys.png and b/tests/_ground_truth_figures/proj_duplicate_keys.png differ
diff --git a/tests/_ground_truth_figures/proj_extra_keys.png b/tests/_ground_truth_figures/proj_extra_keys.png
index 422469533..14ac0903a 100644
Binary files a/tests/_ground_truth_figures/proj_extra_keys.png and b/tests/_ground_truth_figures/proj_extra_keys.png differ
diff --git a/tests/_ground_truth_figures/proj_hide_edges.png b/tests/_ground_truth_figures/proj_hide_edges.png
index d2db618e2..4cc962db9 100644
Binary files a/tests/_ground_truth_figures/proj_hide_edges.png and b/tests/_ground_truth_figures/proj_hide_edges.png differ
diff --git a/tests/_ground_truth_figures/proj_key_added.png b/tests/_ground_truth_figures/proj_key_added.png
index bb5bd14ca..1578075b6 100644
Binary files a/tests/_ground_truth_figures/proj_key_added.png and b/tests/_ground_truth_figures/proj_key_added.png differ
diff --git a/tests/_ground_truth_figures/proj_labeldistance.png b/tests/_ground_truth_figures/proj_labeldistance.png
index 16d9a1180..26af27b1a 100644
Binary files a/tests/_ground_truth_figures/proj_labeldistance.png and b/tests/_ground_truth_figures/proj_labeldistance.png differ
diff --git a/tests/_ground_truth_figures/proj_labelrot.png b/tests/_ground_truth_figures/proj_labelrot.png
index d544e5c0e..4343bb536 100644
Binary files a/tests/_ground_truth_figures/proj_labelrot.png and b/tests/_ground_truth_figures/proj_labelrot.png differ
diff --git a/tests/_ground_truth_figures/proj_ncols.png b/tests/_ground_truth_figures/proj_ncols.png
index 559bbd508..549d7ad01 100644
Binary files a/tests/_ground_truth_figures/proj_ncols.png and b/tests/_ground_truth_figures/proj_ncols.png differ
diff --git a/tests/_ground_truth_figures/proj_no_cbar.png b/tests/_ground_truth_figures/proj_no_cbar.png
index 440b757a9..469b06019 100644
Binary files a/tests/_ground_truth_figures/proj_no_cbar.png and b/tests/_ground_truth_figures/proj_no_cbar.png differ
diff --git a/tests/_ground_truth_figures/proj_scvelo_kwargs.png b/tests/_ground_truth_figures/proj_scvelo_kwargs.png
index 240b8df29..fb42237c7 100644
Binary files a/tests/_ground_truth_figures/proj_scvelo_kwargs.png and b/tests/_ground_truth_figures/proj_scvelo_kwargs.png differ
diff --git a/tests/_ground_truth_figures/proj_text_kwargs.png b/tests/_ground_truth_figures/proj_text_kwargs.png
index 6e2dbb720..9023d4744 100644
Binary files a/tests/_ground_truth_figures/proj_text_kwargs.png and b/tests/_ground_truth_figures/proj_text_kwargs.png differ
diff --git a/tests/_ground_truth_figures/proj_use_raw.png b/tests/_ground_truth_figures/proj_use_raw.png
index 698c1d929..1d227edcf 100644
Binary files a/tests/_ground_truth_figures/proj_use_raw.png and b/tests/_ground_truth_figures/proj_use_raw.png differ
diff --git a/tests/_ground_truth_figures/scvelo_connectivity_kernel_emb_stream.png b/tests/_ground_truth_figures/scvelo_connectivity_kernel_emb_stream.png
index feae795e7..214f2e73d 100644
Binary files a/tests/_ground_truth_figures/scvelo_connectivity_kernel_emb_stream.png and b/tests/_ground_truth_figures/scvelo_connectivity_kernel_emb_stream.png differ
diff --git a/tests/_ground_truth_figures/scvelo_final_states.png b/tests/_ground_truth_figures/scvelo_final_states.png
index c505eea21..5082460eb 100644
Binary files a/tests/_ground_truth_figures/scvelo_final_states.png and b/tests/_ground_truth_figures/scvelo_final_states.png differ
diff --git a/tests/_ground_truth_figures/scvelo_final_states_clusters.png b/tests/_ground_truth_figures/scvelo_final_states_clusters.png
index ad1dfd44f..317ecf928 100644
Binary files a/tests/_ground_truth_figures/scvelo_final_states_clusters.png and b/tests/_ground_truth_figures/scvelo_final_states_clusters.png differ
diff --git a/tests/_ground_truth_figures/scvelo_gpcca_fate_probs_cont_not_same.png b/tests/_ground_truth_figures/scvelo_gpcca_fate_probs_cont_not_same.png
index 86ac0d899..17866be6b 100644
Binary files a/tests/_ground_truth_figures/scvelo_gpcca_fate_probs_cont_not_same.png and b/tests/_ground_truth_figures/scvelo_gpcca_fate_probs_cont_not_same.png differ
diff --git a/tests/_ground_truth_figures/scvelo_gpcca_fate_probs_cont_same_clusters.png b/tests/_ground_truth_figures/scvelo_gpcca_fate_probs_cont_same_clusters.png
index 6193c99ba..861fdb6b6 100644
Binary files a/tests/_ground_truth_figures/scvelo_gpcca_fate_probs_cont_same_clusters.png and b/tests/_ground_truth_figures/scvelo_gpcca_fate_probs_cont_same_clusters.png differ
diff --git a/tests/_ground_truth_figures/scvelo_gpcca_fate_probs_cont_same_no_clusters.png b/tests/_ground_truth_figures/scvelo_gpcca_fate_probs_cont_same_no_clusters.png
index 6193c99ba..861fdb6b6 100644
Binary files a/tests/_ground_truth_figures/scvelo_gpcca_fate_probs_cont_same_no_clusters.png and b/tests/_ground_truth_figures/scvelo_gpcca_fate_probs_cont_same_no_clusters.png differ
diff --git a/tests/_ground_truth_figures/scvelo_gpcca_final_states.png b/tests/_ground_truth_figures/scvelo_gpcca_final_states.png
index 6dc90c434..5b94dcd93 100644
Binary files a/tests/_ground_truth_figures/scvelo_gpcca_final_states.png and b/tests/_ground_truth_figures/scvelo_gpcca_final_states.png differ
diff --git a/tests/_ground_truth_figures/scvelo_gpcca_final_states_cluster_key.png b/tests/_ground_truth_figures/scvelo_gpcca_final_states_cluster_key.png
index 7e6666858..c44d3fe08 100644
Binary files a/tests/_ground_truth_figures/scvelo_gpcca_final_states_cluster_key.png and b/tests/_ground_truth_figures/scvelo_gpcca_final_states_cluster_key.png differ
diff --git a/tests/_ground_truth_figures/scvelo_gpcca_final_states_cmap.png b/tests/_ground_truth_figures/scvelo_gpcca_final_states_cmap.png
index 5dbe40a0c..9da1721af 100644
Binary files a/tests/_ground_truth_figures/scvelo_gpcca_final_states_cmap.png and b/tests/_ground_truth_figures/scvelo_gpcca_final_states_cmap.png differ
diff --git a/tests/_ground_truth_figures/scvelo_gpcca_final_states_discrete.png b/tests/_ground_truth_figures/scvelo_gpcca_final_states_discrete.png
index 6dc90c434..5b94dcd93 100644
Binary files a/tests/_ground_truth_figures/scvelo_gpcca_final_states_discrete.png and b/tests/_ground_truth_figures/scvelo_gpcca_final_states_discrete.png differ
diff --git a/tests/_ground_truth_figures/scvelo_gpcca_final_states_lineages.png b/tests/_ground_truth_figures/scvelo_gpcca_final_states_lineages.png
index 19f8cb2a4..f977611e1 100644
Binary files a/tests/_ground_truth_figures/scvelo_gpcca_final_states_lineages.png and b/tests/_ground_truth_figures/scvelo_gpcca_final_states_lineages.png differ
diff --git a/tests/_ground_truth_figures/scvelo_gpcca_final_states_no_same_plot.png b/tests/_ground_truth_figures/scvelo_gpcca_final_states_no_same_plot.png
index 5dbe40a0c..9da1721af 100644
Binary files a/tests/_ground_truth_figures/scvelo_gpcca_final_states_no_same_plot.png and b/tests/_ground_truth_figures/scvelo_gpcca_final_states_no_same_plot.png differ
diff --git a/tests/_ground_truth_figures/scvelo_gpcca_final_states_time.png b/tests/_ground_truth_figures/scvelo_gpcca_final_states_time.png
index 6dc90c434..5b94dcd93 100644
Binary files a/tests/_ground_truth_figures/scvelo_gpcca_final_states_time.png and b/tests/_ground_truth_figures/scvelo_gpcca_final_states_time.png differ
diff --git a/tests/_ground_truth_figures/scvelo_gpcca_final_states_title.png b/tests/_ground_truth_figures/scvelo_gpcca_final_states_title.png
index 52f9d2ca0..223edbab6 100644
Binary files a/tests/_ground_truth_figures/scvelo_gpcca_final_states_title.png and b/tests/_ground_truth_figures/scvelo_gpcca_final_states_title.png differ
diff --git a/tests/_ground_truth_figures/scvelo_gpcca_meta_states.png b/tests/_ground_truth_figures/scvelo_gpcca_meta_states.png
index 88323cc2e..2da215e5f 100644
Binary files a/tests/_ground_truth_figures/scvelo_gpcca_meta_states.png and b/tests/_ground_truth_figures/scvelo_gpcca_meta_states.png differ
diff --git a/tests/_ground_truth_figures/scvelo_gpcca_meta_states_cluster_key.png b/tests/_ground_truth_figures/scvelo_gpcca_meta_states_cluster_key.png
index 8d601de87..bb938d897 100644
Binary files a/tests/_ground_truth_figures/scvelo_gpcca_meta_states_cluster_key.png and b/tests/_ground_truth_figures/scvelo_gpcca_meta_states_cluster_key.png differ
diff --git a/tests/_ground_truth_figures/scvelo_gpcca_meta_states_cmap.png b/tests/_ground_truth_figures/scvelo_gpcca_meta_states_cmap.png
index 5180cc426..f2f3a915e 100644
Binary files a/tests/_ground_truth_figures/scvelo_gpcca_meta_states_cmap.png and b/tests/_ground_truth_figures/scvelo_gpcca_meta_states_cmap.png differ
diff --git a/tests/_ground_truth_figures/scvelo_gpcca_meta_states_discrete.png b/tests/_ground_truth_figures/scvelo_gpcca_meta_states_discrete.png
index 88323cc2e..2da215e5f 100644
Binary files a/tests/_ground_truth_figures/scvelo_gpcca_meta_states_discrete.png and b/tests/_ground_truth_figures/scvelo_gpcca_meta_states_discrete.png differ
diff --git a/tests/_ground_truth_figures/scvelo_gpcca_meta_states_lineages.png b/tests/_ground_truth_figures/scvelo_gpcca_meta_states_lineages.png
index 65c863d44..ec3c56f37 100644
Binary files a/tests/_ground_truth_figures/scvelo_gpcca_meta_states_lineages.png and b/tests/_ground_truth_figures/scvelo_gpcca_meta_states_lineages.png differ
diff --git a/tests/_ground_truth_figures/scvelo_gpcca_meta_states_no_same_plot.png b/tests/_ground_truth_figures/scvelo_gpcca_meta_states_no_same_plot.png
index 5180cc426..f2f3a915e 100644
Binary files a/tests/_ground_truth_figures/scvelo_gpcca_meta_states_no_same_plot.png and b/tests/_ground_truth_figures/scvelo_gpcca_meta_states_no_same_plot.png differ
diff --git a/tests/_ground_truth_figures/scvelo_gpcca_meta_states_time.png b/tests/_ground_truth_figures/scvelo_gpcca_meta_states_time.png
index 88323cc2e..2da215e5f 100644
Binary files a/tests/_ground_truth_figures/scvelo_gpcca_meta_states_time.png and b/tests/_ground_truth_figures/scvelo_gpcca_meta_states_time.png differ
diff --git a/tests/_ground_truth_figures/scvelo_gpcca_meta_states_title.png b/tests/_ground_truth_figures/scvelo_gpcca_meta_states_title.png
index 52f9d2ca0..223edbab6 100644
Binary files a/tests/_ground_truth_figures/scvelo_gpcca_meta_states_title.png and b/tests/_ground_truth_figures/scvelo_gpcca_meta_states_title.png differ
diff --git a/tests/_ground_truth_figures/scvelo_lin_probs.png b/tests/_ground_truth_figures/scvelo_lin_probs.png
index affb19008..0782be146 100644
Binary files a/tests/_ground_truth_figures/scvelo_lin_probs.png and b/tests/_ground_truth_figures/scvelo_lin_probs.png differ
diff --git a/tests/_ground_truth_figures/scvelo_lin_probs_clusters.png b/tests/_ground_truth_figures/scvelo_lin_probs_clusters.png
index affb19008..0782be146 100644
Binary files a/tests/_ground_truth_figures/scvelo_lin_probs_clusters.png and b/tests/_ground_truth_figures/scvelo_lin_probs_clusters.png differ
diff --git a/tests/_ground_truth_figures/scvelo_lin_probs_cmap.png b/tests/_ground_truth_figures/scvelo_lin_probs_cmap.png
index affb19008..0782be146 100644
Binary files a/tests/_ground_truth_figures/scvelo_lin_probs_cmap.png and b/tests/_ground_truth_figures/scvelo_lin_probs_cmap.png differ
diff --git a/tests/_ground_truth_figures/scvelo_lin_probs_lineages.png b/tests/_ground_truth_figures/scvelo_lin_probs_lineages.png
index f800c6117..b5beb475c 100644
Binary files a/tests/_ground_truth_figures/scvelo_lin_probs_lineages.png and b/tests/_ground_truth_figures/scvelo_lin_probs_lineages.png differ
diff --git a/tests/_ground_truth_figures/scvelo_lin_probs_time.png b/tests/_ground_truth_figures/scvelo_lin_probs_time.png
index dde3525a4..ff5ba8785 100644
Binary files a/tests/_ground_truth_figures/scvelo_lin_probs_time.png and b/tests/_ground_truth_figures/scvelo_lin_probs_time.png differ
diff --git a/tests/_ground_truth_figures/scvelo_pseudotime_kernel_hard_threshold_emb_stream.png b/tests/_ground_truth_figures/scvelo_pseudotime_kernel_hard_threshold_emb_stream.png
index 0eeeb9966..214f2e73d 100644
Binary files a/tests/_ground_truth_figures/scvelo_pseudotime_kernel_hard_threshold_emb_stream.png and b/tests/_ground_truth_figures/scvelo_pseudotime_kernel_hard_threshold_emb_stream.png differ
diff --git a/tests/_ground_truth_figures/scvelo_pseudotime_kernel_soft_threshold_emb_stream.png b/tests/_ground_truth_figures/scvelo_pseudotime_kernel_soft_threshold_emb_stream.png
index f500ebd55..214f2e73d 100644
Binary files a/tests/_ground_truth_figures/scvelo_pseudotime_kernel_soft_threshold_emb_stream.png and b/tests/_ground_truth_figures/scvelo_pseudotime_kernel_soft_threshold_emb_stream.png differ
diff --git a/tests/_ground_truth_figures/scvelo_transition_matrix_projection.png b/tests/_ground_truth_figures/scvelo_transition_matrix_projection.png
index e767dc94c..9e59ff2f6 100644
Binary files a/tests/_ground_truth_figures/scvelo_transition_matrix_projection.png and b/tests/_ground_truth_figures/scvelo_transition_matrix_projection.png differ
diff --git a/tests/_ground_truth_figures/scvelo_velocity_kernel_emb_stream.png b/tests/_ground_truth_figures/scvelo_velocity_kernel_emb_stream.png
index ab19cc6dd..214f2e73d 100644
Binary files a/tests/_ground_truth_figures/scvelo_velocity_kernel_emb_stream.png and b/tests/_ground_truth_figures/scvelo_velocity_kernel_emb_stream.png differ
diff --git a/tests/_ground_truth_figures/transpose.png b/tests/_ground_truth_figures/transpose.png
index b367c78b6..f402d69bc 100644
Binary files a/tests/_ground_truth_figures/transpose.png and b/tests/_ground_truth_figures/transpose.png differ
diff --git a/tests/_ground_truth_figures/transpose_all_models_for_1_gene_failed.png b/tests/_ground_truth_figures/transpose_all_models_for_1_gene_failed.png
index 6dd31127e..0b622954c 100644
Binary files a/tests/_ground_truth_figures/transpose_all_models_for_1_gene_failed.png and b/tests/_ground_truth_figures/transpose_all_models_for_1_gene_failed.png differ
diff --git a/tests/_ground_truth_figures/transpose_all_models_for_1_lineage_failed.png b/tests/_ground_truth_figures/transpose_all_models_for_1_lineage_failed.png
index 681314c75..7c513190e 100644
Binary files a/tests/_ground_truth_figures/transpose_all_models_for_1_lineage_failed.png and b/tests/_ground_truth_figures/transpose_all_models_for_1_lineage_failed.png differ
diff --git a/tests/_ground_truth_figures/transpose_all_models_for_1_lineage_failed_same_plot.png b/tests/_ground_truth_figures/transpose_all_models_for_1_lineage_failed_same_plot.png
index 37426165b..4d83215a8 100644
Binary files a/tests/_ground_truth_figures/transpose_all_models_for_1_lineage_failed_same_plot.png and b/tests/_ground_truth_figures/transpose_all_models_for_1_lineage_failed_same_plot.png differ
diff --git a/tests/_ground_truth_figures/transpose_failed_only_off_diagonal.png b/tests/_ground_truth_figures/transpose_failed_only_off_diagonal.png
index 48ae5c38f..b94540cb9 100644
Binary files a/tests/_ground_truth_figures/transpose_failed_only_off_diagonal.png and b/tests/_ground_truth_figures/transpose_failed_only_off_diagonal.png differ
diff --git a/tests/_ground_truth_figures/transpose_same_plot.png b/tests/_ground_truth_figures/transpose_same_plot.png
index 31babc761..01fb55e06 100644
Binary files a/tests/_ground_truth_figures/transpose_same_plot.png and b/tests/_ground_truth_figures/transpose_same_plot.png differ
diff --git a/tests/_ground_truth_figures/trends.png b/tests/_ground_truth_figures/trends.png
index 02016a4b2..d22febf20 100644
Binary files a/tests/_ground_truth_figures/trends.png and b/tests/_ground_truth_figures/trends.png differ
diff --git a/tests/_ground_truth_figures/trends_bwd.png b/tests/_ground_truth_figures/trends_bwd.png
index 8f8ff062c..49e5c33b8 100644
Binary files a/tests/_ground_truth_figures/trends_bwd.png and b/tests/_ground_truth_figures/trends_bwd.png differ
diff --git a/tests/_ground_truth_figures/trends_cell_alpha.png b/tests/_ground_truth_figures/trends_cell_alpha.png
index 8f7ad4674..bbd1a364a 100644
Binary files a/tests/_ground_truth_figures/trends_cell_alpha.png and b/tests/_ground_truth_figures/trends_cell_alpha.png differ
diff --git a/tests/_ground_truth_figures/trends_conf_int.png b/tests/_ground_truth_figures/trends_conf_int.png
index 8e0a8c2ed..19ba5ea8e 100644
Binary files a/tests/_ground_truth_figures/trends_conf_int.png and b/tests/_ground_truth_figures/trends_conf_int.png differ
diff --git a/tests/_ground_truth_figures/trends_fate_prob_cmap.png b/tests/_ground_truth_figures/trends_fate_prob_cmap.png
index 6c2770fd9..60dbdb1dd 100644
Binary files a/tests/_ground_truth_figures/trends_fate_prob_cmap.png and b/tests/_ground_truth_figures/trends_fate_prob_cmap.png differ
diff --git a/tests/_ground_truth_figures/trends_gam_ci_100.png b/tests/_ground_truth_figures/trends_gam_ci_100.png
index e5c1c505d..1d43cd2aa 100644
Binary files a/tests/_ground_truth_figures/trends_gam_ci_100.png and b/tests/_ground_truth_figures/trends_gam_ci_100.png differ
diff --git a/tests/_ground_truth_figures/trends_gam_ci_20.png b/tests/_ground_truth_figures/trends_gam_ci_20.png
index 5b17e69ce..10a106ca9 100644
Binary files a/tests/_ground_truth_figures/trends_gam_ci_20.png and b/tests/_ground_truth_figures/trends_gam_ci_20.png differ
diff --git a/tests/_ground_truth_figures/trends_gene_as_title.png b/tests/_ground_truth_figures/trends_gene_as_title.png
index d26f9e4a4..2738175ff 100644
Binary files a/tests/_ground_truth_figures/trends_gene_as_title.png and b/tests/_ground_truth_figures/trends_gene_as_title.png differ
diff --git a/tests/_ground_truth_figures/trends_gene_legend_out.png b/tests/_ground_truth_figures/trends_gene_legend_out.png
index b6e6f70f5..0993fc657 100644
Binary files a/tests/_ground_truth_figures/trends_gene_legend_out.png and b/tests/_ground_truth_figures/trends_gene_legend_out.png differ
diff --git a/tests/_ground_truth_figures/trends_gene_no_legend.png b/tests/_ground_truth_figures/trends_gene_no_legend.png
index 403d21b06..c0b570297 100644
Binary files a/tests/_ground_truth_figures/trends_gene_no_legend.png and b/tests/_ground_truth_figures/trends_gene_no_legend.png differ
diff --git a/tests/_ground_truth_figures/trends_gene_symbols.png b/tests/_ground_truth_figures/trends_gene_symbols.png
index be6857f17..5a8d529e1 100644
Binary files a/tests/_ground_truth_figures/trends_gene_symbols.png and b/tests/_ground_truth_figures/trends_gene_symbols.png differ
diff --git a/tests/_ground_truth_figures/trends_hide_cells.png b/tests/_ground_truth_figures/trends_hide_cells.png
index bbc058703..f2613a2f8 100644
Binary files a/tests/_ground_truth_figures/trends_hide_cells.png and b/tests/_ground_truth_figures/trends_hide_cells.png differ
diff --git a/tests/_ground_truth_figures/trends_lineage_alpha.png b/tests/_ground_truth_figures/trends_lineage_alpha.png
index db66af81e..1a793999f 100644
Binary files a/tests/_ground_truth_figures/trends_lineage_alpha.png and b/tests/_ground_truth_figures/trends_lineage_alpha.png differ
diff --git a/tests/_ground_truth_figures/trends_lineage_cell_color.png b/tests/_ground_truth_figures/trends_lineage_cell_color.png
index 8dc4caac2..cda2c8f7e 100644
Binary files a/tests/_ground_truth_figures/trends_lineage_cell_color.png and b/tests/_ground_truth_figures/trends_lineage_cell_color.png differ
diff --git a/tests/_ground_truth_figures/trends_lineage_cell_color_clusters.png b/tests/_ground_truth_figures/trends_lineage_cell_color_clusters.png
index 8bc2083cc..2f07111bc 100644
Binary files a/tests/_ground_truth_figures/trends_lineage_cell_color_clusters.png and b/tests/_ground_truth_figures/trends_lineage_cell_color_clusters.png differ
diff --git a/tests/_ground_truth_figures/trends_lineage_cell_color_clusters_obs_legend_loc.png b/tests/_ground_truth_figures/trends_lineage_cell_color_clusters_obs_legend_loc.png
index e170309d5..27fa7aed5 100644
Binary files a/tests/_ground_truth_figures/trends_lineage_cell_color_clusters_obs_legend_loc.png and b/tests/_ground_truth_figures/trends_lineage_cell_color_clusters_obs_legend_loc.png differ
diff --git a/tests/_ground_truth_figures/trends_lineage_cell_color_gene.png b/tests/_ground_truth_figures/trends_lineage_cell_color_gene.png
index 4f186a1b9..f41f21519 100644
Binary files a/tests/_ground_truth_figures/trends_lineage_cell_color_gene.png and b/tests/_ground_truth_figures/trends_lineage_cell_color_gene.png differ
diff --git a/tests/_ground_truth_figures/trends_lineage_cmap.png b/tests/_ground_truth_figures/trends_lineage_cmap.png
index 40d97e7af..fe24d9c71 100644
Binary files a/tests/_ground_truth_figures/trends_lineage_cmap.png and b/tests/_ground_truth_figures/trends_lineage_cmap.png differ
diff --git a/tests/_ground_truth_figures/trends_lw.png b/tests/_ground_truth_figures/trends_lw.png
index d49558077..c797eda16 100644
Binary files a/tests/_ground_truth_figures/trends_lw.png and b/tests/_ground_truth_figures/trends_lw.png differ
diff --git a/tests/_ground_truth_figures/trends_margins.png b/tests/_ground_truth_figures/trends_margins.png
index 740a71ebb..15805dbab 100644
Binary files a/tests/_ground_truth_figures/trends_margins.png and b/tests/_ground_truth_figures/trends_margins.png differ
diff --git a/tests/_ground_truth_figures/trends_no_cbar.png b/tests/_ground_truth_figures/trends_no_cbar.png
index 954c03cde..914377d56 100644
Binary files a/tests/_ground_truth_figures/trends_no_cbar.png and b/tests/_ground_truth_figures/trends_no_cbar.png differ
diff --git a/tests/_ground_truth_figures/trends_perc.png b/tests/_ground_truth_figures/trends_perc.png
index 403d21b06..c0b570297 100644
Binary files a/tests/_ground_truth_figures/trends_perc.png and b/tests/_ground_truth_figures/trends_perc.png differ
diff --git a/tests/_ground_truth_figures/trends_perc_per_lineage.png b/tests/_ground_truth_figures/trends_perc_per_lineage.png
index 5cc17365e..b9c814b88 100644
Binary files a/tests/_ground_truth_figures/trends_perc_per_lineage.png and b/tests/_ground_truth_figures/trends_perc_per_lineage.png differ
diff --git a/tests/_ground_truth_figures/trends_raw.png b/tests/_ground_truth_figures/trends_raw.png
index ad3370a36..cee447b2f 100644
Binary files a/tests/_ground_truth_figures/trends_raw.png and b/tests/_ground_truth_figures/trends_raw.png differ
diff --git a/tests/_ground_truth_figures/trends_same_plot.png b/tests/_ground_truth_figures/trends_same_plot.png
index 6de30bd19..e28b2fa0d 100644
Binary files a/tests/_ground_truth_figures/trends_same_plot.png and b/tests/_ground_truth_figures/trends_same_plot.png differ
diff --git a/tests/_ground_truth_figures/trends_sharex.png b/tests/_ground_truth_figures/trends_sharex.png
index 403d21b06..c0b570297 100644
Binary files a/tests/_ground_truth_figures/trends_sharex.png and b/tests/_ground_truth_figures/trends_sharex.png differ
diff --git a/tests/_ground_truth_figures/trends_sharey.png b/tests/_ground_truth_figures/trends_sharey.png
index 02016a4b2..d22febf20 100644
Binary files a/tests/_ground_truth_figures/trends_sharey.png and b/tests/_ground_truth_figures/trends_sharey.png differ
diff --git a/tests/_ground_truth_figures/trends_show_lineage_ci.png b/tests/_ground_truth_figures/trends_show_lineage_ci.png
index 3a7cbdab3..986b9f128 100644
Binary files a/tests/_ground_truth_figures/trends_show_lineage_ci.png and b/tests/_ground_truth_figures/trends_show_lineage_ci.png differ
diff --git a/tests/_ground_truth_figures/trends_show_lineage_diff_plot.png b/tests/_ground_truth_figures/trends_show_lineage_diff_plot.png
index 98630ea41..45399591e 100644
Binary files a/tests/_ground_truth_figures/trends_show_lineage_diff_plot.png and b/tests/_ground_truth_figures/trends_show_lineage_diff_plot.png differ
diff --git a/tests/_ground_truth_figures/trends_show_lineage_ignores_no_transpose.png b/tests/_ground_truth_figures/trends_show_lineage_ignores_no_transpose.png
index 818e020d4..255f39e20 100644
Binary files a/tests/_ground_truth_figures/trends_show_lineage_ignores_no_transpose.png and b/tests/_ground_truth_figures/trends_show_lineage_ignores_no_transpose.png differ
diff --git a/tests/_ground_truth_figures/trends_show_lineage_same_plot.png b/tests/_ground_truth_figures/trends_show_lineage_same_plot.png
index 82dc7a833..fcaeb6bd2 100644
Binary files a/tests/_ground_truth_figures/trends_show_lineage_same_plot.png and b/tests/_ground_truth_figures/trends_show_lineage_same_plot.png differ
diff --git a/tests/_ground_truth_figures/trends_size.png b/tests/_ground_truth_figures/trends_size.png
index 5c2bd04b3..369158dfe 100644
Binary files a/tests/_ground_truth_figures/trends_size.png and b/tests/_ground_truth_figures/trends_size.png differ
diff --git a/tests/_ground_truth_figures/trends_suptitle.png b/tests/_ground_truth_figures/trends_suptitle.png
index dd680a123..97caad028 100644
Binary files a/tests/_ground_truth_figures/trends_suptitle.png and b/tests/_ground_truth_figures/trends_suptitle.png differ
diff --git a/tests/_ground_truth_figures/trends_time_key.png b/tests/_ground_truth_figures/trends_time_key.png
index 00cb80913..355849276 100644
Binary files a/tests/_ground_truth_figures/trends_time_key.png and b/tests/_ground_truth_figures/trends_time_key.png differ
diff --git a/tests/_ground_truth_figures/trends_time_key_del_latent_time.png b/tests/_ground_truth_figures/trends_time_key_del_latent_time.png
index 00cb80913..355849276 100644
Binary files a/tests/_ground_truth_figures/trends_time_key_del_latent_time.png and b/tests/_ground_truth_figures/trends_time_key_del_latent_time.png differ
diff --git a/tests/_ground_truth_figures/trends_time_range.png b/tests/_ground_truth_figures/trends_time_range.png
index 8cf42da00..d82a7bff6 100644
Binary files a/tests/_ground_truth_figures/trends_time_range.png and b/tests/_ground_truth_figures/trends_time_range.png differ
diff --git a/tests/_ground_truth_figures/violin.png b/tests/_ground_truth_figures/violin.png
index 084542102..1b60f8cb6 100644
Binary files a/tests/_ground_truth_figures/violin.png and b/tests/_ground_truth_figures/violin.png differ
diff --git a/tests/_ground_truth_figures/violin_cluster_subset.png b/tests/_ground_truth_figures/violin_cluster_subset.png
index 59b035177..baeb6e69a 100644
Binary files a/tests/_ground_truth_figures/violin_cluster_subset.png and b/tests/_ground_truth_figures/violin_cluster_subset.png differ
diff --git a/tests/_ground_truth_figures/violin_lineage_subset.png b/tests/_ground_truth_figures/violin_lineage_subset.png
index d49b8b254..03d420969 100644
Binary files a/tests/_ground_truth_figures/violin_lineage_subset.png and b/tests/_ground_truth_figures/violin_lineage_subset.png differ
diff --git a/tests/_ground_truth_figures/violin_no_cluster_key.png b/tests/_ground_truth_figures/violin_no_cluster_key.png
index 9e6da4be9..390691c2a 100644
Binary files a/tests/_ground_truth_figures/violin_no_cluster_key.png and b/tests/_ground_truth_figures/violin_no_cluster_key.png differ
diff --git a/tests/_helpers.py b/tests/_helpers.py
index 7925558e3..19e8d634d 100644
--- a/tests/_helpers.py
+++ b/tests/_helpers.py
@@ -1,6 +1,6 @@
import os
import pathlib
-from typing import Optional, Tuple, Union
+from typing import Optional, Union
import pytest
import scvelo as scv
@@ -32,15 +32,10 @@ def _jax_not_installed() -> bool:
def _rpy2_mgcv_not_installed() -> bool:
try:
import rpy2
+ from importlib_metadata import version as get_version
from packaging import version
from rpy2.robjects.packages import PackageNotInstalledError, importr
- try:
- from importlib_metadata import version as get_version
- except ImportError:
- # >=Python3.8
- from importlib.metadata import version as get_version
-
try:
assert version.parse(get_version(rpy2.__name__)) >= version.parse("3.3.0")
_ = importr("mgcv")
@@ -102,16 +97,14 @@ def density_normalization(velo_graph, trans_graph):
Q = np.diag(1.0 / q)
else:
Q = sp.spdiags(1.0 / q, 0, trans_graph.shape[0], trans_graph.shape[0])
- velo_graph = Q @ velo_graph @ Q
-
- return velo_graph
+ return Q @ velo_graph @ Q
def create_kernels(
adata: AnnData,
velocity_variances: Optional[str] = None,
connectivity_variances: Optional[str] = None,
-) -> Tuple[VelocityKernel, ConnectivityKernel]:
+) -> tuple[VelocityKernel, ConnectivityKernel]:
rng = np.random.default_rng()
vk = VelocityKernel(adata)
vk._mat_scaler = adata.obsp.get(velocity_variances, rng.normal(size=(adata.n_obs, adata.n_obs)))
diff --git a/tests/conftest.py b/tests/conftest.py
index 69e34e00e..763324749 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -1,6 +1,6 @@
import pathlib
import warnings
-from typing import Optional, Tuple
+from typing import Optional
import pytest
from _helpers import create_model
@@ -44,7 +44,7 @@ def pytest_sessionfinish(session: pytest.Session, exitstatus) -> None:
logger.removeHandler(handler)
-def _create_cflare(*, backward: bool = False) -> Tuple[AnnData, CFLARE]:
+def _create_cflare(*, backward: bool = False) -> tuple[AnnData, CFLARE]:
adata = _adata_medium.copy()
sc.tl.paga(adata, groups="clusters")
@@ -67,7 +67,7 @@ def _create_cflare(*, backward: bool = False) -> Tuple[AnnData, CFLARE]:
return adata, mc
-def _create_gpcca(*, backward: bool = False) -> Tuple[AnnData, GPCCA]:
+def _create_gpcca(*, backward: bool = False) -> tuple[AnnData, GPCCA]:
adata = _adata_medium.copy()
sc.tl.paga(adata, groups="clusters")
@@ -102,43 +102,43 @@ def _create_gamr_model(_adata: AnnData) -> Optional[GAMR]:
return None
-@pytest.fixture()
+@pytest.fixture
def adata() -> AnnData:
return _adata_small.copy()
-@pytest.fixture()
+@pytest.fixture
def adata_large() -> AnnData:
return _adata_large.copy()
-@pytest.fixture()
+@pytest.fixture
def adata_cflare_fwd(
adata_cflare=_create_cflare(backward=False), # noqa: B008
-) -> Tuple[AnnData, CFLARE]:
+) -> tuple[AnnData, CFLARE]:
adata, cflare = adata_cflare
return adata.copy(), cflare
-@pytest.fixture()
-def adata_gpcca_fwd(adata_gpcca=_create_gpcca(backward=False)) -> Tuple[AnnData, GPCCA]: # noqa: B008
+@pytest.fixture
+def adata_gpcca_fwd(adata_gpcca=_create_gpcca(backward=False)) -> tuple[AnnData, GPCCA]: # noqa: B008
adata, gpcca = adata_gpcca
return adata.copy(), gpcca
-@pytest.fixture()
-def adata_gpcca_bwd(adata_gpcca=_create_gpcca(backward=True)) -> Tuple[AnnData, GPCCA]: # noqa: B008
+@pytest.fixture
+def adata_gpcca_bwd(adata_gpcca=_create_gpcca(backward=True)) -> tuple[AnnData, GPCCA]: # noqa: B008
adata, gpcca = adata_gpcca
return adata.copy(), gpcca
-@pytest.fixture()
+@pytest.fixture
def adata_cflare(adata_cflare=_create_cflare(backward=False)) -> AnnData: # noqa: B008
return adata_cflare[0].copy()
-@pytest.fixture()
-def g(adata_gpcca=_create_gpcca(backward=False)) -> Tuple[AnnData, GPCCA]: # noqa: B008
+@pytest.fixture
+def g(adata_gpcca=_create_gpcca(backward=False)) -> tuple[AnnData, GPCCA]: # noqa: B008
return adata_gpcca[1].copy()
@@ -147,28 +147,12 @@ def adata_gamr(adata_cflare=_create_cflare(backward=False)) -> AnnData: # noqa:
return adata_cflare[0].copy()
-@pytest.fixture(scope="session")
-def gamr_model(adata_gamr: AnnData, tmp_path_factory: pathlib.Path, worker_id: str) -> Optional[GAMR]:
- if worker_id == "master":
- model = _create_gamr_model(adata_gamr)
- else:
- root_tmp_dir = tmp_path_factory.getbasetemp().parent
- fn = root_tmp_dir / "model.pickle"
-
- if fn.is_file():
- model = GAMR.read(fn)
- else:
- model = _create_gamr_model(adata_gamr)
- if model is not None:
- model.write(fn)
-
- if model is None:
- pytest.skip("Unable to create `cellrank.models.GAMR`.")
-
- return model
+@pytest.fixture
+def gamr_model(adata_gamr: AnnData, tmp_path_factory: pathlib.Path) -> Optional[GAMR]:
+ return _create_gamr_model(adata_gamr)
-@pytest.fixture()
+@pytest.fixture
def pygam_model(adata_cflare: AnnData) -> GAM:
m = GAM(adata_cflare)
m.prepare(adata_cflare.var_names[0], "0", "latent_time").fit()
@@ -178,7 +162,7 @@ def pygam_model(adata_cflare: AnnData) -> GAM:
return m
-@pytest.fixture()
+@pytest.fixture
def sklearn_model(adata_cflare: AnnData) -> SKLearnModel:
m = create_model(adata_cflare)
assert isinstance(m, SKLearnModel), m
@@ -190,7 +174,7 @@ def sklearn_model(adata_cflare: AnnData) -> SKLearnModel:
return m
-@pytest.fixture()
+@pytest.fixture
def lineage():
x = cr._utils.Lineage(
np.array(
@@ -212,7 +196,7 @@ def lineage():
return x / x.sum(1)
-@pytest.fixture()
+@pytest.fixture
def kernel(adata_large: AnnData):
vk = VelocityKernel(adata_large).compute_transition_matrix(softmax_scale=4)
ck = ConnectivityKernel(adata_large).compute_transition_matrix()
diff --git a/tests/test_cflare.py b/tests/test_cflare.py
index b43c0ca48..740f8f9d0 100644
--- a/tests/test_cflare.py
+++ b/tests/test_cflare.py
@@ -1,5 +1,4 @@
import os
-from typing import Tuple
import pytest
from _helpers import assert_estimators_equal
@@ -492,13 +491,13 @@ def test_fate_probs_negative(self, adata_large: AnnData, mocker):
class TestCFLAREIO:
@pytest.mark.parametrize("deep", [False, True])
- def test_copy(self, adata_cflare_fwd: Tuple[AnnData, cr.estimators.CFLARE], deep: bool):
+ def test_copy(self, adata_cflare_fwd: tuple[AnnData, cr.estimators.CFLARE], deep: bool):
_, mc1 = adata_cflare_fwd
mc2 = mc1.copy(deep=deep)
assert_estimators_equal(mc1, mc2, copy=True, deep=deep)
- def test_read(self, adata_cflare_fwd: Tuple[AnnData, cr.estimators.CFLARE], tmpdir):
+ def test_read(self, adata_cflare_fwd: tuple[AnnData, cr.estimators.CFLARE], tmpdir):
_, mc1 = adata_cflare_fwd
mc1.write(os.path.join(tmpdir, "foo.pickle"))
diff --git a/tests/test_gpcca.py b/tests/test_gpcca.py
index 8af963dee..3cd4f76d4 100644
--- a/tests/test_gpcca.py
+++ b/tests/test_gpcca.py
@@ -1,7 +1,8 @@
import copy
import enum
import os
-from typing import List, Optional, Sequence, Tuple, Union
+from collections.abc import Sequence
+from typing import Optional, Union
import pytest
from _helpers import assert_array_nan_equal, assert_estimators_equal
@@ -71,7 +72,7 @@ def key(self) -> Optional[str]:
return None
@property
- def attr_keys(self) -> Optional[Sequence[Tuple[str, str]]]:
+ def attr_keys(self) -> Optional[Sequence[tuple[str, str]]]:
bwd = False
if self.value == "schur":
key1 = Key.uns.eigen(bwd)
@@ -99,7 +100,7 @@ def attr_keys(self) -> Optional[Sequence[Tuple[str, str]]]:
return None
@property
- def attrs(self) -> Optional[Sequence[Tuple[str, type]]]:
+ def attrs(self) -> Optional[Sequence[tuple[str, type]]]:
if self.value == "schur":
return ("_eigendecomposition", dict), ("_schur_vectors", np.ndarray), ("_schur_matrix", np.ndarray)
if self.value == "macro":
@@ -593,7 +594,7 @@ def test_set_terminal_states_from_macrostates_invalid_name(self, adata_large: An
mc.set_terminal_states(states=["foobar"])
@pytest.mark.parametrize("values", ["Astrocytes", ["Astrocytes", "OPC"]])
- def test_set_terminal_states_clusters(self, adata_large: AnnData, values: Union[str, List[str]]):
+ def test_set_terminal_states_clusters(self, adata_large: AnnData, values: Union[str, list[str]]):
vk = VelocityKernel(adata_large).compute_transition_matrix(softmax_scale=4)
ck = ConnectivityKernel(adata_large).compute_transition_matrix()
terminal_kernel = 0.8 * vk + 0.2 * ck
@@ -1101,13 +1102,13 @@ def test_rename_states_normal_run(self, adata_large: AnnData, initial: bool):
class TestGPCCAIO:
@pytest.mark.parametrize("deep", [False, True])
- def test_copy(self, adata_gpcca_fwd: Tuple[AnnData, cr.estimators.GPCCA], deep: bool):
+ def test_copy(self, adata_gpcca_fwd: tuple[AnnData, cr.estimators.GPCCA], deep: bool):
_, mc1 = adata_gpcca_fwd
mc2 = mc1.copy(deep=deep)
assert_estimators_equal(mc1, mc2, copy=True, deep=deep)
- def test_read(self, adata_gpcca_fwd: Tuple[AnnData, cr.estimators.GPCCA], tmpdir):
+ def test_read(self, adata_gpcca_fwd: tuple[AnnData, cr.estimators.GPCCA], tmpdir):
_, mc1 = adata_gpcca_fwd
mc1.write(os.path.join(tmpdir, "foo.pkl"))
@@ -1118,7 +1119,7 @@ def test_read(self, adata_gpcca_fwd: Tuple[AnnData, cr.estimators.GPCCA], tmpdir
@pytest.mark.parametrize("copy", [False, True])
def test_write_no_adata(
self,
- adata_gpcca_fwd: Tuple[AnnData, cr.estimators.GPCCA],
+ adata_gpcca_fwd: tuple[AnnData, cr.estimators.GPCCA],
copy: bool,
tmpdir,
):
@@ -1133,14 +1134,14 @@ def test_write_no_adata(
assert adata is mc2.adata
assert_estimators_equal(mc1, mc2)
- def test_write_no_adata_read_none_supplied(self, adata_gpcca_fwd: Tuple[AnnData, cr.estimators.GPCCA], tmpdir):
+ def test_write_no_adata_read_none_supplied(self, adata_gpcca_fwd: tuple[AnnData, cr.estimators.GPCCA], tmpdir):
_, mc1 = adata_gpcca_fwd
mc1.write(os.path.join(tmpdir, "foo.pkl"), write_adata=False)
with pytest.raises(TypeError, match="This object was saved without"):
_ = cr.estimators.GPCCA.read(os.path.join(tmpdir, "foo.pkl"), adata=None)
- def test_write_no_adata_read_wrong_length(self, adata_gpcca_fwd: Tuple[AnnData, cr.estimators.GPCCA], tmpdir):
+ def test_write_no_adata_read_wrong_length(self, adata_gpcca_fwd: tuple[AnnData, cr.estimators.GPCCA], tmpdir):
rng = np.random.default_rng()
_, mc1 = adata_gpcca_fwd
adata = AnnData(rng.normal(size=(len(mc1) + 1, 1)))
diff --git a/tests/test_kernels.py b/tests/test_kernels.py
index ca3979bc2..be96c0317 100644
--- a/tests/test_kernels.py
+++ b/tests/test_kernels.py
@@ -2,7 +2,7 @@
import itertools
import pathlib
import pickle
-from typing import Callable, Literal, Optional, Tuple, Type
+from typing import Callable, Literal, Optional
import pytest
from _helpers import (
@@ -48,7 +48,7 @@
class CustomFunc(cr.kernels.utils.SimilarityABC):
- def __call__(self, v: np.ndarray, D: np.ndarray, softmax_scale: float = 1.0) -> Tuple[np.ndarray, np.ndarray]:
+ def __call__(self, v: np.ndarray, D: np.ndarray, softmax_scale: float = 1.0) -> tuple[np.ndarray, np.ndarray]:
probs, logits = np.zeros((D.shape[0],), dtype=np.float64), np.zeros((D.shape[0],), dtype=np.float64)
probs[0] = 1.0
@@ -73,12 +73,12 @@ def copy(self, deep: bool = False) -> "CustomKernel":
class InvalidFuncProbs(cr.kernels.utils.SimilarityABC):
- def __call__(self, v: np.ndarray, D: np.ndarray, _softmax_scale: float = 1.0) -> Tuple[np.ndarray, np.ndarray]:
+ def __call__(self, v: np.ndarray, D: np.ndarray, _softmax_scale: float = 1.0) -> tuple[np.ndarray, np.ndarray]:
return np.ones((D.shape[0],), dtype=np.float64), np.zeros((D.shape[0],), dtype=np.float64)
class InvalidFuncHessianShape(CustomFunc):
- def __call__(self, v: np.ndarray, D: np.ndarray, _softmax_scale: float = 1.0) -> Tuple[np.ndarray, np.ndarray]:
+ def __call__(self, v: np.ndarray, D: np.ndarray, _softmax_scale: float = 1.0) -> tuple[np.ndarray, np.ndarray]:
probs, logits = np.zeros((D.shape[0],), dtype=np.float64), np.zeros((D.shape[0],), dtype=np.float64)
probs[-1] = 1.0
@@ -584,7 +584,7 @@ def test_connectivities_key_kernel(self, adata: AnnData):
@pytest.mark.parametrize("cluster_pair", [("Granule immature", "Granule mature"), ("nIPC", "Neuroblast")])
@pytest.mark.parametrize("graph_key", ["distances", "connectivities"])
- def test_cbc(self, adata: AnnData, cluster_pair: Tuple[str, str], graph_key: str):
+ def test_cbc(self, adata: AnnData, cluster_pair: tuple[str, str], graph_key: str):
cluster_key = "clusters"
rep = "X_pca"
source, target = cluster_pair
@@ -752,7 +752,7 @@ def test_copy_works(self, adata: AnnData):
assert ck2.transition_matrix is None
@pytest.mark.parametrize("ignored", [("_transition_matrix",), ("_params", "foobar")])
- def test_copy_ignore(self, adata: AnnData, ignored: Tuple[str, ...]):
+ def test_copy_ignore(self, adata: AnnData, ignored: tuple[str, ...]):
ck1 = ConnectivityKernel(adata).compute_transition_matrix()
ck2 = ck1._copy_ignore(*ignored)
@@ -1199,7 +1199,7 @@ def test_explicit_shuffle(self, adata_large: AnnData):
n, m = np.sum(col == src), np.sum(col == tgt)
expected[src, tgt] = np.eye(n, m)
- rng = np.random.RandomState(13)
+ rng = np.random.default_rng(13)
ixs = np.arange(adata_large.n_obs)
rng.shuffle(ixs)
adata_large = adata_large[ixs].copy()
@@ -1236,7 +1236,7 @@ def test_from_moscot(
if problem == "temporal":
problem = moscot.problems.TemporalProblem(adata_large)
elif problem == "spatiotemporal":
- rng = np.random.RandomState(42)
+ rng = np.random.default_rng(42)
adata_large.obsm["spatial"] = rng.normal(size=(adata_large.n_obs, 2))
problem = moscot.problems.SpatioTemporalProblem(adata_large)
else:
@@ -1518,7 +1518,7 @@ def test_read_write(self, kernel: Kernel, tmpdir, write_adata: bool, copy: bool)
CustomKernel,
],
)
- def test_from_adata(self, adata: AnnData, clazz: Type[Kernel]):
+ def test_from_adata(self, adata: AnnData, clazz: type[Kernel]):
kwargs, key = {}, "foo"
if clazz is PseudotimeKernel:
kwargs["time_key"] = "latent_time"
diff --git a/tests/test_lineage.py b/tests/test_lineage.py
index a63178808..bbef09cd1 100644
--- a/tests/test_lineage.py
+++ b/tests/test_lineage.py
@@ -46,7 +46,7 @@ def validate(self):
class TestLineageCreation:
def test_creation(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
names = ["foo", "bar", "baz"]
colors = ["#000000", "#ababab", "#ffffff"]
l = Lineage(x, names=names, colors=colors)
@@ -81,7 +81,7 @@ def test_from_lineage(self, lineage: Lineage):
def test_wrong_number_of_dimensions(self):
with pytest.raises(ValueError, match=r".* must be 2-dimensional"):
_ = Lineage(
- np.random.random((10, 3, 1)),
+ np.random.default_rng().random((10, 3, 1)),
names=["foo", "bar", "baz"],
colors=[(0, 0, 0), "#ffffff", "#ff00FF"],
)
@@ -89,7 +89,7 @@ def test_wrong_number_of_dimensions(self):
def test_names_length_mismatch(self):
with pytest.raises(ValueError, match=r".* to be of size"):
_ = Lineage(
- np.random.random((10, 3)),
+ np.random.default_rng().random((10, 3)),
names=["foo", "bar"],
colors=[(0, 0, 0), (0.5, 0.5, 0.5), "foobar"],
)
@@ -97,7 +97,7 @@ def test_names_length_mismatch(self):
def test_colors_length_mismatch(self):
with pytest.raises(ValueError, match=r".* to be of size"):
_ = Lineage(
- np.random.random((10, 3)),
+ np.random.default_rng().random((10, 3)),
names=["foo", "bar", "baz"],
colors=[(0, 0, 0), (0.5, 0.5, 0.5)],
)
@@ -105,14 +105,14 @@ def test_colors_length_mismatch(self):
def test_wrong_colors(self):
with pytest.raises(ValueError, match=r".* is not a valid color"):
_ = Lineage(
- np.random.random((10, 3)),
+ np.random.default_rng().random((10, 3)),
names=["foo", "bar", "baz"],
colors=[(0, 0, 0), (0.5, 0.5, 0.5), "foobar"],
)
def test_colors_setter(self):
l = Lineage(
- np.random.random((10, 3)),
+ np.random.default_rng().random((10, 3)),
names=["foo", "bar", "baz"],
colors=[(0, 0, 0), (0.5, 0.5, 0.5), (1, 1, 1)],
)
@@ -124,7 +124,7 @@ def test_colors_setter(self):
def test_color_setter_wrong_colors(self):
l = Lineage(
- np.random.random((10, 3)),
+ np.random.default_rng().random((10, 3)),
names=["foo", "bar", "baz"],
colors=[(0, 0, 0), (0.5, 0.5, 0.5), (1, 1, 1)],
)
@@ -134,7 +134,7 @@ def test_color_setter_wrong_colors(self):
def test_names_setter(self):
l = Lineage(
- np.random.random((10, 3)),
+ np.random.default_rng().random((10, 3)),
names=["foo", "bar", "baz"],
colors=[(0, 0, 0), (0.5, 0.5, 0.5), (1, 1, 1)],
)
@@ -146,7 +146,7 @@ def test_names_setter(self):
def test_names_setter_wrong_type(self):
l = Lineage(
- np.random.random((10, 3)),
+ np.random.default_rng().random((10, 3)),
names=["foo", "bar", "baz"],
colors=[(0, 0, 0), (0.5, 0.5, 0.5), (1, 1, 1)],
)
@@ -157,7 +157,7 @@ def test_names_setter_wrong_type(self):
def test_names_setter_wrong_size(self):
l = Lineage(
- np.random.random((10, 3)),
+ np.random.default_rng().random((10, 3)),
names=["foo", "bar", "baz"],
colors=[(0, 0, 0), (0.5, 0.5, 0.5), (1, 1, 1)],
)
@@ -167,7 +167,7 @@ def test_names_setter_wrong_size(self):
def test_names_setter_non_unique(self):
l = Lineage(
- np.random.random((10, 3)),
+ np.random.default_rng().random((10, 3)),
names=["foo", "bar", "baz"],
colors=[(0, 0, 0), (0.5, 0.5, 0.5), (1, 1, 1)],
)
@@ -178,7 +178,7 @@ def test_names_setter_non_unique(self):
def test_non_unique_names(self):
with pytest.raises(ValueError, match=r"Not all lineage names .*"):
_ = Lineage(
- np.random.random((10, 3)),
+ np.random.default_rng().random((10, 3)),
names=["foo", "bar", "bar"],
colors=[(0, 0, 0), "#ffffff", "#ff00FF"],
)
@@ -186,7 +186,7 @@ def test_non_unique_names(self):
def test_non_unique_names_conversion(self):
with pytest.raises(ValueError, match=r"Not all lineage names .*"):
_ = Lineage(
- np.random.random((10, 3)),
+ np.random.default_rng().random((10, 3)),
names=["foo", "1", 1],
colors=[(0, 0, 0), "#ffffff", "#ff00FF"],
)
@@ -208,7 +208,7 @@ def test_ellipsis(self, lineage: Lineage):
np.testing.assert_array_equal(y, lineage)
def test_subset_same_instance(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -220,7 +220,7 @@ def test_subset_same_instance(self):
assert isinstance(y, Lineage)
def test_singleton_column(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -232,7 +232,7 @@ def test_singleton_column(self):
np.testing.assert_array_equal(x[:, 0], np.array(y)[:, 0])
def test_singleton_column_name(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -244,7 +244,7 @@ def test_singleton_column_name(self):
np.testing.assert_array_equal(x[:, 0], np.array(y)[:, 0])
def test_singleton_column_first_index_assignment(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -257,7 +257,7 @@ def test_singleton_column_first_index_assignment(self):
np.testing.assert_array_equal(y.names, ["baz"])
def test_singleton_row_and_column(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -271,7 +271,7 @@ def test_singleton_row_and_column(self):
assert x[0, 0] == y[0, 0]
def test_mixed_columns(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -283,7 +283,7 @@ def test_mixed_columns(self):
np.testing.assert_array_equal(x[[[0]], [0, 2, 1]], np.array(y))
def test_remove_duplicates(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -295,7 +295,7 @@ def test_remove_duplicates(self):
np.testing.assert_array_equal(x[[[0]], [0, 2, 1]], np.array(y))
def test_column_invalid_name(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -306,7 +306,7 @@ def test_column_invalid_name(self):
_ = l["quux"]
def test_row_subset_with_ints(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -318,7 +318,7 @@ def test_row_subset_with_ints(self):
np.testing.assert_array_equal(x[[1, 2, 3], :], np.array(y))
def test_column_subset_boolean(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -330,7 +330,7 @@ def test_column_subset_boolean(self):
np.testing.assert_array_equal(x[:, -1], y.X.squeeze())
def test_column_subset_boolean_invalid_dim(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -341,7 +341,7 @@ def test_column_subset_boolean_invalid_dim(self):
_ = l[:, [True]]
def test_row_subset_with_mask(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -355,7 +355,7 @@ def test_row_subset_with_mask(self):
np.testing.assert_array_equal(x[mask, :], np.array(y))
def test_column_subset_with_ints(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -367,7 +367,7 @@ def test_column_subset_with_ints(self):
np.testing.assert_array_equal(x[:, [2, 0]], np.array(y))
def test_column_subset_with_mask(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -381,7 +381,7 @@ def test_column_subset_with_mask(self):
np.testing.assert_array_equal(x[:, mask], np.array(y))
def test_column_subset_with_names(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -393,7 +393,7 @@ def test_column_subset_with_names(self):
np.testing.assert_array_equal(x[:, [0, 1]], np.array(y))
def test_comb_row_int_col_int(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -405,7 +405,7 @@ def test_comb_row_int_col_int(self):
np.testing.assert_array_equal(x[[0, 1], :][:, [1, 2]], np.array(y))
def test_comb_row_int_col_mask(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -419,7 +419,7 @@ def test_comb_row_int_col_mask(self):
np.testing.assert_array_equal(x[[0, 1], :][:, mask], np.array(y))
def test_comb_row_int_col_names(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -431,7 +431,7 @@ def test_comb_row_int_col_names(self):
np.testing.assert_array_equal(x[[0, 1], :][:, [2]], np.array(y))
def test_comb_row_mask_col_int(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -445,7 +445,7 @@ def test_comb_row_mask_col_int(self):
np.testing.assert_array_equal(x[mask, :][:, [0]], np.array(y))
def test_comb_row_mask_col_mask(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -460,7 +460,7 @@ def test_comb_row_mask_col_mask(self):
np.testing.assert_array_equal(x[row_mask, :][:, col_mask], np.array(y))
def test_comb_row_mask_col_names(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(
x,
names=["foo", "bar", "baz"],
@@ -474,7 +474,7 @@ def test_comb_row_mask_col_names(self):
np.testing.assert_array_equal(x[mask, :][:, [2, 1]], np.array(y))
def test_reordering(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(x, names=["foo", "bar", "baz"], colors=["#ff0000", "#00ff00", "#0000ff"])
y = l[["baz", "bar", "foo"]]
@@ -483,7 +483,7 @@ def test_reordering(self):
np.testing.assert_array_equal(y.colors, ["#0000ff", "#00ff00", "#ff0000"])
def test_non_trivial_subset(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(x, names=["foo", "bar", "baz"], colors=["#ff0000", "#00ff00", "#0000ff"])
mask = np.ones((x.shape[0]), dtype=bool)
@@ -495,7 +495,7 @@ def test_non_trivial_subset(self):
np.testing.assert_array_equal(y.colors, ["#0000ff", "#00ff00", "#ff0000"])
def test_non_trivial_subset_2(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(x, names=["foo", "bar", "baz"], colors=["#ff0000", "#00ff00", "#0000ff"])
mask = np.ones((x.shape[0]), dtype=bool)
@@ -509,7 +509,7 @@ def test_non_trivial_subset_2(self):
np.testing.assert_array_equal(y.colors, z.colors)
def test_col_order(self):
- x = np.random.random((10, 5))
+ x = np.random.default_rng().random((10, 5))
l = Lineage(
x,
names=["foo", "bar", "baz", "quux", "wex"],
@@ -523,7 +523,7 @@ def test_col_order(self):
np.testing.assert_array_equal(y.colors, ["#bbbbbb", "#aaaaaa"])
def test_automatic_color_assignment(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(x, names=["foo", "bar", "baz"])
gt_colors = [colors.to_hex(c) for c in _create_categorical_colors(3)]
@@ -531,7 +531,7 @@ def test_automatic_color_assignment(self):
np.testing.assert_array_equal(l.colors, gt_colors)
def test_correct_names_to_ixs(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(x, names=["foo", "bar", "baz"])
y = l[["baz", "bar"]]
@@ -539,13 +539,13 @@ def test_correct_names_to_ixs(self):
assert y._names_to_ixs == {"baz": 0, "bar": 1}
def test_correct_order(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(x, names=["foo", "bar", "baz"])
np.testing.assert_array_equal(l[["foo", "baz"]].X, l[["baz", "foo"]].X[:, ::-1])
def test_mask_x_full_names_y(self):
- x = np.random.random((10, 3))
+ x = np.random.default_rng().random((10, 3))
l = Lineage(x, names=["Beta", "Epsilon", "Alpha"])
cmapper = dict(zip(l.names, l.colors))
mask = np.zeros(l.shape[0], dtype=bool)
@@ -591,7 +591,7 @@ def test_mask_and_names(self):
np.testing.assert_array_equal(res.X, lin[mask, :][:, [3, 7, 1, 5]])
def test_common_name(self):
- l1 = Lineage(np.random.random((10, 2)), names=["EN", "Posterior EN"])
+ l1 = Lineage(np.random.default_rng().random((10, 2)), names=["EN", "Posterior EN"])
l2 = l1[["EN", "Posterior EN"]]
np.testing.assert_equal(l1.X, l2.X)
@@ -601,19 +601,19 @@ def test_common_name(self):
class TestLineageMixing:
def test_overlap(self):
- x = Lineage(np.random.random((10, 4)), names=["foo", "bar", "baz", "quux"])
+ x = Lineage(np.random.default_rng().random((10, 4)), names=["foo", "bar", "baz", "quux"])
with pytest.raises(ValueError, match="Found overlapping keys"):
_ = x[["foo, bar", "foo"]]
def test_overlap_mix(self):
- x = Lineage(np.random.random((10, 4)), names=["foo", "bar", "baz", "quux"])
+ x = Lineage(np.random.default_rng().random((10, 4)), names=["foo", "bar", "baz", "quux"])
with pytest.raises(ValueError, match="Found overlapping keys"):
_ = x[["foo, bar", 0]]
def test_no_rest_or_none(self):
- x = Lineage(np.random.random((10, 4)), names=["foo", "bar", "baz", "quux"])
+ x = Lineage(np.random.default_rng().random((10, 4)), names=["foo", "bar", "baz", "quux"])
y = x[["foo, bar"]]
expected = np.sum(x.X[:, [0, 1]], axis=1)[..., np.newaxis]
@@ -624,7 +624,7 @@ def test_no_rest_or_none(self):
np.testing.assert_array_equal(y.colors, [_compute_mean_color(x.colors[:2])])
def test_row_subset(self):
- x = Lineage(np.random.random((10, 4)), names=["foo", "bar", "baz", "quux"])
+ x = Lineage(np.random.default_rng().random((10, 4)), names=["foo", "bar", "baz", "quux"])
y = x[:5, ["foo, bar"]]
expected = np.sum(x.X[:5, [0, 1]], axis=1)[..., np.newaxis]
@@ -794,7 +794,7 @@ def test_softmax(self, mocker, lineage: Lineage):
class TestLineageSameLengthIndexing:
def test_same_names(self):
- x = Lineage(np.random.random((10, 4)), names=["foo", "bar", "baz", "quux"])
+ x = Lineage(np.random.default_rng().random((10, 4)), names=["foo", "bar", "baz", "quux"])
y = x[np.arange(len(x)), ["foo"] * len(x)]
expected = x["foo"]
@@ -805,7 +805,7 @@ def test_same_names(self):
np.testing.assert_array_equal(y.colors, ["#000000"])
def test_same_indices(self):
- x = Lineage(np.random.random((10, 4)), names=["foo", "bar", "baz", "quux"])
+ x = Lineage(np.random.default_rng().random((10, 4)), names=["foo", "bar", "baz", "quux"])
half = len(x) // 2
y = x[[0] * len(x), ["foo"] * half + ["bar"] * half]
@@ -835,7 +835,7 @@ def test_copy(self, lineage: Lineage):
def test_simple_access(self, lineage: Lineage):
y = lineage.T["foo"]
- with pytest.raises(TypeError, match="unhashable type"):
+ with pytest.raises((IndexError, TypeError)):
_ = lineage.T[:, "foo"]
assert y.shape == (1, lineage.shape[0])
diff --git a/tests/test_linear_solver.py b/tests/test_linear_solver.py
index 98643c316..71663586a 100644
--- a/tests/test_linear_solver.py
+++ b/tests/test_linear_solver.py
@@ -1,5 +1,3 @@
-from typing import Tuple
-
import pytest
import numpy as np
@@ -15,7 +13,7 @@
petsc_slepc_skip = pytest.mark.skipif(not _is_petsc_slepc_available(), reason="PETSc or SLEPc is not installed.")
-def _create_a_b_matrices(seed: int, sparse: bool) -> Tuple[np.ndarray, np.ndarray]:
+def _create_a_b_matrices(seed: int, sparse: bool) -> tuple[np.ndarray, np.ndarray]:
rng = np.random.default_rng(seed)
if sparse:
A = sp.random(20, 20, density=0.8, random_state=rng.integers(0, 100), format="csr")
diff --git a/tests/test_logging.py b/tests/test_logging.py
index e98395901..b6b0267c3 100644
--- a/tests/test_logging.py
+++ b/tests/test_logging.py
@@ -11,7 +11,7 @@
from cellrank import settings
-@pytest.fixture()
+@pytest.fixture
def logging_state(): # noqa: PT004
verbosity_orig = settings.verbosity
yield
diff --git a/tests/test_model.py b/tests/test_model.py
index 407011260..ed6549c26 100644
--- a/tests/test_model.py
+++ b/tests/test_model.py
@@ -487,16 +487,16 @@ def test_dist_link_combinations(self, adata_cflare: AnnData, dist: GamDistributi
class TestFailedModel:
- def test_correct_gene_and_lineage(self, gamr_model):
- fm = FailedModel(gamr_model)
+ def test_correct_gene_and_lineage(self, pygam_model: GAM):
+ fm = FailedModel(pygam_model)
- assert fm.adata is gamr_model.adata
- assert fm.model is gamr_model
- assert fm._gene == gamr_model._gene
- assert fm._lineage == gamr_model._lineage
+ assert fm.adata is pygam_model.adata
+ assert fm.model is pygam_model
+ assert fm._gene == pygam_model._gene
+ assert fm._lineage == pygam_model._lineage
- def test_do_nothing_no_bulk_fit(self, gamr_model: GAMR):
- fm = FailedModel(gamr_model)
+ def test_do_nothing_no_bulk_fit(self, pygam_model: GAM):
+ fm = FailedModel(pygam_model)
for fn in [
"prepare",
@@ -509,9 +509,9 @@ def test_do_nothing_no_bulk_fit(self, gamr_model: GAMR):
with pytest.raises(UnknownModelError, match=r"Fatal model"):
getattr(fm, fn)()
- def test_do_nothing_bulk_fit(self, gamr_model: GAMR):
- gamr_model._is_bulk = True
- fm = FailedModel(gamr_model)
+ def test_do_nothing_bulk_fit(self, pygam_model: GAM):
+ pygam_model._is_bulk = True
+ fm = FailedModel(pygam_model)
expected_dict = fm.__dict__.copy()
for fn in [
@@ -526,32 +526,32 @@ def test_do_nothing_bulk_fit(self, gamr_model: GAMR):
assert expected_dict == fm.__dict__
- def test_copy(self, gamr_model):
- fm1 = FailedModel(gamr_model)
+ def test_copy(self, pygam_model):
+ fm1 = FailedModel(pygam_model)
fm2 = fm1.copy()
assert fm1.model is not fm2.model
assert fm1.adata is fm2.adata
- def test_reraise(self, gamr_model: GAMR):
- fm = FailedModel(gamr_model, exc=ValueError("foobar"))
+ def test_reraise(self, pygam_model: GAM):
+ fm = FailedModel(pygam_model, exc=ValueError("foobar"))
with pytest.raises(ValueError, match=r"Fatal model"):
fm.reraise()
assert isinstance(fm._exc, ValueError)
- def test_reraise_str(self, gamr_model: GAMR):
- fm = FailedModel(gamr_model, exc="foobar")
+ def test_reraise_str(self, pygam_model: GAM):
+ fm = FailedModel(pygam_model, exc="foobar")
with pytest.raises(RuntimeError, match=r"Fatal model"):
fm.reraise()
assert isinstance(fm._exc, RuntimeError)
- def test_str_repr(self, gamr_model: GAMR):
- expected = f"')}]>"
- fm = FailedModel(gamr_model)
+ def test_str_repr(self, pygam_model: GAM):
+ expected = f"')}]>"
+ fm = FailedModel(pygam_model)
assert str(fm) == expected
assert repr(fm) == expected
diff --git a/tests/test_plotting.py b/tests/test_plotting.py
index fb29b978c..bf3ecbb95 100644
--- a/tests/test_plotting.py
+++ b/tests/test_plotting.py
@@ -1,6 +1,6 @@
import os
import pathlib
-from typing import Callable, Literal, Tuple, Union
+from typing import Callable, Literal, Union
import pytest
import scvelo as scv
@@ -81,7 +81,7 @@ def _compare_images(expected_path: Union[str, pathlib.Path], actual_path: Union[
assert res is None, res
# TODO: refactor (we can remove the prefix from scvelo
- def _prepare_fname(func: Callable) -> Tuple[str, str]:
+ def _prepare_fname(func: Callable) -> tuple[str, str]:
fpath = f"{func.__name__.replace('test_', '')}"
# scvelo saves figures as pdf
return fpath, str(fpath[7:] + ".png" if fpath.startswith("scvelo_") else fpath)
@@ -506,6 +506,7 @@ def test_cluster_lineage(self, adata: AnnData, fpath: str):
"1",
"latent_time",
random_state=0,
+ clustering_kwargs={"flavor": "igraph", "n_iterations": 2},
dpi=DPI,
save=fpath,
)
@@ -520,6 +521,7 @@ def test_cluster_lineage_bwd(self, adata: AnnData, fpath: str):
"0",
"latent_time",
random_state=0,
+ clustering_kwargs={"flavor": "igraph", "n_iterations": 2},
backward=True,
dpi=DPI,
save=fpath,
@@ -535,6 +537,7 @@ def test_cluster_lineage_raw(self, adata: AnnData, fpath: str):
"1",
"latent_time",
random_state=0,
+ clustering_kwargs={"flavor": "igraph", "n_iterations": 2},
dpi=DPI,
save=fpath,
use_raw=True,
@@ -549,6 +552,7 @@ def test_cluster_lineage_no_norm(self, adata: AnnData, fpath: str):
GENES[:10],
"1",
"latent_time",
+ clustering_kwargs={"flavor": "igraph", "n_iterations": 2},
random_state=0,
norm=False,
dpi=DPI,
@@ -564,6 +568,7 @@ def test_cluster_lineage_data_key(self, adata: AnnData, fpath: str):
GENES[:10],
"1",
"latent_time",
+ clustering_kwargs={"flavor": "igraph", "n_iterations": 2},
random_state=0,
data_key="Ms",
norm=False,
@@ -580,6 +585,7 @@ def test_cluster_lineage_random_state(self, adata: AnnData, fpath: str):
GENES[:10],
"1",
"latent_time",
+ clustering_kwargs={"flavor": "igraph", "n_iterations": 2},
random_state=42,
dpi=DPI,
save=fpath,
@@ -594,6 +600,7 @@ def test_cluster_lineage_leiden(self, adata: AnnData, fpath: str):
GENES[:10],
"1",
"latent_time",
+ clustering_kwargs={"flavor": "igraph", "n_iterations": 2},
random_state=0,
dpi=DPI,
save=fpath,
@@ -608,6 +615,7 @@ def test_cluster_lineage_2_failed_genes(self, adata: AnnData, fpath: str):
GENES[:10],
"1",
"latent_time",
+ clustering_kwargs={"flavor": "igraph", "n_iterations": 2},
random_state=0,
key="foobar",
dpi=DPI,
@@ -625,6 +633,7 @@ def test_cluster_lineage_returns_fitted_models(self, adata_cflare: AnnData):
GENES[:10],
"1",
"latent_time",
+ clustering_kwargs={"flavor": "igraph", "n_iterations": 2},
random_state=0,
return_models=True,
)
@@ -648,6 +657,7 @@ def test_cluster_lineage_random_state_same_pca(self, adata_cflare: AnnData):
GENES[:10],
"1",
"latent_time",
+ clustering_kwargs={"flavor": "igraph", "n_iterations": 2},
random_state=42,
key="foo",
)
@@ -658,6 +668,7 @@ def test_cluster_lineage_random_state_same_pca(self, adata_cflare: AnnData):
GENES[:10],
"1",
"latent_time",
+ clustering_kwargs={"flavor": "igraph", "n_iterations": 2},
random_state=42,
key="bar",
)
@@ -672,6 +683,7 @@ def test_cluster_lineage_writes(self, adata_cflare: AnnData):
GENES[:10],
"0",
time_key="latent_time",
+ clustering_kwargs={"flavor": "igraph", "n_iterations": 2},
n_test_points=200,
)
@@ -687,6 +699,7 @@ def test_cluster_lineage_key(self, adata_cflare: AnnData):
GENES[:10],
"0",
"latent_time",
+ clustering_kwargs={"flavor": "igraph", "n_iterations": 2},
n_test_points=200,
key="foobar",
)
@@ -705,6 +718,7 @@ def test_cluster_lineage_covariates(self, adata: AnnData, fpath: str):
"1",
"latent_time",
covariate_key=["clusters", "latent_time"],
+ clustering_kwargs={"flavor": "igraph", "n_iterations": 2},
random_state=0,
dpi=DPI,
save=fpath,
@@ -720,6 +734,7 @@ def test_cluster_lineage_covariates_cmap(self, adata: AnnData, fpath: str):
"1",
"latent_time",
covariate_key="latent_time",
+ clustering_kwargs={"flavor": "igraph", "n_iterations": 2},
cmap="inferno",
random_state=0,
dpi=DPI,
@@ -736,6 +751,7 @@ def test_cluster_lineage_covariates_ratio(self, adata: AnnData, fpath: str):
"1",
"latent_time",
covariate_key="latent_time",
+ clustering_kwargs={"flavor": "igraph", "n_iterations": 2},
ratio=0.25,
random_state=0,
dpi=DPI,
@@ -752,6 +768,7 @@ def test_cluster_lineage_gene_symbols(self, adata: AnnData, fpath: str):
"1",
"latent_time",
gene_symbols="symbol",
+ clustering_kwargs={"flavor": "igraph", "n_iterations": 2},
random_state=0,
dpi=DPI,
save=fpath,
@@ -3026,6 +3043,7 @@ def test_log_odds_continuous_keys(self, adata: AnnData, fpath: str):
keys=adata.var_names[:3],
figsize=(4, 3),
size=4,
+ seed=42,
)
@compare()
@@ -3136,6 +3154,7 @@ def test_log_odds_size(self, adata: AnnData, fpath: str):
keys="clusters",
size=20,
figsize=(4, 3),
+ seed=42,
)
@compare()
@@ -3151,6 +3170,7 @@ def test_log_odds_cmap(self, adata: AnnData, fpath: str):
size=10,
cmap="inferno",
figsize=(4, 3),
+ seed=43,
)
@compare()
@@ -3166,7 +3186,7 @@ def test_log_odds_alpha(self, adata: AnnData, fpath: str):
alpha=0.5,
figsize=(4, 3),
size=10,
- seed=42,
+ seed=0,
)
@compare()
@@ -3182,7 +3202,7 @@ def test_log_odds_ncols(self, adata: AnnData, fpath: str):
ncols=1,
figsize=(3, 4),
size=10,
- seed=42,
+ seed=2,
)
@compare()
@@ -3198,7 +3218,7 @@ def test_log_odds_fontsize(self, adata: AnnData, fpath: str):
fontsize=25,
figsize=(3, 4),
size=10,
- seed=42,
+ seed=1,
)
@compare()
@@ -3214,7 +3234,7 @@ def test_log_odds_xticks_steps_size(self, adata: AnnData, fpath: str):
xticks_step_size=None,
figsize=(3, 4),
size=10,
- seed=42,
+ seed=3,
)
@compare()
@@ -3230,7 +3250,7 @@ def test_log_odds_legend_loc(self, adata: AnnData, fpath: str):
legend_loc="upper right out",
figsize=(4, 3),
size=10,
- seed=42,
+ seed=5,
)
@compare(tol=250)
@@ -3244,7 +3264,7 @@ def test_log_odds_jitter(self, adata: AnnData, fpath: str):
save=fpath,
figsize=(4, 3),
size=10,
- seed=42,
+ seed=0,
jitter=1,
)
@@ -3262,6 +3282,7 @@ def test_log_odds_kwargs_return_ax(self, adata: AnnData, fpath: str):
edgecolor="red",
figsize=(4, 3),
size=4,
+ seed=11,
)
assert isinstance(ax, plt.Axes)
@@ -3279,6 +3300,7 @@ def test_log_odds_kwargs_return_axes(self, adata: AnnData, fpath: str):
show=False,
figsize=(4, 3),
size=4,
+ seed=12,
)
assert isinstance(axes, np.ndarray)
assert axes.shape == (3,)
@@ -3297,6 +3319,7 @@ def test_log_odds_kwargs(self, adata: AnnData, fpath: str):
edgecolor="red",
figsize=(4, 3),
size=4,
+ seed=13,
)
diff --git a/tests/test_utils.py b/tests/test_utils.py
index ee729a6c0..26202e5a3 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -855,17 +855,17 @@ def numba_function(self, fn: str, axis: int):
numpy_fn = getattr(np, fn)
numba_fn = globals()[f"np_{fn}"]
- x = np.random.RandomState(42).normal(size=(10, 10))
+ x = np.random.default_rng(42).normal(size=(10, 10))
np.testing.assert_allclose(numpy_fn(x, axis=axis), numba_fn(x, axis))
def test_apply_along_axis(self):
- x = np.random.RandomState(42).normal(size=(10, 10))
+ x = np.random.default_rng(42).normal(size=(10, 10))
- def _create_numba_fn(fn):
+ def _create_numba_fn(func):
@nb.njit
def wrapped(axis: int, x: np.ndarray):
- return _np_apply_along_axis(fn, axis, x)
+ return _np_apply_along_axis(func, axis, x)
return wrapped