Seurat Weekly NO.06 || 數(shù)據(jù)對(duì)象轉(zhuǎn)化之Scanpy2Seurat

其實(shí)诀艰,我們?cè)?019年的時(shí)候就介紹過(guò)單細(xì)胞轉(zhuǎn)錄組數(shù)據(jù)分析||Seurat3.1教程:Interoperability between single-cell object formats柬甥,講了單細(xì)胞轉(zhuǎn)錄組數(shù)據(jù)對(duì)象的轉(zhuǎn)化。對(duì)R語(yǔ)言境內(nèi)的Seurat其垄,CellDataSet苛蒲,SingleCellExperiment,loom的格式轉(zhuǎn)化起來(lái)還是比較方便的绿满,但是對(duì)于異域的anndata轉(zhuǎn)化一直不是很友好臂外,所以我借此機(jī)會(huì)學(xué)會(huì)了python(在等短信驗(yàn)證碼的那六十秒之內(nèi))。anndata的數(shù)據(jù)就在python中分析喇颁,完事漏健。

但是這樣的轉(zhuǎn)化總有需求,于是橘霎,Seurat團(tuán)隊(duì)開發(fā)了SeuratDisk包蔫浆,希望滿足數(shù)據(jù)在Seurat和Scanpy之間快速搬家的需求。遇到規(guī)范的數(shù)據(jù)茎毁,當(dāng)然可以一鍵搬家克懊,但是如果有一點(diǎn)不同,就會(huì)帶來(lái)各種Error七蜘。這里我們就以此為契機(jī),看看遇到Error該如何處理墙懂,這屬于進(jìn)階課程了橡卤,遇到問(wèn)題Google解決不了了,我們?cè)趺崔k损搬?

library(Seurat)

我從網(wǎng)上下了一個(gè)不知道做了什么處理的單細(xì)胞數(shù)據(jù)碧库,只知道是h5ad格式的,當(dāng)我們用ReadH5AD讀取時(shí)

cellxgene1 <- ReadH5AD(file = "some.processed.h5ad")

給出了這樣的報(bào)錯(cuò):

# 報(bào)錯(cuò)信息太長(zhǎng)巧勤,我們只顯示最有用的嵌灰。
In addition: Warning message:
Functionality for reading and writing H5AD files is being moved to SeuratDisk
For more details, please see https://github.com/mojaveazure/seurat-disk
and https://mojaveazure.github.io/seurat-disk/index.html 

顯然,作者這是在提示我們安裝新的R包:seurat-disk颅悉,于是我們挺聽話地去安裝了沽瞭。

