4. MultiQC 报告结构解析:HTML 报告的文件组织、模块、样品、表格、图表等元素

打开一份 MultiQC 生成的 HTML 报告,你看到的绝不只是静态页面。它背后有一套清晰的文件组织,以及模块、样品、表格、图表的协作逻辑。今天,我们就一层层剖开它。

MultiQC 报告结构总览 输入数据(FastQC, qualimap…) MultiQC 聚合引擎 输出目录:multiqc_report/ index.html + static/ + data/ 报告页面 ▸ 报告头(标题、元数据) ▸ 左侧模块导航栏 ▸ 内容区(模块卡片) ▸ 数据表格、图表 ▸ 页脚 模块(Module) FastQC, Cutadapt, STAR… 样品 / 表格 / 图表 行-样品,列-指标,图-分布 静态资源 ▸ multiqc.css ▸ multiqc.js ▸ 图标字体 ▸ 嵌入的 PNG/Plotly ▸ 数据 JSON 说明:用户可针对每个模块编写自定义模板,控制样式、表格和图表渲染

4.1 文件组织:报告输出目录里有什么

运行 multiqc . 后,默认生成 multiqc_report 文件夹。我个人习惯用 --outdir 指定路径,避免污染工作区。

multiqc_report/
├── index.html          # 主报告页面
├── multiqc_data/       # 原始数据(JSON / TSV)
│   ├── multiqc_general_stats.json
│   ├── multiqc_fastqc.txt
│   └── ...
└── multiqc_plots/      # 嵌入式图表(PNG / SVG / Plotly JSON)
    ├── fastqc_per_base_sequence_quality.png
    └── ...

你想想看,multiqc_data/ 里的 JSON 其实就是报告的数据源,后续自定义模板时,我们就是从这里拉取数据。我曾接手一个项目,同事直接把 multiqc_general_stats.json 当 API 用,写了个内部监控看板——嗯,这思路挺野,但也说明它的结构化程度很高。

小技巧: 如果只想保留数据不看网页,加参数 --data-only,只输出 multiqc_data/ 目录。

4.2 模块:报告的心脏

MultiQC 的每个“模块”对应一种质控工具的输出解析器。比如 FastQC、Cutadapt、STAR、Qualimap 等。报告左侧的导航栏就是模块列表,点击可跳转。

模块在报告里表现为一个 section,内部包含:

  • 样品选择器(可勾选过滤样品)
  • General Statistics 表格(每个样品一行)
  • 专有图表(如 FastQC 的碱基质量箱线图、Cutadapt 的剪接长度分布)
  • 详细数据表格(可排序、搜索)

我记得有一次,用户报告说某个模块的图表显示不全。查了半天,原来是自定义模板里漏写了对应模块的 module_js() 调用。所以,搞清楚每个模块的固定内容结构很重要。

4.3 样品:行的逻辑

在 MultiQC 的语境下,“样品”就是你在命令行传入的各个质控报告的原始样本名。报告中几乎所有表格都是以样品为行。举个例子,General Statistics 表:

Sample% Dups% GCLengthM Seqs
sample_124.548.214718.3
sample_231.751.015022.1
sample_319.849.614516.7

表格的排序、搜索、导出都是 JavaScript 控制的。自定义模板时,你可能会想调整列的显示顺序,或者增加自定义指标列。说白了,就是操作 table_config 对象。

4.4 表格:不只是普通 HTML 表格

MultiQC 里的表格用 datatable 库增强,支持:

  • 列排序(单击表头)
  • 列搜索(输入关键词)
  • 行选择(勾选样品,联动图表)
  • 导出为 CSV

报告的表格结构其实藏在 multiqc_data/ 的 JSON 里。举个例子,General Statistics 的数据结构长这样:

{
  "sample_1": {
    "fastqc": {
      "percent_duplicates": 24.5,
      "percent_gc": 48.2,
      "avg_sequence_length": 147,
      "total_sequences": 18300000
    },
    "cutadapt": { ... }
  }
}

模板引擎拿到这个 JSON,用 Jinja2 循环渲染成 <table>。我曾踩过坑:在自定义模板里想给某列加条件格式,但忘了引入 datatables 的初始化脚本,结果用户只能在浏览器看到纯 HTML 表格——没有排序功能,体验差很多。所以,记得在你的自定义模板里包含 multiqc_js() 和 multiqc_css()。

4.5 图表:静态与动态的权衡

MultiQC 支持三种图表渲染方式:

  1. Flat(静态 PNG):加载快,但无法交互。适合批量打印。
  2. Plotly(交互式 HTML):缩放、悬停提示、导出数据。报告中默认使用。
  3. SVG(静态矢量):保真度高,可直接在 Illustrator 中编辑。

如果报告里的图表数量多,文件体积会很大。我建议:

  • 对外交付的报告用 --flat 参数生成静态 PNG,体积小,兼容老浏览器。
  • 内部探索分析时保留 Plotly 交互图,方便数据深挖。

图表的数据通常作为 JSON 嵌入在 <script> 标签中。比如一个 Plotly 图表的数据:

<div id="fastqc-per-base-plot"></div>
<script>
  var data = [{"x": [1,2,3,...], "y": [40,38,39,...], "type": "box"}];
  var layout = {"title": "Per Base Sequence Quality"};
  Plotly.newPlot('fastqc-per-base-plot', data, layout);
</script>

自定义模板时,你可以选择只渲染表格而不显示图表,或者替换成你自己用 D3.js 画的图。这需要修改模块的 generator 逻辑,不过那是后面章节的事了。

4.6 交互与联动:样品勾选如何影响全局

报告里有一个全局的“样品选择器”。当你勾选或取消某个样品时,所有模块的表格行和图表数据都会同步过滤。这个机制是靠发布-订阅模式实现的。核心 JS 对象是 multiqc_samples,它管理所有样品的选中状态。

我曾经在自定义模板里想添加一个“全选/反选”按钮,结果发现 multiqc_samples.toggle_all() 方法早就内置了。很多时候,你需要的功能 MultiQC 已经提供了,只是文档里没写全。建议大家多翻翻 multiqc/multiqc.js 的源码。

注意: 自定义模板如果覆盖了 multiqc.js 或 multiqc.css,必须确保新文件仍然包含样品的联动逻辑。否则报告会失去交互能力。

4.7 从报告结构到自定义模板入口

理解报告的结构,就等于拿到了自定义模板的“地图”。你需要修改的文件主要有:

  • report_content.html — 整个报告的外壳
  • general_stats.html — General Statistics 表格
  • plotly_box.html — Plotly 图表容器
  • datatable_table.html — 其他数据表格
  • nav.html — 左侧导航栏

这些模板默认存放在 multiqtemplates/default/ 路径下。你可以复制到自定义目录,然后修改。嗯,从下一节开始,我们就要动手改真正的模板了,不过先别急,先把今天的结构图刻在脑子里。

核心提炼: MultiQC 报告 = 固定外壳 + 可替换模块 + 数据驱动表格/图表。样品是行,模块是卡片,交互靠 JS。自定义模板就是在不破坏这套架构的前提下,更换皮肤和布局。