seurat-PrepSCTFindMarkers源碼解析

一、FindAllMarkers()函數(shù)報錯

最近事情太多秋泄,好久沒有寫簡書琐馆,斷更很久,慚愧印衔。
前幾天,將服務(wù)器的seurat包升級到4.1.0版本姥敛,在跑單細胞轉(zhuǎn)錄組流程的時候發(fā)現(xiàn)在FindAllMarkers步驟報錯奸焙,想細究下原因。
前面的流程是我使用SCTransform方法對單細胞數(shù)據(jù)進行標準化彤敛;
代碼如下:

DefaultAssay(seurat_obj) <- "SCT" 
Idents(seurat_obj) <- "cluster"
markers_all <- FindAllMarkers(object = seurat_obj, min.pct = 0.25, logfc.threshold = 0.25, only.pos=T)

報錯的截圖:


提示的信息是我需要在執(zhí)行FindMarkers()函數(shù)前与帆,先運行PrepSCTFindMarkers()函數(shù)。


二墨榄、PrepSCTFindMarkers()函數(shù)的用途

去年玄糟,對于SCTransform歸一化處理后的單細胞數(shù)據(jù)如何進行差異基因表達分析,我就很糾結(jié)袄秩,之前寫了一篇隨筆《sctransform預(yù)處理后阵翎,如何進行差異表達分析》逢并。如今,在2022年1月14日郭卫,seurat終于對SCTransform歸一化處理后如何合理進行差異表達分析砍聊,官宣了PrepSCTFindMarkers()函數(shù)。

seurat團隊應(yīng)該是慎之又慎贰军,才宣布此函數(shù)玻蝌,很想看看它具體做了一些什么操作。

查了下PrepSCTFindMarkers()的說明
該函數(shù)的說明文檔:
https://rdrr.io/cran/Seurat/man/PrepSCTFindMarkers.html
https://cran.r-project.org/web/packages/Seurat/Seurat.pdf

函數(shù)用途:

Prepare object to run differential expression on SCT assay with multiple models

詳細說明:

Given a merged object with multiple SCT models, this function uses minimum of the median UMI (calculated using the raw UMI counts) of individual objects to reverse the individual SCT regression model using minimum of median UMI as the sequencing depth covariate. The counts slot of the SCT assay is replaced with recorrected counts and the data slot is replaced with log1p of recorrected counts.

大致翻譯一下:
對多樣本的單細胞轉(zhuǎn)錄組數(shù)據(jù)整合后生成的seurat對象词疼,提前是已經(jīng)進行了SCTransform歸一化處理俯树。針對SCT模式下,進行差異表達分析贰盗,需要對seurat對象進行預(yù)處理许饿,修正 SCT 模式下的counts矩陣和data矩陣。該函數(shù)計算每個樣本的UMI中位數(shù)(使用原始 UMI 計數(shù)計算)童太,取其最小值米辐,然后應(yīng)用于每個樣本的SCT回歸模型,使用UMI 中位數(shù)的最小值作為測序深度協(xié)變量书释。SCT模式下的counts矩陣被重新校正的counts值所取代翘贮,同時,data矩陣也被重新校正counts的 log1p 替換爆惧。

換句話說狸页,用SCT模式的data矩陣做差異表達分析,不是很妥扯再,需要預(yù)先用PrepSCTFindMarkers()函數(shù)校正芍耘,校正后的data矩陣,更適合做下游的差異基因表達分析熄阻。

函數(shù)用法:

PrepSCTFindMarkers(object, assay = "SCT", verbose = TRUE)

那為什么用原先的SCT模式的data做差異表達分析不行斋竞?
作者在曾在seurat的discussions部分中也給出了一段說明:

We had anticipated extending Seurat to actively support DE using the pearson residuals of sctransform, but have decided not to do so. In some cases, Pearson residuals may not be directly comparable across different datasets, particularly if there are batch effects that are unrelated to sequencing depth. While it is possible to correct these differences using the SCTransform-based integration workflow for the purposes of visualization/clustering/etc., we do not recommend running differential expression directly on Pearson residuals. Instead, we recommend running DE on the standard RNA assay.

