mcpField
D
datamol

datamol

github.com/crazymsn数据与数据库2335 次安装22 周前更新
代码仓库

关于 datamol

Datamol 是面向 Python 的化学信息学库,为 RDKit 提供更高层接口,同时保留原生 RDKit 分子对象。此技能适合处理分子数据的研究人员和开发者,涵盖文件读写、描述符计算、结构分析及 3D 构象。

主要功能

  1. 01转换并标准化分子结构
  2. 02读写分子数据文件
  3. 03计算描述符和指纹
  4. 04聚类分子并筛选多样子集
  5. 05生成并分析 3D 构象
  6. 06并行执行批量操作

适用场景

  1. 01整理化合物库以供分析
  2. 02通过指纹比较分子结构
  3. 03按骨架对化合物分组
  4. 04为分子研究生成构象

安装

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

$npx skills add https://github.com/crazymsn/academic-skills --skill datamol

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

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
conformers_module.md
core_api.md
descriptors_viz.md
fragments_scaffolds.md
io_module.md
reactions_data.md

详细介绍

Datamol 化学信息学技能

概述

Datamol 是一个 Python 库,为 RDKit 提供轻量、符合 Python 风格的分子化学信息学抽象层。通过合理的默认设置、高效的并行处理和现代化的 I/O 功能,简化复杂的分子操作。所有分子对象都是原生的 rdkit.Chem.Mol 实例,可确保与 RDKit 生态系统完全兼容。

主要功能:

  • 分子格式转换(SMILES、SELFIES、InChI)
  • 结构标准化和清理
  • 分子描述符和指纹
  • 3D 构象生成与分析
  • 聚类和多样性选择
  • 骨架和片段分析
  • 化学反应应用
  • 可视化和对齐
  • 支持并行处理的批量处理
  • 通过 fsspec 支持云存储

安装和设置

指导用户安装 datamol:

uv pip install datamol

导入约定:

import datamol as dm

核心工作流

1. 分子基本操作

从 SMILES 创建分子:

import datamol as dm

# Single molecule
mol = dm.to_mol("CCO")  # Ethanol

# From list of SMILES
smiles_list = ["CCO", "c1ccccc1", "CC(=O)O"]
mols = [dm.to_mol(smi) for smi in smiles_list]

# Error handling
mol = dm.to_mol("invalid_smiles")  # Returns None
if mol is None:
    print("Failed to parse SMILES")

将分子转换为 SMILES:

# Canonical SMILES
smiles = dm.to_smiles(mol)

# Isomeric SMILES (includes stereochemistry)
smiles = dm.to_smiles(mol, isomeric=True)

# Other formats
inchi = dm.to_inchi(mol)
inchikey = dm.to_inchikey(mol)
selfies = dm.to_selfies(mol)

标准化和清理(始终建议用于用户提供的分子):

# Sanitize molecule
mol = dm.sanitize_mol(mol)

# Full standardization (recommended for datasets)
mol = dm.standardize_mol(
    mol,
    disconnect_metals=True,
    normalize=True,
    reionize=True
)

# For SMILES strings directly
clean_smiles = dm.standardize_smiles(smiles)
2. 读取和写入分子文件

完整的 I/O 文档请参阅 references/io_module.md。

读取文件:

# SDF files (most common in chemistry)
df = dm.read_sdf("compounds.sdf", mol_column='mol')

# SMILES files
df = dm.read_smi("molecules.smi", smiles_column='smiles', mol_column='mol')

# CSV with SMILES column
df = dm.read_csv("data.csv", smiles_column="SMILES", mol_column="mol")

# Excel files
df = dm.read_excel("compounds.xlsx", sheet_name=0, mol_column="mol")

# Universal reader (auto-detects format)
df = dm.open_df("file.sdf")  # Works with .sdf, .csv, .xlsx, .parquet, .json

写入文件:

# Save as SDF
dm.to_sdf(mols, "output.sdf")
# Or from DataFrame
dm.to_sdf(df, "output.sdf", mol_column="mol")

