跳转至

678 宏基因组Contig物种分类

一句话概述:宏基因组组装产生的contigs需要分类注释——Kaiju用蛋白级比对(灵敏度高),Kraken2用k-mer匹配(速度快),CAT/BAT对MAG做分类学分配。

核心知识点速查表

知识点关键内容
Kaiju蛋白级比对contig分类,灵敏度高(~75%)
Kraken2k-mer匹配分类,速度最快(百万reads/分钟)
CAT/BAT专门对contigs(CAT)和bins(BAT)做分类
MMseqs2 taxonomy基于MMseqs2的快速分类
GTDB-TkMAG的分类学分配(金标准)
核心区别reads分类 vs contig分类 vs bin分类

一、为什么要对contigs分类?(白话解释)

打个比方:宏基因组组装就像把碎纸片拼回文件。拼好的大片段(contigs)需要"贴标签"——这段DNA来自哪种细菌?contig分类就是给每个拼好的片段找到它的"户籍"。

三个层级的分类

层级输入工具特点
Reads分类原始测序readsKraken2/MetaPhlAn快速,但不能做功能注释
Contig分类组装后的contigsKaiju/CAT更长序列→更准确
Bin分类分箱后的MAGGTDB-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分类,金标准)。