第1章 质谱数据基础:原理、类型与常见格式
质谱这东西,说白了就是一台"分子天平"。你把样品扔进去,它能把分子一个个称出来,不光告诉你有多重,还能告诉你长什么样。我刚入行那会儿,总觉得质谱仪是黑魔法——样品进去,数据出来,中间发生了什么完全不知道。后来拆过几台仪器、踩过几次坑,才慢慢摸清楚门道。
这一章我们先把地基打牢。我个人习惯是:**先搞懂仪器怎么工作,再去看数据长什么样,最后研究文件格式**。顺序搞反了,后面做质量控制会越做越糊涂。
1.1 质谱原理:从分子到信号
一台质谱仪,不管多贵多复杂,核心就三步:
- 离子化——把中性分子变成带电离子。
- 质量分析——按质荷比(m/z)把离子分开。
- 检测——记录每个m/z的离子信号强度。
为什么非要带电荷?因为只有带电粒子才能在电场或磁场里被"操控"。你想想看,不带电的分子在真空中乱飞,你根本没法让它拐弯。
常见的离子化方式,我列了个表,你在项目里大概率会碰到这些:
| 离子化方式 | 适用样品 | 典型应用 | 避坑提示 |
|---|---|---|---|
| ESI(电喷雾) | 溶液、极性分子 | 蛋白质组学、代谢组学 | 小心盐分堵塞喷针 |
| MALDI(基质辅助激光) | 固体、生物大分子 | 组织成像、微生物鉴定 | 基质选择影响离子产率 |
| EI(电子轰击) | 挥发性小分子 | GC-MS、代谢物标准库 | 碎片太多,分子离子峰可能看不到 |
| APCI(大气压化学电离) | 中等极性、热稳定分子 | 环境污染物、药物 | 容易产生加合物,需要调谐 |
1.2 质谱数据类型:你收到的原始数据长啥样
质谱数据不是一张表,而是一堆"谱图"的集合。从仪器里导出来的原始数据,通常有三层结构:
- 一级质谱(MS1)——全扫描,记录所有离子的m/z和强度。好比一张人群合影,谁在、多高。
- 二级质谱(MS2)——选取某个母离子打碎,记录碎片的质量。好比把一个人拉出来问"你身上都有啥?"
- 色谱维度(Retention Time, RT)——样品通过色谱柱的时间,把不同极性/大小的化合物分离开。
所以我常说,质谱数据是"三维的":保留时间、质荷比、信号强度。你收到的mzXML或mzML文件,本质上就是把这个三维体序列化成了可存储的格式。
再看一组典型的数据结构:
# 一个MS1扫描示例(模拟数据)
Scan 1234, RT=12.34 min, MS1
m/z Intensity
118.0865 4.5e6
155.0344 2.3e5
223.0637 8.9e4
...
# 一个MS2扫描示例
Scan 1235, RT=12.34 min, MS2, Precursor=118.0865@35CE
m/z Intensity
59.0491 7.2e5
74.0237 1.1e6
118.0865 2.0e5 (残余母离子)
1.3 常见数据格式:mzXML与mzML
仪器厂商都有自己的私有格式:Thermo的.raw、AB Sciex的.wiff、Bruker的.d……这些格式不开放,你要读就得靠厂商SDK。好在社区搞了两个开放格式:
- mzXML——早期标准,由Sashimi项目提出,基于XML。优点是简单,工具链成熟。缺点是冗余大,文件体积偏大。
- mzML——HUPO PSI标准,2008年发布,也是XML。吸取了mzXML的教训,结构更清晰。现在的工具基本都支持mzML。
我个人建议:能用mzML就尽量用mzML。原因有三个:
- 它支持二进制编码(zlib压缩),文件能小50%~70%。
- 元数据描述更丰富,便于溯源。
- 几乎所有开源工具(OpenMS、MSGF+、X!Tandem)都优先支持它。
你看一个mzML文件的大致骨架:
<mzML xmlns="http://psi.hupo.org/ms/mzml" ...>
<fileDescription>
<fileContent>
<cvParam cvRef="MS" accession="MS:1000003" name="MS1 spectrum"/>
<cvParam cvRef="MS" accession="MS:1000580" name="MSn spectrum"/>
</fileContent>
</fileDescription>
<instrumentConfigurationList>
<instrumentConfiguration id="IC1">
<cvParam cvRef="MS" accession="MS:1000490" name="LTQ Orbitrap"/>
</instrumentConfiguration>
</instrumentConfigurationList>
<run id="sample_A_rep1">
<spectrumList count="5234">
<spectrum index="0" id="scan=1" defaultArrayLength="5621">
<cvParam cvRef="MS" accession="MS:1000511" name="ms level" value="1"/>
<cvParam cvRef="MS" accession="MS:1000016" name="scan start time" value="0.582" unitName="minute"/>
<binaryDataArrayList count="2">
<binaryDataArray encodedLength="44968">
<cvParam cvRef="MS" accession="MS:1000523" name="64-bit float"/>
<cvParam cvRef="MS" accession="MS:1000576" name="no compression"/>
<binary>AAAAAEy1PkAAAAA+T6Q+...</binary>
</binaryDataArray>
<binaryDataArray encodedLength="44968">
<cvParam cvRef="MS" accession="MS:1000515" name="intensity array"/>
<binary>AAAAAI9KqEA9FqHjQAAAAGCu...</binary>
</binaryDataArray>
</binaryDataArrayList>
</spectrum>
</spectrumList>
</run>
</mzML>
msconvert(来自ProteoWizard)。它能把几乎所有厂商的raw文件转成mzML,还能指定压缩、分级。我每次做批处理都会加 --filter "peakPicking true 1-2" 顺便做峰检测,省一步是一步。
1.4 本章知识体系图
1.5 数据质量从文件头就开始
你可能觉得格式只是"存储方式",跟质量控制没关系。错了。文件头里的元数据,决定了你能不能正确解读后面的二进制数组。我曾经遇到过一批mzML文件,仪器型号写的是"Orbitrap Elite",但实际用的却是"Q Exactive HF"——仪器校准参数完全不同。如果我们直接用通用参数去做质量控制,出来的结果全是偏的。
所以,我建议你拿到任何未知来源的质谱数据,第一步不是跑算法,而是先读文件头:
- 检查
instrumentConfiguration里的型号和参数。 - 确认
cvParam里的ms level是否完整。 - 看
binaryDataArray的压缩方式——如果写的是no compression但实际却是zlib,解压时会直接崩。
# 用Python快速验证mzML文件头(使用pyopenms或pymzml)
import pymzml
run = pymzml.run.Reader("sample.mzML")
for spectrum in run:
if spectrum["ms level"] == 1:
print(f"MS1 scan ID: {spectrum['id']}, RT: {spectrum['scan time']:.2f} min")
break
# 输出示例:MS1 scan ID: scan=1, RT: 0.58 min
- 质谱的三步原理:离子化→质量分析→检测。
- 数据是三维的:保留时间、质荷比、强度。
- mzML 比 mzXML 更优,推荐作为首选格式。
- 数据质量从文件头元数据就开始影响。