2. BLAST 输出格式解析:tabular、XML、pairwise

BLAST跑完之后,输出文件长什么样?很多人上来就盯着屏幕看那个带空格的配对结果,其实这不太够。我个人习惯第一步先检查“-outfmt”参数,这个参数决定了你拿到的是哪种数据。不同的格式,解析成本、信息密度、可读性,完全不一样。

今天咱们就把BLAST最常用的三种输出格式扒开看看:tabular(表格)、XML(可扩展标记语言)、pairwise(成对比对)。我会拿项目中踩过的坑跟你说说,哪种场景用哪个,怎么读,怎么解析。

为什么会先讲这个?因为格式选错,后续可视化全是白费功夫。你想想看,如果后续要批量统计比对长度、相似度分布,pairwise格式你要一行行字符串匹配,解析到哭。而tabular,一行代码就能搞定。

2.1 三种格式的对比总览

先给你一张表,快速建立起印象。以后选格式可以直接翻回来对照。

格式 参数值 主要用途 信息密度 解析难度
tabular 6 或 7(带注释) 批量统计、数据分析 高(每行一条HSP) 极低(制表符分隔)
XML 5 程序间交换、持久化 最高(含所有元数据) 中(需XML解析器)
pairwise 0(默认) 人工阅读、汇报展示 低(大量空格排版) 高(文本结构不固定)

嗯,这里要注意。表格里的参数值是-outfmt后面的数字。BLAST支持的值远不止这几个,但咱们课程核心是可视化评估,所以只聚焦这三种最常见的格式。

2.2 tabular格式:数据分析者的首选

说白了,tabular格式就是一张二维表。每一行代表一条HSP(高分配对片段),每一列是固定的字段。默认输出12列,你可以用-outfmt "6 qseqid sseqid pident length mismatch gapopen qstart qend sstart send evalue bitscore"来指定顺序。

我之前做过一个项目,要处理10万条BLAST结果。如果全用pairwise格式,光解析就要花几个小时。换成tabular + pandas读取,几秒钟加载完,后续统计、筛选、绘图一气呵成。那种感觉,真的很爽。

我们来看一下tabular输出的真实样子:

query_001    seq_A    98.5    150    2    1    1    150    10    159    1e-45    189.0
query_001    seq_B    85.2    120    18    0    1    120    5    124    1e-20    95.3
query_002    seq_C    76.3    90    21    2    1    90    30    119    1e-10    65.2

看到没?制表符分隔,非常干净。列含义分别是:查询ID、目标ID、百分比一致度、比对长度、错配数、空位数、查询起始、查询结束、目标起始、目标结束、E值、比特分。

我的建议: 如果要在脚本或管道中批量处理BLAST结果,永远优先用tabular格式。它能让你的数据处理代码减少80%的边界条件处理。

2.3 XML格式:程序交换的“黄金标准”

XML格式可能看起来啰嗦,但它有一个巨大的优势——标准化。你不需要猜测字段位置,任何支持XML解析的语言都能准确读取。而且,它保留了比tabular更丰富的元信息,比如具体匹配的碱基序列、算法参数、版本号等。

我最初用Python解析BLAST XML时也踩过一些坑,主要是命名空间的问题。后来我固定用Bio.SearchIO模块,省了不少心。如果你不想引入Biopython,也可以用xml.etree.ElementTree自己解析,不过要多写一些代码。

下面是一个简化的XML结构片段,你可以感受一下:

<?xml version="1.0"?>
<!DOCTYPE BlastOutput PUBLIC "-//NCBI//NCBI BlastOutput/EN"
  "http://www.ncbi.nlm.nih.gov/dtd/NCBI_BlastOutput.dtd">
<BlastOutput>
  <BlastOutput_program>blastn</BlastOutput_program>
  <BlastOutput_db>nt</BlastOutput_db>
  <BlastOutput_iterations>
    <Iteration>
      <Iteration_query-def>query_001</Iteration_query-def>
      <Iteration_hits>
        <Hit>
          <Hit_def>seq_A</Hit_def>
          <Hit_hsps>
            <Hsp>
              <Hsp_bit-score>189.0</Hsp_bit-score>
              <Hsp_expect>1e-45</Hsp_expect>
              <Hsp_identity>148</Hsp_identity>
              <Hsp_align-len>150</Hsp_align-len>
            </Hsp>
          </Hit_hsps>
        </Hit>
      </Iteration_hits>
    </Iteration>
  </BlastOutput_iterations>
