September 18, 2026
CellPhoneDB
#R #CellCellCommunication #SpaTalk
loadData() → createSpaTalk() → dec_celltype() → find_lr_path() → dec_cci() / dec_cci_all()
SpaTalk 不提供文件读盘函数 。需要在 R 里把数据加载进来,再传给它的接口。
# 你的空间转录组数据
st_data <- ... # gene × spot/cell 矩阵(data.frame / matrix / dgCMatrix)
st_meta <- ... # spot-based: data.frame(spot, x, y)
# single-cell: data.frame(cell, x, y)
# scRNA-seq 参考(解卷积用,选传)
sc_data <- ... # gene × cell 矩阵
sc_celltype <- ... # 每个 cell 的 cell-type 标签向量
obj <- createSpaTalk(
st_data = st_data,
st_meta = st_meta,
species = "Human", # or "Mouse"
if_st_is_sc = FALSE, # TRUE=ST, FALSE=spot ST
spot_max_cell = 10, # spot 模式:每个 spot 最多重建 N 个细胞
celltype = NULL # 已知 celltype 时跳过解卷积
)
Two Branch
obj <- dec_celltype(
object = obj,
sc_data = sc_data,
sc_celltype = sc_celltype,
min_percent = 0.5, # 单细胞:>此比例才赋予type
iter_num = 1000, # spot:抽样轮数
method = 1, # 1=SpaTalk内置, 2=RCTD, 3=Seurat...
)
内部发生了什么:
过滤可用 LR
obj <- find_lr_path(
object = obj,
lrpairs = lrpairs, # 内置 CellTalkDB,也可自定义
pathways = pathways, # 内置 KEGG + Reactome + AnimalTFDB
max_hop = NULL # Human=3, Mouse=4
)
只保留:
这步不涉及空间,是纯知识图谱预过滤。
推断 CCC
对 sender → receiver 这个 cell-type pair:
# 一对指定类型
obj <- dec_cci(obj, celltype_sender = "T_cell", celltype_receiver =
"Macrophage")
# 全部 cell-type pair(自动枚举)
obj <- dec_cci_all(obj)
内部 5 个子步骤:
dec_cci(sender, receiver)
│
├── 1. 取数据:st_meta, st_data, celltype_dist(距离矩阵)
├── 2. 验证 cell type 是否存在
├── 3. .get_cellpair() ──→ 空间 KNN,选出 sender→receiver 的 cell pair
├── 4. 检查 cell pair 数量是否 ≥ min_pairs
│
├── 5. .lr_distance() ──→ LR 共表达比例 + 置换检验
│ 保留 p < 0.05 的 LR
│
├── 6. .get_tf_res() ──→ 对每个显著 receptor 做胞内通路
│ ├─ .generate_ggi_res() BFS 展开 receptor→TF
│ ├─ .generate_tf_gene_all() 找可达 TF
│ ├─ .generate_tf_res() 记录 n_hop, n_target
│ └─ .random_walk() 10000 次随机游走 → TF score
│
├── 7. .get_score() ──→ 合并分数
│ score = sqrt((1-p) × sigmoid(intra))
│
└── 8. 写回 object@lrpair, object@tf, object@cellpair
##SpaTalk 方法详解
读取数据 → createSpaTalk() → dec_celltype() → find_lr_path() → dec_cci() / dec_cci_all()
核心思想:利用度矩阵进行归一化,解决节点度数差异导致的数值爆炸。
PyG 特点:
add_self_loops。适用场景:经典的半监督节点分类,对图结构比较固定的任务效果稳健。
class GCNConv(MessagePassing):
def __init__(self, in_channels, out_channels):
super().__init__(aggr='add')
self.lin = Linear(in_channels, out_channels, bias=False)
def forward(self, x, edge_index):
# 1. 添加自环
edge_index, _ = add_self_loops(edge_index, num_nodes=x.size(0))
# 2. 线性变换 (通常先做线性变换,减少 message 阶段计算量)
x = self.lin(x)
# 3. 计算归一化系数 (度矩阵 D)
row, col = edge_index
deg = degree(col, x.size(0), dtype=x.dtype)
deg_inv_sqrt = deg.pow(-0.5)
norm = deg_inv_sqrt[row] * deg_inv_sqrt[col] # 即 1/sqrt(di*dj)
return self.propagate(edge_index, x=x, norm=norm)
def message(self, x_j, norm):
# 邻居特征乘以归一化系数
return norm.view(-1, 1) * x_j