关于 medchem
medchem 是用于药物发现中分子筛选与优先级排序的 Python 库,面向研究人员处理化合物库。它整合药物化学规则、结构警示、化学基团检测和可组合查询。
主要功能
- 01类药性规则筛选
- 02结构警示筛查
- 03化学基团检测
- 04分子复杂度评分
- 05自定义性质约束
- 06布尔筛选查询
适用场景
- 01筛选化合物库
- 02排查分子的结构警示
- 03识别官能团与反应性基团
- 04按复杂度和性质确定候选优先级
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ jaechang-hits/ sciagent-skills --skill medchem安装后在 Claude Code 中输入/medchem确认已加载。
附带文件references/rules_catalog.md
详细介绍
Medchem
概述
Medchem 是一个用于药物发现中分子筛选和优先级排序的 Python 库。它提供数百种成熟的药物化学规则、结构警示和化学基团检测器,可大规模筛选化合物库。所有过滤器均支持并行执行,并返回结构化结果。
适用场景
- 对化合物库应用类药性规则(Lipinski、Veber、Oprea、CNS、REOS)
- 根据结构警示筛选分子(PAINS、NIBR、Lilly Demerits)
- 检测特定化学基团(铰链结合基团、Michael 受体、反应性基团)
- 计算分子复杂度指标(Bertz、Whitlock、Barone)
- 应用自定义属性约束(MW、LogP、TPSA、可旋转键)
- 使用布尔逻辑组合复杂的多规则筛选查询
- 对于 SMILES/SDF 解析、描述符和指纹,请使用 rdkit-cheminformatics
- 对于高级分子操作,请使用 datamol-cheminformatics
前置条件
pip install medchem datamol
Medchem 依赖 RDKit 和 datamol。所有分子输入均为 RDKit Chem.Mol 对象;使用 datamol.to_mol() 从 SMILES 转换。
快速入门
import datamol as dm
import medchem as mc
# Convert SMILES to molecules
smiles_list = ["CC(=O)OC1=CC=CC=C1C(=O)O", "c1ccccc1N", "O=C(O)c1ccccc1"]
mols = [dm.to_mol(s) for s in smiles_list]
# Apply Rule of Five + structural alerts in one pass
rule_filter = mc.rules.RuleFilters(rule_list=["rule_of_five"])
alert_filter = mc.structural.CommonAlertsFilters()
rule_results = rule_filter(mols=mols, n_jobs=-1)
alert_results = alert_filter(mols=mols, n_jobs=-1)
print(f"Rule results: {rule_results}")
print(f"Alert results: {[r['has_alerts'] for r in alert_results]}")
核心 API
1. 类药性规则
通过 mc.rules 应用成熟的药物化学规则。单条规则返回 bool;RuleFilters 可批量应用多条规则。
import medchem as mc
# Single rule on a SMILES string
passes = mc.rules.basic_rules.rule_of_five("CC(=O)OC1=CC=CC=C1C(=O)O")
print(f"Passes Ro5: {passes}") # True
# Available individual rules:
# rule_of_five, rule_of_three, rule_of_oprea, rule_of_cns,
# rule_of_leadlike_soft, rule_of_leadlike_strict, rule_of_veber,
# rule_of_reos, rule_of_drug, golden_triangle, pains_filter
import datamol as dm
import medchem as mc
# Batch application with RuleFilters
mols = [dm.to_mol(s) for s in smiles_list]
rfilter = mc.rules.RuleFilters(
rule_list=["rule_of_five", "rule_of_oprea", "rule_of_cns"]
)
results = rfilter(mols=mols, n_jobs=-1, progress=True)
# Returns list of dicts: [{"rule_of_five": True, "rule_of_oprea": False, ...}, ...]
print(f"First molecule: {results[0]}")
2. 结构警示过滤器
通过 mc.structural 检测有问题的结构模式。三组过滤器涵盖不同的范围和严格程度。
import datamol as dm
import medchem as mc
mol = dm.to_mol("c1ccc(N)cc1")
mols = [dm.to_mol(s) for s in smiles_list]
# Common Alerts — general structural alerts from ChEMBL / literature
alert_filter = mc.structural.CommonAlertsFilters()
has_alerts, details = alert_filter.check_mol(mol) # single molecule
batch_results = alert_filter(mols=mols, n_jobs=-1, progress=True)
# Each result: {"has_alerts": bool, "alert_details": [...], "num_alerts": int}
print(f"Alerts: {batch_results[0]}")
import medchem as mc
# NIBR Filters — Novartis industrial filter set (returns bool list)
nibr_filter = mc.structural.NIBRFilters()
nibr_results = nibr_filter(mols=mols, n_jobs=-1)
print(f"NIBR pass: {nibr_results}") # [True, False, ...]
# Lilly Demerits — 275 patterns, molecules rejected at >100 demerits
lilly_filter = mc.structural.LillyDemeritsFilters()
lilly_results = lilly_filter(mols=mols, n_jobs=-1)
# Each result: {"demerits": int, "passes": bool, "matched_patterns": [...]}
print(f"Lilly: {lilly_results[0]}")
3. 化学基团
通过 mc.groups.ChemicalGroup 检测特定的官能团基序。
预定义基团:hinge_binders、phosphate_binders、michael_acceptors、reactive_groups。
import medchem as mc
# Check for kinase hinge binders and Michael acceptors
group = mc.groups.ChemicalGroup(
groups=["hinge_binders", "michael_acceptors"]
)
has_matches = group.has_match(mols) # List[bool]
match_info = group.get_matches(mols[0]) # {group_name: [(atom_indices), ...]}
all_matches = group.get_all_matches(mols) # List[Dict]
print(f"Has hinge binder: {has_matches}")
# Custom SMARTS patterns
custom = mc.groups.ChemicalGroup(
groups=["reactive_groups"],
custom_smarts={"trifluoromethyl_ketone": "[C;H0](=O)C(F)(F)F"}
)
4. 命名目录
通过 mc.catalogs 访问经过筛选的化学结构目录。
可用目录:functional_groups、protecting_groups、reagents、fragments。
import medchem as mc
catalog = mc.catalogs.NamedCatalogs.get("functional_groups")
matches = catalog.get_matches(mol)
print(f"Functional group matches: {matches}")
5. 分子复杂度
通过 mc.complexity 计算合成可及性的代理指标。
方法:bertz(拓扑)、whitlock、barone。
import datamol as dm
import medchem as mc
mol = dm.to_mol("CC(=O)OC1=CC=CC=C1C(=O)O")
# Single molecule complexity
score = mc.complexity.calculate_complexity(mol, method="bertz")
print(f"Bertz complexity: {score:.1f}")
# Batch filtering by complexity threshold
cfilter = mc.complexity.ComplexityFilter(max_complexity=500, method="bertz")
results = cfilter(mols=mols, n_jobs=-1)
print(f"Passes complexity: {results}") # List[bool]
6. 属性约束
通过 mc.constraints.Constraints 应用基于自定义属性的约束。
import medchem as mc
constraints = mc.constraints.Constraints(
mw_range=(200, 500),
logp_range=(-2, 5),
tpsa_max=140,
rotatable_bonds_max=10,
hbd_max=5,
hba_max=10,
rings_range=(1, 5),
aromatic_rings_max=3,
)
results = constraints(mols=mols, n_jobs=-1)
# Each result: {"passes": bool, "violations": ["mw_range", ...]}
print(f"Violations: {results[0]}")
7. 查询语言
通过 mc.query 使用布尔表达式组合复杂筛选逻辑。
import medchem as mc
# Parse a query combining rules, alerts, and property checks
query = mc.query.parse("rule_of_five AND NOT common_alerts")
results = query.apply(mols=mols, n_jobs=-1) # List[bool]
print(f"Passing: {sum(results)}/{len(results)}")
# More complex queries
q2 = mc.query.parse("rule_of_cns AND complexity < 400")
q3 = mc.query.parse("(rule_of_five OR rule_of_oprea) AND NOT pains_filter")
q4 = mc.query.parse("mw > 200 AND mw < 500 AND logp < 5")
8. 函数式 API 和实用工具
使用 mc.functional 中的快捷函数和 mc.utils 中的实用工具。
import medchem as mc
# Functional API — one-liner filters
nibr_ok = mc.functional.nibr_filter(mols=mols, n_jobs=-1) # List[bool]
alerts = mc.functional.common_alerts_filter(mols=mols, n_jobs=-1)
lilly = mc.functional.lilly_demerits_filter(mols=mols, n_jobs=-1)
# Utilities
standardized = mc.utils.standardize_mol(mol) # sanitize, neutralize charges
batch_out = mc.utils.batch_process(
mols=mols, func=mc.complexity.calculate_complexity,
n_jobs=-1, progress=True, batch_size=100
)
关键概念
规则阈值速查
| 规则 | MW | LogP | HBD | HBA | 可旋转键 | TPSA | 其他 |
|---|---|---|---|---|---|---|---|
| Ro5(Lipinski) | ≤500 | ≤5 | ≤5 | ≤10 | — | — | — |
| Veber | — | — | — | — | ≤10 | ≤140 | — |
| Oprea(先导化合物) | 200-350 | -2 到 4 | — | — | ≤7 | — | 环 ≤4 |
| Leadlike Soft | 250-450 | -3 到 4 | — | — | ≤10 | — | — |
| Leadlike Strict | 200-350 | -2 到 3.5 | — | — | ≤7 | — | 环 1-3 |
| CNS | ≤450 | -1 到 5 | ≤2 | — | — | ≤90 | — |
| REOS | 200-500 | -5 到 5 | 0-5 | 0-10 | — | — | — |
| Ro3(片段) | ≤300 | ≤3 | ≤3 | ≤3 | ≤3 | ≤60 | — |
| Golden Triangle | 200-50*LogP+400 | -2 到 5 | — | — | — | — | — |
| 药物规则 | Ro5 + Veber + 无 PAINS |
按发现阶段选择过滤器
| 阶段 | 推荐过滤器 | 依据 |
|---|---|---|
| 初筛 | Ro5、PAINS、Common Alerts | 广泛筛选,去除明显的不利因素 |
| 命中到先导化合物 | Oprea 或 Leadlike Soft、NIBR、Lilly | 先导化合物样空间、工业界过滤器 |
| 先导化合物优化 | 药物规则、Leadlike Strict、复杂度 | 严格的类药性 + 合成可行性 |
| CNS 靶点 | CNS 规则、TPSA ≤90、HBD ≤2 | BBB 渗透性要求 |
| 基于片段的发现 | Ro3、低复杂度(≤250) | 片段具有“生长空间” |
规则是指导原则,而非绝对标准
约 10% 的上市药物违反 Ro5。天然产物、抗生素、PROTAC 和前药中常见此类例外。始终将基于规则的筛选与领域专业知识及靶标类别知识相结合。不同的给药方式(口服、IV、外用)和靶标类别(激酶、GPCR、离子通道)各有其最佳性质范围。
常见工作流
工作流 1:化合物库初筛
从原始 SMILES 到筛选出类药候选物的完整流程。
import pandas as pd
import datamol as dm
import medchem as mc
# Load compound library
df = pd.read_csv("compounds.csv")
mols = [dm.to_mol(s) for s in df["smiles"]]
print(f"Input: {len(mols)} molecules")
# Step 1: Drug-likeness rules
rfilter = mc.rules.RuleFilters(rule_list=["rule_of_five", "rule_of_veber"])
rule_results = rfilter(mols=mols, n_jobs=-1, progress=True)
# Step 2: Structural alerts
alert_filter = mc.structural.CommonAlertsFilters()
alert_results = alert_filter(mols=mols, n_jobs=-1, progress=True)
# Step 3: Combine results
df["passes_rules"] = [all(r.values()) for r in rule_results]
df["has_alerts"] = [r["has_alerts"] for r in alert_results]
df["drug_like"] = df["passes_rules"] & ~df["has_alerts"]
filtered = df[df["drug_like"]]
print(f"Output: {len(filtered)} drug-like molecules ({len(filtered)/len(df)*100:.1f}%)")
filtered.to_csv("filtered_compounds.csv", index=False)
工作流 2:先导化合物优化筛选级联
依次应用严格程度逐步提高的筛选条件,并生成详细报告。
import datamol as dm
import medchem as mc
import pandas as pd
mols = [dm.to_mol(s) for s in smiles_list]
# Cascade: rules → structural alerts → complexity → Lilly demerits
filters = [
("Leadlike Strict", mc.rules.RuleFilters(rule_list=["rule_of_leadlike_strict"])),
("NIBR Alerts", mc.structural.NIBRFilters()),
("Complexity ≤400", mc.complexity.ComplexityFilter(max_complexity=400)),
("Lilly Demerits", mc.structural.LillyDemeritsFilters()),
]
surviving = list(range(len(mols)))
for name, filt in filters:
results = filt(mols=[mols[i] for i in surviving], n_jobs=-1)
# Handle different result formats
if isinstance(results[0], dict):
passed = [i for i, r in zip(surviving, results)
if r.get("passes", not r.get("has_alerts", True))]
else:
passed = [i for i, r in zip(surviving, results) if r]
print(f"{name}: {len(surviving)} → {len(passed)}")
surviving = passed
print(f"Final candidates: {len(surviving)} / {len(mols)}")
关键参数
| 参数 | 模块 | 默认值 | 范围 | 效果 |
|---|---|---|---|---|
rule_list | RuleFilters | — | 参见规则表 | 要应用的类药性规则 |
n_jobs | 所有筛选器 | 1 | -1 到 N | 并行工作进程数(-1 = 使用所有核心) |
progress | 所有筛选器 | False | bool | 显示进度条 |
max_complexity | ComplexityFilter | — | 0-1000+ | Bertz 复杂度阈值 |
method | calculate_complexity | "bertz" | bertz/whitlock/barone | 复杂度指标 |
mw_range | Constraints | None | tuple(float, float) | 分子量范围(Da) |
logp_range | Constraints | None | tuple(float, float) | LogP 范围 |
tpsa_max | Constraints | None | 0-200+ | 拓扑极性表面积上限 |
groups | ChemicalGroup | — | 名称列表 | 要检测的预定义化学基团 |
custom_smarts | ChemicalGroup | None | dict | 自定义 SMARTS 模式 {name: SMARTS} |
最佳实践
-
先宽后严:先应用宽松的筛选条件(Ro5、PAINS),随着流程逐步缩小候选集,再逐渐收紧筛选条件(NIBR、Lilly、复杂度)。
-
始终使用并行处理:对于超过 1000 个分子的库,设置
n_jobs=-1以使用所有 CPU 核心。 -
结合规则与结构警示:规则检查理化性质;警示检查子结构模式。稳健的初筛需要兼顾两者。
-
反模式 — 盲目筛选:不要盲目淘汰所有不符合 Ro5 的分子。筛选前应考虑靶标类别和给药方式。
-
反模式 — 忽视前药:前药有意违反标准规则。应将其标记为例外,而不是筛除。
-
记录筛选决策:跟踪被移除的分子及其原因,以确保结果可复现并符合监管要求。
-
使用已知活性化合物进行验证:对靶标已知的活性化合物运行筛选级联,以估算假阳性率。
常见方案
方案:与 DataFrame 集成
import pandas as pd
import datamol as dm
import medchem as mc
df = pd.read_csv("molecules.csv")
df["mol"] = df["smiles"].apply(dm.to_mol)
rfilter = mc.rules.RuleFilters(rule_list=["rule_of_five", "rule_of_cns"])
results = rfilter(mols=df["mol"].tolist(), n_jobs=-1)
df["passes_ro5"] = [r["rule_of_five"] for r in results]
df["passes_cns"] = [r["rule_of_cns"] for r in results]
filtered = df[df["passes_ro5"] & df["passes_cns"]]
print(f"CNS drug-like: {len(filtered)}")
方案:结合 ML 评分
import medchem as mc
# Rule-based pre-filter
rule_results = mc.rules.RuleFilters(rule_list=["rule_of_five"])(mols, n_jobs=-1)
filtered_mols = [mol for mol, r in zip(mols, rule_results) if r["rule_of_five"]]
# ML model scoring on filtered set (reduces compute cost)
ml_scores = ml_model.predict(filtered_mols)
candidates = [mol for mol, score in zip(filtered_mols, ml_scores) if score > 0.8]
print(f"ML-scored candidates: {len(candidates)}")
方案:自定义 SMARTS 基团筛查
import medchem as mc
# Define project-specific warheads for covalent inhibitor screening
custom_warheads = {
"acrylamide": "[C;H1](=O)[CH]=[CH2]",
"vinyl_sulfonamide": "[NH]S(=O)(=O)[CH]=[CH2]",
"chloroacetamide": "ClCC(=O)N",
}
group = mc.groups.ChemicalGroup(groups=[], custom_smarts=custom_warheads)
has_warhead = group.has_match(mols)
warhead_mols = [mol for mol, match in zip(mols, has_warhead) if match]
print(f"Covalent warhead candidates: {len(warhead_mols)}")
故障排除
| 问题 | 原因 | 解决方案 |
|---|---|---|
分子列表中出现 None | 输入中包含无效 SMILES | 预先筛除:mols = [m for m in mols if m is not None] |
| 所有分子都未通过 Ro5 | 分子库以片段为主,或属于 PPI 空间 | 改用 rule_of_three 或 rule_of_leadlike_soft |
| 未发现 PAINS 警示 | 分子简单或以片段为主 | 这是预期结果 — PAINS 模式针对筛选命中大小的分子 |
| Lilly 扣分均 >100 | 分子高度官能团化 | 检查各个模式;考虑提高阈值或改用 NIBR |
| 处理速度慢 | 大型分子库未使用并行处理 | 设置 n_jobs=-1 以并行执行 |
ImportError: medchem | 缺少依赖项 | pip install medchem datamol(需要 RDKit) |
| 查询解析错误 | 查询语法无效 | 检查运算符:AND、OR、NOT,以及比较符:<、>、== |
| 结果格式不一致 | 不同筛选器类返回不同类型 | 查看文档:RuleFilters → dict,NIBRFilters → bool,LillyDemeritsFilters → dict |
捆绑资源
references/rules_catalog.md
所有药物化学规则和结构警示过滤器的完整目录,包含文献引用、阈值标准、化学基团模式、自定义 SMARTS 示例,以及针对不同阶段的过滤器选择指南。API 函数签名已整合到上方的 Core API 代码块中。
相关技能
- rdkit-cheminformatics — 底层化学信息学:SMILES/SDF 解析、描述符、指纹、子结构搜索
- datamol-cheminformatics — 高层分子操作:标准化、骨架、片段化、3D 构象
- pubchem-compound-search — 数据库查询:检索化合物属性和生物活性数据以供验证
参考文献
- Lipinski CA 等。Adv Drug Deliv Rev(1997)23:3-25 — 五规则
- Veber DF 等。J Med Chem(2002)45:2615-2623 — Veber 规则
- Oprea TI 等。J Chem Inf Comput Sci(2001)41:1308-1315 — 类先导化合物特性
- Baell JB 和 Holloway GA。J Med Chem(2010)53:2719-2740 — PAINS 过滤器
- Congreve M 等。Drug Discov Today(2003)8:876-877 — 三规则
- Johnson TW 等。J Med Chem(2009)52:5487-5500 — 黄金三角
- Walters WP 和 Murcko MA。Adv Drug Deliv Rev(2002)54:255-271 — REOS
- 官方文档:https://medchem-docs.datamol.io/
- GitHub:https://github.com/datamol-io/medchem