mcpField
D
datamol-cheminformatics

datamol-cheminformatics

github.com/jaechang-hits数据与数据库38473 次安装6 天前更新
代码仓库

关于 datamol-cheminformatics

datamol-cheminformatics 是一项使用 Datamol 进行化学信息学和药物发现的技能。它以 Python 接口简化常见分子分析,同时保留与 RDKit 原生分子对象的兼容性。

主要功能

  1. 01解析并标准化分子结构
  2. 02计算描述符和指纹
  3. 03聚类化合物并筛选多样分子
  4. 04提取骨架并进行分子片段化
  5. 05生成 3D 构象
  6. 06读写分子数据文件

适用场景

  1. 01验证并清理 SMILES 或化合物文件
  2. 02为机器学习准备分子特征
  3. 03比较并聚类化合物库
  4. 04生成构象用于分子分析

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/jaechang-hits/sciagent-skills --skill datamol-cheminformatics

安装后在 Claude Code 中输入/datamol-cheminformatics确认已加载。

详细介绍

Datamol 化学信息学工具包

概述

Datamol 为 RDKit 提供轻量级、符合 Python 风格的抽象层,用于分子化学信息学。它简化了常见的药物发现操作——SMILES 解析、标准化、描述符、指纹、聚类、骨架、构象生成和可视化,并提供合理的默认设置、内置并行处理,以及通过 fsspec 支持云存储。所有分子对象都是原生的 rdkit.Chem.Mol 实例,确保与 RDKit 完全兼容。

适用场景

  • 从 SMILES、SDF 或其他格式解析、验证和标准化分子结构
  • 计算分子描述符和指纹,用于机器学习特征工程
  • 在化合物库中进行相似性搜索和多样性筛选
  • 按结构相似性对化合物进行聚类(Butina 聚类)
  • 进行骨架分析,以及基于骨架划分机器学习训练集和测试集
  • 使用 BRICS/RECAP 进行分子片段化,以支持基于片段的设计
  • 生成和分析 3D 构象
  • 将分子可视化为网格,并进行对齐和高亮显示
  • 并行处理分子数据集
  • 如需快速查询基因,请改用 gget;如需高级子结构查询或自定义指纹,请直接使用 RDKit

先决条件

uv pip install datamol
import datamol as dm
import numpy as np
import pandas as pd

快速开始

import datamol as dm

# Parse and standardize
mol = dm.to_mol("CC(=O)Oc1ccccc1C(=O)O")  # Aspirin
mol = dm.standardize_mol(mol)
print(dm.to_smiles(mol))  # Canonical SMILES

# Compute descriptors
desc = dm.descriptors.compute_many_descriptors(mol)
print(f"MW: {desc['mw']:.1f}, LogP: {desc['logp']:.2f}, TPSA: {desc['tpsa']:.1f}")

# Generate fingerprint
fp = dm.to_fp(mol, fp_type='ecfp', radius=2, n_bits=2048)
print(f"Fingerprint shape: {fp.shape}")  # (2048,)

核心 API

1. 分子输入/输出与标准化

解析分子:

import datamol as dm

# From SMILES (returns None on failure)
mol = dm.to_mol("CCO")
if mol is None:
    print("Invalid SMILES")

# Format conversions
smiles = dm.to_smiles(mol, isomeric=True)  # Canonical SMILES
inchi = dm.to_inchi(mol)
inchikey = dm.to_inchikey(mol)
selfies = dm.to_selfies(mol)

标准化(强烈建议用于外部数据):

mol = dm.standardize_mol(
    mol,
    disconnect_metals=True,
    normalize=True,
    reionize=True
)
clean_smiles = dm.standardize_smiles("C(C)O")  # From SMILES directly

文件输入/输出:

# Reading (supports local, S3, GCS, HTTP via fsspec)
df = dm.read_sdf("compounds.sdf", mol_column='mol')
df = dm.read_csv("data.csv", smiles_column="SMILES", mol_column="mol")
df = dm.read_excel("compounds.xlsx", sheet_name=0, mol_column="mol")
df = dm.open_df("file.sdf")  # Auto-detect format

