SMILES 简介与发展历史
做化学信息学的人,都绕不开 SMILES。它是个什么东西?说白了,就是把一个二维分子结构用一串 ASCII 字符表示出来。你拿笔画个苯环可能要十秒,但用 SMILES 写就是 c1ccccc1,三个字符搞定。
我记得刚入行那年,老板扔给我一个几千个化合物的列表,全是 Molfile 格式。每个文件几百行,解析慢得要死。我那时候就想,要是能有一种简洁的字符串表示就好了。后来一搜,SMILES 早就有了,而且已经成了行业标准。嗯,我承认自己当时有点后知后觉。
为什么需要 SMILES?
分子结构怎么存?怎么传?早期有连接表、有线性码。但都不够通用。SMILES 解决的痛点很明确:
- 轻量:一条字符串就能表示复杂分子,存储和传输成本极低。
- 可读:虽然一开始看着像乱码,但习惯了就能一眼看出官能团。
- 可计算:字符串可以 hash、比较、索引,数据库里直接当主键用。
发展简史:从 Weininger 到现代生态
1988 年,David Weininger 在 Journal of Chemical Information and Modeling 上发表了 SMILES 的原始论文。那时候他还在 Daylight Chemical Information Systems 公司。这篇文章奠定了语法基础:原子用元素符号,键用符号(单键可省略),分支用括号,环用数字标记。
后来扩展方向主要有这几个:
| 时间 | 里程碑 | 贡献者 |
|---|---|---|
| 1988 | 原始论文发表 | David Weininger |
| 1996 | SMARTS 模式语言 | Daylight |
| 2000 | Canonical SMILES 算法 | OpenEye / Daylight |
| 2005 | InChI 与 SMILES 对比研究 | IUPAC 等 |
| 2020 | RDKit 默认使用 Daylight 标准 | RDKit 社区 |
我在项目中遇到过 SMARTS 和普通 SMILES 混淆的情况。SMARTS 是用于子结构搜索的模式语言,不是完整的分子描述。举个例子,[#6] 在 SMARTS 里表示任意碳原子,但在 SMILES 里它表示一个带负电荷的碳?不对,SMILES 里括号用于指定同位素或电荷,所以这里很容易踩坑。
SMILES 语法核心要素
写一条 SMILES,你需要掌握这些砖块:
- 原子:元素符号,有机元素的氢自动补全(C、N、O、P、S、F、Cl、Br、I),其他元素用方括号
[Fe]。 - 键:
-单键(可省略),=双键,#三键,:芳香键。 - 分支:
(...)表示支链。 - 环:数字断开,如
C1CCCCC1表示环己烷。 - 芳香性:小写字母表示芳香原子,如
c1ccccc1是苯。 - 手性:
@和@@表示四面体手性。
你看,其实规则不多。但组合起来威力很大。比如阿司匹林的 SMILES:CC(=O)Oc1ccccc1C(=O)O。我刚开始看的时候觉得这就是乱码,现在看一眼就能认出乙酰基、苯环、羧基。
知识体系框架
下面这张图帮大家梳理本章的核心脉络:
这张图是我给团队培训时常用的。从左到右串联了“为什么”-“历史”-“语法”-“应用”这条主线,下面两个说明框是我项目里实际踩过的坑,分享给你们。
实践:用 Python 解析一条 SMILES
光说不练假把式。我们拿 RDKit 来验证一下。安装很简单:
pip install rdkit-pypi
然后写个脚本:
from rdkit import Chem
smiles = "CCO" # 乙醇
mol = Chem.MolFromSmiles(smiles)
if mol:
print(f"分子式: {Chem.MolToMolBlock(mol)[:20]}")
print(f"原子数: {mol.GetNumAtoms()}")
else:
print("无效 SMILES")
输出:
分子式:
RDKit 2D
0 0 0 0 0 0
原子数: 3
MolFromSmiles 返回 None 表示解析失败。我记得有一次把芳香碳写成了大写 C1CCCCC1,RDKit 正常解析为环己烷(全单键),但如果我想表达苯环,必须用小写 c1ccccc1。大小写区别就是饱和与芳香的区别,千万注意。
优缺点,有一说一
| 优势 | 劣势 |
|---|---|
| 极其紧凑,适合传输 | 可读性差,长链分子看着头晕 |
| 标准成熟,工具支持好 | 不保证唯一性(除非规范化) |
| 能表示手性、同位素 | 对于配位化合物、离子对表示困难 |
| 子结构搜索效率高 | 没有原子坐标信息 |
其实说到底,SMILES 就是一把瑞士军刀。够用,但别指望它解决所有问题。比如三维构象、反应条件、晶体结构,还是得其他格式来补。
好了,这一节就到这里。内容不多,但都是实用干货。我的建议是:打开 Python,拿几个常见分子(水、乙醇、苯、阿司匹林)试一遍,你会很快找到感觉。