Spaces:
Running
Running
guide: source-specific starter code; rank and display by each board's own metric
Browse files- app.py +33 -4
- data/caco2_card.json +13 -1
- data/halflife_card.json +12 -1
- data/ld50_card.json +12 -1
- data/logp_card.json +10 -1
- data/mtb_card.json +15 -2
- data/ppb_card.json +10 -1
- data/saureus_card.json +15 -2
- data/sepidermidis_card.json +15 -2
- data/vdss_card.json +11 -1
- index.html +113 -21
app.py
CHANGED
|
@@ -124,10 +124,16 @@ def _load_boards():
|
|
| 124 |
# ๋ชจ๋ธ ์ค์ฐจ๊ฐ ์คํ ์ค์ฐจ์ ๋ช ๋ฐฐ์ธ๊ฐ. 1 ์ ๋ถ์์๋ก ์ธก์ ํ๊ณ๋ค.
|
| 125 |
if best and nf.get("sd_single") and d["metric"] == "mae":
|
| 126 |
d["error_over_noise"] = round(base[best]["mae"] / nf["sd_single"], 2)
|
| 127 |
-
|
| 128 |
-
|
| 129 |
-
|
| 130 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 131 |
if d.get("n_test"):
|
| 132 |
d["near_pct"] = round(100.0 * d.get("near_threshold", 0) / d["n_test"], 1)
|
| 133 |
m = meta.get(d["board"]) or {}
|
|
@@ -138,6 +144,22 @@ def _load_boards():
|
|
| 138 |
return out
|
| 139 |
|
| 140 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
def boards():
|
| 142 |
return cached("boards", 300, _load_boards)
|
| 143 |
|
|
@@ -268,7 +290,12 @@ def api_leaders():
|
|
| 268 |
top = ent[0] if ent else None
|
| 269 |
nf = (b.get("noise_floor") or {}).get("sd_single")
|
| 270 |
base = b.get("baselines") or {}
|
|
|
|
|
|
|
| 271 |
row = {"board": name, "n_test": b.get("n_test"),
|
|
|
|
|
|
|
|
|
|
| 272 |
"blurb": b.get("blurb"), "blurb_en": b.get("blurb_en"),
|
| 273 |
"split_grade": b.get("split_grade"), "answer_grade": b.get("answer_grade"),
|
| 274 |
"noise_floor": nf, "entries": len(ent),
|
|
@@ -279,6 +306,8 @@ def api_leaders():
|
|
| 279 |
"leader": None}
|
| 280 |
if top:
|
| 281 |
row["leader"] = {"method": top.get("method"), "user": top.get("user"),
|
|
|
|
|
|
|
| 282 |
"mae": top.get("mae"), "auroc": top.get("auroc"),
|
| 283 |
"verified": bool(top.get("verified")), "leak": top.get("leak")}
|
| 284 |
out.append(row)
|
|
|
|
| 124 |
# ๋ชจ๋ธ ์ค์ฐจ๊ฐ ์คํ ์ค์ฐจ์ ๋ช ๋ฐฐ์ธ๊ฐ. 1 ์ ๋ถ์์๋ก ์ธก์ ํ๊ณ๋ค.
|
| 125 |
if best and nf.get("sd_single") and d["metric"] == "mae":
|
| 126 |
d["error_over_noise"] = round(base[best]["mae"] / nf["sd_single"], 2)
|
| 127 |
+
# ํ์ต ๊ธฐ์ค์ ์ด ์์ ์์ธก์ ์ด๊ธฐ๋๊ฐ - **๊ทธ ๋ถ๋ฌธ์ ์ฃผ์งํ ์์์** ๋ณธ๋ค.
|
| 128 |
+
# MAE ๋ก๋ง ๋ณด๋ฉด ์๊ด์ผ๋ก ์ฑ์ ๋๋ ๋ถ๋ฌธ์ ๋ป ์๋ ๋น๊ต๊ฐ ๋๊ณ , AUROC ์ ์ฉ
|
| 129 |
+
# ๋ถ๋ฌธ์ mae ๊ฐ None ์ด๋ผ ๋น๊ต ์์ฒด๊ฐ ์์๋ค.
|
| 130 |
+
mk, mhb = primary_metric(d)
|
| 131 |
+
tr = (base.get("Morgan+LightGBM") or {}).get(mk)
|
| 132 |
+
co = (base.get("์์ ์์ธก") or {}).get(mk)
|
| 133 |
+
if tr is not None and co is not None:
|
| 134 |
+
d["beats_constant"] = (tr > co) if mhb else (tr < co)
|
| 135 |
+
# ๊ฒฉ์ฐจ๋ฅผ ํจ๊ป ์ฃ๋๋ค. "์ด๊ฒผ๋ค/์ก๋ค"๋ง์ผ๋ก๋ 0.003 ๊ณผ 0.27 ์ด ๊ฐ์ ๋ณด์ธ๋ค.
|
| 136 |
+
d["beats_constant_margin"] = round((tr - co) if mhb else (co - tr), 4)
|
| 137 |
if d.get("n_test"):
|
| 138 |
d["near_pct"] = round(100.0 * d.get("near_threshold", 0) / d["n_test"], 1)
|
| 139 |
m = meta.get(d["board"]) or {}
|
|
|
|
| 144 |
return out
|
| 145 |
|
| 146 |
|
| 147 |
+
def primary_metric(b):
|
| 148 |
+
"""์ด ๋ถ๋ฌธ์ ์ฃผ์งํ์ ๋ฐฉํฅ. (key, higher_better)
|
| 149 |
+
|
| 150 |
+
ํํํ์ ํ๋กํ์ผ ์๊ด, ๋ถ๋ฅ ์ ์ฉ์ AUROC, ๋๋จธ์ง๋ MAE ๋ค. ํ์ ์ ์ฌ๊ธฐ ํ ๊ณณ์
|
| 151 |
+
๋๋ ์ด์ ๋ ์ฑ์ ๊ธฐ์ ํ๋ฉด์ด ์๋ก ๋ค๋ฅธ ์งํ๋ฅผ ๋ณด๊ณ ์์๊ธฐ ๋๋ฌธ์ด๋ค - Phenotype ๋
|
| 152 |
+
์๊ด์ผ๋ก ์ฑ์ ๋๋๋ฐ ํ๋ฉด์ MAE ๋ง ๋์์, ํ์ต ๊ธฐ์ค์ ์ด ์์ ์์ธก์ 0.003 ์ฐจ์ด๋ก
|
| 153 |
+
๊ฐ์ ํ ์ด๊ธฐ๋ ๊ฒ์ฒ๋ผ ๋ณด์๋ค(์ค์ ์๊ด์ผ๋ก๋ 0.092 ๋ 0.159, ์ก์ ๋ฐ๋ฅ์ 7.6๋ฐฐ).
|
| 154 |
+
"""
|
| 155 |
+
if (b or {}).get("metric") == "profile_corr":
|
| 156 |
+
return "profile_corr", True
|
| 157 |
+
bl = (b or {}).get("baselines") or {}
|
| 158 |
+
if bl and all(v.get("mae") is None for v in bl.values()) and any(v.get("auroc") is not None for v in bl.values()):
|
| 159 |
+
return "auroc", True
|
| 160 |
+
return "mae", False
|
| 161 |
+
|
| 162 |
+
|
| 163 |
def boards():
|
| 164 |
return cached("boards", 300, _load_boards)
|
| 165 |
|
|
|
|
| 290 |
top = ent[0] if ent else None
|
| 291 |
nf = (b.get("noise_floor") or {}).get("sd_single")
|
| 292 |
base = b.get("baselines") or {}
|
| 293 |
+
mkey, mhb = primary_metric(b)
|
| 294 |
+
vals = [v.get(mkey) for v in base.values() if v.get(mkey) is not None]
|
| 295 |
row = {"board": name, "n_test": b.get("n_test"),
|
| 296 |
+
"metric": mkey, "higher_better": mhb,
|
| 297 |
+
# ์ฃผ์งํ ์์์์ ์ต์ ๊ธฐ์ค์ . ๋์ด์ผ ํ ์ ์ ํ๋๋ฟ์ด๋ค.
|
| 298 |
+
"baseline_best_score": (max(vals) if mhb else min(vals)) if vals else None,
|
| 299 |
"blurb": b.get("blurb"), "blurb_en": b.get("blurb_en"),
|
| 300 |
"split_grade": b.get("split_grade"), "answer_grade": b.get("answer_grade"),
|
| 301 |
"noise_floor": nf, "entries": len(ent),
|
|
|
|
| 306 |
"leader": None}
|
| 307 |
if top:
|
| 308 |
row["leader"] = {"method": top.get("method"), "user": top.get("user"),
|
| 309 |
+
# score ๋ ๊ทธ ๋ถ๋ฌธ ์ฃผ์งํ ์์ ๊ฐ์ด๋ค. mae ๋ ์ ํ์๋ถ ํธํ.
|
| 310 |
+
"score": top.get("score", top.get("mae")),
|
| 311 |
"mae": top.get("mae"), "auroc": top.get("auroc"),
|
| 312 |
"verified": bool(top.get("verified")), "leak": top.get("leak")}
|
| 313 |
out.append(row)
|
data/caco2_card.json
CHANGED
|
@@ -42,5 +42,17 @@
|
|
| 42 |
"axis": "A",
|
| 43 |
"desc_ko": "์ฅ ์ํผ ํฌ๊ณผ๋",
|
| 44 |
"desc_en": "Intestinal permeability",
|
| 45 |
-
"built": "2026-08-22"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
}
|
|
|
|
| 42 |
"axis": "A",
|
| 43 |
"desc_ko": "์ฅ ์ํผ ํฌ๊ณผ๋",
|
| 44 |
"desc_en": "Intestinal permeability",
|
| 45 |
+
"built": "2026-08-22",
|
| 46 |
+
"stype": "Papp",
|
| 47 |
+
"units": {
|
| 48 |
+
"10^-6 cm/s": 1.0,
|
| 49 |
+
"ucm/s": 1.0,
|
| 50 |
+
"cm s-1": 1000000.0,
|
| 51 |
+
"nm/s": 0.0001
|
| 52 |
+
},
|
| 53 |
+
"log": true,
|
| 54 |
+
"clip": [
|
| 55 |
+
-4.0,
|
| 56 |
+
4.0
|
| 57 |
+
]
|
| 58 |
}
|
data/halflife_card.json
CHANGED
|
@@ -42,5 +42,16 @@
|
|
| 42 |
"axis": "E",
|
| 43 |
"desc_ko": "๋ฐ๊ฐ๊ธฐ โ ๋ชธ์ ์ผ๋ง๋ ๋จธ๋ฌด๋",
|
| 44 |
"desc_en": "Half-life โ how long it stays",
|
| 45 |
-
"built": "2026-08-22"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
}
|
|
|
|
| 42 |
"axis": "E",
|
| 43 |
"desc_ko": "๋ฐ๊ฐ๊ธฐ โ ๋ชธ์ ์ผ๋ง๋ ๋จธ๋ฌด๋",
|
| 44 |
"desc_en": "Half-life โ how long it stays",
|
| 45 |
+
"built": "2026-08-22",
|
| 46 |
+
"stype": "T1/2",
|
| 47 |
+
"units": {
|
| 48 |
+
"hr": 1.0,
|
| 49 |
+
"min": 0.016666666666666666,
|
| 50 |
+
"day": 24.0
|
| 51 |
+
},
|
| 52 |
+
"log": true,
|
| 53 |
+
"clip": [
|
| 54 |
+
-3.0,
|
| 55 |
+
4.0
|
| 56 |
+
]
|
| 57 |
}
|
data/ld50_card.json
CHANGED
|
@@ -42,5 +42,16 @@
|
|
| 42 |
"axis": "T",
|
| 43 |
"desc_ko": "๊ธ์ฑ๋
์ฑ โ ์น์ฌ๋",
|
| 44 |
"desc_en": "Acute toxicity โ lethal dose",
|
| 45 |
-
"built": "2026-08-22"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
}
|
|
|
|
| 42 |
"axis": "T",
|
| 43 |
"desc_ko": "๊ธ์ฑ๋
์ฑ โ ์น์ฌ๋",
|
| 44 |
"desc_en": "Acute toxicity โ lethal dose",
|
| 45 |
+
"built": "2026-08-22",
|
| 46 |
+
"stype": "LD50",
|
| 47 |
+
"units": {
|
| 48 |
+
"mg.kg-1": "mass",
|
| 49 |
+
"umol.kg-1": 1e-06,
|
| 50 |
+
"mol.kg-1": 1.0
|
| 51 |
+
},
|
| 52 |
+
"log": "neg",
|
| 53 |
+
"clip": [
|
| 54 |
+
0.0,
|
| 55 |
+
9.0
|
| 56 |
+
]
|
| 57 |
}
|
data/logp_card.json
CHANGED
|
@@ -42,5 +42,14 @@
|
|
| 42 |
"axis": "A",
|
| 43 |
"desc_ko": "์น์ ์ฑ โ ๊ธฐ๋ฆ๊ณผ ๋ฌผ ์ฌ์ด ๋ถ๋ฐฐ",
|
| 44 |
"desc_en": "Lipophilicity โ octanol/water partition",
|
| 45 |
-
"built": "2026-08-22"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
}
|
|
|
|
| 42 |
"axis": "A",
|
| 43 |
"desc_ko": "์น์ ์ฑ โ ๊ธฐ๋ฆ๊ณผ ๋ฌผ ์ฌ์ด ๋ถ๋ฐฐ",
|
| 44 |
"desc_en": "Lipophilicity โ octanol/water partition",
|
| 45 |
+
"built": "2026-08-22",
|
| 46 |
+
"stype": "LogP",
|
| 47 |
+
"units": {
|
| 48 |
+
"null": 1.0
|
| 49 |
+
},
|
| 50 |
+
"log": false,
|
| 51 |
+
"clip": [
|
| 52 |
+
-5.0,
|
| 53 |
+
10.0
|
| 54 |
+
]
|
| 55 |
}
|
data/mtb_card.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
{
|
| 2 |
"board": "MTB",
|
| 3 |
-
"target": "
|
| 4 |
"type": "pMIC (์ ์ธํฌ ์ต์์ต์ ๋๋)",
|
| 5 |
"cut": 2020,
|
| 6 |
"threshold": 4.5,
|
|
@@ -44,5 +44,18 @@
|
|
| 44 |
"axis": "X",
|
| 45 |
"desc_ko": "๊ฒฐํต๊ท - ํ์ค๊ท ์ฃผ H37Rv ์ ์ธํฌ ์ฌ๋ฉธ",
|
| 46 |
"desc_en": "M. tuberculosis H37Rv whole-cell kill",
|
| 47 |
-
"built": "2026-08-24"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
}
|
|
|
|
| 1 |
{
|
| 2 |
"board": "MTB",
|
| 3 |
+
"target": "CHEMBL360",
|
| 4 |
"type": "pMIC (์ ์ธํฌ ์ต์์ต์ ๋๋)",
|
| 5 |
"cut": 2020,
|
| 6 |
"threshold": 4.5,
|
|
|
|
| 44 |
"axis": "X",
|
| 45 |
"desc_ko": "๊ฒฐํต๊ท - ํ์ค๊ท ์ฃผ H37Rv ์ ์ธํฌ ์ฌ๋ฉธ",
|
| 46 |
"desc_en": "M. tuberculosis H37Rv whole-cell kill",
|
| 47 |
+
"built": "2026-08-24",
|
| 48 |
+
"stype": "MIC",
|
| 49 |
+
"units": {
|
| 50 |
+
"ug.mL-1": "mass",
|
| 51 |
+
"nM": 1e-09,
|
| 52 |
+
"uM": 1e-06,
|
| 53 |
+
"M": 1.0,
|
| 54 |
+
"nmol/L": 1e-09
|
| 55 |
+
},
|
| 56 |
+
"log": "neg",
|
| 57 |
+
"clip": [
|
| 58 |
+
2.0,
|
| 59 |
+
9.0
|
| 60 |
+
]
|
| 61 |
}
|
data/ppb_card.json
CHANGED
|
@@ -42,5 +42,14 @@
|
|
| 42 |
"axis": "D",
|
| 43 |
"desc_ko": "ํ์ฅ๋จ๋ฐฑ๊ฒฐํฉ โ ์ ๋ฆฌ ์ฝ๋ฌผ ๋น์จ์ ์ ํ๋ค",
|
| 44 |
"desc_en": "Plasma protein binding โ sets the free fraction",
|
| 45 |
-
"built": "2026-08-22"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
}
|
|
|
|
| 42 |
"axis": "D",
|
| 43 |
"desc_ko": "ํ์ฅ๋จ๋ฐฑ๊ฒฐํฉ โ ์ ๋ฆฌ ์ฝ๋ฌผ ๋น์จ์ ์ ํ๋ค",
|
| 44 |
"desc_en": "Plasma protein binding โ sets the free fraction",
|
| 45 |
+
"built": "2026-08-22",
|
| 46 |
+
"stype": "PPB",
|
| 47 |
+
"units": {
|
| 48 |
+
"%": 1.0
|
| 49 |
+
},
|
| 50 |
+
"log": false,
|
| 51 |
+
"clip": [
|
| 52 |
+
0.0,
|
| 53 |
+
100.0
|
| 54 |
+
]
|
| 55 |
}
|
data/saureus_card.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
{
|
| 2 |
"board": "SAureus",
|
| 3 |
-
"target": "
|
| 4 |
"type": "pMIC (์ ์ธํฌ ์ต์์ต์ ๋๋)",
|
| 5 |
"cut": 2023,
|
| 6 |
"threshold": 4.5,
|
|
@@ -44,5 +44,18 @@
|
|
| 44 |
"axis": "X",
|
| 45 |
"desc_ko": "ํฉ์ํฌ๋์๊ตฌ๊ท - ์ ์ธํฌ ์ฌ๋ฉธ",
|
| 46 |
"desc_en": "S. aureus whole-cell kill",
|
| 47 |
-
"built": "2026-08-24"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
}
|
|
|
|
| 1 |
{
|
| 2 |
"board": "SAureus",
|
| 3 |
+
"target": "CHEMBL352",
|
| 4 |
"type": "pMIC (์ ์ธํฌ ์ต์์ต์ ๋๋)",
|
| 5 |
"cut": 2023,
|
| 6 |
"threshold": 4.5,
|
|
|
|
| 44 |
"axis": "X",
|
| 45 |
"desc_ko": "ํฉ์ํฌ๋์๊ตฌ๊ท - ์ ์ธํฌ ์ฌ๋ฉธ",
|
| 46 |
"desc_en": "S. aureus whole-cell kill",
|
| 47 |
+
"built": "2026-08-24",
|
| 48 |
+
"stype": "MIC",
|
| 49 |
+
"units": {
|
| 50 |
+
"ug.mL-1": "mass",
|
| 51 |
+
"nM": 1e-09,
|
| 52 |
+
"uM": 1e-06,
|
| 53 |
+
"M": 1.0,
|
| 54 |
+
"nmol/L": 1e-09
|
| 55 |
+
},
|
| 56 |
+
"log": "neg",
|
| 57 |
+
"clip": [
|
| 58 |
+
2.0,
|
| 59 |
+
9.0
|
| 60 |
+
]
|
| 61 |
}
|
data/sepidermidis_card.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
{
|
| 2 |
"board": "SEpidermidis",
|
| 3 |
-
"target": "
|
| 4 |
"type": "pMIC (์ ์ธํฌ ์ต์์ต์ ๋๋)",
|
| 5 |
"cut": 2018,
|
| 6 |
"threshold": 4.5,
|
|
@@ -44,5 +44,18 @@
|
|
| 44 |
"axis": "X",
|
| 45 |
"desc_ko": "ํํผํฌ๋์๊ตฌ๊ท - ์ ์ธํฌ ์ฌ๋ฉธ",
|
| 46 |
"desc_en": "S. epidermidis whole-cell kill",
|
| 47 |
-
"built": "2026-08-24"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 48 |
}
|
|
|
|
| 1 |
{
|
| 2 |
"board": "SEpidermidis",
|
| 3 |
+
"target": "CHEMBL353",
|
| 4 |
"type": "pMIC (์ ์ธํฌ ์ต์์ต์ ๋๋)",
|
| 5 |
"cut": 2018,
|
| 6 |
"threshold": 4.5,
|
|
|
|
| 44 |
"axis": "X",
|
| 45 |
"desc_ko": "ํํผํฌ๋์๊ตฌ๊ท - ์ ์ธํฌ ์ฌ๋ฉธ",
|
| 46 |
"desc_en": "S. epidermidis whole-cell kill",
|
| 47 |
+
"built": "2026-08-24",
|
| 48 |
+
"stype": "MIC",
|
| 49 |
+
"units": {
|
| 50 |
+
"ug.mL-1": "mass",
|
| 51 |
+
"nM": 1e-09,
|
| 52 |
+
"uM": 1e-06,
|
| 53 |
+
"M": 1.0,
|
| 54 |
+
"nmol/L": 1e-09
|
| 55 |
+
},
|
| 56 |
+
"log": "neg",
|
| 57 |
+
"clip": [
|
| 58 |
+
2.0,
|
| 59 |
+
9.0
|
| 60 |
+
]
|
| 61 |
}
|
data/vdss_card.json
CHANGED
|
@@ -42,5 +42,15 @@
|
|
| 42 |
"axis": "D",
|
| 43 |
"desc_ko": "๋ถํฌ์ฉ์ โ ์กฐ์ง์ผ๋ก ์ผ๋ง๋ ํผ์ง๋",
|
| 44 |
"desc_en": "Volume of distribution",
|
| 45 |
-
"built": "2026-08-22"
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
}
|
|
|
|
| 42 |
"axis": "D",
|
| 43 |
"desc_ko": "๋ถํฌ์ฉ์ โ ์กฐ์ง์ผ๋ก ์ผ๋ง๋ ํผ์ง๋",
|
| 44 |
"desc_en": "Volume of distribution",
|
| 45 |
+
"built": "2026-08-22",
|
| 46 |
+
"stype": "Vdss",
|
| 47 |
+
"units": {
|
| 48 |
+
"L.kg-1": 1.0,
|
| 49 |
+
"mL.kg-1": 0.001
|
| 50 |
+
},
|
| 51 |
+
"log": true,
|
| 52 |
+
"clip": [
|
| 53 |
+
-3.0,
|
| 54 |
+
3.0
|
| 55 |
+
]
|
| 56 |
}
|
index.html
CHANGED
|
@@ -298,10 +298,28 @@ function terrain(items,link){
|
|
| 298 |
/* ๋ถ๋ฅ ์ ์ฉ ๋ถ๋ฌธ์ MAE ๊ธฐ์ค์ ์ด ์๋ค. ๊ทธ๋ฐ ๋ถ๋ฌธ์ 0 ์ผ๋ก ์ฒ๋ฆฌํ๋ฉด ์งํ๋ ๋งจ ์ผ์ชฝ์
|
| 299 |
๋ถ์ด "์ธก์ ํ๊ณ์ ๋๋ฌํ๋ค"๋ก ๋ณด์ธ๋ค. ์ฌ์ง ๋ชปํ ๊ฒ๊ณผ ์ฌ์ ์์ ๊ฒ์ ๋ค๋ฅด๋ฏ๋ก ๋น์ด๋ค. */
|
| 300 |
const blurb=b=>esc(L==="ko"?(b.blurb||""):(b.blurb_en||b.blurb||""));
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 301 |
const ratioOf=b=>{
|
| 302 |
const nf=(b.noise_floor||{}).sd_single;
|
|
|
|
| 303 |
const maes=Object.values(b.baselines||{}).map(v=>v.mae).filter(v=>v!=null);
|
| 304 |
-
if(!
|
| 305 |
return Math.min(...maes)/nf;
|
| 306 |
};
|
| 307 |
|
|
@@ -405,13 +423,14 @@ async function paintLeaders(){
|
|
| 405 |
const rows=d.rows.map(r=>{
|
| 406 |
const ld=r.leader; // ์ ์ญ L ์ ์ธ์ด๋ค. ๊ฐ๋ฆฌ์ง ์๋๋ค
|
| 407 |
// ์ ์๋ ๋ถ๋ฌธ๋ง๋ค ์ฃผ์งํ๊ฐ ๋ค๋ฅด๋ค. ํ๊ท ๋ถ๋ฌธ์ MAE, ๋ถ๋ฅ ์ ์ฉ ๋ถ๋ฌธ์ AUROC.
|
| 408 |
-
const
|
| 409 |
-
const score=ld?(
|
| 410 |
-
const bas=
|
|
|
|
| 411 |
let vs="โ";
|
| 412 |
if(ld&&score!=null&&bas!=null){
|
| 413 |
-
const better=
|
| 414 |
-
const gap=
|
| 415 |
vs=`<span class="${better?"gain":"loss"}">${better?"โฒ":"โผ"} ${Math.abs(gap).toFixed(3)}</span>`;
|
| 416 |
}
|
| 417 |
return `<tr>
|
|
@@ -470,7 +489,7 @@ function boardMini(b){
|
|
| 470 |
<div class="nm">${esc(b.board)}<span class="chip">${b.split_grade}/${b.answer_grade}</span></div>
|
| 471 |
<div class="bl">${blurb(b)}</div>
|
| 472 |
<div class="ds">${t.cardCompounds(b.n_test.toLocaleString())} ยท ${t.noiseH} ${f((b.noise_floor||{}).sd_single)}<br>
|
| 473 |
-
${esc(b.best_baseline)} ${
|
| 474 |
<div class="mt"><span>${esc(b.source)}</span><span>${ratioOf(b)==null?"โ":f(ratioOf(b),2)+"ร"}</span></div></a>`;
|
| 475 |
}
|
| 476 |
|
|
@@ -527,8 +546,9 @@ async function paneRank(b){
|
|
| 527 |
๋๋ถ๋ถ ๊ทธ ๋จ๊ณ์์ ๋จ์ด์ง๋ค. */
|
| 528 |
function promptFor(b){
|
| 529 |
const nf=(b.noise_floor||{}).sd_single;
|
|
|
|
| 530 |
const bl=Object.entries(b.baselines||{})
|
| 531 |
-
.map(([k,v])=>` ${k}: ${
|
| 532 |
const unit = b.type && b.type.indexOf("logS")>=0
|
| 533 |
? "logS = log10(์ฉํด๋ in mol/L)"
|
| 534 |
: b.threshold==null ? "๋ถ๋ฌธ ์ ์๊ฐ" : "p ์ค์ผ์ผ = -log10(๋๋ in M)";
|
|
@@ -552,7 +572,7 @@ b.cut ? ` โ
${b.cut}๋
์ดํ ์ฒ์ ๋ณด๊ณ ๋ ํํฉ๋ฌผ์ ํ์ต์ ๋ฃ์ง
|
|
| 552 |
` ์ ๋ต์ ์กฐํํด ์ฑ์ฐ์ง ๋ง ๊ฒ. ์์ธก๊ฐ์ด ์ค์ธก๊ณผ ์์ ์๋ฆฌ๊น์ง ์ผ์นํ๋ ๋ฐ๋๋ฅผ ๊ฒ์ฌํ๋ค.`,
|
| 553 |
``,
|
| 554 |
`[ํ๊ฐ]`,
|
| 555 |
-
` ์ฃผ์งํ ${
|
| 556 |
nf ? ` ์ด ๋ถ๋ฌธ์ ์คํ ์ฌํ ์ค์ฐจ๋ ${f(nf)} ์ด๋ค. ๊ทธ๋ณด๋ค ์์ ์ฐจ์ด๋ ์์๋ก ์ธ์ ๋์ง ์๋๋ค.` : ``,
|
| 557 |
` ๋์ด์ผ ํ ๊ธฐ์ค์ :`,
|
| 558 |
bl,
|
|
@@ -562,9 +582,26 @@ bl,
|
|
| 562 |
}
|
| 563 |
|
| 564 |
function starterFor(b){
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 565 |
return [
|
| 566 |
`# ${b.board} ์ ์ถ ๋ผ๋`,
|
| 567 |
-
`import json, math, requests, numpy as np`,
|
| 568 |
`from rdkit import Chem`,
|
| 569 |
`from rdkit.Chem import rdFingerprintGenerator`,
|
| 570 |
`import lightgbm as lgb`,
|
|
@@ -573,31 +610,83 @@ function starterFor(b){
|
|
| 573 |
`API = "https://www.ebi.ac.uk/chembl/api/data/activity.json"`,
|
| 574 |
`rows, off = [], 0`,
|
| 575 |
`while True:`,
|
| 576 |
-
|
| 577 |
-
` "standard_relation": "=", "limit": 1000, "offset": off}`,
|
| 578 |
` d = requests.get(API, params=q, timeout=120).json()`,
|
| 579 |
` rows += d["activities"]; off += 1000`,
|
| 580 |
` if off >= d["page_meta"]["total_count"]: break`,
|
| 581 |
``,
|
| 582 |
-
`# 2)
|
|
|
|
|
|
|
|
|
|
| 583 |
`rec = {}`,
|
| 584 |
`for r in rows:`,
|
| 585 |
` s, v, u, y = r["canonical_smiles"], r["standard_value"], r["standard_units"], r["document_year"]`,
|
| 586 |
-
` if not (s and v and
|
|
|
|
|
|
|
|
|
|
|
|
|
| 587 |
` m = Chem.MolFromSmiles(s)`,
|
| 588 |
` if m is None or float(v) <= 0: continue`,
|
| 589 |
` k = Chem.MolToInchiKey(m)`,
|
| 590 |
` rec.setdefault(k, {"y": [], "p": [], "m": m})`,
|
| 591 |
-
` rec[k]["y"].append(int(y)); rec[k]["p"].append(
|
|
|
|
|
|
|
|
|
|
| 592 |
`train = {k: v for k, v in rec.items() if min(v["y"]) < ${b.cut||2022}} # โ
ํ
์คํธ์
์ ์ธ`,
|
| 593 |
``,
|
| 594 |
-
`#
|
| 595 |
`gen = rdFingerprintGenerator.GetMorganGenerator(radius=2, fpSize=2048)`,
|
| 596 |
`X = np.array([gen.GetFingerprintAsNumPy(v["m"]) for v in train.values()])`,
|
| 597 |
`Y = np.array([float(np.median(v["p"])) for v in train.values()])`,
|
| 598 |
`model = lgb.LGBMRegressor(n_estimators=500, learning_rate=0.05).fit(X, Y)`,
|
| 599 |
``,
|
| 600 |
-
`#
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 601 |
`test = json.load(open("${b.board.toLowerCase()}_test.json", encoding="utf-8"))`,
|
| 602 |
`Xt = np.array([gen.GetFingerprintAsNumPy(Chem.MolFromSmiles(c["smiles"]))`,
|
| 603 |
` for c in test["compounds"]])`,
|
|
@@ -611,8 +700,9 @@ function starterFor(b){
|
|
| 611 |
|
| 612 |
function paneGuide(b){
|
| 613 |
const pr=promptFor(b), sk=starterFor(b);
|
|
|
|
| 614 |
const bl=Object.entries(b.baselines||{}).sort((x,y)=>
|
| 615 |
-
(
|
| 616 |
$("#pane").innerHTML=`
|
| 617 |
<p class="lede" style="margin:6px 0 18px">${t.gdIntro}</p>
|
| 618 |
<h3>${t.gdWhat}</h3><p class="dim" style="font-size:14.5px">${t.gdWhatD}</p>
|
|
@@ -626,9 +716,9 @@ function paneGuide(b){
|
|
| 626 |
<pre class="fig" style="white-space:pre;overflow-x:auto;margin:0;font-size:12px">${esc(sk)}</pre></div>
|
| 627 |
<h3>${t.gdTarget}</h3><p class="dim" style="font-size:14px">${t.gdTargetD}</p>
|
| 628 |
<div class="tw"><table><thead><tr><th style="text-align:left;width:auto">${t.baseH}</th>
|
| 629 |
-
<th>
|
| 630 |
${bl.map(([k,v])=>`<tr><td style="text-align:left">${esc(k)}</td>
|
| 631 |
-
<td>${v.
|
| 632 |
</tbody></table></div>
|
| 633 |
<h3>${t.gdRules}</h3>
|
| 634 |
<ol class="cl" style="grid-template-columns:1fr">
|
|
@@ -657,7 +747,9 @@ function paneInfo(b){
|
|
| 657 |
<dt>${t.kOverlap}</dt><dd>${t.overlapNote}</dd>
|
| 658 |
<dt>${t.kThr}</dt><dd>${b.threshold} ยท ${t.posRate((b.positive_rate*100).toFixed(1))}</dd>
|
| 659 |
<dt>${t.kSha}</dt><dd>${esc(b.dataset_sha)}</dd>
|
| 660 |
-
<dt>${t.kLicense}</dt><dd>
|
|
|
|
|
|
|
| 661 |
<h3>${t.noiseH} <span class="dim" style="font-weight:400;font-size:14px">(4)</span></h3>
|
| 662 |
<div class="fig">${t.noiseDesc}<br>
|
| 663 |
${t.noisePairs(nf.pairs.toLocaleString(),nf.compounds.toLocaleString())}<br>
|
|
|
|
| 298 |
/* ๋ถ๋ฅ ์ ์ฉ ๋ถ๋ฌธ์ MAE ๊ธฐ์ค์ ์ด ์๋ค. ๊ทธ๋ฐ ๋ถ๋ฌธ์ 0 ์ผ๋ก ์ฒ๋ฆฌํ๋ฉด ์งํ๋ ๋งจ ์ผ์ชฝ์
|
| 299 |
๋ถ์ด "์ธก์ ํ๊ณ์ ๋๋ฌํ๋ค"๋ก ๋ณด์ธ๋ค. ์ฌ์ง ๋ชปํ ๊ฒ๊ณผ ์ฌ์ ์์ ๊ฒ์ ๋ค๋ฅด๋ฏ๋ก ๋น์ด๋ค. */
|
| 300 |
const blurb=b=>esc(L==="ko"?(b.blurb||""):(b.blurb_en||b.blurb||""));
|
| 301 |
+
/* ๋ถ๋ฌธ๋ง๋ค ์ฃผ์งํ๊ฐ ๋ค๋ฅด๋ค. ํ์ ์ ํ ๊ณณ์๋ง ๋๋ค.
|
| 302 |
+
ํ๋ฉด์ด MAE ๋ง ์๊ณ ์์ด์, ํ๋กํ์ผ ์๊ด์ผ๋ก ์ฑ์ ๋๋ Phenotype ์ด "ํ์ต ๊ธฐ์ค์ ์ด
|
| 303 |
+
์์ ์์ธก์ 0.003 ์ฐจ์ด๋ก ๊ฐ์ ํ ์ด๊ธด๋ค"๋ก ๋ณด์๋ค. ์ค์ ์งํ๋ก๋ 0.092 ๋ 0.159 ๋ก
|
| 304 |
+
์ก์ ๋ฐ๋ฅ์ 7.6๋ฐฐ ์ฐจ์ด๋ค. ์งํ๋ฅผ ์๋ชป ๋์ฐ๋ฉด ๋ถ๋ฌธ์ด ๊ณ ์ฅ ๋ ๊ฒ์ฒ๋ผ ์ฝํ๋ค. */
|
| 305 |
+
const metricOf=b=>{
|
| 306 |
+
if((b||{}).metric==="profile_corr") return {key:"profile_corr",hb:true,label:"ํ๋กํ์ผ ์๊ด"};
|
| 307 |
+
const bl=Object.values((b||{}).baselines||{});
|
| 308 |
+
if(bl.length&&bl.every(v=>v.mae==null)&&bl.some(v=>v.auroc!=null))
|
| 309 |
+
return {key:"auroc",hb:true,label:"AUROC"};
|
| 310 |
+
return {key:"mae",hb:false,label:"MAE"};
|
| 311 |
+
};
|
| 312 |
+
const metricLabel=b=>{const m=metricOf(b);
|
| 313 |
+
return L==="ko"?(m.label+" ("+(m.hb?"๋์์๋ก":"๋ฎ์์๋ก")+" ์ข์)")
|
| 314 |
+
:(m.label+" ("+(m.hb?"higher":"lower")+" is better)");};
|
| 315 |
+
const blScore=(b,v)=>v?v[metricOf(b).key]:null;
|
| 316 |
+
/* ์ธก์ ํ๊ณ๋น๋ ์ค์ฐจ ์งํ ์์์๋ง ๋ป์ด ์๋ค. ์๊ด ๋ถ๋ฌธ์์ MAE ๋ก ๊ณ์ฐํ๋ฉด
|
| 317 |
+
3.40/0.0088 = 385 ๊ฐ์ ๋ฌด์๋ฏธํ ์๊ฐ ๋์จ๋ค. ์ฌ์ง ๋ชปํ ๊ฒ์ ๋น์ด๋ค. */
|
| 318 |
const ratioOf=b=>{
|
| 319 |
const nf=(b.noise_floor||{}).sd_single;
|
| 320 |
+
if(metricOf(b).key!=="mae"||!nf) return null;
|
| 321 |
const maes=Object.values(b.baselines||{}).map(v=>v.mae).filter(v=>v!=null);
|
| 322 |
+
if(!maes.length) return null;
|
| 323 |
return Math.min(...maes)/nf;
|
| 324 |
};
|
| 325 |
|
|
|
|
| 423 |
const rows=d.rows.map(r=>{
|
| 424 |
const ld=r.leader; // ์ ์ญ L ์ ์ธ์ด๋ค. ๊ฐ๋ฆฌ์ง ์๋๋ค
|
| 425 |
// ์ ์๋ ๋ถ๋ฌธ๋ง๋ค ์ฃผ์งํ๊ฐ ๋ค๋ฅด๋ค. ํ๊ท ๋ถ๋ฌธ์ MAE, ๋ถ๋ฅ ์ ์ฉ ๋ถ๋ฌธ์ AUROC.
|
| 426 |
+
const hb=!!r.higher_better;
|
| 427 |
+
const score=ld?(ld.score!=null?ld.score:(hb?ld.auroc:ld.mae)):null;
|
| 428 |
+
const bas=r.baseline_best_score!=null?r.baseline_best_score
|
| 429 |
+
:(hb?r.baseline_best_auroc:r.baseline_best);
|
| 430 |
let vs="โ";
|
| 431 |
if(ld&&score!=null&&bas!=null){
|
| 432 |
+
const better=hb?score>bas:score<bas;
|
| 433 |
+
const gap=hb?(score-bas):(bas-score);
|
| 434 |
vs=`<span class="${better?"gain":"loss"}">${better?"โฒ":"โผ"} ${Math.abs(gap).toFixed(3)}</span>`;
|
| 435 |
}
|
| 436 |
return `<tr>
|
|
|
|
| 489 |
<div class="nm">${esc(b.board)}<span class="chip">${b.split_grade}/${b.answer_grade}</span></div>
|
| 490 |
<div class="bl">${blurb(b)}</div>
|
| 491 |
<div class="ds">${t.cardCompounds(b.n_test.toLocaleString())} ยท ${t.noiseH} ${f((b.noise_floor||{}).sd_single)}<br>
|
| 492 |
+
${esc(b.best_baseline)} ${f(blScore(b,bl))}</div>
|
| 493 |
<div class="mt"><span>${esc(b.source)}</span><span>${ratioOf(b)==null?"โ":f(ratioOf(b),2)+"ร"}</span></div></a>`;
|
| 494 |
}
|
| 495 |
|
|
|
|
| 546 |
๋๋ถ๋ถ ๊ทธ ๋จ๊ณ์์ ๋จ์ด์ง๋ค. */
|
| 547 |
function promptFor(b){
|
| 548 |
const nf=(b.noise_floor||{}).sd_single;
|
| 549 |
+
const mk=metricOf(b);
|
| 550 |
const bl=Object.entries(b.baselines||{})
|
| 551 |
+
.map(([k,v])=>` ${k}: ${mk.label} ${f(v[mk.key])}`).join("\n");
|
| 552 |
const unit = b.type && b.type.indexOf("logS")>=0
|
| 553 |
? "logS = log10(์ฉํด๋ in mol/L)"
|
| 554 |
: b.threshold==null ? "๋ถ๋ฌธ ์ ์๊ฐ" : "p ์ค์ผ์ผ = -log10(๋๋ in M)";
|
|
|
|
| 572 |
` ์ ๋ต์ ์กฐํํด ์ฑ์ฐ์ง ๋ง ๊ฒ. ์์ธก๊ฐ์ด ์ค์ธก๊ณผ ์์ ์๋ฆฌ๊น์ง ์ผ์นํ๋ ๋ฐ๋๋ฅผ ๊ฒ์ฌํ๋ค.`,
|
| 573 |
``,
|
| 574 |
`[ํ๊ฐ]`,
|
| 575 |
+
` ์ฃผ์งํ ${metricLabel(b)}`,
|
| 576 |
nf ? ` ์ด ๋ถ๋ฌธ์ ์คํ ์ฌํ ์ค์ฐจ๋ ${f(nf)} ์ด๋ค. ๊ทธ๋ณด๋ค ์์ ์ฐจ์ด๋ ์์๋ก ์ธ์ ๋์ง ์๋๋ค.` : ``,
|
| 577 |
` ๋์ด์ผ ํ ๊ธฐ์ค์ :`,
|
| 578 |
bl,
|
|
|
|
| 582 |
}
|
| 583 |
|
| 584 |
function starterFor(b){
|
| 585 |
+
/* ๋ถ๋ฌธ์ ์ธ ์ข
๋ฅ๋ค. ํ๋์ ๋ผ๋๋ก ๋ฎ์ผ๋ฉด ๋๋จธ์ง ๋์ ๋์๊ฐ์ง ์๋๋ค.
|
| 586 |
+
|
| 587 |
+
ChEMBL ํ์ ํ์ฑ target_chembl_id + standard_type ์ผ๋ก ์กฐํํ๋ค.
|
| 588 |
+
ChEMBL ๋ฌผ์ฑยท์ ์ธํฌ ํ์ ์ด ์๊ฑฐ๋ ๊ท ์ด๋ค. standard_type ๊ณผ assay ์ค๋ช
์ผ๋ก ๊ณ ๋ฅธ๋ค.
|
| 589 |
+
๊ทธ ์ธ (JUMP ๋ฑ) ChEMBL ์ ์๋ค. ์กฐํ๋ฌธ์ ์ง์ด๋ด์ง ์๋๋ค.
|
| 590 |
+
|
| 591 |
+
์ธ ๋ฒ์งธ๋ฅผ ์ฒซ ๋ฒ์งธ ๋ผ๋๋ก ๋ด๋ณด๋ด๋ค๊ฐ, ํ์ ์๋ฆฌ์ em dash ๊ฐ ๋ฐํ ์ฝ๋๋ฅผ
|
| 592 |
+
์ฐธ๊ฐ์๏ฟฝ๏ฟฝ๊ฒ ์ฃผ๊ณ ์์๋ค. ๊ทธ๋๋ก ๋๋ฆฌ๋ฉด ๋น ํ๋ จ์
์ด ๋์จ๋ค. */
|
| 593 |
+
const isChembl=/^CHEMBL[0-9]+$/.test(String(b.target||""));
|
| 594 |
+
const stype=b.stype||b.type;
|
| 595 |
+
if(!isChembl && !b.stype) return starterNoChembl(b);
|
| 596 |
+
const q=[` q = {"standard_type": "${stype}", "standard_relation": "=",`];
|
| 597 |
+
if(isChembl) q.push(` "target_chembl_id": "${b.target}",`);
|
| 598 |
+
q.push(` "limit": 1000, "offset": off}`);
|
| 599 |
+
const filt=[];
|
| 600 |
+
if(b.assay_keep) filt.push(`ak = re.compile(r"${b.assay_keep}", re.I)`);
|
| 601 |
+
if(b.assay_drop) filt.push(`ad = re.compile(r"${b.assay_drop}", re.I)`);
|
| 602 |
return [
|
| 603 |
`# ${b.board} ์ ์ถ ๋ผ๋`,
|
| 604 |
+
`import json, math, re, requests, numpy as np`,
|
| 605 |
`from rdkit import Chem`,
|
| 606 |
`from rdkit.Chem import rdFingerprintGenerator`,
|
| 607 |
`import lightgbm as lgb`,
|
|
|
|
| 610 |
`API = "https://www.ebi.ac.uk/chembl/api/data/activity.json"`,
|
| 611 |
`rows, off = [], 0`,
|
| 612 |
`while True:`,
|
| 613 |
+
...q,
|
|
|
|
| 614 |
` d = requests.get(API, params=q, timeout=120).json()`,
|
| 615 |
` rows += d["activities"]; off += 1000`,
|
| 616 |
` if off >= d["page_meta"]["total_count"]: break`,
|
| 617 |
``,
|
| 618 |
+
filt.length?`# 2) ์คํ๋ฒ ์ ๋ณ โ ๊ฐ์ ์ด๋ฆ์ ์ธก์ ๋ ์กฐ๊ฑด์ด ๋ค๋ฅด๋ฉด ๊ฐ์ด ๋ค๋ฅด๋ค`:``,
|
| 619 |
+
...filt,
|
| 620 |
+
``,
|
| 621 |
+
`# 3) ์ ์ โ InChIKey ๋ก ์ ๊ณ , ๊ธฐ์ค์ผ ์ดํ๋ ๋ฒ๋ฆฐ๋ค`,
|
| 622 |
`rec = {}`,
|
| 623 |
`for r in rows:`,
|
| 624 |
` s, v, u, y = r["canonical_smiles"], r["standard_value"], r["standard_units"], r["document_year"]`,
|
| 625 |
+
` if not (s and v and y): continue`,
|
| 626 |
+
b.assay_keep?` if not ak.search(r.get("assay_description") or ""): continue`:``,
|
| 627 |
+
b.assay_drop?` if ad.search(r.get("assay_description") or ""): continue`:``,
|
| 628 |
+
b.log===false?` if u not in (None, ""): continue # ์ด ๋ถ๋ฌธ ๊ฐ์ ๋ฌด๋จ์๋ค`
|
| 629 |
+
:` if u != "nM": continue`,
|
| 630 |
` m = Chem.MolFromSmiles(s)`,
|
| 631 |
` if m is None or float(v) <= 0: continue`,
|
| 632 |
` k = Chem.MolToInchiKey(m)`,
|
| 633 |
` rec.setdefault(k, {"y": [], "p": [], "m": m})`,
|
| 634 |
+
b.log===false?` rec[k]["y"].append(int(y)); rec[k]["p"].append(float(v))`
|
| 635 |
+
:` rec[k]["y"].append(int(y)); rec[k]["p"].append(9.0 - math.log10(float(v)))`,
|
| 636 |
+
b.clip?`rec = {k: v for k, v in rec.items()`:``,
|
| 637 |
+
b.clip?` if ${b.clip[0]} <= float(np.median(v["p"])) <= ${b.clip[1]}} # ๋ฌผ๋ฆฌ์ ๋ฒ์ ๋ฐ์ ์
๋ ฅ ์ค๋ฅ๋ค`:``,
|
| 638 |
`train = {k: v for k, v in rec.items() if min(v["y"]) < ${b.cut||2022}} # โ
ํ
์คํธ์
์ ์ธ`,
|
| 639 |
``,
|
| 640 |
+
`# 4) ํน์ง ยท ํ์ต`,
|
| 641 |
`gen = rdFingerprintGenerator.GetMorganGenerator(radius=2, fpSize=2048)`,
|
| 642 |
`X = np.array([gen.GetFingerprintAsNumPy(v["m"]) for v in train.values()])`,
|
| 643 |
`Y = np.array([float(np.median(v["p"])) for v in train.values()])`,
|
| 644 |
`model = lgb.LGBMRegressor(n_estimators=500, learning_rate=0.05).fit(X, Y)`,
|
| 645 |
``,
|
| 646 |
+
`# 5) ์์ธก ยท ์ ์ฅ`,
|
| 647 |
+
`test = json.load(open("${b.board.toLowerCase()}_test.json", encoding="utf-8"))`,
|
| 648 |
+
`Xt = np.array([gen.GetFingerprintAsNumPy(Chem.MolFromSmiles(c["smiles"]))`,
|
| 649 |
+
` for c in test["compounds"]])`,
|
| 650 |
+
`p = model.predict(Xt)`,
|
| 651 |
+
`with open("predictions.csv", "w") as f:`,
|
| 652 |
+
` f.write("compound_id,prediction\n")`,
|
| 653 |
+
` for c, v in zip(test["compounds"], p):`,
|
| 654 |
+
` f.write("%s,%.4f\n" % (c["compound_id"], v))`
|
| 655 |
+
].filter(x=>x!==``||true).join("\n");
|
| 656 |
+
}
|
| 657 |
+
|
| 658 |
+
/* ChEMBL ์์ ๋์ค์ง ์๋ ๋ถ๋ฌธ. ์กฐํ๋ฌธ์ ์ง์ด๋ด์ง ์๊ณ , ์๋ฃ๊ฐ ์ด๋ ์๋์ง ๋ฐํ๋ค.
|
| 659 |
+
ํ๋ จ ๋ผ๋ฒจ์ ์ฐ๋ฆฌ๊ฐ ๋ง๋ ํ๋ณธ์ด๋ฏ๋ก ๋์ ๋ง๋ค์ด ์ค ์ ์๋ค - ๊ท์น ๊ทธ๋๋ก,
|
| 660 |
+
์ฐธ๊ฐ์๊ฐ ๊ณต๊ฐ ์๋ฃ๋ฅผ ์ง์ ํ๋ ์ด์
ํ๋ค. */
|
| 661 |
+
function starterNoChembl(b){
|
| 662 |
+
return [
|
| 663 |
+
`# ${b.board} ์ ์ถ ๋ผ๋`,
|
| 664 |
+
`#`,
|
| 665 |
+
`# ์ด ๋ถ๋ฌธ์ ChEMBL ํ์ฑ ์กฐํ๋ก ๋ง๋ค์ด์ง์ง ์๋๋ค. ์ถ์ฒ: ${b.source}`,
|
| 666 |
+
`# ํ๋ จ ๋ผ๋ฒจ์ ๋ณธ ์ํ๋๊ฐ ๋ง๋ ํ๋ณธ์ด๋ผ ๋ฐฐํฌํ์ง ์๋๋ค. ๊ท์น 3์กฐ๋๋ก`,
|
| 667 |
+
`# ๊ณต๊ฐ ์์๋ฃ์์ ์ง์ ๋ง๋ค์ด ์จ์ผ ํ๋ค.`,
|
| 668 |
+
`#`,
|
| 669 |
+
`# ์๋๋ ํ์ตยท์์ธกยท์ ์ฅ ๋ถ๋ถ์ด๋ค. load_training() ๋ง ์ฑ์ฐ๋ฉด ๋๋ค.`,
|
| 670 |
+
``,
|
| 671 |
+
`import json, numpy as np`,
|
| 672 |
+
`from rdkit import Chem`,
|
| 673 |
+
`from rdkit.Chem import rdFingerprintGenerator`,
|
| 674 |
+
`import lightgbm as lgb`,
|
| 675 |
+
``,
|
| 676 |
+
`def load_training():`,
|
| 677 |
+
` """(SMILES, ๋ชฉํ๊ฐ) ๋ชฉ๋ก์ ๋ธ๋ค.`,
|
| 678 |
+
` ์ถ์ฒ: ${b.source}`,
|
| 679 |
+
` ${b.cut?("โ
"+b.cut+"๋
์ดํ ์ฒ์ ๋ณด๊ณ ๋ ํํฉ๋ฌผ์ ๋ฃ์ง ๋ง ๊ฒ โ ๊ทธ๊ฒ์ด ํ
์คํธ์
์ด๋ค."):"์ํ ํํฉ๋ฌผ๊ณผ ๊ฒน์น์ง ์๊ฒ ๊ตฌ์ฑํ ๊ฒ."}`,
|
| 680 |
+
` """`,
|
| 681 |
+
` raise NotImplementedError("๊ณต๊ฐ ์์๋ฃ์์ ์ง์ ๊ตฌ์ฑํ๋ค")`,
|
| 682 |
+
``,
|
| 683 |
+
`pairs = load_training()`,
|
| 684 |
+
`gen = rdFingerprintGenerator.GetMorganGenerator(radius=2, fpSize=2048)`,
|
| 685 |
+
`mols = [Chem.MolFromSmiles(s) for s, _ in pairs]`,
|
| 686 |
+
`X = np.array([gen.GetFingerprintAsNumPy(m) for m in mols if m is not None])`,
|
| 687 |
+
`Y = np.array([y for (s, y), m in zip(pairs, mols) if m is not None])`,
|
| 688 |
+
`model = lgb.LGBMRegressor(n_estimators=500, learning_rate=0.05).fit(X, Y)`,
|
| 689 |
+
``,
|
| 690 |
`test = json.load(open("${b.board.toLowerCase()}_test.json", encoding="utf-8"))`,
|
| 691 |
`Xt = np.array([gen.GetFingerprintAsNumPy(Chem.MolFromSmiles(c["smiles"]))`,
|
| 692 |
` for c in test["compounds"]])`,
|
|
|
|
| 700 |
|
| 701 |
function paneGuide(b){
|
| 702 |
const pr=promptFor(b), sk=starterFor(b);
|
| 703 |
+
const mk=metricOf(b);
|
| 704 |
const bl=Object.entries(b.baselines||{}).sort((x,y)=>
|
| 705 |
+
(mk.hb?-1:1)*((x[1][mk.key]??0)-(y[1][mk.key]??0)));
|
| 706 |
$("#pane").innerHTML=`
|
| 707 |
<p class="lede" style="margin:6px 0 18px">${t.gdIntro}</p>
|
| 708 |
<h3>${t.gdWhat}</h3><p class="dim" style="font-size:14.5px">${t.gdWhatD}</p>
|
|
|
|
| 716 |
<pre class="fig" style="white-space:pre;overflow-x:auto;margin:0;font-size:12px">${esc(sk)}</pre></div>
|
| 717 |
<h3>${t.gdTarget}</h3><p class="dim" style="font-size:14px">${t.gdTargetD}</p>
|
| 718 |
<div class="tw"><table><thead><tr><th style="text-align:left;width:auto">${t.baseH}</th>
|
| 719 |
+
<th>${esc(metricLabel(b))}</th></tr></thead><tbody>
|
| 720 |
${bl.map(([k,v])=>`<tr><td style="text-align:left">${esc(k)}</td>
|
| 721 |
+
<td>${v[mk.key]!=null?f(v[mk.key]):"โ"}</td></tr>`).join("")}
|
| 722 |
</tbody></table></div>
|
| 723 |
<h3>${t.gdRules}</h3>
|
| 724 |
<ol class="cl" style="grid-template-columns:1fr">
|
|
|
|
| 747 |
<dt>${t.kOverlap}</dt><dd>${t.overlapNote}</dd>
|
| 748 |
<dt>${t.kThr}</dt><dd>${b.threshold} ยท ${t.posRate((b.positive_rate*100).toFixed(1))}</dd>
|
| 749 |
<dt>${t.kSha}</dt><dd>${esc(b.dataset_sha)}</dd>
|
| 750 |
+
<dt>${t.kLicense}</dt><dd>${/JUMP/i.test(b.source||"")
|
| 751 |
+
? "JUMP Cell Painting ยท CC0"
|
| 752 |
+
: "ChEMBL ยท CC BY-SA 3.0"}</dd></dl>
|
| 753 |
<h3>${t.noiseH} <span class="dim" style="font-weight:400;font-size:14px">(4)</span></h3>
|
| 754 |
<div class="fig">${t.noiseDesc}<br>
|
| 755 |
${t.noisePairs(nf.pairs.toLocaleString(),nf.compounds.toLocaleString())}<br>
|