Skip to content

Commit

Permalink
Merge branch 'main' into fix-543
Browse files Browse the repository at this point in the history
  • Loading branch information
grst authored Aug 30, 2024
2 parents 700e29c + 73ce9c4 commit ec18d09
Show file tree
Hide file tree
Showing 48 changed files with 278 additions and 282 deletions.
4 changes: 2 additions & 2 deletions .conda/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ build:

requirements:
host:
- python >=3.9
- python >=3.10
- hatchling
- hatch-vcs

run:
- python >=3.9
- python >=3.10
- anndata >=0.9
- awkward >=2.1.0
- mudata >=0.2.3
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/conda.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
matrix:
include:
- os: ubuntu-latest
python: "3.9"
python: "3.12"

env:
OS: ${{ matrix.os }}
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
matrix:
include:
- os: ubuntu-latest
python: "3.9"
python: "3.10"
- os: ubuntu-latest
python: "3.12"
- os: ubuntu-latest
Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ repos:
- id: prettier
exclude: '^\.conda'
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.6.1
rev: v0.6.2
hooks:
- id: ruff
types_or: [python, pyi, jupyter]
Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ and this project adheres to [Semantic Versioning][].

- Fix that pl.clonotype_network couldn't use non-standard obsm key ([#545](https://github.com/scverse/scirpy/pull/545)).

### Other changes

