Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

run doctests #2605

Merged
merged 65 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from 61 commits
Commits
Show all changes
65 commits
Select commit Hold shift + click to select a range
992f7c3
run doctests
flying-sheep Aug 8, 2023
840902a
fix whitespace problems
flying-sheep Aug 8, 2023
5b565fe
fix is_constant doctest
flying-sheep Aug 8, 2023
4ea5f51
fix get syntax
flying-sheep Aug 8, 2023
05070fa
add doctest deps
flying-sheep Aug 8, 2023
0ef66db
fix and skip
flying-sheep Aug 8, 2023
5325a1b
switch to doctest marks
flying-sheep Aug 10, 2023
a9f4fd6
baseplot doctests
flying-sheep Aug 10, 2023
632ebdc
dotplot
flying-sheep Aug 10, 2023
08c13d0
stacked violin
flying-sheep Aug 10, 2023
1ebd247
scatterplot
flying-sheep Aug 10, 2023
97a246d
fix_kwds
flying-sheep Aug 10, 2023
ef405c9
normalize_counts_per_cell
flying-sheep Aug 10, 2023
a67035c
simple preprocessing
flying-sheep Aug 10, 2023
eed1f58
queries
flying-sheep Aug 10, 2023
6179489
Merge branch 'master' into doctests
flying-sheep Aug 10, 2023
e49a046
whoops
flying-sheep Aug 10, 2023
ad01259
comment where chdir iis available
flying-sheep Aug 10, 2023
ac18703
hashsolo
flying-sheep Aug 10, 2023
985bbb4
defer metplotlib import
flying-sheep Aug 10, 2023
b6effa9
huh
flying-sheep Aug 10, 2023
ec56f61
dendrogram
flying-sheep Aug 10, 2023
2d266ed
docstrings
flying-sheep Aug 10, 2023
b218b69
ingest
flying-sheep Aug 10, 2023
9b5448f
marker gene overlap
flying-sheep Aug 10, 2023
f11c4c1
some mitigation
flying-sheep Aug 10, 2023
6115d7e
reset autoshow
flying-sheep Aug 10, 2023
687bbe4
fix settings
flying-sheep Aug 10, 2023
b4132a6
.
flying-sheep Aug 10, 2023
190b90e
remove debug code
flying-sheep Aug 10, 2023
5c57697
hm
flying-sheep Aug 11, 2023
040b060
try older version
flying-sheep Aug 11, 2023
1ac88e8
Revert "try older version"
flying-sheep Aug 11, 2023
3c253eb
Merge branch 'master' into doctests
flying-sheep Sep 7, 2023
70fbf65
Fix weird merge artifact
flying-sheep Sep 7, 2023
f2e296c
some fixes
flying-sheep Sep 7, 2023
f06d094
Discard changes to scanpy/__init__.py
flying-sheep Sep 8, 2023
9bc7821
Discard changes to scanpy/_utils/__init__.py
flying-sheep Sep 8, 2023
e03e899
Discard changes to scanpy/datasets/_ebi_expression_atlas.py
flying-sheep Sep 8, 2023
f06a3cd
Discard changes to scanpy/datasets/_utils.py
flying-sheep Sep 8, 2023
8a8af07
Discard changes to scanpy/experimental/pp/_highly_variable_genes.py
flying-sheep Sep 8, 2023
9a3169c
Discard changes to scanpy/external/pp/_mnn_correct.py
flying-sheep Sep 8, 2023
03b42ee
Discard changes to scanpy/plotting/_matrixplot.py
flying-sheep Sep 8, 2023
b8beafc
Discard changes to scanpy/plotting/_tools/__init__.py
flying-sheep Sep 8, 2023
f464f4e
Discard changes to scanpy/plotting/_tools/paga.py
flying-sheep Sep 8, 2023
6987c5a
Discard changes to scanpy/preprocessing/_highly_variable_genes.py
flying-sheep Sep 8, 2023
f596ff5
Discard changes to scanpy/readwrite.py
flying-sheep Sep 8, 2023
1c86d6d
import changes
flying-sheep Sep 8, 2023
6aa2b1f
remainder
flying-sheep Sep 8, 2023
5830635
Discard changes to scanpy/tools/_sim.py
flying-sheep Sep 8, 2023
96a43fe
Discard changes to scanpy/tools/_tsne.py
flying-sheep Sep 8, 2023
0deb5d7
Doc fixes
flying-sheep Sep 8, 2023
b1c2f58
Merge branch 'master' into doctests
flying-sheep Oct 12, 2023
38c5d0d
Fix scanorama test
flying-sheep Oct 13, 2023
b5ce71a
Fix neighbors tests
flying-sheep Oct 13, 2023
ecb2d0d
release notes
flying-sheep Oct 13, 2023
ef54d9e
fix doc building
flying-sheep Oct 13, 2023
2ff41ac
More doc fixes
flying-sheep Oct 13, 2023
4c0873e
ugh
flying-sheep Oct 13, 2023
59e1c6d
Comment change to returns section processor
flying-sheep Oct 13, 2023
a70c514
Merge branch 'master' into doctests
flying-sheep Oct 17, 2023
e53e9c5
double quotes
flying-sheep Oct 20, 2023
4f398fd
Merge branch 'master' into doctests
flying-sheep Oct 24, 2023
41b715b
Merge branch 'master' into doctests
flying-sheep Oct 24, 2023
ad29ca5
Finish merge
flying-sheep Oct 24, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
6 changes: 4 additions & 2 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -179,7 +179,7 @@ def setup(app: Sphinx):
# -- Suppress link warnings ----------------------------------------------------