</BlastOutput>
我曾经过的坑: 千万不要手写正则去解析XML。数据量一大,你根本看不清边界条件。用现成的解析库是唯一的正确做法。

2.4 pairwise格式:人工阅读的友好界面

pairwise格式就是你在BLAST网页上看到的那种,带空位标记、序列对齐、星号表示匹配的那种文本。它非常直观,一眼就能看出哪里匹配、哪里错配、哪里有空位。但说实话,做数据分析它是最糟糕的格式。

你想想看,要从中提取“相似度”“比对长度”这些指标,你得用正则去匹配Identities = 148/150 (99%)这种字符串。而且,它的排版依赖于固定宽度字体,稍微一换环境就可能对不齐。

我建议在写论文或做汇报时,还是会保留pairwise输出,尤其是要展示具体的比对区域时。一对多的时候,pairwise的可读性无可替代。

下面是pairwise格式的一个典型片段:

Query= query_001
          Length=150

> seq_A
          Length=200

 Score = 189 bits (102), Expect = 1e-45
 Identities = 148/150 (99%)
 Gaps = 0/150 (0%)
 Strand=Plus/Plus

Query  1  ATGCGTACGTTAGCTAGCTGATCGATCGATCGATC... 150
          ||||||||||||||||||||||||||||||||||||
Sbjct  10 ATGCGTACGTTAGCTAGCTGATCGATCGATCGATC... 159
如果非要用pairwise做自动化解析, 我的经验是,先写一个健壮的正则,匹配Identities、Gaps、Score、Expect这四行。然后忽略那些带星号的比对行,因为你已经拿到了结构化数据。

2.5 格式选择的流程图

下面这张SVG图,我把三种格式的选择逻辑和核心特征画了出来。你可以把这个图贴在手边,以后选格式时瞄一眼就好。

BLAST输出格式选择与特征 BLAST比对输出 tabular 格式 XML 格式 pairwise 格式 ▶ 特征 • 制表符分隔,二维表 • 每行一条HSP • 解析最快,格式稳定 ▶ 特征 • 树形结构化数据 • 包含元信息最全 • 程序间交换首选 ▶ 特征 • 带空位标记、序列对齐 • 人工阅读最直观 • 自动化解析最痛苦 推荐场景 推荐场景 推荐场景 批量统计、聚类分析 机器学习特征提取 数据库导入导出 跨语言系统集成 审计追踪、版本控制 长期存档、备份 论文发表、报告展示 人工审核结果 设计引物时查看区域

2.6 实战选择策略

看完上面这张图,你应该能根据场景快速判断用哪种格式了。我再帮你梳理几个实战中的核心策略:

  • 写脚本跑批量任务:无脑选tabular。配合pandas或numpy,数据处理效率碾压。
  • 构建数据分析管道:优先XML。虽然文件体积大一点,但数据完整,易于长期维护。
  • 给老板汇报结果:pairwise可以准备几份,再配合tabular的可视化图表。两种格式互补,效果最好。
一个小技巧: 如果你不确定以后要用什么格式,可以同时输出tabular和XML。BLAST命令可以指定多个-outfmt参数吗?不能。但你可以跑两次,分别保存。或者用blast_formatter工具在结果生成后转换格式。我一般在第一次跑的时候都用XML保存,因为它是信息熵最高的格式,后续可以无损转换成其他格式。

好了,今天就到这里。记住,格式选对,后续的工作量至少减半。下一章我们会直接上手,拿真实的BLAST结果文件,用Python代码把tabular和XML读进来、筛出来、画出来。今天的内容你消化了吗?找个BLAST结果文件,用命令行分别指定三种格式跑一下,对比看看信息差异,印象会更深刻。