3. RDKit 安装与基础操作:环境配置、分子对象创建与 SMILES 转换

好,咱们开始第三章。这一章是整个ADMET特征筛选流程的基石——RDKit。说白了,没有RDKit,后面所有分子描述符的计算都是空谈。我当年刚入行时,为了配这个环境折腾了一下午,现在回想起来,其实大部分坑都能提前避开。

3.1 环境配置:你得先有把好用的刀

RDKit的安装,我强烈建议你通过Conda来管理。为什么?因为它的依赖链太长,用pip容易碰上一堆编译错误。我个人习惯用Miniconda,轻量,够用。

创建一个干净的环境,指定Python 3.10,稳得很。

conda create -n rdkit-env python=3.10
conda activate rdkit-env

然后直接安装RDKit。注意,别从默认通道装,从conda-forge拿,版本更新而且包更全。

conda install -c conda-forge rdkit

安装完成后,验证一下。

python -c "from rdkit import Chem; print(Chem.RDKFingerprint)"
python -c "import rdkit; print(rdkit.__version__)"

能正常输出,就说明装好了。如果报错,大概率是依赖冲突。嗯,这时别硬装,重新创建个环境试试。

【避坑指南】

我曾经在Windows上直接用pip install rdkit,结果编译了40分钟,最后报了个VC++错误。后来直接用conda install -c conda-forge rdkit,三分钟搞定。别跟自己过不去。

另外,为了后续可视化分子结构,顺手装上Jupyter和ipywidgets。

conda install -c conda-forge jupyter ipywidgets
conda install -c conda-forge matplotlib
【小提示】

用conda list | grep rdkit可以快速检查是否安装成功及版本号。别忘了在Jupyter里激活widgets:jupyter nbextension enable --py widgetsnbextension。

3.2 分子对象创建:从字符串到化学结构

环境配好,咱们开始上手干活。RDKit中最核心的对象就是Mol对象。你想想看,它就是一个分子在计算机里的“分身”。

3.2.1 从SMILES创建

最常见的方式,就用SMILES。我平时做数据清洗时,第一行代码永远是这玩意儿。

from rdkit import Chem

# 最简单的一个分子:乙醇
mol = Chem.MolFromSmiles("CCO")
print(mol)

输出应该是,说明创建成功了。如果返回None,那说明你这个SMILES有问题。我在项目中遇到过好几次,明明是标准的SMILES,结果RDKit就是不吃。后来发现是空格和换行符在捣乱——记得strip一下。

smiles_str = " CCO\n"
mol = Chem.MolFromSmiles(smiles_str.strip())
print(mol.GetNumAtoms())  # 输出3

3.2.2 从Mol文件载入

有时候数据是从供应商给的SDF或MOL文件里读出来的。RDKit也支持直接解析。

mol_from_file = Chem.MolFromMolFile("path/to/molecule.mol")
print(mol_from_file.GetNumAtoms())

也可以批量读SDF文件,这个在ADMET数据集处理里非常常见。

suppl = Chem.SDMolSupplier("path/to/compounds.sdf")
for mol in suppl:
    if mol is not None:
        print(mol.GetNumAtoms())
【核心要点】

创建Mol对象后,一定要先检查是否为None。我早期写脚本时,忘了检查,结果后续算描述符时直接崩溃。所以养成好习惯:if mol is not None: ...

3.3 SMILES与分子转换:读懂化学的通用语言

有了Mol对象,我们就可以在SMILES和其他表示形式之间自由切换了。这里有个坑,SMILES可能不唯一——同样的分子,写法可以千变万化。但RDKit可以帮你规范化。

3.3.1 向SMILES转换

从Mol对象生成SMILES,用MolToSmiles。这个函数默认会做一次规范化,帮你统一格式。

from rdkit import Chem