# Writing
dm.to_sdf(df, "output.sdf", mol_column="mol")
dm.to_smi(mols, "output.smi")
dm.to_xlsx(df, "output.xlsx", mol_columns=["mol"])  # Renders molecule images

# Remote files
df = dm.read_sdf("s3://bucket/compounds.sdf")
dm.to_sdf(mols, "s3://bucket/output.sdf")
2. 描述符与属性
import datamol as dm

mol = dm.to_mol("c1ccc(cc1)CCN")

# Standard descriptor set (single molecule)
desc = dm.descriptors.compute_many_descriptors(mol)
# Returns dict: {'mw': 121.18, 'logp': 1.41, 'hbd': 1, 'hba': 1,
#                'tpsa': 26.02, 'n_aromatic_atoms': 6, ...}

# Batch computation (parallel)
mols = [dm.to_mol(s) for s in ["CCO", "c1ccccc1", "CC(=O)O"]]
desc_df = dm.descriptors.batch_compute_many_descriptors(
    mols, n_jobs=-1, progress=True
)
print(desc_df.head())

# Specific descriptors
n_stereo = dm.descriptors.n_stereo_centers(mol)
n_aromatic = dm.descriptors.n_aromatic_atoms(mol)
aromatic_ratio = dm.descriptors.n_aromatic_atoms_proportion(mol)
n_rigid = dm.descriptors.n_rigid_bonds(mol)

类药性筛选(Lipinski 五法则):

def is_druglike(mol):
    desc = dm.descriptors.compute_many_descriptors(mol)
    return (desc['mw'] <= 500 and desc['logp'] <= 5
            and desc['hbd'] <= 5 and desc['hba'] <= 10)

druglike = [m for m in mols if is_druglike(m)]
print(f"Drug-like: {len(druglike)}/{len(mols)}")
3. 指纹与相似性
import datamol as dm

mol = dm.to_mol("c1ccc(cc1)CCN")

# Fingerprint types
fp_ecfp = dm.to_fp(mol, fp_type='ecfp', radius=2, n_bits=2048)  # Morgan/ECFP
fp_maccs = dm.to_fp(mol, fp_type='maccs')    # MACCS keys (167 bits)
fp_topo = dm.to_fp(mol, fp_type='topological')  # Topological
fp_ap = dm.to_fp(mol, fp_type='atompair')    # Atom pairs

# Pairwise distances (Tanimoto distance = 1 - similarity)
mols = [dm.to_mol(s) for s in ["CCO", "CCCO", "c1ccccc1"]]
dist_matrix = dm.pdist(mols, n_jobs=-1)
print(f"Distance vector shape: {dist_matrix.shape}")

# Distances between two sets
query = [dm.to_mol("CCO")]
library = [dm.to_mol(s) for s in ["CCCO", "c1ccccc1", "CC(=O)O"]]
distances = dm.cdist(query, library, n_jobs=-1)
print(f"Query-library distances: {distances.shape}")
4. 聚类与多样性筛选
import datamol as dm

mols = [dm.to_mol(s) for s in smiles_list]  # Assume smiles_list defined

# Butina clustering (suitable for ~1000 molecules, builds full distance matrix)
clusters = dm.cluster_mols(mols, cutoff=0.2, n_jobs=-1)
for i, cluster in enumerate(clusters[:5]):
    print(f"Cluster {i}: {len(cluster)} molecules")

# Diversity selection (works for larger libraries)
diverse_mols = dm.pick_diverse(mols, npick=100)
print(f"Selected {len(diverse_mols)} diverse molecules")

# Cluster centroids
centroids = dm.pick_centroids(mols, npick=50)
print(f"Selected {len(centroids)} centroids")
5. 骨架与片段

Murcko 骨架提取:

import datamol as dm
from collections import Counter

mol = dm.to_mol("c1ccc(cc1)CCN")
scaffold = dm.to_scaffold_murcko(mol)
print(f"Scaffold: {dm.to_smiles(scaffold)}")

