alterlab-medchem について
alterlab-medchemは、創薬ワークフローで分子を選別・優先順位付けするmedchem Pythonライブラリのスキルです。医薬品化学ルール、構造アラート、化学基の検出、複雑性指標、クエリDSLを組み合わせ、化合物の初期選別やリード最適化に使えます。
主な機能
- 01分子へのドラッグライクネスルールの適用
- 02構造アラートカタログによるフィルタリング
- 03定義済み化学基の検出
- 04分子複雑性の評価
- 05クエリDSLによる条件の組み合わせ
活用シーン
- 01化合物ライブラリの初期選別
- 02指定した構造アラートを持つ分子の除外
- 03リード最適化での候補化合物の優先順位付け
- 04対象の化学基を含む分子の検索
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ alterlab-ieu/ alterlab-academic-skills --skill alterlab-medchemインストール後、Claude Code で/alterlab-medchemを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
evals/evals.jsonreferences/api_guide.mdrules_catalog.mdscripts/filter_molecules.py詳細
Medchem
概要
Medchem(datamol-io/medchem)は、創薬ワークフローにおける分子のフィルタリングと優先順位付けのための Python ライブラリです。メディシナルケミストリーのルール、構造アラート(ChEMBL/NIBR/PAINS)、化学基の検出、複雑性指標、クエリ DSL を提供します。ルールとフィルターは状況に応じた指針であり、絶対的な真実ではありません。専門知識と組み合わせてください。
medchem==2.1.0(2026-09 時点の最新;Python ≥ 3.11、RDKit 2026.03)で検証済みです。 以下の API 名はこのバージョンで確認済みです。それ以前のドキュメントやブログ記事では、異なる API が説明されていました。
このスキルを使う場面
次のような場合にこのスキルを使います。
- 化合物ライブラリに薬物らしさのルール(Lipinski、Veber など)を適用する
- 構造アラートや PAINS パターンで分子をフィルタリングする
- リード最適化のために化合物の優先順位を付ける
- 化合物の品質やメディシナルケミストリー特性を評価する
- 反応性または問題のある官能基を検出する
- 分子の複雑性指標を計算する
対象外
| シナリオ | 代わりに使用 |
|---|---|
| ルールやアラートによるフィルタリングを行わず、記述子(MW、cLogP、TPSA、HBD/HBA)の計算や構造の標準化のみを行う | alterlab-datamol |
| 整備済みカタログ以外のカスタム SMARTS クエリや部分構造ロジックを作成する | alterlab-rdkit |
| スキャフォールド分割を備えた、ラベル付き毒性/ADMET ベンチマーク(例:hERG、AMES)を取得する | alterlab-pytdc |
| 化合物や標的の実測生物活性(IC50/Ki)を取得する | alterlab-chembl |
インストール
uv pip install medchem # PyPI; pulls rdkit + datamol
2 つの機能には、PyPI では提供できない追加のネイティブ依存関係が必要です。
- Lilly demerits(
lilly_demerit_filter)は、コンパイル済みの Lilly MedChem Rules ツールを外部コマンドとして実行します。medchem 2.1 以降では、medchem install-lillyがチェックサム固定されたアップストリームリリース(2.1.0)をダウンロードし、アクティブな Python の隣にビルドします。make、C++ コンパイラー、zlib が必要です(回帰テストには Ruby も必要ですが、--no-testを渡せば省略できます)。ネイティブ Windows はサポートされていないため、WSL を使用してください。以前の conda-forge 版lilly-medchem-rules1.0.1 は古く、現在は使用できません。ツールがない場合、この呼び出しはImportErrorを発生させます。2.1 では Lilly の原子数制限のデフォルトも変更されました(ソフト 25/ハード 40/最小 7。以前は 30/50/1)。 - ChemAxon のルール(
rule_of_chemaxon_druglikeness)には、ライセンス済みの ChemAxon インストールが必要です。
それ以外(RuleFilters、CommonAlerts、NIBR、複雑性、化学基、クエリ)は、PyPI の wheel のみで動作します。
主な機能
medchem 全体に共通する規約です。 フィルターは
mols(SMILES 文字列または RDKit 分子のシーケンス)を受け取り、デフォルトでn_jobs=-1(全コア)を使用し、progress=Trueを受け付けます。medchem.structural/medchem.rulesのフィルター クラス は pandas DataFrame(入力分子ごとに 1 行)を返します。medchem.functional.*ヘルパーは NumPy のブール配列を返し、Trueは分子が条件を満たし、保持されることを表します。ルール名とアラート名の正式な一覧は、推測せずにmc.rules.RuleFilters.list_available_rules()およびmc.structural.CommonAlertsFilters.list_default_available_alerts()から取得してください。
1. メディシナルケミストリーのルール — medchem.rules
単一ルール — medchem.rules.basic_rules.* 関数は1つの分子(SMILES または RDKit)を受け取り、通常の bool を返します。
import medchem as mc
smi = "CC(=O)OC1=CC=CC=C1C(=O)O" # aspirin
mc.rules.basic_rules.rule_of_five(smi) # -> True
mc.rules.basic_rules.rule_of_veber(smi) # -> True
mc.rules.basic_rules.rule_of_cns(smi)
利用可能なルール(完全な一覧は mc.rules.RuleFilters.list_available_rules() で取得できます):rule_of_five、rule_of_five_beyond、rule_of_four、rule_of_three、rule_of_three_extended、rule_of_two、rule_of_ghose、rule_of_veber、rule_of_reos、rule_of_egan、rule_of_pfizer_3_75、rule_of_gsk_4_400、rule_of_oprea、rule_of_xu、rule_of_cns、rule_of_respiratory、rule_of_zinc、rule_of_leadlike_soft、rule_of_druglike_soft、rule_of_generative_design、rule_of_generative_design_strict、rule_of_chemaxon_druglikeness(ChemAxon が必要です)。
rule_of_drug、rule_of_leadlike_strict、golden_triangle、pains_filter関数はありません(2.1.0 で確認済み)。PAINS はアラートシステムにあります(HASALERT("pains")またはCommonAlertsFilters(alerts_set=["PAINS"]))。リードライク性の判定にはrule_of_leadlike_softまたはrule_of_opreaを使用してください。
複数のルール — RuleFilters は、mol、pass_all、pass_any の各列と、ルールごとのブール値列を含む DataFrame を返します。
import datamol as dm
import medchem as mc
mols = [dm.to_mol(s) for s in smiles_list]
rfilter = mc.rules.RuleFilters(rule_list=["rule_of_five", "rule_of_veber", "rule_of_cns"])
df = rfilter(mols=mols, n_jobs=-1, progress=True)
# df["pass_all"] -> bool per molecule; df["rule_of_five"] -> per-rule bool
clean = [m for m, ok in zip(mols, df["pass_all"]) if ok]
物性の範囲 — すべてをまとめて指定する「Constraints(mw_range=...)」オブジェクトはありません(セクション 7 の注記を参照)。mc.rules.list_descriptors() にある記述子名(mw、clogp、tpsa、n_lipinski_hbd、n_lipinski_hba、n_rotatable_bonds、n_rings など)に対して mc.rules.in_range を使ってカスタムの物性カットオフを作成するか、クエリ DSL(セクション 8 の HASPROP)を使用してください。
2. 構造アラートフィルター — medchem.structural
medchem.structural には、CommonAlertsFilters と NIBRFilters の2つのフィルタークラスが用意されています。(Lilly demerits は medchem.functional 経由で使用します。セクション 3 を参照してください。クラスは medchem.structural.lilly_demerits にあり、外部バイナリが必要です。)
共通アラート — ChEMBL の精選されたアラートセット(Glaxo、Dundee、BMS、PAINS、SureChEMBL など)。mol、pass_filter(bool)、status(ok/exclude)、reasons(一致したアラート名を ; で連結)の各列を含む DataFrame を返します。
import medchem as mc
caf = mc.structural.CommonAlertsFilters() # all default sets
caf_pains = mc.structural.CommonAlertsFilters(alerts_set=["PAINS"]) # PAINS only
df = caf(mols=mol_list, n_jobs=-1, progress=True)
clean = df[df["pass_filter"]]
# discover sets: mc.structural.CommonAlertsFilters.list_default_available_alerts()
NIBR フィルター — Novartis のフィルターセット。mol、pass_filter、severity、status、reasons を含む DataFrame を返します。
nibr = mc.structural.NIBRFilters()
df = nibr(mols=mol_list, n_jobs=-1)
3. 関数型 API — medchem.functional
1回の呼び出しで使えるヘルパーで、NumPy のブール値配列を返します(True = 残す)。合格した分子のインデックスを取得するには、return_idx=True を渡してください。
import medchem as mc
mc.functional.rules_filter(mol_list, rules=["rule_of_five", "rule_of_veber"], n_jobs=-1)
mc.functional.alert_filter(mol_list, alerts=["pains"], n_jobs=-1) # alert names are lowercase here
mc.functional.nibr_filter(mol_list, max_severity=10, n_jobs=-1)
mc.functional.complexity_filter(mol_list, complexity_metric="bertz", limit="99", n_jobs=-1)
mc.functional.chemical_group_filter(mol_list, chemical_group=mc.groups.ChemicalGroup(groups=["hinge_binders"]))
Lilly demerits — Lilly ツールが必要です(medchem install-lilly。インストールの項を参照)。利用できない場合は ImportError を発生させます。max_demerits(デフォルトは160)を超える分子は除外されます。
keep = mc.functional.lilly_demerit_filter(mol_list, max_demerits=160, n_jobs=-1) # NumPy bool array
4. 化学基の検出 — medchem.groups
ChemicalGroup は、精選された化学基カタログと照合します。有効なカタログ名は mc.groups.list_default_chemical_groups() で一覧表示できます(例:hinge_binders、electrophilic_warheads_for_kinases、common_warhead_covalent_inhibitors、privileged_kinase_inhibitor_scaffolds、aggregator)。クエリ DSL の HASGROUP で使用する、分子ごとの官能基名は mc.groups.list_functional_group_names() から取得できます。
import medchem as mc
group = mc.groups.ChemicalGroup(groups=["hinge_binders"])
group.has_match(mol) # bool for one mol
group.get_matches(mol) # detailed matches
# batch: mc.functional.chemical_group_filter(mols, chemical_group=group)
phosphate_binders、michael_acceptors、reactive_groupsは、デフォルトのカタログ名ではありません。反応性/求電子性モチーフには、electrophilic_warheads_for_kinases/common_warhead_covalent_inhibitors、アラートフィルター(セクション 2)、またはカスタム SMARTS カタログ(mc.catalogs.catalog_from_smarts)を使用してください。
5. 名前付きカタログ — medchem.catalogs
import medchem as mc
mc.catalogs.list_named_catalogs() # available catalog names
cat = mc.catalogs.NamedCatalogs.pains() # e.g. a PAINS RDKit FilterCatalog
mc.catalogs.catalog_from_smarts(...) # build a catalog from custom SMARTS
6. 分子複雑性 — medchem.complexity
ComplexityFilter は、基準セット(デフォルトは ZINC)から算出したパーセンタイルしきい値を超える複雑性を持つ分子にフラグを付けます。分子ごとに呼び出され、bool(True = 上限内/保持)を返します。指標は bertz、whitlock(WhitlockCT)、barone(BaroneCT)、smcm(SMCM)、twc(TWC)、および sas/qed/clogp です。2.1 で追加:mc.complexity.SPS(mol)(正規化された SpacialScore、Krzyzanowski et al., J. Med. Chem. 2023)。ComplexityFilter の指標("spacialscore")として使う場合は、独自の threshold_stats_file が必要です。
import medchem as mc
cflt = mc.complexity.ComplexityFilter(limit="99", complexity_metric="bertz")
keep = [cflt(m) for m in mol_list]
# or batch: mc.functional.complexity_filter(mol_list, complexity_metric="bertz", limit="99")
mc.complexity.calculate_complexity(...)はありません。また、ComplexityFilterが受け取るのはlimit/complexity_metric/threshold_stats_fileであり、max_complexityではありません。スコアを直接取得するには、指標クラス(mc.complexity.TWCなど)を直接使用してください。
7. 部分構造制約 — medchem.constraints
mc.constraints.Constraints(core, constraint_fns, prop_name="query") は、クエリーコア周辺の部分構造/R 基制約を適用します(has_match/validate 経由)。物理化学的特性の範囲でフィルタリングするものではありません。MW/logP/TPSA の範囲には、RuleFilters と in_range(セクション 1)、またはクエリー DSL の HASPROP(セクション 8)を使用してください。
8. クエリー DSL — medchem.query
QueryFilter は、ルール、特性、アラート、グループに対するブール式を評価します。演算子:AND、OR、NOT、比較演算子 < > <= >= == !=。プリミティブ:MATCHRULE("...")、HASPROP("<descriptor>" < value)、HASALERT("<lowercase set>")、HASGROUP("...")、HASSUBSTRUCTURE/HASSUPERSTRUCTURE、LIKE。
import medchem as mc
qf = mc.query.QueryFilter('MATCHRULE("rule_of_five") AND HASPROP("mw" < 500) AND NOT HASALERT("pains")')
keep = qf(mol_list, n_jobs=-1) # NumPy bool array
構文は上記の構造化 DSL です。
"rule_of_five AND NOT common_alerts"のような自由形式のテキストではありません。mc.query.parse()はありません。mc.query.QueryFilter(query_string)を構築し、分子に対して呼び出してください。HASALERT内のアラート名は小文字です(pains、tox、nih、...)。
ワークフローパターン
パターン 1:化合物ライブラリの初期トリアージ
化合物の大規模なコレクションから、薬剤らしい候補を絞り込み、構造アラートを持つものを除外します。
import datamol as dm
import medchem as mc
import pandas as pd
df = pd.read_csv("compounds.csv")
mols = [dm.to_mol(smi) for smi in df["smiles"]]
# Rule filter -> DataFrame with pass_all + per-rule columns
rule_df = mc.rules.RuleFilters(rule_list=["rule_of_five", "rule_of_veber"])(
mols=mols, n_jobs=-1, progress=True
)
# Structural alerts -> DataFrame with pass_filter (True = clean)
alert_df = mc.structural.CommonAlertsFilters()(mols=mols, n_jobs=-1, progress=True)
df["passes_rules"] = rule_df["pass_all"].to_numpy()
df["no_alerts"] = alert_df["pass_filter"].to_numpy()
df["drug_like"] = df["passes_rules"] & df["no_alerts"]
df[df["drug_like"]].to_csv("filtered_compounds.csv", index=False)
パターン 2:リード最適化のフィルタリング
より厳格なフィルターを重ね、すべての段階を通過した分子だけを残します。functional.* ヘルパーはすべて、要素の対応が保たれた NumPy の bool 配列を返すため、交差を取るのは簡単です。
import numpy as np
import medchem as mc
f = mc.functional
keep = (
f.rules_filter(candidate_mols, rules=["rule_of_oprea"], n_jobs=-1)
& f.nibr_filter(candidate_mols, n_jobs=-1)
& f.complexity_filter(candidate_mols, complexity_metric="bertz", limit="99", n_jobs=-1)
)
# Add lilly_demerit_filter(...) too if the Lilly binaries are installed.
survivors = [m for m, ok in zip(candidate_mols, keep) if ok]
パターン 3:特定の化学基の特定
対象の骨格/モチーフを含む分子にフラグを付けます(mc.groups.list_default_chemical_groups() で名前を確認してください)。
import medchem as mc
group = mc.groups.ChemicalGroup(groups=["hinge_binders"])
keep = mc.functional.chemical_group_filter(mol_list, chemical_group=group)
with_group = [m for m, ok in zip(mol_list, keep) if ok]
ベストプラクティス
-
状況を考慮する:フィルターを盲目的に適用しないでください。生物学的標的と化学空間を理解しましょう。
-
複数のフィルターを組み合わせる:より適切な判断のため、ルール、構造アラート、ドメイン知識を組み合わせて使用してください。
-
並列化を使用する:大規模なデータセット(分子数 >1000)では、並列処理に
n_jobs=-1を常に使用してください。 -
反復的に絞り込む:まず広範なフィルター(Ro5)から始め、必要に応じてより具体的な基準(CNS、リードらしさ)を適用してください。
-
フィルタリングの判断を記録する:再現性を確保するため、どの分子を、なぜ除外したかを記録してください。
-
結果を検証する:市販薬でも標準的なフィルターに適合しないことがよくあります。これらは絶対的なルールではなく、指針として使用してください。
-
プロドラッグを考慮する:プロドラッグとして設計された分子は、意図的に標準的なメディシナルケミストリーのルールに違反する場合があります。
リソース
references/api_guide.md
すべての medchem モジュールを網羅した包括的な API リファレンスです。関数シグネチャ、パラメーター、戻り値の型について詳しく説明しています。
references/rules_catalog.md
利用可能なルール、フィルター、アラートを、説明、しきい値、文献参照とともに網羅したカタログです。
scripts/filter_molecules.py
バッチフィルタリング用 CLI です。CSV/TSV、SDF、プレーンな SMILES の .txt 入力、設定可能なフィルターの組み合わせ、サマリーレポートに対応しています。
使用方法:
uv run python scripts/filter_molecules.py input.csv \
--rules rule_of_five,rule_of_cns --nibr --output filtered.csv
フラグは個別のスイッチ(--nibr、--common-alerts、--lilly、--pains)であり、--alerts <name> ではありません。--lilly の使用には Lilly ツールが必要です(medchem install-lilly)。
ドキュメント
公式ドキュメント:https://medchem-docs.datamol.io/ GitHub リポジトリ:https://github.com/datamol-io/medchem
AlterLab Academic Skills スイートの一部です。