STUtility || 空间转录组多样本分析框架(二)

前情回顾:
应用空间统计学分析空间表达数据
空间信息在空间转录组中的运用
Giotto|| 空间表达数据分析工具箱
SPOTlight || 用NMF解卷积空间表达数据
空间转录组教程|| stLearn :空间轨迹推断
Seurat 新版教程:分析空间转录组数据
单细胞转录组数据分析|| scanpy教程:空间转录组数据分析
10X Visium:空间转录组样本制备到数据分析
定量免疫浸润在单细胞研究中的应用
STUtility || 空间转录组多样本分析框架(一)

我们在上一篇文章STUtility || 空间转录组多样本分析框架(一)中演示了用STUtility分析空转多样本,主要是对空间信息和图像信息的分析,可以说凸显了空转应有的特性。在这里,我们将探讨:

  • 空转数据和单转数据的相似性
  • 用Seurat对空转数据的标准分析
  • 感兴趣区域的边缘检测

同样地,我们载入数据加载R包,并执行Seurat的标准化:

library(Matrix)
library(magrittr)
library(dplyr)
library(ggplot2)
library(spdep)

se <- readRDS('se.rds')

#  我们可以去除一下切片的批次,但是内存太小,只能放弃了。
# Add a section column to your meta.data
#se$section <- paste0("section_", GetStaffli(se)[[, "sample", drop = T]])

# Run normalization with "vars.to.regress" option
?SCTransform
# se.batch.cor <- SCTransform(se, vars.to.regress = "section", variable.features.n=1000,conserve.memory=T)
se<- SCTransform(se)
# 空间高变基因
spatgenes <- CorSpatialGenes(se)
head(spatgenes)
         gene       cor
CRISP3 CRISP3 0.9636610
RPL17   RPL17 0.9379202
CXCL14 CXCL14 0.9371324
MGP       MGP 0.9361545
CRIP1   CRIP1 0.9333115
NME2     NME2 0.9292425
heatmap.colors <- c("dark blue", "cyan", "yellow", "red", "dark red")
ST.FeaturePlot(se, features = c('CRISP3',"CXCL14",'CRIP1','MGP'), cols = heatmap.colors, dark.theme = T)
空转数据和单转数据的相似性

STUtility 的分析框架是继承Seurat的方法,那么我们不禁要问,目前的空间表达数据和单细胞转录组数据到底有多相似呢? 拿pbmc3k数据比较一下。

# Get raw count data 
umi_data <- GetAssayData(object = se, slot = "counts", assay = "RNA")
dim(umi_data)
umi_data[1:4,1:4]

# Calculate gene attributes
gene_attr <- data.frame(mean = rowMeans(umi_data),
                        detection_rate = rowMeans(umi_data > 0),
                        var = apply(umi_data, 1, var), 
                        row.names = rownames(umi_data)) %>%
    mutate(log_mean = log10(mean), log_var = log10(var))
head(gene_attr)
        mean detection_rate        var  log_mean    log_var
1 0.02564760     0.02513465 0.02601904 -1.590953 -1.5847087
2 0.03552193     0.03372660 0.03785564 -1.449503 -1.4218694
3 0.04334445     0.04142088 0.04531866 -1.363067 -1.3437230
4 0.02436522     0.02333932 0.02582668 -1.613230 -1.5879315
5 0.03500898     0.03270069 0.03840484 -1.455821 -1.4156140
6 0.07989228     0.06758143 0.10506953 -1.097495 -0.9785232

# Obtain spot attributes from Seurat meta.data slot
spot_attr <- se[[c("nFeature_RNA", "nCount_RNA")]]
# Get  pbm  raw count data 
library(pbmc3k.SeuratData,lib.loc = 'E:\\software\\R\\R-4.0.2\\library')
AvailableData()

pbmc3kumi_data <- GetAssayData(object = pbmc3k.final, slot = "counts", assay = "RNA")
dim(pbmc3kumi_data)
# Calculate gene attributes
pbmc3kgene_attr <- data.frame(mean = rowMeans(pbmc3kumi_data),
                              detection_rate = rowMeans(pbmc3kumi_data > 0),
                              var = apply(pbmc3kumi_data, 1, var), 
                              row.names = rownames(pbmc3kumi_data)) %>%
    mutate(log_mean = log10(mean), log_var = log10(var))

绘制两种数据的分布:

