作者,Evil Genius
我们的课程很快了,我也需要准备大量的内容,如果大家有兴趣并且有条件可以参加一下培训课程,链接在2025年单细胞空间系列课程,我们21号开始上第一课。
今天我们准备一下关于高精度空间细胞通讯相关的内容。
对于细胞通讯,无论是单细胞还是空间,都是分析重要的一环,就难度上而言,空间通讯因为要考虑细胞之间的空间位置关系,所以分析更为复杂一点,其中通过三角网络计算细胞间的物理距离和配体-受体相互作用分数是一种常用的方法。
其中构建细胞类型的空间关系,就分为以下几步。
1、将每个细胞视为空间中的一个点
2、构建网络连接邻近细胞
3、基于这些连接计算细胞间的相互作用
那么空间通讯的主要分析思路如下:
1、构建空间网络
2、确定配体-受体基因对
3、计算相邻细胞间的配体-受体相互作用分数。
相互作用分数计算原理
对于每对相邻细胞(i,j),相互作用分数计算通常考虑:
细胞i中配体基因的表达水平
细胞j中受体基因的表达水平
两者的乘积或更复杂的统计量
我们来实现一下
其中R脚本的传参与python是类似的,示例如下
# 创建参数解析器
parser <- ArgumentParser(description = "空间转录组配受体分析")
# 添加参数
parser$add_argument("--expression", type = "character", help = "表达矩阵文件路径")
parser$add_argument("--locations", type = "character", help = "细胞位置文件路径")
parser$add_argument("--output", type = "character", help = "输出目录路径")
parser$add_argument("--lr_pairs", type = "character", default = NULL,
help = "自定义配体-受体对文件路径(可选)")
parser$add_argument("--n_cores", type = "integer", default = 4,
help = "使用的CPU核心数")
# 解析参数
args <- parser$parse_args()
其中无论是哪种空间平台,都会有表达矩阵和空间坐标信息,只是放的位置可能不同,像CosMx就是单独给的,所以大家要灵活运用。
高精度平台的细胞注释,也是大家需要认真做的。
完整脚本如下,比较简单,cell_types为细胞注释的列。
#!/usr/bin/env Rscript
###zhaoyunfei
###20250417
suppressPackageStartupMessages({
library(Giotto)
library(data.table)
library(ggplot2)
library(argparse)
})
parser <- ArgumentParser(description = "空间转录组配受体分析")
parser$add_argument("--expression", type = "character", help = "表达矩阵文件路径")
parser$add_argument("--locations", type = "character", help = "细胞位置文件路径")
parser$add_argument("--output", type = "character", help = "输出目录路径")
parser$add_argument("--lr_pairs", type = "character", default = NULL,
help = "自定义配体-受体对文件路径(可选)")
parser$add_argument("--n_cores", type = "integer", default = 4,
help = "使用的CPU核心数")
args <- parser$parse_args()
if (!file.exists(args$expression)) {
stop(paste("表达矩阵文件不存在:", args$expression))
}
if (!file.exists(args$locations)) {
stop(paste("位置文件不存在:", args$locations))
}
if (!dir.exists(args$output)) {
dir.create(args$output, recursive = TRUE)
}
cat("加载数据...\n")
expr_mat <- data.table::fread(args$expression)
loc_mat <- data.table::fread(args$locations)
if (!all(c("cell_ID", "x", "y") %in% colnames(loc_mat))) {
stop("位置文件必须包含'cell_ID', 'x', 'y'列")
}
cat("创建Giotto对象...\n")
my_giotto_object <- createGiottoObject(
expression = list(raw = as.matrix(expr_mat[, -1], rownames = expr_mat[[1]])),
spatial_locs = as.matrix(loc_mat[, .(x, y)]),
cell_metadata = data.frame(cell_ID = loc_mat$cell_ID),
gene_metadata = data.frame(gene_ID = colnames(expr_mat)[-1])
)
cat("处理数据...\n")
my_giotto_object <- filterGiotto(gobject = my_giotto_object)
my_giotto_object <- normalizeGiotto(gobject = my_giotto_object)
my_giotto_object <- addStatistics(gobject = my_giotto_object)
cat("创建Delaunay空间网络...\n")
my_giotto_object <- createSpatialNetwork(gobject = my_giotto_object,
method = "Delaunay",
name = "delaunay_network")
cat("进行配体-受体分析...\n")
if (!is.null(args$lr_pairs) && file.exists(args$lr_pairs)) {
lr_pairs <- fread(args$lr_pairs)
} else {
# 使用Giotto内置的配体-受体对
lr_pairs <- Giotto::getLigandReceptors()
}
# 计算配体-受体分数
lr_scores <- exprCellCellcom(
gobject = my_giotto_object,
cluster_column = "cell_types",
spatial_network_name = "delaunay_network",
random_iter = 100,
gene_set_1 = lr_pairs$ligand,
gene_set_2 = lr_pairs$receptor,
cores = args$n_cores
)
cat("保存结果...\n")
fwrite(lr_scores, file.path(args$output, "ligand_receptor_scores.csv"))
cat("生成可视化...\n")
### 可视化空间网络
spatial_plot <- spatPlot(
gobject = my_giotto_object,
show_network = TRUE,
network_color = "blue",
spatial_network_name = "delaunay_network",
point_size = 1.5,
save_param = list(
save_name = "spatial_network",
save_dir = args$output
)
)
# 可视化配体-受体相互作用热图
heatmap_plot <- heatmAPCellCellcom(
gobject = my_giotto_object,
comScores = lr_scores,
save_param = list(
save_name = "lr_interaction_heatmap",
save_dir = args$output
)
)
# 可视化特定配体-受体对的空间模式
if (nrow(lr_scores) > 0) {
top_lr <- lr_scores[order(-LR_expr)][1:5, unique(LR_comb)]
for (lr in top_lr) {
lr_plot <- spatCellCellcom(
gobject = my_giotto_object,
comScores = lr_scores,
selected_LR = lr,
show_plot = FALSE,
save_param = list(
save_name = paste0("lr_interaction_", gsub(" ", "_", lr)),
save_dir = args$output
)
)
}
}
cat("分析完成! 结果保存在:", args$output, "\n")
生活很好,有你更好