RNA Velocity via Optimal Transport
Project description
VelOT — RNA Velocity via Optimal Transport
VelOT is a kinetic-free framework for estimating RNA velocity from single-cell transcriptomic data. Instead of modeling the molecular kinetics of splicing and degradation, VelOT treats velocity inference as an optimal transport problem in gene expression space, producing smooth, continuous velocity fields without requiring spliced/unspliced count matrices.
Paper: VelOT: kinetic-free RNA velocity inference via optimal transport, flow-field smoothing, and VAMP coarse-graining of cellular dynamics — Preprint (coming soon)
Highlights
- No kinetic assumptions — does not require spliced/unspliced quantification or kinetic parameter fitting.
- Optimal transport — estimates cell-to-cell transitions via entropy-regularized OT within spatial-temporal windows.
- Continuous velocity field — a neural network learns a smooth, queryable velocity field over the full expression manifold.
- Fast — full pipeline runs in seconds to minutes, significantly faster than dynamical scVelo or other deep-learning methods.
- Scanpy-compatible — follows the
pp/tl/plAPI convention. Works with standard AnnData objects.
Installation
VelOT requires Python ≥ 3.10. We recommend a fresh conda environment:
# Create environment and install PyTorch first
conda create -n velot python=3.10 -y
conda activate velot
# Install PyTorch (adjust for your CUDA version — see https://pytorch.org)
# GPU:
pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118
# CPU only:
# pip3 install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cpu
# Install VelOT
git clone https://github.com/lucas-rdlr/velot.git
cd velot
pip install -e .
PyTorch is installed separately to allow users to choose the appropriate CUDA version for their system. See pytorch.org for installation options.
Quick Start
import velot
# Load a dataset
adata = velot.datasets.pancreas()
# Preprocess: normalize, HVG, PCA, KNN, UMAP, pseudotime
adata = velot.pp.prepare(adata, root_cluster="Ductal", cluster_key="clusters")
# Compute velocity (windows → OT → smoothing → UMAP projection)
velot.tl.velocity(adata)
# Visualize
velot.pl.velocity_stream(adata, color="clusters")
Pipeline Overview
VelOT proceeds in four stages, all operating in PCA space:
| Stage | Function | Description |
|---|---|---|
| 1. Preprocessing | velot.pp.prepare() |
Normalization, HVG selection, PCA, KNN graph, pseudotime via DPT |
| 2. Windowing | velot.tl.build_windows() |
Spatial clustering + temporal windowing for local OT |
| 3. OT Velocity | velot.tl.compute_ot_velocity() |
Entropy-regularized OT within each window pair |
| 4. Smoothing | velot.tl.smooth_velocity() |
Neural network learns a continuous velocity field |
The convenience function velot.tl.velocity() runs stages 2–4 in one call.
Step-by-Step Usage
import velot
adata = velot.datasets.pancreas()
# Step 1: Preprocessing
adata = velot.pp.prepare(adata, root_cluster="Ductal", cluster_key="clusters")
# Step 2: Build spatial-temporal windows
velot.tl.build_windows(adata, n_clusters=10, window_size=50)
# Step 3: Compute OT velocity
velot.tl.compute_ot_velocity(adata, reg=0.05, lambda_time=1.0, lambda_knn=1.0)
# Step 4: Smooth with neural network
velot.tl.smooth_velocity(adata, n_epochs=200, lambda_smooth=0.5)
# Step 5: Project to UMAP for visualization
velot.tl.project_to_umap(adata)
# Visualize
velot.pl.velocity_stream(adata, color="clusters")
velot.pl.confidence(adata)
velot.pl.training_curves(adata)
Evaluation
VelOT includes built-in metrics for velocity quality assessment:
edges = [
("Ngn3 low EP", "Ngn3 high EP"),
("Ngn3 high EP", "Fev+"),
("Fev+", "Alpha"),
("Fev+", "Beta"),
("Fev+", "Delta"),
("Fev+", "Epsilon"),
]
results = velot.metrics.summary(
adata,
cluster_edges=edges,
cluster_key="clusters",
)
velot.pl.metric_summary(results)
Metrics:
- ICCoh (Inner-Cluster Coherence) — consistency of velocity directions within clusters.
- CBDir (Cross-Boundary Direction Correctness) — whether velocities at cluster boundaries point in the expected direction.
Trajectory Analysis
# Forward trajectories from progenitors
velot.tl.compute_trajectories(
adata,
start_cluster="Ngn3 low EP",
direction="forward",
n_trajectories=20,
)
velot.pl.trajectories(adata, color="clusters")
velot.pl.fate_summary(adata)
Benchmarking
VelOT includes a benchmarking framework for comparing velocity methods:
from velot.benchmark import BenchmarkTimer, save_benchmark
timer = BenchmarkTimer()
with timer("velocity"):
velot.tl.velocity(adata)
with timer("evaluate"):
results = velot.metrics.summary(adata, cluster_edges=edges)
save_benchmark(results, timer, model_name="velot", dataset_name="pancreas")
# Compare across methods and datasets
from velot.benchmark import benchmark_dotplot
benchmark_dotplot("benchmark_results")
Built-in Datasets
# Real datasets (via scVelo)
adata = velot.datasets.pancreas()
adata = velot.datasets.erythroid()
adata = velot.datasets.dentategyrus()
# Synthetic datasets
adata = velot.datasets.synthetic_linear(densities=[200, 200, 200])
adata = velot.datasets.synthetic_bifurcation()
adata = velot.datasets.synthetic_cycle()
Documentation
Full API documentation: velot.readthedocs.io
For the detailed mathematical methodology, see the Methods section of the documentation or the accompanying paper.
Reproducibility
Scripts to reproduce all figures and benchmarks from the paper are in
the article/ directory:
# Reproduce a specific dataset analysis
python article/real_pancreas_dataset.py
# Reproduce benchmark results
python article/benchmark/real/pancreas_velot.py
python article/benchmark/real/pancreas_scvelo_dynamic.py
# Generate benchmark figures
jupyter notebook article/benchmark/benchmark_figures.ipynb
Citation
If you use VelOT in your research, please cite:
@article{velot2026,
title = {VelOT: kinetic-free RNA velocity inference via optimal transport,
flow-field smoothing, and VAMP coarse-graining of cellular dynamics},
author = {Rincon de la Rosa, Lucas},
journal = {bioRxiv},
year = {2026},
doi = {10.1101/2026.XX.XX.XXXXXX}
}
License
VelOT is released under the MIT License.
Note on torch: Not listed in dependencies since it requires platform-specific installation (CUDA version). Users install it separately before installing VelOT. An import-time error in
tl.pyalready catches this if torch is missing.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file velot-1.0.0.tar.gz.
File metadata
- Download URL: velot-1.0.0.tar.gz
- Upload date:
- Size: 68.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.20
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6d14ab94bb77f5b87225189add3058f6582e853be5e9013dbb47b12730fa3d51
|
|
| MD5 |
3fc68dde9cdde8ec3b80f402adb42490
|
|
| BLAKE2b-256 |
b000590028775ed57802031f782c71094779cf31f23f1b58b54169f94759e85f
|
File details
Details for the file velot-1.0.0-py3-none-any.whl.
File metadata
- Download URL: velot-1.0.0-py3-none-any.whl
- Upload date:
- Size: 68.3 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.10.20
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bb470b03877e126efe7c361ff41c7e081fcdcff1f83784f299ebbaf90f8a627d
|
|
| MD5 |
17ae9a9e728df4807345910ab8bac5a9
|
|
| BLAKE2b-256 |
80b6510c70343d241ead7890550479f79d10caa143cedf07882be57847f3eb71
|