Github开源生信云平台 DEMO
很好,这个问题已经进入 Kraken2 内核级理解了。我们把 hash.k2d、taxo.k2d、opts.k2d 拆开讲,从:
hash.k2d
taxo.k2d
opts.k2d
逐层解释。
Kraken2 数据库构建完成后核心文件:
hash.k2d → k-mer → taxid 映射表(核心) taxo.k2d → taxonomy 树结构 opts.k2d → 构建参数
运行时:
读取 opts.k2d 读取 taxo.k2d mmap hash.k2d 开始 classify
一个 压缩版 k-mer → taxid 的最小完美哈希表
但不是普通哈希表,而是:
Compact Hash Table + Minimizer 索引
Kraken2 不存所有 k-mer,而是:
所以:
k-mer → minimizer → hash lookup → taxid
简化理解为:
[ header ] [ hash table buckets ] [ value array ]
概念化结构:
struct Bucket { uint64_t minimizer_key; uint32_t taxid; }
但真实实现更复杂:
如果数据库大:
标准数据库可达 30~60GB。
如果不加 -M:
读取整个 hash.k2d 到内存
如果加 -M:
mmap() 映射 按需加载页
所以 -M 适合内存不足机器。
这个文件是:
NCBI taxonomy 的压缩内存结构版本
当多个 k-mer 命中不同 taxid 时:
计算 LCA(lowest common ancestor)
需要一棵 taxonomy 树。
逻辑模型:
struct TaxNode { uint32_t taxid; uint32_t parent; uint32_t rank; }
实际上是:
因为:
所以构建时:
nodes.dmp → internal compact tree → taxo.k2d
Kraken2 使用:
while taxid_a != taxid_b: 上升到 parent
优化版本使用:
这是最简单的文件。
构建数据库时使用的参数:
防止运行时参数不匹配:
比如:
数据库 k=35 运行时却用 k=31
那结果完全错误。
所以 classify 启动时:
读取 opts.k2d 验证参数一致
运行 classify 时逻辑:
1. 读取 opts.k2d 2. 加载 taxonomy(taxo.k2d) 3. mmap hash.k2d 4. 读取序列 5. 切 k-mer 6. 提取 minimizer 7. hash lookup 8. 得到 taxid 9. 多个 taxid → LCA 10. 输出结果
k2d = Kraken2 Database
Kraken1:
Kraken2:
Kraken2 本质是:
空间优化的 k-mer 精确匹配分类器
核心技术:
我可以继续讲:
1️⃣ hash.k2d 的真实二进制布局2️⃣ Kraken2 的 CompactHashTable C++ 实现3️⃣ minimizer 为什么能减少内存4️⃣ LCA 统计策略为什么准确5️⃣ 如何自己写一个 mini-kraken
你想深入哪个层面?