# Scaffold frequency analysis
scaffolds = [dm.to_scaffold_murcko(m) for m in mols]
scaffold_smiles = [dm.to_smiles(s) for s in scaffolds]
counts = Counter(scaffold_smiles)
print(f"Top scaffolds: {counts.most_common(5)}")

# Scaffold-based train/test split (for ML)
scaffold_to_mols = {}
for mol, scaf in zip(mols, scaffold_smiles):
    scaffold_to_mols.setdefault(scaf, []).append(mol)
scaffolds_list = list(scaffold_to_mols.keys())
split_idx = int(0.8 * len(scaffolds_list))
train_mols = [m for s in scaffolds_list[:split_idx] for m in scaffold_to_mols[s]]
test_mols = [m for s in scaffolds_list[split_idx:] for m in scaffold_to_mols[s]]

片段化:

mol = dm.to_mol("CC(=O)Oc1ccccc1C(=O)O")  # Aspirin

# BRICS (16 bond types, retrosynthetic)
brics_frags = dm.fragment.brics(mol)
print(f"BRICS fragments: {brics_frags}")  # Set of fragment SMILES with [1*] attachment points

# RECAP (11 bond types, combinatorial)
recap_frags = dm.fragment.recap(mol)

# MMPA (matched molecular pair analysis)
mmpa_frags = dm.fragment.mmpa_frag(mol)
6. 3D 构象
import datamol as dm

mol = dm.to_mol("c1ccc(cc1)CCN")

# Generate conformers
mol_3d = dm.conformers.generate(
    mol,
    n_confs=50,           # Number to generate
    rms_cutoff=0.5,       # Filter similar (Angstroms)
    minimize_energy=True,  # UFF minimization
    method='ETKDGv3'      # Embedding method
)
print(f"Generated {mol_3d.GetNumConformers()} conformers")

# Access coordinates
conf = mol_3d.GetConformer(0)
positions = conf.GetPositions()  # Nx3 array
print(f"Atom positions shape: {positions.shape}")

# Cluster conformers by RMSD
clusters = dm.conformers.cluster(mol_3d, rms_cutoff=1.0)
centroids = dm.conformers.return_centroids(mol_3d, clusters)

# Solvent accessible surface area
sasa = dm.conformers.sasa(mol_3d, n_jobs=-1)
print(f"SASA values: {sasa[:3]}")

关键概念

Datamol 与 RDKit 选择指南
使用 Datamol 的场景……直接使用 RDKit 的场景……
标准 SMILES ↔ Mol 转换自定义指纹定义
并行处理批量数据底层原子/键操作
快速计算描述符子结构查询优化
文件输入/输出(SDF、CSV、Excel、云端)大规模反应枚举
聚类与多样性筛选自定义力场参数
骨架分析高级立体化学处理
关键数据类型
  • 所有分子都是原生的 rdkit.Chem.Mol 对象,可与 RDKit 函数完全兼容
  • 指纹是 numpy 数组(稠密位向量)
  • DataFrame 使用 pandas,其中 mol 列包含 Mol 对象
  • 距离矩阵使用 Tanimoto 距离(0 = 完全相同,1 = 完全不同)
并行处理

支持 n_jobs 参数的函数:dm.read_sdf、dm.descriptors.batch_compute_many_descriptors、dm.cluster_mols、dm.pdist、dm.cdist、dm.conformers.sasa。使用 n_jobs=-1 可利用所有核心,使用 progress=True 可显示进度条。

常见工作流

1. 药物发现流程:加载 → 筛选 → 聚类 → 可视化
import datamol as dm

# 1. Load and standardize
df = dm.read_sdf("compounds.sdf")
df['mol'] = df['mol'].apply(lambda m: dm.standardize_mol(m) if m else None)
df = df[df['mol'].notna()]
print(f"Loaded {len(df)} valid molecules")

