第三章:立体化学、同位素与电荷表示

这一章我们聊聊 SMILES 里三个容易翻车的细节——立体化学、同位素和电荷。这三个东西看着不起眼,但一旦写错,下游的分子检索、性质预测全部跑偏。我在项目里见过不止一次,因为手性标记错了一个符号,整个虚拟筛选的结果全废。

3.1 立体化学:手性中心的标记

SMILES 用一套“方向”标记来表达分子的三维信息。具体怎么做的?其实很简单——顺着 SMILES 字符串爬一遍,每个手性原子周围,系统会记录它的邻居方向,然后用一个@或者@@来区分两种对映体。

3.1.1 基本规则

对于四面体手性中心,SMILES 用@表示反时针(counter‑clockwise),用@@表示顺时针(clockwise)。这个方向是相对于 SMILES 字符串中原子出现顺序的,不是绝对 R/S。所以你写的时候必须保证输入顺序一致,不然解析结果会反。

关键点:手性标记只出现在分支或方括号内的原子上。比如:
# 正确定义(R)-2-丁醇
C[C@H](O)CC

# 正确定义(S)-2-丁醇
C[C@@H](O)CC
我个人的习惯:写完手性分子后,先拿可视化软件(比如 RDKit 的 Draw)看一眼结构,确认方向正确再往下走。你想想看,要是批量生成数万个 SMILES 结果全是反的,重新跑一遍的时间成本太高了。

3.1.2 顺反异构:双键与环

双键的顺反用/和\表示。这两个符号插在双键两边,表示取代基的相对空间位置。举个例子:

# (E)-2-丁烯
C/C=C/C

# (Z)-2-丁烯
C/C=C\C

需要注意,SMILES 里/和\是方向键,不是斜杠或反斜杠字符。我曾经在写脚本时不小心把/写成普通的/,解析器直接报错,白白浪费了一上午。

避坑指南:我曾经在处理环状顺反异构时,忘了环上的默认键是不带方向的。如果你的分子是环内双键,一定要显式加上/或\,否则解析器会认为没有立体信息。

3.2 同位素:原子质量的标记

同位素表示用数字前缀,放在元素符号前面,方括号内。比如碳‑13 写成[13C],氘写成[2H]。这个规则很直观,但有几个容易踩的坑:

  • 同位素数字必须紧贴元素符号,不能有空格。
  • 当原子同时有同位素和电荷时,顺序是:同位素 → 元素符号 → 电荷。例如:[13CH3+]。
  • 对于没有指定同位素的原子(最常见的自然丰度),可以不加前缀,默认就是最丰同位素。
批量一致性检查的要点:如果你的数据库中有些分子用了[13C],有些用了[C],它们的化学性质相同,但 SMILES 字符串不同。在做去重或批次比较时,必须统一规则:要么全部保留同位素标记,要么全部标准化为默认同位素。

我遇到过这样一个场景:一批输入文件里,同一个化合物一半写了[13CH3]一半写了C,导致关联表连接失败。现在我在预处理阶段都会加一个规则:将所有[12C](如果是显式写出的)先替换成C,再统一同位素格式。

3.3 电荷:正负号的写法

电荷用方括号内的+和-表示,紧跟在元素符号后面。多个电荷用数字指定,比如[Fe+3]、[SO4-2]。注意:+和-的位置不能颠倒,数字不能放在符号前面。

# 正确示例
[Na+]    # 钠离子
[Ca+2]   # 钙离子
[OH-]    # 氢氧根离子

# 常见错误(会解析失败或得到错误结构)
[Na1+]   # 多余数字1,实际上应该写成[Na+]
[Ca++]   # 废弃写法,尽量用[Ca+2]
小技巧:如果你在处理大量离子 SMILES,可以用 Python 正则把[Ca++]这种旧格式统一转成[Ca+2]。我写过一个脚本,专门处理七种常见的“歧义电荷写法”,能减少 90% 的解析异常。

3.4 三者组合时的书写顺序

当同一个原子同时需要立体化学、同位素和电荷时,SMILES 要求按固定顺序书写:

  1. 同位素(可选)
  2. 元素符号(必需)
  3. 立体化学标记(可选,仅限手性)
  4. 电荷(可选)
  5. 氢原子数量(可选,通常用于显式氢)

举个例子,一个氘代的手性铵离子:[2NH3+] —— 同位素2,元素N,氢数3,电荷+。注意这里没有手性标记,因为氮是四级铵,不是手性中心。如果是一个手性碳,比如[13C@H],就变成了:同位素→元素→立体标记→氢→电荷(本例无电荷)。

注意:顺序绝对不能乱。我曾经看到有人写了[C@13H],解析器直接报错,因为@后面不能接数字。规范是死的,写代码的时候一定要按规矩来。

3.5 知识结构一览

下面这张图把本章的核心关系梳理清楚了:

SMILES 立体化学·同位素·电荷表示体系 立体化学 同位素 电荷 @ / @@(四面体) / \(顺反双键) [13C] [2H] 等 方括号内数字前缀 + / - 符号 数字指定多电荷 组合顺序:同位素→元素→立体→氢→电荷 例如 [2NH3+]、[13C@H] 一致性检查核心:顺序 & 格式

3.6 常用工具与自动化检查

手动检查成千上万的 SMILES 不现实。我这里推荐两个做法:

  1. RDKit 标准化:调用 Chem.MolToSmiles(mol, isomericSmiles=True) 可以标准输出带立体信息的 SMILES。如果是同位素/电荷,MolFromSmiles 解析后再输出就能自动修复格式错误。
  2. 正则表达式预检:脚本里跑一遍正则,检查是否有[C@@]后面跟了数字、[Fe2]没有电荷符号之类的问题。
示例脚本片段:
import re
import sys

def check_smiles_format(smiles):
    # 检查立体标记是否放在正确位置
    if re.search(r'\[[A-Za-z]+@[0-9]', smiles):
        print(f"错误:立体标记后不应直接跟数字: {smiles}")
        return False
    # 检查电荷是否用了旧式写法
    if re.search(r'\[[A-Za-z]+\+\+', smiles):
        print(f"警告:建议使用数字电荷如 [Ca+2]: {smiles}")
    return True
我个人经验:把这段检查脚本加到 CI/CD 流水线里,每次提交新的 SDF 或 SMILES 文件时自动跑一遍。即使只抓出 1% 的错误,也能避免后续全部重算的悲剧。

好了,第三章就聊这些。立体化学、同位素、电荷是 SMILES 批次一致性检查中最容易出问题的三个点——往后几章我们会看到它们怎么影响到实际的数据比对和搜索。