2026年4月16日 研究日志¶
研究内容:阅读了一篇蛋白质组学相关综述和一篇利用iPSC进行多组学研究的论文。这两篇内容太丰富了,总结尚未完成。今天讲一个大家可能经常看到,但又因为现在各种工具的自动处理而忽略的内容。就是fastq文件的base quality行。就是每条记录里最后那条各种符号横飞宛如乱码的那一行,同时也是其之所以与fasta文件不同的那一行。
1. FASTQ 的四行结构¶
FASTQ 是测序数据最常见的格式,每条 read 占四行:
@read_name
ACGTACGTACGT
+
HHGFFEDDDCCB
其中:
- 第 1 行:read 名称
- 第 2 行:碱基序列
- 第 3 行:占位符(通常是
+) - 第 4 行:base quality(质量分数),用 ASCII 字符编码
第四行就是今天要聊的内容哦。
📝 附言:为什么测序需要质量分数?(理想 vs 现实)¶
在理想世界里,测序仪读到的每一个碱基都应该是 100% 正确 的:
A 就是 A
C 就是 C
G 就是 G
T 就是 T
但现实世界远没有这么完美。
现实世界的测序会出错¶
测序仪在读取碱基时会受到很多因素影响:
- 光信号太弱或太强
- 相邻 cluster 干扰
- 化学反应效率不稳定
- 测序 cycles 越往后噪声越大
- 某些序列(如同聚物)更难读
因此,测序仪对每个碱基都会给出一个 “我有多大把握读对了” 的概率。
这就是 测序错误概率 $P_{\text{error}}$
2. 测序错误概率 $P_{\text{error}}$ 是怎么来的?¶
测序仪内部会对每个碱基的信号进行建模,例如:
- 光强度
- 峰形
- 背景噪声
- 颜色通道分离度
- 该 cycle 的整体质量
然后根据这些信号计算:
$$ P_{\text{error}} = \text{该碱基被读错的概率} $$
例如:
- (P = 0.01) → 1% 的可能性读错
- (P = 0.001) → 0.1% 的可能性读错 但一大堆的小数不方便机器储存及输出,因此才发明了质量分数Q值。
2. Base Quality(Q 值)是什么?¶
测序仪对每个碱基都会给一个“可信度”,称为 Phred 质量分数(Q)。
它的定义是:
$$ Q = -10 \log_{10}(P_{\text{error}}) $$
其中 $P_{\text{error}}$ 是测序错误的概率。
容易得:
- Q = 20 → 错误率 1%
- Q = 30 → 错误率 0.1%
- Q = 40 → 错误率 0.01%
Q 值越高,碱基越可靠。
3. FASTQ 如何把 Q 值编码成字符?(Phred+33)¶
Illumina 现代测序平台使用 Phred+33 编码:
$$ \text{ASCII code} = Q + 33 $$
也就是说:
- 字符
'!'(ASCII 33) → Q = 0 - 字符
'I'(ASCII 73) → Q = 40
你看到的那一串奇怪字符,其实就是质量分数的“压缩版”。
4. 常用 ASCII ↔ Q 值对照表¶
下面是最常见的质量字符(你博客里可以直接贴这张表):
| 字符 | ASCII | Q 值 | 错误率(约) |
|---|---|---|---|
! |
33 | 0 | 1(完全不可信) |
" |
34 | 1 | 0.79 |
# |
35 | 2 | 0.63 |
+ |
43 | 10 | 0.1 |
5 |
53 | 20 | 0.01 |
? |
63 | 30 | 0.001 |
I |
73 | 40 | 0.0001 |
J |
74 | 41 | 0.000079 |
K |
75 | 42 | 0.000063 |
你会发现:
- 越靠后的字符 → Q 越高
- Illumina 常见 Q 值范围是 Q20–Q40
5. 一个简单示例¶
假设 FASTQ 的质量行是:
HHGFFEDDDCCB
我们可以逐个字符转换:
H→ ASCII 72 → Q = 39G→ ASCII 71 → Q = 38F→ ASCII 70 → Q = 37E→ ASCII 69 → Q = 36D→ ASCII 68 → Q = 35C→ ASCII 67 → Q = 34B→ ASCII 66 → Q = 33
这说明:
- 这个 read 的质量非常高(Q33–Q39)
- 错误率大约在 0.05%–0.001% 之间
6. 小结¶
- FASTQ 的第 4 行是 base quality
- 使用 Phred+33 编码
- Q 值越高,碱基越可靠
- ASCII 字符是为了节省空间,麻烦你自己转化咯
- 你可以用
ord(char) - 33得到 Q 值,并根据Q值得到具体的错误概率,如下所示:
import math
def char_to_q(char):
"""
将 FASTQ 的质量字符转换为 Phred Q 值(Phred+33)
"""
return ord(char) - 33
def q_to_perror(q):
"""
根据 Q 值计算测序错误概率 P_error
Q = -10 * log10(P_error)
=> P_error = 10^(-Q/10)
"""
return 10 ** (-q / 10)
# 示例:一串质量字符
quality_string = "HHGFFEDDDCCB"
print("质量字符:", quality_string)
print("字符 | Q值 | P_error")
print("--------------------------")
for c in quality_string:
q = char_to_q(c)
perror = q_to_perror(q)
print(f" {c} | {q:2d} | {perror:.6f}")
质量字符: HHGFFEDDDCCB 字符 | Q值 | P_error -------------------------- H | 39 | 0.000126 H | 39 | 0.000126 G | 38 | 0.000158 F | 37 | 0.000200 F | 37 | 0.000200 E | 36 | 0.000251 D | 35 | 0.000316 D | 35 | 0.000316 D | 35 | 0.000316 C | 34 | 0.000398 C | 34 | 0.000398 B | 33 | 0.000501
附注: 完整Q=0–41 的 ASCII ↔ Q 值对照表(illumina设备输出的质量分数行是不会输出Q>41的质量分数,所以以下是你所有可能看到的字符)
| Q 值 | ASCII 码 | 字符 |
|---|---|---|
| 0 | 33 | ! |
| 1 | 34 | " |
| 2 | 35 | # |
| 3 | 36 | $ |
| 4 | 37 | % |
| 5 | 38 | & |
| 6 | 39 | ' |
| 7 | 40 | ( |
| 8 | 41 | ) |
| 9 | 42 | * |
| 10 | 43 | + |
| 11 | 44 | , |
| 12 | 45 | - |
| 13 | 46 | . |
| 14 | 47 | / |
| 15 | 48 | 0 |
| 16 | 49 | 1 |
| 17 | 50 | 2 |
| 18 | 51 | 3 |
| 19 | 52 | 4 |
| 20 | 53 | 5 |
| 21 | 54 | 6 |
| 22 | 55 | 7 |
| 23 | 56 | 8 |
| 24 | 57 | 9 |
| 25 | 58 | : |
| 26 | 59 | ; |
| 27 | 60 | |
| 28 | 61 | = |
| 29 | 62 | > |
| 30 | 63 | ? |
| 31 | 64 | @ |
| 32 | 65 | A |
| 33 | 66 | B |
| 34 | 67 | C |
| 35 | 68 | D |
| 36 | 69 | E |
| 37 | 70 | F |
| 38 | 71 | G |
| 39 | 72 | H |
| 40 | 73 | I |
| 41 | 74 | J |
发现规律了吗?因为是根据ASCII码生成的字符,而字符又是按顺序来的,所以符号和数字往往意味着测序结果不够可靠,而字母则相对可靠,尤其是越往后越可靠,要都是J……那应该是用来展示的示例(笑)好了,今天就到这里,下个工作日见!