我們曾期望擴展Seurat的功能以支持使用sctransform的pearson殘差進行DE分析,但已決定不這樣做秃殉。在某些情況下坝初,皮爾遜殘差可能無法在不同的數(shù)據(jù)集之間直接進行比較,尤其是當存在與測序深度無關(guān)的批次效應(yīng)時钾军。雖然為了可視化/聚類等目的鳄袍,可以使用基于SCTransform的集成工作流來糾正這些差異,但我們不建議直接在Pearson殘差上運行差分表達式吏恭。相反拗小,我們建議在標準RNA分析中運行DE分析。

我們可以這樣理解樱哼,Satija團隊本來期望用sctransform的皮爾遜殘差進行DE分析哀九,但是他們發(fā)現(xiàn)剿配,Pearson殘差可能無法在不同數(shù)據(jù)集之間直接進行比較,決定不這么做勾栗〔依椋基于SCTransform 的分析工作流可以剔除實驗差異以實現(xiàn)可基因可視化和聚類等功能。但是他們建議在標準RNA assay中運行DE分析围俘。

給出的案例是:
針對SCTransform歸一化流程砸讳,在FindMarkers之前需要運行PrepSCTFindMarkers()函數(shù)。

data("pbmc_small") 
pbmc_small1 <- SCTransform(object = pbmc_small, variable.features.n = 20) 
pbmc_small2 <- SCTransform(object = pbmc_small, variable.features.n = 20) 
pbmc_merged <- merge(x = pbmc_small1, y = pbmc_small2) 
pbmc_merged <- PrepSCTFindMarkers(object = pbmc_merged) 
markers <- FindMarkers( 
  object = pbmc_merged, 
  ident.1 = "0", 
  ident.2 = "1", 
  assay = "SCT" 
) 
pbmc_subset <- subset(pbmc_merged, idents = c("0", "1")) 
markers_subset <- FindMarkers( 
  object = pbmc_subset, 
  ident.1 = "0", 
  ident.2 = "1", 
  assay = "SCT", 
  recorrect_umi = FALSE 
)

三界牡、PrepSCTFindMarkers()函數(shù)解析

源碼位置:https://github.com/satijalab/seurat/blob/f1b2593ea72f2e6d6b16470dc7b9e9b645179923/R/differential_expression.R

library(Seurat)
data("pbmc_small") 
pbmc_small1 <- SCTransform(object = pbmc_small, variable.features.n = 20) 
pbmc_small2 <- SCTransform(object = pbmc_small, variable.features.n = 20) 
pbmc_merged <- merge(x = pbmc_small1, y = pbmc_small2)
pbmc_merged
# An object of class Seurat 
# 450 features across 160 samples within 2 assays 
# Active assay: SCT (220 features, 0 variable features)
# 1 other assay present: RNA

下面我們進入到PrepSCTFindMarkers()函數(shù)中簿寂,代碼較長,我們分解一下:
step1:判斷seurat對象的SCT模型的數(shù)目宿亡,如果只有一個樣本常遂,跳出此函數(shù),不需要進行SCT模型的counts和data數(shù)據(jù)校正挽荠;
在我們的案例中克胳,有2個樣本,即兩個SCR模型圈匆。

if (length(x = levels(x = object[[assay]])) == 1) {
    if (verbose) {
      message("Only one SCT model is stored - skipping recalculating corrected counts")
    }
    return(object)
  }

step2:此處調(diào)用了SCTResults函數(shù)漠另,計算每個SCT模型的UMI中位數(shù)。先不細究該函數(shù)跃赚。

observed_median_umis <- lapply(
  X = SCTResults(object = object[[assay]], slot = "cell.attributes"),
  FUN = function(x) median(x[, "umi"])
)
observed_median_umis
# $model1
# [1] 180
# 
# $model1.1
# [1] 180

step3:計算min_median_umi

model.list <- slot(object = object[[assay]], name = "SCTModel.list")
model.list
# $model1
# An sctransform model.
# Model formula:  y ~ log_umi 
# Parameters stored for 220 features, 80 cells
# $model1.1
# An sctransform model.
# Model formula:  y ~ log_umi 
# Parameters stored for 220 features, 80 cells

