跳转至

622_微生物溯源与传播链

一句话概述: 微生物溯源与传播链分析利用全基因组测序(WGS)数据追踪病原体"从哪来、怎么传",结合SNP分析、系统发育和流行病学数据重建传播路径,是院感控制和疫情调查的核心技术。

核心知识点速查表

概念白话解释
Source tracking溯源——追踪微生物的来源(哪个人/环境传过来的)
Transmission chain传播链——病原体从一个宿主到另一个宿主的路径
Core-genome SNP核心基因组SNP——用于高分辨率菌株比较
cgMLST核心基因组多位点序列分型
wgMLST全基因组多位点序列分型
Phylodynamics系统发育动力学——从系统发育树推断流行病学参数
MRCA最近共同祖先——传播树的根
SNP距离两个菌株间的SNP差异数,越少越可能是直接传播

一、核心工具安装

# === 基因组比较和分型工具 ===
conda install -c bioconda snippy      # SNP分析核心工具
conda install -c bioconda gubbins     # 重组检测
conda install -c bioconda snp-dists   # SNP距离矩阵
conda install -c bioconda mlst        # MLST分型
conda install -c bioconda chewbbaca   # cgMLST/wgMLST
conda install -c bioconda iqtree      # 建树

# === 传播链推断工具 ===
pip install transphylo  # 传播树推断(Python接口)

二、WGS溯源分析流程

2.1 SNP分析(Snippy)

# === 用Snippy找SNP ===
# 第1步:每个样本与参考基因组比较
for sample in samples/*.fastq.gz; do
    name=$(basename "$sample" _R1.fastq.gz)
    snippy \
        --cpus 8 \                         # 线程数
        --outdir snippy_${name} \          # 输出目录
        --ref reference.fasta \            # 参考基因组
        --R1 ${sample} \                   # 正向reads
        --R2 ${sample/_R1/_R2}             # 反向reads
done

# 第2步:生成核心SNP比对
snippy-core \
    --ref reference.fasta \                # 参考基因组
    snippy_*/                              # 所有Snippy结果目录
# 输出:core.aln(核心SNP比对), core.full.aln(全长度比对)

# 第3步:只提取变异位点
snippy-clean_full_aln core.full.aln > clean.full.aln  # 清理比对
snp-sites -c clean.full.aln > core_snps.aln  # 只保留SNP位点

2.2 检测和去除重组区域

# Gubbins去除重组产生的SNP(对细菌很重要!)
run_gubbins.py \
    clean.full.aln \           # 输入全长度比对
    --threads 8 \              # 线程数
    --tree-builder iqtree \    # 用IQ-TREE建树
    --prefix gubbins_output    # 输出前缀

# 输出:
# gubbins_output.filtered_polymorphic_sites.fasta — 去除重组后的SNP
# gubbins_output.final_tree.tre — 最终树
# gubbins_output.recombination_predictions.gff — 重组区域

2.3 SNP距离矩阵

# 计算成对SNP距离
snp-dists core_snps.aln > snp_distance_matrix.tsv

# 查看距离矩阵
cat snp_distance_matrix.tsv
# R语言可视化SNP距离热图
library(pheatmap)  # 加载pheatmap

# 读取SNP距离矩阵
dist <- read.table("snp_distance_matrix.tsv", 
                    header = TRUE, row.names = 1, sep = "\t")

# 画热图
pheatmap(
    as.matrix(dist),
    display_numbers = TRUE,     # 显示数值
    number_format = "%.0f",     # 整数格式
    fontsize_number = 8,        # 数字大小
    color = colorRampPalette(c("white", "yellow", "red"))(100),
    main = "Pairwise SNP Distances"  # 标题
)

2.4 系统发育分析

# 用IQ-TREE建树
iqtree2 \
    -s gubbins_output.filtered_polymorphic_sites.fasta \
    -m GTR+G4 \               # GTR模型(或用MFP自动选)
    -bb 1000 \                # UFBoot
    -alrt 1000 \              # SH-aLRT
    -nt AUTO \
    -pre transmission_tree

三、传播链推断

3.1 基于SNP阈值的传播关系判断

import pandas as pd  # 导入pandas
import networkx as nx  # 导入networkx画网络图
import matplotlib.pyplot as plt  # 导入matplotlib

# 读取SNP距离矩阵
dist = pd.read_csv("snp_distance_matrix.tsv", sep="\t", index_col=0)

# 读取流行病学数据(采样时间、病房等)
epi = pd.read_csv("epidemiological_data.csv")

# === 基于SNP阈值判断传播关系 ===
# 常用阈值(取决于病原体):
# 金黄色葡萄球菌(MRSA): <40 SNPs(同一传播链)
# 结核分枝杆菌(MTB): <5-12 SNPs(近期传播)
# 大肠杆菌: <20 SNPs

SNP_THRESHOLD = 15  # 设置SNP阈值