qualname_overrides = {
"sklearn.neighbors._dist_metrics.DistanceMetric": "sklearn.neighbors.DistanceMetric",
"sklearn.neighbors._dist_metrics.DistanceMetric": "sklearn.metrics.DistanceMetric",
# If the docs are built with an old version of numpy, this will make it work:
"numpy.random.RandomState": "numpy.random.mtrand.RandomState",
"scanpy.plotting._matrixplot.MatrixPlot": "scanpy.pl.MatrixPlot",
Expand All @@ -192,8 +192,10 @@ def setup(app: Sphinx):
# Will probably be documented
('py:class', 'scanpy._settings.Verbosity'),
('py:class', 'scanpy.neighbors.OnFlySymMatrix'),
# Currently undocumented: https://github.com/mwaskom/seaborn/issues/1810
# Currently undocumented
# https://github.com/mwaskom/seaborn/issues/1810
('py:class', 'seaborn.ClusterGrid'),
('py:class', 'samalg.SAM'),
# Won’t be documented
('py:class', 'scanpy.plotting._utils._AxesSubplot'),
('py:class', 'scanpy._utils.Empty'),
Expand Down
4 changes: 4 additions & 0 deletions docs/extensions/typed_returns.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ def process_return(lines):

def scanpy_parse_returns_section(self, section):
lines_raw = list(process_return(self._dedent(self._consume_to_next_section())))
if lines_raw[0] == ':':
# Remove the “:” inserted by sphinx-autodoc-typehints
# https://github.com/tox-dev/sphinx-autodoc-typehints/blob/a5c091f725da8374347802d54c16c3d38833d41c/src/sphinx_autodoc_typehints/patches.py#L66
lines_raw.pop(0)
lines = self._format_block(':returns: ', lines_raw)
if lines and lines[-1]:
lines.append('')
Expand Down
3 changes: 2 additions & 1 deletion docs/release-notes/1.10.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,15 @@

```{rubric} Docs
```
* Fixed a lot of broken usage examples {pr}`2605` {smaller}`P Angerer`

```{rubric} Bug fixes
```

* Updated {func}`~scanpy.read_visium` such that it can read spaceranger 2.0 files {smaller}`L Lehner`
* Fix {func}`~scanpy.pp.normalize_total` {pr}`2466` {smaller}`P Angerer`
* Fix testing package build {pr}`2468` {smaller}`P Angerer`

* Fix setting `sc.settings.verbosity` in some cases {pr}`2605` {smaller}`P Angerer`

```{rubric} Ecosystem
```
7 changes: 5 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ scanpy = "scanpy.cli:console_main"

[project.optional-dependencies]
test-min = [
"pytest>=4.4",
"pytest>=7.4.2",
"pytest-nunit",
"pytest-mock",
"profimp",
Expand All @@ -111,7 +111,7 @@ test-full = [
"scanpy[dask-ml]",
]
doc = [
"sphinx>=4.4,<5", # remove upper bound when theme supports dark mode
"sphinx>=5",
"sphinx-book-theme",
"scanpydoc>=0.9.5",
"sphinx-autodoc-typehints",
Expand All @@ -123,7 +123,9 @@ doc = [
"nbsphinx",
"ipython>=7.20", # for nbsphinx code highlighting
"matplotlib!=3.6.1",
# TODO: remove necessity for being able to import doc-linked classes
"scanpy[paga]",
"sam-algorithm",
]
dev = [
# getting the dev version
Expand Down Expand Up @@ -156,6 +158,7 @@ exclude = [
addopts = [
"--import-mode=importlib",
"--strict-markers",
"--doctest-modules",
"-pscanpy.testing._pytest",
]
testpaths = ["scanpy"]
Expand Down
23 changes: 23 additions & 0 deletions scanpy/_compat.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
from __future__ import annotations

from dataclasses import dataclass, field
from pathlib import Path
from packaging import version

try:
Expand Down Expand Up @@ -26,6 +30,25 @@ def fullname(typ: type) -> str:
return f'{module}.{name}'


try:
from contextlib import chdir
except ImportError: # Python < 3.11
import os
from contextlib import AbstractContextManager

@dataclass
class chdir(AbstractContextManager):
path: Path
_old_cwd: list[Path] = field(default_factory=list)

def __enter__(self) -> None:
self._old_cwd.append(Path.cwd())
os.chdir(self.path)

def __exit__(self, *_excinfo) -> None:
os.chdir(self._old_cwd.pop())


def pkg_metadata(package):
from importlib.metadata import metadata as m

Expand Down
44 changes: 29 additions & 15 deletions scanpy/_settings.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from __future__ import annotations

import inspect
import sys
from contextlib import contextmanager
Expand All @@ -18,25 +20,42 @@
'hint': 'HINT',
'debug': 'DEBUG',
}
# Python 3.7 ensures iteration order
# Python 3.7+ ensures iteration order
for v, level in enumerate(list(_VERBOSITY_TO_LOGLEVEL.values())):
_VERBOSITY_TO_LOGLEVEL[v] = level


# Collected from the print_* functions in matplotlib.backends
_Format = Union[
Literal['png', 'jpg', 'tif', 'tiff'],
Literal['pdf', 'ps', 'eps', 'svg', 'svgz', 'pgf'],
Literal['raw', 'rgba'],
]


class Verbosity(IntEnum):
error = 0
warn = 1
warning = 1
info = 2
hint = 3
debug = 4

def __eq__(self, other: Verbosity | int | str) -> bool:
if isinstance(other, Verbosity):
return self is other
if isinstance(other, int):
return self.value == other
if isinstance(other, str):
return self.name == other
return NotImplemented

@property
def level(self) -> int:
# getLevelName(str) returns the int level…
return getLevelName(_VERBOSITY_TO_LOGLEVEL[self])
return getLevelName(_VERBOSITY_TO_LOGLEVEL[self.name])

@contextmanager
def override(self, verbosity: "Verbosity") -> ContextManager["Verbosity"]:
def override(self, verbosity: Verbosity | str | int) -> ContextManager[Verbosity]:
"""\
Temporarily override verbosity
"""
Expand All @@ -45,6 +64,10 @@ def override(self, verbosity: "Verbosity") -> ContextManager["Verbosity"]:
settings.verbosity = self


# backwards compat
Verbosity.warn = Verbosity.warning


def _type_check(var: Any, varname: str, types: Union[type, Tuple[type, ...]]):
if isinstance(var, types):
return
Expand All @@ -69,7 +92,7 @@ class ScanpyConfig:
def __init__(
self,
*,
verbosity: str = "warning",
verbosity: Verbosity | int | str = Verbosity.warning,
plot_suffix: str = "",
file_format_data: str = "h5ad",
file_format_figs: str = "pdf",
Expand Down Expand Up @@ -160,7 +183,7 @@ def verbosity(self, verbosity: Union[Verbosity, int, str]):
self._verbosity = Verbosity(verbosity_str_options.index(verbosity))
else:
_type_check(verbosity, "verbosity", (str, int))
_set_log_level(self, _VERBOSITY_TO_LOGLEVEL[self._verbosity])
_set_log_level(self, _VERBOSITY_TO_LOGLEVEL[self._verbosity.name])

@property
def plot_suffix(self) -> str:
Expand Down Expand Up @@ -386,15 +409,6 @@ def categories_to_ignore(self, categories_to_ignore: Iterable[str]):
# Functions
# --------------------------------------------------------------------------------

# Collected from the print_* functions in matplotlib.backends
# fmt: off
_Format = Literal[
'png', 'jpg', 'tif', 'tiff',
'pdf', 'ps', 'eps', 'svg', 'svgz', 'pgf',
'raw', 'rgba',
]
# fmt: on

def set_figure_params(
self,
scanpy: bool = True,
Expand Down
2 changes: 1 addition & 1 deletion scanpy/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ def parse_known_args(


def _cmd_settings() -> None:
from . import settings
from ._settings import settings

print(settings)

Expand Down
6 changes: 2 additions & 4 deletions scanpy/datasets/_datasets.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,10 +95,8 @@ def krumsiek11() -> ad.AnnData:
Annotated data matrix.
"""
filename = HERE / 'krumsiek11.txt'
verbosity_save = settings.verbosity
settings.verbosity = 'error' # suppress output...
adata = read(filename, first_column_names=True)
settings.verbosity = verbosity_save
with settings.verbosity.override('error'): # suppress output...
adata = read(filename, first_column_names=True)
adata.uns['iroot'] = 0
fate_labels = {0: 'Stem', 159: 'Mo', 319: 'Ery', 459: 'Mk', 619: 'Neu'}
adata.uns['highlights'] = fate_labels
Expand Down
2 changes: 2 additions & 0 deletions scanpy/external/pl.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from anndata import AnnData
from matplotlib.axes import Axes

from ..testing._doctests import doctest_needs
from .._utils import _doc_params
from ..plotting import embedding
from ..plotting._docs import (
Expand All @@ -19,6 +20,7 @@
from .tl._wishbone import _anndata_to_wishbone


@doctest_needs('phate')
@_wraps_plot_scatter
@_doc_params(
adata_color_etc=doc_adata_color_etc,
Expand Down
25 changes: 13 additions & 12 deletions scanpy/external/pp/_bbknn.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
from typing import Union, Optional, Callable
from __future__ import annotations

from anndata import AnnData
import sklearn
from typing import TYPE_CHECKING, Union, Optional, Callable

from ..._utils import lazy_import
from anndata import AnnData

if TYPE_CHECKING:
from sklearn.metrics import DistanceMetric

# Import this lazily so we don’t slowly import sklearn.stats just for annotation
lazy_import("sklearn.neighbors")
del lazy_import
from ...testing._doctests import doctest_needs


@doctest_needs('bbknn')
def bbknn(
adata: AnnData,
batch_key: str = 'batch',
use_rep: str = 'X_pca',
approx: bool = True,
use_annoy: bool = True,
metric: Union[str, Callable, 'sklearn.neighbors.DistanceMetric'] = 'euclidean',
metric: Union[str, Callable, DistanceMetric] = 'euclidean',
copy: bool = False,
*,
neighbors_within_batch: int = 3,
Expand Down Expand Up @@ -55,7 +55,7 @@ def bbknn(
use_rep
The dimensionality reduction in `.obsm` to use for neighbour detection. Defaults to PCA.
approx
If `True`, use approximate neighbour finding - annoy or pyNNDescent. This results
If `True`, use approximate neighbour finding - annoy or PyNNDescent. This results
in a quicker run time for large datasets while also potentially increasing the degree of
batch correction.
use_annoy
Expand All @@ -78,12 +78,13 @@ def bbknn(
'kantorovich', 'wasserstein', 'tsss', 'true_angular', 'hamming', 'jaccard', 'dice', 'matching', 'kulsinski',
'rogerstanimoto', 'russellrao', 'sokalsneath', 'sokalmichener', 'yule'])

KDTree supports members of the `sklearn.neighbors.KDTree.valid_metrics` list, or parameterised
`sklearn.neighbors.DistanceMetric` `objects
<https://scikit-learn.org/stable/modules/generated/sklearn.neighbors.DistanceMetric.html>`_:
KDTree supports members of :class:`sklearn.neighbors.KDTree`’s ``valid_metrics`` list, or parameterised
:class:`~sklearn.metrics.DistanceMetric` objects:

>>> sklearn.neighbors.KDTree.valid_metrics
['p', 'chebyshev', 'cityblock', 'minkowski', 'infinity', 'l2', 'euclidean', 'manhattan', 'l1']

.. note:: check the relevant documentation for up-to-date lists.
copy
If `True`, return a copy instead of writing to the supplied adata.
neighbors_within_batch
Expand Down
5 changes: 3 additions & 2 deletions scanpy/external/pp/_harmony_integrate.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,13 @@
Use harmony to integrate cells from different experiments.
"""

from typing import Optional

from anndata import AnnData
import numpy as np

from ...testing._doctests import doctest_needs


@doctest_needs('harmonypy')
def harmony_integrate(
adata: AnnData,
key: str,
Expand Down
19 changes: 11 additions & 8 deletions scanpy/external/pp/_hashsolo.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,3 @@
#!/usr/bin/env python
from scipy.stats import norm
from scanpy._utils import check_nonnegative_integers
from itertools import product
import anndata
import numpy as np
import pandas as pd

"""
HashSolo script provides a probabilistic cell hashing demultiplexing method
which generates a noise distribution and signal distribution for
Expand All @@ -23,6 +15,16 @@
hypotheses in a bayesian fashion, and select the most probable hypothesis.
"""

from itertools import product

import anndata
import numpy as np
import pandas as pd
from scipy.stats import norm

from ..._utils import check_nonnegative_integers
from ...testing._doctests import doctest_skip


def _calculate_log_likelihoods(data, number_of_noise_barcodes):
"""Calculate log likelihoods for each hypothesis, negative, singlet, doublet
Expand Down Expand Up @@ -255,6 +257,7 @@ def _calculate_bayes_rule(data, priors, number_of_noise_barcodes):
}


@doctest_skip('Illustrative but not runnable doctest code')
def hashsolo(
adata: anndata.AnnData,
cell_hashing_columns: list,
Expand Down
2 changes: 2 additions & 0 deletions scanpy/external/pp/_magic.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,13 @@
from ... import logging as logg
from ..._settings import settings
from ..._utils import AnyRandom
from ...testing._doctests import doctest_needs


MIN_VERSION = "2.0"


@doctest_needs('magic')
def magic(
adata: AnnData,
name_list: Union[Literal['all_genes', 'pca_only'], Sequence[str], None] = None,
Expand Down