MISTy:空間轉錄組細胞互作分析方法

1. 簡介

MISTy主要有四個功能:

算法:Multi-view framework to dissect effects related to CCI (剖析與細胞-細胞互作相關影響的多視角框架)

優點:1. 不需要細胞類型注釋;2. 利用完整的表達譜。

缺點:提取的互作不能直接視為因果關系。

??MISTy不僅可以做細胞-細胞之間的dependency,基因和基因之間,甚至細胞和通路之間的dependency都可以做。

2. 數據準備
# MISTy
library(mistyR)
library(future)

# data manipulation
library(dplyr)
library(purrr)
library(distances)

# plotting
library(ggplot2)

plan(multisession)

以下演示使用了合成的標準演示數據集synthetic。 該數據集是一個包含 10 個 tibbles 的列表,每個 tibbles 代表從四種單元格類型的隨機布局和 100×100 網格上的空白空間生成的數據。

該數據是通過模擬一個專注于signaling events的二維cellular automata model生成的。 該模型模擬了 11 種分子的產生、擴散、降解和相互作用。 請注意,數據集僅包含非空白空間的模擬測量值。

data("synthetic")

ggplot(synthetic[[1]], aes(x = col, y = row, color = type)) +
  geom_point(shape = 15, size = 0.7) +
  scale_color_manual(values = c("#e9eed3", "#dcc38d", "#c9e2ad", "#a6bab6")) +
  theme_void()
四種顏色的格子代表四種細胞類型
str(synthetic[[1]], give.attr = FALSE)
#> spec_tbl_df [4,205 × 14] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
#>  $ row  : num [1:4205] 1 1 1 1 1 1 1 1 1 1 ...
#>  $ col  : num [1:4205] 100 11 13 14 15 20 23 24 26 32 ...
#>  $ ECM  : num [1:4205] 0.0385 0.0327 0.1444 0.387 0.1635 ...
#>  $ ligA : num [1:4205] 0.834 0.119 0.525 0.269 0.195 ...
#>  $ ligB : num [1:4205] 0.0157 0.0104 0.014 0.0367 0.1176 ...
#>  $ ligC : num [1:4205] 0.236 0.804 0.334 0.502 0.232 ...
#>  $ ligD : num [1:4205] 1.183 0.101 0.434 0.241 0.203 ...
#>  $ protE: num [1:4205] 1.18 0 1.67 0 0 ...
#>  $ protF: num [1:4205] 2.547 0.386 1.614 0.913 0.162 ...
#>  $ prodA: num [1:4205] 0.382 0 0.472 0 0 ...
#>  $ prodB: num [1:4205] 0 0 0 0 0.16 ...
#>  $ prodC: num [1:4205] 0 0.536 0 0.418 0 ...
#>  $ prodD: num [1:4205] 0.588 0 0.379 0 0 ...
#>  $ type : chr [1:4205] "CT1" "CT2" "CT1" "CT2" ...
3. View composition

mistyR 工作流程總是從定義一個內部視圖 (create_initial_view()) 開始,包含了在每個感興趣的細胞中檢測作為建模目標的marker的測量值。 對于synthetic數據集中的第一個樣本,我們選擇除了所有可用細胞的配體(ligA-D)之外的所有marker。

expr <- synthetic[[1]] %>% select(-c(row, col, type, starts_with("lig")))
# head(expr)
##  A tibble: 6 × 7
#      ECM protE protF prodA prodB prodC prodD
#    <dbl> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
# 1 0.0385  1.18 2.55  0.382 0     0     0.588
# 2 0.0327  0    0.386 0     0     0.536 0    
# 3 0.144   1.67 1.61  0.472 0     0     0.379
# 4 0.387   0    0.913 0     0     0.418 0    
# 5 0.163   0    0.162 0     0.160 0     0    
# 6 0.203   0    0.603 0     0     0.555 0 

misty.intra <- create_initial_view(expr)

summary(misty.intra)
#>                Length Class  Mode     
#> intraview      2      -none- list     
#> misty.uniqueid 1      -none- character
summary(misty.intra$intraview)
#>        Length Class       Mode     
#> abbrev 1      -none-      character
#> data   7      spec_tbl_df list