# 构建传播网络
G = nx.Graph()
samples = dist.columns.tolist()
G.add_nodes_from(samples)

for i in range(len(samples)):
    for j in range(i+1, len(samples)):
        snp_dist = dist.iloc[i, j]
        if snp_dist <= SNP_THRESHOLD:  # SNP距离在阈值内
            G.add_edge(samples[i], samples[j], weight=snp_dist)

# 画传播网络图
pos = nx.spring_layout(G)  # 布局
nx.draw(G, pos, with_labels=True, node_size=500,
        node_color='lightblue', font_size=8)
edge_labels = nx.get_edge_attributes(G, 'weight')
nx.draw_networkx_edge_labels(G, pos, edge_labels=edge_labels, font_size=6)
plt.title(f"Transmission Network (SNP threshold={SNP_THRESHOLD})")
plt.savefig("transmission_network.pdf")
plt.close()

# 输出传播簇
clusters = list(nx.connected_components(G))
print(f"发现 {len(clusters)} 个传播簇:")
for i, cluster in enumerate(clusters):
    print(f"  簇{i+1}: {', '.join(cluster)}")

3.2 结合流行病学数据

# === 结合时间和空间信息 ===
library(ape)      # 系统发育分析
library(ggtree)   # 画树

# 读取树和元数据
tree <- read.tree("transmission_tree.treefile")
meta <- read.csv("epidemiological_data.csv")

# 画带元数据的系统发育树
p <- ggtree(tree) %<+% meta +  # 合并元数据
    geom_tiplab(aes(color = Ward), size = 3) +  # 按病房着色
    geom_tippoint(aes(shape = Source), size = 2) +  # 按来源形状
    theme_tree2() +
    labs(title = "Transmission Phylogeny")

# 添加时间线
p <- p + geom_text(
    aes(label = Collection_Date),
    size = 2, hjust = -0.1
)

ggsave("transmission_phylogeny.pdf", p, width = 12, height = 8)

四、不同病原体的SNP阈值参考

病原体同一传播链SNP阈值近期传播阈值参考
MRSA<40<15Harris et al., Science 2010
MTB<12<5Walker et al., NEJM 2013
E. coli<20<10经验值
Klebsiella<25<10经验值
Salmonella<5<3Leekitcharoenphon 2014
SARS-CoV-2不适用需结合时间病毒用系统发育方法

五、常见报错与解决

报错信息原因解决方案
No core SNPs found样本差异太小或参考不当检查参考基因组选择
Too many recombination高度重组物种先用Gubbins去重组
Low mapping ratereads质量差或参考不匹配检查物种鉴定是否正确
聚类结果与流行病学不符SNP阈值不合适调整阈值或加入时间信息
Memory error (Gubbins)样本太多分批运行或增加内存

六、面试高频题

Q1:WGS溯源的基本流程是什么?

答: 四步:(1) 对所有样本WGS测序;(2) 与参考基因组比较找核心SNP(Snippy);(3) 去除重组区域的SNP(Gubbins);(4) 基于SNP距离和系统发育树判断传播关系。SNP距离小于物种特异性阈值(如MRSA<40 SNPs)的样本可能属于同一传播链。最终需要结合流行病学数据(时间、地点、接触史)综合判断。

Q2:为什么细菌溯源要去除重组区域?

答: 细菌通过重组获取大段外来DNA,这些区域的SNP不反映垂直传播关系,会导致:(1) SNP距离被高估——实际没有传播关系的菌株因为获得了相同的重组片段而看起来很相似;(2) 系统发育树拓扑被扭曲。Gubbins通过检测SNP密度异常高的区域来识别重组,去除后只保留能反映真实传播历史的突变。

Q3:SNP距离和系统发育树在溯源中各有什么作用?

答: SNP距离是定量指标——直接告诉你两个菌株有多少个碱基差异,可以设阈值快速筛选可能的传播对。系统发育树是定性工具——展示所有菌株的进化关系,能直观看到哪些菌株聚在一起形成传播簇。两者互补:SNP距离小但在树上不相邻可能是趋同进化;树上相邻但SNP距离大可能是参考基因组选择问题。

Q4:微生物溯源在公共卫生中有什么应用?

答: (1) 院感暴发调查——追踪耐药菌(如MRSA、CRE)在病房间的传播路径;(2) 食源性疾病溯源——追踪沙门氏菌、李斯特菌污染源头;(3) 结核病传播监测——确定社区传播链指导防控;(4) 新发传染病疫情追踪——如COVID-19的传播路径重建。WGS溯源的分辨率远高于传统分型方法(PFGE/MLST),能区分PFGE无法区分的菌株。


参考资料:Snippy: Seemann 2015 | Gubbins: Croucher et al., NAR 2015 | Harris et al., Science 2010 | Walker et al., NEJM 2013 | 系统发育动力学综述: Duchêne et al., Trends Microbiol 2021