Skip to content

Commit 8db4238

Browse files
authored
Merge pull request #2 from HiDiHlabs/dev
Prepare Publication
2 parents e07bc39 + 28f81f5 commit 8db4238

File tree

8 files changed

+191
-18
lines changed

8 files changed

+191
-18
lines changed

.github/workflows/publish-pypi.yml

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
name: Publish Python Package to PyPI
2+
3+
on:
4+
release:
5+
types: [published]
6+
7+
jobs:
8+
publish:
9+
runs-on: ubuntu-latest
10+
environment: pypi
11+
permissions:
12+
id-token: write # to authenticate as Trusted Publisher to pypi.org
13+
steps:
14+
- uses: actions/checkout@v4
15+
- uses: actions/setup-python@v5
16+
with:
17+
python-version: "3.x"
18+
cache: "pip"
19+
- run: pip install build
20+
- run: python -m build
21+
- uses: pypa/gh-action-pypi-publish@release/v1

.pre-commit-config.yaml

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
ci:
2+
autoupdate_schedule: quarterly
13
repos:
24
- repo: https://github.com/pre-commit/pre-commit-hooks
35
rev: v4.6.0
@@ -13,7 +15,7 @@ repos:
1315
- id: no-commit-to-branch
1416
args: [--branch=main]
1517
- repo: https://github.com/astral-sh/ruff-pre-commit
16-
rev: v0.3.5
18+
rev: v0.6.1
1719
hooks:
1820
- id: ruff
1921
args: [--fix]
@@ -22,15 +24,15 @@ repos:
2224
hooks:
2325
- id: isort
2426
- repo: https://github.com/psf/black
25-
rev: 24.3.0
27+
rev: 24.8.0
2628
hooks:
2729
- id: black
2830
- repo: https://github.com/pre-commit/mirrors-mypy
29-
rev: v1.9.0
31+
rev: v1.11.1
3032
hooks:
3133
- id: mypy
3234
- repo: https://github.com/codespell-project/codespell
33-
rev: v2.2.6
35+
rev: v2.3.0
3436
hooks:
3537
- id: codespell
3638
additional_dependencies:

README.md

+25-4
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,34 @@ but can also be used independently.
1717

1818
## Installation
1919

