Skip to content

Commit 34ca984

Browse files
committed
Bootstrap notebooks repo with getting-started tutorial
- Scaffold pyproject (exec/dev extras), README, CONTRIBUTING, .gitignore. - Add lint + execute CI workflows; weekly re-execution against latest release. - Add tutorials/getting_started.ipynb using sd.datasets.blobs() (executed, outputs committed) covering fluent .pl API, layering, and styling. - Add tutorials/ and examples/ index landing pages for sphinx toctree.
1 parent 266f4d9 commit 34ca984

10 files changed

Lines changed: 719 additions & 0 deletions

File tree

.github/workflows/execute.yaml

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
name: Execute notebooks
2+
3+
on:
4+
schedule:
5+
# Weekly: Mondays 04:00 UTC
6+
- cron: "0 4 * * 1"
7+
pull_request:
8+
branches: [main]
9+
paths:
10+
- "**/*.ipynb"
11+
- "pyproject.toml"
12+
- ".github/workflows/execute.yaml"
13+
workflow_dispatch:
14+
15+
concurrency:
16+
group: ${{ github.workflow }}-${{ github.ref }}
17+
cancel-in-progress: true
18+
19+
jobs:
20+
execute:
21+
runs-on: ubuntu-latest
22+
timeout-minutes: 60
23+
steps:
24+
- uses: actions/checkout@v5
25+
with:
26+
# Need full history so nbdime can diff against base.
27+
fetch-depth: 0
28+
29+
- uses: actions/setup-python@v5
30+
with:
31+
python-version: "3.13"
32+
33+
- name: Cache pooch datasets
34+
uses: actions/cache@v4
35+
with:
36+
path: ~/.cache/pooch
37+
key: pooch-${{ runner.os }}-${{ hashFiles('**/*.ipynb') }}
38+
restore-keys: |
39+
pooch-${{ runner.os }}-
40+
41+
- name: Install execution environment
42+
run: |
43+
pip install --upgrade pip
44+
pip install -e ".[exec]" nbdime jupyter
45+
46+
- name: Re-execute notebooks
47+
run: |
48+
# Find every notebook under tutorials/ and examples/, execute in
49+
# place, fail on any cell error.
50+
find tutorials examples -name "*.ipynb" -not -path "*/.ipynb_checkpoints/*" | while read -r nb; do
51+
echo "Executing $nb"
52+
jupyter nbconvert --to notebook --execute --inplace "$nb"
53+
done
54+
55+
- name: Diff outputs against committed
56+
run: |
57+
# If outputs drift from what's committed, fail the job. Authors are
58+
# expected to commit re-executed notebooks; CI catches drift between
59+
# commits (e.g., upstream lib changes).
60+
if ! git diff --quiet -- '*.ipynb'; then
61+
echo "Notebook outputs drifted from committed state:"
62+
nbdime diff
63+
exit 1
64+
fi

.github/workflows/lint.yaml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
name: Lint
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
concurrency:
10+
group: ${{ github.workflow }}-${{ github.ref }}
11+
cancel-in-progress: true
12+
13+
jobs:
14+
lint:
15+
runs-on: ubuntu-latest
16+
steps:
17+
- uses: actions/checkout@v5
18+
19+
- uses: actions/setup-python@v5
20+
with:
21+
python-version: "3.13"
22+
23+
- uses: actions/cache@v4
24+
with:
25+
path: ~/.cache/pre-commit
26+
key: pre-commit-${{ runner.os }}-${{ hashFiles('.pre-commit-config.yaml') }}
27+
28+
- name: Install pre-commit
29+
run: pip install pre-commit
30+
31+
- name: Run pre-commit
32+
run: pre-commit run --all-files --show-diff-on-failure

