diff --git a/docs/_ext/edit_on_github.py b/docs/_ext/edit_on_github.py index 85ed75de..746d2c41 100644 --- a/docs/_ext/edit_on_github.py +++ b/docs/_ext/edit_on_github.py @@ -20,7 +20,7 @@ def get_github_repo(app: Sphinx, path: str) -> str: def _html_page_context( - app: Sphinx, _pagename: str, templatename: str, context: dict[str, Any], doctree: Optional[Any] + app: Sphinx, _pagename: str, templatename: str, context: dict[str, Any], doctree: Any | None ) -> None: # doctree is None - otherwise viewcode fails if templatename != "page.html" or doctree is None: diff --git a/ehrapy/_utils_doc.py b/ehrapy/_utils_doc.py index b0cf9587..ae3c8857 100644 --- a/ehrapy/_utils_doc.py +++ b/ehrapy/_utils_doc.py @@ -1,9 +1,10 @@ import inspect +from collections.abc import Callable from textwrap import dedent -from typing import Callable, Optional, Union +from typing import Optional, Union -def getdoc(c_or_f: Union[Callable, type]) -> Optional[str]: # pragma: no cover +def getdoc(c_or_f: Callable | type) -> str | None: # pragma: no cover if getattr(c_or_f, "__doc__", None) is None: return None doc = inspect.getdoc(c_or_f) diff --git a/ehrapy/data/_datasets.py b/ehrapy/data/_datasets.py index 5719373a..7957d17c 100644 --- a/ehrapy/data/_datasets.py +++ b/ehrapy/data/_datasets.py @@ -743,7 +743,7 @@ def synthea_1k_sample( df = anndata_to_df(adata) df.drop( - columns=[col for col in df.columns if any(isinstance(x, (list, dict)) for x in df[col].dropna())], inplace=True + columns=[col for col in df.columns if any(isinstance(x, list | dict) for x in df[col].dropna())], inplace=True ) df.drop(columns=df.columns[df.isna().all()], inplace=True) adata = df_to_anndata(df, index_column="id") diff --git a/ehrapy/plot/_scanpy_pl_api.py b/ehrapy/plot/_scanpy_pl_api.py index a1d032a2..f6af8dd1 100644 --- a/ehrapy/plot/_scanpy_pl_api.py +++ b/ehrapy/plot/_scanpy_pl_api.py @@ -1,10 +1,10 @@ from __future__ import annotations -from collections.abc import Collection, Iterable, Mapping, Sequence +from collections.abc import Callable, Collection, Iterable, Mapping, Sequence from enum import Enum from functools import partial from types import MappingProxyType -from typing import TYPE_CHECKING, Any, Callable, Literal, Union +from typing import TYPE_CHECKING, Any, Literal, Union import scanpy as sc from scanpy.plotting import DotPlot, MatrixPlot, StackedViolin diff --git a/ehrapy/preprocessing/_encoding.py b/ehrapy/preprocessing/_encoding.py index 1f761e71..ad531eaa 100644 --- a/ehrapy/preprocessing/_encoding.py +++ b/ehrapy/preprocessing/_encoding.py @@ -73,7 +73,7 @@ def encode( if isinstance(encodings, str) and not autodetect: raise ValueError("Passing a string for parameter encodings is only possible when using autodetect=True!") - elif autodetect and not isinstance(encodings, (str, type(None))): + elif autodetect and not isinstance(encodings, str | type(None)): raise ValueError( f"Setting encode mode with autodetect=True only works by passing a string (encode mode name) or None not {type(encodings)}!" ) diff --git a/ehrapy/preprocessing/_imputation.py b/ehrapy/preprocessing/_imputation.py index 60facfeb..03796c2b 100644 --- a/ehrapy/preprocessing/_imputation.py +++ b/ehrapy/preprocessing/_imputation.py @@ -63,7 +63,7 @@ def explicit_impute( _warn_imputation_threshold(adata, var_names=replacement.keys(), threshold=warning_threshold) # type: ignore # 1: Replace all missing values with the specified value - if isinstance(replacement, (int, str)): + if isinstance(replacement, int | str): _replace_explicit(adata.X, replacement, impute_empty_strings) # 2: Replace all missing values in a subset of columns with a specified value per column or a default value, when the column is not explicitly named diff --git a/ehrapy/preprocessing/_normalization.py b/ehrapy/preprocessing/_normalization.py index 4541cef3..de6cf646 100644 --- a/ehrapy/preprocessing/_normalization.py +++ b/ehrapy/preprocessing/_normalization.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import TYPE_CHECKING, Callable +from typing import TYPE_CHECKING import numpy as np import sklearn.preprocessing as sklearn_pp @@ -20,7 +20,7 @@ ) if TYPE_CHECKING: - from collections.abc import Sequence + from collections.abc import Callable, Sequence import pandas as pd from anndata import AnnData diff --git a/ehrapy/preprocessing/_scanpy_pp_api.py b/ehrapy/preprocessing/_scanpy_pp_api.py index 5317530e..34ad6aa4 100644 --- a/ehrapy/preprocessing/_scanpy_pp_api.py +++ b/ehrapy/preprocessing/_scanpy_pp_api.py @@ -1,7 +1,8 @@ from __future__ import annotations +from collections.abc import Callable from types import MappingProxyType -from typing import TYPE_CHECKING, Any, Callable, Literal, Union +from typing import TYPE_CHECKING, Any, Literal, Union import numpy as np import scanpy as sc diff --git a/ehrapy/tools/_scanpy_tl_api.py b/ehrapy/tools/_scanpy_tl_api.py index 4e1af6b0..fa3875b7 100644 --- a/ehrapy/tools/_scanpy_tl_api.py +++ b/ehrapy/tools/_scanpy_tl_api.py @@ -14,16 +14,16 @@ def tsne( adata: AnnData, - n_pcs: Optional[int] = None, - use_rep: Optional[str] = None, - perplexity: Union[float, int] = 30, - early_exaggeration: Union[float, int] = 12, - learning_rate: Union[float, int] = 1000, + n_pcs: int | None = None, + use_rep: str | None = None, + perplexity: float | int = 30, + early_exaggeration: float | int = 12, + learning_rate: float | int = 1000, random_state: AnyRandom = 0, - n_jobs: Optional[int] = None, + n_jobs: int | None = None, copy: bool = False, metric: str = "euclidean", -) -> Optional[AnnData]: # pragma: no cover +) -> AnnData | None: # pragma: no cover """Calculates t-SNE [Maaten08]_ [Amir13]_ [Pedregosa11]_. t-distributed stochastic neighborhood embedding (tSNE) [Maaten08]_ has been @@ -83,18 +83,18 @@ def umap( min_dist: float = 0.5, spread: float = 1.0, n_components: int = 2, - maxiter: Optional[int] = None, + maxiter: int | None = None, alpha: float = 1.0, gamma: float = 1.0, negative_sample_rate: int = 5, - init_pos: Union[_method_options._InitPos, np.ndarray, None] = "spectral", + init_pos: _method_options._InitPos | np.ndarray | None = "spectral", random_state: AnyRandom = 0, - a: Optional[float] = None, - b: Optional[float] = None, + a: float | None = None, + b: float | None = None, copy: bool = False, method: Literal["umap", "rapids"] = "umap", - neighbors_key: Optional[str] = None, -) -> Optional[AnnData]: # pragma: no cover + neighbors_key: str | None = None, +) -> AnnData | None: # pragma: no cover """Embed the neighborhood graph using UMAP [McInnes18]_. UMAP (Uniform Manifold Approximation and Projection) is a manifold learning @@ -186,17 +186,17 @@ def umap( def draw_graph( adata: AnnData, layout: _method_options._Layout = "fa", - init_pos: Union[str, bool, None] = None, - root: Optional[int] = None, + init_pos: str | bool | None = None, + root: int | None = None, random_state: AnyRandom = 0, - n_jobs: Optional[int] = None, - adjacency: Optional[spmatrix] = None, - key_added_ext: Optional[str] = None, - neighbors_key: Optional[str] = None, - obsp: Optional[str] = None, + n_jobs: int | None = None, + adjacency: spmatrix | None = None, + key_added_ext: str | None = None, + neighbors_key: str | None = None, + obsp: str | None = None, copy: bool = False, **kwds, -) -> Optional[AnnData]: # pragma: no cover +) -> AnnData | None: # pragma: no cover """Force-directed graph drawing [Islam11]_ [Jacomy14]_ [Chippada18]_. .. _fa2: https://github.com/bhargavchippada/forceatlas2 @@ -264,10 +264,10 @@ def draw_graph( def diffmap( adata: AnnData, n_comps: int = 15, - neighbors_key: Optional[str] = None, + neighbors_key: str | None = None, random_state: AnyRandom = 0, copy: bool = False, -) -> Optional[AnnData]: # pragma: no cover +) -> AnnData | None: # pragma: no cover """Diffusion Maps [Coifman05]_ [Haghverdi15]_ [Wolf18]_. Diffusion maps [Coifman05]_ has been proposed for visualizing single-cell @@ -309,9 +309,9 @@ def diffmap( def embedding_density( adata: AnnData, basis: str = "umap", # was positional before 1.4.5 - groupby: Optional[str] = None, - key_added: Optional[str] = None, - components: Union[str, Sequence[str]] = None, + groupby: str | None = None, + key_added: str | None = None, + components: str | Sequence[str] = None, ) -> None: # pragma: no cover """Calculate the density of observation in an embedding (per condition). @@ -353,19 +353,19 @@ def embedding_density( def leiden( adata: AnnData, resolution: float = 1, - restrict_to: Optional[tuple[str, Sequence[str]]] = None, + restrict_to: tuple[str, Sequence[str]] | None = None, random_state: AnyRandom = 0, key_added: str = "leiden", - adjacency: Optional[spmatrix] = None, + adjacency: spmatrix | None = None, directed: bool = True, use_weights: bool = True, n_iterations: int = -1, - partition_type: Optional[type[MutableVertexPartition]] = None, - neighbors_key: Optional[str] = None, - obsp: Optional[str] = None, + partition_type: type[MutableVertexPartition] | None = None, + neighbors_key: str | None = None, + obsp: str | None = None, copy: bool = False, **partition_kwargs, -) -> Optional[AnnData]: # pragma: no cover +) -> AnnData | None: # pragma: no cover """Cluster observations into subgroups [Traag18]_. Cluster observations using the Leiden algorithm [Traag18]_, @@ -429,15 +429,15 @@ def leiden( def dendrogram( adata: AnnData, groupby: str, - n_pcs: Optional[int] = None, - use_rep: Optional[str] = None, - var_names: Optional[Sequence[str]] = None, + n_pcs: int | None = None, + use_rep: str | None = None, + var_names: Sequence[str] | None = None, cor_method: str = "pearson", linkage_method: str = "complete", optimal_ordering: bool = False, - key_added: Optional[str] = None, + key_added: str | None = None, inplace: bool = True, -) -> Optional[dict[str, Any]]: # pragma: no cover +) -> dict[str, Any] | None: # pragma: no cover """Computes a hierarchical clustering for the given `groupby` categories. By default, the PCA representation is used unless `.X` has less than 50 variables. @@ -505,9 +505,9 @@ def dpt( n_branchings: int = 0, min_group_size: float = 0.01, allow_kendall_tau_shift: bool = True, - neighbors_key: Optional[str] = None, + neighbors_key: str | None = None, copy: bool = False, -) -> Optional[AnnData]: # pragma: no cover +) -> AnnData | None: # pragma: no cover """Infer progression of observations through geodesic distance along the graph [Haghverdi16]_ [Wolf19]_. Reconstruct the progression of a biological process from snapshot @@ -562,12 +562,12 @@ def dpt( def paga( adata: AnnData, - groups: Optional[str] = None, + groups: str | None = None, use_rna_velocity: bool = False, model: Literal["v1.2", "v1.0"] = "v1.2", - neighbors_key: Optional[str] = None, + neighbors_key: str | None = None, copy: bool = False, -) -> Optional[AnnData]: # pragma: no cover +) -> AnnData | None: # pragma: no cover """Mapping out the coarse-grained connectivity structures of complex manifolds [Wolf19]_. By quantifying the connectivity of partitions (groups, clusters), @@ -626,13 +626,13 @@ def paga( def ingest( adata: AnnData, adata_ref: AnnData, - obs: Optional[Union[str, Iterable[str]]] = None, - embedding_method: Union[str, Iterable[str]] = ("umap", "pca"), + obs: str | Iterable[str] | None = None, + embedding_method: str | Iterable[str] = ("umap", "pca"), labeling_method: str = "knn", - neighbors_key: Optional[str] = None, + neighbors_key: str | None = None, inplace: bool = True, **kwargs, -) -> Optional[AnnData]: # pragma: no cover +) -> AnnData | None: # pragma: no cover """Map labels and embeddings from reference data to new data. Integrates embeddings and annotations of an `adata` with a reference dataset diff --git a/ehrapy/tools/causal/_dowhy.py b/ehrapy/tools/causal/_dowhy.py index 55916179..f972804b 100644 --- a/ehrapy/tools/causal/_dowhy.py +++ b/ehrapy/tools/causal/_dowhy.py @@ -244,7 +244,7 @@ def causal_inference( pval = "Not applicable" # Format effect, can be list when refuter is "add_unobserved_common_cause" - if isinstance(refute.new_effect, (list, tuple)): + if isinstance(refute.new_effect, list | tuple): new_effect = ", ".join([str(np.round(x, 2)) for x in refute.new_effect]) else: new_effect = f"{refute.new_effect:.3f}" diff --git a/ehrapy/tools/cohort_tracking/_cohort_tracker.py b/ehrapy/tools/cohort_tracking/_cohort_tracker.py index 4d92fb84..fc331550 100644 --- a/ehrapy/tools/cohort_tracking/_cohort_tracker.py +++ b/ehrapy/tools/cohort_tracking/_cohort_tracker.py @@ -390,7 +390,7 @@ def create_legend_with_subtitles(patches_list, subtitles_list, tot_legend_kwargs # there can be empty lists which distort the logic of matching patches to subtitles patches_list = [patch for patch in patches_list if patch] - for patches, subtitle in zip(patches_list, subtitles_list): + for patches, subtitle in zip(patches_list, subtitles_list, strict=False): handles.append(Line2D([], [], linestyle="none", marker="", alpha=0)) # Placeholder for title labels.append(subtitle) @@ -494,7 +494,7 @@ def plot_flowchart( tot_bbox_kwargs = {"boxstyle": "round,pad=0.3", "fc": "lightblue", "alpha": 0.5} if bbox_kwargs is not None: tot_bbox_kwargs.update(bbox_kwargs) - for _, (y, label) in enumerate(zip(y_positions, node_labels)): + for _, (y, label) in enumerate(zip(y_positions, node_labels, strict=False)): axes.annotate( label, xy=(0, y), diff --git a/ehrapy/tools/feature_ranking/_rank_features_groups.py b/ehrapy/tools/feature_ranking/_rank_features_groups.py index d78bfd1c..6fb3932c 100644 --- a/ehrapy/tools/feature_ranking/_rank_features_groups.py +++ b/ehrapy/tools/feature_ranking/_rank_features_groups.py @@ -107,7 +107,7 @@ def _save_rank_features_result( fields = (names, scores, pvals, pvals_adj, logfoldchanges, pts) field_names = ("names", "scores", "pvals", "pvals_adj", "logfoldchanges", "pts") - for values, key in zip(fields, field_names): + for values, key in zip(fields, field_names, strict=False): if values is None or not len(values): continue @@ -139,7 +139,7 @@ def _get_groups_order(groups_subset, group_names, reference): """ if groups_subset == "all": groups_order = group_names - elif isinstance(groups_subset, (str, int)): + elif isinstance(groups_subset, str | int): raise ValueError("Specify a sequence of groups") else: groups_order = list(groups_subset)