Skip to content

Commit 1dd7a55

Browse files
committed
version 0.9.0
1 parent d7a5bfa commit 1dd7a55

File tree

16 files changed

+82
-251
lines changed

16 files changed

+82
-251
lines changed

CHANGELOG.md

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,32 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
77

88
## [Unreleased]
99

10+
## [0.9.0] - 2026-01-01
11+
12+
This release graduates Cellucid Python out of alpha (still pre-1.0).
13+
14+
### Added
15+
16+
- AnnData-first viewing and serving with `.h5ad` and `.zarr` support (lazy/backed loading where possible).
17+
- Unified `cellucid serve` CLI with auto-detection for `.h5ad`, `.zarr`, and pre-exported dataset directories.
18+
- Jupyter notebook integration (`CellucidViewer`, `AnnDataViewer`, `show()`, `show_anndata()`) with event hooks and session export.
19+
- Session bundle support (`.cellucid-session`) including `CellucidSessionBundle` and `apply_cellucid_session_to_anndata()` for round-tripping highlights and user-defined fields back into AnnData.
20+
- Multi-dimensional embedding exports (1D/2D/3D/4D) and vector-field overlays (RNA velocity / drift) via `prepare()` and `vector_fields` helpers.
21+
- Hosted web UI proxy mode with on-disk caching helpers (`get_web_cache_dir()`, `clear_web_cache()`).
22+
23+
### Changed
24+
25+
- Export format now includes explicit dataset identity metadata (`dataset_identity.json`) for reproducible sharing and session compatibility checks.
26+
- Reduced export size and improved load performance with optimized manifests, improved connectivity edge export, and optional quantization + gzip compression knobs.
27+
28+
### Security
29+
30+
- Session bundles are treated as untrusted input with bounds checks and dataset mismatch policies when applying to AnnData.
31+
32+
### Documentation
33+
34+
- Major Read the Docs expansion and restructuring (Python package + web app guides), plus new publishing and contributing documentation.
35+
1036
## [0.0.1a2] - 2025
1137

1238
### Added
@@ -25,5 +51,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
2551
- Jupyter integration (`show()`, `show_anndata()`)
2652
- Export functionality for web deployment
2753

28-
[Unreleased]: https://github.com/theislab/cellucid-python/compare/v0.0.1a2...HEAD
54+
[Unreleased]: https://github.com/theislab/cellucid-python/compare/v0.9.0...HEAD
55+
[0.9.0]: https://github.com/theislab/cellucid-python/releases/tag/v0.9.0
2956
[0.0.1a2]: https://github.com/theislab/cellucid-python/releases/tag/v0.0.1a2