p1 <- ggplot(gene_attr, aes(log_mean, log_var)) + 
    geom_point(alpha = 0.3, shape = 16, color = "white") + 
    geom_density_2d(size = 0.3) +
    geom_abline(intercept = 0, slope = 1, color = 'red') +
    ggtitle("Mean-variance relationship") + DarkTheme()
# add the expected detection rate under Poisson model
x = seq(from = -2, to = 2, length.out = 1000)
poisson_model <- data.frame(log_mean = x, detection_rate = 1 - dpois(0, lambda = 10^x))
p2 <- ggplot(gene_attr, aes(log_mean, detection_rate)) + 
    geom_point(alpha = 0.3, shape = 16, color = "white") + 
    geom_line(data = poisson_model, color='red') +
    ggtitle("Mean-detection-rate relationship") + DarkTheme()

p3 <- ggplot(pbmc3kgene_attr, aes(log_mean, log_var)) + 
    geom_point(alpha = 0.3, shape = 16, color = "white") + 
    geom_density_2d(size = 0.3) +
    geom_abline(intercept = 0, slope = 1, color = 'red') +
    ggtitle("PBMC3k\n Mean-variance relationship") + DarkTheme()
# add the expected detection rate under Poisson model
x = seq(from = -2, to = 2, length.out = 1000)
poisson_model <- data.frame(log_mean = x, detection_rate = 1 - dpois(0, lambda = 10^x))
p4 <- ggplot(pbmc3kgene_attr, aes(log_mean, detection_rate)) + 
    geom_point(alpha = 0.3, shape = 16, color = "white") + 
    geom_line(data = poisson_model, color='red') +
    ggtitle("PBMC3k\n Mean-detection-rate relationship") + DarkTheme()
cowplot::plot_grid(p1, p2,p3,p4, nrow = 2)

我们看到二种数据的分布还是很相似的,这也解释了为什么大部分的单细胞转录组的分析方法在空转中都是可以应用的。接下来,我们检查空转数据是否为稀疏矩阵,也就是零值有多少。

 sum(pbmc3kumi_data == 0)/(ncol(pbmc3kumi_data)*nrow(pbmc3kumi_data))
[1] 0.9381182
 sum(umi_data == 0)/(ncol(umi_data)*nrow(umi_data))
[1] 0.6779447
 sum(umi_data == 0) / prod(dim(umi_data))
[1] 0.6779447
 print(object.size(pbmc3kumi_data), units = "Mb")
26.7 Mb
 print(object.size(umi_data), units = "Mb")
469.4 Mb
Seurat对空转数据的标准分析

可见在空转中零值也是很多的,虽然没有单转那么多。接下来进行表达数据的降维聚类分析。鉴于这一部分和单转太相似了,我们就不再每一步地解释了。

?RunNMF  # 特征选择类似PCA
se <- RunNMF(se, nfactors = 40) # Specificy nfactors to choose the number of factors, default=20.
cscale <- c("darkblue", "cyan", "yellow", "red", "darkred")
ST.DimPlot(se, 
           dims = 1:2,
           ncol = 2, # Sets the number of columns at dimensions level
           grid.ncol = 2, # Sets the number of columns at sample level
           reduction = "NMF", 
           dark.theme = T, 
           pt.size = 1, 
           center.zero = F, 
           cols = cscale)
print(se[["NMF"]])

分群并绘制分群信息:

FactorGeneLoadingPlot(se, factor = 1, dark.theme = TRUE)
se <- FindNeighbors(object = se, verbose = FALSE, reduction = "NMF", dims = 1:40)
se <- FindClusters(object = se, verbose = FALSE)
library(RColorBrewer)
n <- 19
qual_col_pals = brewer.pal.info[brewer.pal.info$category == 'qual',]
col_vector = unlist(mapply(brewer.pal, qual_col_pals$maxcolors, rownames(qual_col_pals)))
ST.FeaturePlot(object = se, features = "seurat_clusters", dark.theme = T, cols = col_vector, pt.size = 2,sb.size = 5 )
head(se@assays$SCT@var.features, 20)
[1] "IGLC2"    "IGHG3"    "IGKC"     "ALB"      "IGLC3"    "IGHG1"    "IGHM"     "IGLC1"    "IGHA1"    "MGP"      "CRISP3"   "IGHG2"   
[13] "IGHG4"    "CPB1"     "IGHA2"    "SERPINA3" "JCHAIN"   "CXCL14"   "CCL21"    "CCL19"   