從內在視圖(intraview)的角度,mistyR 將模擬每個marker的表達作為細胞內其他marker的表達的函數。我們有興趣探索來自互補的不同空間背景的marker表達,即,可區分并有助于解釋marker的整體表達。

mistyR 包含兩個默認helper functions,用于計算和添加考慮到數據spatial context的視圖:add_juxtaview()add_paraview()。juxtaview表示局部空間視圖,并捕獲每個單元的直接鄰域內的內部視圖中可用的所有marker的表達。 paraview 捕獲邊界組織結構內視圖中所有可用marker的表達,其中importance of the influence與兩個細胞之間距離的倒數成正比。要在視圖合成中添加一個 paraview,我們首先需要來自內部視圖的每個cell的位置信息。使用這些信息,我們可以創建一個重要半徑為 10 的 paraview 并將其添加到視圖組合中。

pos <- synthetic[[1]] %>% select(row, col)
pos
##  A tibble: 4,205 × 2
#      row   col
#    <dbl> <dbl>
#  1     1   100
#  2     1    11
#  3     1    13
#  4     1    14
#  5     1    15
#  6     1    20
#  7     1    23
#  8     1    24
#  9     1    26
# 10     1    32
##  … with 4,195 more rows

misty.views <- misty.intra %>% add_paraview(pos, l = 10)
#> 
#> Generating paraview

summary(misty.views)
#>                Length Class  Mode     
#> intraview      2      -none- list     
#> misty.uniqueid 1      -none- character
#> paraview.10    2      -none- list

View(misty.views)
注意 misty.views[["paraview.10"]][["data"]] 和 misty.views[["intraview"]][["data"]] 的不同

當樣本中有大量細胞時,juxtaview和paraview的計算可能是計算密集型的。 因此需要設置future::plan() 并行運行。 計算paraview所需的計算時間也可以通過approximation顯著減少。 有關詳細信息,請參閱此函數的文檔 (help(add_paraview))。

此外,也可以從外部資源(data.frame、tibble)創建其他相關和自定義視圖(create_view())并將其添加到視圖組合中。 數據應按內部視圖中的順序(每個細胞一行)。 例如,我們可以創建一個視圖來捕獲每個cell的 10 個最近鄰居的平均表達式。

# find the 10 nearest neighbors
neighbors <- nearest_neighbor_search(distances(as.matrix(pos)), k = 11)[-1, ]
dim(neighbors)
# [1]   10 4205
neighbors[,1:6]
#         1    2    3    4   5    6
#  [1,]  46  488    4  490   4  494
#  [2,] 489    3  490    5 490  493
#  [3,] 533  935    2    3 938  943
#  [4,] 934   38  936  937   3  495
#  [5,] 985  933    5  938 939  944
#  [6,] 532  936  937  936 937  492
#  [7,] 984  979  935  939 491  945
#  [8,]  45    4  938    2 940  941
#  [9,] 983  490 1420  491 936 1421
# [10,]  44 1420  488 1420 492    7

# calculate the mean expression of the nearest neighbors for all markers
# for each cell in expr
nnexpr <- seq_len(nrow(expr)) %>%
  map_dfr(~ expr %>%
    slice(neighbors[, .x]) %>%
    colMeans())

nn.view <- create_view("nearest", nnexpr, "nn")

nn.view
#> $nearest
#> $nearest$abbrev
#> [1] "nn"
#> 
#> $nearest$data
#> # A tibble: 4,205 × 7
#>      ECM protE protF  prodA  prodB  prodC  prodD
#>    <dbl> <dbl> <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
#>  1 0.169 0.337 1.07  0.120  0.0138 0.146  0.165 
#>  2 0.346 0.676 0.549 0.0969 0.0140 0.190  0.0766
#>  3 0.219 0.304 0.495 0.0496 0.0288 0.236  0.0387
#>  4 0.238 0.607 0.651 0.132  0.0288 0.0954 0.122 
#>  5 0.313 0.688 0.835 0.166  0.0297 0.0837 0.173 
#>  6 0.527 0.743 0.616 0.0722 0.0184 0.135  0.0964
#>  7 0.278 0.399 0.501 0.0413 0.0632 0.160  0.0604
#>  8 0.266 0.537 0.624 0.0738 0.0463 0.154  0.117 
#>  9 0.356 0.564 0.565 0.0696 0.0415 0.208  0.106 
#> 10 0.625 0.863 0.458 0.0350 0.0823 0.230  0.0576
#> # … with 4,195 more rows

