1. SMILES 基础:从字符串到分子结构

说实话,SMILES 这玩意儿看起来就是一堆乱码。我第一次接触时,盯着CCO看了半天,心想这能代表乙醇?后来才明白,它其实就是把分子结构“压扁”成一行文本。说白了,SMILES 是一种用 ASCII 字符描述分子拓扑结构的规范。你不需要画图,不需要三维坐标,一行字符串就能完整表达一个分子。

1.1 SMILES 表示法简介

SMILES 的全称是 Simplified Molecular Input Line Entry System,由 David Weininger 在 1980 年代提出。它的核心思想很简单:用深度优先遍历的方式,把分子结构图转化为线性字符串。

我习惯把 SMILES 比作“分子结构的简谱”。五线谱虽然精确,但传播成本高;简谱虽然抽象,但传播效率极高。SMILES 就是化学信息学里的简谱。

来看一个最直观的例子:

# 乙醇的 SMILES
CCO

# 乙烷的 SMILES
CC

# 乙烯的 SMILES
C=C

嗯,这里要注意:C 代表碳原子,O 代表氧原子,= 代表双键。原子默认按照价态补足氢原子——这就是 SMILES 能这么紧凑的原因。

SMILES 的核心原则:非氢原子显式写出,氢原子根据价态隐式补全。

1.2 原子与键的编码规则

SMILES 对原子的编码遵循化学元素周期表的大写-小写规则。单字母元素大写,双字母元素首字母大写、第二字母小写。我开始时就栽过跟头——把Cl写成了CL,结果解析器直接报错。

元素 SMILES 表示 说明
碳 C 标准四价,默认补足 4 个氢
氮 N 标准三价,默认补足 3 个氢
氧 O 标准二价,默认补足 2 个氢
氯 Cl 双字母,首字母大写
溴 Br 双字母,首字母大写
硫 S 标准二价,默认补足 2 个氢
磷 P 标准三价,默认补足 3 个氢

键的编码规则更简单:

  • 单键:默认不写,原子直接相邻
  • 双键:用 = 表示
  • 三键:用 # 表示
  • 芳香键:用小写字母表示,如 c 代表芳香碳

个人习惯:我写芳香化合物时,一定把小写字母和双键交替表达区分开。苯环写成 c1ccccc1 而不是 C1=CC=CC=C1,虽然两者都合法,但小写版本更符合化学直觉。

1.3 分支与环的表示

线性分子还好说,遇到分支和环,SMILES 就需要更复杂的语法了。我在项目中处理过最大规模的分支结构——一个天然产物分子含有 15 个分支点。如果没有规范的括号嵌套,解析起来非常痛苦。

分支用圆括号表示。括号内的内容属于侧链,括号后的内容回到主链。你可以嵌套多层括号,就像数学表达式一样。

# 异丙醇 (Isopropanol)
CC(O)C

# 叔丁醇 (tert-Butanol)
CC(C)(C)O

# 丙氨酸 (Alanine)
CC(N)C(=O)O

为什么会这样?因为 SMILES 的遍历算法是深度优先——先走主链,遇到分支就递归进入括号,分支走完再回到分叉点继续。你想想看,这和计算机里树的遍历算法一模一样。

环用数字标记。环的断开点用相同数字标记,数字成对出现。

# 环己烷
C1CCCCC1

# 苯
c1ccccc1

# 环丙烷
C1CC1

# 双环结构(十氢萘)
C1CCC2CCCCC2C1

我曾经被一个同事坑过:他在一个 SMILES 里同时出现了 %10 和 %11,结果 %1 和 %10 的解析优先级冲突了。记住,用 % 前缀表示两位数及以上的环编号,避免与单数字编号混淆。

环编号可以重复使用——不同的环用不同的数字。遇到螺环或桥环,需要小心规划环编号的顺序。我建议你画个草图再写 SMILES,不然很容易出现“想当然”的错误。

下面我用一张图把 SMILES 的构成要素梳理一下:

SMILES 表示要素结构图 SMILES 表示 原子编码 键的编码 拓扑结构 单字母元素 双字母元素 单键(默认) 双键(=) 分支(括号) 环(数字) 解析策略 • 原子 → 键 → 拓扑:逐层构建 • 分支:遇到 '(' 进入子递归,')' 返回 • 环:相同数字标记的原子通过环键连接

我常跟团队说:“SMILES 就是化学领域的 JSON。”结构化的、自描述的、容易被程序解析的。你把原子当成 JSON 的键,把化学键当成键值对之间的连接关系,分支就是嵌套对象,环就是引用关系。越琢磨越觉得它设计得精巧。

避坑指南:SMILES 的解析器有很多实现——Open Babel、RDKit、CDK 等。不同解析器对非规范 SMILES 的处理可能不同。我坚持使用 canonical SMILES(规范化 SMILES)来避免歧义。RDKit 的 Chem.MolToSmiles() 默认输出 canonical 版本,值得信赖。

嗯,到这里 SMILES 的基础知识就铺垫完了。原子怎么编码、键怎么表示、分支和环怎么处理,这些是后续一切数据增强操作的地基。下一篇我们就要开始动手了——用 Python 配合 RDKit 把 SMILES 转成分子对象,再探索各种数据增强的策略。记住,扎实的基础比花哨的技巧更重要。