3. Python与化学信息学:RDKit、Open Babel等工具
说到化学信息学,Python 生态里有两个绕不开的工具——RDKit 和 Open Babel。我个人觉得,搞 SMILES 序列处理,RDKit 是主力,Open Babel 做格式转换更趁手。这章咱们就聊聊这两把“瑞士军刀”怎么用,以及我在项目中踩过哪些坑。
3.1 RDKit:化学信息学的“神兵利器”
RDKit 是一个开源的化学信息学工具包,底层用 C++ 写的,但提供了 Python 接口。它把 SMILES 转成分子对象后,你能干很多事:计算分子量、提取环结构、算指纹,甚至做分子对接前的预处理。
我最早接触 RDKit 是在一个药物筛选项目里。当时要处理几十万条 SMILES,手动清理肯定不现实。RDKit 帮了大忙——几行代码搞定。
核心思想:SMILES 只是字符串,RDKit 把它变成“活”的分子对象。你可以像操作 Python 对象一样操作分子。
3.1.1 安装与基本用法
安装 RDKit 其实挺简单的。我个人习惯用 conda 安装,因为依赖关系处理得比较好。
conda install -c conda-forge rdkit
安装好之后,来看看怎么把 SMILES 转换成分子对象:
from rdkit import Chem
from rdkit.Chem import Descriptors, Draw
# 把 SMILES 转成分子对象
smiles = "CCO" # 乙醇
mol = Chem.MolFromSmiles(smiles)
if mol is not None:
print(f"分子式: {Chem.MolToSmiles(mol)}")
print(f"分子量: {Descriptors.MolWt(mol):.2f}")
# 原子数
print(f"原子数: {mol.GetNumAtoms()}")
else:
print("SMILES 无效")
你看,从字符串到分子对象,一步到位。不过我刚开始用的时候,有个坑:MolFromSmiles 返回 None 时,后续操作全炸。所以记得加个判断。
注意:RDKit 对 SMILES 格式要求严格。比如“C1CC1”这种环写法,它认;“C1CC1(缺失右括号)”就不认。批量处理时,一定要检查返回值。
3.1.2 常用功能:计算性质与指纹
实际应用中,我们常需要计算分子的物理化学性质。RDKit 的 Descriptors 模块直接封装好了。
from rdkit.Chem import Descriptors
mol = Chem.MolFromSmiles("CC(=O)Oc1ccccc1C(=O)O") # 阿司匹林
mw = Descriptors.MolWt(mol)
logp = Descriptors.MolLogP(mol)
hba = Descriptors.NumHAcceptors(mol)
hbd = Descriptors.NumHDonors(mol)
print(f"分子量: {mw:.2f}, LogP: {logp:.2f}")
print(f"氢键受体: {hba}, 供体: {hbd}")
但有个地方要当心:MolLogP 是预测值,不是实验数据。我曾在项目中直接用这个值做筛选,结果后期验证时发现误差挺大。后来我改成用 MolLogP 做初筛,再用更精确的方法验证。
分子指纹也是常用功能。说白了,就是把分子结构编码成固定长度的二进制向量,用于相似度比较。
from rdkit.Chem import AllChem
mol = Chem.MolFromSmiles("c1ccccc1C(=O)O") # 苯甲酸
fp = AllChem.GetMorganFingerprintAsBitVect(mol, radius=2, nBits=2048)
# 转成位串
bit_string = fp.ToBitString()
print(f"指纹长度: {len(bit_string)}")
print(f"前50位: {bit_string[:50]}")
小技巧:Morgen 指纹的 radius 参数影响信息量。radius=2 适合大多数任务,但你想捕捉更细的局部结构,可以试试 radius=3。不过指纹越长,计算越慢。
3.2 Open Babel:格式转换的“多面手”
Open Babel 和 RDKit 不一样。它更像一个文件格式转换器,支持超过 110 种化学文件格式。SMILES、SDF、MOL2、PDB……你想从 A 格式转到 B 格式,它基本都能干。
我记得有一次,合作方发来一批 SDF 文件,可我需要的是 SMILES。手动转?别逗了,几万条呢。Open Babel 一行命令就搞定。
3.2.1 安装与命令行用法
同样建议用 conda 安装:
conda install -c openbabel openbabel
装好后,命令行下就能用 obabel 命令。工作流程通常是这样的:
obabel input.sdf -O output.smi
就这么简单。但如果你需要更多选项,比如输出的是规范化的 SMILES:
obabel input.sdf -O output.smi -c
-c 参数表示“规范化”。相信我,没这个参数,同一分子在不同软件里可能会生成不同的 SMILES。
核心思想:RDKit 适合做分子操作和分析,Open Babel 擅长格式转换。两者不冲突,配合使用效果更好。
3.2.2 Python 调用 Open Babel
Open Babel 也提供了 Python 接口,虽然没 RDKit 那么友好,但也够用。
from openbabel import pybel
# 读取 SMILES
mol = pybel.readstring("smi", "CCO")
# 转换成 MOL2 格式
mol.write("mol2", "ethanol.mol2")
# 批量转换
for mol in pybel.readfile("sdf", "data.sdf"):
smiles = mol.write("smi").strip()
print(smiles)
不过要注意,Open Babel 的 Python 接口在 Windows 上安装时容易出问题。我曾在 Windows 上折腾了半天,最后老老实实切到 Linux 下用命令行。
避坑指南:千万不要在 Open Babel Python 接口里对大量分子做复杂计算。它慢,而且内存管理不好。我有个同事曾经拿它处理 10 万条 SMILES。结果你猜怎么着?跑了三天,最后内存爆了。改用 RDKit 后,半小时搞定。
3.3 工具对比:什么时候选哪个?
这两个工具各有侧重。我用一个表格总结下:
| 特性 | RDKit | Open Babel |
|---|---|---|
| 核心功能 | 分子操作与计算 | 格式转换与导入导出 |
| 性能 | 快(C++ 底层) | 中速(命令行快) |
| Python 接口 | 非常友好 | 基础可用,有坑 |
| 支持格式 | 主要化学格式 | 110+ 种格式 |
| 典型场景 | 分子指纹、性质计算、子结构搜索 | 文件格式互转、批量格式转换 |
我个人习惯是:处理数据用 RDKit,互转格式用 Open Babel。当然,如果你只需要其中一个功能,选哪个都行。
3.4 实战案例:用 RDKit 批量处理 SMILES
最后来一个完整的实战案例。假设你有一个 CSV 文件,里面有一列“smiles”,你需要:
- 读取每条 SMILES;
- 计算分子量和 LogP;
- 过滤掉分子量 > 500 或 LogP > 5 的分子;
- 输出结果到新 CSV。
用 RDKit 实现:
import csv
from rdkit import Chem
from rdkit.Chem import Descriptors
input_file = "input.csv"
output_file = "filtered.csv"
with open(input_file, "r") as infile, open(output_file, "w", newline="") as outfile:
reader = csv.DictReader(infile)
fieldnames = reader.fieldnames + ["MolWt", "LogP"]
writer = csv.DictWriter(outfile, fieldnames=fieldnames)
writer.writeheader()
for row in reader:
smi = row["smiles"]
mol = Chem.MolFromSmiles(smi)
if mol is None:
continue # 跳过无效 SMILES
mw = Descriptors.MolWt(mol)
logp = Descriptors.MolLogP(mol)
if mw <= 500 and logp <= 5:
row["MolWt"] = f"{mw:.2f}"
row["LogP"] = f"{logp:.2f}"
writer.writerow(row)
这段代码我实际项目里跑过。当时有 5 万条 SMILES,过滤后剩下 3000 多条,速度很快。需要注意的是:MolLogP 是预测值,如果你要严格标准,可以考虑用更精确的 LogP 计算方法。
经验之谈:处理大批量 SMILES 时,记得用 Chem.SanitizeMol(mol) 先清理一下分子。不清理的话,有些 SMILES 虽然能读进去,但原子价态不对,后续计算会出莫名其妙的结果。我曾经因为这个查了一下午 bug。
嗯,以上就是 Python 化学信息学工具链的核心内容。记住:工具是死的,用的人才是关键。别贪多,把 RDKit 玩熟了,应付大多数 SMILES 任务绰绰有余。遇到格式问题,再用 Open Babel 补刀。下次看到 SMILES 别害怕,直接拿它们开刀就对了。