scVelo — Analyse de la vélocité ARN
Vue d'ensemble
scVelo est le principal package Python pour l'analyse de la vélocité ARN dans les données de séquençage ARN en cellule unique (scRNA-seq). Il infère les transitions d'état cellulaire en modélisant la cinétique de l'épissage des ARNm — en utilisant le rapport entre les abondances d'ARN non épissé (pré-ARNm) et d'ARN épissé (ARNm mature) pour déterminer si un gène est régulé positivement ou négativement dans chaque cellule. Cela permet la reconstruction de trajectoires développementales et l'identification des décisions de destin cellulaire sans nécessiter de données temporelles.
Installation : uv pip install scvelo
Ressources clés :
- Documentation : https://scvelo.readthedocs.io/
- GitHub : https://github.com/theislab/scvelo
- Article : Bergen et al. (2020) Nature Biotechnology. PMID : 32747759
Quand utiliser cette compétence
Utilisez scVelo lorsque :
- Inférence de trajectoire à partir de données instantanées : Déterminez dans quelle direction les cellules se différencient
- Prédiction du destin cellulaire : Identifiez les cellules progénitrices et leurs devenirs en aval
- Identification des gènes moteurs : Trouvez les gènes dont la dynamique explique le mieux les trajectoires observées
- Biologie du développement : Modélisez l'hématopoïèse, la neurogenèse, les transitions épithélio-mésenchymateuses
- Estimation du temps latent : Ordonnez les cellules le long d'un pseudo-temps dérivé de la dynamique d'épissage
- Complément à Scanpy : Ajoutez des informations directionnelles aux intégrations UMAP
Prérequis
scVelo nécessite des matrices de comptage pour l'ARN non épissé et épissé. Elles sont générées par :
- STARsolo ou kallisto|bustools avec le mode
lamanno - velocyto CLI :
velocyto run10x/velocyto run - alevin-fry / simpleaf avec sortie épissé/non épissé
Les données sont stockées dans un objet AnnData avec layers["spliced"] et layers["unspliced"].
Flux de travail standard de la vélocité ARN
1. Configuration et chargement des données
import scvelo as scv
import scanpy as sc
import numpy as np
import matplotlib.pyplot as plt
# Configurer les paramètres
scv.settings.verbosity = 3 # Afficher les étapes de calcul
scv.settings.presenter_view = True
scv.settings.set_figure_params('scvelo')
# Charger les données (AnnData avec couches épissé/non épissé)
# Option A : Charger depuis un fichier loom (sortie velocyto)
adata = scv.read("cellranger_output.loom", cache=True)
# Option B : Fusionner le fichier loom velocyto avec l'AnnData traitée par Scanpy
adata_processed = sc.read_h5ad("processed.h5ad") # Contient UMAP, clusters
adata_velocity = scv.read("velocyto.loom")
adata = scv.utils.merge(adata_processed, adata_velocity)
# Vérifier les couches
print(adata)
# obs × var : N × G
# layers : 'spliced', 'unspliced' (requis)
# obsm['X_umap'] (requis pour la visualisation)
2. Prétraitement
# Filtrer et normaliser. Depuis scVelo 0.3, filter_and_normalize() filtre
# uniquement les gènes et normalise par cellule -- elle ne prend plus n_top_genes et ne
# fait plus de transformation log, donc l'étape log et la sélection HVG viennent de Scanpy.
scv.pp.filter_and_normalize(
adata,
min_shared_counts=20 # Comptes minimums dans épissé+non épissé
)
sc.pp.log1p(adata)
sc.pp.highly_variable_genes(adata, n_top_genes=2000, subset=True)
# Calculer les moments du premier et du second ordre (moyennes et variances)
# knn_connectivities doit d'abord être calculé
sc.pp.neighbors(adata, n_neighbors=30, n_pcs=30)
scv.pp.moments(
adata,
n_pcs=30,
n_neighbors=30
)
3. Estimation de la vélocité — Modèle stochastique
Le modèle stochastique est rapide et adapté à l'analyse exploratoire :
# Vélocité stochastique (plus rapide, moins précise)
scv.tl.velocity(adata, mode='stochastic')
scv.tl.velocity_graph(adata)
# Visualiser
scv.pl.velocity_embedding_stream(
adata,
basis='umap',
color='leiden',
title="Vélocité ARN (Stochastique)"
)
4. Estimation de la vélocité — Modèle dynamique (Recommandé)
Le modèle dynamique ajuste la cinétique d'épissage complète et est plus précis :
# Récupérer la dynamique (intensif en calcul ; ~10-30 min pour 10K cellules)
scv.tl.recover_dynamics(adata, n_jobs=4)
# Calculer la vélocité à partir du modèle dynamique
scv.tl.velocity(adata, mode='dynamical')
scv.tl.velocity_graph(adata)
5. Temps latent
Le modèle dynamique permet le calcul d'un temps latent partagé (pseudo-temps) :
# Calculer le temps latent
scv.tl.latent_time(adata)
# Visualiser le temps latent sur UMAP
scv.pl.scatter(
adata,
color='latent_time',
color_map='gnuplot',
size=80,
title='Temps latent'
)
# Identifier les meilleurs gènes ordonnés par temps latent
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. Analyse des gènes moteurs
# Identifier les gènes avec le meilleur ajustement de vélocité
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))
# Vitesse et cohérence
scv.tl.velocity_confidence(adata)
scv.pl.scatter(
adata,
c=['velocity_length', 'velocity_confidence'],
cmap='coolwarm',
perc=[5, 95]
)
# Portraits de phase pour des gènes spécifiques
scv.pl.velocity(adata, ['Cpe', 'Gnao1', 'Ins2'],
ncols=3, figsize=(16, 4))
7. Flèches de vélocité et pseudo-temps
# Graphique de flèches sur UMAP
scv.pl.velocity_embedding(
adata,
arrow_length=3,
arrow_size=2,
color='leiden',
basis='umap'
)
# Graphique de flux (visualisation plus propre)
scv.pl.velocity_embedding_stream(
adata,
basis='umap',
color='leiden',
smooth=0.8,
min_mass=4
)
# Pseudo-temps de vélocité (alternative au temps latent)
scv.tl.velocity_pseudotime(adata)
scv.pl.scatter(adata, color='velocity_pseudotime', cmap='gnuplot')
8. Graphe de trajectoire PAGA
# Graphe PAGA avec transitions informées par la vélocité
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}')
# Tracer PAGA avec vélocité
scv.pl.paga(
adata,
basis='umap',
size=50,
alpha=0.1,
min_edge_width=2,
node_size_scale=1.5
)
Script de flux de travail complet
import scvelo as scv
import scanpy as sc
def run_rna_velocity(adata, n_top_genes=2000, mode='dynamical', n_jobs=4):
"""
Flux de travail complet de la vélocité ARN.
Args :
adata : AnnData avec les couches 'spliced' et 'unspliced', UMAP dans obsm
n_top_genes : Nombre de meilleurs HVGs pour la vélocité
mode : 'stochastic' (rapide) ou 'dynamical' (précis)
n_jobs : Tâches parallèles pour le modèle dynamique
Retourne :
AnnData traité avec les informations de vélocité
"""
scv.settings.verbosity = 2
# 1. Prétraitement (scVelo 0.3 a supprimé 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. Estimation de la vélocité
if mode == 'dynamical':
scv.tl.recover_dynamics(adata, n_jobs=n_jobs)
scv.tl.velocity(adata, mode=mode)
scv.tl.velocity_graph(adata)
# 3. Analyses en aval
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
Champs de sortie clés dans AnnData
Après avoir exécuté le flux de travail, les champs suivants sont ajoutés :
| Emplacement | Clé | Description |
|---|---|---|
adata.layers | velocity | Vélocité ARN par gène par cellule |
adata.layers | fit_t | Temps latent ajusté par gène par cellule |
adata.obsm | velocity_umap | Vecteurs de vélocité 2D sur UMAP |
adata.obs | velocity_pseudotime | Pseudo-temps issu de la vélocité |
adata.obs | latent_time | Temps latent issu du modèle dynamique |
adata.obs | velocity_length | Vitesse de chaque cellule |
adata.obs | velocity_confidence | Score de confiance par cellule |
adata.var | fit_likelihood | Qualité d'ajustement du modèle au niveau du gène |
adata.var | fit_alpha | Taux de transcription |
adata.var | fit_beta | Taux d'épissage |
adata.var | fit_gamma | Taux de dégradation |
adata.uns | velocity_graph | Matrice de probabilité de transition cellule-cellule |
Comparaison des modèles de vélocité
| Modèle | Vitesse | Précision | Quand l'utiliser |
|---|---|---|---|
stochastic | Rapide | Modérée | Exploratoire ; grands ensembles de données |
deterministic | Moyenne | Modérée | Cinétique linéaire simple |
dynamical | Lente | Élevée | Qualité publication ; identifie les gènes moteurs |
Bonnes pratiques
- Commencez par le mode stochastique pour l'exploration ; passez au mode dynamique pour l'analyse finale
- Besoin d'une bonne couverture des lectures non épissées : Les lectures courtes (< 100 pb) peuvent manquer la couverture des introns
- Minimum 2 000 cellules : La vélocité ARN est bruyante avec moins de cellules
- La vélocité doit être cohérente : Les flèches doivent suivre la biologie connue ; le caractère aléatoire indique des problèmes
- La largeur de bande k-NN est importante : Trop peu de voisins → vélocité bruyante ; trop → sur-lissage
- Vérification de cohérence : Les cellules racines (progéniteurs) doivent avoir des rapports non épissé/épissé élevés pour les gènes marqueurs
- Le modèle dynamique nécessite des états cinétiques distincts : Fonctionne mieux pour des processus de différenciation clairs
Dépannage
| Problème | Solution |
|---|---|
| Couche non épissée manquante | Réexécutez velocyto ou utilisez STARsolo avec --soloFeatures Gene Velocyto |
| Très peu de gènes de vélocité | Abaissez min_shared_counts ; vérifiez la profondeur de séquençage |
| Flèches d'apparence aléatoire | Essayez différents n_neighbors ou modèle de vélocité |
| Erreur de mémoire avec le modèle dynamique | Définissez n_jobs=1 ; réduisez n_top_genes |
| Vélocité négative partout | Vérifiez que les couches épissé/non épissé ne sont pas inversées |
Ressources supplémentaires
- Documentation scVelo : https://scvelo.readthedocs.io/
- Carnets de tutoriels : https://scvelo.readthedocs.io/tutorials/
- GitHub : https://github.com/theislab/scvelo
- Article : Bergen V et al. (2020) Nature Biotechnology. PMID : 32747759
- velocyto (prétraitement) : http://velocyto.org/
- CellRank (prédiction de destin, étend scVelo) : https://cellrank.readthedocs.io/
- dynamo (alternative au marquage métabolique) : https://dynamo-release.readthedocs.io/