mcpField
A
alterlab-bindingdb

alterlab-bindingdb

github.com/alterlab-ieu数据与数据库7867 次安装5 周前更新
代码仓库

关于 alterlab-bindingdb

alterlab-bindingdb 是面向药物发现、药理学和计算化学研究的 BindingDB 数据查询与分析技能,可通过 REST API 或下载文件获取蛋白质与化合物的实测亲和力。它支持按 UniProt 靶点或 SMILES 查询,并提供 SAR、多靶点分析和机器学习数据准备方法。

主要功能

  1. 01通过 REST API 查询结合数据
  2. 02按 UniProt ID 搜索靶点配体
  3. 03按 SMILES 进行结构相似性搜索
  4. 04下载 TSV 进行批量分析
  5. 05分析 SAR 与多靶点结合

适用场景

  1. 01为蛋白靶点查找已知配体
  2. 02比较类似物的结合亲和力
  3. 03分析化合物的选择性与脱靶
  4. 04准备亲和力机器学习数据集

安装

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

$npx skills add https://github.com/alterlab-ieu/alterlab-academic-skills --skill alterlab-bindingdb

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

包含的文件

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

evals/
evals.json
references/
affinity_queries.md
scripts/
query_bindingdb.py

详细介绍

BindingDB 数据库

概述

BindingDB(https://www.bindingdb.org/)是主要的公开药物-蛋白质结合亲和力实测数据库。它包含约 320 万条结合数据记录,涉及约 140 万种化合物对约 11,500 个蛋白质靶标的测试结果(主页数据,2026-09),数据整理自科学文献和专利文献。BindingDB 存储定量结合测量值(Ki、Kd、IC50、EC50),这些数据对药物发现、药理学和计算化学研究至关重要。

关键资源:

何时使用此工具

在以下情况下使用 BindingDB:

  • 基于靶标的药物发现:哪些已知化合物能与某个蛋白质靶标结合?它们的亲和力如何?
  • SAR 分析:结构修饰会如何影响一系列类似物的结合亲和力?
  • 先导化合物分析:某个化合物会与哪些靶标结合(选择性/多药理学)?
  • 基准数据集:获取经过整理的蛋白质-配体亲和力数据,用于 ML 模型训练
  • 药物再利用分析:已获批药物是否会与非预期靶标结合?
  • 竞品分析:某类靶标报道的最佳亲和力是多少?
  • 片段筛选:查找针对某个靶标的片段验证结合数据
不适用场景
场景请改用
大规模整理生物活性数据、检测元数据、药物作用机制alterlab-chembl
按名称或 CID 查询化合物标识符/属性、PubChem BioAssayalterlab-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 参数,格式为 <UniProt accession>;<cutoff in nM>,例如 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:选择性分析
  1. 获取化合物针对所有靶标的亲和力数据
  2. 比较目标靶标与脱靶靶标之间的亲和力比值
  3. 找出选择性差异显著的情况(可提高选择性的结构变化)
  4. 交叉参照 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)半数最大抑制浓度
EC50 (nM)半数最大有效浓度
kon (M-1-s-1)结合速率常数
koff (s-1)解离速率常数
UniProt (SwissProt) Primary ID靶标 UniProt 登录号
Target Name蛋白质名称
PDB ID(s) for Ligand-Target Complex晶体结构
PubChem CIDPubChem 化合物 ID
ChEMBL ID of LigandChEMBL 化合物 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 收录了更多经过整理的药物化学活性数据

其他资源

脚本

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

评论

支持 Markdown