# 2. Compute descriptors and filter by drug-likeness
desc_df = dm.descriptors.batch_compute_many_descriptors(
    df['mol'].tolist(), n_jobs=-1, progress=True
)
druglike = (desc_df['mw'] <= 500) & (desc_df['logp'] <= 5) & (desc_df['hbd'] <= 5) & (desc_df['hba'] <= 10)
filtered_df = df[druglike.values].reset_index(drop=True)
print(f"Drug-like compounds: {len(filtered_df)}")

# 3. Select diverse subset
diverse = dm.pick_diverse(filtered_df['mol'].tolist(), npick=100)

# 4. Visualize
dm.viz.to_image(diverse[:20], legends=[dm.to_smiles(m) for m in diverse[:20]],
                n_cols=5, mol_size=(300, 300), outfile="diverse_hits.png")
2. 虚拟筛选:查询 → 相似性计算 → 排序
import datamol as dm
import numpy as np

# Query actives and screening library
actives = [dm.to_mol(s) for s in active_smiles]  # Known actives
library = [dm.to_mol(s) for s in library_smiles]  # Screening library

# Calculate distances (Tanimoto)
distances = dm.cdist(actives, library, n_jobs=-1)
min_distances = distances.min(axis=0)  # Best match to any active
similarities = 1 - min_distances

# Rank and select top hits
top_idx = np.argsort(similarities)[::-1][:100]
top_hits = [library[i] for i in top_idx]
top_scores = [similarities[i] for i in top_idx]
print(f"Top hit similarity: {top_scores[0]:.3f}")

# Visualize top hits
dm.viz.to_image(top_hits[:20],
    legends=[f"Sim: {s:.3f}" for s in top_scores[:20]],
    outfile="screening_hits.png")
3. SAR 分析:按骨架分组 → 比较活性
import datamol as dm

# Group compounds by scaffold
scaffolds = [dm.to_scaffold_murcko(m) for m in mols]
scaffold_smiles = [dm.to_smiles(s) for s in scaffolds]

sar_df = pd.DataFrame({
    'mol': mols, 'scaffold': scaffold_smiles, 'activity': activities
})

# Analyze each scaffold series
for scaffold, group in sar_df.groupby('scaffold'):
    if len(group) >= 3:
        print(f"Scaffold: {scaffold} | N={len(group)} | "
              f"Activity: {group['activity'].min():.2f}–{group['activity'].max():.2f}")
        dm.viz.to_image(group['mol'].tolist(), align=True,
            legends=[f"Act: {a:.2f}" for a in group['activity']])

关键参数

函数参数默认值说明
dm.to_fpfp_type'ecfp'指纹类型:ecfp、maccs、topological、atompair
dm.to_fpradius2Morgan 半径(仅适用于 ecfp);radius=2 ≈ ECFP4
dm.to_fpn_bits2048指纹长度(ecfp、topological)
dm.cluster_molscutoff0.2Tanimoto 距离阈值(0=相同,1=不同)
dm.pick_diversenpickrequired要选择的多样化分子数量
dm.conformers.generaten_confsNone构象数量(None = 自动)
dm.conformers.generaterms_cutoffNoneRMSD 筛选阈值(埃)
dm.conformers.generatemethod'ETKDGv3'嵌入方法:ETKDGv3、ETKDGv2、ETKDG
dm.standardize_moldisconnect_metalsFalse移除金属-配体键
dm.read_sdfsanitizeTrue对分子进行清理
dm.read_sdfremove_hsTrue移除显式氢原子
dm.viz.to_imagealignFalse按 MCS 对齐分子
dm.viz.to_imageuse_svgFalse输出 SVG(True)或 PNG(False)

