@nahisaho/satori 0.14.0 → 0.16.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 +72 -30
- package/package.json +1 -1
- package/src/.github/skills/scientific-advanced-imaging/SKILL.md +382 -0
- package/src/.github/skills/scientific-chembl-assay-mining/SKILL.md +509 -0
- package/src/.github/skills/scientific-data-submission/SKILL.md +357 -0
- package/src/.github/skills/scientific-deep-chemistry/SKILL.md +350 -0
- package/src/.github/skills/scientific-ensembl-genomics/SKILL.md +378 -0
- package/src/.github/skills/scientific-expression-comparison/SKILL.md +303 -0
- package/src/.github/skills/scientific-gpu-singlecell/SKILL.md +296 -0
- package/src/.github/skills/scientific-marine-ecology/SKILL.md +429 -0
- package/src/.github/skills/scientific-md-simulation/SKILL.md +315 -0
- package/src/.github/skills/scientific-model-organism-db/SKILL.md +329 -0
- package/src/.github/skills/scientific-nci60-screening/SKILL.md +307 -0
- package/src/.github/skills/scientific-perturbation-analysis/SKILL.md +297 -0
- package/src/.github/skills/scientific-plant-biology/SKILL.md +321 -0
- package/src/.github/skills/scientific-rrna-taxonomy/SKILL.md +379 -0
- package/src/.github/skills/scientific-scatac-signac/SKILL.md +300 -0
- package/src/.github/skills/scientific-scvi-integration/SKILL.md +344 -0
- package/src/.github/skills/scientific-string-network-api/SKILL.md +376 -0
- package/src/.github/skills/scientific-toxicology-env/SKILL.md +309 -0
|
@@ -0,0 +1,376 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: scientific-string-network-api
|
|
3
|
+
description: |
|
|
4
|
+
STRING/BioGRID/STITCH ネットワーク解析スキル。STRING タンパク質相互作用
|
|
5
|
+
ネットワーク直接 API、BioGRID 実験的 PPI、STITCH 化学-タンパク質ネットワーク、
|
|
6
|
+
ネットワークトポロジー解析・コミュニティ検出・機能濃縮統合パイプライン。
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Scientific STRING Network API
|
|
10
|
+
|
|
11
|
+
STRING v12 / BioGRID / STITCH API を活用した PPI・化合物-タンパク質
|
|
12
|
+
ネットワーク解析パイプラインを提供する。既存の protein-interaction-network
|
|
13
|
+
スキル (IntAct/HumanBase) を補完し、STRING 直接 API ベースの高度な
|
|
14
|
+
ネットワーク分析を統合。
|
|
15
|
+
|
|
16
|
+
## When to Use
|
|
17
|
+
|
|
18
|
+
- STRING API でタンパク質相互作用ネットワークを直接構築するとき
|
|
19
|
+
- BioGRID から実験的エビデンスベースの PPI を取得するとき
|
|
20
|
+
- STITCH で化合物-タンパク質間ネットワークを検索するとき
|
|
21
|
+
- ネットワークトポロジー指標 (次数分布・媒介中心性) を計算するとき
|
|
22
|
+
- PPI ネットワーク上でコミュニティ検出を行うとき
|
|
23
|
+
- 機能濃縮解析 (STRING enrichment) をネットワーク上で実行するとき
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Quick Start
|
|
28
|
+
|
|
29
|
+
## 1. STRING PPI ネットワーク取得
|
|
30
|
+
|
|
31
|
+
```python
|
|
32
|
+
import requests
|
|
33
|
+
import pandas as pd
|
|
34
|
+
import networkx as nx
|
|
35
|
+
|
|
36
|
+
STRING_API = "https://string-db.org/api"
|
|
37
|
+
OUTPUT_FORMAT = "json"
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
def get_string_network(proteins, species=9606, score_threshold=400,
|
|
41
|
+
network_type="functional", limit=50):
|
|
42
|
+
"""
|
|
43
|
+
STRING PPI ネットワーク取得。
|
|
44
|
+
|
|
45
|
+
Parameters:
|
|
46
|
+
proteins: list — タンパク質名リスト (例: ["TP53", "MDM2", "BRCA1"])
|
|
47
|
+
species: int — NCBI Taxonomy ID (9606=human)
|
|
48
|
+
score_threshold: int — 信頼スコア閾値 (0-1000)
|
|
49
|
+
network_type: str — "functional" or "physical"
|
|
50
|
+
limit: int — interactor 最大数
|
|
51
|
+
|
|
52
|
+
ToolUniverse:
|
|
53
|
+
STRING_get_protein_interactions(
|
|
54
|
+
protein_ids=proteins, species=species,
|
|
55
|
+
confidence_score=score_threshold/1000,
|
|
56
|
+
network_type=network_type, limit=limit
|
|
57
|
+
)
|
|
58
|
+
"""
|
|
59
|
+
url = f"{STRING_API}/{OUTPUT_FORMAT}/network"
|
|
60
|
+
params = {
|
|
61
|
+
"identifiers": "\r".join(proteins),
|
|
62
|
+
"species": species,
|
|
63
|
+
"required_score": score_threshold,
|
|
64
|
+
"network_type": network_type,
|
|
65
|
+
"limit": limit,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
resp = requests.post(url, data=params)
|
|
69
|
+
resp.raise_for_status()
|
|
70
|
+
interactions = resp.json()
|
|
71
|
+
|
|
72
|
+
rows = []
|
|
73
|
+
for i in interactions:
|
|
74
|
+
rows.append({
|
|
75
|
+
"protein_a": i.get("preferredName_A"),
|
|
76
|
+
"protein_b": i.get("preferredName_B"),
|
|
77
|
+
"combined_score": i.get("score"),
|
|
78
|
+
"nscore": i.get("nscore"),
|
|
79
|
+
"fscore": i.get("fscore"),
|
|
80
|
+
"pscore": i.get("pscore"),
|
|
81
|
+
"ascore": i.get("ascore"),
|
|
82
|
+
"escore": i.get("escore"),
|
|
83
|
+
"dscore": i.get("dscore"),
|
|
84
|
+
"tscore": i.get("tscore"),
|
|
85
|
+
})
|
|
86
|
+
|
|
87
|
+
df = pd.DataFrame(rows)
|
|
88
|
+
print(f"STRING network: {len(df)} interactions "
|
|
89
|
+
f"(score ≥ {score_threshold/1000})")
|
|
90
|
+
return df
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## 2. BioGRID 実験的 PPI 取得
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
def get_biogrid_interactions(genes, organism=9606, evidence_type=None,
|
|
97
|
+
api_key="YOUR_KEY", limit=500):
|
|
98
|
+
"""
|
|
99
|
+
BioGRID 実験的 PPI データ取得。
|
|
100
|
+
|
|
101
|
+
Parameters:
|
|
102
|
+
genes: list — 遺伝子名リスト
|
|
103
|
+
organism: int — NCBI Taxonomy ID
|
|
104
|
+
evidence_type: str — "physical" or "genetic"
|
|
105
|
+
api_key: str — BioGRID API key (https://webservice.thebiogrid.org)
|
|
106
|
+
limit: int — 最大取得数
|
|
107
|
+
|
|
108
|
+
ToolUniverse:
|
|
109
|
+
BioGRID_get_interactions(
|
|
110
|
+
gene_names=genes, organism=organism,
|
|
111
|
+
interaction_type=evidence_type, limit=limit
|
|
112
|
+
)
|
|
113
|
+
"""
|
|
114
|
+
url = "https://webservice.thebiogrid.org/interactions"
|
|
115
|
+
params = {
|
|
116
|
+
"accessKey": api_key,
|
|
117
|
+
"geneList": "|".join(genes),
|
|
118
|
+
"organism": organism,
|
|
119
|
+
"format": "json",
|
|
120
|
+
"max": limit,
|
|
121
|
+
"searchNames": "true",
|
|
122
|
+
"includeInteractors": "true",
|
|
123
|
+
}
|
|
124
|
+
if evidence_type:
|
|
125
|
+
params["interSpeciesExcluded"] = "true"
|
|
126
|
+
|
|
127
|
+
resp = requests.get(url, params=params)
|
|
128
|
+
resp.raise_for_status()
|
|
129
|
+
data = resp.json()
|
|
130
|
+
|
|
131
|
+
rows = []
|
|
132
|
+
for _, interaction in data.items():
|
|
133
|
+
rows.append({
|
|
134
|
+
"gene_a": interaction.get("OFFICIAL_SYMBOL_A"),
|
|
135
|
+
"gene_b": interaction.get("OFFICIAL_SYMBOL_B"),
|
|
136
|
+
"experimental_system": interaction.get("EXPERIMENTAL_SYSTEM"),
|
|
137
|
+
"throughput": interaction.get("THROUGHPUT"),
|
|
138
|
+
"pubmed_id": interaction.get("PUBMED_ID"),
|
|
139
|
+
"source_db": "BioGRID",
|
|
140
|
+
})
|
|
141
|
+
|
|
142
|
+
df = pd.DataFrame(rows)
|
|
143
|
+
print(f"BioGRID: {len(df)} interactions for {genes}")
|
|
144
|
+
return df
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## 3. STITCH 化合物-タンパク質ネットワーク
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
def get_stitch_interactions(identifiers, species=9606, score=400, limit=20):
|
|
151
|
+
"""
|
|
152
|
+
STITCH 化合物-タンパク質相互作用取得。
|
|
153
|
+
|
|
154
|
+
Parameters:
|
|
155
|
+
identifiers: list — CID (化合物) または遺伝子名リスト
|
|
156
|
+
species: int — NCBI Taxonomy ID
|
|
157
|
+
score: int — 信頼スコア閾値
|
|
158
|
+
limit: int — 最大結果数
|
|
159
|
+
|
|
160
|
+
ToolUniverse:
|
|
161
|
+
STITCH_get_chemical_protein_interactions(
|
|
162
|
+
identifiers=identifiers, species=species,
|
|
163
|
+
required_score=score, limit=limit
|
|
164
|
+
)
|
|
165
|
+
STITCH_get_interaction_partners(identifiers=identifiers)
|
|
166
|
+
STITCH_resolve_identifier(identifiers=identifiers)
|
|
167
|
+
"""
|
|
168
|
+
url = f"https://stitch.embl.de/api/{OUTPUT_FORMAT}/interactionsList"
|
|
169
|
+
params = {
|
|
170
|
+
"identifiers": "\r".join(identifiers),
|
|
171
|
+
"species": species,
|
|
172
|
+
"required_score": score,
|
|
173
|
+
"limit": limit,
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
resp = requests.post(url, data=params)
|
|
177
|
+
resp.raise_for_status()
|
|
178
|
+
interactions = resp.json()
|
|
179
|
+
|
|
180
|
+
rows = []
|
|
181
|
+
for i in interactions:
|
|
182
|
+
rows.append({
|
|
183
|
+
"interactor_a": i.get("preferredName_A", i.get("stringId_A")),
|
|
184
|
+
"interactor_b": i.get("preferredName_B", i.get("stringId_B")),
|
|
185
|
+
"combined_score": i.get("score"),
|
|
186
|
+
"is_chemical": "CID" in str(i.get("stringId_A", ""))
|
|
187
|
+
or "CID" in str(i.get("stringId_B", "")),
|
|
188
|
+
})
|
|
189
|
+
|
|
190
|
+
df = pd.DataFrame(rows)
|
|
191
|
+
print(f"STITCH: {len(df)} chemical-protein interactions")
|
|
192
|
+
return df
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## 4. ネットワーク構築 & トポロジー解析
|
|
196
|
+
|
|
197
|
+
```python
|
|
198
|
+
def build_network(interaction_df, source_col="protein_a", target_col="protein_b",
|
|
199
|
+
weight_col="combined_score"):
|
|
200
|
+
"""
|
|
201
|
+
NetworkX グラフ構築 & トポロジー解析。
|
|
202
|
+
|
|
203
|
+
Parameters:
|
|
204
|
+
interaction_df: DataFrame — 相互作用データ
|
|
205
|
+
source_col, target_col: str — ノードカラム名
|
|
206
|
+
weight_col: str — エッジ重みカラム名
|
|
207
|
+
"""
|
|
208
|
+
G = nx.Graph()
|
|
209
|
+
for _, row in interaction_df.iterrows():
|
|
210
|
+
G.add_edge(
|
|
211
|
+
row[source_col], row[target_col],
|
|
212
|
+
weight=row.get(weight_col, 1.0),
|
|
213
|
+
)
|
|
214
|
+
|
|
215
|
+
# トポロジー指標
|
|
216
|
+
degree = dict(G.degree())
|
|
217
|
+
betweenness = nx.betweenness_centrality(G)
|
|
218
|
+
closeness = nx.closeness_centrality(G)
|
|
219
|
+
clustering = nx.clustering(G)
|
|
220
|
+
|
|
221
|
+
metrics = pd.DataFrame({
|
|
222
|
+
"node": list(degree.keys()),
|
|
223
|
+
"degree": list(degree.values()),
|
|
224
|
+
"betweenness": [betweenness[n] for n in degree],
|
|
225
|
+
"closeness": [closeness[n] for n in degree],
|
|
226
|
+
"clustering": [clustering[n] for n in degree],
|
|
227
|
+
}).sort_values("betweenness", ascending=False)
|
|
228
|
+
|
|
229
|
+
print(f"Network: {G.number_of_nodes()} nodes, "
|
|
230
|
+
f"{G.number_of_edges()} edges, "
|
|
231
|
+
f"density={nx.density(G):.4f}")
|
|
232
|
+
return G, metrics
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## 5. コミュニティ検出
|
|
236
|
+
|
|
237
|
+
```python
|
|
238
|
+
from networkx.algorithms.community import greedy_modularity_communities
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def detect_communities(G, resolution=1.0):
|
|
242
|
+
"""
|
|
243
|
+
ネットワーク上のコミュニティ (モジュール) 検出。
|
|
244
|
+
|
|
245
|
+
Parameters:
|
|
246
|
+
G: nx.Graph — ネットワークグラフ
|
|
247
|
+
resolution: float — 解像度パラメータ
|
|
248
|
+
"""
|
|
249
|
+
communities = list(greedy_modularity_communities(G, resolution=resolution))
|
|
250
|
+
modularity = nx.algorithms.community.modularity(G, communities)
|
|
251
|
+
|
|
252
|
+
comm_data = []
|
|
253
|
+
for i, comm in enumerate(communities):
|
|
254
|
+
for node in comm:
|
|
255
|
+
comm_data.append({"node": node, "community": i})
|
|
256
|
+
|
|
257
|
+
df = pd.DataFrame(comm_data)
|
|
258
|
+
print(f"Communities: {len(communities)} detected, "
|
|
259
|
+
f"modularity={modularity:.4f}")
|
|
260
|
+
return df, modularity
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## 6. STRING 機能濃縮解析
|
|
264
|
+
|
|
265
|
+
```python
|
|
266
|
+
def string_enrichment(proteins, species=9606):
|
|
267
|
+
"""
|
|
268
|
+
STRING API 機能濃縮解析 (GO/KEGG/Reactome/InterPro)。
|
|
269
|
+
|
|
270
|
+
Parameters:
|
|
271
|
+
proteins: list — タンパク質名リスト
|
|
272
|
+
species: int — NCBI Taxonomy ID
|
|
273
|
+
"""
|
|
274
|
+
url = f"{STRING_API}/{OUTPUT_FORMAT}/enrichment"
|
|
275
|
+
params = {
|
|
276
|
+
"identifiers": "\r".join(proteins),
|
|
277
|
+
"species": species,
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
resp = requests.post(url, data=params)
|
|
281
|
+
resp.raise_for_status()
|
|
282
|
+
enrichment = resp.json()
|
|
283
|
+
|
|
284
|
+
rows = []
|
|
285
|
+
for e in enrichment:
|
|
286
|
+
rows.append({
|
|
287
|
+
"category": e.get("category"),
|
|
288
|
+
"term": e.get("term"),
|
|
289
|
+
"description": e.get("description"),
|
|
290
|
+
"p_value": e.get("p_value"),
|
|
291
|
+
"fdr": e.get("fdr"),
|
|
292
|
+
"number_of_genes": e.get("number_of_genes"),
|
|
293
|
+
"input_genes": e.get("inputGenes", ""),
|
|
294
|
+
})
|
|
295
|
+
|
|
296
|
+
df = pd.DataFrame(rows)
|
|
297
|
+
if not df.empty:
|
|
298
|
+
df = df.sort_values("fdr")
|
|
299
|
+
print(f"Enrichment: {len(df)} terms, "
|
|
300
|
+
f"{df[df['fdr'] < 0.05].shape[0]} significant (FDR<0.05)")
|
|
301
|
+
return df
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## 7. 統合 PPI 解析パイプライン
|
|
305
|
+
|
|
306
|
+
```python
|
|
307
|
+
def integrated_ppi_pipeline(genes, species=9606, score=700):
|
|
308
|
+
"""
|
|
309
|
+
STRING + BioGRID + STITCH 統合 PPI パイプライン。
|
|
310
|
+
|
|
311
|
+
Pipeline:
|
|
312
|
+
STRING network → BioGRID validation → topology → communities →
|
|
313
|
+
enrichment
|
|
314
|
+
"""
|
|
315
|
+
# STRING ネットワーク
|
|
316
|
+
string_df = get_string_network(genes, species, score)
|
|
317
|
+
|
|
318
|
+
# ネットワーク構築 & トポロジー
|
|
319
|
+
G, metrics = build_network(string_df)
|
|
320
|
+
|
|
321
|
+
# コミュニティ検出
|
|
322
|
+
comm_df, modularity = detect_communities(G)
|
|
323
|
+
|
|
324
|
+
# STRING 濃縮解析
|
|
325
|
+
all_nodes = list(G.nodes())
|
|
326
|
+
enrichment = string_enrichment(all_nodes[:500], species)
|
|
327
|
+
|
|
328
|
+
result = {
|
|
329
|
+
"n_nodes": G.number_of_nodes(),
|
|
330
|
+
"n_edges": G.number_of_edges(),
|
|
331
|
+
"density": round(nx.density(G), 4),
|
|
332
|
+
"n_communities": comm_df["community"].nunique(),
|
|
333
|
+
"modularity": round(modularity, 4),
|
|
334
|
+
"hub_genes": metrics.head(10)["node"].tolist(),
|
|
335
|
+
"n_enriched_terms": len(enrichment[enrichment["fdr"] < 0.05])
|
|
336
|
+
if not enrichment.empty else 0,
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
print(f"\n=== Integrated PPI Pipeline ===")
|
|
340
|
+
print(f"Nodes: {result['n_nodes']}, Edges: {result['n_edges']}")
|
|
341
|
+
print(f"Hub genes: {', '.join(result['hub_genes'][:5])}")
|
|
342
|
+
return result
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
---
|
|
346
|
+
|
|
347
|
+
## パイプライン統合
|
|
348
|
+
|
|
349
|
+
```
|
|
350
|
+
drug-target-profiling → string-network-api → pathway-enrichment
|
|
351
|
+
(候補ターゲット) (STRING PPI 構築) (GO/KEGG 濃縮)
|
|
352
|
+
│ │ ↓
|
|
353
|
+
protein-interaction ───┘ │ ontology-enrichment
|
|
354
|
+
(IntAct/HumanBase) ↓ (EFO/Enrichr)
|
|
355
|
+
network-analysis
|
|
356
|
+
(既存スキル補完)
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
## パイプライン出力
|
|
360
|
+
|
|
361
|
+
| ファイル | 説明 | 次スキル |
|
|
362
|
+
|---------|------|---------|
|
|
363
|
+
| `results/string_network.csv` | STRING PPI ネットワーク | → network-analysis |
|
|
364
|
+
| `results/ppi_topology.csv` | トポロジー指標 | → drug-target-profiling |
|
|
365
|
+
| `results/ppi_communities.csv` | コミュニティ割当 | → pathway-enrichment |
|
|
366
|
+
| `results/string_enrichment.csv` | 機能濃縮結果 | → ontology-enrichment |
|
|
367
|
+
|
|
368
|
+
## 利用可能ツール (ToolUniverse SMCP)
|
|
369
|
+
|
|
370
|
+
| ツール名 | 用途 |
|
|
371
|
+
|---------|------|
|
|
372
|
+
| `STRING_get_protein_interactions` | STRING PPI 取得 |
|
|
373
|
+
| `BioGRID_get_interactions` | BioGRID 実験的 PPI |
|
|
374
|
+
| `STITCH_get_chemical_protein_interactions` | STITCH 化合物-タンパク質 |
|
|
375
|
+
| `STITCH_get_interaction_partners` | STITCH 相互作用パートナー |
|
|
376
|
+
| `STITCH_resolve_identifier` | STITCH ID 解決 |
|
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: scientific-toxicology-env
|
|
3
|
+
description: |
|
|
4
|
+
毒性学・環境衛生スキル。CTD (Comparative Toxicogenomics Database)
|
|
5
|
+
化学-遺伝子-疾患関連・ToxCast/Tox21 高スループット毒性スクリーニング・
|
|
6
|
+
IRIS ヒトリスク評価・T3DB 食品/環境毒性物質・PubChem BioAssay 毒性データ。
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Scientific Toxicology & Environmental Health
|
|
10
|
+
|
|
11
|
+
CTD / Tox21 / ToxCast / T3DB / IRIS を活用した毒性学・環境衛生
|
|
12
|
+
パイプラインを提供する。化学物質-遺伝子-疾患関連、高スループット
|
|
13
|
+
毒性スクリーニング、ヒト健康リスク評価。
|
|
14
|
+
|
|
15
|
+
## When to Use
|
|
16
|
+
|
|
17
|
+
- 化学物質が関連する遺伝子・疾患を調べるとき (CTD)
|
|
18
|
+
- Tox21/ToxCast アッセイデータで毒性メカニズムを解析するとき
|
|
19
|
+
- IRIS リスク評価データ (RfD/RfC/UR) を参照するとき
|
|
20
|
+
- 食品・環境毒性物質の詳細データベース (T3DB) を検索するとき
|
|
21
|
+
- PubChem BioAssay から毒性関連ハイスループットデータを取得するとき
|
|
22
|
+
- ADMET 毒性予測と実験毒性データを併用するとき
|
|
23
|
+
|
|
24
|
+
---
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
## 1. CTD 化学-遺伝子-疾患関連検索
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
import requests
|
|
32
|
+
import pandas as pd
|
|
33
|
+
import json
|
|
34
|
+
|
|
35
|
+
CTD_BASE = "https://ctdbase.org/tools"
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
def ctd_chemical_gene(chemical_name, limit=100):
|
|
39
|
+
"""
|
|
40
|
+
CTD — 化学物質-遺伝子相互作用を検索。
|
|
41
|
+
|
|
42
|
+
Parameters:
|
|
43
|
+
chemical_name: str — 化学物質名 (例: "Bisphenol A")
|
|
44
|
+
limit: int — 最大取得数
|
|
45
|
+
"""
|
|
46
|
+
url = f"{CTD_BASE}/batchQuery.go"
|
|
47
|
+
params = {
|
|
48
|
+
"inputType": "chem",
|
|
49
|
+
"inputTerms": chemical_name,
|
|
50
|
+
"report": "genes_curated",
|
|
51
|
+
"format": "json",
|
|
52
|
+
}
|
|
53
|
+
resp = requests.get(url, params=params, timeout=60)
|
|
54
|
+
resp.raise_for_status()
|
|
55
|
+
data = resp.json()[:limit]
|
|
56
|
+
|
|
57
|
+
results = []
|
|
58
|
+
for entry in data:
|
|
59
|
+
results.append({
|
|
60
|
+
"chemical": entry.get("ChemicalName", ""),
|
|
61
|
+
"gene": entry.get("GeneSymbol", ""),
|
|
62
|
+
"organism": entry.get("Organism", ""),
|
|
63
|
+
"interaction": entry.get("Interaction", ""),
|
|
64
|
+
"pubmed_ids": entry.get("PubMedIDs", ""),
|
|
65
|
+
})
|
|
66
|
+
|
|
67
|
+
df = pd.DataFrame(results)
|
|
68
|
+
print(f"CTD: {chemical_name} → {len(df)} gene interactions")
|
|
69
|
+
return df
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
## 2. CTD 化学-疾患関連検索
|
|
73
|
+
|
|
74
|
+
```python
|
|
75
|
+
def ctd_chemical_disease(chemical_name, limit=100):
|
|
76
|
+
"""
|
|
77
|
+
CTD — 化学物質-疾患関連を検索。
|
|
78
|
+
|
|
79
|
+
Parameters:
|
|
80
|
+
chemical_name: str — 化学物質名
|
|
81
|
+
limit: int — 最大取得数
|
|
82
|
+
"""
|
|
83
|
+
url = f"{CTD_BASE}/batchQuery.go"
|
|
84
|
+
params = {
|
|
85
|
+
"inputType": "chem",
|
|
86
|
+
"inputTerms": chemical_name,
|
|
87
|
+
"report": "diseases_curated",
|
|
88
|
+
"format": "json",
|
|
89
|
+
}
|
|
90
|
+
resp = requests.get(url, params=params, timeout=60)
|
|
91
|
+
resp.raise_for_status()
|
|
92
|
+
data = resp.json()[:limit]
|
|
93
|
+
|
|
94
|
+
results = []
|
|
95
|
+
for entry in data:
|
|
96
|
+
results.append({
|
|
97
|
+
"chemical": entry.get("ChemicalName", ""),
|
|
98
|
+
"disease": entry.get("DiseaseName", ""),
|
|
99
|
+
"disease_id": entry.get("DiseaseID", ""),
|
|
100
|
+
"direct_evidence": entry.get("DirectEvidence", ""),
|
|
101
|
+
"inference_score": float(entry.get("InferenceScore", 0)),
|
|
102
|
+
})
|
|
103
|
+
|
|
104
|
+
df = pd.DataFrame(results)
|
|
105
|
+
df = df.sort_values("inference_score", ascending=False)
|
|
106
|
+
print(f"CTD: {chemical_name} → {len(df)} disease associations")
|
|
107
|
+
return df
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## 3. Tox21/ToxCast アッセイデータ取得
|
|
111
|
+
|
|
112
|
+
```python
|
|
113
|
+
COMPTOX_BASE = "https://comptox.epa.gov/dashboard/api"
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def tox21_assay_search(chemical_identifier, assay_source="Tox21"):
|
|
117
|
+
"""
|
|
118
|
+
CompTox Dashboard — Tox21/ToxCast アッセイ結果を取得。
|
|
119
|
+
|
|
120
|
+
Parameters:
|
|
121
|
+
chemical_identifier: str — DTXSID or CAS
|
|
122
|
+
assay_source: str — "Tox21" or "ToxCast"
|
|
123
|
+
"""
|
|
124
|
+
# CompTox Dashboard API で化学物質のアッセイデータ取得
|
|
125
|
+
url = f"{COMPTOX_BASE}/chemical/search"
|
|
126
|
+
params = {"query": chemical_identifier}
|
|
127
|
+
resp = requests.get(url, params=params, timeout=30)
|
|
128
|
+
resp.raise_for_status()
|
|
129
|
+
chem_data = resp.json()
|
|
130
|
+
|
|
131
|
+
dtxsid = chem_data.get("dtxsid", chemical_identifier)
|
|
132
|
+
|
|
133
|
+
# アッセイエンドポイント取得
|
|
134
|
+
url_assay = f"{COMPTOX_BASE}/chemical/{dtxsid}/assays"
|
|
135
|
+
resp_assay = requests.get(url_assay, timeout=30)
|
|
136
|
+
resp_assay.raise_for_status()
|
|
137
|
+
assays = resp_assay.json()
|
|
138
|
+
|
|
139
|
+
results = []
|
|
140
|
+
for assay in assays:
|
|
141
|
+
if assay_source.lower() in assay.get("assaySource", "").lower():
|
|
142
|
+
results.append({
|
|
143
|
+
"assay_name": assay.get("assayName", ""),
|
|
144
|
+
"assay_source": assay.get("assaySource", ""),
|
|
145
|
+
"endpoint": assay.get("assayEndpoint", ""),
|
|
146
|
+
"activity": assay.get("activity", ""),
|
|
147
|
+
"ac50_um": assay.get("ac50", None),
|
|
148
|
+
"hit_call": assay.get("hitCall", ""),
|
|
149
|
+
})
|
|
150
|
+
|
|
151
|
+
df = pd.DataFrame(results)
|
|
152
|
+
n_active = (df["hit_call"] == "Active").sum() if len(df) > 0 else 0
|
|
153
|
+
print(f"Tox21/ToxCast: {dtxsid} → {len(df)} assays, {n_active} active")
|
|
154
|
+
return df
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
## 4. T3DB 毒性物質検索
|
|
158
|
+
|
|
159
|
+
```python
|
|
160
|
+
T3DB_BASE = "https://t3db.ca/api"
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def t3db_search(query, search_type="name"):
|
|
164
|
+
"""
|
|
165
|
+
T3DB — 食品/環境毒性物質データベース検索。
|
|
166
|
+
|
|
167
|
+
Parameters:
|
|
168
|
+
query: str — 検索語
|
|
169
|
+
search_type: str — "name", "cas", "category"
|
|
170
|
+
"""
|
|
171
|
+
url = f"{T3DB_BASE}/toxins/search"
|
|
172
|
+
params = {"query": query, "search_type": search_type}
|
|
173
|
+
resp = requests.get(url, params=params, timeout=30)
|
|
174
|
+
resp.raise_for_status()
|
|
175
|
+
data = resp.json()
|
|
176
|
+
|
|
177
|
+
results = []
|
|
178
|
+
for toxin in data.get("toxins", []):
|
|
179
|
+
results.append({
|
|
180
|
+
"name": toxin.get("name", ""),
|
|
181
|
+
"t3db_id": toxin.get("t3db_id", ""),
|
|
182
|
+
"cas_number": toxin.get("cas_number", ""),
|
|
183
|
+
"category": toxin.get("category", ""),
|
|
184
|
+
"toxicity_class": toxin.get("toxicity_class", ""),
|
|
185
|
+
"ld50_oral": toxin.get("ld50_oral", ""),
|
|
186
|
+
"target_organs": toxin.get("target_organs", []),
|
|
187
|
+
})
|
|
188
|
+
|
|
189
|
+
df = pd.DataFrame(results)
|
|
190
|
+
print(f"T3DB: '{query}' → {len(df)} toxins")
|
|
191
|
+
return df
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## 5. EPA IRIS リスク評価
|
|
195
|
+
|
|
196
|
+
```python
|
|
197
|
+
def iris_risk_assessment(chemical_name):
|
|
198
|
+
"""
|
|
199
|
+
EPA IRIS — ヒト健康リスク評価データ取得。
|
|
200
|
+
|
|
201
|
+
Parameters:
|
|
202
|
+
chemical_name: str — 化学物質名
|
|
203
|
+
"""
|
|
204
|
+
url = "https://iris.epa.gov/AtoZ"
|
|
205
|
+
resp = requests.get(url, timeout=30)
|
|
206
|
+
|
|
207
|
+
# IRIS は構造化 API なし — スクレイピングまたはローカルデータ
|
|
208
|
+
# 代替: CompTox Dashboard API 経由
|
|
209
|
+
url_comptox = f"{COMPTOX_BASE}/chemical/search"
|
|
210
|
+
params = {"query": chemical_name}
|
|
211
|
+
resp = requests.get(url_comptox, params=params, timeout=30)
|
|
212
|
+
resp.raise_for_status()
|
|
213
|
+
data = resp.json()
|
|
214
|
+
|
|
215
|
+
risk_data = {
|
|
216
|
+
"chemical": chemical_name,
|
|
217
|
+
"dtxsid": data.get("dtxsid", ""),
|
|
218
|
+
"rfd_oral_mg_kg_day": data.get("rfdOral", None),
|
|
219
|
+
"rfc_inhalation_mg_m3": data.get("rfcInhalation", None),
|
|
220
|
+
"cancer_classification": data.get("cancerClassification", ""),
|
|
221
|
+
"oral_slope_factor": data.get("oralSlopeFactor", None),
|
|
222
|
+
"inhalation_unit_risk": data.get("inhalationUnitRisk", None),
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
print(f"IRIS: {chemical_name}")
|
|
226
|
+
for k, v in risk_data.items():
|
|
227
|
+
if v and k != "chemical":
|
|
228
|
+
print(f" {k}: {v}")
|
|
229
|
+
return risk_data
|
|
230
|
+
```
|
|
231
|
+
|
|
232
|
+
## 6. 毒性パスウェイ解析
|
|
233
|
+
|
|
234
|
+
```python
|
|
235
|
+
def toxicity_pathway_analysis(chemical_name, species="Homo sapiens"):
|
|
236
|
+
"""
|
|
237
|
+
CTD + パスウェイ統合毒性解析。
|
|
238
|
+
|
|
239
|
+
Parameters:
|
|
240
|
+
chemical_name: str — 化学物質名
|
|
241
|
+
species: str — 生物種
|
|
242
|
+
"""
|
|
243
|
+
# 1) CTD 遺伝子取得
|
|
244
|
+
gene_df = ctd_chemical_gene(chemical_name, limit=500)
|
|
245
|
+
if species:
|
|
246
|
+
gene_df = gene_df[gene_df["organism"] == species]
|
|
247
|
+
|
|
248
|
+
gene_list = gene_df["gene"].unique().tolist()
|
|
249
|
+
|
|
250
|
+
# 2) CTD 疾患取得
|
|
251
|
+
disease_df = ctd_chemical_disease(chemical_name, limit=100)
|
|
252
|
+
|
|
253
|
+
# 3) パスウェイ濃縮 (KEGG enrichment via Enrichr)
|
|
254
|
+
enrichr_url = "https://maayanlab.cloud/Enrichr"
|
|
255
|
+
add_resp = requests.post(
|
|
256
|
+
f"{enrichr_url}/addList",
|
|
257
|
+
files={"list": (None, "\n".join(gene_list))}
|
|
258
|
+
)
|
|
259
|
+
user_list_id = add_resp.json()["userListId"]
|
|
260
|
+
|
|
261
|
+
enrich_resp = requests.get(
|
|
262
|
+
f"{enrichr_url}/enrich",
|
|
263
|
+
params={"userListId": user_list_id, "backgroundType": "KEGG_2021_Human"}
|
|
264
|
+
)
|
|
265
|
+
pathways = enrich_resp.json().get("KEGG_2021_Human", [])
|
|
266
|
+
|
|
267
|
+
pathway_results = []
|
|
268
|
+
for pw in pathways[:20]:
|
|
269
|
+
pathway_results.append({
|
|
270
|
+
"pathway": pw[1],
|
|
271
|
+
"p_value": pw[2],
|
|
272
|
+
"adj_p_value": pw[6],
|
|
273
|
+
"genes": pw[5],
|
|
274
|
+
})
|
|
275
|
+
|
|
276
|
+
print(f"Toxicity pathway: {chemical_name}")
|
|
277
|
+
print(f" Target genes: {len(gene_list)}")
|
|
278
|
+
print(f" Diseases: {len(disease_df)}")
|
|
279
|
+
print(f" Pathways: {len(pathway_results)}")
|
|
280
|
+
return {
|
|
281
|
+
"genes": gene_df,
|
|
282
|
+
"diseases": disease_df,
|
|
283
|
+
"pathways": pd.DataFrame(pathway_results),
|
|
284
|
+
}
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
---
|
|
288
|
+
|
|
289
|
+
## パイプライン統合
|
|
290
|
+
|
|
291
|
+
```
|
|
292
|
+
admet-pharmacokinetics → toxicology-env → pharmacovigilance
|
|
293
|
+
(ADMET 毒性予測) (CTD/Tox21/IRIS) (市販後安全性)
|
|
294
|
+
│ │ ↓
|
|
295
|
+
cheminformatics ───────────────┘ disease-research
|
|
296
|
+
(RDKit 構造アラート) │ (疾患-遺伝子関連)
|
|
297
|
+
↓
|
|
298
|
+
public-health-data
|
|
299
|
+
(CDC/WHO 公衆衛生)
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
## パイプライン出力
|
|
303
|
+
|
|
304
|
+
| ファイル | 説明 | 次スキル |
|
|
305
|
+
|---------|------|---------|
|
|
306
|
+
| `results/ctd_gene_interactions.csv` | CTD 化学-遺伝子関連 | → pathway-enrichment |
|
|
307
|
+
| `results/ctd_disease_associations.csv` | CTD 化学-疾患関連 | → disease-research |
|
|
308
|
+
| `results/tox21_assays.csv` | Tox21/ToxCast アッセイ結果 | → admet-pharmacokinetics |
|
|
309
|
+
| `results/toxicity_pathways.json` | 毒性パスウェイ解析結果 | → pharmacovigilance |
|