678 宏基因组Contig物种分类¶
一句话概述:宏基因组组装产生的contigs需要分类注释——Kaiju用蛋白级比对(灵敏度高),Kraken2用k-mer匹配(速度快),CAT/BAT对MAG做分类学分配。
核心知识点速查表¶
| 知识点 | 关键内容 |
|---|---|
| Kaiju | 蛋白级比对contig分类,灵敏度高(~75%) |
| Kraken2 | k-mer匹配分类,速度最快(百万reads/分钟) |
| CAT/BAT | 专门对contigs(CAT)和bins(BAT)做分类 |
| MMseqs2 taxonomy | 基于MMseqs2的快速分类 |
| GTDB-Tk | MAG的分类学分配(金标准) |
| 核心区别 | reads分类 vs contig分类 vs bin分类 |
一、为什么要对contigs分类?(白话解释)¶
打个比方:宏基因组组装就像把碎纸片拼回文件。拼好的大片段(contigs)需要"贴标签"——这段DNA来自哪种细菌?contig分类就是给每个拼好的片段找到它的"户籍"。
三个层级的分类:
| 层级 | 输入 | 工具 | 特点 |
|---|---|---|---|
| Reads分类 | 原始测序reads | Kraken2/MetaPhlAn | 快速,但不能做功能注释 |
| Contig分类 | 组装后的contigs | Kaiju/CAT | 更长序列→更准确 |
| Bin分类 | 分箱后的MAG | GTDB-Tk/BAT | 最准确,基因组级别 |
二、Kaiju(蛋白级分类)¶
# Kaiju安装和数据库
conda install -c bioconda kaiju # conda安装
# 下载数据库(选一个)
kaiju-makedb -s nr_euk \ # NCBI nr(最全,~100GB)
--index-only # 只建索引
# 或使用预构建数据库
# 下载地址: https://bioinformatics-centre.github.io/kaiju/
# 1. 对contigs分类
kaiju \
-t nodes.dmp \ # NCBI分类学节点文件
-f kaiju_db.fmi \ # Kaiju数据库索引
-i contigs.fasta \ # 输入contigs
-o kaiju_contigs.out \ # 输出结果
-z 16 \ # 线程数
-e 5 \ # 允许5个错配(灵敏模式)
-x # 启用更灵敏的搜索
# 2. 转换为分类学名称
kaiju-addTaxonNames \
-t nodes.dmp \ # 节点文件
-n names.dmp \ # 名称文件
-i kaiju_contigs.out \ # 输入结果
-o kaiju_contigs_names.out \ # 输出(带名称)
-r superkingdom,phylum,class,order,family,genus,species # 分类级别
# 3. 汇总分类结果
kaiju2table \
-t nodes.dmp \ # 节点文件
-n names.dmp \ # 名称文件
-r genus \ # 汇总级别(属)
-o kaiju_genus_summary.tsv \ # 输出汇总表
kaiju_contigs.out # 输入结果
# 4. 生成Krona交互式图表
kaiju2krona \
-t nodes.dmp \ # 节点文件
-n names.dmp \ # 名称文件
-i kaiju_contigs.out \ # 输入
-o kaiju_krona.txt # Krona输入文件
ktImportText -o kaiju_krona.html kaiju_krona.txt # 生成HTML
三、Kraken2(k-mer分类)¶
# Kraken2安装和数据库
conda install -c bioconda kraken2 # conda安装
# 下载/构建数据库
# 1. 使用预构建的标准数据库
kraken2-build --standard \ # 标准数据库(~60GB)
--db standard_db \ # 数据库路径
--threads 16 # 线程数
# 2. 或下载预构建的mini数据库(~8GB,适合测试)
# 从 https://benlangmead.github.io/aws-indexes/k2
# 对contigs分类
kraken2 \
--db standard_db \ # 数据库路径
--threads 16 \ # 线程数
--output kraken2_contigs.out \ # 逐条结果
--report kraken2_report.txt \ # 汇总报告
--confidence 0.1 \ # 置信度阈值(0-1)
contigs.fasta # 输入contigs
# Kraken2输出格式解读:
# C/U contig_name taxid length LCA_mapping
# C = classified(已分类)
# U = unclassified(未分类)
# Bracken丰度估算(基于Kraken2结果)
bracken \
-d standard_db \ # Kraken2数据库
-i kraken2_report.txt \ # Kraken2报告
-o bracken_genus.txt \ # 输出
-r 150 \ # 读长
-l G \ # 分类级别(G=属)
-t 10 # 最小reads阈值
四、CAT/BAT(contigs和bins的专用分类)¶
# CAT/BAT安装
conda install -c bioconda cat # conda安装
# 准备CAT数据库
CAT prepare \
--existing \ # 使用已有的NCBI数据
-d /path/to/CAT_database/ \ # 数据库目录
-t /path/to/taxonomy/ # 分类学目录
# 1. CAT(Contig Annotation Tool)——对contigs分类
CAT contigs \
-c contigs.fasta \ # 输入contigs
-d /path/to/CAT_database/ \ # CAT数据库
-t /path/to/taxonomy/ \ # 分类学数据库
-o CAT_output \ # 输出前缀
-n 16 \ # 线程数
--force # 覆盖已有结果
# 添加分类学名称
CAT add_names \
-i CAT_output.contig2classification.txt \ # 分类结果
-o CAT_named.txt \ # 带名称的输出
-t /path/to/taxonomy/ \ # 分类学数据库
--only_official # 只用标准分类级别
# 2. BAT(Bin Annotation Tool)——对MAG/bins分类
BAT bins \
-b bins_directory/ \ # bins目录(每个bin一个fasta)
-d /path/to/CAT_database/ \ # CAT数据库
-t /path/to/taxonomy/ \ # 分类学数据库
-o BAT_output \ # 输出前缀
-n 16 \ # 线程数
-s .fa # bin文件后缀
# 添加名称
BAT add_names \
-i BAT_output.bin2classification.txt \
-o BAT_named.txt \
-t /path/to/taxonomy/ \
--only_official
# CAT/BAT工作原理:
# 1. 对contigs/bins做基因预测(Prodigal)
# 2. 用DIAMOND将预测蛋白比对到NCBI nr数据库
# 3. 基于LCA(最低共同祖先)算法确定分类
# 4. 对bins整合所有contigs的分类信息投票
五、结果比较与整合¶
# 比较不同工具的分类结果
import pandas as pd # 数据处理
import matplotlib.pyplot as plt # 绑图
# 1. 解析Kaiju结果
def parse_kaiju(filepath):
"""解析Kaiju输出"""
results = {} # 存储结果
with open(filepath) as f:
for line in f:
parts = line.strip().split('\t')
status = parts[0] # C=classified, U=unclassified
contig = parts[1] # contig名
if status == "C":
taxid = parts[2] # 分类ID
results[contig] = {"taxid": taxid, "tool": "Kaiju"}
return results
# 2. 解析Kraken2结果
def parse_kraken2(filepath):
"""解析Kraken2输出"""
results = {}
with open(filepath) as f:
for line in f:
parts = line.strip().split('\t')
status = parts[0] # C/U
contig = parts[1] # contig名
if status == "C":
taxid = parts[2] # 分类ID
results[contig] = {"taxid": taxid, "tool": "Kraken2"}
return results
# 3. 解析CAT结果
def parse_cat(filepath):
"""解析CAT分类结果"""
results = {}
df = pd.read_csv(filepath, sep='\t') # 读取CAT输出
for _, row in df.iterrows():
contig = row.iloc[0] # contig名
classification = row.iloc[1] # 分类状态
if classification == "classified":
results[contig] = {
"lineage": row.get("lineage", ""),
"tool": "CAT"
}
return results
# 4. 比较工具一致性
def compare_classifications(kaiju, kraken2, cat):
"""比较三种工具的分类一致性"""
all_contigs = set(kaiju.keys()) | set(kraken2.keys()) | set(cat.keys())
stats = {
"total_contigs": len(all_contigs),
"kaiju_classified": len(kaiju),
"kraken2_classified": len(kraken2),
"cat_classified": len(cat),
"all_three_agree": 0,
"two_agree": 0,
"disagree": 0
}
for contig in all_contigs:
tools_classified = []
if contig in kaiju: tools_classified.append("Kaiju")
if contig in kraken2: tools_classified.append("Kraken2")
if contig in cat: tools_classified.append("CAT")
if len(tools_classified) == 3:
# 检查三种工具是否一致(简化:只比较taxid)
if (kaiju[contig]["taxid"] == kraken2[contig]["taxid"]):
stats["all_three_agree"] += 1
else:
stats["two_agree"] += 1
print("分类工具比较:")
for k, v in stats.items():
print(f" {k}: {v}")
# 分类率柱状图
tools = ["Kaiju", "Kraken2", "CAT"]
classified_pct = [
len(kaiju) / len(all_contigs) * 100,
len(kraken2) / len(all_contigs) * 100,
len(cat) / len(all_contigs) * 100
]
fig, ax = plt.subplots(figsize=(8, 5))
ax.bar(tools, classified_pct, color=["#FF6B6B", "#4ECDC4", "#45B7D1"])
ax.set_ylabel("分类率 (%)")
ax.set_title("不同工具的Contig分类率比较")
for i, v in enumerate(classified_pct):
ax.text(i, v + 1, f"{v:.1f}%", ha='center')
plt.tight_layout()
plt.savefig("classification_comparison.png", dpi=150)
return stats
# 5. 共识分类策略
def consensus_classification(kaiju, kraken2, cat):
"""共识分类:≥2种工具一致才接受"""
all_contigs = set(kaiju.keys()) | set(kraken2.keys()) | set(cat.keys())
consensus = {}
for contig in all_contigs:
votes = [] # 收集投票
if contig in kaiju: votes.append(kaiju[contig]["taxid"])
if contig in kraken2: votes.append(kraken2[contig]["taxid"])
if contig in cat: votes.append(cat.get(contig, {}).get("taxid", None))
votes = [v for v in votes if v is not None] # 去除None
if len(votes) >= 2:
from collections import Counter
most_common = Counter(votes).most_common(1)[0]
if most_common[1] >= 2: # ≥2个工具一致
consensus[contig] = most_common[0]
print(f"共识分类: {len(consensus)}/{len(all_contigs)} contigs")
return consensus
常见报错与解决¶
| 报错 | 原因 | 解决方案 |
|---|---|---|
| Kaiju分类率太低 | 数据库不包含目标物种 | 使用更大的数据库(nr_euk) |
| Kraken2内存不足 | 标准数据库需要~64GB RAM | 使用mini数据库或增加内存 |
| CAT运行太慢 | DIAMOND比对耗时 | 增加线程数,用--block_size加速 |
| 分类结果不一致 | 不同工具算法不同 | 使用共识策略(≥2工具一致) |
| 大量contigs未分类 | 短contigs信息不足 | 过滤<1000bp的contigs |
速查表¶
# Contig分类工具选择
速度优先: Kraken2(k-mer,秒级)
灵敏度优先: Kaiju(蛋白级比对)
Contigs专用: CAT(LCA+投票机制)
MAG/Bins: BAT 或 GTDB-Tk
# 工具对比
Kraken2: 速度最快,内存需求大(~64GB),k-mer匹配
Kaiju: 灵敏度最高(~75%),蛋白级比对
CAT: contig专用,每个基因独立比对再投票
# 推荐流程
1. 组装后的contigs → Kaiju + Kraken2 双重分类
2. 取共识(≥2工具一致的分类)
3. Bins/MAG → GTDB-Tk(金标准)
4. 未分类contigs → 可能是新物种
# 数据库选择
Kraken2标准: NCBI RefSeq(~60GB)
Kraken2 mini: PlusPF-8(~8GB,适合测试)
Kaiju nr_euk: NCBI nr+真核(~100GB)
CAT: NCBI nr(需要自行构建)
# 最小contig长度建议
Kraken2: ≥200bp即可
Kaiju: ≥500bp更准确
CAT: ≥2000bp(需要基因预测)
面试高频问题¶
Q1:Kaiju和Kraken2的核心区别是什么? A:Kraken2在核酸级别用k-mer精确匹配,速度极快但对远缘物种灵敏度低;Kaiju在蛋白质级别比对(将DNA翻译成蛋白),可以检测更远缘的物种(氨基酸比核酸更保守),灵敏度高约10-15%,但速度慢。一般推荐两者组合使用,取共识分类。
Q2:CAT/BAT和Kraken2有什么不同? A:Kraken2是对每条read/contig整体做k-mer匹配;CAT先在contig上预测基因(ORF),然后对每个基因独立比对到蛋白数据库,最后用投票机制综合所有基因的分类结果。CAT对长contigs更准确,因为利用了多个基因的信息来"投票"决定分类。
Q3:为什么很多contigs无法被分类? A:(1) 数据库不完整——环境微生物中>50%的物种没有参考基因组;(2) contig太短——信息不足以做可靠分类;(3) 横向基因转移——某些基因来自不同物种,导致分类矛盾;(4) 新物种——数据库中没有近缘参考。未分类contigs可能代表待发现的新物种。
Q4:GTDB-Tk和这些工具有什么区别? A:GTDB-Tk专门对MAG(基因组级别)做分类,使用GTDB分类系统(比NCBI更标准化),基于标记基因的系统发育放置。它比contig级分类更准确,但需要完整的MAG作为输入。通常的流程是:reads→Kraken2(快速概览)→组装→CAT(contig分类)→分箱→GTDB-Tk(MAG分类,金标准)。