- Drop support for Python 3.9 (in accordance with [SPEC0](https://scientific-python.org/specs/spec-0000/))

## v0.17.2

### Fixes
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ Please refer to the [documentation][link-docs]. In particular, the

## Installation

You need to have Python 3.9 or newer installed on your system. If you don't have
You need to have Python 3.10 or newer installed on your system. If you don't have
Python installed, we recommend installing [Mambaforge](https://github.com/conda-forge/miniforge#mambaforge).

There are several alternative options to install scirpy:
Expand Down
2 changes: 1 addition & 1 deletion docs/tutorials/tutorial_3k_tcr.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -3048,7 +3048,7 @@
" method=\"wilcoxon\",\n",
" )\n",
" fig, axs = plt.subplots(1, 2, figsize=(8, 4))\n",
" for ct, ax in zip(clonotypes_top_modularity, axs):\n",
" for ct, ax in zip(clonotypes_top_modularity, axs, strict=False):\n",
" sc.pl.rank_genes_groups_violin(tmp_ad, groups=[ct], n_genes=15, ax=ax, show=False, strip=False)"
]
},
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ name = 'scirpy'
dynamic = ["version"]
description = "Python library for single-cell adaptive immune receptor repertoire (AIRR) analysis"
readme = "README.md"
requires-python = '>= 3.9'
requires-python = '>= 3.10'
license = {file = "LICENSE"}
authors = [
{name = "Gregor Sturm"},
Expand All @@ -20,7 +20,7 @@ urls.Documentation = "https://scirpy.readthedocs.io/"
urls.Source = "https://github.com/scverse/scirpy"
urls.Home-page = "https://github.com/scverse/scirpy"
dependencies = [
'anndata>=0.9',
'anndata>=0.9,<0.10.9', # TODO remove constraint
'awkward>=2.1.0',
'mudata>=0.2.3',
'scanpy>=1.9.3',
Expand Down
2 changes: 1 addition & 1 deletion src/scirpy/datasets/_processing_scripts/wu2020.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ def _load_adata(path):
adatas = p.map(_load_adata, mtx_paths)
p.close()

adatas, adatas_airr = zip(*adatas)
adatas, adatas_airr = zip(*adatas, strict=False)

adata = anndata.concat(adatas)

Expand Down
12 changes: 6 additions & 6 deletions src/scirpy/get/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,13 @@
@DataHandler.inject_param_docs()
def airr(
adata: DataHandler.TYPE,
airr_variable: Union[str, Sequence[str]],
chain: Union[ChainType, Sequence[ChainType]] = ("VJ_1", "VDJ_1", "VJ_2", "VDJ_2"),
airr_variable: str | Sequence[str],
chain: ChainType | Sequence[ChainType] = ("VJ_1", "VDJ_1", "VJ_2", "VDJ_2"),
*,
airr_mod: str = "airr",
airr_key: str = "airr",
chain_idx_key: str = "chain_indices",
) -> Union[pd.DataFrame, pd.Series]:
) -> pd.DataFrame | pd.Series:
"""\
Retrieve AIRR variables for each cell, given a specific chain.
Expand Down Expand Up @@ -110,7 +110,7 @@ def _airr_col(


@contextmanager
def obs_context(data: Union[AnnData, MuData], temp_cols: Union[pd.DataFrame, Mapping[str, Any]]):
def obs_context(data: AnnData | MuData, temp_cols: pd.DataFrame | Mapping[str, Any]):
"""
Contextmanager that temporarily adds columns to obs.
Expand Down Expand Up @@ -151,8 +151,8 @@ def obs_context(data: Union[AnnData, MuData], temp_cols: Union[pd.DataFrame, Map
@DataHandler.inject_param_docs()
def airr_context(
data: DataHandler.TYPE,
airr_variable: Union[str, Sequence[str]],
chain: Union[ChainType, Sequence[ChainType]] = ("VJ_1", "VDJ_1", "VJ_2", "VDJ_2"),
airr_variable: str | Sequence[str],
chain: ChainType | Sequence[ChainType] = ("VJ_1", "VDJ_1", "VJ_2", "VDJ_2"),
*,
airr_mod: str = "airr",
airr_key: str = "airr",
Expand Down
2 changes: 1 addition & 1 deletion src/scirpy/io/_convert_anndata.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ def to_airr_cells(adata: DataHandler.TYPE, *, airr_mod: str = "airr", airr_key:
tmp_airr = ak.to_list(params.airr[i : i + CHUNKSIZE])
tmp_obs = params.adata.obs.iloc[i : i + CHUNKSIZE].to_dict(orient="index")

for (cell_id, row), chains in zip(tmp_obs.items(), tmp_airr):
for (cell_id, row), chains in zip(tmp_obs.items(), tmp_airr, strict=False):
tmp_cell = AirrCell(cast(str, cell_id), logger=logger)
# add cell-level metadata
tmp_cell.update(row)
Expand Down
22 changes: 11 additions & 11 deletions src/scirpy/io/_io.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from collections.abc import Collection, Iterable, Sequence
from glob import iglob
from pathlib import Path
from typing import Any, Union
from typing import Any

import numpy as np
import pandas as pd
Expand Down Expand Up @@ -46,7 +46,7 @@ def _cdr3_from_junction(junction_aa, junction_nt):


def _read_10x_vdj_json(
path: Union[str, Path],
path: str | Path,
filtered: bool = True,
) -> Iterable[AirrCell]:
"""Read IR data from a 10x genomics `all_contig_annotations.json` file"""
Expand Down Expand Up @@ -148,7 +148,7 @@ def _read_10x_vdj_json(


def _read_10x_vdj_csv(
path: Union[str, Path],
path: str | Path,
filtered: bool = True,
) -> Iterable[AirrCell]:
"""Read IR data from a 10x genomics `_contig_annotations.csv` file"""
Expand Down Expand Up @@ -199,7 +199,7 @@ def _read_10x_vdj_csv(


@_doc_params(doc_working_model=doc_working_model)
def read_10x_vdj(path: Union[str, Path], filtered: bool = True, include_fields: Any = None, **kwargs) -> AnnData:
def read_10x_vdj(path: str | Path, filtered: bool = True, include_fields: Any = None, **kwargs) -> AnnData:
"""\
Read :term:`AIRR` data from 10x Genomics cell-ranger output.
Expand Down Expand Up @@ -241,7 +241,7 @@ def read_10x_vdj(path: Union[str, Path], filtered: bool = True, include_fields:


@_doc_params(doc_working_model=doc_working_model)
def read_tracer(path: Union[str, Path], **kwargs) -> AnnData:
def read_tracer(path: str | Path, **kwargs) -> AnnData:
"""\
Read data from `TraCeR <https://github.com/Teichlab/tracer>`_ (:cite:`Stubbington2016-kh`).
Expand Down Expand Up @@ -351,7 +351,7 @@ def _process_chains(chains, chain_type):
cell_attributes=f"""`({",".join([f'"{x}"' for x in DEFAULT_AIRR_CELL_ATTRIBUTES])})`""",
)
def read_airr(
path: Union[str, Sequence[str], Path, Sequence[Path], pd.DataFrame, Sequence[pd.DataFrame]],
path: str | Sequence[str] | Path | Sequence[Path] | pd.DataFrame | Sequence[pd.DataFrame],
use_umi_count_col: None = None, # deprecated, kept for backwards-compatibility
infer_locus: bool = True,
cell_attributes: Collection[str] = DEFAULT_AIRR_CELL_ATTRIBUTES,
Expand Down Expand Up @@ -405,8 +405,8 @@ def read_airr(
airr_cells = {}
logger = _IOLogger()

if isinstance(path, (str, Path, pd.DataFrame)):
path: list[Union[str, Path, pd.DataFrame]] = [path] # type: ignore
if isinstance(path, str | Path | pd.DataFrame):
path: list[str | Path | pd.DataFrame] = [path] # type: ignore

for tmp_path_or_df in path:
if isinstance(tmp_path_or_df, pd.DataFrame):
Expand Down Expand Up @@ -475,7 +475,7 @@ def _infer_locus_from_gene_names(chain_dict, *, keys=("v_call", "d_call", "j_cal


@_doc_params(doc_working_model=doc_working_model)
def read_bracer(path: Union[str, Path], **kwargs) -> AnnData:
def read_bracer(path: str | Path, **kwargs) -> AnnData:
"""\
Read data from `BraCeR <https://github.com/Teichlab/bracer>`_ (:cite:`Lindeman2018`).
Expand Down Expand Up @@ -546,7 +546,7 @@ def read_bracer(path: Union[str, Path], **kwargs) -> AnnData:
return from_airr_cells(bcr_cells.values(), **kwargs)


def write_airr(adata: DataHandler.TYPE, filename: Union[str, Path], **kwargs) -> None:
def write_airr(adata: DataHandler.TYPE, filename: str | Path, **kwargs) -> None:
"""Export :term:`IR` data to :term:`AIRR` Rearrangement `tsv` format.
Parameters
Expand Down Expand Up @@ -636,7 +636,7 @@ def from_dandelion(dandelion, transfer: bool = False, to_mudata: bool = False, *


@_doc_params(doc_working_model=doc_working_model)
def read_bd_rhapsody(path: Union[str, Path], **kwargs) -> AnnData:
def read_bd_rhapsody(path: str | Path, **kwargs) -> AnnData:
"""\
Read :term:`IR` data from the BD Rhapsody Analysis Pipeline.
Expand Down
22 changes: 11 additions & 11 deletions src/scirpy/ir_dist/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,10 +34,10 @@ def IrNeighbors(*args, **kwargs):
)


MetricType = Union[
Literal["alignment", "fastalignment", "identity", "levenshtein", "hamming", "normalized_hamming", "tcrdist"],
metrics.DistanceCalculator,
]
MetricType = (
Literal["alignment", "fastalignment", "identity", "levenshtein", "hamming", "normalized_hamming", "tcrdist"]
| metrics.DistanceCalculator
)

_doc_metrics = """\
metric
Expand Down Expand Up @@ -77,7 +77,7 @@ def _get_metric_key(metric: MetricType) -> str:
return "custom" if isinstance(metric, metrics.DistanceCalculator) else metric # type: ignore


def _get_distance_calculator(metric: MetricType, cutoff: Union[int, None], *, n_jobs=-1, **kwargs):
def _get_distance_calculator(metric: MetricType, cutoff: int | None, *, n_jobs=-1, **kwargs):
"""Returns an instance of :class:`~scirpy.ir_dist.metrics.DistanceCalculator`
given a metric.
Expand Down Expand Up @@ -116,12 +116,12 @@ def _get_distance_calculator(metric: MetricType, cutoff: Union[int, None], *, n_
@DataHandler.inject_param_docs(metric=_doc_metrics, cutoff=_doc_cutoff, dist_mat=metrics._doc_dist_mat)
def _ir_dist(
adata: DataHandler.TYPE,
reference: Optional[DataHandler.TYPE] = None,
reference: DataHandler.TYPE | None = None,
*,
metric: MetricType = "identity",
cutoff: Union[int, None] = None,
cutoff: int | None = None,
sequence: Literal["aa", "nt"] = "nt",
key_added: Union[str, None] = None,
key_added: str | None = None,
inplace: bool = True,
n_jobs: int = -1,
airr_mod: str = "airr",
Expand All @@ -131,7 +131,7 @@ def _ir_dist(
airr_key_ref: str = "airr",
chain_idx_key_ref: str = "chain_indices",
**kwargs,
) -> Union[dict, None]:
) -> dict | None:
"""\
Computes a sequence-distance metric between all unique :term:`VJ <Chain locus>`
:term:`CDR3` sequences and between all unique :term:`VDJ <Chain locus>`
Expand Down Expand Up @@ -257,10 +257,10 @@ def _get_unique_seqs(tmp_adata, chain_type):
@_doc_params(metric=_doc_metrics, cutoff=_doc_cutoff, dist_mat=metrics._doc_dist_mat)
def sequence_dist(
seqs: Sequence[str],
seqs2: Optional[Sequence[str]] = None,
seqs2: Sequence[str] | None = None,
*,
metric: MetricType = "identity",
cutoff: Union[None, int] = None,
cutoff: None | int = None,
n_jobs: int = -1,
**kwargs,
) -> csr_matrix:
Expand Down
6 changes: 3 additions & 3 deletions src/scirpy/ir_dist/_clonotype_neighbors.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import itertools
from collections.abc import Mapping, Sequence
from typing import Literal, Optional, Union
from typing import Literal

import numpy as np
import pandas as pd
Expand All @@ -19,12 +19,12 @@ class ClonotypeNeighbors:
def __init__(
self,
params: DataHandler,
params2: Optional[DataHandler] = None,
params2: DataHandler | None = None,
*,
receptor_arms: Literal["VJ", "VDJ", "all", "any"],
dual_ir: Literal["primary_only", "all", "any"],
same_v_gene: bool = False,
match_columns: Union[None, Sequence[str]] = None,
match_columns: None | Sequence[str] = None,
distance_key: str,
sequence_key: str,
n_jobs: int = -1,
Expand Down
14 changes: 7 additions & 7 deletions src/scirpy/ir_dist/_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
from collections.abc import Hashable, Mapping, Sequence
from functools import reduce
from operator import mul
from typing import Literal, Optional, Union
from typing import Literal

import numpy as np
import pandas as pd
Expand Down Expand Up @@ -46,7 +46,7 @@ def merge_coo_matrices(mats: Sequence[coo_matrix], shape=None) -> coo_matrix:
if not len(mats) or shape is None or reduce(mul, shape) == 0:
return coo_matrix((0, 0) if shape is None else shape)

data, row, col = zip(*((x.data, x.row, x.col) for x in mats))
data, row, col = zip(*((x.data, x.row, x.col) for x in mats), strict=False)

return sp.coo_matrix((np.hstack(data), (np.hstack(row), np.hstack(col))), shape=shape)

Expand Down Expand Up @@ -174,7 +174,7 @@ def __getitem__(self, i):


class DoubleLookupNeighborFinder:
def __init__(self, feature_table: pd.DataFrame, feature_table2: Optional[pd.DataFrame] = None):
def __init__(self, feature_table: pd.DataFrame, feature_table2: pd.DataFrame | None = None):
"""
A datastructure to efficiently retrieve distances based on different features.
Expand Down Expand Up @@ -235,8 +235,8 @@ def lookup(
self,
object_id: int,
forward_lookup_table: str,
reverse_lookup_table: Union[str, None] = None,
) -> Union[coo_matrix, np.ndarray]:
reverse_lookup_table: str | None = None,
) -> coo_matrix | np.ndarray:
"""Get ids of neighboring objects from a lookup table.
Performs the following lookup:
Expand Down Expand Up @@ -285,7 +285,7 @@ def lookup(
# ... and get column indices directly from sparse row
# sum concatenates coo matrices
return merge_coo_matrices(
(reverse[i] * multiplier for i, multiplier in zip(row.indices, row.data)), # type: ignore
(reverse[i] * multiplier for i, multiplier in zip(row.indices, row.data, strict=False)), # type: ignore
shape=(1, reverse.size),
)

Expand All @@ -294,7 +294,7 @@ def add_distance_matrix(
name: str,
distance_matrix: sp.csr_matrix,
labels: Sequence,
labels2: Optional[Sequence] = None,
labels2: Sequence | None = None,
):
"""Add a distance matrix.
Expand Down
Loading

0 comments on commit ec18d09

Please sign in to comment.