scVeloR implements three velocity estimation models, each with distinct assumptions and use cases. This vignette provides a comprehensive comparison to help you choose the appropriate model for your data.
Assumption: Cells are near transcriptional equilibrium.
Key equation: \[\gamma \approx \frac{\beta u}{s}\]
Velocity: \[v_s = \beta u - \gamma s\]
Pros: - Fast computation - Requires minimal data - Works well for slowly changing processes
Cons: - May miss transient dynamics - Assumes equilibrium
Assumption: Accounts for transcriptional bursting and noise.
Uses: First and second-order moments (mean, variance, covariance)
Pros: - More robust to noise - Better for bursty transcription - Intermediate computational cost
Cons: - Still assumes near-equilibrium - Requires sufficient cell numbers
Assumption: Full kinetics without equilibrium constraint.
Inferred parameters: α (transcription), β (splicing), γ (degradation), t_ (switching time)
Pros: - Captures transient states - Infers absolute time - Most accurate for complex dynamics
Cons: - Computationally intensive - Requires high-quality data - May overfit small datasets
| Feature | Steady-State | Stochastic | Dynamical |
|---|---|---|---|
| Speed | ~1 min | ~5 min | ~30 min |
| Data requirement | Low | Medium | High |
| Parameters inferred | γ only | γ only | α, β, γ, t_ |
| Handles transient states | No | Partial | Yes |
| Provides latent time | No | No | Yes |
| Recommended dataset size | >1,000 cells | >3,000 cells | >5,000 cells |
| Best for | Exploration | Default choice | Publication |
Velocity vectors from different models showing varying sensitivity to dynamics.
Phase portraits showing how each model fits the data.
Distribution of R² values indicating model fit quality.
Computational time comparison across dataset sizes.
library(scVeloR)
# 1. Start with steady-state for quick exploration
seurat_obj <- velocity(seurat_obj, mode = "deterministic")
plot_velocity(seurat_obj)
# 2. If results look promising, try stochastic
seurat_obj <- velocity(seurat_obj, mode = "stochastic")
plot_velocity(seurat_obj)
# 3. For final analysis, use dynamical
seurat_obj <- velocity(seurat_obj, mode = "dynamical")
plot_velocity(seurat_obj)
# 4. Compare results
velocity_summary(seurat_obj)sessionInfo()
#> R version 4.6.0 (2026-04-24)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 24.04.4 LTS
#>
#> Matrix products: default
#> BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
#> LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.26.so; LAPACK version 3.12.0
#>
#> locale:
#> [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
#> [3] LC_TIME=en_US.UTF-8 LC_COLLATE=en_US.UTF-8
#> [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
#> [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
#> [9] LC_ADDRESS=C LC_TELEPHONE=C
#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
#>
#> time zone: Etc/UTC
#> tzcode source: system (glibc)
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] tidyr_1.3.2 gridExtra_2.3 ggplot2_4.0.3 rmarkdown_2.31
#>
#> loaded via a namespace (and not attached):
#> [1] gtable_0.3.6 jsonlite_2.0.0 dplyr_1.2.1 compiler_4.6.0
#> [5] tidyselect_1.2.1 jquerylib_0.1.4 scales_1.4.0 yaml_2.3.12
#> [9] fastmap_1.2.0 R6_2.6.1 labeling_0.4.3 generics_0.1.4
#> [13] knitr_1.51 tibble_3.3.1 maketools_1.3.2 bslib_0.11.0
#> [17] pillar_1.11.1 RColorBrewer_1.1-3 rlang_1.2.0 cachem_1.1.0
#> [21] xfun_0.57 sass_0.4.10 sys_3.4.3 S7_0.2.2
#> [25] otel_0.2.0 viridisLite_0.4.3 cli_3.6.6 withr_3.0.2
#> [29] magrittr_2.0.5 digest_0.6.39 grid_4.6.0 lifecycle_1.0.5
#> [33] vctrs_0.7.3 evaluate_1.0.5 glue_1.8.1 farver_2.1.2
#> [37] buildtools_1.0.0 purrr_1.2.2 tools_4.6.0 pkgconfig_2.0.3
#> [41] htmltools_0.5.9