异构体与立体化学:手性中心、顺反异构、Z/E标记

做化学信息学,躲不开一个坎——异构体。你想想看,两个分子分子式一模一样,性质却可能天差地别。我在项目中遇到过好几次,因为没处理好立体化学,模型预测的活性跟实验值差了十万八千里。说白了,SMILES 里如果不把立体信息写清楚,后面所有的指纹和建模都是白搭。

异构体的两大分类

先分清楚两个大类:结构异构和立体异构。

  • 结构异构:连接方式不同。比如正丁烷和异丁烷,原子顺序不一样。
  • 立体异构:连接方式一样,空间排列不同。又细分为构型异构和构象异构。

我们做 SMILES 编码,主要关心构型异构——因为构象在常温下会快速转换,不值得费劲去标记。

记住一条铁律:手性中心、双键顺反、Z/E 标记是 SMILES 立体化学的核心。漏掉一个,分子就不完整了。

手性中心与四面体立体化学

一个碳连着四个不同的基团,就是手性中心。SMILES 用 @ 和 @@ 来标记方向。我刚开始学的时候总搞混哪个表示顺时针哪个表示逆时针。后来发现一个诀窍:@ 是标准方向(顺时针),@@ 是反向。

看个例子:

# 丙氨酸的两种对映体
L-丙氨酸:C[C@@H](N)C(=O)O
D-丙氨酸:C[C@H](N)C(=O)O

我习惯在写 SMILES 之前,先把手性原子的局部排列画出来。尤其是复杂天然产物,一个环上可能有四五个手性中心。我曾经踩过一个坑:把天然产物的一个手性中心标记反了,结果合成的化合物完全没有活性——白白浪费了两个月实验时间。

小技巧:SMILES 中手性标记只针对四面体中心。如果遇到 SN2 反应产物,记得检查产物 SMILES 是否正确地翻转了手性符号。

双键顺反与 Z/E 标记

双键不能自由旋转,所以两个基团有顺(cis)和反(trans)之分。SMILES 用 / 和 \ 表示双键两侧的立体构型。

看一个经典例子——2-丁烯:

# 顺-2-丁烯
C/C=C\C

# 反-2-丁烯
C/C=C/C

注意斜线的方向。从第一个碳看向第二个碳,/ 表示键向上,\ 表示键向下。这样就能唯一确定双键的立体构型。

Z/E 标记则是按优先规则(Cahn-Ingold-Prelog)来命名:

  • Z:同一侧(德语 zusammen,一起)
  • E:相对侧(德语 entgegen,相反)

SMILES 里不需要写 Z 或 E,只需要用 / 和 \ 正确连接即可。程序在解析时自然会算出 Z/E 命名。

避坑指南:我曾经写顺反异构的 SMILES 时,漏掉了双键两侧的立体标记。结果 RDKit 读进去之后,默认把它当成未指定立体化学的双键——这样生成的分子指纹就失去了区分异构体的能力。一定要检查输出,确保每个双键都明确标记了方向。

宏观图谱:异构体与立体化学在 SMILES 中的地位

下面是本章的知识结构图,帮助你理解各类异构体以及它们在 SMILES 中的表示方法。

异构体与立体化学 — SMILES 编码中的表示 异构体 结构异构 立体异构 碳链异构 位置异构 官能团异构 构型异构 构象异构 手性中心 双键顺反 SMILES 立体标记 手性:@ / @@ (四面体方向) 双键:/ \ (指定 Z/E 方向) 未标记 = 未知或外消旋

实际编码中的细节

写 SMILES 时,立体标记可以嵌套。比如手性中心又连着含 Z/E 的双键。我推荐这样处理:

  1. 先确定所有手性中心,用 @ 或 @@ 标记。
  2. 再处理所有双键,用 / 或 \ 标记。
  3. 最后用工具(比如 RDKit)验证,确保 Standardizer 不报错。

来看一个复杂点的例子:

# 酒石酸(含两个手性中心)
(2R,3R)-酒石酸:OC(=O)[C@@H](O)[C@@H](O)C(=O)O
(2S,3S)-酒石酸:OC(=O)[C@H](O)[C@H](O)C(=O)O
meso-酒石酸:OC(=O)[C@@H](O)[C@H](O)C(=O)O

注意 meso 形式有一个对称面,两个手性中心方向相反。SMILES 里要分别标出来。

经验之谈:遇到大环化合物,环上可能有多个手性和双键。我习惯把 SMILES 写在一行里,然后用 Chem.MolFromSmiles 读取后打印 Chem.MolToSmiles(mol, isomericSmiles=True) 来双检查。很多编辑器会自动重新排序原子,但立体标记会保留。

Z/E 与顺反的区别

有些同学会搞混:顺反只适用于两个相同基团,Z/E 是通用命名。举个例子:

双键结构 顺/反命名 Z/E 命名 SMILES 标记
CH3-CH=CH-CH3 顺 / 反 Z / E C/C=C\C 或 C/C=C/C
Br-CH=CH-Cl 不适用(基团不同) Z / E Br/C=C\Cl 或 Br/C=C/Cl

在 SMILES 里,你不需要去判断 Z/E,只需要按优先级规则画好 / 和 \ 的方向。RDKit 会帮你算出来。

避坑指南:我曾经在处理一个含氟双键的分子时,把 / 和 \ 写反了。结果是 RDKit 解析时并没有报错,但生成的指纹完全不一样。后来我用 Chem.AssignStereochemistry 函数检查,才发现立体中心被错误标记。建议你在写 SMILES 后立即调用一次立体化学分配函数。

from rdkit import Chem

smiles = "C/C=C\C"
mol = Chem.MolFromSmiles(smiles)
Chem.AssignStereochemistry(mol)
# 然后打印包含立体信息的 SMILES
print(Chem.MolToSmiles(mol, isomericSmiles=True))
# 输出应为:C/C=C\C (如果正确)

为什么这对分子指纹很重要

生成分子指纹时,如果 SMILES 里没有立体信息,指纹对映体完全相同。你想想看,一个左手分子和右手分子,和受体结合完全不一样,但指纹一模一样——模型怎么可能区分?

我习惯在指纹生成前,先检查 SMILES 是否有立体标记。可以用一个简单函数:

def has_stereo_info(smiles):
    mol = Chem.MolFromSmiles(smiles)
    if mol is None:
        return False
    # 检查是否有手性标记
    chiral_centers = Chem.FindMolChiralCenters(mol, includeUnspecified=True)
    # 检查双键立体标记
    stereo_bonds = sum(1 for b in mol.GetBonds() if b.GetStereo() != Chem.BondStereo.STEREONONE)
    return len(chiral_centers) > 0 or stereo_bonds > 0

如果返回 False,说明 SMILES 里没立体信息,这时候生成的指纹就没法区分异构体了。

核心要点:没有立体标记的 SMILES 相当于“平均”了所有立体异构体。在药物分子建模中,这是不可接受的。