化学信息学入门:分子指纹、描述符与相似性
FreeGuideOnline
最新
2026-06-20
python from rdkit import Chem from rdkit.Chem import AllChem
mol = Chem.MolFromSmiles('c1ccccc1C(=O)O') # 苯甲酸 fp = AllChem.GetMorganFingerprintAsBitVect(mol, radius=2, nBits=2048)
`nBits`参数控制指纹长度,如果原始生成的位置超过位数限制,会自动执行“折叠”(fold)压缩,即通过取模运算将多个位压缩到一起。较大的`nBits`减少碰撞,但占用更多存储;常见选择是1024或2048位。
### 分子相似性:从比特串到化学空间距离
一旦分子被表示为描述符向量或比特指纹,就可以用数学距离或相似度指标来量化它们之间的“化学距离”。相似性概念是虚拟筛选、数据库聚类、多样性选择的基石。
#### 主要相似性度量
- **Tanimoto系数(Jaccard指数)**:用于比较两个二进制指纹。定义为共同为1的位数除以至少一个为1的位数。取值0到1,1表示完全相同。它是最通用的分子指纹相似性度量。
T(A,B) = |A∩B| / |A∪B|
- **Dice系数**:给予重合位更高权重,等于 2×|A∩B| / (|A|+|B|)。与Tanimoto类似但倾向于更高分。
- **Cosine相似性**:常用于实数描述符向量,计算两者夹角的余弦值。适用于描述符空间中的相似性比较。
- **欧几里得距离**:描述符空间中两点直线距离,越小越相似。通常需要标准化描述符以避免量纲影响。
在指纹筛选场景中,通常直接使用Tanimoto系数与预设阈值(如0.7或0.8)来判断两个分子是否“类似”。
#### 基于描述符的相似性
对于描述符向量(如3个描述符组成的向量[MW, logP, TPSA]),可以先标准化(使各维度均值为0,标准差为1),再计算欧氏距离或马氏距离。也可使用主成分分析(PCA)降维后可视化化合物的分布。
#### 应用场景
- **相似性搜索**:给定一个活性化合物(查询分子),在数据库中找出Tanimoto系数大于0.8的所有分子,作为新的候选。这依赖于“相似性性质原理”——结构相似的分子倾向于具有相似的生物活性。
- **虚拟筛选**:利用指纹快速扫描大型化合物库,替代分子对接等昂贵计算的前置过滤。
- **分子聚类**:基于指纹距离矩阵对分子进行层次聚类或k-Means聚类,识别化学系列,便于后续选择代表性分子进行实验。
- **多样性分析**:评估化合物库的覆盖范围,选择去重后多样性最大的子集,避免重复购买或合成。
### 实践工具与入门示例
开源化学信息学工具让上述概念落地。以下是三个最主流的选择:
- **RDKit**:Python生态下最活跃的化学信息学库,提供分子处理、描述符计算、多种指纹生成、相似性计算。文档丰富,社区庞大。
- **CDK(Chemistry Development Kit)**:Java库,也有Python接口。提供大量描述符和指纹,适合需要与Java集成的环境。
- **Open Babel**:通用化学文件格式转换工具,支持命令行和Python绑定,可计算描述符和指纹,支持3D坐标生成。
#### 快速上手:基于RDKit的相似性筛选
假设你有一个参考分子,想要从本地化合物库中找出类似物:
1. 安装RDKit:`pip install rdkit-pypi`
2. 准备一个SMILES格式的化合物库文件 `library.smi`,每行一个SMILES。
3. 运行以下Python脚本片段:
```python
from rdkit import Chem, DataStructs
from rdkit.Chem import AllChem, Draw
# 查询分子(苯甲酸)
query_mol = Chem.MolFromSmiles('O=C(O)c1ccccc1')
query_fp = AllChem.GetMorganFingerprintAsBitVect(query_mol, 2, nBits=2048)
# 读取库并计算指纹
library = [line.strip() for line in open('library.smi')]
mol_suppl = [Chem.MolFromSmiles(s) for s in library if s]
fps = [AllChem.GetMorganFingerprintAsBitVect(m, 2, nBits=2048) for m in mol_suppl]
# 计算Tanimoto相似性并保留高于0.6的分子
hits = []
for i, fp in enumerate(fps):
sim = DataStructs.TanimotoSimilarity(query_fp, fp)
if sim >= 0.6:
hits.append((sim, library[i]))
# 按相似性降序打印
hits.sort(reverse=True)
for sim, smi in hits[:10]:
print(f"{sim:.3f} {smi}")