.gitignore

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
# Byte-compiled / optimized / DLL files
2+
__pycache__/
3+
*.py[cod]
4+
*$py.class
5+
6+
# Distribution / packaging
7+
build/
8+
dist/
9+
*.egg-info/
10+
*.egg
11+
12+
# Environments
13+
.env
14+
.venv
15+
env/
16+
venv/
17+
ENV/
18+
19+
# Editors
20+
.idea/
21+
.vscode/
22+
.DS_Store
23+
24+
# Jupyter
25+
.ipynb_checkpoints/
26+
profile_default/
27+
ipython_config.py
28+
29+
# Caches
30+
.cache/
31+
.pytest_cache/
32+
.mypy_cache/
33+
.ruff_cache/
34+
35+
# Datasets cached on first run
36+
data/
37+
tutorial_data/
38+
39+
# Sphinx build artifacts (in case anyone builds locally)
40+
docs/_build/

.pre-commit-config.yaml

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
fail_fast: false
2+
default_language_version:
3+
python: python3
4+
minimum_pre_commit_version: 3.0.0
5+
6+
repos:
7+
- repo: https://github.com/pre-commit/pre-commit-hooks
8+
rev: v5.0.0
9+
hooks:
10+
- id: check-yaml
11+
- id: check-toml
12+
- id: end-of-file-fixer
13+
exclude: \.ipynb$
14+
- id: mixed-line-ending
15+
args: [--fix=lf]
16+
- id: trailing-whitespace
17+
exclude: \.ipynb$
18+
- id: check-added-large-files
19+
args: [--maxkb=5000]
20+
exclude: \.ipynb$
21+
22+
- repo: https://github.com/astral-sh/ruff-pre-commit
23+
rev: v0.7.4
24+
hooks:
25+
- id: ruff
26+
args: [--fix]
27+
- id: ruff-format
28+
29+
- repo: https://github.com/nbQA-dev/nbQA
30+
rev: 1.9.0
31+
hooks:
32+
- id: nbqa-ruff
33+
args: [--fix]