# Save as SMILES file
dm.to_smi(mols, "output.smi")

# Excel with rendered molecule images
dm.to_xlsx(df, "output.xlsx", mol_columns=["mol"])

远程文件支持(S3、GCS、HTTP):

# Read from cloud storage
df = dm.read_sdf("s3://bucket/compounds.sdf")
df = dm.read_csv("https://example.com/data.csv")

# Write to cloud storage
dm.to_sdf(mols, "s3://bucket/output.sdf")
3. 分子描述符和属性

详细的描述符文档请参阅 references/descriptors_viz.md。

计算单个分子的描述符:

# Get standard descriptor set
descriptors = dm.descriptors.compute_many_descriptors(mol)
# Returns: {'mw': 46.07, 'logp': -0.03, 'hbd': 1, 'hba': 1,
#           'tpsa': 20.23, 'n_aromatic_atoms': 0, ...}

批量计算描述符(推荐用于数据集):

# Compute for all molecules in parallel
desc_df = dm.descriptors.batch_compute_many_descriptors(
    mols,
    n_jobs=-1,      # Use all CPU cores
    progress=True   # Show progress bar
)

特定描述符:

# Aromaticity
n_aromatic = dm.descriptors.n_aromatic_atoms(mol)
aromatic_ratio = dm.descriptors.n_aromatic_atoms_proportion(mol)

# Stereochemistry
n_stereo = dm.descriptors.n_stereo_centers(mol)
n_unspec = dm.descriptors.n_stereo_centers_unspecified(mol)

# Flexibility
n_rigid = dm.descriptors.n_rigid_bonds(mol)

药物相似性筛选(Lipinski 五法则):

# Filter compounds
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_mols = [mol for mol in mols if is_druglike(mol)]
4. 分子指纹和相似性

生成指纹:

# ECFP (Extended Connectivity Fingerprint, default)
fp = dm.to_fp(mol, fp_type='ecfp', radius=2, n_bits=2048)

# Other fingerprint types
fp_maccs = dm.to_fp(mol, fp_type='maccs')
fp_topological = dm.to_fp(mol, fp_type='topological')
fp_atompair = dm.to_fp(mol, fp_type='atompair')

相似性计算:

# Pairwise distances within a set
distance_matrix = dm.pdist(mols, n_jobs=-1)

# Distances between two sets
distances = dm.cdist(query_mols, library_mols, n_jobs=-1)

# Find most similar molecules
from scipy.spatial.distance import squareform
dist_matrix = squareform(dm.pdist(mols))
# Lower distance = higher similarity (Tanimoto distance = 1 - Tanimoto similarity)
5. 聚类和多样性选择

聚类详情请参阅 references/core_api.md。

Butina 聚类:

# Cluster molecules by structural similarity
clusters = dm.cluster_mols(
    mols,
    cutoff=0.2,    # Tanimoto distance threshold (0=identical, 1=completely different)
    n_jobs=-1      # Parallel processing
)

# Each cluster is a list of molecule indices
for i, cluster in enumerate(clusters):
    print(f"Cluster {i}: {len(cluster)} molecules")
    cluster_mols = [mols[idx] for idx in cluster]

重要提示:Butina 聚类会构建完整的距离矩阵,适用于约 1000 个分子,不适用于 10,000 个以上的分子。

多样性选择:

# Pick diverse subset
diverse_mols = dm.pick_diverse(
    mols,
    npick=100  # Select 100 diverse molecules
)

# Pick cluster centroids
centroids = dm.pick_centroids(
    mols,
    npick=50   # Select 50 representative molecules
)
6. 骨架分析

完整的骨架文档请参阅 references/fragments_scaffolds.md。

提取 Murcko 骨架:

# Get Bemis-Murcko scaffold (core structure)
scaffold = dm.to_scaffold_murcko(mol)
scaffold_smiles = dm.to_smiles(scaffold)

基于骨架的分析:

# Group compounds by scaffold
from collections import Counter

scaffolds = [dm.to_scaffold_murcko(mol) for mol in mols]
scaffold_smiles = [dm.to_smiles(s) for s in scaffolds]