PUBLISHING.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ python -m twine check dist/*
114114
### 3.0 Publish via GitHub Actions (recommended)
115115

116116
If `PYPI_API_TOKEN` is configured (Section 1.3):
117-
1) Push a tag like `v0.0.1a3` (Section 2.3.1).
117+
1) Push a tag like `v0.0.9` (Section 2.3.1). <!-- CELLUCID_VERSION -->
118118
2) Watch the GitHub Actions run: **Actions → Publish to PyPI**.
119119

120120
That workflow builds and uploads both wheel and sdist.

README.md

Lines changed: 29 additions & 229 deletions
Original file line numberDiff line numberDiff line change
@@ -1,257 +1,57 @@
1-
<p>
2-
<img src="https://raw.githubusercontent.com/theislab/cellucid-python/main/cellucid-logo.svg" alt="Cellucid logo" width="360">
3-
</p>
1+
![Cellucid](https://raw.githubusercontent.com/theislab/cellucid-python/main/cellucid-logo.svg)
42

53
[![PyPI version](https://img.shields.io/pypi/v/cellucid.svg)](https://pypi.org/project/cellucid/)
64
[![Python versions](https://img.shields.io/pypi/pyversions/cellucid.svg)](https://pypi.org/project/cellucid/)
75
[![Documentation Status](https://readthedocs.org/projects/cellucid/badge/?version=latest)](https://cellucid.readthedocs.io/en/latest/)
6+
[![License](https://img.shields.io/pypi/l/cellucid.svg)](https://pypi.org/project/cellucid/)
87

98
# Cellucid
109

11-
Python package for visualizing single-cell data with the [Cellucid WebGL viewer](https://cellucid.com). Cellucid renders millions of cells in real-time 3D, enabling interactive exploration of UMAP/tSNE embeddings with gene expression overlays, filtering, and KNN connectivity visualization.
10+
**See every cell. Query any gene. Fly through millions. Interactive, GPU-accelerated single-cell visualization in the browser.**
1211

13-
## Features
12+
Cellucid is a browser-first viewer for exploring large single-cell datasets in real time: fly through 2D/3D embeddings (UMAP/t-SNE/PCA), color by genes or metadata, filter and compare populations, and share reproducible views with collaborators.
1413

15-
- **Interactive Single-Cell Data Visualization** of UMAP/tSNE embeddings
16-
- **Gene expression overlays** with fast queries
17-
- **Cell metadata filtering** and categorical coloring
18-
- **KNN connectivity** edge visualization
19-
- **Multi-dimensional** support (1D timelines, 2D, 3D)
20-
- **Jupyter integration** with bidirectional communication
21-
- **Scales to millions** of cells with adaptive LOD
14+
## Highlights
2215

23-
## Installation
16+
- **GPU-accelerated WebGL rendering** with adaptive detail for millions of cells
17+
- **AnnData-first workflow** for the Scanpy ecosystem (`.h5ad` and Zarr supported)
18+
- **Shareable exports** you can host locally, on GitHub, or behind a server
19+
- **Genes + metadata overlays** optimized for interactive querying
20+
- **Connectivity + dynamics**: KNN edges and animated vector fields (RNA velocity / drift)
21+
- **Collaboration**: community annotation voting with optional GitHub sync
22+
- **Publication export**: SVG (vector) and high-DPI PNG figures
23+
- **Works everywhere**: web app, local/remote server, and Jupyter notebooks
2424

25-
```bash
26-
pip install cellucid
27-
```
28-
29-
All features (Jupyter, AnnData, server) are included in the standard install.
30-
31-
## Quick Start
32-
33-
### Option 1: Direct AnnData Visualization (No Export)
34-
35-
The fastest way to get started - visualize your AnnData directly:
36-
37-
```python
38-
from cellucid import show_anndata
39-
40-
# In-memory AnnData
41-
show_anndata(adata)
42-
43-
# From h5ad file (lazy loading)
44-
show_anndata("/path/to/data.h5ad")
45-
46-
# From zarr store (lazy loading)
47-
show_anndata("/path/to/data.zarr")
48-
```
49-
50-
### Option 2: Pre-export for Best Performance
51-
52-
For production use or sharing, export to optimized binary format:
53-
54-
```python
55-
from cellucid import prepare, show
56-
57-
# Pick UMAP embeddings (explicit keys preferred, fall back to X_umap).
58-
X_umap_1d = adata.obsm.get("X_umap_1d")
59-
X_umap_2d = adata.obsm.get("X_umap_2d")
60-
X_umap_3d = adata.obsm.get("X_umap_3d")
61-
X_umap = adata.obsm.get("X_umap") # may be 1D/2D/3D depending on how it was computed
62-
if X_umap is not None and X_umap_1d is None and X_umap.shape[1] == 1:
63-
X_umap_1d = X_umap
64-
if X_umap is not None and X_umap_2d is None and X_umap.shape[1] == 2:
65-
X_umap_2d = X_umap
66-
if X_umap is not None and X_umap_3d is None and X_umap.shape[1] == 3:
67-
X_umap_3d = X_umap
68-
69-
# Optional: include any per-cell displacement vector fields in embedding space
70-
# (see "Vector Field Overlay" section below for naming conventions).
71-
vector_fields = {
72-
"velocity_umap_2d": adata.obsm.get("velocity_umap_2d"),
73-
"velocity_umap_3d": adata.obsm.get("velocity_umap_3d"),
74-
}
75-
76-
prepare(
77-
# Required inputs
78-
latent_space=adata.obsm.get(
79-
"X_pca",
80-
X_umap_3d if X_umap_3d is not None else (X_umap_2d if X_umap_2d is not None else X_umap_1d),
81-
),
82-
obs=adata.obs,
83-
var=adata.var,
84-
gene_expression=adata.X,
85-
86-
# Optional inputs
87-
connectivities=adata.obsp.get("connectivities"),
88-
vector_fields=vector_fields,
89-
90-
# Embeddings (provide any/all of 1D/2D/3D)
91-
X_umap_1d=X_umap_1d,
92-
X_umap_2d=X_umap_2d,
93-
X_umap_3d=X_umap_3d,
94-
95-
# Output + performance knobs
96-
out_dir="./my_export",
97-
compression=6,
98-
var_quantization=8,
99-
obs_continuous_quantization=8,
100-
)
101-
102-
# View anytime (fastest loading)
103-
show("./my_export")
104-
```
105-
106-
## AnnData Requirements
107-
108-
Your AnnData needs UMAP coordinates in `obsm`:
109-
110-
```python
111-
# Required: one of these
112-
adata.obsm['X_umap_3d'] # shape (n_cells, 3) - recommended
113-
adata.obsm['X_umap_2d'] # shape (n_cells, 2)
114-
adata.obsm['X_umap'] # shape (n_cells, 2 or 3)
115-
116-
# Optional
117-
adata.obsm['velocity_umap_2d'] # shape (n_cells, 2) - vector field overlay (velocity/drift)
118-
adata.obs # Cell metadata (categorical/continuous)
119-
adata.X # Gene expression (dense or sparse)
120-
adata.obsp['connectivities'] # KNN graph edges
121-
```
122-
123-
### Vector Field Overlay (Velocity / CellRank Drift)
124-
125-
Cellucid’s web viewer can render an animated particle-flow overlay from **per-cell displacement vectors** in embedding space.
126-
127-
Store vectors in `adata.obsm` with keys like:
128-
- `velocity_umap_2d`, `velocity_umap_3d`
129-
- `T_fwd_umap_2d`, `T_bwd_umap_2d` (CellRank-style drift)
130-
131-
If you have a CellRank transition matrix `T` and an embedding `X_umap`, you can derive drift vectors:
132-
133-
```python
134-
from cellucid import add_transition_drift_to_obsm
135-
136-
add_transition_drift_to_obsm(
137-
adata,
138-
T_fwd, # (n_cells, n_cells) sparse/dense transition matrix
139-
basis="umap",
140-
field_prefix="T_fwd", # -> writes adata.obsm['T_fwd_umap_<dim>d']
141-
)
142-
```
143-
144-
Computing 3D UMAP with scanpy:
145-
146-
```python
147-
import scanpy as sc
148-
sc.pp.neighbors(adata)
149-
sc.tl.umap(adata, n_components=3)
150-
adata.obsm['X_umap_3d'] = adata.obsm['X_umap']
151-
```
152-
153-
## All 14 Loading Options
154-
155-
Cellucid supports 6 deployment modes, each with support for pre-exported binary data, h5ad files, and zarr stores:
156-
157-
| # | Method | Exported | h5ad | zarr | Python | Lazy Load | Performance |
158-
|---|--------|----------|------|------|--------|-----------|-------------|
159-
| 1 | Local Demo (GitHub) || - | - | No* | Yes | Best |
160-
| 2 | Remote Demo (GitHub) || - | - | No* | Yes | Best |
161-
| 3 | Browser File Picker || - | - | No | Yes | Best |
162-
| 4 | Browser File Picker | - || - | No | **No** | Slower |
163-
| 5 | Browser File Picker | - | - || No | **No** | Slower |
164-
| 6 | Server CLI || - | - | Yes | Yes | Best |
165-
| 7 | Server CLI | - ||| Yes | Yes | Good |
166-
| 8 | Python serve() || - | - | Yes | Yes | Best |
167-
| 9 | Python serve_anndata() | - ||| Yes | Yes | Good |
168-
| 10 | Jupyter show() || - | - | Yes | Yes | Best |
169-
| 11 | Jupyter show_anndata() | - ||| Yes | Yes | Good |
170-
171-
\* Python required for initial export, not for viewing
172-
173-
**Summary by method:**
174-
| Method | Exported | h5ad | zarr | Total |
175-
|--------|----------|------|------|-------|
176-
| Local/Remote Demo || - | - | 2 |
177-
| Browser File Picker |||| 3 |
178-
| Server CLI |||| 3 |
179-
| Python serve |||| 3 |
180-
| Jupyter |||| 3 |
181-
| **Total** | | | | **14** |
182-
183-
### Key Notes:
184-
- **Browser h5ad/zarr**: Entire file loaded into memory - no lazy loading due to JavaScript limitations
185-
- **Python h5ad/zarr modes**: True lazy loading via AnnData backed mode (h5ad) or zarr's native chunked access
186-
- **Pre-exported data**: Always fastest - use for production and sharing
187-
- **zarr stores**: Can be a directory (.zarr) or a file - the Python server auto-detects the format
188-
189-
## Deployment Modes
190-
191-
| Mode | Best For | Command/Function |
192-
|------|----------|------------------|
193-
| **Jupyter** | Interactive analysis | `show_anndata(adata)` |
194-
| **Local server** | Development | `cellucid serve ./data` |
195-
| **Remote + SSH** | Team access | `cellucid serve data.h5ad` |
196-
| **Browser** | Quick preview | [cellucid.com](https://cellucid.com) file picker |
197-
| **Static hosting** | Public sharing | GitHub Pages |
198-
199-
### CLI Commands
25+
## Install
20026

20127
```bash
202-
# Serve any data - format auto-detected
203-
cellucid serve /path/to/data.h5ad # h5ad file
204-
cellucid serve /path/to/data.zarr # zarr store
205-
cellucid serve /path/to/export # pre-exported data
206-
207-
# With options
208-
cellucid serve data.h5ad --port 9000 --no-browser
209-
210-
# Show version
211-
cellucid --version
28+
pip install cellucid
21229
```
21330

214-
### Remote Server Access
31+
## Quickstart
21532

216-
```bash
217-
# On remote server
218-
cellucid serve /data/cells.h5ad --no-browser
33+
Try the web app (no setup):
21934

220-
# On local machine (SSH tunnel)
221-
ssh -L 8765:localhost:8765 user@server
222-
# Then open: https://cellucid.com?remote=http://localhost:8765
223-
```
35+
1. Open https://cellucid.com
36+
2. Load a pre-exported folder, `.h5ad`, or `.zarr`
22437

225-
## Jupyter Features
38+
Or visualize an AnnData from Python/Jupyter:
22639

22740
```python
22841
from cellucid import show_anndata
22942

230-
viewer = show_anndata(adata, height=600)
231-
232-
# Programmatic control
233-
viewer.highlight_cells([1, 2, 3], color="#ff0000")
234-
viewer.set_color_by("cell_type")
235-
viewer.set_visibility([0, 1, 2], visible=False)
236-
237-
# Cleanup
238-
viewer.stop()
43+
show_anndata(adata) # or: show_anndata("dataset.h5ad")
23944
```
24045

241-
## Performance Guide
242-
243-
| Method | Load Time | Gene Queries | Recommended For |
244-
|--------|-----------|--------------|-----------------|
245-
| Pre-exported (`show`) | Fast | Fast | Production, sharing |
246-
| Direct AnnData (`show_anndata`) | Medium | Medium | Exploration |
247-
| Browser file picker | Slower | Slower | Quick preview |
248-
249-
For datasets > 500k cells, pre-export with `prepare()` is recommended.
250-
251-
## Documentation
46+
## Links
25247

253-
- **[Full documentation](https://cellucid.readthedocs.io)** - API reference and tutorials
254-
- **[Web viewer](https://github.com/theislab/cellucid)** - JavaScript repository
48+
- Web app: https://cellucid.com
49+
- Documentation: https://cellucid.readthedocs.io
50+
- Community annotation voting: https://cellucid.readthedocs.io/en/latest/user_guide/web_app/j_community_annotation/index.html
51+
- Source: https://github.com/theislab/cellucid-python
52+
- Web viewer: https://github.com/theislab/cellucid
53+
- Annotation template: https://github.com/theislab/cellucid-annotation
54+
- Issues: https://github.com/theislab/cellucid-python/issues
25555

25656
## License
25757

docs/_static/switcher.json

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
"url": "https://cellucid.readthedocs.io/en/latest/"
66
},
77
{
8-
"name": "0.0.1a2 (stable)",
9-
"version": "0.0.1a2",
8+
"name": "0.0.9 (stable)",
9+
"version": "0.0.9",
10+
"cellucid_version_marker": "CELLUCID_VERSION",
1011
"url": "https://cellucid.readthedocs.io/en/stable/",
1112
"preferred": true
1213
}

docs/conf.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222

2323
release = version = __version__
2424
except Exception:
25-
release = version = "0.0.1a2"
25+
release = version = "0.0.9" # CELLUCID_VERSION
2626

2727
# -- General configuration ---------------------------------------------------
2828
extensions = [

docs/user_guide/python_package/a_landing_pages/02_installation.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ pip install -U cellucid
6767
Pin a specific version (recommended for paper pipelines):
6868

6969
```bash
70-
pip install "cellucid==0.0.1a2"
70+
pip install "cellucid==0.0.9" # CELLUCID_VERSION
7171
```
7272

7373
### Optional dependencies (what you might need next)

docs/user_guide/python_package/c_data_preparation_api/09_output_format_specification_exports_directory.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ It provides:
8181
"name": "PBMC demo",
8282
"description": "",
8383
"created_at": "2026-01-01T00:00:00Z",
84-
"cellucid_data_version": "0.0.1a2",
84+
"_cellucid_version_marker": "CELLUCID_VERSION",
85+
"cellucid_data_version": "0.0.9",
8586
"stats": {
8687
"n_cells": 10000,
8788
"n_genes": 2000,

docs/user_guide/python_package/f_notebooks_tutorials/jupyter_hooks_sessions_he_developmental.ipynb

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,12 +267,12 @@
267267
" 'client_server_url': 'http://127.0.0.1:8766',\n",
268268
" 'server_health': {'status': 'ok',\n",
269269
" 'type': 'anndata',\n",
270-
" 'version': '0.0.1a2',\n",
270+
" 'version': '0.0.9',\n",
271271
" 'format': 'h5ad',\n",
272272
" 'is_backed': True,\n",
273273
" 'n_cells': 71650,\n",
274274
" 'n_genes': 8192},\n",
275-
" 'server_info': {'version': '0.0.1a2',\n",
275+
" 'server_info': {'version': '0.0.9',\n",
276276
" 'type': 'anndata',\n",
277277
" 'format': 'h5ad',\n",
278278
" 'host': '127.0.0.1',\n",
@@ -493,6 +493,7 @@
493493
}
494494
],
495495
"metadata": {
496+
"cellucid_version_marker": "CELLUCID_VERSION",
496497
"kernelspec": {
497498
"display_name": "tardis_env",
498499
"language": "python",

0 commit comments

Comments
 (0)