跳转至

原核基因组比较分析

一句话概述

通过Roary/Panaroo进行泛基因组分析确定核心基因和可变基因,计算ANI值判定物种边界,利用核心基因构建高分辨率系统发育树,是细菌分类学、进化分析和功能基因组学研究的标准流程。


核心知识点表格

知识点关键内容常用工具
泛基因组概念核心基因组+可变基因组+独有基因Roary, Panaroo, PPanGGOLiN
ANI计算平均核苷酸一致性(物种划分金标准95%)FastANI, skani, pyani, OrthoANI
基因预测原核ORF识别与注释Prokka, Bakta, PGAP
直系同源聚类基因家族分组OrthoFinder, CD-HIT
核心基因系统发育保守基因联合建树IQ-TREE, RAxML
基因组共线性大尺度基因排列比较Mauve, MUMmer, SyRI
基因岛检测水平转移区域识别IslandViewer, Alien_Hunter
泛基因组可视化基因present/absent热图Phandango, Anvi'o

各步骤详解

第一步:基因组注释标准化

白话解释: 比较基因组分析的第一步是确保所有基因组使用相同的注释流程。如果不同基因组的注释标准不一致,后续的同源基因比较就会有偏差。通常用Prokka或Bakta统一重新注释所有基因组。

技术细节: - Prokka: 快速原核基因组注释,输出GFF3格式 - Bakta: 更新的工具,使用UniProt等数据库,注释质量更高 - 关键:所有样本使用相同版本、相同数据库注释 - 注释质量影响泛基因组分析的准确性

代码示例:

# 安装
conda install -c bioconda prokka bakta

# 方法1: Prokka批量注释
for genome in genomes/*.fasta; do
    name=$(basename $genome .fasta)
    prokka --outdir prokka_output/$name \
        --prefix $name \
        --kingdom Bacteria \
        --genus Staphylococcus \
        --species aureus \
        --strain $name \
        --cpus 8 \
        --compliant \
        --force \
        $genome
done

# 方法2: Bakta注释(更推荐)
# 先下载数据库
bakta_db download --output /db/bakta_db

for genome in genomes/*.fasta; do
    name=$(basename $genome .fasta)
    bakta --db /db/bakta_db \
        --output bakta_output/$name \
        --prefix $name \
        --genus Staphylococcus \
        --species aureus \
        --threads 8 \
        $genome
done

# 收集所有GFF文件
mkdir gff_files
cp prokka_output/*/*.gff gff_files/

第二步:ANI计算与物种划分

白话解释: ANI(平均核苷酸一致性)就是两个基因组之间共享区域的平均序列相似度。如果ANI≥95%,通常认为是同一个种。这相当于用数字来精确定义"这两个细菌是不是同一个种"。

技术细节: - ANI 95-96% 等价于传统的70% DNA-DNA杂交阈值 - FastANI使用MinHash算法快速估计,适合大规模比较 - pyani使用BLAST或MUMmer精确计算 - 还有AAI(氨基酸一致性)用于更远的进化关系 - dDDH(数字DNA-DNA杂交)是另一种物种划分指标

代码示例:

# 方法1: FastANI (推荐,快速)
conda install -c bioconda fastani