可以將創建的視圖(add_views())一個一個地添加到現有的視圖組合中,或者以列表的形式添加。 創建和添加自定義視圖到合成的其他示例

extended.views <- misty.views %>% add_views(nn.view)

summary(extended.views)
#>                Length Class  Mode     
#> intraview      2      -none- list     
#> misty.uniqueid 1      -none- character
#> paraview.10    2      -none- list     
#> nearest        2      -none- list

也可以通過向 remove_views() 提供一個或多個視圖名稱來從組合中刪除視圖。 但是這個方法無法刪除 intraview 和 misty.uniqueid。

extended.views %>%
  remove_views("nearest") %>%
  summary()
#>                Length Class  Mode     
#> intraview      2      -none- list     
#> misty.uniqueid 1      -none- character
#> paraview.10    2      -none- list

extended.views %>%
  remove_views("intraview") %>%
  summary()
#>                Length Class  Mode     
#> intraview      2      -none- list     
#> misty.uniqueid 1      -none- character
#> paraview.10    2      -none- list     
#> nearest        2      -none- list
4. Model training

視圖組合創建好之后,就可以使用 run_misty() 函數進行model training。 默認情況下,針對每個視圖的內部視圖中可用的每個marker單獨訓練模型。 模型訓練的結果將存儲在名為“results”的文件夾中。

misty.views %>% run_misty()

# Training models
#  Progress: ───────────────────────────────────────── 100%
# [1] "/tmp/results"

我們用于synthetic數據集中第一個樣本的工作流程可以輕松擴展以應用于所有 10 個樣本,以完全重現已發表文獻中的結果。 每個樣本的結果將存儲在“results”文件夾的子文件夾中。

result.folders <- synthetic %>% imap_chr(function(sample, name) {
  sample.expr <- sample %>% select(-c(row, col, type, starts_with("lig")))
  sample.pos <- sample %>% select(row, col)
  
  create_initial_view(sample.expr) %>% add_paraview(sample.pos, l = 10) %>%
    run_misty(results.folder = paste0("results", .Platform$file.sep, name))
})
#> 
#> Generating paraview
#> 
#> Training models
#> 
#> Generating paraview
#> 
#> Training models
#> 
#> Generating paraview
#> 
#> Training models
#> 
#> Generating paraview
#> 
#> Training models
#> 
#> Generating paraview
#> 
#> Training models
#> 
#> Generating paraview
#> 
#> Training models
#> 
#> Generating paraview
#> 
#> Training models
#> 
#> Generating paraview
#> 
#> Training models
#> 
#> Generating paraview
#> 
#> Training models
#> 
#> Generating paraview
#> 
#> Training models

result.folders
#>                                                                 synthetic1 
#>  "/tmp/results/synthetic1" 
#>                                                                synthetic10 
#> "/tmp/results/synthetic10" 
#>                                                                 synthetic2 
#>  "/tmp/results/synthetic2" 
#>                                                                 synthetic3 
#>  "/tmp/results/synthetic3" 
#>                                                                 synthetic4 
#>  "/tmp/results/synthetic4" 
#>                                                                 synthetic5 
#>  "/tmp/results/synthetic5" 
#>                                                                 synthetic6 
#>  "/tmp/results/synthetic6" 
#>                                                                 synthetic7 
#>  "/tmp/results/synthetic7" 
#>                                                                 synthetic8 
#>  "/tmp/results/synthetic8" 
#>                                                                 synthetic9 
#>  "/tmp/results/synthetic9"

需要注意的是,默認情況下,mistyR 會緩存計算出的視圖和經過訓練的模型,這樣在工作流重復運行的情況下,它們將被檢索而不是重新計算,從而節省了大量的計算時間。 但是,生成的緩存文件的大小可能很大。 因此,可以使用緩存文件的函數,例如 run_misty()中名為 cached 的參數,可以設置為 FALSE。 此外,函數 clear_cache() 提供了刪除緩存文件的方法。

