scVelo — Análisis de Velocidad de ARN
Resumen
scVelo es el paquete líder en Python para el análisis de velocidad de ARN en datos de scRNA-seq. Infiere transiciones de estado celular modelando la cinética del splicing de ARN — utilizando la proporción de abundancias de ARN no empalmado (pre-ARNm) a empalmado (ARNm maduro) para determinar si un gen se está regulando al alza o a la baja en cada célula. Esto permite reconstruir trayectorias de desarrollo e identificar decisiones de destino celular sin necesidad de datos de series temporales.
Instalación: uv pip install scvelo
Recursos clave:
- Documentación: https://scvelo.readthedocs.io/
- GitHub: https://github.com/theislab/scvelo
- Artículo: Bergen et al. (2020) Nature Biotechnology. PMID: 32747759
Cuándo usar esta habilidad
Usa scVelo cuando:
- Inferencia de trayectorias a partir de datos instantáneos: Determinar en qué dirección se están diferenciando las células
- Predicción de destino celular: Identificar células progenitoras y sus destinos posteriores
- Identificación de genes impulsores: Encontrar genes cuya dinámica explica mejor las trayectorias observadas
- Biología del desarrollo: Modelar hematopoyesis, neurogénesis, transiciones epitelio-mesenquimales
- Estimación de tiempo latente: Ordenar células a lo largo de un pseudotiempo derivado de la dinámica de splicing
- Complemento a Scanpy: Añadir información direccional a las proyecciones UMAP
Prerrequisitos
scVelo requiere matrices de recuento tanto para ARN no empalmado como empalmado. Estas se generan mediante:
- STARsolo o kallisto|bustools con modo
lamanno - CLI de velocyto:
velocyto run10x/velocyto run - alevin-fry / simpleaf con salida de empalmado/no empalmado
Los datos se almacenan en un objeto AnnData con layers["spliced"] y layers["unspliced"].
Flujo de trabajo estándar de velocidad de ARN
1. Configuración y carga de datos
import scvelo as scv
import scanpy as sc
import numpy as np
import matplotlib.pyplot as plt
# Configurar opciones
scv.settings.verbosity = 3 # Mostrar pasos de cálculo
scv.settings.presenter_view = True
scv.settings.set_figure_params('scvelo')
# Cargar datos (AnnData con capas spliced/unspliced)
# Opción A: Cargar desde loom (salida de velocyto)
adata = scv.read("cellranger_output.loom", cache=True)
# Opción B: Fusionar loom de velocyto con AnnData procesado con Scanpy
adata_processed = sc.read_h5ad("processed.h5ad") # Tiene UMAP, clústeres
adata_velocity = scv.read("velocyto.loom")
adata = scv.utils.merge(adata_processed, adata_velocity)
# Verificar capas
print(adata)
# obs × var: N × G
# layers: 'spliced', 'unspliced' (requerido)
# obsm['X_umap'] (requerido para visualización)
2. Preprocesamiento
# Filtrar y normalizar. A partir de scVelo 0.3, filter_and_normalize() solo filtra
# genes y normaliza por célula -- ya no toma n_top_genes y ya no
# aplica transformación logarítmica, por lo que el paso de log y la selección de HVG vienen de Scanpy.
scv.pp.filter_and_normalize(
adata,
min_shared_counts=20 # Recuentos mínimos en spliced+unspliced
)
sc.pp.log1p(adata)
sc.pp.highly_variable_genes(adata, n_top_genes=2000, subset=True)
# Calcular momentos de primer y segundo orden (medias y varianzas)
# knn_connectivities debe calcularse primero
sc.pp.neighbors(adata, n_neighbors=30, n_pcs=30)
scv.pp.moments(
adata,
n_pcs=30,
n_neighbors=30
)
3. Estimación de velocidad — Modelo estocástico
El modelo estocástico es rápido y adecuado para análisis exploratorios:
# Velocidad estocástica (más rápida, menos precisa)
scv.tl.velocity(adata, mode='stochastic')
scv.tl.velocity_graph(adata)
# Visualizar
scv.pl.velocity_embedding_stream(
adata,
basis='umap',
color='leiden',
title="Velocidad de ARN (Estocástica)"
)
4. Estimación de velocidad — Modelo dinámico (Recomendado)
El modelo dinámico ajusta la cinética completa de splicing y es más preciso:
# Recuperar dinámica (intensivo computacionalmente; ~10-30 min para 10K células)
scv.tl.recover_dynamics(adata, n_jobs=4)
# Calcular velocidad a partir del modelo dinámico
scv.tl.velocity(adata, mode='dynamical')
scv.tl.velocity_graph(adata)
5. Tiempo latente
El modelo dinámico permite calcular un tiempo latente compartido (pseudotiempo):
# Calcular tiempo latente
scv.tl.latent_time(adata)
# Visualizar tiempo latente en UMAP
scv.pl.scatter(
adata,
color='latent_time',
color_map='gnuplot',
size=80,
title='Tiempo latente'
)
# Identificar genes principales ordenados por tiempo latente
top_genes = adata.var['fit_likelihood'].sort_values(ascending=False).index[:300]
scv.pl.heatmap(
adata,
var_names=top_genes,
sortby='latent_time',
col_color='leiden',
n_convolve=100
)
6. Análisis de genes impulsores
# Identificar genes con mejor ajuste de velocidad
scv.tl.rank_velocity_genes(adata, groupby='leiden', min_corr=0.3)
df = scv.DataFrame(adata.uns['rank_velocity_genes']['names'])
print(df.head(10))
# Velocidad y coherencia
scv.tl.velocity_confidence(adata)
scv.pl.scatter(
adata,
c=['velocity_length', 'velocity_confidence'],
cmap='coolwarm',
perc=[5, 95]
)
# Retratos de fase para genes específicos
scv.pl.velocity(adata, ['Cpe', 'Gnao1', 'Ins2'],
ncols=3, figsize=(16, 4))
7. Flechas de velocidad y pseudotiempo
# Gráfico de flechas en UMAP
scv.pl.velocity_embedding(
adata,
arrow_length=3,
arrow_size=2,
color='leiden',
basis='umap'
)
# Gráfico de flujo (visualización más limpia)
scv.pl.velocity_embedding_stream(
adata,
basis='umap',
color='leiden',
smooth=0.8,
min_mass=4
)
# Pseudotiempo de velocidad (alternativa al tiempo latente)
scv.tl.velocity_pseudotime(adata)
scv.pl.scatter(adata, color='velocity_pseudotime', cmap='gnuplot')
8. Gráfico de trayectoria PAGA
# Gráfico PAGA con transiciones informadas por velocidad
scv.tl.paga(adata, groups='leiden')
df = scv.get_df(adata, 'paga/transitions_confidence', precision=2).T
df.style.background_gradient(cmap='Blues').format('{:.2g}')
# Trazar PAGA con velocidad
scv.pl.paga(
adata,
basis='umap',
size=50,
alpha=0.1,
min_edge_width=2,
node_size_scale=1.5
)
Script de flujo de trabajo completo
import scvelo as scv
import scanpy as sc
def run_rna_velocity(adata, n_top_genes=2000, mode='dynamical', n_jobs=4):
"""
Flujo de trabajo completo de velocidad de ARN.
Args:
adata: AnnData con capas 'spliced' y 'unspliced', UMAP en obsm
n_top_genes: Número de genes altamente variables principales para velocidad
mode: 'stochastic' (rápido) o 'dynamical' (preciso)
n_jobs: Trabajos paralelos para el modelo dinámico
Returns:
AnnData procesado con información de velocidad
"""
scv.settings.verbosity = 2
# 1. Preprocesamiento (scVelo 0.3 eliminó log/HVG de filter_and_normalize)
scv.pp.filter_and_normalize(adata, min_shared_counts=20)
sc.pp.log1p(adata)
sc.pp.highly_variable_genes(adata, n_top_genes=n_top_genes, subset=True)
if 'neighbors' not in adata.uns:
sc.pp.neighbors(adata, n_neighbors=30)
scv.pp.moments(adata, n_pcs=30, n_neighbors=30)
# 2. Estimación de velocidad
if mode == 'dynamical':
scv.tl.recover_dynamics(adata, n_jobs=n_jobs)
scv.tl.velocity(adata, mode=mode)
scv.tl.velocity_graph(adata)
# 3. Análisis posteriores
if mode == 'dynamical':
scv.tl.latent_time(adata)
scv.tl.rank_velocity_genes(adata, groupby='leiden', min_corr=0.3)
scv.tl.velocity_confidence(adata)
scv.tl.velocity_pseudotime(adata)
return adata
Campos clave de salida en AnnData
Después de ejecutar el flujo de trabajo, se añaden los siguientes campos:
| Ubicación | Clave | Descripción |
|---|---|---|
adata.layers | velocity | Velocidad de ARN por gen por célula |
adata.layers | fit_t | Tiempo latente ajustado por gen por célula |
adata.obsm | velocity_umap | Vectores de velocidad 2D en UMAP |
adata.obs | velocity_pseudotime | Pseudotiempo derivado de la velocidad |
adata.obs | latent_time | Tiempo latente del modelo dinámico |
adata.obs | velocity_length | Velocidad de cada célula |
adata.obs | velocity_confidence | Puntuación de confianza por célula |
adata.var | fit_likelihood | Calidad del ajuste del modelo por gen |
adata.var | fit_alpha | Tasa de transcripción |
adata.var | fit_beta | Tasa de splicing |
adata.var | fit_gamma | Tasa de degradación |
adata.uns | velocity_graph | Matriz de probabilidades de transición célula-célula |
Comparación de modelos de velocidad
| Modelo | Velocidad | Precisión | Cuándo usarlo |
|---|---|---|---|
stochastic | Rápido | Moderada | Exploratorio; conjuntos de datos grandes |
deterministic | Medio | Moderada | Cinética lineal simple |
dynamical | Lento | Alta | Calidad de publicación; identifica genes impulsores |
Mejores prácticas
- Comienza con el modo estocástico para exploración; cambia a dinámico para el análisis final
- Buena cobertura de lecturas no empalmadas: Las lecturas cortas (< 100 pb) pueden perder cobertura de intrones
- Mínimo 2,000 células: La velocidad de ARN es ruidosa con menos células
- La velocidad debe ser coherente: Las flechas deben seguir la biología conocida; la aleatoriedad indica problemas
- El ancho de banda k-NN importa: Demasiados pocos vecinos → velocidad ruidosa; demasiados → demasiado suavizada
- Verificación de cordura: Las células raíz (progenitoras) deben tener altas proporciones de no empalmado/empalmado para genes marcadores
- El modelo dinámico requiere estados cinéticos distintos: Funciona mejor para procesos de diferenciación claros
Solución de problemas
| Problema | Solución |
|---|---|
| Falta la capa de no empalmado | Vuelve a ejecutar velocyto o usa STARsolo con --soloFeatures Gene Velocyto |
| Muy pocos genes de velocidad | Reduce min_shared_counts; verifica la profundidad de secuenciación |
| Flechas con apariencia aleatoria | Prueba diferentes valores de n_neighbors o modelo de velocidad |
| Error de memoria con el modelo dinámico | Establece n_jobs=1; reduce n_top_genes |
| Velocidad negativa en todas partes | Verifica que las capas spliced/unspliced no estén intercambiadas |
Recursos adicionales
- Documentación de scVelo: https://scvelo.readthedocs.io/
- Tutoriales: https://scvelo.readthedocs.io/tutorials/
- GitHub: https://github.com/theislab/scvelo
- Artículo: Bergen V et al. (2020) Nature Biotechnology. PMID: 32747759
- velocyto (preprocesamiento): http://velocyto.org/
- CellRank (predicción de destino, extiende scVelo): https://cellrank.readthedocs.io/
- dynamo (alternativa de marcaje metabólico): https://dynamo-release.readthedocs.io/