基因调控网络推断¶
一句话概述¶
利用SCENIC/pySCENIC、GRNBoost2和GENIE3等算法从单细胞或bulk RNA-seq数据推断转录因子(TF)及其靶基因的调控关系,构建基因调控网络(GRN),是揭示细胞命运决定机制和疾病调控失调的核心分析方法。
核心知识点表格¶
| 知识点 | 关键内容 | 常用工具 |
|---|---|---|
| GRN概念 | TF→靶基因的有向调控关系 | - |
| 共表达推断 | 从表达相关性推断调控 | GENIE3, GRNBoost2 |
| motif验证 | 用TF结合位点验证调控关系 | RcisTarget, SCENIC |
| regulon活性 | 每个细胞中TF regulon的活性评分 | AUCell |
| SCENIC流程 | 共表达→motif筛→regulon活性 | SCENIC, pySCENIC |
| 差异调控 | 条件间TF活性变化 | SCENIC+, CellOracle |
| 因果推断 | 扰动数据验证因果关系 | Perturb-seq, CRISPRi |
各步骤详解¶
第一步:理解基因调控网络¶
白话解释: 基因调控网络描述的是"谁控制谁"的关系:哪些转录因子控制哪些基因的表达。就像公司的组织架构图——经理(TF)管理一群员工(靶基因),这一群人就是一个"regulon"。SCENIC流程通过三步推断这个网络:1)找共表达关系;2)用motif信息验证TF是否真的能结合靶基因;3)计算每个细胞中各TF的活性。
技术细节: - Regulon = TF + 其直接靶基因集合 - SCENIC三步: GRNBoost2(共表达)→RcisTarget(motif)→AUCell(活性) - GRNBoost2: 随机梯度提升树推断TF-gene关联 - RcisTarget: 检查靶基因启动子区是否富集TF的结合motif - AUCell: 用AUC评分量化每个细胞中regulon的活性
第二步:pySCENIC完整流程¶
代码示例:
# 安装
# pip install pyscenic
import scanpy as sc
import loompy
from pyscenic.rnkdb import FeatherRankingDatabase as RankingDatabase
from pyscenic.utils import modules_from_adjacencies
from pyscenic.prune import prune2df, df2regulons
from pyscenic.aucell import aucell
import pandas as pd
import numpy as np
# 1. 准备数据
adata = sc.read_h5ad("scRNA_processed.h5ad")
# 过滤:保留在至少1%细胞中表达的基因
sc.pp.filter_genes(adata, min_cells=int(0.01 * adata.n_obs))
# 导出为loom格式
row_attrs = {"Gene": np.array(adata.var_names)}
col_attrs = {"CellID": np.array(adata.obs_names),
"CellType": np.array(adata.obs["cell_type"])}
loompy.create("input.loom", adata.X.T, row_attrs, col_attrs)
# 2. 准备数据库文件(需要预下载)
# TF列表: https://resources.aertslab.org/cistarget/tf_lists/
# Ranking数据库: https://resources.aertslab.org/cistarget/databases/
# pySCENIC 0.12.0+ 要求 Feather v2 格式数据库(需 ctxcore >= 0.2),旧格式 Feather v1 不兼容
# Motif注释: https://resources.aertslab.org/cistarget/motif2tf/
# 3. 命令行运行pySCENIC(推荐,更稳定)
# pySCENIC命令行流程(推荐方式)
# Step 1: GRNBoost2 共表达网络推断
pyscenic grn \
input.loom \
/db/allTFs_hg38.txt \ # TF列表
-o adjacencies.tsv \
--method grnboost2 \
--num_workers 16 \
--seed 42
# Step 2: RcisTarget motif pruning (cisTarget)
pyscenic ctx \
adjacencies.tsv \
/db/hg38_10kbp_up_10kbp_down_full_tx_v10_clust.genes_vs_motifs.rankings.feather \
/db/hg38_500bp_up_100bp_down_full_tx_v10_clust.genes_vs_motifs.rankings.feather \
--annotations_fname /db/motifs-v10nr_clust-nr.hgnc-m0.001-o0.0.tbl \
--expression_mtx_fname input.loom \
--output regulons.csv \
--mask_dropouts \
--num_workers 16
# Step 3: AUCell regulon活性评分
pyscenic aucell \
input.loom \
regulons.csv \
-o scenic_output.loom \
--num_workers 16
# 输出: scenic_output.loom 包含原始数据 + regulon AUC scores
# 4. 解析和可视化结果
import loompy
# 读取SCENIC结果
lf = loompy.connect("scenic_output.loom")
# 获取AUCell矩阵
auc_mtx = pd.DataFrame(
lf.ca.RegulonsAUC,
index=lf.ca.CellID,
columns=lf.ra.Regulons)
# 关闭loom文件
lf.close()
# 或使用scanpy读取
adata_scenic = sc.read_loom("scenic_output.loom")
# 5. 可视化TF活性
# 在UMAP上展示特定TF活性
import matplotlib.pyplot as plt
fig, axes = plt.subplots(2, 3, figsize=(15, 10))
tfs_to_show = ["PAX6(+)", "SOX2(+)", "NEUROD1(+)",
"GATA3(+)", "FOXP3(+)", "TCF7(+)"]
for ax, tf in zip(axes.flat, tfs_to_show):
if tf in auc_mtx.columns:
sc.pl.umap(adata, color=auc_mtx[tf].values,
ax=ax, title=tf, show=False)
plt.tight_layout()
plt.savefig("tf_activity_umap.pdf")
# 6. 差异TF活性分析
from scipy.stats import mannwhitneyu
cell_types = adata.obs["cell_type"]
diff_regulons = []
for tf in auc_mtx.columns:
for ct in cell_types.unique():
mask = cell_types == ct
stat, pval = mannwhitneyu(
auc_mtx.loc[mask, tf],
auc_mtx.loc[~mask, tf],
alternative="greater")
if pval < 0.001:
diff_regulons.append({"TF": tf, "CellType": ct, "pvalue": pval})
diff_df = pd.DataFrame(diff_regulons)
print(diff_df.sort_values("pvalue").head(20))
第三步:SCENIC R版本¶
代码示例:
# 安装
# BiocManager::install(c("SCENIC","AUCell","RcisTarget"))
library(SCENIC)
library(AUCell)
library(RcisTarget)
library(Seurat)
# 1. 准备数据
seurat_obj <- readRDS("seurat_processed.rds")
exprMat <- GetAssayData(seurat_obj, slot="counts")
exprMat <- as.matrix(exprMat)
cellInfo <- data.frame(
CellType = seurat_obj$cell_type,
row.names = colnames(seurat_obj))
# 2. 初始化SCENIC设置
org <- "hgnc" # 人类; "mgi"=小鼠
dbDir <- "/db/scenic/" # 数据库目录
myDatasetTitle <- "My_SCENIC_Analysis"
scenicOptions <- initializeScenic(
org = org,
dbDir = dbDir,
# mc9nr 为旧版数据库,当前推荐使用 mc_v10_clust 系列(motif 数量和注释质量更高)
dbs = c("hg38__refseq-r80__500bp_up_and_100bp_down_tss.mc9nr.feather",
"hg38__refseq-r80__10kb_up_and_down_tss.mc9nr.feather"),
datasetTitle = myDatasetTitle,
nCores = 16)
# 3. 基因过滤和共表达模块
genesKept <- geneFiltering(exprMat, scenicOptions,
minCountsPerGene = 3 * 0.01 * ncol(exprMat),
minSamples = ncol(exprMat) * 0.01)
exprMat_filtered <- exprMat[genesKept, ]
# 4. 计算相关性矩阵
runCorrelation(exprMat_filtered, scenicOptions)
# 5. GRNBoost2推断共表达网络
# 通常在Python中运行GRNBoost2(更快)
# 或使用GENIE3:
runGenie3(exprMat_filtered, scenicOptions, nParts = 20)
# 6. 构建和修剪regulons (cisTarget)
scenicOptions <- runSCENIC_1_coexNetwork2modules(scenicOptions)
scenicOptions <- runSCENIC_2_createRegulons(scenicOptions)
# 7. AUCell活性评分
scenicOptions <- runSCENIC_3_scoreCells(scenicOptions, exprMat_filtered)
# 8. 二值化(可选:判断regulon在每个细胞中是否"开启")
scenicOptions <- runSCENIC_4_aucell_binarize(scenicOptions)
# 9. 提取结果
regulonAUC <- getAUC(loadInt(scenicOptions, "aucell_regulonAUC"))
regulons <- loadInt(scenicOptions, "regulons")
# 10. 可视化
# TF活性热图
library(ComplexHeatmap)
avg_auc <- t(apply(regulonAUC, 1, function(x)
tapply(x, cellInfo$CellType, mean)))
Heatmap(avg_auc, name="AUC",
show_row_names=TRUE, row_names_gp=gpar(fontsize=6))
第四步:GENIE3独立使用¶
白话解释: GENIE3使用随机森林回归来推断每个基因的表达受哪些TF调控。对于每个靶基因,它训练一个随机森林模型用所有TF的表达来预测该基因的表达,根据特征重要性排序得到最可能的调控TF。
代码示例:
library(GENIE3)
# 准备数据
expr_matrix <- as.matrix(GetAssayData(seurat_obj, "data"))
# TF列表
tf_list <- read.table("/db/allTFs_hg38.txt")$V1
tf_list <- intersect(tf_list, rownames(expr_matrix))
# 运行GENIE3
# 注意:计算密集,建议子采样或使用GRNBoost2替代
set.seed(42)
# 子采样细胞(加速)
cells_subset <- sample(colnames(expr_matrix), min(5000, ncol(expr_matrix)))
expr_subset <- expr_matrix[, cells_subset]
weightMat <- GENIE3(
exprMatrix = expr_subset,
regulators = tf_list,
nCores = 16,
verbose = TRUE)
# 提取Top边
link_list <- getLinkList(weightMat, threshold = 0.01)
# 格式: regulatoryGene, targetGene, weight
head(link_list)
# 筛选高置信度边
top_links <- link_list[link_list$weight > quantile(link_list$weight, 0.99), ]
cat("高置信度调控关系数:", nrow(top_links), "\n")
第五步:GRN可视化和解读¶
代码示例:
library(igraph)
library(ggraph)
# 构建网络
# 只取top TF及其靶基因
top_tfs <- names(sort(table(top_links$regulatoryGene), decreasing=TRUE))[1:20]
subnet <- top_links[top_links$regulatoryGene %in% top_tfs, ]
subnet <- subnet[1:200, ] # 限制边数
# 创建igraph对象
g <- graph_from_data_frame(subnet[,1:2], directed=TRUE)
V(g)$type <- ifelse(V(g)$name %in% tf_list, "TF", "Target")
V(g)$size <- ifelse(V(g)$type == "TF", 10, 3)
V(g)$color <- ifelse(V(g)$type == "TF", "red", "lightblue")
# 绘制网络
pdf("GRN_network.pdf", width=12, height=12)
plot(g, layout=layout_with_fr(g),
vertex.label.cex=0.6,
edge.arrow.size=0.3,
edge.width=E(g)$weight * 5,
main="Gene Regulatory Network")
dev.off()
# 使用ggraph更美观
ggraph(g, layout="fr") +
geom_edge_link(aes(alpha=weight), arrow=arrow(length=unit(2,"mm"))) +
geom_node_point(aes(color=type, size=size)) +
geom_node_text(aes(label=name), size=2, repel=TRUE) +
theme_void()
第六步:差异调控分析¶
代码示例:
# 比较不同条件间的TF活性变化
import scanpy as sc
from scipy.stats import ranksums
# 读取SCENIC结果
auc_scores = pd.read_csv("regulon_auc_matrix.csv", index_col=0)
# 比较两个条件
condition = adata.obs["condition"]
cond_A = auc_scores[condition == "disease"]
cond_B = auc_scores[condition == "healthy"]
# 对每个regulon做差异检验
diff_results = []
for tf in auc_scores.columns:
stat, pval = ranksums(cond_A[tf], cond_B[tf])
diff_results.append({
"TF": tf,
"mean_disease": cond_A[tf].mean(),
"mean_healthy": cond_B[tf].mean(),
"diff": cond_A[tf].mean() - cond_B[tf].mean(),
"pvalue": pval
})
diff_df = pd.DataFrame(diff_results)
from statsmodels.stats.multitest import multipletests
_, diff_df["padj"], _, _ = multipletests(diff_df["pvalue"], method="fdr_bh")
diff_df = diff_df.sort_values("padj")
# 上调的TF regulons
upregulated_tfs = diff_df[(diff_df["padj"] < 0.01) & (diff_df["diff"] > 0)]
print("疾病中上调的TF:", upregulated_tfs["TF"].tolist()[:10])
实战命令¶
# === SCENIC/pySCENIC完整流程 ===
# 准备数据库(一次性下载)
wget https://resources.aertslab.org/cistarget/databases/homo_sapiens/hg38/refseq_r80/mc_v10_clust/gene_based/hg38_10kbp_up_10kbp_down_full_tx_v10_clust.genes_vs_motifs.rankings.feather
wget https://resources.aertslab.org/cistarget/databases/homo_sapiens/hg38/refseq_r80/mc_v10_clust/gene_based/hg38_500bp_up_100bp_down_full_tx_v10_clust.genes_vs_motifs.rankings.feather
wget https://resources.aertslab.org/cistarget/motif2tf/motifs-v10nr_clust-nr.hgnc-m0.001-o0.0.tbl
# 运行pySCENIC
pyscenic grn input.loom allTFs_hg38.txt -o adj.tsv --method grnboost2 --num_workers 16
pyscenic ctx adj.tsv hg38_10kbp.feather hg38_500bp.feather --annotations_fname motifs.tbl --expression_mtx_fname input.loom --output regulons.csv --num_workers 16
pyscenic aucell input.loom regulons.csv -o scenic_output.loom --num_workers 16
面试常问点¶
Q1: SCENIC流程的三个步骤分别做什么? A: 1)GRNBoost2/GENIE3:用随机森林推断TF-基因的共表达关系,输出候选调控边;2)RcisTarget:用TF结合motif信息过滤候选边,只保留靶基因启动子区有对应TF motif富集的关系(去除间接关联),形成regulon;3)AUCell:用AUC评分量化每个细胞中每个regulon的活性(regulon基因集是否被该细胞高表达)。
Q2: GENIE3和GRNBoost2的区别? A: GENIE3用Random Forest,GRNBoost2用Gradient Boosting Trees。GRNBoost2快10-50倍,在大规模单细胞数据上实用。两者的网络推断质量相当,但GRNBoost2更适合>5000细胞的数据。
Q3: 推断的GRN如何验证? A: 1)ChIP-seq验证TF实际结合靶基因启动子;2)Perturb-seq/CRISPRi验证敲低TF后靶基因表达下降;3)已知调控关系数据库(RegNetwork、TRRUST)比对;4)motif验证(SCENIC内置);5)跨数据集一致性。
Q4: 为什么单细胞数据特别适合GRN推断? A: 1)细胞间的表达异质性提供了大量"自然扰动"数据点;2)不同细胞代表不同的调控状态,类似于时间序列采样;3)细胞数量远大于基因数,避免了bulk中的n<p问题;4)可以获得细胞类型特异的调控网络。
易错点¶
计算资源不足:SCENIC对大数据集(>50K cells)非常耗时和耗内存。建议子采样(5000-10000 cells per cell type)。
TF列表不准确:使用了过时或不完整的TF列表会遗漏重要调控关系或引入假阳性。
数据库版本不匹配:ranking database必须与基因组版本和注释版本一致。
过度解读共表达为调控:即使有motif支持,共表达也可能是共同被第三个TF调控,而非直接调控关系。
未考虑调控方向:标准SCENIC不区分激活和抑制。需要额外分析(如表达反相关)判断正/负调控。
补充知识¶
GRN推断工具比较¶
| 工具 | 方法 | 输入 | 特点 |
|---|---|---|---|
| SCENIC/pySCENIC | GRNBoost2+cisTarget+AUCell | scRNA-seq | 金标准,motif验证 |
| CellOracle | GRN+扰动模拟 | scRNA+ATAC | 整合可及性 |
| SCENIC+ | SCENIC+ATAC | scRNA+scATAC | 增强子调控 |
| Dictys | 动态GRN | 时间序列scRNA | 动态网络 |
| GENIE3 | 随机森林 | bulk/scRNA | 简单独立 |
| GRNBoost2 | 梯度提升树 | scRNA | SCENIC内核 |