# Count scaffold frequency
scaffold_counts = Counter(scaffold_smiles)
most_common = scaffold_counts.most_common(10)

# Create scaffold-to-molecules mapping
scaffold_groups = {}
for mol, scaf_smi in zip(mols, scaffold_smiles):
    if scaf_smi not in scaffold_groups:
        scaffold_groups[scaf_smi] = []
    scaffold_groups[scaf_smi].append(mol)

基于骨架划分训练集和测试集(用于机器学习):

# Ensure train and test sets have different scaffolds
scaffold_to_mols = {}
for mol, scaf in zip(mols, scaffold_smiles):
    if scaf not in scaffold_to_mols:
        scaffold_to_mols[scaf] = []
    scaffold_to_mols[scaf].append(mol)

# Split scaffolds into train/test
import random
scaffolds = list(scaffold_to_mols.keys())
random.shuffle(scaffolds)
split_idx = int(0.8 * len(scaffolds))
train_scaffolds = scaffolds[:split_idx]
test_scaffolds = scaffolds[split_idx:]

# Get molecules for each split
train_mols = [mol for scaf in train_scaffolds for mol in scaffold_to_mols[scaf]]
test_mols = [mol for scaf in test_scaffolds for mol in scaffold_to_mols[scaf]]
7. 分子片段化

片段化详情请参阅 references/fragments_scaffolds.md。

BRICS 片段化(16 种键类型):

# Fragment molecule
fragments = dm.fragment.brics(mol)
# Returns: set of fragment SMILES with attachment points like '[1*]CCN'

RECAP 片段化(11 种键类型):

fragments = dm.fragment.recap(mol)

片段分析:

# Find common fragments across compound library
from collections import Counter

all_fragments = []
for mol in mols:
    frags = dm.fragment.brics(mol)
    all_fragments.extend(frags)

fragment_counts = Counter(all_fragments)
common_frags = fragment_counts.most_common(20)

# Fragment-based scoring
def fragment_score(mol, reference_fragments):
    mol_frags = dm.fragment.brics(mol)
    overlap = mol_frags.intersection(reference_fragments)
    return len(overlap) / len(mol_frags) if mol_frags else 0
8. 3D 构象生成

详细的构象文档请参阅 references/conformers_module.md。

生成构象:

# Generate 3D conformers
mol_3d = dm.conformers.generate(
    mol,
    n_confs=50,           # Number to generate (auto if None)
    rms_cutoff=0.5,       # Filter similar conformers (Ångströms)
    minimize_energy=True,  # Minimize with UFF force field
    method='ETKDGv3'      # Embedding method (recommended)
)

# Access conformers
n_conformers = mol_3d.GetNumConformers()
conf = mol_3d.GetConformer(0)  # Get first conformer
positions = conf.GetPositions()  # Nx3 array of atom coordinates

构象聚类:

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

# Get representative conformers
centroids = dm.conformers.return_centroids(mol_3d, clusters)

SASA 计算:

# Calculate solvent accessible surface area
sasa_values = dm.conformers.sasa(mol_3d, n_jobs=-1)

# Access SASA from conformer properties
conf = mol_3d.GetConformer(0)
sasa = conf.GetDoubleProp('rdkit_free_sasa')
9. 可视化

可视化文档请参阅 references/descriptors_viz.md。

基本分子网格:

# Visualize molecules
dm.viz.to_image(
    mols[:20],
    legends=[dm.to_smiles(m) for m in mols[:20]],
    n_cols=5,
    mol_size=(300, 300)
)

# Save to file
dm.viz.to_image(mols, outfile="molecules.png")

# SVG for publications
dm.viz.to_image(mols, outfile="molecules.svg", use_svg=True)

对齐可视化(用于 SAR 分析):

# Align molecules by common substructure
dm.viz.to_image(
    similar_mols,
    align=True,  # Enable MCS alignment
    legends=activity_labels,
    n_cols=4
)

高亮子结构:

# Highlight specific atoms and bonds
dm.viz.to_image(
    mol,
    highlight_atom=[0, 1, 2, 3],  # Atom indices
    highlight_bond=[0, 1, 2]      # Bond indices
)

构象可视化:

# Display multiple conformers
dm.viz.conformers(
    mol_3d,
    n_confs=10,
    align_conf=True,
    n_cols=3
)
10. 化学反应

反应文档请参阅 references/reactions_data.md。

应用反应:

from rdkit.Chem import rdChemReactions

# Define reaction from SMARTS
rxn_smarts = '[C:1](=[O:2])[OH:3]>>[C:1](=[O:2])[Cl:3]'
rxn = rdChemReactions.ReactionFromSmarts(rxn_smarts)

# Apply to molecule
reactant = dm.to_mol("CC(=O)O")  # Acetic acid
product = dm.reactions.apply_reaction(
    rxn,
    (reactant,),
    sanitize=True
)

# Convert to SMILES
product_smiles = dm.to_smiles(product)

批量应用反应:

# Apply reaction to library
products = []
for mol in reactant_mols:
    try:
        prod = dm.reactions.apply_reaction(rxn, (mol,))
        if prod is not None:
            products.append(prod)
    except Exception as e:
        print(f"Reaction failed: {e}")

并行处理

Datamol 为许多操作内置了并行处理功能。使用 n_jobs 参数:

  • n_jobs=1:顺序执行(不进行并行处理)
  • n_jobs=-1:使用所有可用的 CPU 核心
  • n_jobs=4:使用 4 个核心

支持并行处理的函数:

  • dm.read_sdf(..., n_jobs=-1)
  • dm.descriptors.batch_compute_many_descriptors(..., n_jobs=-1)
  • dm.cluster_mols(..., n_jobs=-1)
  • dm.pdist(..., n_jobs=-1)
  • dm.conformers.sasa(..., n_jobs=-1)

进度条:许多批量操作支持 progress=True 参数。

常见工作流和模式

完整流程:数据加载 → 筛选 → 分析
import datamol as dm
import pandas as pd

# 1. Load molecules
df = dm.read_sdf("compounds.sdf")

# 2. Standardize
df['mol'] = df['mol'].apply(lambda m: dm.standardize_mol(m) if m else None)
df = df[df['mol'].notna()]  # Remove failed molecules

# 3. Compute descriptors
desc_df = dm.descriptors.batch_compute_many_descriptors(
    df['mol'].tolist(),
    n_jobs=-1,
    progress=True
)

# 4. Filter by drug-likeness
druglike = (
    (desc_df['mw'] <= 500) &
    (desc_df['logp'] <= 5) &
    (desc_df['hbd'] <= 5) &
    (desc_df['hba'] <= 10)
)
filtered_df = df[druglike]

# 5. Cluster and select diverse subset
diverse_mols = dm.pick_diverse(
    filtered_df['mol'].tolist(),
    npick=100
)

# 6. Visualize results
dm.viz.to_image(
    diverse_mols,
    legends=[dm.to_smiles(m) for m in diverse_mols],
    outfile="diverse_compounds.png",
    n_cols=10
)
构效关系(SAR)分析
# Group by scaffold
scaffolds = [dm.to_scaffold_murcko(mol) for mol in mols]
scaffold_smiles = [dm.to_smiles(s) for s in scaffolds]

# Create DataFrame with activities
sar_df = pd.DataFrame({
    'mol': mols,
    'scaffold': scaffold_smiles,
    'activity': activities  # User-provided activity data
})

# Analyze each scaffold series
for scaffold, group in sar_df.groupby('scaffold'):
    if len(group) >= 3:  # Need multiple examples
        print(f"\nScaffold: {scaffold}")
        print(f"Count: {len(group)}")
        print(f"Activity range: {group['activity'].min():.2f} - {group['activity'].max():.2f}")

        # Visualize with activities as legends
        dm.viz.to_image(
            group['mol'].tolist(),
            legends=[f"Activity: {act:.2f}" for act in group['activity']],
            align=True  # Align by common substructure
        )
