SMILES表示法基础:分子结构编码规则、线性表示、规范SMILES
做化学信息学,绕不开SMILES。说白了,它就是分子结构的「身份证号」。你想想看,一个二维结构图,在计算机里怎么存?总不能存个图片吧。SMILES就是解决这个问题的——用一串字符,把分子结构描述清楚。
我第一次接触SMILES,是在做化合物库清洗的时候。那时候没注意规范问题,同一分子有人写CCO,有人写OCC,导致去重时漏掉不少。嗯,从那次起我就知道,SMILES看似简单,坑其实不少。
为什么需要SMILES?
有机化学里,分子结构图是最直观的。但计算机不认图。我们需要一种线性的、无歧义的、文本化的表示方式。SMILES(Simplified Molecular Input Line Entry System)正是为此而生。它由David Weininger在1980年代提出,现在已经是化学信息学的事实标准。
- 紧凑:一个字符串就能表示极其复杂的分子
- 可读:有经验的化学家能直接“读”出结构
- 可计算:字符串可以哈希、比较、作为数据库主键
SMILES编码规则
1. 原子表示
原子直接用元素符号。有机常用元素:C、N、O、S、P、F、Cl、Br、I。氢原子通常省略(隐含),除非是特殊情况(如氢同位素)。
举个例子,乙醇的SMILES:CCO。你看,三个碳连在一起?不对。实际上C代表甲基,第二个C是亚甲基,O是羟基。氢全部隐含了。如果你非要写全,可以写成CC(O)C?嗯这里要注意,乙醇正确的SMILES是CCO,因为羟基连在第二个碳上。
CC(O)C表示乙醇,结果匹配不上其他来源的CCO。原因:CC(O)C其实是异丙醇(2-丙醇)的写法。SMILES中括号内的原子表示连在前一个原子上,顺序很重要。
2. 键型表示
| 键型 | 符号 | 示例 | 说明 |
|---|---|---|---|
| 单键 | -(可省略) | CC 等同 C-C | 酒精的C-C键 |
| 双键 | = | C=C | 乙烯 |
| 三键 | # | C#C | 乙炔 |
| 芳香键 | :(或小写原子) | c1ccccc1 | 苯环(小写c代表芳香碳) |
单键可以省略不写,这是SMILES常见缩写。双键和三键必须写。芳香键用冒号,但更常用的是小写原子符号:c代表芳香碳,n代表芳香氮,等等。
3. 分支
用圆括号()表示分支。括号里的内容连接在前一个原子上。比如丙氨酸的SMILES:CC(N)C(=O)O。
来了,常见坑:如果你看到CC(=O)O,这是乙酸。括号表示=O连在第二个碳上,而不是连在氧上。这个顺序我花了好一阵才适应。
4. 环结构
用数字标记环的断开与闭合。比如苯环:c1ccccc1。第一个c1标记环起点,最后一个c1表示闭合回1号位置。如果有两个环,用2、3等数字。
萘的SMILES:c1ccc2ccccc2c1。这有两个环,共用一条边。数字不能重复,每个环用唯一数字。
5. 电荷与同位素
电荷用+和-表示。比如铵根:[NH4+]。注意方括号的作用:当原子有特殊状态(如电荷、同位素、非标准价)时,必须用方括号括起来。
同位素在前加数字,比如重氢(氘):[2H]。
正规化与规范SMILES
你知道同一个分子可以写出很多种SMILES吗?乙醇可以是CCO,也可以是OCC,甚至C(O)C。虽然它们对应同一个分子,但在字符串层面不同。如果你的数据库用SMILES做主键,那就悲剧了。
这就是规范SMILES的由来。规范SMILES通过一套规则(比如原子编号顺序、分支优先顺序、环编号最小化等),保证同一个分子只有一个SMILES字符串。最常用的生成工具是RDKit的Chem.MolToSmiles(mol, canonical=True)。
我在做一个百万级化合物库清洗时,遇到过这样的场景:两个不同供应商的库,明明分子一样,SMILES却不同。后来我强制跑一遍规范SMILES,去重率提高了15%。
from rdkit import Chem
# 不同写法的乙醇
smiles1 = "CCO"
smiles2 = "OCC"
smiles3 = "C(O)C"
mol1 = Chem.MolFromSmiles(smiles1)
mol2 = Chem.MolFromSmiles(smiles2)
mol3 = Chem.MolFromSmiles(smiles3)
# 规范后全部变成 "CCO"
canon1 = Chem.MolToSmiles(mol1)
canon2 = Chem.MolToSmiles(mol2)
canon3 = Chem.MolToSmiles(mol3)
print(canon1, canon2, canon3)
# 输出: CCO CCO CCO
知识体系:从分子结构到规范SMILES
下面这张SVG图,帮你理清SMILES编码的核心流程:
SMILES的局限与须知
SMILES虽好,但不是万能的。我个人踩过几个坑:
- 手性表示:基本的SMILES不支持手性。扩展版用
@和@@表示手性中心。比如L-丙氨酸:C[C@H](N)C(=O)O。 - 没有立体化学:顺反异构要用
/和\表示,比如C/C=C\C表示顺-2-丁烯。 - 不能表示多组分混合物:SMILES只有一个分子。混合物需要用
.分隔,比如NaCl水溶液:[Na+].[Cl-]。 - 歧义风险:如果不对SMILES做规范化处理,很多数据库里同分异构体会被当成不同物质。
C1=CC=CC=C1表示苯环,但规范工具跑出来是c1ccccc1。除非你写的是骨架测试,否则永远用程序生成规范SMILES。
实践:如何编写与验证SMILES
如果你刚开始接触,建议按这个流程走:
- 画出分子结构,确定所有重原子(非氢)
- 确定连接顺序:选择一个起始原子,逐步写出线性链
- 遇到分支,用括号括起来
- 遇到环,用数字标记闭合位置
- 芳香环用对应的小写原子
- 最后用RDKit或Open Babel验证并转换为规范形式
举个例子,咖啡因的SMILES:Cn1c(=O)c2c(ncn2C)n(C)c1=O。你看,有分支(=O)、有环(数字1和2)、有甲基(用小写c表示芳香碳配合数字)。如果是新手写这个,很容易漏掉某个闭环数字或写错括号。
MolToSmiles还是CDK的generateSMILES,效果一样。这能节省你后面90%的匹配头疼时间。
常见分子SMILES示例
| 分子 | 结构描述 | 非规范写法 | 规范写法 |
|---|---|---|---|
| 水 | H-O-H | O | O |
| 乙醇 | CH3-CH2-OH | OCC | CCO |
| 苯 | C6H6(芳香) | C1=CC=CC=C1 | c1ccccc1 |
| 乙酸 | CH3-COOH | CC=O(错误!) | CC(=O)O |
| 甲烷 | CH4 | C | C |
注意乙酸那个例子:CC=O是乙醛,完全不同的分子。所以写SMILES时一定要小心双键和括号的位置。我见过最多错误就是羧基写成了醛基。
好了,这一章的内容就到这。SMILES是后续所有分析的基础。你只有把这一关搞扎实了,后面做批次差异分析时才能放心地操作字符串、比较子结构、计算相似度。别着急,慢慢来,先从水分子开始,写到苯环,写到咖啡因,你会有感觉的。