# 准备文件列表
ls genomes/*.fasta > genome_list.txt

# 全部两两比较
fastANI --ql genome_list.txt \
        --rl genome_list.txt \
        -o fastani_output.txt \
        -t 16 \
        --matrix

# 输出格式: query reference ANI orthologous_matches total_fragments
# 示例: genome_A.fasta genome_B.fasta 98.7654 800 850

# 方法2: pyani (更精确)
pip install pyani

# 使用ANIb (BLAST)或ANIm (MUMmer)
average_nucleotide_identity.py \
    -i genomes/ \
    -o pyani_output/ \
    -m ANIb \
    --workers 8 \
    -g --gformat pdf

# 方法3: skani (最快,比FastANI快>20倍,对MAGs更鲁棒)
conda install -c bioconda skani

skani dist -q genomes/*.fasta -r genomes/*.fasta \
    -o skani_results.txt -t 16
# skani使用稀疏链式比对(sparse chaining),适合大规模和低质量MAGs

# 绘制ANI热图
python3 << 'EOF'
import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

# 读取FastANI结果
df = pd.read_csv("fastani_output.txt", sep="\t", header=None,
    names=["query","ref","ANI","ortho","total"])

# 构建矩阵
genomes = sorted(set(df["query"].tolist()))
matrix = pd.DataFrame(100.0, index=genomes, columns=genomes)
for _, row in df.iterrows():
    q = row["query"]
    r = row["ref"]
    matrix.loc[q, r] = row["ANI"]

# 绘制热图
plt.figure(figsize=(12,10))
sns.clustermap(matrix, cmap="YlOrRd", vmin=90, vmax=100,
    annot=True, fmt=".1f", figsize=(12,10))
plt.savefig("ANI_heatmap.pdf")
EOF

第三步:泛基因组分析(Roary/Panaroo)

白话解释: 泛基因组就是一个物种所有菌株的基因总和。其中"核心基因组"是所有菌株都有的基因(维持基本生命活动),"可变基因组"是部分菌株有的基因(可能与特殊环境适应相关),"独有基因"只在个别菌株中出现。

技术细节: - Roary: 经典工具,使用CD-HIT+MCL聚类 - Panaroo: 更新工具,使用图算法校正注释错误,假阳性更少 - 核心基因定义阈值:通常99%(严格)或95%(软核心) - 泛基因组开放性:Heap's law拟合判断泛基因组是否开放

代码示例:

# === 方法1: Roary ===
conda install -c bioconda roary

# 运行Roary
roary -p 16 \
    -f roary_output \
    -e -n \              # 生成核心基因比对
    -cd 99 \             # 核心基因阈值99%
    -i 95 \              # 序列一致性阈值95%
    -s \                 # 不拆分同源基因
    -v \                 # 详细输出
    gff_files/*.gff

# 输出文件:
# gene_presence_absence.csv   - 基因存在/缺失矩阵
# core_gene_alignment.aln     - 核心基因比对
# summary_statistics.txt      - 统计汇总
# pan_genome_reference.fa     - 泛基因组参考序列

# 查看统计
cat roary_output/summary_statistics.txt
# Core genes (99% <= strains <= 100%): 2,145
# Soft core genes (95% <= strains < 99%): 156
# Shell genes (15% <= strains < 95%): 1,823
# Cloud genes (0% < strains < 15%): 4,567
# Total genes: 8,691

# === 方法2: Panaroo (推荐) ===
conda install -c bioconda panaroo

# 运行Panaroo
panaroo -i gff_files/*.gff \
    -o panaroo_output \
    --clean-mode strict \    # 严格清理错误注释
    -t 16 \
    --core_threshold 0.99 \
    --remove-invalid-genes \
    -a core \               # 输出核心基因比对
    --aligner mafft

# Panaroo优势:
# 1. 使用图算法检测并修正注释错误
# 2. 处理基因分裂/融合事件
# 3. 三种清理模式:strict/moderate/sensitive

# 查看结果
head panaroo_output/gene_presence_absence_roary.csv
# 与Roary输出格式兼容

第四步:核心基因系统发育

白话解释: 用所有菌株都共有的核心基因来建系统发育树,这比用单个基因(如16S rRNA)分辨率高得多。核心基因联合分析提供了基因组水平的进化关系证据。

技术细节: - 核心基因比对连接(concatenation)后建树 - 或者用基因树+物种树方法(coalescent-based) - SNP-based方法更快但信息较少 - Recombination可能影响树的准确性,需要检测和去除

代码示例:

# 从Roary/Panaroo核心基因比对建树
# 方法1: 直接使用核心基因alignment
iqtree2 -s panaroo_output/core_gene_alignment.aln \
    -m GTR+G4 \
    -B 1000 \
    --alrt 1000 \
    -T AUTO \
    --prefix core_phylo

# 方法2: SNP-based快速建树
# 提取SNP位点
snp-sites -c panaroo_output/core_gene_alignment.aln \
    > core_snps.fasta

# 用SNP建树(更快)
iqtree2 -s core_snps.fasta \
    -m GTR+ASC+G \    # ASC校正:只有变异位点
    -B 1000 \
    -T AUTO \
    --prefix snp_phylo

# 方法3: 去除重组区域后建树
# 使用Gubbins检测重组
conda install -c bioconda gubbins

run_gubbins.py \
    panaroo_output/core_gene_alignment.aln \
    --threads 16 \
    --prefix gubbins_output \
    --tree-builder iqtree

# Gubbins输出去除重组后的alignment
iqtree2 -s gubbins_output.filtered_polymorphic_sites.fasta \
    -m GTR+G -B 1000 -T AUTO --prefix recomb_free_phylo

# 方法4: ClonalFrameML(ML框架下的重组检测)
ClonalFrameML core_phylo.treefile \
    panaroo_output/core_gene_alignment.aln \
    clonalframe_output

第五步:泛基因组可视化与功能分析

白话解释: 将泛基因组的基因存在/缺失矩阵与系统发育树结合展示,可以直观看到哪些基因在哪些菌株中存在。同时对可变基因进行功能富集分析,理解细菌环境适应的遗传基础。

代码示例:

# 使用Phandango在线可视化
# 上传: 树文件 + gene_presence_absence.csv
# 网址: https://jameshadfield.github.io/phandango/

# 使用roary_plots.py
python roary_plots.py core_phylo.treefile \
    roary_output/gene_presence_absence.csv

# 使用R进行自定义可视化
Rscript << 'EOF'
library(ggtree)
library(pheatmap)
library(tidyverse)

# 读取树
tree <- read.tree("core_phylo.treefile")

# 读取基因存在/缺失矩阵
pa <- read.csv("roary_output/gene_presence_absence.csv", 
    check.names=FALSE)

# 转为二值矩阵
binary_matrix <- pa %>%
    select(Gene, starts_with("genome_")) %>%
    column_to_rownames("Gene") %>%
    mutate(across(everything(), ~ifelse(is.na(.), 0, 1)))

# 绘制树+热图
p <- ggtree(tree) + geom_tiplab(size=2)
gheatmap(p, t(binary_matrix[1:50,]), 
    colnames=FALSE, width=2) +
    scale_fill_manual(values=c("white","steelblue"))

ggsave("pangenome_tree_heatmap.pdf", width=15, height=10)
EOF

# 泛基因组曲线(Heap's law)
Rscript << 'EOF'
library(micropan)

# 读取基因矩阵
pa_matrix <- read.csv("gene_presence_absence_binary.csv", row.names=1)

# 随机抽样绘制泛基因组增长曲线
heap <- heaps(pa_matrix, n.perm=100)
# alpha < 1: 开放泛基因组(新基因组总能带来新基因)
# alpha > 1: 封闭泛基因组
cat("Heaps law alpha:", heap$alpha, "\n")
EOF

第六步:基因组共线性与结构变异

白话解释: 除了基因的有无,基因在染色体上的排列顺序也会发生变化(倒位、转位、重复)。基因组共线性分析可以发现这些大尺度结构变异。

代码示例:

# 使用MUMmer进行两两比较
conda install -c bioconda mummer

nucmer --prefix=ref_vs_query \
    reference.fasta query.fasta

# 过滤比对结果
delta-filter -1 ref_vs_query.delta > ref_vs_query.filter

# 生成坐标文件
show-coords -rcl ref_vs_query.filter > ref_vs_query.coords

# 绘制dot plot
mummerplot --png --large \
    -p dotplot \
    ref_vs_query.filter

# 使用Mauve进行多基因组比对
progressiveMauve --output=mauve_output.xmfa \
    genome1.fasta genome2.fasta genome3.fasta

# 使用pyGenomeViz可视化
pip install pygenomeviz

python3 << 'EOF'
from pygenomeviz import GenomeViz

gv = GenomeViz()
gv.set_scale_bar()

# 添加基因组track
track1 = gv.add_feature_track("Genome_A", 3000000)
track2 = gv.add_feature_track("Genome_B", 2950000)

# 添加link(共线性区域)
# 从MUMmer coords文件解析
gv.savefig("synteny_plot.pdf")
EOF


实战命令

#!/bin/bash
# === 原核基因组比较分析完整流程 ===
set -e

GENOMES_DIR="genomes"
THREADS=16
OUTPUT="comparative_analysis"
mkdir -p $OUTPUT

# 1. 统一注释
mkdir -p $OUTPUT/gff
for fasta in $GENOMES_DIR/*.fasta; do
    name=$(basename $fasta .fasta)
    prokka --outdir $OUTPUT/prokka/$name --prefix $name \
        --cpus $THREADS --kingdom Bacteria $fasta
    cp $OUTPUT/prokka/$name/$name.gff $OUTPUT/gff/
done

# 2. ANI计算
ls $GENOMES_DIR/*.fasta > $OUTPUT/genome_list.txt
fastANI --ql $OUTPUT/genome_list.txt --rl $OUTPUT/genome_list.txt \
    -o $OUTPUT/fastani_results.txt -t $THREADS --matrix

# 3. 泛基因组分析
panaroo -i $OUTPUT/gff/*.gff -o $OUTPUT/panaroo \
    --clean-mode strict -t $THREADS -a core --aligner mafft

# 4. 去重组+建树
run_gubbins.py $OUTPUT/panaroo/core_gene_alignment.aln \
    --threads $THREADS --prefix $OUTPUT/gubbins
iqtree2 -s $OUTPUT/gubbins.filtered_polymorphic_sites.fasta \
    -m GTR+G -B 1000 -T AUTO --prefix $OUTPUT/final_tree

echo "Analysis complete!"

面试常问点

Q1: 什么是泛基因组?核心基因和可变基因的生物学意义? A: 泛基因组是一个物种所有基因的总和。核心基因(所有菌株共有)编码基本生命功能(转录、翻译、代谢);可变基因与环境适应相关(抗生素耐药、毒力因子、代谢特殊底物);独有基因可能来自水平转移或噬菌体。

Q2: ANI 95%阈值的理论基础是什么? A: 95% ANI等价于传统的70% DNA-DNA杂交值,是公认的原核物种划分标准。生物学上对应约10^8年的分化时间。但对某些类群(如Bacillus cereus group)这个阈值可能需要调整。

Q3: Roary和Panaroo有什么区别?为什么推荐Panaroo? A: Roary使用CD-HIT+MCL简单聚类;Panaroo使用图算法可以检测并修正注释错误(假基因、基因分裂/融合)。Panaroo的核心基因组估计更保守准确,假阳性更少,但运行更慢。

Q4: 为什么要去除重组区域再建树? A: 细菌频繁发生同源重组,重组片段的进化历史与物种树不同。如果包含重组区域,树的拓扑会被扭曲(尤其是支长)。Gubbins/ClonalFrameML可以识别并mask这些区域。

Q5: 如何判断泛基因组是开放还是封闭的? A: 用Heap's law拟合: n = κ·N^γ。γ>0(α<1)为开放泛基因组(每增加一个基因组都能发现新基因),常见于生态位多样的物种(如E. coli)。γ≈0(α>1)为封闭泛基因组,常见于专性寄生菌。


易错点

  1. 注释工具不一致:不同工具注释的基因数差异显著。必须用同一工具、同一版本重新注释所有基因组。

  2. draft基因组的contig断裂:基因可能跨越contig边界被截断,导致泛基因组统计偏差。Panaroo对此有一定容错。

  3. ANI计算方向性:ANI(A→B)可能≠ANI(B→A),因为片段化程度不同。应取双向平均值。

  4. 同源基因聚类阈值:过松会合并旁系同源(paralog),过严会分裂真正的直系同源。需要根据物种分化程度调整。

  5. 忽略质粒序列:质粒上的基因可能被当作独有基因,实际是可移动元件。需要注意chromosome vs plasmid的分开处理。

  6. 样本量不足:泛基因组分析至少需要15-20个基因组才能得到稳定的统计估计。


补充知识

泛基因组分析工具选择指南

工具适用场景优势局限
Roary近缘菌株(同种)快速,经典对注释错误敏感
Panaroo近缘菌株图算法修正错误较慢
PPanGGOLiN大规模分析可处理数千基因组不输出比对
OrthoFinder跨属比较处理基因重复不限于原核
GET_HOMOLOGUES灵活参数多种聚类算法学习曲线陡

细菌物种划分标准

ANI ≥ 95-96%  → 同种
AAI ≥ 65%     → 同属
16S ≥ 98.65%  → 同种(Kim et al. 2014; 旧标准97%已不推荐)
16S ≥ 95%     → 同属
dDDH ≥ 70%    → 同种(GGDC在线计算)