CONTRIBUTING.md

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Contributing
2+
3+
Thanks for contributing a notebook to the `spatialdata-plot` gallery.
4+
5+
## Setup
6+
7+
```bash
8+
git clone https://github.com/scverse/spatialdata-plot-notebooks.git
9+
cd spatialdata-plot-notebooks
10+
pip install -e ".[exec,dev]"
11+
pre-commit install
12+
```
13+
14+
## Adding a notebook
15+
16+
1. Decide the type:
17+
- **`tutorials/<topic>.ipynb`** — end-to-end workflow on a real dataset
18+
(Visium, Xenium, MERFISH, …). Focuses on a complete analysis story.
19+
- **`examples/<group>/<topic>.ipynb`** — short, single-feature notebook
20+
(e.g., `examples/customization/outlines.ipynb`). Focuses on one technique.
21+
22+
2. Start the notebook with a markdown cell containing:
23+
- A title (`# ...`).
24+
- 2-3 sentences on what the reader will learn.
25+
- A dataset citation when applicable.
26+
27+
3. Use `squidpy.datasets.*` or `spatialdata.datasets.*` for data — never raw
28+
URLs. Both libraries cache via `pooch`, so first-run downloads are cheap on
29+
re-runs.
30+
31+
4. Re-execute the notebook end-to-end (Restart Kernel & Run All) and commit
32+
with outputs. The `spatialdata-plot` docs build performs no execution; what
33+
you commit is what users see rendered.
34+
35+
5. Add the notebook to the appropriate `index.md` so it appears in the gallery
36+
toctree.
37+
38+
6. Open a PR. CI will:
39+
- Lint structure and code (`lint.yaml`).
40+
- Re-execute the notebook against the latest `spatialdata-plot` release
41+
and diff outputs (`execute.yaml`).
42+
43+
## Updating an existing notebook
44+
45+
Edit, re-execute, commit. CI catches output drift on the next scheduled run if
46+
you forget.
47+
48+
## What not to commit
49+
50+
- Raw datasets (use `squidpy.datasets` / `spatialdata.datasets`).
51+
- Notebooks larger than ~5 MB after execution — open an issue first; we may
52+
need git-lfs or a downsampled variant.
53+
- Cells that depend on local files outside the repo.
54+
55+
## Questions
56+
57+
Open an issue or ping in [scverse Zulip](https://scverse.zulipchat.com).

README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# spatialdata-plot-notebooks
2+
3+
Executable notebooks demonstrating [spatialdata-plot] on real spatial-omics
4+
datasets. Rendered into the [spatialdata-plot documentation][docs] as a
5+
gallery.
6+
7+
[spatialdata-plot]: https://github.com/scverse/spatialdata-plot
8+
[docs]: https://spatialdata.scverse.org/projects/plot/en/latest/
9+
10+
## Layout
11+
12+
```
13+
tutorials/ # end-to-end workflows on real datasets (Visium, Xenium, MERFISH, ...)
14+
examples/ # short, focused notebooks demonstrating one feature at a time
15+
```
16+
17+
Each notebook is committed **with outputs** so the `spatialdata-plot` docs build
18+
performs no execution. Outputs are kept fresh by a scheduled CI job that
19+
re-executes every notebook against the latest `spatialdata-plot` release.
20+
21+
## Running notebooks locally
22+
23+
```bash
24+
git clone https://github.com/scverse/spatialdata-plot-notebooks.git
25+
cd spatialdata-plot-notebooks
26+
pip install -e ".[exec]"
27+
jupyter lab
28+
```
29+
30+
The `exec` extra pulls `spatialdata-plot`, `squidpy` (for dataset loaders),
31+
and `jupyter`. Datasets are fetched on first run via each library's built-in
32+
caching (`pooch`), then re-used across runs.
33+
34+
## Contributing a notebook
35+
36+
See [CONTRIBUTING.md](CONTRIBUTING.md). Short version:
37+
38+
1. Add `tutorials/<topic>.ipynb` (workflow) or `examples/<group>/<topic>.ipynb`
39+
(focused).
40+
2. Re-execute end-to-end and commit with outputs.
41+
3. Add the notebook to `tutorials/index.md` or `examples/index.md`.
42+
4. Open a PR — `lint.yaml` checks structure; `execute.yaml` re-runs notebooks
43+
on the PR.
44+
45+
## Datasets and attribution
46+
47+
Notebooks use public datasets distributed via `squidpy.datasets` and
48+
`spatialdata.datasets`. Per-dataset citations live in the markdown header of
49+
each notebook; please follow the same convention when contributing.
50+
51+
## License
52+
53+
BSD-3-Clause. See [LICENSE](LICENSE).

examples/index.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Examples
2+
3+
Short, focused notebooks demonstrating individual `spatialdata-plot` features.
4+
Use these as a quick reference when you know what you want to do and need to
5+
see the call shape.
6+
7+
```{toctree}
8+
:maxdepth: 2
9+
:glob:
10+
11+
*/index
12+
```

pyproject.toml

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
[build-system]
2+
requires = ["hatchling"]
3+
build-backend = "hatchling.build"
4+
5+
[project]
6+
name = "spatialdata-plot-notebooks"
7+
version = "0.0.0"
8+
description = "Executable notebooks demonstrating spatialdata-plot on real spatial-omics datasets."
9+
readme = "README.md"
10+
license = { file = "LICENSE" }
11+
requires-python = ">=3.11"
12+
authors = [{ name = "scverse" }]
13+
14+
# The package itself ships no Python code; this is a pyproject for tooling +
15+
# environment management. The `exec` extra installs everything needed to run
16+
# the notebooks end-to-end.
17+
[project.optional-dependencies]
18+
exec = [
19+
"spatialdata-plot>=0.3",
20+
"squidpy",
21+
"jupyter",
22+
"ipykernel",
23+
]
24+
dev = [
25+
"pre-commit>=3.0",
26+
"ruff",
27+
"nbstripout",
28+
]
29+
30+
[project.urls]
31+
Source = "https://github.com/scverse/spatialdata-plot-notebooks"
32+
Documentation = "https://spatialdata.scverse.org/projects/plot/en/latest/"
33+
34+
[tool.hatch.build.targets.wheel]
35+
bypass-selection = true
36+
37+
[tool.ruff]
38+
line-length = 120
39+
target-version = "py311"
40+
41+
[tool.ruff.lint]
42+
select = ["E", "F", "W", "I", "UP", "B"]
43+
ignore = ["E501"] # long lines fine in notebooks
44+
45+
[tool.ruff.lint.per-file-ignores]
46+
"*.ipynb" = ["E402"] # imports after markdown intro cells are common

0 commit comments

Comments
 (0)