alterlab-bindingdb について
alterlab-bindingdbは、創薬、薬理学、計算化学向けにBindingDBのデータを検索・分析するスキルです。REST APIまたはダウンロードデータからタンパク質と化合物の実測親和性を取得し、UniProtやSMILESによる検索、SAR、多標的分析、機械学習用データの準備を支援します。
主な機能
- 01REST APIによる結合データ検索
- 02UniProt IDによる標的リガンド検索
- 03SMILESによる構造類似検索
- 04大規模分析向けTSVダウンロード
- 05SARと多標的結合の分析
活用シーン
- 01タンパク質標的の既知リガンド検索
- 02類似化合物間の親和性比較
- 03化合物の選択性とオフターゲットの評価
- 04機械学習向け親和性データセットの準備
インストール
コマンドをコピーしてターミナルで実行します。
npx skills add https:/ / github.com/ alterlab-ieu/ alterlab-academic-skills --skill alterlab-bindingdbインストール後、Claude Code で/alterlab-bindingdbを入力して読み込まれたか確認します。
同梱ファイル
SKILL.md と一緒にインストールされる参考資料やスクリプト。
evals/evals.jsonreferences/affinity_queries.mdscripts/query_bindingdb.py詳細
BindingDB データベース
概要
BindingDB(https://www.bindingdb.org/)は、測定された薬物とタンパク質の結合親和性を収録する主要な公開データベースです。科学文献および特許文献から精選された、約140万種類の化合物と約11,500種類のタンパク質標的についての約320万件の結合データレコードが含まれています(ホームページの数値、2026-09)。BindingDB には、創薬、薬理学、計算化学研究に不可欠な定量的結合測定値(Ki、Kd、IC50、EC50)が保存されています。
主なリソース:
- BindingDB ウェブサイト:https://www.bindingdb.org/
- REST API のベース URL:https://bindingdb.org/rest/(キー不要。デフォルトの応答形式は XML です。
response=application/jsonを追加すると JSON になります) - ダウンロードページ:https://www.bindingdb.org/rwd/bind/chemsearch/marvin/Download.jsp(全件 TSV は日付付きの
BindingDB_All_<YYYYMM>_tsv.zipで、圧縮時のサイズは約560 MB、毎月更新されます)
このスキルを使用する場面
次のような場合に BindingDB を使用します。
- 標的ベースの創薬:標的タンパク質に結合する既知の化合物と、その親和性を調べる場合
- SAR 解析:類似体の系列で、構造修飾が結合親和性にどのような影響を与えるかを調べる場合
- リード化合物のプロファイリング:化合物がどの標的に結合するか(選択性/ポリファーマコロジー)を調べる場合
- ベンチマークデータセット:ML モデルのトレーニングに使用する、精選されたタンパク質とリガンドの親和性データを取得する場合
- ドラッグリポジショニング解析:承認薬が意図しない標的に結合するかを調べる場合
- 競合分析:標的クラスについて、報告されている最も高い親和性を調べる場合
- フラグメントスクリーニング:標的に対するフラグメントの検証済み結合データを探す場合
該当しない場合
| シナリオ | 代わりに使用 |
|---|---|
| アッセイメタデータや薬物作用機序を含む、大規模な精選済み生物活性データのマイニング | alterlab-chembl |
| 名前または CID による化合物識別子/特性の検索、PubChem BioAssay | alterlab-pubchem |
| 購入可能な類似体またはドッキング対応の3Dライブラリ | alterlab-zinc-db |
| リガンドを受容体構造にドッキングする場合 | alterlab-diffdock |
主な機能
1. BindingDB REST API
ベース URL:https://bindingdb.org/rest
import requests
BASE_URL = "https://bindingdb.org/rest"
def bindingdb_query(method, params):
"""Query the BindingDB REST API."""
url = f"{BASE_URL}/{method}"
response = requests.get(url, params=params, headers={"Accept": "application/json"})
response.raise_for_status()
return response.json()
2. 標的によるクエリ(UniProt ID)
getLigandsByUniprot エンドポイントは、<UniProt accession>;<cutoff in nM> 形式の単一の uniprot パラメーターを受け取ります。例:P00519;10000。
def get_ligands_for_target(uniprot_id, cutoff=10000):
"""
Get all ligands with measured affinity for a UniProt target.
Args:
uniprot_id: UniProt accession (e.g., "P00519" for ABL1)
cutoff: Maximum affinity value to return (in nM)
"""
params = {
"uniprot": f"{uniprot_id};{cutoff}",
"response": "application/json",
}
return bindingdb_query("getLigandsByUniprot", params)
# Example: Get all compounds binding ABL1 (imatinib target) at <=100 nM
ligands = get_ligands_for_target("P00519", cutoff=100)
# Response shape (verified 2026-09): one top-level key, spelled
# "getLindsByUniprotResponse" (sic — getTargetByCompound uses the same key),
# holding "bdb.hit" (count, as a string) and "bdb.affinities": a list of
# {"bdb.monomerid", "bdb.smile", "bdb.affinity_type", "bdb.affinity"}.
# Affinities are strings, may carry leading spaces or ">"/"<" qualifiers.
resp = next(iter(ligands.values()))
rows = resp.get("bdb.affinities", [])
3. SMILES によるクエリ(構造類似性)
def search_by_smiles(smiles, cutoff=0.85):
"""
Search BindingDB by SMILES string (structural-similarity search).
Args:
smiles: SMILES string of the compound
cutoff: Tanimoto similarity threshold (0.0-1.0; e.g. 0.85)
"""
params = {
"smiles": smiles,
"cutoff": cutoff,
"response": "application/json",
}
return bindingdb_query("getTargetByCompound", params)
# Example: structural-similarity search for imatinib's binding targets
result = search_by_smiles("Cc1ccc(NC(=O)c2ccc(CN3CCN(C)CC3)cc2)cc1Nc1nccc(-c2cccnc2)n1")
PubChem CID でクエリするには、まず PubChem PUG-REST を使って CID を SMILES 文字列に変換し、その後 search_by_smiles に渡します。BindingDB REST には、名前または CID による検索エンドポイントはありません。
4. ダウンロードによる解析(大規模なクエリに推奨)
包括的な解析には、BindingDB のデータを直接ダウンロードします。
import pandas as pd
def load_bindingdb(filepath="BindingDB_All.tsv"):
"""
Load BindingDB TSV file (the unzipped BindingDB_All_<YYYYMM>.tsv).
Download the dated BindingDB_All_<YYYYMM>_tsv.zip from:
https://www.bindingdb.org/rwd/bind/chemsearch/marvin/Download.jsp
"""
# Key columns
usecols = [
"BindingDB Reactant_set_id",
"Ligand SMILES",
"Ligand InChI",
"Ligand InChI Key",
"BindingDB Target Chain Sequence",
"PDB ID(s) for Ligand-Target Complex",
"UniProt (SwissProt) Entry Name of Target Chain",
"UniProt (SwissProt) Primary ID of Target Chain",
"UniProt (TrEMBL) Primary ID of Target Chain",
"Ki (nM)",
"IC50 (nM)",
"Kd (nM)",
"EC50 (nM)",
"kon (M-1-s-1)",
"koff (s-1)",
"Target Name",
"Target Source Organism According to Curator or DataSource",
"Number of Protein Chains in Target (>1 implies a multichain complex)",
"PubChem CID",
"PubChem SID",
"ChEMBL ID of Ligand",
"DrugBank ID of Ligand",
]
# Exact TSV headers drift between monthly releases (some contain double
# spaces), so intersect with the actual header rather than hard-failing.
header = pd.read_csv(filepath, sep="\t", nrows=0).columns
keep = [c for c in usecols if c in header]
df = pd.read_csv(filepath, sep="\t", usecols=keep,
low_memory=False, on_bad_lines='skip')
# Convert affinity columns to numeric
for col in ["Ki (nM)", "IC50 (nM)", "Kd (nM)", "EC50 (nM)"]:
if col in df.columns:
df[col] = pd.to_numeric(df[col], errors='coerce')
return df
def query_target_affinity(df, uniprot_id, affinity_types=None, max_nm=10000):
"""Query loaded BindingDB for a specific target."""
if affinity_types is None:
affinity_types = ["Ki (nM)", "IC50 (nM)", "Kd (nM)"]
# Filter by UniProt ID
mask = df["UniProt (SwissProt) Primary ID of Target Chain"] == uniprot_id
target_df = df[mask].copy()
# Filter by affinity cutoff
has_affinity = pd.Series(False, index=target_df.index)
for col in affinity_types:
if col in target_df.columns:
has_affinity |= target_df[col] <= max_nm
result = target_df[has_affinity][["Ligand SMILES"] + affinity_types +
["PubChem CID", "ChEMBL ID of Ligand"]].dropna(how='all')
return result.sort_values(affinity_types[0])
5. SAR 解析
import pandas as pd
def sar_analysis(df, target_uniprot, affinity_col="IC50 (nM)"):
"""
Structure-activity relationship analysis for a target.
Retrieves all compounds with affinity data and ranks by potency.
"""
target_data = query_target_affinity(df, target_uniprot, [affinity_col])
if target_data.empty:
return target_data
# Add pIC50 (negative log of IC50 in molar)
if affinity_col in target_data.columns:
target_data = target_data[target_data[affinity_col].notna()].copy()
target_data["pAffinity"] = -((target_data[affinity_col] * 1e-9).apply(
lambda x: __import__('math').log10(x)
))
target_data = target_data.sort_values("pAffinity", ascending=False)
return target_data
# Most potent compounds against EGFR (P00533)
# sar = sar_analysis(df, "P00533", "IC50 (nM)")
# print(sar.head(20))
6. ポリファーマコロジーのプロファイル
def polypharmacology_profile(df, ligand_smiles, affinity_cutoff_nM=1000):
"""
Find all targets a compound binds to, by exact SMILES match.
For tolerance to tautomers/salts/charge states, match on the InChIKey
skeleton (first 14 chars of "Ligand InChI Key") instead of raw SMILES.
"""
# Search by ligand SMILES (exact string match)
mask = df["Ligand SMILES"] == ligand_smiles
ligand_data = df[mask].copy()
# Filter by affinity
aff_cols = ["Ki (nM)", "IC50 (nM)", "Kd (nM)"]
has_aff = pd.Series(False, index=ligand_data.index)
for col in aff_cols:
if col in ligand_data.columns:
has_aff |= ligand_data[col] <= affinity_cutoff_nM
result = ligand_data[has_aff][
["Target Name", "UniProt (SwissProt) Primary ID of Target Chain"] + aff_cols
].dropna(how='all')
# Rank by the tightest measured constant per row (NaNs ignored)
result = result.assign(best_nM=result[aff_cols].min(axis=1))
return result.sort_values("best_nM")
クエリのワークフロー
ワークフロー 1:標的に対する最良の阻害剤を探す
import pandas as pd
def find_best_inhibitors(uniprot_id, affinity_type="IC50 (nM)", top_n=20):
"""Find the most potent inhibitors for a target in BindingDB."""
df = load_bindingdb("BindingDB_All.tsv") # Load once and reuse
result = query_target_affinity(df, uniprot_id, [affinity_type])
if result.empty:
print(f"No data found for {uniprot_id}")
return result
result = result.sort_values(affinity_type).head(top_n)
print(f"Top {top_n} inhibitors for {uniprot_id} by {affinity_type}:")
for _, row in result.iterrows():
print(f" {row['PubChem CID']}: {row[affinity_type]:.1f} nM | SMILES: {row['Ligand SMILES'][:40]}...")
return result
ワークフロー 2:選択性のプロファイリング
- すべての標的にわたる化合物の親和性データを取得します
- オンターゲットとオフターゲットの親和性比を比較します
- 選択性のクリフ(選択性を向上させる構造変化)を特定します
- ChEMBL と照合して、選択性に関する追加データを確認します
ワークフロー 3:機械学習データセットの準備
def prepare_ml_dataset(df, uniprot_ids, affinity_col="IC50 (nM)",
max_affinity_nM=100000, min_count=50):
"""Prepare BindingDB data for ML model training."""
records = []
for uid in uniprot_ids:
target_df = query_target_affinity(df, uid, [affinity_col], max_affinity_nM)
if len(target_df) >= min_count:
target_df = target_df.copy()
target_df["target"] = uid
records.append(target_df)
if not records:
return pd.DataFrame()
combined = pd.concat(records)
# Add pAffinity (normalized)
combined["pAffinity"] = -((combined[affinity_col] * 1e-9).apply(
lambda x: __import__('math').log10(max(x, 1e-12))
))
return combined[["Ligand SMILES", "target", "pAffinity", affinity_col]].dropna()
主なデータフィールド
| フィールド | 説明 |
|---|---|
Ligand SMILES | 化合物の2D構造 |
Ligand InChI Key | 一意の化学識別子 |
Ki (nM) | 阻害定数(平衡時、機能的) |
Kd (nM) | 解離定数(熱力学的、結合) |
IC50 (nM) | 50%阻害濃度 |
EC50 (nM) | 50%有効濃度 |
kon (M-1-s-1) | 結合速度定数 |
koff (s-1) | 解離速度定数 |
UniProt (SwissProt) Primary ID | 標的の UniProt アクセッション |
Target Name | タンパク質名 |
PDB ID(s) for Ligand-Target Complex | 結晶構造 |
PubChem CID | PubChem 化合物 ID |
ChEMBL ID of Ligand | ChEMBL 化合物 ID |
親和性の解釈
| 親和性 | 分類 | 薬物らしさ |
|---|---|---|
| < 1 nM | サブナノモル | 非常に強力(ピコモル範囲) |
| 1–10 nM | ナノモル | 強力で、承認薬に一般的な範囲 |
| 10–100 nM | 中程度 | 一般的なリード化合物 |
| 100–1000 nM | 弱い | フラグメント/出発点 |
| > 1000 nM | 非常に弱い | 一般に薬物としての関連性の基準を下回る |
ベストプラクティス
- 直接結合にはKiを使用:Kiは酵素の作用機序に依存せず、真の結合親和性を反映します
- IC50は状況に依存:IC50値は基質濃度によって変わります(Cheng-Prusoffの式)
- 修飾子の接頭辞に注意:TSVの親和性セルには、打ち切り測定値を示す
>、<、>=などの接頭辞が付いていることがよくあります(例:>10000)。pd.to_numeric(errors='coerce')を使うと、これらは警告なくNaNに変換されます。まず接頭辞を削除し(例:df[col].astype(str).str.lstrip("<>= "))、モデリングの前に打ち切り値を保持するか、除外するか、不等式として扱うかを明示的に決定してください - 単位を正規化:BindingDBの報告値はnMです。研究間で比較する際は単位を確認してください
- 標的生物種でフィルタリング:
Target Source Organismを使用して、ヒトタンパク質のデータを確保してください - 欠損値を処理:すべての化合物にすべての測定タイプの値があるわけではありません
- ChEMBLとの相互参照:ChEMBLには、メディシナルケミストリー向けに、より多くのキュレーション済み活性データがあります
追加リソース
- BindingDBのウェブサイト:https://www.bindingdb.org/
- データのダウンロード:https://www.bindingdb.org/rwd/bind/chemsearch/marvin/Download.jsp
- REST APIのドキュメント:https://www.bindingdb.org/rwd/bind/BindingDBRESTfulAPI.jsp (REST base: https://bindingdb.org/rest)
- 引用:Liu T et al. "BindingDB in 2024: a FAIR knowledgebase of protein-small molecule binding data." Nucleic Acids Research 2025;53(D1):D1633-D1644. doi:10.1093/nar/gkae1075 (earlier: Gilson MK et al., NAR 2016;44(D1):D1045-53, doi:10.1093/nar/gkv1072)
- 関連リソース:ChEMBL (https://www.ebi.ac.uk/chembl/)、PubChem BioAssay
スクリプト
scripts/query_bindingdb.py — BindingDB REST API用の実行可能なヘルパー(キー不要):
python scripts/query_bindingdb.py uniprot P00519 --cutoff 10000
python scripts/query_bindingdb.py pdb 1Q0L,3ANM --cutoff 100 --identity 92
python scripts/query_bindingdb.py compound "<SMILES>" --cutoff 0.85