mcpField
C
chembl-database-bioactivity

chembl-database-bioactivity

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

chembl-database-bioactivity について

chembl-database-bioactivityは、公開REST APIでChEMBLの化合物、標的、生物活性を検索するスキルです。創薬やケモインフォマティクスに向け、SDKや認証なしで構造検索や条件指定付きページングを利用できます。

主な機能

  1. 01名称、ID、物性による化合物検索
  2. 02標的と生物活性レコードの照会
  3. 03SMILESによる類似性・部分構造検索
  4. 04薬剤の作用機序と適応症の取得
  5. 05条件指定とページングによる結果整理

活用シーン

  1. 01標的に対する阻害活性の検索
  2. 02化合物系列間の構造活性相関の比較
  3. 03薬剤類似性の物性による分子の選別
  4. 04承認薬の作用機序と適応症の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/jaechang-hits/sciagent-skills --skill chembl-database-bioactivity

インストール後、Claude Code で/chembl-database-bioactivityを入力して読み込まれたか確認します。

詳細

ChEMBL Database — 生物活性クエリ

SDK がない理由は? chembl_webresource_client パッケージは、認証不要の公開 REST/JSON API(https://www.ebi.ac.uk/chembl/api/data/)を便利に利用するためのラッパーです。SDK が利用できない場合でも、すべての操作は通常の requests と URL パラメーターで再現できます。この SKILL.md では、requests がインストールされているあらゆる環境でコードを実行できるよう、全体を通して REST を使用しています。Django 形式のフィルター構文(field__icontains=…、field__lte=…、field__range=a,b)は、URL クエリパラメーターとして機能します。

概要

ChEMBL は EMBL-EBI の生物活性分子データベースです。200 万件以上の化合物、1,900 万件以上の生物活性測定値(IC50、Ki、EC50、Kd、…)、1 万 3,000 件以上のターゲットが登録されています。https://www.ebi.ac.uk/chembl/api/data/ の REST API は JSON(.json を追加)または XML/YAML を返し、認証は不要です。また、URL パラメーターによる Django 形式のクエリフィルターと、page_meta.next によるカーソル形式のページネーションに対応しています。

使用する場面

  • 名前、ChEMBL ID、または物理化学的特性で化合物を検索する
  • 特定のターゲットの生物活性データ(IC50、Ki、EC50)をクエリする
  • SMILES を使って類似性検索や部分構造検索を行う
  • 薬物の作用機序や臨床適応症を取得する
  • ターゲットに対する阻害剤、アゴニスト、生物活性分子を特定する
  • 化合物シリーズ全体の構造活性相関(SAR)を分析する
  • リピンスキーのルール・オブ・ファイブなど、薬物らしさの基準で分子をフィルタリングする
  • 一般的なケモインフォマティクス(SMILES の操作、フィンガープリント、記述子)には、代わりに rdkit-cheminformatics を使用してください
  • 別の化合物データベース(NIH、より広範な網羅性)を使う場合は、pubchem-compound-search を使用してください

前提条件

  • Python パッケージ:requests(唯一の必須パッケージ)。任意:表形式で分析する場合は pandas。
  • API キー不要:ChEMBL は無料で利用できます。
  • レート制限:公表された厳格な制限はありません。インフラストラクチャは共有されているため、一括処理のループではリクエスト間に time.sleep(0.2-0.5) を追加し、HTTP 429 が発生した場合はバックオフしてください。
pip install requests
# Optional, for DataFrame work:
pip install pandas

クイックスタート

import requests

BASE = "https://www.ebi.ac.uk/chembl/api/data"

# Retrieve a molecule by ChEMBL ID
r = requests.get(f"{BASE}/molecule/CHEMBL25.json", timeout=15)
r.raise_for_status()
aspirin = r.json()
print(f"{aspirin['pref_name']}: MW={aspirin['molecule_properties']['mw_freebase']}")
# ASPIRIN: MW=180.16

# Search targets by full name (acronyms like 'EGFR' don't match pref_name — use full term)
r = requests.get(
    f"{BASE}/target.json",
    params={"pref_name__icontains": "epidermal growth factor receptor",
            "target_type": "SINGLE PROTEIN", "limit": 5},
    timeout=15,
)
targets = r.json()["targets"]
print(f"EGFR-like targets: {len(targets)}, first={targets[0]['target_chembl_id']}")

# Potent bioactivities: EGFR (CHEMBL203) IC50 <= 100 nM
r = requests.get(
    f"{BASE}/activity.json",
    params={"target_chembl_id": "CHEMBL203",
            "standard_type": "IC50",
            "standard_value__lte": 100,
            "standard_units": "nM",
            "limit": 5},
    timeout=30,
)
data = r.json()
print(f"EGFR IC50 ≤ 100 nM records: {data['page_meta']['total_count']}")

主な概念

フィルター演算子(Django 形式、URL パラメーターとして指定)

SDK の field__operator=value 構文は、URL クエリパラメーターにそのまま対応します。フィルターを組み合わせるには & を使用してください。

演算子URL パターンURL の例
__exactfield=valuetarget_type=SINGLE+PROTEIN
__iexactfield__iexact=valuepref_name__iexact=aspirin
__contains / __icontainsfield__icontains=valuepref_name__icontains=kinase
__startswith / __endswithfield__startswith=Epipref_name__endswith=nib
__gt / __gte / __lt / __ltefield__lte=100standard_value__lte=100
__rangefield__range=lo,himolecule_properties__mw_freebase__range=300,500
__infield__in=a,b,cstandard_type__in=IC50,Ki,Kd
__isnullfield__isnull=False(Python の False / True 文字列)pchembl_value__isnull=False
__regexfield__regex=…pref_name__regex=^EGF.*kinase$
__searchfield__search=…description__search=apoptosis

requests.get(..., params={...}) に渡すと、ライブラリが URL エンコードを自動的に処理します(__range と __in のコンマを含む)。

コアエンドポイント

すべてのエンドポイントで、.json、.xml、.yaml のサフィックスを使用できます。以下では JSON をデフォルトとします。

エンドポイント URL返される内容主なフィールド
/molecule/{chembl_id}.jsonID で指定した化合物pref_name、molecule_chembl_id、molecule_properties、molecule_structures
/molecule.json?<filters>化合物検索ページ分割された molecules[]
/target/{chembl_id}.jsonID で指定した標的pref_name、target_type、organism、target_components
/target.json?<filters>標的検索ページ分割された targets[]
/activity.json?<filters>生物活性レコードページ分割された activities[]
/assay.json?<filters>アッセイの詳細ページ分割された assays[]
/drug.json?<filters>承認薬の情報drugs[]。ページ分割に対応。/drug/{chembl_id}.json も利用可能
/mechanism.json?<filters>作用機序ページ分割された mechanisms[]
/drug_indication.json?<filters>治療適応症ページ分割された drug_indications[]
/similarity/{smiles}/{tanimoto}.jsonタニモト類似度(0~100)similarity フィールドを含む、ページ分割された molecules[]
/substructure/{smiles}.json部分構造検索ページ分割された molecules[]
/image/{chembl_id}.svgSVG 構造画像バイナリ SVG(JSON ではありません)
/molecule_form/{chembl_id}.json親化合物/塩形molecule_forms[]
/protein_class.jsonタンパク質分類階層階層形式で参照
/document.json?<filters>文献ソースレコードページ分割された documents[]
レスポンスの形式
{
  "page_meta": {
    "limit": 20,
    "offset": 0,
    "total_count": 12145,
    "next": "/chembl/api/data/activity.json?...&offset=20",
    "previous": null
  },
  "activities": [ /* or molecules[], targets[], etc. */ ]
}

page_meta.next(相対 URL。先頭に https://www.ebi.ac.uk を付けます)が null になるまで、順にたどります。

分子特性

各レコードの molecule_properties から次のプロパティにアクセスできます。

フィールド説明
mw_freebase分子量(遊離塩基)
full_mwt全分子量(塩を含む)
alogp計算 LogP
hba水素結合受容体
hbd水素結合供与体
psa極性表面積
rtb回転可能結合
num_ro5_violationsリピンスキーの Rule of 5 違反数
ro3_passRule of 3 への適合
cx_most_apka / cx_most_bpka最も酸性/塩基性の pKa
標的情報のフィールド
フィールド説明
target_chembl_idChEMBL 標的識別子
pref_name優先名(標的の正式名称)。「EGFR」のような略称では一致しません。正式名称を使用してください
target_typeSINGLE PROTEIN、PROTEIN COMPLEX、ORGANISM、…
organism標的の生物種(例:Homo sapiens)
tax_idNCBI 分類 ID
target_components[]構成要素(UniProt アクセッション、配列、…)
生物活性データのフィールド
フィールド説明
standard_type活性の種類:IC50、Ki、Kd、EC50、…
standard_value活性の数値
standard_units単位:nM、uM、…
pchembl_value正規化された -log10 活性値(6 超は高活性)
activity_comment活性に関する注釈
data_validity_commentデータ品質フラグ(解析前に確認してください)
potential_duplicate重複フラグ

コア API

1. 分子クエリ
import requests
BASE = "https://www.ebi.ac.uk/chembl/api/data"

# By ChEMBL ID
r = requests.get(f"{BASE}/molecule/CHEMBL25.json", timeout=15)
aspirin = r.json()
print(f"{aspirin['pref_name']}: MW={aspirin['molecule_properties']['mw_freebase']}")

# By name (case-insensitive substring)
r = requests.get(f"{BASE}/molecule.json",
                 params={"pref_name__icontains": "imatinib", "limit": 5},
                 timeout=15)
for mol in r.json()["molecules"]:
    print(f"  {mol['molecule_chembl_id']}  {mol.get('pref_name')!r}")

# By Lipinski-compliant property ranges
r = requests.get(f"{BASE}/molecule.json",
                 params={"molecule_properties__mw_freebase__range": "300,500",
                         "molecule_properties__alogp__lte": 5,
                         "molecule_properties__hba__lte": 10,
                         "molecule_properties__hbd__lte": 5,
                         "limit": 3},
                 timeout=15)
print(f"Lipinski-compliant total: {r.json()['page_meta']['total_count']}")
2. 標的クエリ
import requests
BASE = "https://www.ebi.ac.uk/chembl/api/data"

# By ChEMBL ID
r = requests.get(f"{BASE}/target/CHEMBL203.json", timeout=15)
egfr = r.json()
print(f"{egfr['pref_name']} ({egfr['organism']}) — type={egfr['target_type']}")

# Search by full name (NOT acronym) + type
r = requests.get(f"{BASE}/target.json",
                 params={"pref_name__icontains": "kinase",
                         "target_type": "SINGLE PROTEIN", "limit": 5},
                 timeout=15)
d = r.json()
print(f"Kinase SINGLE_PROTEIN targets: total={d['page_meta']['total_count']}")
for t in d["targets"][:5]:
    print(f"  {t['target_chembl_id']:12s} {t.get('pref_name')!r}  ({t['organism']})")

# By organism
r = requests.get(f"{BASE}/target.json",
                 params={"organism": "Homo sapiens", "limit": 3},
                 timeout=15)
print(f"Human targets: total={r.json()['page_meta']['total_count']}")
3. 生物活性データ
import requests
BASE = "https://www.ebi.ac.uk/chembl/api/data"

# Potent inhibitors for a target (EGFR = CHEMBL203)
r = requests.get(f"{BASE}/activity.json",
                 params={"target_chembl_id": "CHEMBL203",
                         "standard_type": "IC50",
                         "standard_value__lte": 100,
                         "standard_units": "nM",
                         "limit": 5},
                 timeout=30)
data = r.json()
print(f"EGFR IC50≤100nM: total={data['page_meta']['total_count']}")
for act in data["activities"][:5]:
    print(f"  {act['molecule_chembl_id']:14s} IC50={act['standard_value']} nM "
          f"pChEMBL={act.get('pchembl_value')}")

# All pChEMBL-tagged activities for a compound
r = requests.get(f"{BASE}/activity.json",
                 params={"molecule_chembl_id": "CHEMBL25",
                         "pchembl_value__isnull": "False",
                         "limit": 5},
                 timeout=30)
print(f"Aspirin pChEMBL activities: total={r.json()['page_meta']['total_count']}")

# Multiple activity types (CHEMBL240 = D2 dopamine receptor)
r = requests.get(f"{BASE}/activity.json",
                 params={"target_chembl_id": "CHEMBL240",
                         "standard_type__in": "IC50,Ki,Kd",
                         "limit": 5},
                 timeout=30)
print(f"D2 receptor IC50/Ki/Kd: total={r.json()['page_meta']['total_count']}")
4. 構造ベースの検索
import requests
from urllib.parse import quote
BASE = "https://www.ebi.ac.uk/chembl/api/data"

# Similarity search (Tanimoto ≥ 85%)
# Path-style endpoint: /similarity/{smiles}/{threshold}
# The SMILES MUST be URL-encoded (it contains '/', '(', ')' etc.)
aspirin_smiles = quote("CC(=O)Oc1ccccc1C(=O)O", safe="")
r = requests.get(f"{BASE}/similarity/{aspirin_smiles}/85.json",
                 params={"limit": 5}, timeout=30)
data = r.json()
print(f"Similar to aspirin (≥85% Tanimoto): total={data['page_meta']['total_count']}")
for m in data["molecules"][:5]:
    print(f"  {m['molecule_chembl_id']}  similarity={m.get('similarity')}")
# Substructure search
benzimidazole = quote("c1ccc2[nH]cnc2c1", safe="")
r = requests.get(f"{BASE}/substructure/{benzimidazole}.json",
                 params={"limit": 3}, timeout=30)
print(f"Benzimidazole substructure total: {r.json()['page_meta']['total_count']}")
5. 薬剤と作用機序のデータ
import requests
BASE = "https://www.ebi.ac.uk/chembl/api/data"

# Drug record (max clinical phase, ATC class, etc.)
r = requests.get(f"{BASE}/drug/CHEMBL941.json", timeout=15)   # imatinib
drug = r.json()
print(f"Imatinib max_phase={drug.get('max_phase')}")

# Mechanisms of action — note: not every drug has mechanism records.
# Imatinib (CHEMBL941) returns 0 mechanism rows; sunitinib (CHEMBL535) has many.
r = requests.get(f"{BASE}/mechanism.json",
                 params={"molecule_chembl_id": "CHEMBL535"}, timeout=15)
for m in r.json()["mechanisms"]:
    print(f"  {m['mechanism_of_action']} → target {m.get('target_chembl_id')}")

# Therapeutic indications
r = requests.get(f"{BASE}/drug_indication.json",
                 params={"molecule_chembl_id": "CHEMBL941", "limit": 5},
                 timeout=15)
for ind in r.json()["drug_indications"]:
    print(f"  {ind.get('mesh_heading')!r}  max_phase_for_ind={ind.get('max_phase_for_ind')}")
# SVG molecular structure image — direct binary response, NOT JSON
# Do NOT call /image/{cid}.json — that endpoint raises JSONDecodeError.
r = requests.get(f"{BASE}/image/CHEMBL25.svg", timeout=15)
r.raise_for_status()
with open("aspirin.svg", "w") as f:
    f.write(r.text)
print(f"Saved aspirin.svg ({len(r.text)} bytes, looks_svg={'<svg' in r.text})")

一般的なワークフロー

ワークフロー 1:標的の阻害剤を検索する

注: pref_name__icontains は正式名称に一致します。'EGFR' や 'BRAF' のような略称では結果が 0 件になるため、'epidermal growth factor receptor' または 'B-raf'(ハイフンあり)を使用してください。

import requests, pandas as pd, time
BASE = "https://www.ebi.ac.uk/chembl/api/data"

# Step 1: Resolve the target by full name
r = requests.get(f"{BASE}/target.json",
                 params={"pref_name__icontains": "B-raf",
                         "target_type": "SINGLE PROTEIN", "limit": 5},
                 timeout=15)
targets = r.json()["targets"]
human_braf = next(t for t in targets if t["organism"] == "Homo sapiens")
target_id = human_braf["target_chembl_id"]
print(f"Using {target_id} — {human_braf['pref_name']}")

# Step 2: Paginate all potent IC50 activities (cap at 500 for demo)
url = (f"{BASE}/activity.json"
       f"?target_chembl_id={target_id}"
       f"&standard_type=IC50"
       f"&standard_value__lte=100"
       f"&standard_units=nM"
       f"&pchembl_value__isnull=False"
       f"&limit=200")
records = []
while url and len(records) < 500:
    r = requests.get(url, timeout=30)
    r.raise_for_status()
    data = r.json()
    records.extend(data["activities"])
    nxt = data["page_meta"].get("next")
    url = f"https://www.ebi.ac.uk{nxt}" if nxt else None
    time.sleep(0.2)

df = pd.DataFrame(records)
df["standard_value"] = pd.to_numeric(df["standard_value"])
print(f"Retrieved {len(df)} potent {target_id} compounds")
print(df[["molecule_chembl_id", "standard_value", "pchembl_value"]].head(10))
ワークフロー 2:既知の薬剤を解析する
import requests
BASE = "https://www.ebi.ac.uk/chembl/api/data"

# Sunitinib (CHEMBL535) — has documented mechanisms + indications.
# Imatinib (CHEMBL941) sometimes returns 0 mechanism rows depending on ChEMBL release.
chembl_id = "CHEMBL535"

# Molecule record
m = requests.get(f"{BASE}/molecule/{chembl_id}.json", timeout=15).json()
print(f"Name: {m['pref_name']}")
print(f"MW  : {m['molecule_properties']['mw_freebase']}")

# Mechanisms
mechs = requests.get(f"{BASE}/mechanism.json",
                     params={"molecule_chembl_id": chembl_id},
                     timeout=15).json()["mechanisms"]
for mc in mechs:
    print(f"  Mechanism: {mc['mechanism_of_action']}")

# Indications
inds = requests.get(f"{BASE}/drug_indication.json",
                    params={"molecule_chembl_id": chembl_id, "limit": 5},
                    timeout=15).json()["drug_indications"]
for ind in inds:
    print(f"  Indication: {ind.get('mesh_heading')}  "
          f"(Phase {ind.get('max_phase_for_ind')})")

# Bioactivity record count
total = requests.get(f"{BASE}/activity.json",
                     params={"molecule_chembl_id": chembl_id,
                             "pchembl_value__isnull": "False",
                             "limit": 1},
                     timeout=30).json()["page_meta"]["total_count"]
print(f"Total bioactivity records (pChEMBL-tagged): {total}")
ワークフロー 3:SAR 研究
import requests, pandas as pd, time
from urllib.parse import quote
BASE = "https://www.ebi.ac.uk/chembl/api/data"

# Step 1: Similar compounds to a lead (e.g., quinoline scaffold)
lead_smiles = "c1ccc2c(c1)cc(nc2N)c3ccc(cc3)NC(=O)c4ccccc4"
r = requests.get(f"{BASE}/similarity/{quote(lead_smiles, safe='')}/80.json",
                 params={"limit": 20}, timeout=30)
analogs = r.json()["molecules"]
print(f"Analogs found: {len(analogs)}")

# Step 2: Collect bioactivities for each analog
records = []
for compound in analogs[:20]:
    cid = compound["molecule_chembl_id"]
    acts = requests.get(f"{BASE}/activity.json",
                        params={"molecule_chembl_id": cid,
                                "standard_type": "IC50",
                                "pchembl_value__isnull": "False",
                                "limit": 20},
                        timeout=30).json()["activities"]
    for act in acts:
        records.append({
            "chembl_id": cid,
            "target": act.get("target_pref_name"),
            "IC50_nM": act.get("standard_value"),
            "pchembl": act.get("pchembl_value"),
            "mw":    (compound.get("molecule_properties") or {}).get("mw_freebase"),
            "alogp": (compound.get("molecule_properties") or {}).get("alogp"),
        })
    time.sleep(0.2)

df = pd.DataFrame(records)
if not df.empty:
    df["IC50_nM"] = pd.to_numeric(df["IC50_nM"])
    print(df.groupby("target")["IC50_nM"].describe())

よく使うレシピ

レシピ:バーチャルスクリーニング用フィルター(リピンスキーの Rule of 5)
import requests
BASE = "https://www.ebi.ac.uk/chembl/api/data"
r = requests.get(f"{BASE}/molecule.json",
                 params={"molecule_properties__mw_freebase__range": "300,500",
                         "molecule_properties__alogp__lte": 5,
                         "molecule_properties__hba__lte": 10,
                         "molecule_properties__hbd__lte": 5,
                         "molecule_properties__num_ro5_violations": 0,
                         "limit": 1},
                 timeout=15)
print(f"Drug-like candidates: {r.json()['page_meta']['total_count']}")
レシピ:活性データをページ分割して CSV に出力する
import requests, pandas as pd, time
BASE = "https://www.ebi.ac.uk/chembl/api/data"

url = (f"{BASE}/activity.json"
       f"?target_chembl_id=CHEMBL203"
       f"&standard_type=IC50"
       f"&pchembl_value__isnull=False"
       f"&limit=500")
all_acts = []
while url:
    r = requests.get(url, timeout=60)
    r.raise_for_status()
    data = r.json()
    all_acts.extend(data["activities"])
    nxt = data["page_meta"].get("next")
    url = f"https://www.ebi.ac.uk{nxt}" if nxt else None
    time.sleep(0.3)

df = pd.DataFrame(all_acts)
df.to_csv("egfr_activities.csv", index=False)
print(f"Exported {len(df)} records → egfr_activities.csv")
レシピ:リトライ機能付きの堅牢なセッション
import requests
from requests.adapters import HTTPAdapter
from urllib3.util.retry import Retry

def chembl_session(retries=3, backoff=1.0):
    s = requests.Session()
    s.headers.update({"Accept": "application/json"})
    s.mount("https://", HTTPAdapter(max_retries=Retry(
        total=retries, backoff_factor=backoff,
        status_forcelist=[429, 500, 502, 503, 504],
        allowed_methods=["GET"])))
    return s

session = chembl_session()
r = session.get("https://www.ebi.ac.uk/chembl/api/data/molecule/CHEMBL25.json", timeout=15)
print(r.json()["pref_name"])
レシピ:SVG 構造画像をダウンロードする
import requests
r = requests.get("https://www.ebi.ac.uk/chembl/api/data/image/CHEMBL25.svg", timeout=15)
r.raise_for_status()
with open("aspirin.svg", "w") as f:
    f.write(r.text)

主要なパラメーター

パラメーターエンドポイントデフォルト説明
limitすべてのリストエンドポイント20ページサイズ。最大 1000
offsetすべてのリストエンドポイント0ページネーションのオフセット(または page_meta.next をたどります)
formatすべてのエンドポイントjson(.json サフィックス経由).xml、.yaml も利用できます
pref_name__icontains/target、/molecule—名前全体に対する部分文字列検索です。略称は一致しないため、正式名称を使用してください
target_chembl_id/activity—例:CHEMBL203(EGFR)、CHEMBL240(D2 受容体)
molecule_chembl_id/activity、/mechanism、/drug_indication—例:CHEMBL25(アスピリン)
standard_type/activity—IC50、Ki、Kd、EC50
standard_value__lte/activity—活性値の最大値(standard_units と組み合わせて使用)
pchembl_value__isnull/activity—pChEMBL タグ付きデータを必須にするには "False" を指定します
target_type/target—SINGLE PROTEIN、PROTEIN COMPLEX、ORGANISM、…
{tanimoto}(パス)/similarity/{smiles}/{tanimoto}—Tanimoto 閾値(0~100)
{smiles}(パス)/similarity、/substructure—URL エンコードされた SMILES(urllib.parse.quote(s, safe=""))

トラブルシューティング

問題原因解決策
pref_name__icontains=EGFR(または BRAF)が 0 件を返すChEMBL では正式名称が保存されており、略称は一致しません"epidermal growth factor receptor" を使用してください。BRAF にはハイフン付きの "B-raf" を使用してください
mechanism.json?molecule_chembl_id=CHEMBL941 が空を返すすべてのリリースですべての薬剤にメカニズムの行があるわけではありません(例:現在のデータではイマチニブは 0 件です)データが登録されていることが分かっている例として、CHEMBL535(スニチニブ)または CHEMBL192(シルデナフィル)を使用してください
/image/{cid}.json で JSONDecodeError が発生する画像エンドポイントは JSON ではなくバイナリです必ず .svg または .png サフィックスを使用してください:/image/{cid}.svg
/molecule/{id} で 404 が発生するChEMBL ID の形式が無効ですID にはプレフィックスが必要です:25 ではなく CHEMBL25
類似性検索で 400 が発生するSMILES がエンコードされていません(/ が URL パスと衝突します)URL エンコードしてください:urllib.parse.quote(smiles, safe="")
total_count はより大きいのに next ページが空内部制限に達しました(offset ページネーションでは通常 10000 件です)フィルター(期間、標的クラス)を絞り込んで再度ページネーションを行ってください。または、10 万件を超えるレコードには ChEMBL FTP ダウンロードを使用してください
HTTP 429 Too Many Requestsリクエストの間隔が短すぎますtime.sleep(0.3) を追加し、Retry アダプターを設定してください(レシピを参照)
activity レコードの単位が混在しているアッセイによって nM/µM/阻害率(%)で報告されていますstandard_units="nM" でフィルターし、アッセイ間の比較には pchembl_value を優先してください
data_validity_comment が空ではないキュレーションフラグが設定されています(例:「転記ミスの可能性あり」、「通常の範囲外」)SAR/回帰分析の前にこれらの行を除外してください
活性レコードが重複している同じ測定値が複数のソースで報告されていますpotential_duplicate=True を確認して重複を除去してください

ベストプラクティス

  • 複数の研究間で比較する場合は、pchembl_valueを使用してください。IC50/Ki/EC50を、比較可能な-log10スケールに正規化します。
  • 集計を計算する前に、必ずdata_validity_commentを確認してください。フラグ付きの行は分布を歪める可能性があります。
  • 活性クエリでは、nMとµMが混在しないよう、standard_units="nM"を指定してください。
  • offsetを手動で増やす代わりに、ページネーションではpage_meta.nextに従ってください。URLに適切なカーソルがすでに含まれています。
  • パス形式のエンドポイント(/similarity/{smiles}/...、/substructure/{smiles})では、urllib.parse.quote(smi, safe="")を使用してSMILESをURLエンコードしてください。
  • バッチ処理では、リトライアダプターを設定したSessionを使用してください(レシピを参照)。ChEMBLはかなりのトラフィックを処理しており、502/503を返すことがあります。
  • 10万件を超えるレコードの場合は、ページネーション付きのAPI呼び出しよりもChEMBL FTP ダウンロードを利用してください。
  • pref_name__icontainsでの略語の使用には注意してください。EGFR、BRAF、HER2はいずれも検索結果が0件になります。正式名称を使用するか、代わりにtarget_components__accession=<UniProt>で絞り込んでください。

関連スキル

  • rdkit-cheminformatics — SMILESの操作、フィンガープリント、記述子
  • datamol-cheminformatics — 分子の前処理と特徴量化
  • pubchem-compound-search — 代替の化合物データベース(NIH。対象範囲はより広いものの、生物活性の情報は少なめです)
  • pdb-database — RCSB PDB REST APIを介したChEMBLターゲットの3D構造
  • opentargets-database — ChEMBLの医薬品とターゲットのエビデンスを疾患との関連付けに紐付けます

参考資料

コメント