基于Seurat UAMP和celltype的RNA Velocity速率分析的全套流程

参考资料:
参考生物技能树
Velocyto官网Tutorial
scvelo实战教程
Seurat-to-RNA-Velocity
分析步骤:
本教程是velocyto基于Seurat对象中UMAP和细胞类型进行RNA速率分析,推断细胞Cluster命运的状态(过渡与稳定)和分化方向性(轨迹)。
第一步:在linux系统中用velocyto将bam文件转换成loom文件;
第二步:按照scvelo需要的格式获取seurat中的UMAP坐标和Celltype信息;
第三步:在 python程序中整合loom文件和UMAP坐标和Celltype数据,并进行下游速率分析。

1、将bam文件转换成loom文件(Linux系统操作)

1.1 conda安装velocyto的一些依赖

需要一些依赖

conda create -n velocyto 
conda activate velocyto 
conda install samtools
conda install numpy scipy cython numba matplotlib scikit-learn h5py click
pip install pysam
pip install velocyto

Successfully installed loompy-3.0.6 numpy-groupies-0.9.13 pandas-1.2.5 pytz-2021.1 velocyto-0.17.17

1.2 下载特定物种的特殊gtf文件(这个步骤是可选的)

你如果要屏蔽repetetive elements,可以使用这一步骤
我们这个单细胞转录组使用cellranger流程的话,需要重复数据的gtf文件,rmsk。
进入UCSC官网,在Tools菜单中打开Table Brower,选择目的物种以及个性化的需求

1650200197137.jpg

1.3 bam文件循环进行sort

理论上,这下一步命令,就可以完成bam转换成loom文件,但是因为 samtools问题,上面的流程可能是会失败。这个时候可以自行先运行 samtools sort 命令处理得到 cellsorted_possorted_genome_bam.bam 文件。

 ls  */outs/possorted_genome_bam.bam|while read id
do  new=${id/possorted_genome_bam.bam/cellsorted_possorted_genome_bam.bam}
echo $new 
samtools sort -@ 4  -t CB -O BAM -o $new   $id  
 done
1.4 bam文件循环运行velocyto
#! /bin/sh
rmsk_gtf=/lustre/home/acct-medxh/medxh/sccdata/Rawdata/reference/hg38_repeat_rmsk.gtf # 从genome.ucsc.edu下载 
cellranger_outDir=/lustre/home/acct-medxh/medxh/sccdata/Rawdata/output_EC3 # 这个输出目录可以随便选择文件夹,但是最后一个文件夹决定了loom的细胞名字如”output_EU1:TTTCCTCAGTCCGCGTx“,所以output_EU1尽量为样品名
cellranger_gtf=/lustre/home/acct-medxh/medxh/yard/reference/refdata-gex-GRCh38-2020-A/genes/genes.gtf # 这个是cellranger官网提供的
ls -lh $rmsk_gtf  $cellranger_outDir $cellranger_gtf
ls -d *-*|while read cellranger_outDir
do 
velocyto run10x -m $rmsk_gtf  $cellranger_outDir $cellranger_gtf 
done

2、Seurat UMAP和Celltype提取(R和python)

参考官网https://scvelo.readthedocs.io/getting_started/