mol = Chem.MolFromSmiles("C1=CC=CC=C1")  # 苯环的SMILES
smiles_canonical = Chem.MolToSmiles(mol)
print(smiles_canonical)  # 输出 c1ccccc1

看到了吧?原来的大写C变成了小写c,位置也变了。这就是规范化的标准表示。

3.3.2 获得所有SMILES与原子SMILES

有时候你需要知道所有可能的SMILES表示,使用MolToSmiles的allBondsExplict等参数可以做到。或者用MolToRandomSmiles生成随机SMILES,用来做数据增强。

import random
from rdkit import Chem

mol = Chem.MolFromSmiles("CCO")
random_smiles = Chem.MolToRandomSmiles(mol, random)
print(random_smiles)  # 每次输出可能不同

更细粒度的是,你可以获取某个原子在SMILES中的对应位置——这在分析反应中心时极有用。

atom_smiles = Chem.MolFragmentToSmiles(mol, atomsToUse=[1])  # 只包含氧原子和它周围的键
print(atom_smiles)  # 输出 O

3.3.3 SMARTS与InChI转换

除了SMILES,RDKit还支持SMARTS(子结构模式)和InChI(国际化学标识)。

SMARTS常用于模式匹配。比如你想查所有芳香性碳原子:

pattern = Chem.MolFromSmarts("c")
mol = Chem.MolFromSmiles("c1ccccc1")
matches = mol.GetSubstructMatches(pattern)
print(len(matches))  # 输出6

InChI转换则更侧重唯一性标识:

inchi = Chem.MolToInchi(mol)
print(inchi)  # InChI=1S/C6H6/c1-2-4-6-5-3-1/h1-6H

mol_from_inchi = Chem.MolFromInchi(inchi)
print(Chem.MolToSmiles(mol_from_inchi))  # c1ccccc1

这下明白了吧?SMILES、SMARTS、InChI这三兄弟,各有各的用处。我个人习惯是:日常处理用SMILES,模式匹配用SMARTS,需要全球唯一标识时用InChI。

【实战经验】

我在做ADMET数据清洗时,经常用InChI来去重。两个SMILES看起来一样,但写法不同,用字符串比较就失效了。转成InChI后再比较,保证唯一性。

3.4 本章知识结构图

我把这一章的核心逻辑画成了一张图,方便你从高处理解。

第三章:RDKit安装与基础操作 环境配置 Conda安装 Pip安装(不推荐) 分子对象创建 MolFromSmiles MolFromMolFile SDMolSupplier MolFromInchi SMILES 转换

3.5 基础操作与常用技巧

再往后看,Mol对象创建好了,怎么用它做点事情?这里列几个我每天都会用到的操作。

3.5.1 原子与键的遍历

mol = Chem.MolFromSmiles("CCO")
for atom in mol.GetAtoms():
    print(atom.GetAtomicNum(), atom.GetSymbol(), atom.GetDegree())

for bond in mol.GetBonds():
    print(bond.GetBondType(), bond.GetBeginAtomIdx(), bond.GetEndAtomIdx())

3.5.2 添加氢原子与计算分子式

mol = Chem.MolFromSmiles("CCO")
mol_h = Chem.AddHs(mol)  # 显示所有氢
print(mol_h.GetNumAtoms())  # 9(原来的3个原子+6个H)

formula = Chem.rdMolDescriptors.CalcMolFormula(mol)
print(formula)  # C2H6O

3.5.3 分子可视化(在Jupyter中)

from rdkit.Chem import Draw

mol = Chem.MolFromSmiles("CCO")
img = Draw.MolToImage(mol, size=(300, 300))
display(img)  # Jupyter中显示
【经验总结】

RDKit的API非常统一:用MolFrom*创建,用MolTo*转换。记住这个原则,后面学描述符计算时顺风顺水。

好了,这一章的内容就到这。环境配好了,分子能创建能转换了,下一步我们就可以开始真正计算ADMET描述符了。这条路,咱们一步步趟。