5. Result processing

對于每個分析的樣本,原始 mistyR 結果存儲在輸出文件夾中的多個文本文件中。 通過提供包含 run_misty() 生成的結果的文件夾的路徑,可以使用函數 collect_results() 收集、聚合和轉換來自一個或多個樣本的結果到 R 對象。

misty.results <- collect_results(result.folders)
#> 
#> Collecting improvements
#> 
#> Collecting contributions
#> 
#> Collecting importances
#> 
#> Aggregating

summary(misty.results)
#>                        Length Class  Mode
#> improvements           4      tbl_df list
#> contributions          4      tbl_df list
#> importances            5      tbl_df list
#> improvements.stats     5      tbl_df list
#> contributions.stats    6      tbl_df list
#> importances.aggregated 5      tbl_df list

See help(collect_results) for more information on the structure of misty.results.

6. 繪圖

MISTy 可以用于解釋如下三個general questions。 每個問題都可以通過查看相應的plot來回答。

1. How much can the broader spatial context explain the expression of markers (in contrast to the intraview)?

這可以在使用多視圖模型的 R2 增益(絕對百分比)(或減少 RMSE 的相對百分比)中觀察到(與單個視圖內模型相比)。

misty.results %>%
  plot_improvement_stats("gain.R2") %>%
  plot_improvement_stats("gain.RMSE")

我們可以通過基于交叉驗證改進的assigned p-value進一步檢查解釋的方差增益的重要性。

misty.results$improvements %>%
  filter(measure == "p.R2") %>%
  group_by(target) %>% 
  summarize(mean.p = mean(value)) %>%
  arrange(mean.p)

In general, the significant gain in R2 can be interpreted as the following: “We can better explain the expression of marker X, when we consider additional views, other than the intrinsic view.”

2. How much do different view components contribute to explaining the expression?
misty.results %>% plot_view_contributions()

正如預期的那樣,對標記表達預測的大部分貢獻來自視圖內。 然而,對于我們觀察到方差顯著改善的marker,我們還可以觀察到 paraview 的比例估計貢獻。

3. What are the specific relations that can explain the contributions?

為了解釋contributions,我們可以將來自每個視圖的marker的重要性分別可視化為所有marker表達的預測因子。

First, the intraview importances.

misty.results %>% plot_interaction_heatmap(view = "intra", cutoff = 0.8)

這些importances與同一單元格中marker之間的關系有關。 由于我們在建模過程中沒有以任何方式使用有關細胞類型的信息,因此我們在熱圖中看到的重要相互作用可能來自任何細胞類型。

Second, the paraview importances.

misty.results %>% plot_interaction_heatmap(view = "para.10", cutoff = 0.5)

這些importances與細胞中的marker和更廣泛結構中的marker之間的關系有關(由我們的參數 l 控制)。

我們可以觀察到 paraview 中的一些交互可能是多余的,即它們在 intraview 中也很重要。 為了只關注來自 paraview 的交互,我們可以繪制這些結果之間的對比。

misty.results %>% plot_contrast_heatmap("intra", "para.10", cutoff = 0.5)

此外,由于兩個視圖中的預測變量和目標marker相同,我們可以從intraview的estimated interaction pairs中提取interaction communities并繪圖。

misty.results %>% plot_interaction_communities("intra")

and the paraview.

misty.results %>% plot_interaction_communities("para.10", cutoff = 0.5)

在解釋結果和圖時,重要的是要注意重要性中捕獲的關系不是假設或解釋為線性或隨意的。 此外,不應孤立地解釋單個預測變量 - marker對的估計重要性,而應在其他預測變量的上下文中進行解釋,因為訓練 MISTy 模型是多變量預測任務。

更多例子
browseVignettes("mistyR")

官網:https://www.bioconductor.org/packages/release/bioc/vignettes/mistyR/inst/doc/mistyR.html#view-composition

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
禁止轉載,如需轉載請通過簡信或評論聯系作者。

推薦閱讀更多精彩內容