@nahisaho/satori 0.12.0 → 0.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +150 -54
- package/package.json +1 -1
- package/src/.github/skills/scientific-biomedical-pubtator/SKILL.md +331 -0
- package/src/.github/skills/scientific-biothings-idmapping/SKILL.md +298 -0
- package/src/.github/skills/scientific-cell-line-resources/SKILL.md +258 -0
- package/src/.github/skills/scientific-compound-screening/SKILL.md +245 -0
- package/src/.github/skills/scientific-ebi-databases/SKILL.md +280 -0
- package/src/.github/skills/scientific-genome-sequence-tools/SKILL.md +304 -0
- package/src/.github/skills/scientific-healthcare-ai/SKILL.md +273 -0
- package/src/.github/skills/scientific-human-protein-atlas/SKILL.md +244 -0
- package/src/.github/skills/scientific-metabolic-modeling/SKILL.md +288 -0
- package/src/.github/skills/scientific-noncoding-rna/SKILL.md +262 -0
- package/src/.github/skills/scientific-ontology-enrichment/SKILL.md +340 -0
- package/src/.github/skills/scientific-pharmacology-targets/SKILL.md +323 -0
- package/src/.github/skills/scientific-phylogenetics/SKILL.md +297 -0
- package/src/.github/skills/scientific-preprint-archive/SKILL.md +476 -0
- package/src/.github/skills/scientific-public-health-data/SKILL.md +322 -0
- package/src/.github/skills/scientific-rare-disease-genetics/SKILL.md +327 -0
- package/src/.github/skills/scientific-regulatory-genomics/SKILL.md +274 -0
- package/src/.github/skills/scientific-reinforcement-learning/SKILL.md +280 -0
- package/src/.github/skills/scientific-structural-proteomics/SKILL.md +317 -0
- package/src/.github/skills/scientific-symbolic-mathematics/SKILL.md +277 -0
|
@@ -0,0 +1,340 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: scientific-ontology-enrichment
|
|
3
|
+
description: |
|
|
4
|
+
オントロジー・エンリッチメント解析スキル。EFO 実験ファクターオントロジー、
|
|
5
|
+
OLS オントロジー検索サービス、Enrichr 遺伝子セット濃縮解析、
|
|
6
|
+
UMLS メタシソーラス統一医学言語体系の統合パイプライン。
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Scientific Ontology Enrichment
|
|
10
|
+
|
|
11
|
+
EFO / OLS / Enrichr / UMLS を統合した
|
|
12
|
+
オントロジー検索・エンリッチメント解析パイプラインを提供する。
|
|
13
|
+
|
|
14
|
+
## When to Use
|
|
15
|
+
|
|
16
|
+
- EFO で実験条件 (疾患・細胞型・組織) のオントロジー ID を取得するとき
|
|
17
|
+
- OLS で複数オントロジー横断検索 (HP, MONDO, DOID, GO, CHEBI) するとき
|
|
18
|
+
- Enrichr で遺伝子リストの濃縮解析を行うとき
|
|
19
|
+
- UMLS CUI で異なる用語体系間のマッピングを行うとき
|
|
20
|
+
- GWAS Catalog の trait を EFO 用語で標準化するとき
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
## 1. EFO 実験ファクターオントロジー
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
import requests
|
|
30
|
+
import pandas as pd
|
|
31
|
+
|
|
32
|
+
OLS_API = "https://www.ebi.ac.uk/ols4/api"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def search_efo(query, exact=False):
|
|
36
|
+
"""
|
|
37
|
+
EFO (Experimental Factor Ontology) 検索。
|
|
38
|
+
|
|
39
|
+
Parameters:
|
|
40
|
+
query: str — 検索語 (疾患名、細胞型、組織名等)
|
|
41
|
+
exact: bool — 完全一致検索
|
|
42
|
+
|
|
43
|
+
ToolUniverse:
|
|
44
|
+
EFO_search(query=query, exact=exact)
|
|
45
|
+
"""
|
|
46
|
+
params = {
|
|
47
|
+
"q": query,
|
|
48
|
+
"ontology": "efo",
|
|
49
|
+
"exact": str(exact).lower(),
|
|
50
|
+
"rows": 30,
|
|
51
|
+
}
|
|
52
|
+
resp = requests.get(f"{OLS_API}/search", params=params)
|
|
53
|
+
resp.raise_for_status()
|
|
54
|
+
data = resp.json()
|
|
55
|
+
|
|
56
|
+
results = []
|
|
57
|
+
for doc in data.get("response", {}).get("docs", []):
|
|
58
|
+
results.append({
|
|
59
|
+
"efo_id": doc.get("obo_id", ""),
|
|
60
|
+
"label": doc.get("label", ""),
|
|
61
|
+
"description": (doc.get("description") or [""])[0][:200],
|
|
62
|
+
"iri": doc.get("iri", ""),
|
|
63
|
+
"ontology": doc.get("ontology_name", ""),
|
|
64
|
+
"is_defining_ontology": doc.get("is_defining_ontology", False),
|
|
65
|
+
"synonyms": doc.get("synonym", []),
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
df = pd.DataFrame(results)
|
|
69
|
+
print(f"EFO search '{query}': {len(df)} terms")
|
|
70
|
+
return df
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## 2. OLS マルチオントロジー検索
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
def search_ols(query, ontologies=None, type_filter=None):
|
|
77
|
+
"""
|
|
78
|
+
OLS (Ontology Lookup Service) マルチオントロジー横断検索。
|
|
79
|
+
|
|
80
|
+
Parameters:
|
|
81
|
+
query: str — 検索語
|
|
82
|
+
ontologies: list — オントロジー ID リスト (e.g., ["hp", "mondo", "go"])
|
|
83
|
+
type_filter: str — "class", "property", "individual"
|
|
84
|
+
|
|
85
|
+
ToolUniverse:
|
|
86
|
+
OLS_search(query=query, ontology=ontology)
|
|
87
|
+
OLS_get_term(ontology=ontology, iri=iri)
|
|
88
|
+
OLS_get_ancestors(ontology=ontology, iri=iri)
|
|
89
|
+
"""
|
|
90
|
+
params = {"q": query, "rows": 50}
|
|
91
|
+
if ontologies:
|
|
92
|
+
params["ontology"] = ",".join(ontologies)
|
|
93
|
+
if type_filter:
|
|
94
|
+
params["type"] = type_filter
|
|
95
|
+
|
|
96
|
+
resp = requests.get(f"{OLS_API}/search", params=params)
|
|
97
|
+
resp.raise_for_status()
|
|
98
|
+
data = resp.json()
|
|
99
|
+
|
|
100
|
+
results = []
|
|
101
|
+
for doc in data.get("response", {}).get("docs", []):
|
|
102
|
+
results.append({
|
|
103
|
+
"obo_id": doc.get("obo_id", ""),
|
|
104
|
+
"label": doc.get("label", ""),
|
|
105
|
+
"ontology": doc.get("ontology_name", ""),
|
|
106
|
+
"description": (doc.get("description") or [""])[0][:200],
|
|
107
|
+
"iri": doc.get("iri", ""),
|
|
108
|
+
"synonyms": doc.get("synonym", []),
|
|
109
|
+
"has_children": doc.get("has_children", False),
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
df = pd.DataFrame(results)
|
|
113
|
+
print(f"OLS search '{query}' "
|
|
114
|
+
f"[{','.join(ontologies) if ontologies else 'all'}]: "
|
|
115
|
+
f"{len(df)} terms")
|
|
116
|
+
return df
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
def get_ols_term_hierarchy(ontology, term_id):
|
|
120
|
+
"""
|
|
121
|
+
OLS 用語の階層構造 (ancestors/descendants) 取得。
|
|
122
|
+
|
|
123
|
+
Parameters:
|
|
124
|
+
ontology: str — オントロジー ID (e.g., "hp", "go")
|
|
125
|
+
term_id: str — OBO ID (e.g., "HP:0001250")
|
|
126
|
+
"""
|
|
127
|
+
iri = f"http://purl.obolibrary.org/obo/{term_id.replace(':', '_')}"
|
|
128
|
+
encoded_iri = requests.utils.quote(requests.utils.quote(iri, safe=""), safe="")
|
|
129
|
+
|
|
130
|
+
# Ancestors
|
|
131
|
+
anc_resp = requests.get(
|
|
132
|
+
f"{OLS_API}/ontologies/{ontology}/terms/{encoded_iri}/ancestors"
|
|
133
|
+
)
|
|
134
|
+
|
|
135
|
+
# Descendants
|
|
136
|
+
desc_resp = requests.get(
|
|
137
|
+
f"{OLS_API}/ontologies/{ontology}/terms/{encoded_iri}/descendants"
|
|
138
|
+
)
|
|
139
|
+
|
|
140
|
+
hierarchy = {"ancestors": [], "descendants": []}
|
|
141
|
+
|
|
142
|
+
if anc_resp.status_code == 200:
|
|
143
|
+
for t in anc_resp.json().get("_embedded", {}).get("terms", []):
|
|
144
|
+
hierarchy["ancestors"].append({
|
|
145
|
+
"id": t.get("obo_id", ""),
|
|
146
|
+
"label": t.get("label", ""),
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
if desc_resp.status_code == 200:
|
|
150
|
+
for t in desc_resp.json().get("_embedded", {}).get("terms", []):
|
|
151
|
+
hierarchy["descendants"].append({
|
|
152
|
+
"id": t.get("obo_id", ""),
|
|
153
|
+
"label": t.get("label", ""),
|
|
154
|
+
})
|
|
155
|
+
|
|
156
|
+
print(f"OLS hierarchy {term_id}: "
|
|
157
|
+
f"{len(hierarchy['ancestors'])} ancestors, "
|
|
158
|
+
f"{len(hierarchy['descendants'])} descendants")
|
|
159
|
+
return hierarchy
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
## 3. Enrichr 遺伝子セット濃縮解析
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
ENRICHR_API = "https://maayanlab.cloud/Enrichr"
|
|
166
|
+
|
|
167
|
+
|
|
168
|
+
def run_enrichr(gene_list, description="", gene_set_libraries=None):
|
|
169
|
+
"""
|
|
170
|
+
Enrichr 遺伝子リスト濃縮解析。
|
|
171
|
+
|
|
172
|
+
Parameters:
|
|
173
|
+
gene_list: list — 遺伝子シンボルリスト (e.g., ["TP53", "BRCA1", "EGFR"])
|
|
174
|
+
description: str — 解析の説明
|
|
175
|
+
gene_set_libraries: list — 使用する遺伝子セットライブラリ
|
|
176
|
+
|
|
177
|
+
ToolUniverse:
|
|
178
|
+
Enrichr_submit_gene_list(genes=gene_list)
|
|
179
|
+
Enrichr_get_enrichment(user_list_id=id, library=library)
|
|
180
|
+
"""
|
|
181
|
+
if gene_set_libraries is None:
|
|
182
|
+
gene_set_libraries = [
|
|
183
|
+
"GO_Biological_Process_2023",
|
|
184
|
+
"GO_Molecular_Function_2023",
|
|
185
|
+
"KEGG_2021_Human",
|
|
186
|
+
"Reactome_2022",
|
|
187
|
+
"WikiPathway_2023_Human",
|
|
188
|
+
"DisGeNET",
|
|
189
|
+
]
|
|
190
|
+
|
|
191
|
+
# Submit gene list
|
|
192
|
+
genes_str = "\n".join(gene_list)
|
|
193
|
+
submit_resp = requests.post(
|
|
194
|
+
f"{ENRICHR_API}/addList",
|
|
195
|
+
files={"list": (None, genes_str), "description": (None, description)},
|
|
196
|
+
)
|
|
197
|
+
submit_resp.raise_for_status()
|
|
198
|
+
user_list_id = submit_resp.json().get("userListId")
|
|
199
|
+
print(f"Enrichr: submitted {len(gene_list)} genes (ID={user_list_id})")
|
|
200
|
+
|
|
201
|
+
# Get enrichment results per library
|
|
202
|
+
all_results = {}
|
|
203
|
+
for library in gene_set_libraries:
|
|
204
|
+
enrich_resp = requests.get(
|
|
205
|
+
f"{ENRICHR_API}/enrich",
|
|
206
|
+
params={"userListId": user_list_id, "backgroundType": library},
|
|
207
|
+
)
|
|
208
|
+
enrich_resp.raise_for_status()
|
|
209
|
+
data = enrich_resp.json()
|
|
210
|
+
|
|
211
|
+
results = []
|
|
212
|
+
for term_data in data.get(library, []):
|
|
213
|
+
results.append({
|
|
214
|
+
"rank": term_data[0],
|
|
215
|
+
"term": term_data[1],
|
|
216
|
+
"p_value": term_data[2],
|
|
217
|
+
"z_score": term_data[3],
|
|
218
|
+
"combined_score": term_data[4],
|
|
219
|
+
"overlap_genes": term_data[5],
|
|
220
|
+
"adjusted_p": term_data[6],
|
|
221
|
+
})
|
|
222
|
+
|
|
223
|
+
df = pd.DataFrame(results)
|
|
224
|
+
if not df.empty:
|
|
225
|
+
df = df.sort_values("adjusted_p")
|
|
226
|
+
all_results[library] = df
|
|
227
|
+
sig_count = (df["adjusted_p"] < 0.05).sum() if not df.empty else 0
|
|
228
|
+
print(f" {library}: {sig_count} significant terms (FDR < 0.05)")
|
|
229
|
+
|
|
230
|
+
return all_results
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## 4. UMLS メタシソーラスマッピング
|
|
234
|
+
|
|
235
|
+
```python
|
|
236
|
+
UMLS_API = "https://uts-ws.nlm.nih.gov/rest"
|
|
237
|
+
|
|
238
|
+
|
|
239
|
+
def search_umls(query, api_key, search_type="words"):
|
|
240
|
+
"""
|
|
241
|
+
UMLS メタシソーラス検索。
|
|
242
|
+
|
|
243
|
+
Parameters:
|
|
244
|
+
query: str — 検索語 (疾患名、症状、薬剤名)
|
|
245
|
+
api_key: str — UMLS API キー
|
|
246
|
+
search_type: str — "words", "exact", "leftTruncation"
|
|
247
|
+
|
|
248
|
+
ToolUniverse:
|
|
249
|
+
UMLS_search(query=query, search_type=search_type)
|
|
250
|
+
UMLS_get_concept(cui=cui)
|
|
251
|
+
"""
|
|
252
|
+
params = {
|
|
253
|
+
"string": query,
|
|
254
|
+
"searchType": search_type,
|
|
255
|
+
"apiKey": api_key,
|
|
256
|
+
"pageSize": 25,
|
|
257
|
+
}
|
|
258
|
+
resp = requests.get(f"{UMLS_API}/search/current", params=params)
|
|
259
|
+
resp.raise_for_status()
|
|
260
|
+
data = resp.json()
|
|
261
|
+
|
|
262
|
+
results = []
|
|
263
|
+
for item in data.get("result", {}).get("results", []):
|
|
264
|
+
results.append({
|
|
265
|
+
"cui": item.get("ui", ""),
|
|
266
|
+
"name": item.get("name", ""),
|
|
267
|
+
"root_source": item.get("rootSource", ""),
|
|
268
|
+
"uri": item.get("uri", ""),
|
|
269
|
+
})
|
|
270
|
+
|
|
271
|
+
df = pd.DataFrame(results)
|
|
272
|
+
print(f"UMLS search '{query}': {len(df)} concepts")
|
|
273
|
+
return df
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
def get_umls_crosswalk(cui, api_key, target_source=None):
|
|
277
|
+
"""
|
|
278
|
+
UMLS CUI からの用語体系間マッピング。
|
|
279
|
+
|
|
280
|
+
Parameters:
|
|
281
|
+
cui: str — UMLS CUI (e.g., "C0023264")
|
|
282
|
+
api_key: str — UMLS API キー
|
|
283
|
+
target_source: str — ターゲット用語体系 (e.g., "SNOMEDCT_US", "ICD10CM", "MeSH")
|
|
284
|
+
"""
|
|
285
|
+
params = {"apiKey": api_key, "pageSize": 100}
|
|
286
|
+
if target_source:
|
|
287
|
+
params["sabs"] = target_source
|
|
288
|
+
|
|
289
|
+
resp = requests.get(f"{UMLS_API}/content/current/CUI/{cui}/atoms", params=params)
|
|
290
|
+
resp.raise_for_status()
|
|
291
|
+
data = resp.json()
|
|
292
|
+
|
|
293
|
+
mappings = []
|
|
294
|
+
for atom in data.get("result", []):
|
|
295
|
+
mappings.append({
|
|
296
|
+
"source": atom.get("rootSource", ""),
|
|
297
|
+
"code": atom.get("sourceConcept", ""),
|
|
298
|
+
"name": atom.get("name", ""),
|
|
299
|
+
"term_type": atom.get("termType", ""),
|
|
300
|
+
})
|
|
301
|
+
|
|
302
|
+
df = pd.DataFrame(mappings)
|
|
303
|
+
if target_source:
|
|
304
|
+
df = df[df["source"] == target_source]
|
|
305
|
+
|
|
306
|
+
print(f"UMLS crosswalk {cui}: {len(df)} mappings "
|
|
307
|
+
f"({target_source or 'all sources'})")
|
|
308
|
+
return df
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
---
|
|
312
|
+
|
|
313
|
+
## 利用可能ツール
|
|
314
|
+
|
|
315
|
+
| ToolUniverse カテゴリ | 主なツール |
|
|
316
|
+
|---|---|
|
|
317
|
+
| `efo` | `EFO_search` |
|
|
318
|
+
| `ols` | `OLS_search`, `OLS_get_term`, `OLS_get_ancestors` |
|
|
319
|
+
| `enrichr` | `Enrichr_submit_gene_list`, `Enrichr_get_enrichment` |
|
|
320
|
+
| `umls` | `UMLS_search`, `UMLS_get_concept` |
|
|
321
|
+
|
|
322
|
+
## パイプライン出力
|
|
323
|
+
|
|
324
|
+
| 出力ファイル | 説明 | 連携先スキル |
|
|
325
|
+
|---|---|---|
|
|
326
|
+
| `results/efo_terms.csv` | EFO 標準化用語 | → disease-research, gene-expression |
|
|
327
|
+
| `results/enrichr_results/` | 遺伝子セット濃縮結果 | → pathway-enrichment, multi-omics |
|
|
328
|
+
| `results/umls_mapping.json` | UMLS 用語マッピング | → clinical-decision-support, public-health-data |
|
|
329
|
+
| `results/ontology_hierarchy.json` | オントロジー階層 | → text-mining-nlp, knowledge-graph |
|
|
330
|
+
|
|
331
|
+
## パイプライン統合
|
|
332
|
+
|
|
333
|
+
```
|
|
334
|
+
disease-research ──→ ontology-enrichment ──→ pathway-enrichment
|
|
335
|
+
(GWAS/DisGeNET) (EFO/OLS/UMLS/Enrichr) (KEGG/Reactome/GO)
|
|
336
|
+
│
|
|
337
|
+
├──→ biothings-idmapping (CUI→Gene→Protein)
|
|
338
|
+
├──→ public-health-data (UMLS→RxNorm)
|
|
339
|
+
└──→ clinical-reporting (SNOMED/ICD マッピング)
|
|
340
|
+
```
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: scientific-pharmacology-targets
|
|
3
|
+
description: |
|
|
4
|
+
薬理学的ターゲットプロファイリングスキル。BindingDB 結合親和性、
|
|
5
|
+
GPCRdb GPCR 構造-活性、GtoPdb 薬理学、BRENDA 酵素動態、
|
|
6
|
+
Pharos 未解明ターゲット(TDL)の統合解析パイプライン。
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Scientific Pharmacology Targets
|
|
10
|
+
|
|
11
|
+
複数の薬理学データベース (BindingDB, GPCRdb, GtoPdb, BRENDA, Pharos) を
|
|
12
|
+
統合した包括的ターゲットプロファイリングパイプラインを提供する。
|
|
13
|
+
|
|
14
|
+
## When to Use
|
|
15
|
+
|
|
16
|
+
- 特定タンパク質の既知リガンド・結合親和性を調べるとき
|
|
17
|
+
- GPCR のリガンド・変異・構造情報を取得するとき
|
|
18
|
+
- 薬物-ターゲット相互作用のデータベース横断検索を行うとき
|
|
19
|
+
- 酵素阻害剤データ (BRENDA) を調べるとき
|
|
20
|
+
- 未解明ターゲット (Tdark/Tbio) のドラッガビリティを評価するとき
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
## 1. BindingDB 結合親和性データ取得
|
|
27
|
+
|
|
28
|
+
```python
|
|
29
|
+
import requests
|
|
30
|
+
import pandas as pd
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def get_bindingdb_ligands(uniprot_id, cutoff=None):
|
|
34
|
+
"""
|
|
35
|
+
BindingDB から UniProt ID ベースのリガンド結合データを取得。
|
|
36
|
+
|
|
37
|
+
Parameters:
|
|
38
|
+
uniprot_id: str — UniProt accession (e.g., "P00533")
|
|
39
|
+
cutoff: float | None — affinity cutoff nM
|
|
40
|
+
|
|
41
|
+
ToolUniverse:
|
|
42
|
+
BindingDB_get_ligands_by_uniprot(uniprot_id=uniprot_id)
|
|
43
|
+
BindingDB_get_targets_by_compound(smiles=smiles)
|
|
44
|
+
"""
|
|
45
|
+
url = "https://bindingdb.org/axis2/services/BDBService"
|
|
46
|
+
params = {
|
|
47
|
+
"uniprot": uniprot_id,
|
|
48
|
+
"response": "json",
|
|
49
|
+
}
|
|
50
|
+
if cutoff:
|
|
51
|
+
params["cutoff"] = cutoff
|
|
52
|
+
|
|
53
|
+
resp = requests.get(f"{url}/getLigandsByUniprot", params=params)
|
|
54
|
+
resp.raise_for_status()
|
|
55
|
+
data = resp.json()
|
|
56
|
+
|
|
57
|
+
ligands = data.get("getLigandsByUniprotResponse", {}).get("affinities", [])
|
|
58
|
+
results = []
|
|
59
|
+
for lig in ligands:
|
|
60
|
+
results.append({
|
|
61
|
+
"monomer_id": lig.get("monomerid", ""),
|
|
62
|
+
"smiles": lig.get("smiles", ""),
|
|
63
|
+
"affinity_type": lig.get("affinity_type", ""),
|
|
64
|
+
"affinity_value_nm": lig.get("affinity", ""),
|
|
65
|
+
"source": lig.get("source", ""),
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
df = pd.DataFrame(results)
|
|
69
|
+
print(f"BindingDB '{uniprot_id}': {len(df)} ligands")
|
|
70
|
+
return df
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## 2. GPCRdb GPCR プロファイリング
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
def get_gpcrdb_profile(protein_entry):
|
|
77
|
+
"""
|
|
78
|
+
GPCRdb から GPCR のリガンド・変異・構造情報を取得。
|
|
79
|
+
|
|
80
|
+
Parameters:
|
|
81
|
+
protein_entry: str — GPCRdb entry name (e.g., "adrb2_human")
|
|
82
|
+
|
|
83
|
+
ToolUniverse:
|
|
84
|
+
GPCRdb_get_protein(entry_name=protein_entry)
|
|
85
|
+
GPCRdb_get_ligands(entry_name=protein_entry)
|
|
86
|
+
GPCRdb_get_mutations(entry_name=protein_entry)
|
|
87
|
+
GPCRdb_get_structures(entry_name=protein_entry)
|
|
88
|
+
GPCRdb_list_proteins()
|
|
89
|
+
"""
|
|
90
|
+
base = "https://gpcrdb.org/services"
|
|
91
|
+
|
|
92
|
+
# Protein info
|
|
93
|
+
resp_p = requests.get(f"{base}/protein/{protein_entry}/")
|
|
94
|
+
resp_p.raise_for_status()
|
|
95
|
+
protein = resp_p.json()
|
|
96
|
+
|
|
97
|
+
# Ligands
|
|
98
|
+
resp_l = requests.get(f"{base}/ligands/{protein_entry}/")
|
|
99
|
+
ligands = resp_l.json() if resp_l.status_code == 200 else []
|
|
100
|
+
|
|
101
|
+
# Mutations
|
|
102
|
+
resp_m = requests.get(f"{base}/mutants/{protein_entry}/")
|
|
103
|
+
mutations = resp_m.json() if resp_m.status_code == 200 else []
|
|
104
|
+
|
|
105
|
+
# Structures
|
|
106
|
+
resp_s = requests.get(f"{base}/structure/protein/{protein_entry}/")
|
|
107
|
+
structures = resp_s.json() if resp_s.status_code == 200 else []
|
|
108
|
+
|
|
109
|
+
profile = {
|
|
110
|
+
"entry_name": protein.get("entry_name", ""),
|
|
111
|
+
"name": protein.get("name", ""),
|
|
112
|
+
"family": protein.get("family", ""),
|
|
113
|
+
"species": protein.get("species", ""),
|
|
114
|
+
"num_ligands": len(ligands),
|
|
115
|
+
"num_mutations": len(mutations),
|
|
116
|
+
"num_structures": len(structures),
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
print(f"GPCRdb '{protein_entry}': "
|
|
120
|
+
f"{profile['num_ligands']} ligands, "
|
|
121
|
+
f"{profile['num_mutations']} mutations, "
|
|
122
|
+
f"{profile['num_structures']} structures")
|
|
123
|
+
return profile, ligands, mutations, structures
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## 3. GtoPdb 薬理学データ
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
def get_gtopdb_target_pharmacology(target_id):
|
|
130
|
+
"""
|
|
131
|
+
Guide to PHARMACOLOGY (GtoPdb) から
|
|
132
|
+
ターゲットの薬理学的相互作用データを取得。
|
|
133
|
+
|
|
134
|
+
ToolUniverse:
|
|
135
|
+
GtoPdb_get_target(target_id=target_id)
|
|
136
|
+
GtoPdb_get_target_interactions(target_id=target_id)
|
|
137
|
+
GtoPdb_get_ligand(ligand_id=ligand_id)
|
|
138
|
+
GtoPdb_search_interactions(query=query)
|
|
139
|
+
"""
|
|
140
|
+
base = "https://www.guidetopharmacology.org/services"
|
|
141
|
+
|
|
142
|
+
# Target info
|
|
143
|
+
resp_t = requests.get(f"{base}/targets/{target_id}")
|
|
144
|
+
resp_t.raise_for_status()
|
|
145
|
+
target = resp_t.json()
|
|
146
|
+
|
|
147
|
+
# Interactions
|
|
148
|
+
resp_i = requests.get(f"{base}/targets/{target_id}/interactions")
|
|
149
|
+
interactions = resp_i.json() if resp_i.status_code == 200 else []
|
|
150
|
+
|
|
151
|
+
results = []
|
|
152
|
+
for ix in interactions:
|
|
153
|
+
results.append({
|
|
154
|
+
"ligand_id": ix.get("ligandId", ""),
|
|
155
|
+
"ligand_name": ix.get("ligandName", ""),
|
|
156
|
+
"type": ix.get("type", ""),
|
|
157
|
+
"action": ix.get("action", ""),
|
|
158
|
+
"affinity_type": ix.get("affinityType", ""),
|
|
159
|
+
"affinity_median": ix.get("affinityMedian", ""),
|
|
160
|
+
"approved": ix.get("approvedDrug", False),
|
|
161
|
+
})
|
|
162
|
+
|
|
163
|
+
df = pd.DataFrame(results)
|
|
164
|
+
print(f"GtoPdb target {target_id} ({target.get('name', '')}): "
|
|
165
|
+
f"{len(df)} interactions")
|
|
166
|
+
return target, df
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
## 4. Pharos/TCRD 未解明ターゲット検索
|
|
170
|
+
|
|
171
|
+
```python
|
|
172
|
+
def search_pharos_targets(query, tdl=None):
|
|
173
|
+
"""
|
|
174
|
+
Pharos / TCRD からターゲット情報を取得。
|
|
175
|
+
Target Development Level (TDL) でフィルタ可能。
|
|
176
|
+
|
|
177
|
+
Parameters:
|
|
178
|
+
query: str — gene symbol or target name
|
|
179
|
+
tdl: str | None — "Tclin", "Tchem", "Tbio", "Tdark"
|
|
180
|
+
|
|
181
|
+
ToolUniverse:
|
|
182
|
+
Pharos_search_targets(q=query)
|
|
183
|
+
Pharos_get_target(q=query)
|
|
184
|
+
Pharos_get_tdl_summary()
|
|
185
|
+
Pharos_get_disease_targets(disease_name=disease_name)
|
|
186
|
+
"""
|
|
187
|
+
url = "https://pharos-api.ncats.io/graphql"
|
|
188
|
+
gql = """
|
|
189
|
+
query TargetSearch($term: String!, $top: Int) {
|
|
190
|
+
targets(filter: { term: $term }, top: $top) {
|
|
191
|
+
targets {
|
|
192
|
+
name
|
|
193
|
+
sym
|
|
194
|
+
uniprot { accession }
|
|
195
|
+
tdl
|
|
196
|
+
fam
|
|
197
|
+
novelty
|
|
198
|
+
jensenScore
|
|
199
|
+
diseaseCount
|
|
200
|
+
ligandCount
|
|
201
|
+
}
|
|
202
|
+
count
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
"""
|
|
206
|
+
variables = {"term": query, "top": 20}
|
|
207
|
+
resp = requests.post(url, json={"query": gql, "variables": variables})
|
|
208
|
+
resp.raise_for_status()
|
|
209
|
+
data = resp.json()["data"]["targets"]
|
|
210
|
+
|
|
211
|
+
results = []
|
|
212
|
+
for t in data["targets"]:
|
|
213
|
+
results.append({
|
|
214
|
+
"symbol": t.get("sym", ""),
|
|
215
|
+
"name": t.get("name", ""),
|
|
216
|
+
"uniprot": t.get("uniprot", {}).get("accession", ""),
|
|
217
|
+
"tdl": t.get("tdl", ""),
|
|
218
|
+
"family": t.get("fam", ""),
|
|
219
|
+
"novelty": t.get("novelty", 0),
|
|
220
|
+
"disease_count": t.get("diseaseCount", 0),
|
|
221
|
+
"ligand_count": t.get("ligandCount", 0),
|
|
222
|
+
})
|
|
223
|
+
|
|
224
|
+
df = pd.DataFrame(results)
|
|
225
|
+
if tdl:
|
|
226
|
+
df = df[df["tdl"] == tdl]
|
|
227
|
+
|
|
228
|
+
print(f"Pharos '{query}': {len(df)} targets"
|
|
229
|
+
f"{f' (TDL={tdl})' if tdl else ''}")
|
|
230
|
+
return df
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## 5. 統合ターゲットプロファイリング
|
|
234
|
+
|
|
235
|
+
```python
|
|
236
|
+
def integrated_target_profile(uniprot_id, gene_symbol):
|
|
237
|
+
"""
|
|
238
|
+
複数データベースを統合したターゲットプロファイル。
|
|
239
|
+
|
|
240
|
+
ToolUniverse (横断):
|
|
241
|
+
BindingDB_get_ligands_by_uniprot(uniprot_id)
|
|
242
|
+
Pharos_get_target(q=gene_symbol)
|
|
243
|
+
GtoPdb_get_targets() → GtoPdb_get_target_interactions()
|
|
244
|
+
"""
|
|
245
|
+
profile = {
|
|
246
|
+
"uniprot_id": uniprot_id,
|
|
247
|
+
"gene_symbol": gene_symbol,
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
# BindingDB ligands
|
|
251
|
+
try:
|
|
252
|
+
bdb_df = get_bindingdb_ligands(uniprot_id)
|
|
253
|
+
profile["bindingdb_ligand_count"] = len(bdb_df)
|
|
254
|
+
except Exception:
|
|
255
|
+
profile["bindingdb_ligand_count"] = 0
|
|
256
|
+
|
|
257
|
+
# Pharos TDL
|
|
258
|
+
try:
|
|
259
|
+
pharos_df = search_pharos_targets(gene_symbol)
|
|
260
|
+
if not pharos_df.empty:
|
|
261
|
+
row = pharos_df.iloc[0]
|
|
262
|
+
profile["tdl"] = row.get("tdl", "")
|
|
263
|
+
profile["novelty"] = row.get("novelty", 0)
|
|
264
|
+
except Exception:
|
|
265
|
+
profile["tdl"] = "Unknown"
|
|
266
|
+
|
|
267
|
+
print(f"Integrated profile {gene_symbol}: TDL={profile.get('tdl', '?')}, "
|
|
268
|
+
f"BindingDB={profile['bindingdb_ligand_count']} ligands")
|
|
269
|
+
return profile
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## References
|
|
273
|
+
|
|
274
|
+
### Output Files
|
|
275
|
+
|
|
276
|
+
| ファイル | 形式 |
|
|
277
|
+
|---|---|
|
|
278
|
+
| `results/bindingdb_ligands.csv` | CSV |
|
|
279
|
+
| `results/gpcrdb_profile.json` | JSON |
|
|
280
|
+
| `results/gtopdb_interactions.csv` | CSV |
|
|
281
|
+
| `results/pharos_targets.csv` | CSV |
|
|
282
|
+
| `results/integrated_target_profile.json` | JSON |
|
|
283
|
+
|
|
284
|
+
### 利用可能ツール
|
|
285
|
+
|
|
286
|
+
| カテゴリ | 主要ツール | 用途 |
|
|
287
|
+
|---|---|---|
|
|
288
|
+
| BindingDB | `BindingDB_get_ligands_by_uniprot` | UniProt→リガンド |
|
|
289
|
+
| BindingDB | `BindingDB_get_ligands_by_uniprots` | バッチ |
|
|
290
|
+
| BindingDB | `BindingDB_get_ligands_by_pdb` | PDB→リガンド |
|
|
291
|
+
| BindingDB | `BindingDB_get_targets_by_compound` | 化合物→ターゲット |
|
|
292
|
+
| GPCRdb | `GPCRdb_get_protein` | GPCR 詳細 |
|
|
293
|
+
| GPCRdb | `GPCRdb_get_ligands` | GPCR リガンド |
|
|
294
|
+
| GPCRdb | `GPCRdb_get_mutations` | GPCR 変異 |
|
|
295
|
+
| GPCRdb | `GPCRdb_get_structures` | GPCR 構造 |
|
|
296
|
+
| GPCRdb | `GPCRdb_list_proteins` | GPCR 一覧 |
|
|
297
|
+
| GtoPdb | `GtoPdb_get_target` | ターゲット情報 |
|
|
298
|
+
| GtoPdb | `GtoPdb_get_target_interactions` | 相互作用 |
|
|
299
|
+
| GtoPdb | `GtoPdb_get_ligand` | リガンド情報 |
|
|
300
|
+
| GtoPdb | `GtoPdb_get_targets` | ターゲット一覧 |
|
|
301
|
+
| GtoPdb | `GtoPdb_list_ligands` | リガンド一覧 |
|
|
302
|
+
| GtoPdb | `GtoPdb_get_disease` | 疾患関連 |
|
|
303
|
+
| GtoPdb | `GtoPdb_list_diseases` | 疾患一覧 |
|
|
304
|
+
| GtoPdb | `GtoPdb_search_interactions` | 相互作用検索 |
|
|
305
|
+
| BRENDA | `BRENDA_get_inhibitors` | 酵素阻害剤 |
|
|
306
|
+
| Pharos | `Pharos_search_targets` | ターゲット検索 |
|
|
307
|
+
| Pharos | `Pharos_get_target` | ターゲット詳細 |
|
|
308
|
+
| Pharos | `Pharos_get_tdl_summary` | TDL サマリー |
|
|
309
|
+
| Pharos | `Pharos_get_disease_targets` | 疾患→ターゲット |
|
|
310
|
+
|
|
311
|
+
### 参照スキル
|
|
312
|
+
|
|
313
|
+
| スキル | 関連 |
|
|
314
|
+
|---|---|
|
|
315
|
+
| `scientific-drug-target-interaction` | DTI 予測 |
|
|
316
|
+
| `scientific-compound-similarity` | 化合物類似性 |
|
|
317
|
+
| `scientific-compound-screening` | 化合物スクリーニング |
|
|
318
|
+
| `scientific-molecular-docking` | 分子ドッキング |
|
|
319
|
+
| `scientific-protein-interaction-network` | PPI ネットワーク |
|
|
320
|
+
|
|
321
|
+
### 依存パッケージ
|
|
322
|
+
|
|
323
|
+
`requests`, `pandas`
|