虚拟筛选工作流
# 1. Generate fingerprints for query and library
query_fps = [dm.to_fp(mol) for mol in query_actives]
library_fps = [dm.to_fp(mol) for mol in library_mols]

# 2. Calculate similarities
from scipy.spatial.distance import cdist
import numpy as np

distances = dm.cdist(query_actives, library_mols, n_jobs=-1)

# 3. Find closest matches (min distance to any query)
min_distances = distances.min(axis=0)
similarities = 1 - min_distances  # Convert distance to similarity

# 4. Rank and select top hits
top_indices = np.argsort(similarities)[::-1][:100]  # Top 100
top_hits = [library_mols[i] for i in top_indices]
top_scores = [similarities[i] for i in top_indices]

# 5. Visualize hits
dm.viz.to_image(
    top_hits[:20],
    legends=[f"Sim: {score:.3f}" for score in top_scores[:20]],
    outfile="screening_hits.png"
)

参考文档

如需详细的 API 文档,请查阅以下参考文件:

  • references/core_api.md:核心命名空间函数(转换、标准化、指纹、聚类)
  • references/io_module.md:文件输入/输出操作(读取/写入 SDF、CSV、Excel 和远程文件)
  • references/conformers_module.md:3D 构象生成、聚类、SASA 计算
  • references/descriptors_viz.md:分子描述符和可视化函数
  • references/fragments_scaffolds.md:骨架提取、BRICS/RECAP 片段化
  • references/reactions_data.md:化学反应和玩具数据集

最佳实践

  1. 始终标准化来自外部来源的分子:

    mol = dm.standardize_mol(mol, disconnect_metals=True, normalize=True, reionize=True)
    
  2. 检查分子解析后的 None 值:

    mol = dm.to_mol(smiles)
    if mol is None:
        # Handle invalid SMILES
    
  3. 对大型数据集使用并行处理:

    result = dm.operation(..., n_jobs=-1, progress=True)
    
  4. 利用 fsspec 处理云存储:

    df = dm.read_sdf("s3://bucket/compounds.sdf")
    
  5. 根据相似性选择合适的指纹:

    • ECFP(Morgan):通用,适用于结构相似性
    • MACCS:速度快,特征空间较小
    • 原子对:考虑原子对及其距离
  6. 考虑规模限制:

    • Butina 聚类:约 1,000 个分子(完整距离矩阵)
    • 对于更大的数据集:使用多样性选择或层次方法
  7. 用于机器学习的骨架拆分:确保按骨架正确划分训练集/测试集

  8. 可视化 SAR 系列时对齐分子

错误处理

# Safe molecule creation
def safe_to_mol(smiles):
    try:
        mol = dm.to_mol(smiles)
        if mol is not None:
            mol = dm.standardize_mol(mol)
        return mol
    except Exception as e:
        print(f"Failed to process {smiles}: {e}")
        return None

# Safe batch processing
valid_mols = []
for smiles in smiles_list:
    mol = safe_to_mol(smiles)
    if mol is not None:
        valid_mols.append(mol)

与机器学习集成

# Feature generation
X = np.array([dm.to_fp(mol) for mol in mols])

# Or descriptors
desc_df = dm.descriptors.batch_compute_many_descriptors(mols, n_jobs=-1)
X = desc_df.values

# Train model
from sklearn.ensemble import RandomForestRegressor
model = RandomForestRegressor()
model.fit(X, y_target)

# Predict
predictions = model.predict(X_test)

故障排除

问题:分子解析失败

  • 解决方案:先使用 dm.standardize_smiles(),或尝试 dm.fix_mol()

问题:聚类时发生内存错误

  • 解决方案:对于较大的数据集,使用 dm.pick_diverse() 代替完整聚类

问题:构象生成速度慢

  • 解决方案:减小 n_confs 或增大 rms_cutoff,以生成更少的构象

问题:远程文件访问失败

  • 解决方案:确保已安装 fsspec 和相应的云服务提供商库(s3fs、gcsfs 等)

其他资源

评论

支持 Markdown