mcpField
M
medchem

medchem

github.com/jaechang-hitsデータ・データベース38467 回インストール1 週間前に更新
リポジトリ

medchem について

medchemは、創薬における分子のフィルタリングと優先順位付けを行うPythonライブラリです。薬化学ルール、構造アラート、化学基の検出、組み合わせ可能なクエリで化合物ライブラリを評価できます。

主な機能

  1. 01ドラッグライクネスルールの適用
  2. 02構造アラートのスクリーニング
  3. 03化学基の検出
  4. 04分子複雑度のスコア計算
  5. 05カスタム物性制約
  6. 06ブール式フィルタークエリ

活用シーン

  1. 01化合物ライブラリの選別
  2. 02分子の構造アラート検査
  3. 03官能基や反応性基の特定
  4. 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 オブジェクトです。SMILES から変換するには datamol.to_mol() を使用してください。

クイックスタート

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 を使って、問題となる構造パターンを検出します。対象範囲と厳格さが異なる 3 つのフィルターセットがあります。

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
)

主な概念

ルールのしきい値早見表
ルールMWLogPHBDHBARotBondsTPSAその他
Ro5(Lipinski)≤500≤5≤5≤10———
Veber————≤10≤140—
Oprea(リード)200-350-2 to 4——≤7—環 ≤4
Leadlike Soft250-450-3 to 4——≤10——
Leadlike Strict200-350-2 to 3.5——≤7—環 1-3
CNS≤450-1 to 5≤2——≤90—
REOS200-500-5 to 50-50-10———
Ro3(フラグメント)≤300≤3≤3≤3≤3≤60—
Golden Triangle200-50*LogP+400-2 to 5—————
Rule of DrugRo5 + Veber + PAINS なし
創薬段階別のフィルター選択
段階推奨フィルター理由
初期スクリーニングRo5、PAINS、Common Alerts広範なトリアージを行い、明らかな問題要因を除外
ヒットからリードへの展開Oprea または Leadlike Soft、NIBR、Lillyリードライクな領域、業界向けフィルター
リード最適化Rule of Drug、Leadlike Strict、Complexity厳格なドラッグライク性と合成可能性
CNS 標的Rule of CNS、TPSA ≤90、HBD ≤2BBB 透過性の要件
フラグメントベース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_listRuleFilters—ルールの表を参照適用するドラッグライクネスルール
n_jobsすべてのフィルター1-1 から N並列ワーカー数(-1 = すべてのコア)
progressすべてのフィルターFalsebool進捗バーを表示
max_complexityComplexityFilter—0-1000+Bertz複雑度のしきい値
methodcalculate_complexity"bertz"bertz/whitlock/barone複雑度の指標
mw_rangeConstraintsNonetuple(float, float)分子量の範囲(Da)
logp_rangeConstraintsNonetuple(float, float)LogPの範囲
tpsa_maxConstraintsNone0-200+トポロジカル極性表面積の上限
groupsChemicalGroup—名前のリスト検出する定義済み化学基
custom_smartsChemicalGroupNonedictカスタムSMARTSパターン {name: SMARTS}

ベストプラクティス

  1. 広く始めてから絞り込む:まず許容範囲の広いフィルター(Ro5、PAINS)を適用し、パイプラインで候補が絞られるにつれて、段階的に条件を厳しくします(NIBR、Lilly、複雑度)。

  2. 必ず並列化する:分子数が1000を超えるライブラリでは、すべてのCPUコアを使用するために n_jobs=-1 を設定します。

  3. ルールと構造アラートを組み合わせる:ルールは物理化学的性質を確認し、アラートは部分構造パターンを確認します。堅牢なトリアージには両方が必要です。

  4. アンチパターン — 無差別なフィルタリング:Ro5に違反するものをすべて無条件に除外しないでください。フィルタリングの前に、標的クラスと投与経路を考慮してください。

  5. アンチパターン — プロドラッグの無視:プロドラッグは意図的に標準ルールに違反します。除外するのではなく、例外として記録してください。

  6. フィルタリングの判断を記録する:再現性と規制遵守のため、どの分子を、なぜ除外したかを追跡してください。

  7. 既知の活性化合物で検証する:対象の既知の活性化合物にフィルターカスケードを適用し、偽陽性率を推定してください。

よく使うレシピ

レシピ: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 et al. Adv Drug Deliv Rev (1997) 23:3-25 — Rule of Five
  • Veber DF et al. J Med Chem (2002) 45:2615-2623 — Veber ルール
  • Oprea TI et al. J Chem Inf Comput Sci (2001) 41:1308-1315 — リードライクネス
  • Baell JB & Holloway GA. J Med Chem (2010) 53:2719-2740 — PAINS フィルター
  • Congreve M et al. Drug Discov Today (2003) 8:876-877 — Rule of Three
  • Johnson TW et al. J Med Chem (2009) 52:5487-5500 — Golden Triangle
  • 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

コメント