2.1 提取seurat中的cells、UMAP、celltype (R studio)
setwd("~/Desktop/bioinformation/End_analysis/velocyto")
library(dplyr)
library(ggplot2)
library(cowplot)
library(patchwork)
suppressMessages(library(Seurat))
End.combined <- readRDS("~/Desktop/bioinformation/End_analysis/End.combined.rds")
2.2 提取对象
table(End.combined$group)
Idents(object=End.combined)<-End.combined$group
Eutopic<-subset(End.combined, idents = c("Eutopic"), invert = F)
2.3 修改Cells名字(”ATCCCTGTCACTGAAC-1_1")保持和loom中cell ID("output_EU3:TTTGACTGTTGCCGACx")一致
df<-data.frame(Cells=Cells(Eutopic),sample=paste("output_EU",Eutopic$sampleID,sep = ""))#制做data.frame,含有cells和output_EU3
df$id<-sapply(df$Cells,function(x)paste(unlist(strsplit(x, "-"))[1],"x",sep = ""))#将“-”之前的字符和“x”连接
df$Cells<-paste(df$sample,df$id,sep = ":")#将“output_EU3”和Cells通过“:”连接
write.csv(df$Cells, file = "cellID_obs.csv", row.names = FALSE) #提取修改后的cell ID

cell_embeddings<-Embeddings(Eutopic, reduction = "umap")#使用Embeddings功能提取seurat UMAP或者TSNE
rownames(cell_embeddings)<-df$Cells #修改rowname的名字使其和cell ID一致
write.csv(cell_embeddings, file = "cell_embeddings.csv")
clusters_obs<-Eutopic$celltype.1 #提取celltype
names(clusters_obs)<-df$Cells #修改名字和保持cell ID一致
write.csv(clusters_obs, file = "clusters_obs.csv")

3、anndata导入loom文件和Seurat中meta-data并进行下游速率分析(多样本整合)

3.1加载依赖包
cona activate velocyto
python
import anndata
import scvelo as scv
import pandas as pd
import numpy as np
import matplotlib as plt
3.2 读取每个样品中的loom文件
sample_one = anndata.read_loom("/Users/linyu1/Desktop/bioinformation/End_analysis/velocyto/output_EU1.loom")
##Variable names are not unique. To make them unique, call `.var_names_make_unique`.
sample_one.var_names_make_unique()
sample_one
##AnnData object with n_obs × n_vars = 5992 × 36601
#    obs: 'Clusters', '_X', '_Y'
#   var: 'Accession', 'Chromosome', 'End', 'Start', 'Strand'
#    layers: 'matrix', 'ambiguous', 'spliced', 'unspliced'
sample_two = anndata.read_loom("/Users/linyu1/Desktop/bioinformation/End_analysis/velocyto/output_EU2.loom")
sample_two.var_names_make_unique()
sample_three = anndata.read_loom("/Users/linyu1/Desktop/bioinformation/End_analysis/velocyto/output_EU3.loom")
sample_three.var_names_make_unique()
3.3 读取seurat中cells、UMAP和celltype的信息
sample_obs = pd.read_csv("/Users/linyu1/Desktop/bioinformation/End_analysis/velocyto/cellID_obs.csv")
umap = pd.read_csv("/Users/linyu1/Desktop/bioinformation/End_analysis/velocyto/cell_embeddings.csv")
cell_clusters = pd.read_csv("/Users/linyu1/Desktop/bioinformation/End_analysis/velocyto/clusters_obs.csv")
3.4 在每个样品loom中过滤出seurat中选择的Cell ID
sample_one = sample_one[np.isin(sample_one.obs.index,sample_obs["x"])]
sample_two = sample_two[np.isin(sample_two.obs.index,sample_obs["x"])]
sample_three = sample_three[np.isin(sample_three.obs.index,sample_obs["x"])]
3.5 将过滤后的文件整合成一个文件
adata = sample_one.concatenate(sample_two, sample_three)
3.6 将umap坐标和celltype添加到anndata 对象中

需要确保我们添加umapCell ID和anndata对象中的Cell ID的顺序完全匹配,Cell ID是对象的观察层中的行名,因此我们可以使用以下方法更改
一步、我们把index提取成表达矩阵并更改列名;
二步、由于多个样品合并成adata时Cell ID后面多了“-0”(如下图),为了完全匹配Cell ID,通过apply和split去除“-0”(保证adata和seurat中barcode名字相同);
三步、umap坐标和celltype添加到anndata 对象。

adata_index = pd.DataFrame(adata.obs.index)
adata_index = adata_index.rename(columns = {0:'Cell ID'})
adata_index = adata_index.rename(columns = {"CellID":'Cell ID'})

rep=lambda x : x.split("-")[0]
adata_index["Cell ID"]=adata_index["Cell ID"].apply(rep)

umap = umap.rename(columns = {'Unnamed: 0':'Cell ID'})#更改umap的列名统一相同的列名Cell ID
umap = umap[np.isin(umap["Cell ID"],adata_index["Cell ID"])] #过滤adata_index在umap中的cell ID
umap=umap.drop_duplicates(subset=["Cell ID"]) #去除重复值
umap_ordered = adata_index.merge(umap, on = "Cell ID")#依据adata_index Cell ID顺序与umap的数据进行合并
umap_ordered = umap_ordered.iloc[:,1:] #去除umap_ordered中的第一列
adata.obsm['X_umap'] = umap_ordered.values #将UMAP并入到adata对象中


cell_clusters=cell_clusters.iloc[:,1:]
cell_clusters = cell_clusters.rename(columns = {'cell':'Cell ID'})
cell_clusters = cell_clusters[np.isin(cell_clusters["Cell ID"],adata_index["Cell ID"])]
cell_clusters=cell_clusters.drop_duplicates(subset=["Cell ID"]) #去除重复值
cell_clusters_ordered = adata_index.merge(cell_clusters, on = "Cell ID")
cell_clusters_ordered = cell_clusters_ordered.iloc[:,1:]
adata.obs['clusters']=cell_clusters_ordered.values
3.8 运行RNA Velocity

我们现在可以运行scVelo命令,并根据Seurat UMAP坐标生成RNA速度图

scv.pp.filter_and_normalize(adata)
scv.pp.moments(adata)
scv.tl.velocity(adata, mode = "stochastic")
scv.tl.velocity_graph(adata)
3.9 spliced/unspliced的比例
scv.pl.proportions(adata)
splice.png
3.10 可视化
scv.pl.velocity_embedding(adata, basis = 'umap')
2.png
scv.pl.velocity_embedding_stream(adata, basis = 'umap')
3.png
3.11 解释velocities

这可能是最重要的部分,因为我们建议用户不要将生物学结论局限于预测的速度,而是通过阶段画像来检查个体基因动力学,以了解推断的方向是如何由特定基因支持的。

参考下图思考如何解释spliced vs. unspliced 时相特征[图1.6a]。基因活性是由转录调控调控的。对特定基因的转录的诱导表达,会导致前体unspliced mRNAs 的增加,而相反地,转录抑制或缺失会导致unspliced mRNAs 的减少。spliced mRNA由未剪接的unspliced的mRNA产生,具有相同的趋势,但存在时间滞后。时间是一个隐藏/潜在的变量。因此,动力学需要从实际测量的东西来推断: 在相位图中显示的剪接和未剪接的mrna。


图1.6a

用scv.pl.velocity(adata, gene_names检查某些特定基因的时相特征

scv.pl.velocity(adata, ['Cpe',  'Gnao1', 'Ins2', 'Adk'], ncols=2)
图1.6b

黑线对应于估计的“稳态”比率,即处于恒定转录状态的spliced 和 unspliced mRNA丰度之比。一个特定基因的RNA速度是由残差决定的,即观察值偏离稳态线的程度。正速度表明一个基因被上调,这种现象发生在细胞中,在稳定状态下,该基因的unspliced mRNA的丰度高于预期。相反,负速度表明基因被下调。

例如,Cpe解释了上调的Ngn3(黄色)向Pre-endocrine(橙色)向β-cells(绿色)的方向,而Adk解释了下调的Ductal(深绿色)向Ngn3(黄色)向其余内分泌细胞的方向。

scv.pl.scatter(adata, 'Cpe', color=['clusters', 'velocity'],
               add_outline='Ngn3 high EP, Pre-endocrine, Beta')
3.12 鉴定重要基因

我们需要一个系统的方法来识别基因,这可能有助于解释最终的向量场和推断的谱系。为了做到这一点,我们可以测试哪些基因具有集群特有的差异速度表达,与其他种群相比显著地更高或更低。模块scv.tl.rank_velocity_genes运行一个差分速度t检验,并为每个集群输出一个基因排名。可以设置阈值(例如min_corr)来限制对候选基因的测试。

scv.tl.rank_velocity_genes(adata, groupby='clusters', min_corr=.3)

df = scv.DataFrame(adata.uns['rank_velocity_genes']['names'])
df.head()
kwargs = dict(frameon=False, size=10, linewidth=1.5,
              add_outline='Ngn3 high EP, Pre-endocrine, Beta')

scv.pl.scatter(adata, df['Ngn3 high EP'][:5], ylabel='Ngn3 high EP', **kwargs)
scv.pl.scatter(adata, df['Pre-endocrine'][:5], ylabel='Pre-endocrine', **kwargs)

例如,基因Ptprs、Pclo、Pam、Abcc8、Gnas支持从Ngn3高EP(黄色)到Pre-endocrine(橙色)再到Beta(绿色)的方向性。

3.13 细胞周期的Velocities分析

由RNA速度检测的细胞周期,在生物学上由细胞周期分数(阶段标志基因平均表达水平的标准化分数) 确定。

scv.tl.score_genes_cell_cycle(adata)
scv.pl.scatter(adata, color_gradients=['S_score', 'G2M_score'], smooth=True, perc=[5, 95])
s_genes, g2m_genes = scv.utils.get_phase_marker_genes(adata)
s_genes = scv.get_df(adata[:, s_genes], 'spearmans_score', sort_values=True).index
g2m_genes = scv.get_df(adata[:, g2m_genes], 'spearmans_score', sort_values=True).index

kwargs = dict(frameon=False, ylabel='cell cycle genes')
scv.pl.scatter(adata, list(s_genes[:2]) + list(g2m_genes[:3]), **kwargs)

特别是hell和Top2a非常适合解释周期祖先中的向量场。Top2a在G2M阶段达到峰值前不久被赋予了一个高速。在这里,负的速度与紧随其后的下调完全匹配。

scv.pl.velocity(adata, ['Hells', 'Top2a'], ncols=2, add_outline=True)
3.14 速度和一致性

两个更有用的stats:-速度或分化率是由速度矢量的长度给出的。-矢量场的一致性(即,速度矢量如何与其邻近速度相关联)提供了一个可信度的度量。

scv.tl.velocity_confidence(adata)
keys = 'velocity_length', 'velocity_confidence'
scv.pl.scatter(adata, c=keys, cmap='coolwarm', perc=[5, 95])

这些提供了细胞在哪里以较慢/较快的速度分化
在集群水平上,我们发现分化在细胞周期退出(Ngn3 low EP)后显著加快,在Beta细胞生产期间保持速度,而在Alpha细胞生产期间减慢速度。

df = adata.obs.groupby('clusters')[keys].mean().T
df.style.background_gradient(cmap='coolwarm', axis=1)

3.15 动力学模型

它在一个基于可能性的期望最大化框架中解决,通过迭代估计反应速率和潜在细胞特异性变量的参数,即转录状态和细胞内部潜伏时间。因此,它的目的是了解每个基因未拼接/已拼接阶段的轨迹。

scv.tl.recover_dynamics(adata)
scv.tl.velocity(adata, mode='dynamical')
scv.tl.velocity_graph(adata)
#adata.write('data/pancreas.h5ad', compression='gzip')
#adata = scv.read('data/pancreas.h5ad')
scv.pl.velocity_embedding_stream(adata, basis='umap')
3.16 动率参数

在不需要任何实验数据的情况下,可以估计RNA转录、剪接和降解的速率。
它们有助于更好地理解细胞的特性和表型异质性。

df = adata.var
df = df[(df['fit_likelihood'] > .1) & df['velocity_genes'] == True]

kwargs = dict(xscale='log', fontsize=16)
with scv.GridSpec(ncols=3) as pl:
    pl.hist(df['fit_alpha'], xlabel='transcription rate', **kwargs)
    pl.hist(df['fit_beta'] * df['fit_scaling'], xlabel='splicing rate', xticks=[.1, .4, 1], **kwargs)
    pl.hist(df['fit_gamma'], xlabel='degradation rate', xticks=[.1, .4, 1], **kwargs)

scv.get_df(adata, 'fit*', dropna=True).head()

The estimated gene-specific parameters comprise rates of transription (fit_alpha), splicing (fit_beta), degradation (fit_gamma), switching time point (fit_t_), a scaling parameter to adjust for under-represented unspliced reads (fit_scaling), standard deviation of unspliced and spliced reads (fit_std_u, fit_std_s), the gene likelihood (fit_likelihood), inferred steady-state levels (fit_steady_u, fit_steady_s) with their corresponding p-values (fit_pval_steady_u, fit_pval_steady_s), the overall model variance (fit_variance), and a scaling factor to align the gene-wise latent times to a universal, gene-shared latent time (fit_alignment_scaling).

3.17 逆时分析

动态模型恢复了潜在细胞过程的潜在时间。这一潜伏时间代表了细胞的内部时钟,仅根据其转录动力学,与细胞分化时所经历的实时时间近似。

scv.tl.latent_time(adata)
scv.pl.scatter(adata, color='latent_time', color_map='gnuplot', size=80)
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='clusters', n_convolve=100)
2.3 Top-likelihood基因

驱动基因表现出明显的动态行为,并通过动态模型中的高可能性对其特征进行系统地检测。

top_genes = adata.var['fit_likelihood'].sort_values(ascending=False).index
scv.pl.scatter(adata, basis=top_genes[:15], ncols=5, frameon=False)
var_names = ['Actn4', 'Ppp3ca', 'Cpe', 'Nnat']
scv.pl.scatter(adata, var_names, frameon=False)
scv.pl.scatter(adata, x='latent_time', y=var_names, frameon=False)
3.18 Cluster-specific top-likelihood 基因

此外,可以计算每个细胞集群的部分基因可能性,以实现集群特异性识别潜在驱动因素。

scv.tl.rank_dynamical_genes(adata, groupby='clusters')
df = scv.get_df(adata, 'rank_dynamical_genes/names')
df.head(5)
for cluster in ['Ductal', 'Ngn3 high EP', 'Pre-endocrine', 'Beta']:
    scv.pl.scatter(adata, df[cluster][:5], ylabel=cluster, frameon=False)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,524评论 5 460
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,869评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,813评论 0 320
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,210评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,085评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,117评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,533评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,219评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,487评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,582评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,362评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,218评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,589评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,899评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,176评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,503评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,707评论 2 335

推荐阅读更多精彩内容