20-
`spatialleiden` will be made available on [PyPI](https://pypi.org/) and
21-
[bioconda](https://bioconda.github.io/). For detailed installation instructions
22-
please refer to the [documentation](https://spatialleiden.readthedocs.io/en/stable/installation.html).
20+
`spatialleiden` is available on [PyPI](https://pypi.org/project/spatialleiden/) and
21+
[bioconda](https://bioconda.github.io/recipes/spatialleiden/README.html).
22+
23+
```sh
24+
# PyPI
25+
pip install spatialleiden
26+
```
27+
28+
```sh
29+
# or conda
30+
conda install bioconda::spatialleiden
31+
```
32+
33+
For detailed installation instructions please refer to the
34+
[documentation](https://spatialleiden.readthedocs.io/stable/installation.html).
2335

2436
## Documentation
2537

26-
For documentation of the package please refer to the [ReadTheDocs page](https://spatialleiden.readthedocs.io/)
38+
For documentation of the package please refer to the
39+
[ReadTheDocs page](https://spatialleiden.readthedocs.io/).
40+
41+
## Citations
42+
43+
If you are using `spatialleiden` for your research please cite
44+
45+
Müller-Bötticher, N., Sahay, S., Eils, R., and Ishaque, N.
46+
"SpatialLeiden - Spatially-aware Leiden clustering"
47+
bioRxiv (2024) https://doi.org/10.1101/2024.08.23.609349
2748

2849
## Versioning
2950

docs/source/conf.py

+4
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
"sphinx.ext.napoleon",
2828
"sphinx.ext.autosummary",
2929
"sphinx.ext.mathjax",
30+
"myst_nb",
3031
]
3132

3233

@@ -41,6 +42,8 @@
4142
nitpicky = True
4243
nitpick_ignore = [("py:class", "optional")]
4344

45+
# MyST-NB config
46+
nb_execution_timeout = 3 * 60
4447

4548
exclude_patterns: list[str] = []
4649

@@ -51,6 +54,7 @@
5154
python=("https://docs.python.org/3", None),
5255
scanpy=("https://scanpy.readthedocs.io/en/stable/", None),
5356
scipy=("https://docs.scipy.org/doc/scipy/", None),
57+
squidpy=("https://squidpy.readthedocs.io/en/stable/", None),
5458
)
5559

5660
# -- Options for HTML output -------------------------------------------------

docs/source/index.rst

+10
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,23 @@ SpatialLeiden integrates with the `scverse <https://scverse.org/>`_ by leveragin
99
`scanpy <https://scanpy.readthedocs.io/>`_ and `anndata <https://anndata.readthedocs.io/>`_
1010
but can also be used independently.
1111

12+
Citations
13+
---------
14+
15+
If you are using `spatialleiden` for your research please cite
16+
17+
Müller-Bötticher, N., Sahay, S., Eils, R., and Ishaque, N.
18+
"SpatialLeiden - Spatially-aware Leiden clustering"
19+
bioRxiv (2024) https://doi.org/10.1101/2024.08.23.609349
20+
1221

1322
.. toctree::
1423
:maxdepth: 1
1524
:caption: Contents:
1625

1726
self
1827
installation
28+
usage
1929
api
2030

2131

docs/source/installation.rst

+10-9
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ Installation
55
PyPi and ``pip``
66
----------------
77

8-
To install ``spatialleiden`` from `PyPI <https://pypi.org/>`_ using ``pip`` just run
8+
To install ``spatialleiden`` from `PyPI <https://pypi.org/project/spatialleiden/>`_
9+
using ``pip`` just run
910

1011
.. code-block:: bash
1112
@@ -15,19 +16,19 @@ To install ``spatialleiden`` from `PyPI <https://pypi.org/>`_ using ``pip`` just
1516
bioconda and ``conda``
1617
----------------------
1718

18-
``spatialleiden`` is not yet available for
19-
`Miniconda <https://docs.conda.io/en/latest/miniconda.html>`_ installations. But we are
20-
planning to add it to `bioconda <https://bioconda.github.io/>`_ soon.
19+
``spatialleiden`` is available for `Miniconda <https://docs.conda.io/en/latest/miniconda.html>`_
20+
installations from the `bioconda <https://bioconda.github.io/recipes/spatialleiden/README.html>`_
21+
channel.
2122

2223

23-
.. .. code-block:: bash
24+
.. code-block:: bash
2425
25-
.. conda install -c conda-forge spatialleiden
26+
conda install bioconda::spatialleiden
2627
27-
.. .. note::
28+
.. note::
2829

29-
.. Of course, it is also possible to use ``mamba`` instead of ``conda``
30-
.. to speed up the installation.
30+
Of course, it is also possible to use ``mamba`` instead of ``conda``
31+
to speed up the installation.
3132

3233

3334
From GitHub

docs/source/usage.md

+113
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
---
2+
file_format: mystnb
3+
kernelspec:
4+
name: python
5+
jupytext:
6+
text_representation:
7+
extension: .md
8+
format_name: myst
9+
format_version: 0.13
10+
jupytext_version: 1.16.2
11+
---
12+
13+
# Usage
14+
15+
+++
16+
17+
To demonstrate the usage of the `spatialleiden` package we are going to use a MERFISH data set from [Moffit _et al._ 2018](https://doi.org/10.1126/science.aau5324) that can be downloaded from [figshare](https://figshare.com/articles/dataset/MERFISH_datasets/22565170) and then loaded as {py:class}`anndata.AnnData` object.
18+
19+
```{code-cell} ipython3
20+
---
21+
tags: [hide-cell]
22+
---
23+
24+
from tempfile import NamedTemporaryFile
25+
from urllib.request import urlretrieve
26+
27+
import anndata as ad
28+
29+
with NamedTemporaryFile(suffix=".h5ad") as h5ad_file:
30+
urlretrieve("https://figshare.com/ndownloader/files/40038538", h5ad_file.name)
31+
adata = ad.read_h5ad(h5ad_file)
32+
```
33+
34+
First of all we are going to load the relevant packages that we will be working with as well as setting a random seed that we will use throughout this example to make the results reproducible.
35+
36+
```{code-cell} ipython3
37+
import scanpy as sc
38+
import spatialleiden as sl
39+
import squidpy as sq
40+
41+
seed = 42
42+
```
43+
44+
The data set consists of 155 genes and ~5,500 cells including their annotation for cell type as well as domains.
45+
46+
+++
47+
48+
## SpatialLeiden
49+
50+
We will do some standard preprocessing by log-transforming the data and then using PCA for dimensionality reduction. The PCA will be used to build a kNN graph in the latent gene expression space. This graph is the basis for the Leiden clustering.
51+
52+
```{code-cell} ipython3
53+
sc.pp.log1p(adata)
54+
sc.pp.pca(adata, random_state=seed)
55+
56+
sc.pp.neighbors(adata, random_state=seed)
57+
```
58+
59+
For SpatialLeiden we need an additional graph representing the connectivities in the topological space. Here we will use a kNN graph with 10 neighbors that we generate with {py:func}`squidpy.gr.spatial_neighbors`. Alternatives are Delaunay triangulation or regular grids in case of e.g. Visium data.
60+
61+
We can use the calculated distances between neighboring points and transform them into connectivities using the {py:func}`spatialleiden.distance2connectivity` function.
62+
63+
```{code-cell} ipython3
64+
sq.gr.spatial_neighbors(adata, coord_type="generic", n_neighs=10)
65+
66+
adata.obsp["spatial_connectivities"] = sl.distance2connectivity(
67+
adata.obsp["spatial_distances"]
68+
)
69+
```
70+
71+
Now, we can already run {py:func}`spatialleiden.spatialleiden` (which we will also compare to normal Leiden clustering).
72+
73+
The `layer_ratio` determines the weighting between the gene expression and the topological layer and is influenced by the graph structures (i.e. how many connections exist, the edge weights, etc.); the lower the value is the closer SpatialLeiden will be to normal Leiden clustering, while higher values lead to more spatially homogeneous clusters.
74+
75+
The resolution has the same effect as in Leiden clustering (higher resolution will lead to more clusters) and can be defined for each of the layers (but for now is left at its default value).
76+
77+
```{code-cell} ipython3
78+
sc.tl.leiden(adata, directed=False, random_state=seed)
79+
80+
sl.spatialleiden(adata, layer_ratio=1.8, directed=(False, True), seed=seed)
81+
82+
sc.pl.embedding(adata, basis="spatial", color=["leiden", "spatialleiden"])
83+
```
84+
85+
We can see how Leiden clustering identifies cell types while SpatialLeiden defines domains of the tissue.
86+
87+
+++
88+
89+
## Resolution search
90+
91+
If you already know how many domains you expect in your sample you can use the {py:func}`spatialleiden.search_resolution` function to identify the resolutions needed to obtain the correct number of clusters.
92+
93+
Conceptually, this function first runs Leiden clustering multiple times while changing the resolution to identify the value leading to the desired number of clusters. Next, this procedure is repeated by running SpatialLeiden, but now the resolution of the latent layer (gene expression) is kept fixed and the resolution of the spatial layer is varied.
94+
95+
```{code-cell} ipython3
96+
n_clusters = adata.obs["domain"].nunique()
97+
98+
latent_resolution, spatial_resolution = sl.search_resolution(
99+
adata,
100+
n_clusters,
101+
latent_kwargs={"seed": seed},
102+
spatial_kwargs={"layer_ratio": 1.8, "seed": seed, "directed": (False, True)},
103+
)
104+
105+
print(f"Latent resolution: {latent_resolution:.3f}")
106+
print(f"Spatial resolution: {spatial_resolution:.3f}")
107+
```
108+
109+
In our case we can compare the resulting clusters to the annotated ground truth regions. If we are not satisfied with the results, we can go back and tweak other parameters such as the underlying neighborhood graphs or the `layer_ratio` to achieve the desired granularity of our results.
110+
111+
```{code-cell} ipython3
112+
sc.pl.embedding(adata, basis="spatial", color=["spatialleiden", "Region"])
113+
```

pyproject.toml

+2-1
Original file line numberDiff line numberDiff line change
@@ -30,11 +30,12 @@ classifiers = [
3030
"Programming Language :: Python :: 3",
3131
"Programming Language :: Python :: 3 :: Only",
3232
"Topic :: Scientific/Engineering",
33+
"Topic :: Scientific/Engineering :: Bio-Informatics",
3334
"Typing :: Typed",
3435
]
3536

3637
[project.optional-dependencies]
37-
docs = ["sphinx", "sphinx-copybutton", "sphinx-rtd-theme"]
38+
docs = ["sphinx", "sphinx-copybutton", "sphinx-rtd-theme", "squidpy", "myst-nb"]
3839
dev = ["spatialleiden[docs]", "pre-commit"]
3940

4041
[project.urls]

0 commit comments

Comments
 (0)