最佳实践

  1. 始终标准化来自外部来源的分子 — 在任何分析之前,调用 dm.standardize_mol() 并设置 disconnect_metals=True, normalize=True, reionize=True。同一分子的不同 SMILES 表示会产生不同的指纹
  2. 解析后检查是否为 None — 对于无效的 SMILES,dm.to_mol() 会返回 None。在批量操作前过滤这些值,以避免崩溃
  3. 对数据集使用并行处理 — 将 n_jobs=-1, progress=True 传递给批量操作。对 10,000 个以上的分子进行顺序处理会不必要地拖慢速度
  4. 根据用途选择指纹 — ECFP(Morgan):适用于通用结构相似性;MACCS:速度快、空间较小;Atom pairs:对距离敏感。radius=2、n_bits=2048 的 ECFP 是最常见的默认设置
  5. 注意聚类规模限制 — Butina 聚类(dm.cluster_mols)会构建完整的距离矩阵,适用于 ≤~1,000 个分子。对于更大的集合,请使用 dm.pick_diverse() 或层次聚类方法
  6. 机器学习使用骨架拆分 — 随机拆分会导致相似结构泄漏到训练集和测试集中。分子性质预测模型应始终使用基于骨架的拆分
  7. 利用 fsspec 处理云端数据 — 所有 I/O 函数都直接接受 S3、GCS 和 HTTP 路径。安装 s3fs 或 gcsfs 即可支持云端数据

常见配方

配方:批量验证和标准化 SMILES

适用场景:在后续分析之前清理一组 SMILES 字符串。

import datamol as dm

smiles_list = ["CC(=O)Oc1ccccc1C(=O)O", "c1ccccc1", "invalid_smiles", "CC(N)C(=O)O"]
mols = [dm.to_mol(s) for s in smiles_list]
valid = [(s, m) for s, m in zip(smiles_list, mols) if m is not None]
standardized = [(s, dm.standardize_mol(m)) for s, m in valid]
print(f"Valid: {len(valid)}/{len(smiles_list)}")
for orig, mol in standardized:
    print(f"  {orig} → {dm.to_smiles(mol)}")
配方:成对相似度矩阵

适用场景:比较一小组化合物之间的相似度,或与参考库进行比较。

import datamol as dm
import numpy as np

smiles = ["CC(=O)Oc1ccccc1C(=O)O", "c1ccc(cc1)C(=O)O", "CC(N)C(=O)O", "c1ccccc1"]
mols = [dm.to_mol(s) for s in smiles]
fps = [dm.to_fp(m) for m in mols]

# Pairwise Tanimoto similarity
n = len(fps)
sim_matrix = np.zeros((n, n))
for i in range(n):
    for j in range(n):
        sim_matrix[i, j] = dm.similarity.tanimoto(fps[i], fps[j])
print(f"Similarity matrix shape: {sim_matrix.shape}")
print(f"Most similar pair: {np.unravel_index(np.argsort(sim_matrix.ravel())[-3], (n, n))}")

故障排查

问题原因解决方案
dm.to_mol() 返回 NoneSMILES 无效或非规范先尝试 dm.standardize_smiles();检查是否存在 Kekulé 化问题
聚类时出现 MemoryError大型数据集需要完整距离矩阵对于超过 1000 个分子,请使用 dm.pick_diverse(),而非 dm.cluster_mols
构象生成缓慢构象数量过多或分子过大减少 n_confs,增大 rms_cutoff,或限制分子大小
远程文件访问失败缺少 fsspec 后端安装 s3fs(AWS)、gcsfs(GCP)或 adlfs(Azure)
描述符计算失败分子没有构象先进行标准化;某些 3D 描述符需要调用 dm.conformers.generate()
dm.to_xlsx 缺少图像未安装 openpyxluv pip install openpyxl
指纹不一致同一分子使用了不同的 SMILES计算指纹前先对所有分子进行标准化
骨架提取返回完整分子分子中没有环系Murcko 骨架至少需要一个环;无环分子会返回其自身
反应产物为 None反应物与 SMARTS 模式不匹配确认反应物与反应模板匹配;检查原子映射
导入 dm.viz 时出错缺少可视化依赖项uv pip install Pillow cairosvg

相关技能

  • rdkit-cheminformatics — 提供完整的 RDKit API,用于执行 datamol 简化接口未涵盖的高级操作
  • pubchem-compound-search — 按名称、CID 或结构从 PubChem 获取化合物数据
  • scikit-learn-machine-learning — 使用 datamol 生成的特征训练 ML 模型
  • matplotlib-scientific-plotting — 自定义适合发表的分子属性图

参考资料

评论

支持 Markdown