top <- se@assays$SCT@var.features
FeatureOverlay(se, 
                        features = c('IGLC2','CXCL14'), 
                        sampleids = 1:2,
                        cols = c("darkblue", "cyan", "yellow", "red", "darkred"),
                        pt.size = 1.5, 
                        pt.alpha = 0.5, 
                        dark.theme = T, 
                        ncols.samples = 2)

我们可以在UMAP空间上看spot的分群情况,当然,之前在Seurat中对分群做的一切动作这里都是可以做的,如split和group等。

 se <- RunUMAP(se, reduction = "NMF", dims = 1:40, n.neighbors = 10)
 DimPlot(object = se, reduction = "umap", pt.size = 1.5,ncol = 2)+ DarkTheme()

STUtility 还提供用三原色可视化分群信息的选项,这样可视化更加清楚。

 se <- RunUMAP(object = se, dims = 1:40, verbose = FALSE, n.components = 3, reduction = "NMF", reduction.name = "umap.3d")
ST.DimPlot(object = se, dims = 1:3, reduction = "umap.3d", blend = T, dark.theme = T, pt.size = 1.5)

分群之后,我们要做的就是看每个群的特征,比较直接的生物学意义就是做差异分析:

markers <- FindMarkers(se, ident.1 = "12")
head(markers)
                   p_val avg_logFC pct.1 pct.2     p_val_adj
AC026355.1 7.800313e-211 0.6957137 0.799 0.165 1.269345e-206
U62317.5   6.955878e-192 0.4293024 0.454 0.053 1.131930e-187
CPB1       1.666918e-171 1.4851863 1.000 0.959 2.712576e-167
FCGR3B     4.019841e-160 1.1899326 0.883 0.335 6.541488e-156
IL6ST      5.819598e-158 0.6636229 1.000 0.998 9.470232e-154
SCUBE3     1.797465e-157 0.7575323 0.862 0.288 2.925015e-153

可视化marker基因:

 FeatureOverlay(se, 
                        features = c('IL6ST'), 
                        sampleids = 1:2,
                        cols = c("darkblue", "cyan", "yellow", "red", "darkred"),
                        pt.size = 1.5, 
                        pt.alpha = 0.5, 
                        dark.theme = T, 
                        ncols.samples = 2)
边缘检测

有时提取一一亚群点的“邻域”是有用的。,我们展示了如何应用这个方法来找到任何感兴趣区域的所有邻近点。

一旦定义好了一个感兴趣的区域(region of interest,ROI),并且希望找到与该区域相邻的所有点,您可以使用regionneighbors函数来自动检测这些点。
例如,假设我们想要选择所有cluster 2 的边缘spot。第一步是确保seurat对象的标识是正确的,这里我们需要将其设置为“seurat_clusters”。当然, 如果是注释好的,那就更有生物学意义了。

?RegionNeighbours
st <- SetIdent(st, value = "seurat_clusters")
st <- RegionNeighbours(st, id = "2", verbose = TRUE)
FeatureOverlay(st, features = "nbs_2", ncols.samples = 2, sampleids = 1:2, cols = c("red", "lightgray"), pt.size = 2, dark.theme = T)

检测到亚群的边缘之后,肯定是要看看边缘和内部有什么差异了,最直观的就是做一下差异基因看看:

library(magrittr)
library(dplyr)

se <- SetIdent(se, value = "nbs_2")
 nbs_2.markers <- FindMarkers(se, ident.1 = "2", ident.2 = "nbs_2")
 nbs_2.markers$gene <- rownames(nbs_2.markers)
 st.subset <- SubsetSTData(se, expression = nbs_2 %in% c("2", "nbs_2"))
 sorted.marks <- nbs_2.markers %>% top_n(n = 40, wt = abs(avg_logFC))
 sorted.marks <- sorted.marks[order(sorted.marks$avg_logFC, decreasing = T), ]
 DoHeatmap(st.subset, features = sorted.marks$gene, group.colors = c("red", "lightgray"), disp.min = -2, disp.max = 2) + DarkTheme() 
FeatureOverlay(st.subset, features =sorted.marks$gene[1:4], pt.size = 2, dark.theme = T, 
               ncols.features = 2, cols = c("darkblue", "cyan", "yellow", "red", "darkred"))


https://en.wikipedia.org/wiki/Region_of_interest
感兴趣的区域(通常缩写为ROI)是为特定目确定的数据集中的样本。ROI的概念在许多应用领域中普遍使用。例如,在医学成像中,为了测量肿瘤的大小,肿瘤的边界可以在图像或体积上确定。我们将会在下一篇文章中讲述如何选择感兴趣的区域。

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

推荐阅读更多精彩内容