2. 数据格式基础

做质谱数据合并,第一步就得把文件格式弄清楚。
我见过不少新手,一上来就想着跑算法,结果连数据读都读不进去,白白浪费时间。
说白了,RAW、mzML、HDF5 这几种格式,就是我们要打交道的基本单位。
这章我就带你一个一个拆开看,顺便讲讲我这些年踩过的坑。

1. 二进制原生格式:RAW 与 .d

每个质谱仪厂商都有自己的“私房”格式。

  • Thermo .RAW:Orbitrap 的母语。它不单单存谱图,还存了仪器状态、温度、电压、校准曲线等等。我刚开始做数据处理时,总想解析 RAW 文件里的全部字段,后来发现根本没必要——批处理只要读峰列表和元数据就够了。
  • Bruker .d:timsTOF 的数据格式,其实它是个文件夹,里面包含好多个小文件。如果你直接当单个文件拷贝,很容易丢数据。
  • SCIEX .wiff / .wiff.scan:比较老牌,但在跨平台合并时兼容性一般。
我曾经踩过坑: 直接从不同仪器拷 RAW 文件,以为后缀一样就能通用。结果 Thermo RAW 用 Bruker 的软件读,直接报错。不同厂商的二进制格式内部编码完全不一样,必须用相应的 SDK 或工具转换。

2. 开放交换格式:mzML

mzML 是质谱界的“世界语”。
它是 HUPO PSI 标准,纯 XML 或者压缩后的 .mzML.gz。

为什么我推荐用 mzML?

  • 厂商无关性:任何软件都能解析
  • 人眼可读:我就曾经打开 mzML 查一条缺失的扫描
  • 保留完整元数据:包括离子淌度、碰撞能、色谱保留时间

转换工具我用得最多的是 ProteoWizard 的 msConvert。命令很简单:

msconvert.exe input.raw --mzML --zlib --filter "peakPicking true 1-" --filter "msLevel 1-2"

注意两个参数:

  • --zlib:压缩文件,我在服务器上存 1000 个 mzML,压缩后省了 60% 空间
  • --filter "peakPicking true 1-":把 profile 模式转成 centroided,做批处理必须走这一步

我个人习惯: 转完 mzML 后,用 grep 或文本编辑器检查文件头,确认版本号是 1.1.0 以上。老版本 mzML 在某些解析器里会丢失离子淌度数据,到合并时就傻眼了。

3. 层级数据格式:HDF5

HDF5 不是质谱专属,但它在处理大型、多维数据时特别好使。
为什么需要它?想想看,Orbitrap 的数据二维(m/z, RT),timsTOF 的数据多了一维离子淌度(IMS)。普通表格存三维数据非常痛苦,HDF5 用 dataset 和 group 就能优雅解决。

一个典型的 HDF5 内部结构:

/ (根组)
├── /RawData/
│   ├── /RawData/Spectra (数据集, shape [nSpectra, 2])
│   ├── /RawData/IonMobility (数据集, shape [nFrames, nScans])
│   └── /RawData/Attributes (数据集, shape [nSpectra, 5])
└── /MetaData/
    ├── /MetaData/Instrument (字符串)
    └── /MetaData/RunTime (浮点)

我用 Python 读写 HDF5 经常是用 h5py。关键代码:

import h5py

# 写入
with h5py.File('combined.h5', 'w') as f:
    f.create_dataset('RawData/Spectra', data=spectra_array)
    f.create_dataset('RawData/IonMobility', data=ims_array)
    f.attrs['instrument'] = 'timsTOF_Pro'

# 读取
with h5py.File('combined.h5', 'r') as f:
    spectra = f['RawData/Spectra'][:]
    ims = f['RawData/IonMobility'][:]

做批次校正时,我一般用 HDF5 做中间桥梁: 把不同格式的数据统一转成 HDF5,再跑校正算法。这样 IO 效率高,而且方便按需分块读取,不会一次把内存吃掉。

4. 其他值得一提的格式

格式 来源/用途 我遇到过的要点
MGF 搜库结果分享 丢失离子淌度信息,不适合合并前处理
mzXML mzML 的前身 兼容性好,但元数据不完整,能不碰就别碰
Parquet 分析中间产物 列式存储,读特定列速度飞快,我做特征表导出常用
CSV/TSV 最终结果输出 简单明了,但会丢失数据结构和类型信息,只适用于展示

5. 格式选择的核心逻辑

你想想看,平时做多批次合并,数据流是这样的:

  • 仪器出来是 RAW 或 .d → 先用 msConvert 或者 OpenMS 转成 mzML
  • mzML 解析后,存入 HDF5 中间文件
  • 在 HDF5 上做批次校正,得到统一的特征矩阵
  • 最后导出 Parquet 或 CSV 供下游统计
质谱数据格式转换与批次校正工作流 Thermo .RAW (Orbitrap) Bruker .d (timsTOF) mzML 开放式标准格式 (保留仪器元数据) HDF5 层级化中间存储 (支持三维数据) 批次校正算法 (归一化、局部回归) Parquet / CSV (特征矩阵导出) ⚠ 避坑提示 RAW转mzML时,务必检查 是否丢失离子淌度信息。 我曾因此重跑过整个批次。

嗯,其实工具链很成熟,但关键是想清楚每一步要留下什么信息。你要合并,就必须保证所有文件都保留了 m/z、RT、强度,以及最重要的——批次标签。

6. 一点补充:文件头别忽略

无论是 RAW 还是 mzML,文件头里的 startTimeStamp、instrumentSerialNumber、scanPolarity 这些字段,在批处理时一定要确认。
我曾经因为两台 Orbitrap 的 scanPolarity 一个正一个负没做区分,合并校正后结果全错了。说实话,花 5 分钟检查文件头,比跑完后分析异常数据要省时很多。