remotes::install_github("mojaveazure/seurat-disk")
library(SeuratDisk)
Convert("some.processed.h5ad", dest = "h5seurat", overwrite = TRUE)`
Warning: Unknown file type: h5ad
Warning: 'assay' not set, setting to 'RNA'
Creating h5Seurat file for version 3.1.2
Adding X as data
Adding X as counts
Error: Cannot find feature names in this H5AD file

同樣,轉(zhuǎn)角處遇到Error剩瓶,于是直接google Error信息驹溃,我們看到Seurat團(tuán)隊(duì)給出的答案:

For this specific H5AD file, it's compressed using the LZF filter. This filter is Python-specific, and cannot easily be used in R. To use this file with Seurat and SeuratDisk, you'll need to read it in Python and save it out using the gzip compression

import anndata
adata = anndata.read("some.processed.h5ad")
adata.write("some.processed.gzip.h5ad", compression="gzip")

這顯然是python語(yǔ)法,在R里面該如何操作呢延曙?自然是在R里調(diào)用Python了,所以別問(wèn)人家用的是R還是python了布疙,這兩個(gè)可以相互運(yùn)行的語(yǔ)言,其實(shí)是一種語(yǔ)言灵临。

library(reticulate)
reticulate::py_config()
Sys.which('python')  # 該python 下要安裝了anndata 
# usethis::edit_r_environ()

filesmy2 ='some.processed.gzip.h5ad'
ad <- import("anndata", convert = FALSE)
some_ad <- ad$read_h5ad(filesmy)
adata = anndata.read("some.processed.h5ad")
some_ad$write("some.processed.gzip.h5ad", compression="gzip")

之后俱诸,我們終于可以轉(zhuǎn)化了。

 Convert("some.processed.gzip.h5ad", dest = "h5seurat", overwrite = TRUE)
Warning: Unknown file type: h5ad
Warning: 'assay' not set, setting to 'RNA' # 這里其實(shí)要格外小心赶诊,看看數(shù)據(jù)里面是不是 RNA啊
Creating h5Seurat file for version 3.1.5.9900
Adding X as data
Adding raw/X as counts
Adding meta.features from raw/var
Adding X_umap as cell embeddings for umap

Convert 成功后目錄下多了一個(gè)文件:some.processed.gzip.h5seurat舔痪,就差一個(gè)Seurat對(duì)象了锄码。

cellxgene <- LoadH5Seurat('some.processed.gzip.h5seurat',
                       assays ="RNA")

Validating h5Seurat file
Initializing RNA with data
Error in dimnamesGets(x, value) : 
  invalid dimnames given for “dgCMatrix” object 

同樣滋捶,在轉(zhuǎn)角處遇到了Error 重窟,于是我們?cè)俅蜧oogle 這個(gè)Error 惧财。一番瀏覽垮衷,我們發(fā)現(xiàn)自己遇到了Google解決不了的問(wèn)題。

決心debug這個(gè)函數(shù)拭抬。

debug(LoadH5Seurat)
cellxgene <- LoadH5Seurat('some.processed.gzip.h5seurat',
                       assays ="RNA")
# 一波回車
debug( as.Seurat) #因?yàn)長(zhǎng)oadH5Seurat里面用了這個(gè)函數(shù)垛耳,所以在LoadH5Seurat的debug環(huán)境種再debug  as.Seurat
# 一波回車
debug(AssembleAssay) #因?yàn)閍s.Seurat里面用了這個(gè)函數(shù),所以在as.Seurat的debug環(huán)境種再debug  AssembleAssay
# 一波回車 

我們找到問(wèn)題了:

slots.assay <- names(x = Filter(f = isTRUE, x = index[[assay]]$slots))
  slots <- slots %||% slots.assay
  slots <- match.arg(arg = slots, choices = slots.assay, several.ok = TRUE)
  if (!any(c("counts", "data") %in% slots)) {
    stop("At least one of 'counts' or 'data' must be loaded", 
      call. = FALSE)
  }
  assay.group <- file[["assays"]][[assay]]
  features <- assay.group[["features"]][]
  if ("counts" %in% slots && !"data" %in% slots) {
    if (verbose) {
      message("Initializing ", assay, " with counts")
    }
    counts <- as.matrix(x = assay.group[["counts"]])
    rownames(x = counts) <- features # 還是第一個(gè)features <- assay.group[["features"]][] 
    colnames(x = counts) <- Cells(x = file)
    obj <- CreateAssayObject(counts = counts, min.cells = -1, 
      min.features = -1)
  }
  else {
    if (verbose) {
      message("Initializing ", assay, " with data")
    }
    data <- as.matrix(x = assay.group[["data"]])
    rownames(x = data) <- features  # 還是第一個(gè)features <- assay.group[["features"]][]
    colnames(x = data) <- Cells(x = file)
    obj <- CreateAssayObject(data = data)
  }

也就是在這部分代碼中作者是認(rèn)為,slots 之counts和data 的行名是一樣的花墩,其實(shí)我們知道Seurat的每部分存的數(shù)據(jù)其實(shí)都是可以獨(dú)立操作的,所以可能并不是都一樣冰蘑。

懷疑就要檢查:


Browse[8]> counts <- as.matrix(x = assay.group[["counts"]])
Browse[8]> dim(counts)
[1] 33567 10550
Browse[8]> data <- as.matrix(x = assay.group[["data"]])
Browse[8]> dim(data)
[1] 33421 10550
Browse[8]> length(features )
[1] 33567

果然不一樣祠肥。

既然我們找到了invalid dimnames given for “dgCMatrix” objectError 的報(bào)錯(cuò)原因我們就可以針對(duì)counts來(lái)轉(zhuǎn)化仇箱,data的部分我們?cè)赟eurat里面做。為什么不找到data的行名忠烛,賦值給data呢美尸?這里留作思考題吧师坎。壞堪滨。

我們開始改造原函數(shù)使之能夠接受slots='counts' 這樣的限定,于是我們找到 as.Seurat源代碼中調(diào)用AssembleAssay的部分:

for (assay in names(x = assays)) {
    assay.objects[[assay]] <- AssembleAssay(
      assay = assay,
      file = x,
      slots =  assays[[assay]],  #這里強(qiáng)制對(duì)所有的slots進(jìn)行轉(zhuǎn)化,我們要讓他接受傳參
      verbose = verbose
    )
  }

除了在函數(shù)參數(shù)中加入slots = NULL,之外犯眠,這部分改為:

for (assay in names(x = assays)) {
    assay.objects[[assay]] <- AssembleAssay(
      assay = assay,
      file = x,
      slots =slots %||%  assays[[assay]],
      verbose = verbose
    )
  }

考慮到基本上要改動(dòng)https://github.com/mojaveazure/seurat-disk/blob/master/R/LoadH5Seurat.R這個(gè)腳本的大部分函數(shù)筐咧,所以我們Fork一份seurat-disk 對(duì)應(yīng)的我們改https://github.com/tuqiang2014/seurat-disk/blob/master/R/LoadH5Seurat.R

至于怎么改的量蕊,這里就略過(guò)了残炮。如果遇到同樣的問(wèn)題缩滨,你可以安裝這個(gè)改過(guò)了的泉瞻。改完之后袖牙,我們卸載掉這個(gè)官方的seurat-disk 鞭达,安裝自己改過(guò)的皇忿。

detach("package:SeuratDisk", unload = TRUE)
remove.packages('SeuratDisk')
remotes::install_github("tuqiang2014/seurat-disk")  # tuqiang2014就是我啦
library(SeuratDisk)
undebug(LoadH5Seurat) 
undebug( as.Seurat)
undebug(AssembleAssay) # 這里的提示忽略禁添,不是同一個(gè)環(huán)境。


cellxgene <- LoadH5Seurat('some.processed.gzip.h5seurat',
                       assays ="RNA",slots='counts')

# 提示信息:
Validating h5Seurat file
Initializing RNA with counts
Warning: Feature names cannot have underscores ('_'), replacing with dashes ('-')
Adding feature-level metadata for RNA
Adding reduction umap
Adding cell embeddings for umap
Adding miscellaneous information for umap
Adding command information
Adding cell-level metadata

于是芹啥,一個(gè)標(biāo)致的Seurat對(duì)象就呈現(xiàn)在我們面前了:

cellxgene
An object of class Seurat 
XXXX  features across XXXXX samples within 1 assay 
Active assay: RNA (XXXX features, 0 variable features)
 1 dimensional reduction calculated: umap

可以在Seurat里面盡情的分析墓怀。

library(ggplot2)
ggplot(DimPlot(cellxgene)$data,aes(umap_1        , umap_2   ,fill=ident)) + 
  geom_point(shape=21,colour="black",stroke=0.25,alpha=0.8) +
  DimPlot(cellxgene,label = T)$theme +
  theme_bw()+ NoLegend()

單細(xì)胞轉(zhuǎn)錄組數(shù)據(jù)分析||Seurat3.1教程:Interoperability between single-cell object formats
Convert AnnData to Seurat fails with raw h5ad
conversion_vignette
convert-anndata RMD
Error: Cannot find feature names in this H5AD file #7

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末莉炉,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子梆暮,更是在濱河造成了極大的恐慌啦粹,老刑警劉巖窘游,帶你破解...
    沈念sama閱讀 206,126評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件忍饰,死亡現(xiàn)場(chǎng)離奇詭異喘批,居然都是意外死亡铣揉,警方通過(guò)查閱死者的電腦和手機(jī)逛拱,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門朽合,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)曹步,“玉大人休讳,你說(shuō)我怎么就攤上這事〕雉铮” “怎么了物赶?”我有些...
    開封第一講書人閱讀 152,445評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵酵紫,是天一觀的道長(zhǎng)错维。 經(jīng)常有香客問(wèn)我,道長(zhǎng)鹉动,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,185評(píng)論 1 278
  • 正文 為了忘掉前任蜜氨,我火速辦了婚禮捎泻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘郎汪。我一直安慰自己,他們只是感情好抛计,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,178評(píng)論 5 371
  • 文/花漫 我一把揭開白布吹截。 她就那樣靜靜地躺著波俄,像睡著了一般蛾默。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上冬念,一...
    開封第一講書人閱讀 48,970評(píng)論 1 284
  • 那天刘急,我揣著相機(jī)與錄音叔汁,去河邊找鬼检碗。 笑死,一個(gè)胖子當(dāng)著我的面吹牛另假,可吹牛的內(nèi)容都是我干的怕犁。 我是一名探鬼主播,決...
    沈念sama閱讀 38,276評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼戈轿,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼思杯!你這毒婦竟也來(lái)了色乾?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,927評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤案怯,失蹤者是張志新(化名)和其女友劉穎漆撞,沒(méi)想到半個(gè)月后浮驳,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,400評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡离咐,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,883評(píng)論 2 323
  • 正文 我和宋清朗相戀三年宵蛀,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了县貌。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片煤痕。...
    茶點(diǎn)故事閱讀 37,997評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡摆碉,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出巷帝,到底是詐尸還是另有隱情,我是刑警寧澤驰徊,帶...
    沈念sama閱讀 33,646評(píng)論 4 322
  • 正文 年R本政府宣布堕阔,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏侥猬。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,213評(píng)論 3 307
  • 文/蒙蒙 一鹃锈、第九天 我趴在偏房一處隱蔽的房頂上張望瞧预。 院中可真熱鬧,春花似錦垢油、人聲如沸滩愁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)妻味。三九已至,卻和暖如春焦履,著一層夾襖步出監(jiān)牢的瞬間棕诵,已是汗流浹背校套。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評(píng)論 1 260
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留侨把,地道東北人妹孙。 一個(gè)月前我還...
    沈念sama閱讀 45,423評(píng)論 2 352
  • 正文 我出身青樓蠢正,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子懦傍,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,722評(píng)論 2 345

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