median_umi.status <- lapply(X = model.list,
                            FUN = function(x) { return(tryCatch(
                              expr = slot(object = x, name = 'median_umi'),
                              error = function(...) {return(NULL)})
                            )})
# median_umi.status
# $model1
# [1] 180
# 
# $model1.1
# [1] 180
if (any(is.null(x = unlist(x = median_umi.status)))){
  # For old SCT objects  median_umi is set to median umi as calculated from obserbed UMIs
  slot(object = object[[assay]], name = "SCTModel.list") <- lapply(X = model.list,
                                                                   FUN = UpdateSlots)
  SCTResults(object = object[[assay]], slot = "median_umi") <- observed_median_umis
  
}
model_median_umis <- SCTResults(object = object[[assay]], slot = "median_umi")
min_median_umi <- min(unlist(x = observed_median_umis))

step4:生成校正的corrected_counts矩陣
step5:對corrected_counts取log1p笆搓,生成校正的corrected_data矩陣
時間太趕,先大致記錄下纬傲,后面再補充满败。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市叹括,隨后出現(xiàn)的幾起案子算墨,更是在濱河造成了極大的恐慌,老刑警劉巖汁雷,帶你破解...
    沈念sama閱讀 206,013評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件净嘀,死亡現(xiàn)場離奇詭異,居然都是意外死亡摔竿,警方通過查閱死者的電腦和手機面粮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評論 2 382
  • 文/潘曉璐 我一進店門少孝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來继低,“玉大人,你說我怎么就攤上這事稍走≡蹋” “怎么了柴底?”我有些...
    開封第一講書人閱讀 152,370評論 0 342
  • 文/不壞的土叔 我叫張陵,是天一觀的道長粱胜。 經(jīng)常有香客問我柄驻,道長,這世上最難降的妖魔是什么焙压? 我笑而不...
    開封第一講書人閱讀 55,168評論 1 278
  • 正文 為了忘掉前任鸿脓,我火速辦了婚禮,結(jié)果婚禮上涯曲,老公的妹妹穿的比我還像新娘野哭。我一直安慰自己,他們只是感情好幻件,可當我...
    茶點故事閱讀 64,153評論 5 371
  • 文/花漫 我一把揭開白布拨黔。 她就那樣靜靜地躺著,像睡著了一般绰沥。 火紅的嫁衣襯著肌膚如雪篱蝇。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,954評論 1 283
  • 那天徽曲,我揣著相機與錄音零截,去河邊找鬼。 笑死疟位,一個胖子當著我的面吹牛瞻润,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播甜刻,決...
    沈念sama閱讀 38,271評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼绍撞,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了得院?” 一聲冷哼從身側(cè)響起傻铣,我...
    開封第一講書人閱讀 36,916評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎祥绞,沒想到半個月后非洲,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,382評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡蜕径,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,877評論 2 323
  • 正文 我和宋清朗相戀三年两踏,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片兜喻。...
    茶點故事閱讀 37,989評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡梦染,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情帕识,我是刑警寧澤泛粹,帶...
    沈念sama閱讀 33,624評論 4 322
  • 正文 年R本政府宣布,位于F島的核電站肮疗,受9級特大地震影響晶姊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜伪货,卻給世界環(huán)境...
    茶點故事閱讀 39,209評論 3 307
  • 文/蒙蒙 一们衙、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧碱呼,春花似錦砍艾、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至懊悯,卻和暖如春蜓谋,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背炭分。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評論 1 260
  • 我被黑心中介騙來泰國打工桃焕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人捧毛。 一個月前我還...
    沈念sama閱讀 45,401評論 2 352
  • 正文 我出身青樓观堂,卻偏偏與公主長得像,于是被迫代替她去往敵國和親呀忧。 傳聞我的和親對象是個殘疾皇子师痕,可洞房花燭夜當晚...
    茶點故事閱讀 42,700評論 2 345

推薦閱讀更多精彩內(nèi)容