CARD — 空间转录组细胞类型反卷积(R 原生版)
概述
CARD(Conditional Autoregressive Regression for Deconvolution)是一个 R 包,用于从空间转录组数据反卷积细胞类型组成。它结合 scRNA-seq 参考数据和空间表达数据,使用条件自回归模型估计每个 spot 的细胞类型比例。
本 Skill 提供 R 全流程:使用 CARD 包进行反卷积计算 + 使用 CARD 原生函数进行可视化,并提供基于 ggplot2 的扩展可视化作为补充。
核心特性:
- R 原生实现:不依赖 Python 版本
- 多分辨率支持:Visium、Visium HD(16µm/8µm)
- 官方可视化:饼图、空间分布、相关性热图、基因表达图
- 扩展可视化:平均比例条形图、主导细胞类型空间分布
- 真实数据案例:胰腺导管腺癌(PDAC)Visium HD 16µm
适用场景
当用户需要执行以下任务时使用此 Skill:
- 使用 R 进行空间转录组细胞类型反卷积
- 从 Python 版 CARD 结果转换为 R 可视化兼容格式
- 提取 Visium HD 空间坐标用于下游分析
- 生成 CARD 官方可视化(饼图、空间分布、相关性热图等)
- 基于 ggplot2 生成自定义扩展可视化
安装
环境要求
- R: >= 4.0.0
- 操作系统: Windows 10, macOS, Ubuntu 18.04+
安装步骤
1. 安装 R
从 CRAN 下载并安装 R >= 4.0.0
2. 安装 CARD R 包
install.packages("devtools")
devtools::install_github("YingMa0107/CARD")
3. 安装依赖包
install.packages(c(
"SingleCellExperiment",
"SummarizedExperiment",
"concaveman",
"sp",
"Matrix",
"ggplot2",
"ggcorrplot",
"MuSiC",
"fields",
"MCMCpack",
"dplyr"
))
验证安装
library(CARD)
print("CARD 安装成功!")
常见安装问题
| 问题 | 解决方案 |
|---|---|
| installation of package 'CARD' had non-zero exit status | 确保 R >= 4.0.0;Windows 安装 Rtools |
| 依赖包安装失败 | 逐个安装依赖包,查看具体错误 |
CARD 反卷积原理
CARD 使用条件自回归(CAR)模型,将空间表达视为空间相邻 spot 的平滑函数,结合 scRNA-seq 参考,估计每个 spot 的细胞类型比例矩阵。
核心步骤:
- 构建参考:从 scRNA-seq 数据获取每种细胞类型的 marker 基因表达
- 创建 CARD 对象:合并 scRNA-seq 参考和空间表达/坐标
- 反卷积计算:使用 CAR 模型估计比例矩阵
- 可视化:官方
CARD.visualize.*函数 + 自定义 ggplot2
输入数据要求
| 数据 | 格式 | 说明 |
|---|---|---|
| scRNA-seq 表达矩阵 | matrix / dgCMatrix | 行=基因,列=细胞 |
| scRNA-seq 元数据 | data.frame | 至少包含 cellType 和 sampleInfo 列 |
| 空间表达矩阵 | matrix / dgCMatrix | 行=基因,列=spot |
| 空间坐标 | data.frame | 列名 x、y;行名=spot ID |
基因名需在 scRNA-seq 和空间数据之间一致。
完整可运行脚本
以下脚本均为最小可运行示例,按需复制到 .R 文件执行。
注意:脚本中
I:/TRAE skill 数据分析/...为示例路径,使用时请替换为实际数据路径。
脚本 1 — 提取 CARD 分析用空间坐标
# Author: LKP <kunpeng.liao@abiosciences.com>
# Date: 2026-08-18
#
# extract_card_coordinates.R
# 提取CARD分析用的空间坐标
library(Seurat)
# 设置工作目录
setwd("I:/TRAE skill 数据分析/untested-skills-test/spatial-16um-test")
# 读取比例数据以获取spot名称
prop_df <- read.csv("card_16um_results/card_cell_type_proportions_16um.csv", row.names = 1)
print("比例数据spot数量:")
print(nrow(prop_df))
print("前5个spot名称:")
print(rownames(prop_df)[1:5])
# 读取空间数据
spatial_dir <- "I:/TRAE skill 数据分析/测试数据/空间-HD/binned_outputs/square_016um"
spatial_data <- Load10X_Spatial(
data.dir = spatial_dir,
filename = "filtered_feature_bc_matrix.h5"
)
# 提取空间坐标
spatial_location <- GetTissueCoordinates(spatial_data)
spatial_location <- spatial_location[, c("x", "y")]
print("空间数据spot数量:")
print(nrow(spatial_location))
print("前5个spot名称:")
print(rownames(spatial_location)[1:5])
# 只保留与CARD结果匹配的spots
spatial_location_matched <- spatial_location[rownames(prop_df), ]
print("匹配后的spot数量:")
print(nrow(spatial_location_matched))
print("前5行:")
print(head(spatial_location_matched, 5))
# 保存坐标
write.csv(spatial_location_matched, "card_16um_results/card_spatial_coordinates_16um.csv")
print("✓ 空间坐标已保存到 card_16um_results/card_spatial_coordinates_16um.csv")
脚本 2 — Python 版 CARD 结果转 R 兼容 RDS
# Author: LKP <kunpeng.liao@abiosciences.com>
# Date: 2026-08-18
#
# convert_card_to_rds.R
# 将CARD Python版数据转换为RDS格式并修复S4类型
library(CARD)
library(Seurat)
# 设置工作目录
setwd("I:/TRAE skill 数据分析/untested-skills-test/spatial-16um-test")
print("==================================================")
print("CARD数据转换 - Python版转RDS格式")
print("==================================================")
# 1. 读取Python版CARD结果
print("\n【1/5】读取Python版CARD结果...")
prop_df <- read.csv("card_16um_results/card_cell_type_proportions_16um.csv", row.names = 1)
print(paste(" 比例数据:", nrow(prop_df), "spots x", ncol(prop_df), "cell types"))
# 读取空间坐标
spatial_coord <- read.csv("card_16um_results/card_spatial_coordinates_16um.csv", row.names = 1)
print(paste(" 空间坐标:", nrow(spatial_coord), "spots"))
# 2. 创建最小化的CARD对象结构
print("\n【2/5】创建CARD兼容的数据结构...")
# 将比例数据转换为普通矩阵(避免S4类型问题)
prop_matrix <- as.matrix(prop_df)
print(paste(" 比例矩阵类型:", class(prop_matrix)))
print(paste(" 比例矩阵维度:", nrow(prop_matrix), "x", ncol(prop_matrix)))
# 确保空间坐标是data.frame
spatial_loc <- as.data.frame(spatial_coord[, c("x", "y")])
print(paste(" 空间坐标类型:", class(spatial_loc)))
print(paste(" 空间坐标维度:", nrow(spatial_loc), "x", ncol(spatial_loc)))
# 3. 尝试创建S4对象(可选)
print("\n【3/5】创建S4对象...")
# 定义一个简单的S4类来存储结果
setClass("CARDResult",
slots = list(
Proportion_CARD = "matrix",
spatial_location = "data.frame"
))
# 创建对象
CARD_result <- new("CARDResult",
Proportion_CARD = prop_matrix,
spatial_location = spatial_loc)
print(" S4对象创建成功")
print(paste(" Proportion_CARD类型:", class(CARD_result@Proportion_CARD)))
# 4. 保存为RDS
print("\n【4/5】保存为RDS格式...")
saveRDS(CARD_result, "card_16um_results/CARD_result_converted.rds")
print(" ✓ 已保存到 card_16um_results/CARD_result_converted.rds")
# 同时保存为RData(兼容性更好)
save(CARD_result, prop_matrix, spatial_loc, file = "card_16um_results/CARD_result_converted.RData")
print(" ✓ 已保存到 card_16um_results/CARD_result_converted.RData")
# 5. 测试直接可视化(不通过S4对象)
print("\n【5/5】测试直接可视化...")
# 定义颜色
colors <- c("#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd",
"#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf",
"#aec7e8", "#ffbb78", "#98df8a", "#ff9896")
# 测试1:饼图
print(" 测试饼图...")
tryCatch({
p_pie <- CARD.visualize.pie(
proportion = prop_matrix,
spatial_location = spatial_loc,
colors = colors,
radius = 0.52
)
print(" ✓ 饼图函数调用成功")
# 保存
pdf("card_16um_results/card_r_visualization_pie_test.pdf", width = 10, height = 8)
print(p_pie)
dev.off()
print(" ✓ 饼图已保存")
}, error = function(e) {
print(paste(" ⚠️ 饼图失败:", e$message))
})
# 测试2:单个细胞类型分布
print(" 测试单个细胞类型分布...")
ct.visualize <- colnames(prop_matrix)[1:min(4, ncol(prop_matrix))]
print(paste(" 可视化细胞类型:", paste(ct.visualize, collapse = ", ")))
tryCatch({
p_prop <- CARD.visualize.prop(
proportion = prop_matrix,
spatial_location = spatial_loc,
ct.visualize = ct.visualize,
colors = c("lightblue", "lightyellow", "red"),
NumCols = 2,
pointSize = 3.0
)
print(" ✓ 单个细胞类型分布函数调用成功")
# 保存
pdf("card_16um_results/card_r_visualization_prop_test.pdf", width = 12, height = 10)
print(p_prop)
dev.off()
print(" ✓ 单个细胞类型分布图已保存")
}, error = function(e) {
print(paste(" ⚠️ 单个细胞类型分布失败:", e$message))
})
# 测试3:相关性热图
print(" 测试相关性热图...")
tryCatch({
p_cor <- CARD.visualize.Cor(prop_matrix, colors = NULL)
print(" ✓ 相关性热图函数调用成功")
# 保存
pdf("card_16um_results/card_r_visualization_cor_test.pdf", width = 10, height = 8)
print(p_cor)
dev.off()
print(" ✓ 相关性热图已保存")
}, error = function(e) {
print(paste(" ⚠️ 相关性热图失败:", e$message))
})
print("\n==================================================")
print("转换完成!")
print("==================================================")
print("\n生成的文件:")
print(" 📦 CARD_result_converted.rds - S4对象")
print(" 📦 CARD_result_converted.RData - 包含所有变量")
print(" 🖼️ card_r_visualization_*_test.pdf - 测试可视化")
脚本 3 — CARD 官方可视化(基于 RDS 对象)
# Author: LKP <kunpeng.liao@abiosciences.com>
# Date: 2026-08-18
#
# card_official_visualization.R
# 基于CARD包原生函数生成可视化
library(CARD)
library(ggplot2)
# 设置工作目录
setwd("I:/TRAE skill 数据分析/untested-skills-test/spatial-16um-test")
# 读取CARD结果
CARD_obj <- readRDS("card_16um_results/card_object_16um.rds")
print("CARD对象内容:")
print(slotNames(CARD_obj))
# 读取比例数据
prop_df <- read.csv("card_16um_results/card_cell_type_proportions_16um.csv", row.names = 1)
print("比例数据维度:")
print(dim(prop_df))
print("前5行:")
print(head(prop_df, 5))
# 获取空间坐标
spatial_loc <- CARD_obj@spatial_location
print("空间坐标维度:")
print(dim(spatial_loc))
print("前5行:")
print(head(spatial_loc, 5))
# 定义颜色
colors <- c("#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd",
"#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf",
"#aec7e8", "#ffbb78", "#98df8a", "#ff9896")
# 1. 饼图可视化 (适合<500 spots)
print("生成饼图...")
tryCatch({
p_pie <- CARD.visualize.pie(
proportion = CARD_obj@Proportion_CARD,
spatial_location = CARD_obj@spatial_location,
colors = colors,
radius = 0.52
)
# 保存PDF
pdf("card_official_pie.pdf", width = 10, height = 8)
print(p_pie)
dev.off()
# 保存PNG
png("card_official_pie.png", width = 1000, height = 800, res = 150)
print(p_pie)
dev.off()
print("✅ 饼图生成成功")
}, error = function(e) {
print(paste("⚠️ 饼图生成失败:", e$message))
})
# 2. 单个细胞类型空间分布
print("生成单个细胞类型分布图...")
ct.visualize <- colnames(prop_df)[1:min(8, ncol(prop_df))]
print(paste("可视化细胞类型:", paste(ct.visualize, collapse = ", ")))
tryCatch({
p_prop <- CARD.visualize.prop(
proportion = CARD_obj@Proportion_CARD,
spatial_location = CARD_obj@spatial_location,
ct.visualize = ct.visualize,
colors = c("lightblue", "lightyellow", "red"),
NumCols = 4,
pointSize = 3.0
)
# 保存PDF
pdf("card_official_prop_individual.pdf", width = 16, height = 12)
print(p_prop)
dev.off()
# 保存PNG
png("card_official_prop_individual.png", width = 1600, height = 1200, res = 150)
print(p_prop)
dev.off()
print("✅ 单个细胞类型分布图生成成功")
}, error = function(e) {
print(paste("⚠️ 单个细胞类型分布图生成失败:", e$message))
})
# 3. 两个细胞类型对比
print("生成两个细胞类型对比图...")
if(ncol(prop_df) >= 2) {
ct2.visualize <- colnames(prop_df)[1:2]
print(paste("对比细胞类型:", paste(ct2.visualize, collapse = " vs ")))
tryCatch({
p_2ct <- CARD.visualize.prop.2CT(
proportion = CARD_obj@Proportion_CARD,
spatial_location = CARD_obj@spatial_location,
ct2.visualize = ct2.visualize,
colors = list(
c("lightblue", "lightyellow", "red"),
c("lightblue", "lightyellow", "black")
)
)
# 保存PDF
pdf("card_official_2celltypes.pdf", width = 12, height = 10)
print(p_2ct)
dev.off()
# 保存PNG
png("card_official_2celltypes.png", width = 1200, height = 1000, res = 150)
print(p_2ct)
dev.off()
print("✅ 两个细胞类型对比图生成成功")
}, error = function(e) {
print(paste("⚠️ 两个细胞类型对比图生成失败:", e$message))
})
}
# 4. 细胞类型相关性热图
print("生成细胞类型相关性热图...")
tryCatch({
p_cor <- CARD.visualize.Cor(CARD_obj@Proportion_CARD, colors = NULL)
# 保存PDF
pdf("card_official_correlation.pdf", width = 10, height = 8)
print(p_cor)
dev.off()
# 保存PNG
png("card_official_correlation.png", width = 1000, height = 800, res = 150)
print(p_cor)
dev.off()
print("✅ 细胞类型相关性热图生成成功")
}, error = function(e) {
print(paste("⚠️ 细胞类型相关性热图生成失败:", e$message))
})
# 5. 基因表达可视化 (使用空间数据)
print("生成基因表达图...")
# 获取高表达基因
spatial_counts <- CARD_obj@spatial_countMat
mean_exp <- rowMeans(spatial_counts)
top_genes <- names(sort(mean_exp, decreasing = TRUE))[1:6]
print(paste("可视化基因:", paste(top_genes, collapse = ", ")))
tryCatch({
p_gene <- CARD.visualize.gene(
spatial_expression = CARD_obj@spatial_countMat,
spatial_location = CARD_obj@spatial_location,
gene.visualize = top_genes,
colors = NULL,
NumCols = 3
)
# 保存PDF
pdf("card_official_gene_expression.pdf", width = 15, height = 10)
print(p_gene)
dev.off()
# 保存PNG
png("card_official_gene_expression.png", width = 1500, height = 1000, res = 150)
print(p_gene)
dev.off()
print("✅ 基因表达图生成成功")
}, error = function(e) {
print(paste("⚠️ 基因表达图生成失败:", e$message))
})
print("官方可视化生成完成!")
print("生成的文件:")
print(list.files(pattern = "card_official.*\\.(pdf|png)$"))
脚本 4 — CARD 官方可视化 v2(基于 CSV 数据)
# Author: LKP <kunpeng.liao@abiosciences.com>
# Date: 2026-08-18
#
# card_official_visualization_v2.R
# 基于CARD包原生函数生成可视化 - 使用CSV数据
library(CARD)
library(ggplot2)
library(reshape2)
# 设置工作目录
setwd("I:/TRAE skill 数据分析/untested-skills-test/spatial-16um-test")
# 读取比例数据
prop_df <- read.csv("card_16um_results/card_cell_type_proportions_16um.csv", row.names = 1)
print("比例数据维度:")
print(dim(prop_df))
print("细胞类型:")
print(colnames(prop_df))
# 读取空间坐标
spatial_coord <- read.csv("card_16um_results/card_spatial_coordinates_16um.csv", row.names = 1)
print("空间坐标维度:")
print(dim(spatial_coord))
print("前5行:")
print(head(spatial_coord, 5))
# 定义颜色
colors <- c("#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd",
"#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf",
"#aec7e8", "#ffbb78", "#98df8a", "#ff9896")
# 1. 饼图可视化 (适合<500 spots)
print("生成饼图...")
tryCatch({
# 确保数据格式正确
prop_matrix <- as.matrix(prop_df)
spatial_loc <- spatial_coord[, c("x", "y")]
p_pie <- CARD.visualize.pie(
proportion = prop_matrix,
spatial_location = spatial_loc,
colors = colors,
radius = 0.52
)
# 保存PDF
pdf("card_16um_results/card_official_pie.pdf", width = 10, height = 8)
print(p_pie)
dev.off()
# 保存PNG
png("card_16um_results/card_official_pie.png", width = 1000, height = 800, res = 150)
print(p_pie)
dev.off()
print("✅ 饼图生成成功")
}, error = function(e) {
print(paste("⚠️ 饼图生成失败:", e$message))
})
# 2. 单个细胞类型空间分布
print("生成单个细胞类型分布图...")
ct.visualize <- colnames(prop_df)[1:min(8, ncol(prop_df))]
print(paste("可视化细胞类型:", paste(ct.visualize, collapse = ", ")))
tryCatch({
prop_matrix <- as.matrix(prop_df)
spatial_loc <- spatial_coord[, c("x", "y")]
p_prop <- CARD.visualize.prop(
proportion = prop_matrix,
spatial_location = spatial_loc,
ct.visualize = ct.visualize,
colors = c("lightblue", "lightyellow", "red"),
NumCols = 4,
pointSize = 3.0
)
# 保存PDF
pdf("card_16um_results/card_official_prop_individual.pdf", width = 16, height = 12)
print(p_prop)
dev.off()
# 保存PNG
png("card_16um_results/card_official_prop_individual.png", width = 1600, height = 1200, res = 150)
print(p_prop)
dev.off()
print("✅ 单个细胞类型分布图生成成功")
}, error = function(e) {
print(paste("⚠️ 单个细胞类型分布图生成失败:", e$message))
})
# 3. 两个细胞类型对比
print("生成两个细胞类型对比图...")
if(ncol(prop_df) >= 2) {
ct2.visualize <- colnames(prop_df)[1:2]
print(paste("对比细胞类型:", paste(ct2.visualize, collapse = " vs ")))
tryCatch({
prop_matrix <- as.matrix(prop_df)
spatial_loc <- spatial_coord[, c("x", "y")]
p_2ct <- CARD.visualize.prop.2CT(
proportion = prop_matrix,
spatial_location = spatial_loc,
ct2.visualize = ct2.visualize,
colors = list(
c("lightblue", "lightyellow", "red"),
c("lightblue", "lightyellow", "black")
)
)
# 保存PDF
pdf("card_16um_results/card_official_2celltypes.pdf", width = 12, height = 10)
print(p_2ct)
dev.off()
# 保存PNG
png("card_16um_results/card_official_2celltypes.png", width = 1200, height = 1000, res = 150)
print(p_2ct)
dev.off()
print("✅ 两个细胞类型对比图生成成功")
}, error = function(e) {
print(paste("⚠️ 两个细胞类型对比图生成失败:", e$message))
})
}
# 4. 细胞类型相关性热图
print("生成细胞类型相关性热图...")
tryCatch({
prop_matrix <- as.matrix(prop_df)
p_cor <- CARD.visualize.Cor(prop_matrix, colors = NULL)
# 保存PDF
pdf("card_16um_results/card_official_correlation.pdf", width = 10, height = 8)
print(p_cor)
dev.off()
# 保存PNG
png("card_16um_results/card_official_correlation.png", width = 1000, height = 800, res = 150)
print(p_cor)
dev.off()
print("✅ 细胞类型相关性热图生成成功")
}, error = function(e) {
print(paste("⚠️ 细胞类型相关性热图生成失败:", e$message))
})
print("官方可视化生成完成!")
print("生成的文件:")
print(list.files("card_16um_results", pattern = "card_official.*\\.(pdf|png)$"))
脚本 5 — CARD 完整 R 可视化(含饼图/分布/扩展)
# Author: LKP <kunpeng.liao@abiosciences.com>
# Date: 2026-08-18
#
# card_complete_r_visualization.R
# 使用转换后的数据生成所有官方可视化
library(CARD)
library(ggplot2)
library(gridExtra)
# 设置工作目录
setwd("I:/TRAE skill 数据分析/untested-skills-test/spatial-16um-test")
print("==================================================")
print("CARD 完整R可视化")
print("==================================================")
# 1. 读取转换后的数据
print("\n【1/4】读取转换后的数据...")
load("card_16um_results/CARD_result_converted.RData")
print(" ✓ 数据加载成功")
# 提取数据
prop_matrix <- CARD_result@Proportion_CARD
spatial_loc <- CARD_result@spatial_location
print(paste(" 比例矩阵:", nrow(prop_matrix), "spots x", ncol(prop_matrix), "cell types"))
print(paste(" 细胞类型:", paste(colnames(prop_matrix), collapse = ", ")))
# 计算统计
mean_props <- colMeans(prop_matrix)
mean_props_sorted <- sort(mean_props, decreasing = TRUE)
top4_cell_types <- names(mean_props_sorted)[1:4]
print("\n各细胞类型平均比例:")
for (ct in names(mean_props_sorted)) {
print(paste(" -", ct, ":", round(mean_props_sorted[ct], 4),
paste0("(", round(mean_props_sorted[ct]*100, 2), "%)")))
}
# 2. 定义颜色方案
print("\n【2/4】定义颜色方案...")
colors <- c("#1f77b4", "#ff7f0e", "#2ca02c", "#d62728", "#9467bd",
"#8c564b", "#e377c2", "#7f7f7f", "#bcbd22", "#17becf",
"#aec7e8", "#ffbb78", "#98df8a", "#ff9896")
# 3. 生成所有可视化
print("\n【3/4】生成所有可视化...")
# 1. 饼图可视化
print(" 1/7 生成饼图...")
p_pie <- CARD.visualize.pie(
proportion = prop_matrix,
spatial_location = spatial_loc,
colors = colors,
radius = 0.52
)
# 保存饼图
pdf("card_16um_results/card_r_pie.pdf", width = 10, height = 8)
print(p_pie)
dev.off()
png("card_16um_results/card_r_pie.png", width = 1000, height = 800, res = 150)
print(p_pie)
dev.off()
print(" ✓ 饼图已保存")
# 2. 前4种细胞类型分布
print(" 2/7 生成前4种细胞类型分布...")
p_top4 <- CARD.visualize.prop(
proportion = prop_matrix,
spatial_location = spatial_loc,
ct.visualize = top4_cell_types,
colors = c("lightblue", "lightyellow", "red"),
NumCols = 2,
pointSize = 3.0
)
# 保存
pdf("card_16um_results/card_r_top4_celltypes.pdf", width = 14, height = 12)
print(p_top4)
dev.off()
png("card_16um_results/card_r_top4_celltypes.png", width = 1400, height = 1200, res = 150)
print(p_top4)
dev.off()
print(" ✓ 前4种细胞类型分布已保存")
# 3. 所有细胞类型分布(分两组)
print(" 3/7 生成所有细胞类型分布...")
all_cell_types <- colnames(prop_matrix)
# 第一组:前7种
p_all_1 <- CARD.visualize.prop(
proportion = prop_matrix,
spatial_location = spatial_loc,
ct.visualize = all_cell_types[1:7],
colors = c("lightblue", "lightyellow", "red"),
NumCols = 4,
pointSize = 2.5
)
pdf("card_16um_results/card_r_all_celltypes_1.pdf", width = 16, height = 10)
print(p_all_1)
dev.off()
png("card_16um_results/card_r_all_celltypes_1.png", width = 1600, height = 1000, res = 150)
print(p_all_1)
dev.off()
# 第二组:后7种
p_all_2 <- CARD.visualize.prop(
proportion = prop_matrix,
spatial_location = spatial_loc,
ct.visualize = all_cell_types[8:14],
colors = c("lightblue", "lightyellow", "red"),
NumCols = 4,
pointSize = 2.5
)
pdf("card_16um_results/card_r_all_celltypes_2.pdf", width = 16, height = 10)
print(p_all_2)
dev.off()
png("card_16um_results/card_r_all_celltypes_2.png", width = 1600, height = 1000, res = 150)
print(p_all_2)
dev.off()
print(" ✓ 所有细胞类型分布已保存")
# 4. 两个细胞类型对比
print(" 4/7 生成两个细胞类型对比...")
if (ncol(prop_matrix) >= 2) {
ct2 <- names(mean_props_sorted)[1:2]
p_2ct <- CARD.visualize.prop.2CT(
proportion = prop_matrix,
spatial_location = spatial_loc,
ct2.visualize = ct2,
colors = list(
c("lightblue", "lightyellow", "red"),
c("lightblue", "lightyellow", "black")
)
)
pdf("card_16um_results/card_r_2celltypes_comparison.pdf", width = 12, height = 10)
print(p_2ct)
dev.off()
png("card_16um_results/card_r_2celltypes_comparison.png", width = 1200, height = 1000, res = 150)
print(p_2ct)
dev.off()
print(" ✓ 两个细胞类型对比已保存")
}
# 5. 细胞类型相关性热图
print(" 5/7 生成细胞类型相关性热图...")
p_cor <- CARD.visualize.Cor(prop_matrix, colors = NULL)
pdf("card_16um_results/card_r_correlation_heatmap.pdf", width = 12, height = 10)
print(p_cor)
dev.off()
png("card_16um_results/card_r_correlation_heatmap.png", width = 1200, height = 1000, res = 150)
print(p_cor)
dev.off()
print(" ✓ 细胞类型相关性热图已保存")
# 6. 自定义:平均比例条形图
print(" 6/7 生成平均比例条形图...")
p_bar <- ggplot(data.frame(
CellType = names(mean_props_sorted),
Proportion = mean_props_sorted
), aes(x = reorder(CellType, Proportion), y = Proportion, fill = CellType)) +
geom_bar(stat = "identity") +
coord_flip() +
scale_fill_manual(values = colors) +
labs(title = "CARD: Mean Cell Type Proportions",
x = "Cell Type",
y = "Mean Proportion") +
theme_minimal() +
theme(legend.position = "none")
pdf("card_16um_results/card_r_mean_proportions_barplot.pdf", width = 10, height = 8)
print(p_bar)
dev.off()
png("card_16um_results/card_r_mean_proportions_barplot.png", width = 1000, height = 800, res = 150)
print(p_bar)
dev.off()
print(" ✓ 平均比例条形图已保存")
# 7. 自定义:主导细胞类型分布
print(" 7/7 生成主导细胞类型分布...")
dominant_types <- colnames(prop_matrix)[apply(prop_matrix, 1, which.max)]
dominant_df <- data.frame(
x = spatial_loc$x,
y = spatial_loc$y,
DominantType = dominant_types
)
# 为每种主导类型分配颜色
type_colors <- setNames(colors[1:length(unique(dominant_types))], unique(dominant_types))
p_dominant <- ggplot(dominant_df, aes(x = x, y = y, color = DominantType)) +
geom_point(size = 2, alpha = 0.8) +
scale_color_manual(values = type_colors) +
labs(title = "CARD: Dominant Cell Type Distribution",
x = "X coordinate",
y = "Y coordinate") +
theme_minimal() +
coord_equal() +
theme(legend.position = "right")
pdf("card_16um_results/card_r_dominant_celltypes.pdf", width = 14, height = 10)
print(p_dominant)
dev.off()
png("card_16um_results/card_r_dominant_celltypes.png", width = 1400, height = 1000, res = 150)
print(p_dominant)
dev.off()
print(" ✓ 主导细胞类型分布已保存")
# 4. 生成总结报告
print("\n【4/4】生成总结报告...")
sink("card_16um_results/card_r_visualization_summary.txt")
cat("=== CARD R可视化总结 ===\n\n")
cat("生成时间:", format(Sys.time(), "%Y-%m-%d %H:%M:%S"), "\n")
cat("数据: 转换后的Python版CARD结果\n")
cat("Spots:", nrow(prop_matrix), "\n")
cat("细胞类型:", ncol(prop_matrix), "\n\n")
cat("生成的可视化文件:\n")
cat(" 1. card_r_pie.pdf/png - 饼图\n")
cat(" 2. card_r_top4_celltypes.pdf/png - 前4种细胞类型分布\n")
cat(" 3. card_r_all_celltypes_1.pdf/png - 所有细胞类型分布(第1组)\n")
cat(" 4. card_r_all_celltypes_2.pdf/png - 所有细胞类型分布(第2组)\n")
cat(" 5. card_r_2celltypes_comparison.pdf/png - 两个细胞类型对比\n")
cat(" 6. card_r_correlation_heatmap.pdf/png - 细胞类型相关性热图\n")
cat(" 7. card_r_mean_proportions_barplot.pdf/png - 平均比例条形图\n")
cat(" 8. card_r_dominant_celltypes.pdf/png - 主导细胞类型分布\n\n")
cat("各细胞类型平均比例:\n")
for (ct in names(mean_props_sorted)) {
cat(paste(" -", ct, ":", round(mean_props_sorted[ct], 4),
paste0("(", round(mean_props_sorted[ct]*100, 2), "%)"), "\n"))
}
sink()
print(" ✓ 总结报告已保存")
print("\n==================================================")
print("R可视化完成!")
print("==================================================")
print("\n生成的文件 (共16个):")
print(" 🖼️ 8个PDF文件")
print(" 🖼️ 8个PNG文件")
print(" 📝 1个总结报告")
print("\n关键发现:")
print(paste(" - 主导细胞类型:", names(mean_props_sorted)[1],
paste0("(", round(mean_props_sorted[1]*100, 2), "%)")))
print(paste(" - 可视化成功率: 100% (修复了S4类型转换错误)"))
脚本 6 — CARD 胰腺癌 Visium HD 16µm 全流程分析
#!/usr/bin/env Rscript
# Author: LKP <kunpeng.liao@abiosciences.com>
# Date: 2026-08-18
#
# card_pancreas_16um.R
# CARD 胰腺癌Visium HD 16um分辨率空间反卷积分析
# CARD: Conditional Autoregressive Regression for Deconvolution
library(CARD)
library(Seurat)
library(ggplot2)
library(dplyr)
library(reshape2)
print("==================================================")
print("CARD 胰腺癌Visium HD 16um空间反卷积分析")
print("==================================================")
# 设置工作目录
work_dir <- "I:/TRAE skill 数据分析/untested-skills-test/spatial-16um-test"
setwd(work_dir)
# 创建结果目录
results_dir <- "card_16um_results"
if (!dir.exists(results_dir)) {
dir.create(results_dir, recursive = TRUE)
}
# 1. 读取单细胞参考数据
print("\n【1/5】读取单细胞参考数据...")
sc_data <- readRDS("I:/TRAE skill 数据分析/测试数据/胰腺癌单细胞测序数据/scAtlas.rds")
# 提取表达矩阵和细胞类型
sc_count <- GetAssayData(sc_data, layer = "counts")
sc_meta <- data.frame(
cellType = sc_data$Clusters,
sampleInfo = sc_data$Name,
row.names = colnames(sc_data)
)
print(paste(" 单细胞数据:", ncol(sc_count), "cells,", nrow(sc_count), "genes"))
print(paste(" 细胞类型数:", length(unique(sc_meta$cellType))))
# 2. 读取空间转录组数据(16um分辨率)
print("\n【2/5】读取空间转录组数据 (16um)...")
spatial_dir <- "I:/TRAE skill 数据分析/测试数据/空间-HD/binned_outputs/square_016um"
# 读取空间数据
spatial_data <- Load10X_Spatial(
data.dir = spatial_dir,
filename = "filtered_feature_bc_matrix.h5"
)
# 提取表达矩阵
spatial_count <- GetAssayData(spatial_data, layer = "counts")
# 读取空间坐标
spatial_location <- GetTissueCoordinates(spatial_data)
spatial_location <- spatial_location[, c("x", "y")]
print(paste(" 空间数据:", ncol(spatial_count), "spots,", nrow(spatial_count), "genes"))
print(paste(" 空间坐标:", nrow(spatial_location), "spots"))
# 采样spots(可选,加快分析)
if (ncol(spatial_count) > 5000) {
print(" 采样5000个spots...")
set.seed(42)
selected_spots <- sample(colnames(spatial_count), 5000)
spatial_count <- spatial_count[, selected_spots]
spatial_location <- spatial_location[selected_spots, ]
print(paste(" 采样后:", ncol(spatial_count), "spots"))
}
# 3. 准备CARD数据
print("\n【3/5】准备CARD数据...")
# 创建CARD对象
CARD_obj <- createCARDObject(
sc_count = sc_count,
sc_meta = sc_meta,
spatial_count = spatial_count,
spatial_location = spatial_location,
ct.varname = "cellType",
sample.varname = "sampleInfo",
ct.select = unique(sc_meta$cellType) # 选择所有细胞类型
)
print(" ✓ CARD对象创建成功")
# 4. 运行CARD反卷积
print("\n【4/5】运行CARD反卷积...")
print(" 这可能需要10-20分钟,请耐心等待...")
# 运行CARD
CARD_obj <- CARD_deconvolution(CARD_obj)
print(" ✓ CARD反卷积完成")
# 5. 提取和保存结果
print("\n【5/5】提取和保存结果...")
# 提取比例矩阵
prop_df <- CARD_obj@Proportion_CARD
# 保存比例矩阵
write.csv(prop_df, file = paste0(results_dir, "/card_cell_type_proportions_16um.csv"))
# 计算统计
mean_props <- colMeans(prop_df)
mean_props_sorted <- sort(mean_props, decreasing = TRUE)
print("\n各细胞类型平均比例:")
for (ct in names(mean_props_sorted)) {
print(paste(" -", ct, ":", round(mean_props_sorted[ct], 4),
paste0("(", round(mean_props_sorted[ct]*100, 2), "%)")))
}
# 验证总和
total <- sum(mean_props)
print(paste("\n所有细胞类型比例总和:", round(total, 4), "(应该是1.0)"))
# 主要细胞类型
dominant_types <- colnames(prop_df)[apply(prop_df, 1, which.max)]
dominant_counts <- table(dominant_types)
print("\n各细胞类型作为主要类型的Spot数:")
for (ct in names(sort(dominant_counts, decreasing = TRUE))) {
pct <- dominant_counts[ct] / nrow(prop_df) * 100
print(paste(" -", ct, ":", dominant_counts[ct], "spots (", round(pct, 1), "%)"))
}
# 保存统计结果
sink(paste0(results_dir, "/card_statistics_16um.txt"))
cat("=== CARD 胰腺癌16um反卷积结果统计 ===\n\n")
cat("分析日期:", format(Sys.time(), "%Y-%m-%d %H:%M:%S"), "\n")
cat("样本: 胰腺癌Visium HD 16um\n")
cat("Spots:", nrow(prop_df), "\n")
cat("细胞类型:", ncol(prop_df), "\n\n")
cat("各细胞类型平均比例:\n")
for (ct in names(mean_props_sorted)) {
cat(paste(" -", ct, ":", round(mean_props_sorted[ct], 4),
paste0("(", round(mean_props_sorted[ct]*100, 2), "%)"), "\n"))
}
cat("\n各细胞类型作为主要类型的Spot数:\n")
for (ct in names(sort(dominant_counts, decreasing = TRUE))) {
pct <- dominant_counts[ct] / nrow(prop_df) * 100
cat(paste(" -", ct, ":", dominant_counts[ct], "spots (", round(pct, 1), "%)\n"))
}
sink()
print("\n ✓ 统计结果已保存")
# 6. 生成可视化
print("\n生成可视化...")
# 设置图形参数
options(repr.plot.width = 14, repr.plot.height = 12)
# 1. 平均比例条形图
print(" 生成平均比例条形图...")
pdf(paste0(results_dir, "/card_mean_proportions_16um.pdf"), width = 12, height = 8)
par(mar = c(5, 10, 4, 2))
barplot(mean_props_sorted, horiz = TRUE, las = 1,
main = "CARD 16um: Mean Cell Type Proportions",
xlab = "Mean Proportion", col = heat.colors(length(mean_props_sorted)))
dev.off()
png(paste0(results_dir, "/card_mean_proportions_16um.png"), width = 1200, height = 800, res = 150)
par(mar = c(5, 10, 4, 2))
barplot(mean_props_sorted, horiz = TRUE, las = 1,
main = "CARD 16um: Mean Cell Type Proportions",
xlab = "Mean Proportion", col = heat.colors(length(mean_props_sorted)))
dev.off()
# 2. 空间可视化(前4种细胞类型)
print(" 生成空间可视化...")
top4_cell_types <- names(mean_props_sorted)[1:4]
for (ct in top4_cell_types) {
# PDF
pdf(paste0(results_dir, "/card_spatial_", gsub(" ", "_", ct), "_16um.pdf"),
width = 10, height = 8)
plot(CARD_obj, ct.name = ct,
main = paste(ct, "(CARD 16um)"))
dev.off()
# PNG
png(paste0(results_dir, "/card_spatial_", gsub(" ", "_", ct), "_16um.png"),
width = 1000, height = 800, res = 150)
plot(CARD_obj, ct.name = ct,
main = paste(ct, "(CARD 16um)"))
dev.off()
}
# 3. 所有细胞类型热图
print(" 生成所有细胞类型热图...")
pdf(paste0(results_dir, "/card_all_cell_types_16um.pdf"), width = 20, height = 16)
plot(CARD_obj,
main = "CARD 16um: All Cell Types",
layout = c(5, 3))
dev.off()
png(paste0(results_dir, "/card_all_cell_types_16um.png"),
width = 2000, height = 1600, res = 150)
plot(CARD_obj,
main = "CARD 16um: All Cell Types",
layout = c(5, 3))
dev.off()
# 4. 相关性热图
print(" 生成相关性热图...")
corr_matrix <- cor(prop_df)
pdf(paste0(results_dir, "/card_cell_type_correlation_16um.pdf"), width = 12, height = 10)
heatmap(corr_matrix,
main = "CARD 16um: Cell Type Correlation Matrix",
col = colorRampPalette(c("blue", "white", "red"))(100),
symm = TRUE)
dev.off()
png(paste0(results_dir, "/card_cell_type_correlation_16um.png"),
width = 1200, height = 1000, res = 150)
heatmap(corr_matrix,
main = "CARD 16um: Cell Type Correlation Matrix",
col = colorRampPalette(c("blue", "white", "red"))(100),
symm = TRUE)
dev.off()
print(" ✓ 可视化已保存")
# 7. 保存CARD对象
saveRDS(CARD_obj, file = paste0(results_dir, "/card_object_16um.rds"))
print("\n==================================================")
print("CARD 16um分析完成!")
print("==================================================")
print("\n输出文件:")
print(" 📊 card_cell_type_proportions_16um.csv")
print(" 📦 card_object_16um.rds")
print(" 🖼️ card_mean_proportions_16um.png/pdf")
print(" 🖼️ card_spatial_*_16um.png/pdf (4个)")
print(" 🖼️ card_all_cell_types_16um.png/pdf")
print(" 🖼️ card_cell_type_correlation_16um.png/pdf")
print(" 📝 card_statistics_16um.txt")
脚本 7 — CARD 胰腺癌 Visium HD 16µm v2(采样版,更快)
#!/usr/bin/env Rscript
# Author: LKP <kunpeng.liao@abiosciences.com>
# Date: 2026-08-18
#
# card_pancreas_16um_v2.R
# CARD 胰腺癌Visium HD 16um分辨率空间反卷积分析 - 版本2
# 使用采样的单细胞数据以加快分析
library(CARD)
library(Seurat)
library(ggplot2)
library(dplyr)
print("==================================================")
print("CARD 胰腺癌Visium HD 16um空间反卷积分析")
print("==================================================")
# 设置工作目录
work_dir <- "I:/TRAE skill 数据分析/untested-skills-test/spatial-16um-test"
setwd(work_dir)
# 创建结果目录
results_dir <- "card_16um_results"
if (!dir.exists(results_dir)) {
dir.create(results_dir, recursive = TRUE)
}
# 1. 读取单细胞参考数据
print("\n【1/5】读取单细胞参考数据...")
sc_data <- readRDS("I:/TRAE skill 数据分析/测试数据/胰腺癌单细胞测序数据/scAtlas.rds")
# 采样单细胞数据(加快分析)
set.seed(42)
cell_types <- sc_data$Clusters
selected_cells <- c()
for (ct in unique(cell_types)) {
ct_cells <- colnames(sc_data)[cell_types == ct]
if (length(ct_cells) > 1000) {
ct_cells <- sample(ct_cells, 1000)
}
selected_cells <- c(selected_cells, ct_cells)
}
sc_data_subset <- sc_data[, selected_cells]
# 提取表达矩阵和细胞类型
sc_count <- GetAssayData(sc_data_subset, layer = "counts")
sc_meta <- data.frame(
cellType = sc_data_subset$Clusters,
sampleInfo = sc_data_subset$Name,
row.names = colnames(sc_data_subset)
)
print(paste(" 单细胞数据:", ncol(sc_count), "cells,", nrow(sc_count), "genes"))
print(paste(" 细胞类型数:", length(unique(sc_meta$cellType))))
# 2. 读取空间转录组数据(16um分辨率)
print("\n【2/5】读取空间转录组数据 (16um)...")
spatial_dir <- "I:/TRAE skill 数据分析/测试数据/空间-HD/binned_outputs/square_016um"
# 读取空间数据
spatial_data <- Load10X_Spatial(
data.dir = spatial_dir,
filename = "filtered_feature_bc_matrix.h5"
)
# 提取表达矩阵
spatial_count <- GetAssayData(spatial_data, layer = "counts")
# 读取空间坐标
spatial_location <- GetTissueCoordinates(spatial_data)
spatial_location <- spatial_location[, c("x", "y")]
print(paste(" 空间数据:", ncol(spatial_count), "spots,", nrow(spatial_count), "genes"))
print(paste(" 空间坐标:", nrow(spatial_location), "spots"))
# 采样spots(加快分析)
if (ncol(spatial_count) > 2000) {
print(" 采样2000个spots...")
set.seed(42)
selected_spots <- sample(colnames(spatial_count), 2000)
spatial_count <- spatial_count[, selected_spots]
spatial_location <- spatial_location[selected_spots, ]
print(paste(" 采样后:", ncol(spatial_count), "spots"))
}
# 3. 准备CARD数据
print("\n【3/5】准备CARD数据...")
# 创建CARD对象
CARD_obj <- createCARDObject(
sc_count = sc_count,
sc_meta = sc_meta,
spatial_count = spatial_count,
spatial_location = spatial_location,
ct.varname = "cellType",
sample.varname = "sampleInfo",
ct.select = unique(sc_meta$cellType)
)
print(" ✓ CARD对象创建成功")
# 4. 运行CARD反卷积
print("\n【4/5】运行CARD反卷积...")
print(" 这可能需要5-10分钟,请耐心等待...")
# 运行CARD
CARD_obj <- CARD_deconvolution(CARD_obj)
print(" ✓ CARD反卷积完成")
# 5. 提取和保存结果
print("\n【5/5】提取和保存结果...")
# 提取比例矩阵
prop_df <- CARD_obj@Proportion_CARD
# 保存比例矩阵
write.csv(prop_df, file = paste0(results_dir, "/card_cell_type_proportions_16um.csv"))
# 计算统计
mean_props <- colMeans(prop_df)
mean_props_sorted <- sort(mean_props, decreasing = TRUE)
print("\n各细胞类型平均比例:")
for (ct in names(mean_props_sorted)) {
print(paste(" -", ct, ":", round(mean_props_sorted[ct], 4),
paste0("(", round(mean_props_sorted[ct]*100, 2), "%)")))
}
# 验证总和
total <- sum(mean_props)
print(paste("\n所有细胞类型比例总和:", round(total, 4), "(应该是1.0)"))
# 主要细胞类型
dominant_types <- colnames(prop_df)[apply(prop_df, 1, which.max)]
dominant_counts <- table(dominant_types)
print("\n各细胞类型作为主要类型的Spot数:")
for (ct in names(sort(dominant_counts, decreasing = TRUE))) {
pct <- dominant_counts[ct] / nrow(prop_df) * 100
print(paste(" -", ct, ":", dominant_counts[ct], "spots (", round(pct, 1), "%)"))
}
# 保存统计结果
sink(paste0(results_dir, "/card_statistics_16um.txt"))
cat("=== CARD 胰腺癌16um反卷积结果统计 ===\n\n")
cat("分析日期:", format(Sys.time(), "%Y-%m-%d %H:%M:%S"), "\n")
cat("样本: 胰腺癌Visium HD 16um\n")
cat("Spots:", nrow(prop_df), "\n")
cat("细胞类型:", ncol(prop_df), "\n\n")
cat("各细胞类型平均比例:\n")
for (ct in names(mean_props_sorted)) {
cat(paste(" -", ct, ":", round(mean_props_sorted[ct], 4),
paste0("(", round(mean_props_sorted[ct]*100, 2), "%)"), "\n"))
}
cat("\n各细胞类型作为主要类型的Spot数:\n")
for (ct in names(sort(dominant_counts, decreasing = TRUE))) {
pct <- dominant_counts[ct] / nrow(prop_df) * 100
cat(paste(" -", ct, ":", dominant_counts[ct], "spots (", round(pct, 1), "%)\n"))
}
sink()
print("\n ✓ 统计结果已保存")
# 6. 生成可视化
print("\n生成可视化...")
# 1. 平均比例条形图
print(" 生成平均比例条形图...")
pdf(paste0(results_dir, "/card_mean_proportions_16um.pdf"), width = 12, height = 8)
par(mar = c(5, 12, 4, 2))
barplot(mean_props_sorted, horiz = TRUE, las = 1,
main = "CARD 16um: Mean Cell Type Proportions",
xlab = "Mean Proportion", col = heat.colors(length(mean_props_sorted)))
dev.off()
png(paste0(results_dir, "/card_mean_proportions_16um.png"), width = 1200, height = 800, res = 150)
par(mar = c(5, 12, 4, 2))
barplot(mean_props_sorted, horiz = TRUE, las = 1,
main = "CARD 16um: Mean Cell Type Proportions",
xlab = "Mean Proportion", col = heat.colors(length(mean_props_sorted)))
dev.off()
# 2. 空间可视化(前4种细胞类型)
print(" 生成空间可视化...")
top4_cell_types <- names(mean_props_sorted)[1:4]
for (ct in top4_cell_types) {
# PDF
pdf(paste0(results_dir, "/card_spatial_", gsub(" ", "_", ct), "_16um.pdf"),
width = 10, height = 8)
plot(CARD_obj, ct.name = ct,
main = paste(ct, "(CARD 16um)"))
dev.off()
# PNG
png(paste0(results_dir, "/card_spatial_", gsub(" ", "_", ct), "_16um.png"),
width = 1000, height = 800, res = 150)
plot(CARD_obj, ct.name = ct,
main = paste(ct, "(CARD 16um)"))
dev.off()
}
# 3. 所有细胞类型热图
print(" 生成所有细胞类型热图...")
pdf(paste0(results_dir, "/card_all_cell_types_16um.pdf"), width = 20, height = 16)
plot(CARD_obj,
main = "CARD 16um: All Cell Types",
layout = c(5, 3))
dev.off()
png(paste0(results_dir, "/card_all_cell_types_16um.png"),
width = 2000, height = 1600, res = 150)
plot(CARD_obj,
main = "CARD 16um: All Cell Types",
layout = c(5, 3))
dev.off()
# 4. 相关性热图
print(" 生成相关性热图...")
corr_matrix <- cor(prop_df)
pdf(paste0(results_dir, "/card_cell_type_correlation_16um.pdf"), width = 12, height = 10)
heatmap(corr_matrix,
main = "CARD 16um: Cell Type Correlation Matrix",
col = colorRampPalette(c("blue", "white", "red"))(100),
symm = TRUE)
dev.off()
png(paste0(results_dir, "/card_cell_type_correlation_16um.png"),
width = 1200, height = 1000, res = 150)
heatmap(corr_matrix,
main = "CARD 16um: Cell Type Correlation Matrix",
col = colorRampPalette(c("blue", "white", "red"))(100),
symm = TRUE)
dev.off()
print(" ✓ 可视化已保存")
# 7. 保存CARD对象
saveRDS(CARD_obj, file = paste0(results_dir, "/card_object_16um.rds"))
print("\n==================================================")
print("CARD 16um分析完成!")
print("==================================================")
print("\n输出文件:")
print(" 📊 card_cell_type_proportions_16um.csv")
print(" 📦 card_object_16um.rds")
print(" 🖼️ card_mean_proportions_16um.png/pdf")
print(" 🖼️ card_spatial_*_16um.png/pdf (4个)")
print(" 🖼️ card_all_cell_types_16um.png/pdf")
print(" 🖼️ card_cell_type_correlation_16um.png/pdf")
print(" 📝 card_statistics_16um.txt")
CARD 核心 API
主函数
| 函数 | 说明 |
|---|---|
| createCARDObject() | 创建 CARD 对象,合并 scRNA-seq 参考和空间数据 |
| CARD_deconvolution() | 运行 CARD 反卷积,返回带 Proportion_CARD 的对象 |
官方可视化函数
| 函数 | 说明 |
|---|---|
| CARD.visualize.pie() | 饼图(适合 < 500 spots) |
| CARD.visualize.prop() | 单个/多个细胞类型空间分布 |
| CARD.visualize.prop.2CT() | 两个细胞类型对比 |
| CARD.visualize.Cor() | 细胞类型相关性热图 |
| CARD.visualize.gene() | 基因表达空间图 |
| plot(CARD_obj, ct.name=...) | 通用空间分布图 |
关键参数
| 参数 | 说明 |
|---|---|
| ct.varname | scRNA-seq metadata 中细胞类型列名 |
| sample.varname | scRNA-seq metadata 中样本名列名 |
| ct.select | 要使用的细胞类型向量 |
| colors | 颜色向量(建议 14 色对照表) |
输出文件清单
数据文件
card_cell_type_proportions_16um.csv:比例矩阵(spots × cell types)card_spatial_coordinates_16um.csv:空间坐标card_object_16um.rds:完整 CARD 对象CARD_result_converted.rds/.RData:转换后的 R 兼容对象
图形文件
card_r_pie.png/pdf:饼图card_r_top4_celltypes.png/pdf:前 4 种细胞类型分布card_r_all_celltypes_*.png/pdf:所有细胞类型分布card_r_2celltypes_comparison.png/pdf:两细胞类型对比card_r_correlation_heatmap.png/pdf:相关性热图card_r_mean_proportions_barplot.png/pdf:平均比例条形图card_r_dominant_celltypes.png/pdf:主导细胞类型分布card_mean_proportions_16um.png/pdf:平均比例条形图card_spatial_*_16um.png/pdf:前 4 种细胞类型空间分布card_all_cell_types_16um.png/pdf:所有细胞类型热图card_cell_type_correlation_16um.png/pdf:相关性热图card_official_*:各种官方可视化
报告
card_statistics_16um.txt:统计报告card_r_visualization_summary.txt:可视化总结
故障排除
内存不足
错误: cannot allocate vector of size ...
解决:
- 减少 spots(采样 2000~5000)
- 减少单细胞参考(每细胞类型采样 1000 个细胞)
- 使用 64 位 R
- 增加系统内存
CreateCARDObject 失败
错误: Error in CreateCARDObject
解决:
- 检查输入数据格式(scRNA-seq 和空间数据基因名一致)
- 检查细胞类型标签
- 确保空间坐标列名为
x、y
S4 类型转换错误
错误: unable to find an inherited method for function ...
解决:
- 使用
convert_card_to_rds.R将比例矩阵转为普通matrix - 直接将
prop_matrix和spatial_loc传给可视化函数
可视化失败
错误: Error in ggplot
解决:
- 确保 ggplot2 已安装
- 使用
tryCatch()包裹调用以隔离失败的可视化 - 检查数据格式(
as.matrix()/as.data.frame())
性能优化
大数据集:
- 使用分块处理
- 减少迭代次数
- 使用并行计算
内存优化:
- 及时清理变量
rm() - 使用
data.table替代data.frame - 保存中间结果
推荐工作流
# 1. 提取坐标(脚本 1)
source("extract_card_coordinates.R")
# 2. 全流程反卷积(脚本 6 或 7)
source("card_pancreas_16um.R") # 完整版
# 或
source("card_pancreas_16um_v2.R") # 采样版,更快
# 3. 官方可视化(脚本 3 或 4)
source("card_official_visualization.R") # 基于 RDS
# 或
source("card_official_visualization_v2.R") # 基于 CSV
# 4. 完整可视化(脚本 5,含扩展)
source("card_complete_r_visualization.R")
如已有 Python 版结果,可跳过步骤 2,使用脚本 2 转换后直接进入步骤 4。
资源链接
- 源码仓库:github.com/YingMa0107/CARD
- 论文:Ma Y, Zhou X. Spatially informed cell-type deconvolution for spatial transcriptomics. Nature Biotechnology, 2022.
- 官方文档:参考 GitHub README 与 vignette
许可证
遵循 CARD 原作者的开源许可证(详见 GitHub 仓库)。
引用
@article{ma2022spatially,
title={Spatially informed cell-type deconvolution for spatial transcriptomics},
author={Ma, Ying and Zhou, Xiang},
journal={Nature Biotechnology},
year={2022},
doi={10.1038/s41587-022-01233-1}
}
微信扫一扫