TEZv commited on
Commit
13bdb66
·
verified ·
1 Parent(s): dbdba07

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +447 -406
app.py CHANGED
@@ -18,6 +18,7 @@ TXT = "#f1f5f9"
18
  GRN = "#22c55e"
19
  RED = "#ef4444"
20
  DIM = "#8e9bae"
 
21
 
22
  LOG_PATH = Path("/tmp/lab_journal.csv")
23
 
@@ -26,13 +27,11 @@ def log_entry(tab, inputs, result, note=""):
26
  write_header = not LOG_PATH.exists()
27
  with open(LOG_PATH, "a", newline="", encoding="utf-8") as f:
28
  w = csv.DictWriter(f, fieldnames=["timestamp","tab","inputs","result","note"])
29
- if write_header:
30
- w.writeheader()
31
  w.writerow({"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M"),
32
  "tab": tab, "inputs": str(inputs),
33
  "result": str(result)[:200], "note": note})
34
- except Exception:
35
- pass
36
 
37
  def load_journal():
38
  try:
@@ -167,9 +166,8 @@ def predict_drug(pocket):
167
  fig, ax = plt.subplots(figsize=(6, 4), facecolor=CARD)
168
  ax.set_facecolor(CARD)
169
  ax.barh(df["Compound"], df["Final_score"], color=ACC)
170
- ax.set_xlabel("Final Score", color=TXT)
171
- ax.tick_params(colors=TXT)
172
- for sp in ax.spines.values(): sp.set_edgecolor("#334155")
173
  ax.set_title(f"Top compounds — {pocket}", color=TXT, fontsize=10)
174
  plt.tight_layout()
175
  buf = BytesIO(); plt.savefig(buf, format="png", dpi=120, facecolor=CARD); plt.close(); buf.seek(0)
@@ -179,8 +177,7 @@ def predict_drug(pocket):
179
  def predict_variant(hgvs, sift, polyphen, gnomad):
180
  hgvs = hgvs.strip()
181
  if hgvs in VARIANT_DB:
182
- r = VARIANT_DB[hgvs]
183
- cls, conf, score = r["cls"], r["conf"], r["score"]
184
  else:
185
  score = 0.0
186
  if sift < 0.05: score += 0.4
@@ -191,19 +188,16 @@ def predict_variant(hgvs, sift, polyphen, gnomad):
191
  conf = "High" if (sift < 0.01 or sift > 0.9) else "Moderate"
192
  colour = RED if "Pathogenic" in cls else GRN
193
  icon = "⚠️ WARNING" if "Pathogenic" in cls else "✅ OK"
194
- explanation = PLAIN.get(cls, "")
195
  log_entry("S1-A | S1-R1 | OpenVariant", hgvs or f"SIFT={sift}", f"{cls} score={score}")
196
  return (
197
  f"<div style=\'background:{CARD};padding:16px;border-radius:8px;font-family:sans-serif;color:{TXT}\'>"
198
- f"<p style=\'font-size:11px;color:{DIM};margin:0 0 8px\'>"
199
- f"S1 · Biomedical &nbsp;›&nbsp; S1-A · PHYLO-GENOMICS &nbsp;›&nbsp; S1-R1 · OpenVariant</p>"
200
  f"<h3 style=\'color:{colour};margin:0 0 8px\'>{icon} {cls}</h3>"
201
  f"<p>Score: <b>{score:.3f}</b> &nbsp;|&nbsp; Confidence: <b>{conf}</b></p>"
202
- f"<div style=\'background:#334155;border-radius:4px;height:14px\'>"
203
  f"<div style=\'background:{colour};height:14px;border-radius:4px;width:{int(score*100)}%\'></div></div>"
204
- f"<p style=\'margin-top:12px\'>{explanation}</p>"
205
- f"<p style=\'font-size:11px;color:{DIM}\'>Research only. Not clinical advice.</p>"
206
- f"</div>"
207
  )
208
 
209
  def predict_corona(size, zeta, peg, lipid):
@@ -216,43 +210,39 @@ def predict_corona(size, zeta, peg, lipid):
216
  dominant = ["ApoE","Albumin","Fibrinogen","Vitronectin","ApoA-I"][min(score, 4)]
217
  efficacy = "High" if score >= 4 else "Medium" if score >= 2 else "Low"
218
  log_entry("S1-D | S1-R6 | Corona", f"size={size},peg={peg}", f"dominant={dominant}")
219
- return (f"**Dominant corona protein:** {dominant}\n\n"
220
- f"**Predicted efficacy:** {efficacy}\n\n"
221
- f"**Score:** {score}/6")
222
 
223
  def predict_cancer(c1,c2,c3,c4,c5,c6,c7,c8,c9,c10):
224
- vals = [c1,c2,c3,c4,c5,c6,c7,c8,c9,c10]
225
- names = list(BM_W.keys())
226
- weights = list(BM_W.values())
227
- raw = sum(v*w for v,w in zip(vals, weights))
228
- prob = 1 / (1 + np.exp(-raw * 2))
229
- label = "CANCER" if prob > 0.5 else "HEALTHY"
230
- colour = RED if prob > 0.5 else GRN
231
  contribs = [v*w for v,w in zip(vals, weights)]
232
- fig, ax = plt.subplots(figsize=(6, 3.5), facecolor=CARD)
233
  ax.set_facecolor(CARD)
234
  ax.barh(names, contribs, color=[ACC if c > 0 else ACC2 for c in contribs])
235
  ax.axvline(0, color=TXT, linewidth=0.8)
236
  ax.set_xlabel("Contribution to cancer score", color=TXT)
237
  ax.tick_params(colors=TXT, labelsize=8)
238
- for sp in ax.spines.values(): sp.set_edgecolor("#334155")
239
  ax.set_title("Protein contributions", color=TXT, fontsize=10)
240
  plt.tight_layout()
241
  buf = BytesIO(); plt.savefig(buf, format="png", dpi=120, facecolor=CARD); plt.close(); buf.seek(0)
242
  log_entry("S1-E | S1-R9 | LiquidBiopsy", f"CTHRC1={c1},FHL2={c2}", f"{label} {prob:.2f}")
243
  return (
244
- f"<div style=\'background:{CARD};padding:12px;border-radius:8px;font-family:sans-serif;\'>"
245
  f"<p style=\'font-size:11px;color:{DIM};margin:0 0 6px\'>S1-E · PHYLO-BIOMARKERS · S1-R9</p>"
246
- f"<span style=\'color:{colour};font-size:22px;font-weight:bold\'>{label}</span><br>"
247
  f"<span style=\'color:{TXT};font-size:14px\'>Probability: {prob:.2f}</span></div>"
248
  ), Image.open(buf)
249
 
250
  def predict_flow(size, zeta, peg, charge, flow_rate):
251
  csi = round(min((flow_rate/40)*0.6 + (peg/5)*0.2 + (1 if charge=="Cationic" else 0)*0.2, 1.0), 3)
252
  stability = "High remodeling" if csi > 0.6 else "Medium" if csi > 0.3 else "Stable"
253
- t = np.linspace(0, 60, 200)
254
- kf = 0.03 * (1 + flow_rate/40)
255
- ks = 0.038 * (1 + flow_rate/40)
256
  fig, ax = plt.subplots(figsize=(6, 3.5), facecolor=CARD)
257
  ax.set_facecolor(CARD)
258
  ax.plot(t, 60*np.exp(-0.03*t)+20, color="#60a5fa", ls="--", label="Albumin (static)")
@@ -260,9 +250,8 @@ def predict_flow(size, zeta, peg, charge, flow_rate):
260
  ax.plot(t, 14*(1-np.exp(-0.038*t))+5, color=ACC, ls="--", label="ApoE (static)")
261
  ax.plot(t, 20*(1-np.exp(-ks*t))+5, color=ACC, label="ApoE (flow)")
262
  ax.set_xlabel("Time (min)", color=TXT); ax.set_ylabel("% Corona", color=TXT)
263
- ax.tick_params(colors=TXT)
264
- ax.legend(fontsize=7, labelcolor=TXT, facecolor=CARD)
265
- for sp in ax.spines.values(): sp.set_edgecolor("#334155")
266
  ax.set_title("Vroman Effect — flow vs static", color=TXT, fontsize=9)
267
  plt.tight_layout()
268
  buf = BytesIO(); plt.savefig(buf, format="png", dpi=120, facecolor=CARD); plt.close(); buf.seek(0)
@@ -270,15 +259,15 @@ def predict_flow(size, zeta, peg, charge, flow_rate):
270
  return f"**Corona Shift Index: {csi}** — {stability}", Image.open(buf)
271
 
272
  def predict_bbb(smiles, pka, zeta):
273
- logp = smiles.count("C")*0.3 - smiles.count("O")*0.5 + 1.5
274
  apoe_pct = max(0, min(40, (7.0-pka)*8 + abs(zeta)*0.5 + logp*0.8))
275
  bbb_prob = min(0.95, apoe_pct/30)
276
- tier = "HIGH (>20%)" if apoe_pct > 20 else "MEDIUM (10-20%)" if apoe_pct > 10 else "LOW (<10%)"
277
- cats = ["ApoE%","BBB","logP","pKa fit","Zeta"]
278
- vals = [apoe_pct/40, bbb_prob, min(logp/5,1), (7-abs(pka-6.5))/7, (10-abs(zeta))/10]
279
- angles = np.linspace(0, 2*np.pi, len(cats), endpoint=False).tolist()
280
- v2, a2 = vals+[vals[0]], angles+[angles[0]]
281
- fig, ax = plt.subplots(figsize=(5, 4), subplot_kw={"polar":True}, facecolor=CARD)
282
  ax.set_facecolor(CARD)
283
  ax.plot(a2, v2, color=ACC, linewidth=2); ax.fill(a2, v2, color=ACC, alpha=0.2)
284
  ax.set_xticks(angles); ax.set_xticklabels(cats, color=TXT, fontsize=8)
@@ -291,12 +280,11 @@ def predict_bbb(smiles, pka, zeta):
291
  def extract_corona(text):
292
  out = {"nanoparticle_composition":"","size_nm":None,"zeta_mv":None,"PDI":None,
293
  "protein_source":"","corona_proteins":[],"confidence":{}}
294
- m = re.search(r"(\d+\.?\d*)\s*(?:nm|nanometer)", text, re.I)
295
- if m: out["size_nm"] = float(m.group(1)); out["confidence"]["size_nm"] = "HIGH"
296
- m = re.search(r"([+-]?\d+\.?\d*)\s*mV", text, re.I)
297
- if m: out["zeta_mv"] = float(m.group(1)); out["confidence"]["zeta_mv"] = "HIGH"
298
- m = re.search(r"PDI\s*[=:of]*\s*(\d+\.?\d*)", text, re.I)
299
- if m: out["PDI"] = float(m.group(1)); out["confidence"]["PDI"] = "HIGH"
300
  for src in ["human plasma","human serum","fetal bovine serum","FBS","PBS"]:
301
  if src.lower() in text.lower():
302
  out["protein_source"] = src; out["confidence"]["protein_source"] = "HIGH"; break
@@ -312,364 +300,380 @@ def extract_corona(text):
312
  log_entry("S1-D | S1-R10 | NLP", text[:80], f"proteins={len(out['corona_proteins'])}")
313
  return json.dumps(out, indent=2), summary
314
 
315
- # ── SECTION BADGE HELPER ──────────────────────────────────────────────────────
316
- def badge(sphere_code, sphere_name, project_code, project_name, description, metric=""):
317
- metric_html = (f"<span style=\'background:#1e3a5f;color:{ACC2};padding:2px 8px;"
318
- f"border-radius:4px;font-size:11px;margin-left:8px\'>{metric}</span>"
319
- if metric else "")
 
 
 
 
 
 
 
 
 
 
 
320
  return (
321
  f"<div style=\'background:{CARD};border-left:3px solid {ACC};"
322
- f"padding:10px 14px;border-radius:0 6px 6px 0;margin-bottom:6px;\'>"
323
- f"<span style=\'color:{DIM};font-size:11px\'>S1 · Biomedical &nbsp;›&nbsp; "
324
- f"{sphere_code} · {sphere_name} &nbsp;›&nbsp; {project_code}</span>{metric_html}<br>"
325
- f"<span style=\'color:{TXT};font-weight:bold;font-size:15px\'>{project_name}</span><br>"
326
- f"<span style=\'color:{DIM};font-size:12px\'>{description}</span>"
327
  f"</div>"
328
  )
329
 
330
  # ── CSS ───────────────────────────────────────────────────────────────────────
331
- css = (
332
- f"body,.gradio-container{{background:{BG}!important;color:{TXT}!important}}"
333
- f".tab-nav button{{color:{TXT}!important;background:{CARD}!important;font-size:13px!important}}"
334
- f".tab-nav button.selected{{border-bottom:2px solid {ACC}!important;color:{ACC}!important}}"
335
- f"h1,h2,h3{{color:{ACC}!important}}"
336
- f".gr-button-primary{{background:{ACC}!important;border:none!important}}"
337
- f"footer{{display:none!important}}"
338
- # section divider tabs look different
339
- f".tab-nav button[data-testid*='divider']{{color:{DIM}!important;cursor:default!important;"
340
- f"border-bottom:1px solid #334155!important;font-size:11px!important}}"
341
- )
342
-
343
- # ── CONTENT STRINGS ───────────────────────────────────────────────────────────
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
344
  MAP_HTML = f"""
345
- <div style="background:{CARD};padding:20px;border-radius:8px;font-family:monospace;
346
- font-size:13px;line-height:1.9;color:{TXT}">
347
 
348
- <span style="color:{ACC};font-size:15px;font-weight:bold">K R&D Lab · S1 Biomedical</span>
349
- <span style="color:{DIM};font-size:11px">Science Sphere, sub-direction 1</span>
350
  <br><br>
351
 
352
- <span style="color:{ACC2}">S1-A · PHYLO-GENOMICS</span> &nbsp;<span style="color:{DIM}">← What breaks in DNA</span><br>
353
- &nbsp;&nbsp;&nbsp;├─ <b>S1-R1</b> &nbsp;OpenVariant &nbsp;<span style="color:{GRN}">AUC=0.939 </span><br>
354
- &nbsp;&nbsp;&nbsp;├─ <b>S1-R1b</b> Somatic classifier &nbsp;<span style="color:#f59e0b">🔶 In progress</span><br>
355
- &nbsp;&nbsp;&nbsp;└─ <b>S1-R12a</b> Rare variants (DIPG · UVM) &nbsp;<span style="color:{DIM}">🔴 Planned</span><br>
356
- <br>
357
-
358
- <span style="color:{ACC2}">S1-B · PHYLO-RNA</span> &nbsp;<span style="color:{DIM}">← How to silence it via RNA</span><br>
359
- &nbsp;&nbsp;&nbsp;├─ <b>S1-R2</b> &nbsp;miRNA silencing (BRCA1/2, TP53) &nbsp;<span style="color:{GRN}"></span><br>
360
- &nbsp;&nbsp;&nbsp;├─ <b>S1-R3</b> &nbsp;siRNA synthetic lethal (20+ cancers) &nbsp;<span style="color:{GRN}">✅</span><br>
361
- &nbsp;&nbsp;&nbsp;├─ <b>S1-R4</b> &nbsp;lncRNA-TREM2 ceRNA network &nbsp;<span style="color:{GRN}"></span><br>
362
- &nbsp;&nbsp;&nbsp;└─ <b>S1-R4b</b> ASO designer &nbsp;<span style="color:{GRN}"></span><br>
363
- <br>
364
-
365
- <span style="color:{ACC2}">S1-C · PHYLO-DRUG</span> &nbsp;<span style="color:{DIM}">← Which molecule treats it</span><br>
366
- &nbsp;&nbsp;&nbsp;├─ <b>S1-R5</b> &nbsp;FGFR3 RNA-directed compounds &nbsp;<span style="color:{GRN}">✅</span><br>
367
- &nbsp;&nbsp;&nbsp;├─ <b>S1-R5b</b> Synthetic lethal drug mapping &nbsp;<span style="color:#f59e0b">🔶</span><br>
368
- &nbsp;&nbsp;&nbsp;└─ <b>S1-R13</b> m6A × Ferroptosis × Circadian ⭐ &nbsp;<span style="color:{DIM}">🔴 Frontier</span><br>
369
- <br>
370
-
371
- <span style="color:{ACC2}">S1-D · PHYLO-LNP</span> &nbsp;<span style="color:{DIM}">← How to deliver the drug</span><br>
372
- &nbsp;&nbsp;&nbsp;├─ <b>S1-R6</b> &nbsp;LNP corona (serum) &nbsp;<span style="color:{GRN}">AUC=0.791 </span><br>
373
- &nbsp;&nbsp;&nbsp;├─ <b>S1-R7</b> &nbsp;Flow corona — Vroman effect &nbsp;<span style="color:{GRN}"></span><br>
374
- &nbsp;&nbsp;&nbsp;├─ <b>S1-R8</b> &nbsp;LNP brain / BBB / ApoE &nbsp;<span style="color:{GRN}">✅</span><br>
375
- &nbsp;&nbsp;&nbsp;├─ <b>S1-R10</b> AutoCorona NLP &nbsp;<span style="color:{GRN}">F1=0.71 ✅</span><br>
376
- &nbsp;&nbsp;&nbsp;─ <b>S1-R11</b> CSF · Vitreous · Bone Marrow ⭐ &nbsp;<span style="color:{DIM}">🔴 0 prior studies</span><br>
377
- <br>
378
-
379
- <span style="color:{ACC2}">S1-E · PHYLO-BIOMARKERS</span> &nbsp;<span style="color:{DIM}">← Detect without biopsy</span><br>
380
- &nbsp;&nbsp;&nbsp;├─ <b>S1-R9</b> &nbsp;Liquid Biopsy classifier &nbsp;<span style="color:{GRN}">AUC=0.992* ✅</span><br>
381
- &nbsp;&nbsp;&nbsp;├─ <b>S1-R9b</b> Protein panel validator &nbsp;<span style="color:#f59e0b">🔶</span><br>
382
- &nbsp;&nbsp;&nbsp;└─ <b>S1-R9c</b> ctDNA gap analysis &nbsp;<span style="color:{DIM}">🔴</span><br>
383
- <br>
384
-
385
- <span style="color:{ACC2}">S1-F · PHYLO-RARE</span> &nbsp;<span style="color:{DIM}">← Where nobody looked yet</span><br>
386
- &nbsp;&nbsp;&nbsp;├─ <b>S1-R12b</b> DIPG toolkit (H3K27M) &nbsp;<span style="color:{DIM}">🔴</span><br>
387
- &nbsp;&nbsp;&nbsp;├─ <b>S1-R12c</b> UVM toolkit (GNAQ/GNA11) &nbsp;<span style="color:{DIM}">🔴</span><br>
388
- &nbsp;&nbsp;&nbsp;└─ <b>S1-R12d</b> pAML toolkit (FLT3-ITD) &nbsp;<span style="color:{DIM}">🔴</span><br>
389
- <br>
390
- <span style="color:{DIM};font-size:12px">
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
391
  ✅ Active in this demo &nbsp;·&nbsp; 🔶 In progress &nbsp;·&nbsp; 🔴 Planned / Frontier<br>
392
- = gap research (0–1 prior studies globally) &nbsp;·&nbsp; * = tissue proxy, plasma validation pending
393
  </span>
394
  </div>
395
  """
396
 
397
- LEARNING_CASES = f"""
398
- ## 🧪 Guided Investigations — S1 Biomedical
399
-
400
- > Progress through levels: 🟢 Beginner → 🟡 Intermediate → 🔴 Advanced
401
-
402
- ---
403
-
404
- ### 🟢 Case 1 · S1-A · S1-R1 — Variant Pathogenicity
405
- **Why does the same position give two different outcomes?**
406
-
407
- 1. **OpenVariant** → `BRCA1:p.R1699Q` → Benign
408
- 2. **OpenVariant** → `BRCA1:p.R1699W` → Pathogenic
409
- 3. Same position (R1699), different amino acid (Q vs W). What changed?
410
-
411
- *Key concept: Amino acid polarity determines BRCT domain folding. Q is polar-uncharged; W is bulky-aromatic.*
412
-
413
- ---
414
-
415
- ### 🟢 Case 2 · S1-D · S1-R6 + S1-R8 — PEG and Brain Delivery
416
- **How does PEG% change which protein coats your nanoparticle?**
417
-
418
- 1. **LNP Corona** → Ionizable, Zeta=−5, Size=100, **PEG=0.5%** → note protein
419
- 2. **PEG=2.5%** → compare dominant protein
420
- 3. **LNP Brain** → pKa=6.5 → check ApoE%
421
-
422
- *Key concept: More PEG → steric shielding → less Fibrinogen → more ApoE → better BBB crossing.*
423
-
424
- ---
425
-
426
- ### 🟡 Case 3 · S1-D · S1-R7 — Vroman Effect Under Flow
427
- **Does blood flow speed reshape the corona over time?**
428
-
429
- 1. **Flow Corona** → Flow=0, Ionizable → observe ApoE plateau minute
430
- 2. **Flow=40** (arterial) → compare same curve
431
- 3. At what minute does ApoE dominate under arterial flow?
432
-
433
- *Key concept: Albumin adsorbs first (abundance), then displaced by ApoE (affinity). Flow accelerates exchange 3–4×.*
434
-
435
- ---
436
-
437
- ### 🟡 Case 4 · S1-B · S1-R3 — Novel siRNA Targets
438
- **Which cancer type has the most undrugged therapeutic targets?**
439
-
440
- 1. **TP53 siRNA** → LUAD → count Drug_status = "Novel"
441
- 2. Repeat for BRCA, COAD
442
- 3. Pick one Novel gene → search: `[gene name] cancer PubMed`
443
-
444
- *Key concept: "Novel" = no approved or clinical drug yet — highest opportunity for new therapeutic development.*
445
-
446
- ---
447
-
448
- ### 🔴 Case 5 · S1-E · S1-R9 — Cancer Detection Threshold
449
- **What is the minimum signal that flips diagnosis to CANCER?**
450
-
451
- 1. **Liquid Biopsy** → all sliders = 0 → HEALTHY
452
- 2. Set CTHRC1=2.5, FHL2=2.0, LDHA=1.8 → observe
453
- 3. Reset all. Increase only CTHRC1 step by step. At what value does it tip?
454
-
455
- *Key concept: CTHRC1 weight=0.18 is the dominant feature. One protein can outweigh a full panel.*
456
-
457
- ---
458
-
459
- ### 🔴 Case 6 · S1-B + S1-C · Cross-tool — Convergent Evidence
460
- **Is there target overlap between RNA silencing and drug discovery?**
461
-
462
- 1. **miRNA** → gene=TP53 → find top silenced targets (BCL2, CDK6)
463
- 2. **FGFR3 Drug** → P1 → find if CDK6 pathway appears in compound targets
464
- 3. **siRNA** → BRCA → does CDK6 appear in synthetic lethal list?
465
-
466
- *Key concept: Convergence across S1-B and S1-C = higher-confidence therapeutic hypothesis. This is how real pipelines are built.*
467
- """
468
-
469
- # ── BLOCKS UI ─────────────────────────────────────────────────────────────────
470
  with gr.Blocks(css=css, title="K R&D Lab · S1 Biomedical") as demo:
471
 
472
  gr.Markdown(
473
- "# 🔬 K R&D Lab · Science Sphere\n"
474
- "**S1 Biomedical** 10 active projects · "
475
- "[Oksana Kolisnyk](https://kosatiks-group.pp.ua) · KOSATIKS GROUP\n"
476
- "> Research only. Not clinical advice. &nbsp;|&nbsp; "
477
  "[GitHub](https://github.com/K-RnD-Lab) &nbsp; "
478
- "[HuggingFace](https://huggingface.co/K-RnD-Lab)"
 
479
  )
480
 
481
- with gr.Tabs():
 
 
 
482
 
483
- # ── MAP ───────────────────────────────────────────────────────────────
484
  with gr.TabItem("🗺️ Lab Map"):
485
  gr.HTML(MAP_HTML)
486
 
487
- # ── S1-A · GENOMICS ───────────────────────────────────────────────────
488
- with gr.TabItem("── S1-A · GENOMICS ──"):
489
- gr.HTML(
490
- f"<div style=\'background:{CARD};padding:14px;border-radius:8px;\'>"
491
- f"<b style=\'color:{ACC2}\'>S1-A · PHYLO-GENOMICS</b>"
492
- f"<span style=\'color:{DIM};font-size:12px\'> — What breaks in DNA</span><br>"
493
- f"<span style=\'color:{TXT};font-size:13px\'>Projects: S1-R1 (active) · S1-R1b (in progress) · S1-R12a (planned)</span>"
494
- f"</div>"
495
- )
496
-
497
- with gr.TabItem("S1-R1 · OpenVariant"):
498
- gr.HTML(badge("S1-A","PHYLO-GENOMICS","S1-R1","OpenVariant",
499
- "SNV pathogenicity classifier · ClinVar 2026","AUC = 0.939"))
500
- hgvs = gr.Textbox(label="HGVS notation", placeholder="BRCA1:p.R1699Q")
501
- gr.Markdown("**Or enter functional scores manually:**")
502
- with gr.Row():
503
- sift = gr.Slider(0,1,value=0.5,step=0.01,label="SIFT (0=damaging)")
504
- pp = gr.Slider(0,1,value=0.5,step=0.01,label="PolyPhen-2")
505
- gn = gr.Slider(0,0.01,value=0.001,step=0.0001,label="gnomAD AF")
506
- b5 = gr.Button("Predict Pathogenicity", variant="primary")
507
- o5 = gr.HTML()
508
- gr.Examples([["BRCA1:p.R1699Q",0.82,0.05,0.0012],
509
- ["TP53:p.R248W",0.00,1.00,0.0],
510
- ["BRCA2:p.D2723A",0.01,0.98,0.0]], inputs=[hgvs,sift,pp,gn])
511
- b5.click(predict_variant, [hgvs,sift,pp,gn], o5)
512
-
513
- # ── S1-B · RNA THERAPEUTICS ───────────────────────────────────────────
514
- with gr.TabItem("── S1-B · RNA THER ──"):
515
- gr.HTML(
516
- f"<div style=\'background:{CARD};padding:14px;border-radius:8px;\'>"
517
- f"<b style=\'color:{ACC2}\'>S1-B · PHYLO-RNA</b>"
518
- f"<span style=\'color:{DIM};font-size:12px\'> — How to silence it via RNA</span><br>"
519
- f"<span style=\'color:{TXT};font-size:13px\'>Projects: S1-R2 · S1-R3 · S1-R4 · S1-R4b (all active)</span>"
520
- f"</div>"
521
- )
522
-
523
- with gr.TabItem("S1-R2 · miRNA"):
524
- gr.HTML(badge("S1-B","PHYLO-RNA","S1-R2","miRNA Silencing",
525
- "Downregulated miRNAs in tumor suppressor knockouts · BRCA1/2 · TP53"))
526
- g1 = gr.Dropdown(["BRCA2","BRCA1","TP53"], value="BRCA2", label="Gene")
527
- b1 = gr.Button("Find miRNAs", variant="primary")
528
- o1 = gr.Dataframe(label="Top 5 downregulated miRNAs")
529
- gr.Examples([["BRCA2"],["TP53"]], inputs=[g1])
530
- b1.click(predict_mirna, g1, o1)
531
-
532
- with gr.TabItem("S1-R3 · siRNA"):
533
- gr.HTML(badge("S1-B","PHYLO-RNA","S1-R3","siRNA Synthetic Lethal",
534
- "TP53-null cancer — novel undrugged SL targets · LUAD · BRCA · COAD"))
535
- g2 = gr.Dropdown(["LUAD","BRCA","COAD"], value="LUAD", label="Cancer type")
536
- b2 = gr.Button("Find Targets", variant="primary")
537
- o2 = gr.Dataframe(label="Top 5 synthetic lethal targets")
538
- gr.Examples([["LUAD"],["BRCA"],["COAD"]], inputs=[g2])
539
- b2.click(predict_sirna, g2, o2)
540
-
541
- with gr.TabItem("S1-R4 · lncRNA"):
542
- gr.HTML(badge("S1-B","PHYLO-RNA","S1-R4","lncRNA-TREM2 Network",
543
- "ceRNA axis in Alzheimer neuroinflammation · CYTOR→miR-138-5p→AKT1"))
544
- b3 = gr.Button("Load Results", variant="primary")
545
- o3a = gr.Dataframe(label="ceRNA Network")
546
- o3b = gr.Dataframe(label="ASO Candidates (S1-R4b)")
547
- b3.click(get_lncrna, [], [o3a, o3b])
548
-
549
- # ── S1-C · DRUG DISCOVERY ─────────────────────────────────────────────
550
- with gr.TabItem("── S1-C · DRUG ──"):
551
- gr.HTML(
552
- f"<div style=\'background:{CARD};padding:14px;border-radius:8px;\'>"
553
- f"<b style=\'color:{ACC2}\'>S1-C · PHYLO-DRUG</b>"
554
- f"<span style=\'color:{DIM};font-size:12px\'> Which molecule treats it</span><br>"
555
- f"<span style=\'color:{TXT};font-size:13px\'>Projects: S1-R5 (active) · S1-R5b (in progress) · S1-R13 (frontier)</span>"
556
- f"</div>"
557
- )
558
-
559
- with gr.TabItem("S1-R5 · Drug"):
560
- gr.HTML(badge("S1-C","PHYLO-DRUG","S1-R5","FGFR3 RNA-Directed Drug Discovery",
561
- "Small molecules binding FGFR3 RNA structural pockets · ChEMBL screen",
562
- "top score 0.793"))
563
- g4 = gr.Radio(["P1 (hairpin loop)","P10 (G-quadruplex)"],
564
- value="P1 (hairpin loop)", label="Target pocket")
565
- b4 = gr.Button("Screen Compounds", variant="primary")
566
- o4t = gr.Dataframe(label="Top 5 candidates")
567
- o4p = gr.Image(label="Binding scores")
568
- gr.Examples([["P1 (hairpin loop)"],["P10 (G-quadruplex)"]], inputs=[g4])
569
- b4.click(predict_drug, g4, [o4t, o4p])
570
-
571
- # ── S1-D · LNP DELIVERY ───────────────────────────────────────────────
572
- with gr.TabItem("── S1-D · LNP ──"):
573
- gr.HTML(
574
- f"<div style=\'background:{CARD};padding:14px;border-radius:8px;\'>"
575
- f"<b style=\'color:{ACC2}\'>S1-D · PHYLO-LNP</b>"
576
- f"<span style=\'color:{DIM};font-size:12px\'> How to deliver the drug to the cell</span><br>"
577
- f"<span style=\'color:{TXT};font-size:13px\'>Active: S1-R6 · S1-R7 · S1-R8 · S1-R10 &nbsp;|&nbsp; "
578
- f"Frontier: S1-R11 (CSF/Vitreous/Bone Marrow — 0 prior studies)</span>"
579
- f"</div>"
580
- )
581
-
582
- with gr.TabItem("S1-R6 · Corona"):
583
- gr.HTML(badge("S1-D","PHYLO-LNP","S1-R6","LNP Protein Corona (Serum)",
584
- "Dominant corona protein from formulation parameters","AUC = 0.791"))
585
- with gr.Row():
586
- sz = gr.Slider(50,300,value=100,step=1,label="Size (nm)")
587
- zt = gr.Slider(-40,10,value=-5,step=1,label="Zeta (mV)")
588
- with gr.Row():
589
- pg = gr.Slider(0,5,value=1.5,step=0.1,label="PEG mol%")
590
- lp = gr.Dropdown(["Ionizable","Cationic","Anionic","Neutral"],value="Ionizable",label="Lipid type")
591
- b6 = gr.Button("Predict", variant="primary"); o6 = gr.Markdown()
592
- gr.Examples([[100,-5,1.5,"Ionizable"],[80,5,0.5,"Cationic"]], inputs=[sz,zt,pg,lp])
593
- b6.click(predict_corona, [sz,zt,pg,lp], o6)
594
-
595
- with gr.TabItem("S1-R7 · Flow"):
596
- gr.HTML(badge("S1-D","PHYLO-LNP","S1-R7","Flow Corona Vroman Effect",
597
- "Blood flow reshapes LNP corona over time · albumin→ApoE exchange kinetics"))
598
- with gr.Row():
599
- s8 = gr.Slider(50,300,value=100,step=1,label="Size (nm)")
600
- z8 = gr.Slider(-40,10,value=-5,step=1,label="Zeta (mV)")
601
- pg8 = gr.Slider(0,5,value=1.5,step=0.1,label="PEG mol%")
602
- with gr.Row():
603
- ch8 = gr.Dropdown(["Ionizable","Cationic","Anionic","Neutral"],value="Ionizable",label="Charge")
604
- fl8 = gr.Slider(0,40,value=20,step=1,label="Flow rate cm/s (aorta=40)")
605
- b8 = gr.Button("Model Vroman Effect", variant="primary")
606
- o8t = gr.Markdown(); o8p = gr.Image(label="Kinetics")
607
- gr.Examples([[100,-5,1.5,"Ionizable",40],[150,5,0.5,"Cationic",10]], inputs=[s8,z8,pg8,ch8,fl8])
608
- b8.click(predict_flow, [s8,z8,pg8,ch8,fl8], [o8t,o8p])
609
-
610
- with gr.TabItem("S1-R8 · Brain"):
611
- gr.HTML(badge("S1-D","PHYLO-LNP","S1-R8","LNP Brain Delivery",
612
- "ApoE corona % and blood-brain barrier crossing probability"))
613
- smi = gr.Textbox(label="Ionizable lipid SMILES",value="CC(C)CC(=O)OCC(COC(=O)CC(C)C)OC(=O)CC(C)C")
614
- with gr.Row():
615
- pk = gr.Slider(4,8,value=6.5,step=0.1,label="pKa")
616
- zt9 = gr.Slider(-20,10,value=-3,step=1,label="Zeta (mV)")
617
- b9 = gr.Button("Predict BBB Crossing", variant="primary")
618
- o9t = gr.Markdown(); o9p = gr.Image(label="Radar profile")
619
- gr.Examples([["CC(C)CC(=O)OCC(COC(=O)CC(C)C)OC(=O)CC(C)C",6.5,-3]], inputs=[smi,pk,zt9])
620
- b9.click(predict_bbb, [smi,pk,zt9], [o9t,o9p])
621
-
622
- with gr.TabItem("S1-R10 · NLP"):
623
- gr.HTML(badge("S1-D","PHYLO-LNP","S1-R10","AutoCorona NLP",
624
- "Extract structured LNP data from PubMed/PMC abstracts","F1 = 0.71"))
625
- txt = gr.Textbox(lines=6,label="Paper abstract",placeholder="Paste abstract text here...")
626
- b10 = gr.Button("Extract Data", variant="primary")
627
- o10j = gr.Code(label="Extracted JSON", language="json")
628
- o10f = gr.Textbox(label="Validation flags")
629
- gr.Examples([[
630
- "LNPs composed of MC3, DSPC, Cholesterol (50:10:40 mol%) with 1.5% PEG-DMG. "
631
- "Hydrodynamic diameter was 98 nm, zeta potential -3.2 mV, PDI 0.12. "
632
- "Incubated in human plasma. Corona: albumin, apolipoprotein E, fibrinogen."
633
- ]], inputs=[txt])
634
- b10.click(extract_corona, txt, [o10j, o10f])
635
-
636
- # ── S1-E · BIOMARKERS ─────────────────────────────────────────────────
637
- with gr.TabItem("── S1-E · BIO ──"):
638
- gr.HTML(
639
- f"<div style=\'background:{CARD};padding:14px;border-radius:8px;\'>"
640
- f"<b style=\'color:{ACC2}\'>S1-E · PHYLO-BIOMARKERS</b>"
641
- f"<span style=\'color:{DIM};font-size:12px\'> — Detect cancer without tissue biopsy</span><br>"
642
- f"<span style=\'color:{TXT};font-size:13px\'>Projects: S1-R9 (active) · S1-R9b (in progress) · S1-R9c (planned)</span>"
643
- f"</div>"
644
- )
645
-
646
- with gr.TabItem("S1-R9 · Biopsy"):
647
- gr.HTML(badge("S1-E","PHYLO-BIOMARKERS","S1-R9","Liquid Biopsy Classifier",
648
- "CTHRC1 · FHL2 · LDHA panel · tissue proteomics proxy","AUC = 0.992*"))
649
- with gr.Row():
650
- p1=gr.Slider(-3,3,value=0,step=0.1,label="CTHRC1")
651
- p2=gr.Slider(-3,3,value=0,step=0.1,label="FHL2")
652
- p3=gr.Slider(-3,3,value=0,step=0.1,label="LDHA")
653
- p4=gr.Slider(-3,3,value=0,step=0.1,label="P4HA1")
654
- p5=gr.Slider(-3,3,value=0,step=0.1,label="SERPINH1")
655
- with gr.Row():
656
- p6=gr.Slider(-3,3,value=0,step=0.1,label="ABCA8")
657
- p7=gr.Slider(-3,3,value=0,step=0.1,label="CA4")
658
- p8=gr.Slider(-3,3,value=0,step=0.1,label="CKB")
659
- p9=gr.Slider(-3,3,value=0,step=0.1,label="NNMT")
660
- p10=gr.Slider(-3,3,value=0,step=0.1,label="CACNA2D2")
661
- b7=gr.Button("Classify", variant="primary")
662
- o7t=gr.HTML(); o7p=gr.Image(label="Feature contributions")
663
- gr.Examples([[2,2,1.5,1.8,1.6,-1,-1.2,-0.8,1.4,-1.1],[0,0,0,0,0,0,0,0,0,0]],
664
- inputs=[p1,p2,p3,p4,p5,p6,p7,p8,p9,p10])
665
- b7.click(predict_cancer, [p1,p2,p3,p4,p5,p6,p7,p8,p9,p10], [o7t,o7p])
666
-
667
- # ── LAB ───────────────────────────────────────────────────────────────
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
668
  with gr.TabItem("📓 Journal"):
669
- gr.Markdown("### Lab Journal · Auto-logged by project code\nEvery tool call is saved with its S1-X · S1-RX label.")
670
  with gr.Row():
671
- note_text = gr.Textbox(label="📝 Observation / conclusion",
672
- placeholder="What did you discover?", lines=3)
673
  note_tab = gr.Textbox(label="Project code (e.g. S1-R1)", value="General")
674
  note_last = gr.Textbox(visible=False)
675
  save_btn = gr.Button("💾 Save", variant="primary")
@@ -679,36 +683,73 @@ with gr.Blocks(css=css, title="K R&D Lab · S1 Biomedical") as demo:
679
  refresh_btn.click(load_journal, [], journal_df)
680
  save_btn.click(save_note, [note_text,note_tab,note_last], [save_msg,journal_df])
681
 
 
682
  with gr.TabItem("📚 Learning"):
683
- gr.Markdown(LEARNING_CASES)
684
- gr.Markdown("""---
685
- ### 📖 Quick Reference S1 Active Tools
686
-
687
- | Code | Sub-dir | Tool | Key metric |
688
- |------|---------|------|------------|
689
- | S1-R1 | S1-A | OpenVariant | AUC=0.939 |
690
- | S1-R2 | S1-B | miRNA silencing | hsa-miR-148a-3p top hit |
691
- | S1-R3 | S1-B | siRNA SL targets | SPC24 top in LUAD |
692
- | S1-R4 | S1-B | lncRNA-TREM2 | CYTOR→AKT1 |
693
- | S1-R5 | S1-C | FGFR3 drug | score=0.793 |
694
- | S1-R6 | S1-D | LNP corona | AUC=0.791 |
695
- | S1-R7 | S1-D | Flow corona | 3–4× ApoE acceleration |
696
- | S1-R8 | S1-D | LNP brain | pKa 6.2–6.8 optimal |
697
- | S1-R9 | S1-E | Liquid biopsy | AUC=0.992* |
698
- | S1-R10 | S1-D | AutoCorona NLP | F1=0.71 |
699
-
700
- ### 🔗 Resources
701
- [PubMed](https://pubmed.ncbi.nlm.nih.gov) · [ClinVar](https://ncbi.nlm.nih.gov/clinvar/) ·
702
- [miRBase](https://mirbase.org) · [ChEMBL](https://ebi.ac.uk/chembl/) ·
703
- [DepMap](https://depmap.org) · [UniProt](https://uniprot.org)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
704
  """)
705
 
706
  gr.Markdown(
707
- f"---\n"
708
- f"**K R&D Lab** · Science Sphere · S1 Biomedical · "
709
- f"[GitHub](https://github.com/K-RnD-Lab) · "
710
- f"[HuggingFace](https://huggingface.co/K-RnD-Lab) · "
711
- f"[KOSATIKS GROUP 🦈](https://kosatiks-group.pp.ua) · MIT License"
712
  )
713
 
714
  demo.launch(server_name="0.0.0.0", server_port=7860)
 
18
  GRN = "#22c55e"
19
  RED = "#ef4444"
20
  DIM = "#8e9bae"
21
+ BORDER = "#334155"
22
 
23
  LOG_PATH = Path("/tmp/lab_journal.csv")
24
 
 
27
  write_header = not LOG_PATH.exists()
28
  with open(LOG_PATH, "a", newline="", encoding="utf-8") as f:
29
  w = csv.DictWriter(f, fieldnames=["timestamp","tab","inputs","result","note"])
30
+ if write_header: w.writeheader()
 
31
  w.writerow({"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M"),
32
  "tab": tab, "inputs": str(inputs),
33
  "result": str(result)[:200], "note": note})
34
+ except Exception: pass
 
35
 
36
  def load_journal():
37
  try:
 
166
  fig, ax = plt.subplots(figsize=(6, 4), facecolor=CARD)
167
  ax.set_facecolor(CARD)
168
  ax.barh(df["Compound"], df["Final_score"], color=ACC)
169
+ ax.set_xlabel("Final Score", color=TXT); ax.tick_params(colors=TXT)
170
+ for sp in ax.spines.values(): sp.set_edgecolor(BORDER)
 
171
  ax.set_title(f"Top compounds — {pocket}", color=TXT, fontsize=10)
172
  plt.tight_layout()
173
  buf = BytesIO(); plt.savefig(buf, format="png", dpi=120, facecolor=CARD); plt.close(); buf.seek(0)
 
177
  def predict_variant(hgvs, sift, polyphen, gnomad):
178
  hgvs = hgvs.strip()
179
  if hgvs in VARIANT_DB:
180
+ r = VARIANT_DB[hgvs]; cls, conf, score = r["cls"], r["conf"], r["score"]
 
181
  else:
182
  score = 0.0
183
  if sift < 0.05: score += 0.4
 
188
  conf = "High" if (sift < 0.01 or sift > 0.9) else "Moderate"
189
  colour = RED if "Pathogenic" in cls else GRN
190
  icon = "⚠️ WARNING" if "Pathogenic" in cls else "✅ OK"
 
191
  log_entry("S1-A | S1-R1 | OpenVariant", hgvs or f"SIFT={sift}", f"{cls} score={score}")
192
  return (
193
  f"<div style=\'background:{CARD};padding:16px;border-radius:8px;font-family:sans-serif;color:{TXT}\'>"
194
+ f"<p style=\'font-size:11px;color:{DIM};margin:0 0 8px\'>S1-A · PHYLO-GENOMICS · S1-R1</p>"
 
195
  f"<h3 style=\'color:{colour};margin:0 0 8px\'>{icon} {cls}</h3>"
196
  f"<p>Score: <b>{score:.3f}</b> &nbsp;|&nbsp; Confidence: <b>{conf}</b></p>"
197
+ f"<div style=\'background:{BORDER};border-radius:4px;height:14px\'>"
198
  f"<div style=\'background:{colour};height:14px;border-radius:4px;width:{int(score*100)}%\'></div></div>"
199
+ f"<p style=\'margin-top:12px\'>{PLAIN.get(cls,'')}</p>"
200
+ f"<p style=\'font-size:11px;color:{DIM}\'>Research only. Not clinical advice.</p></div>"
 
201
  )
202
 
203
  def predict_corona(size, zeta, peg, lipid):
 
210
  dominant = ["ApoE","Albumin","Fibrinogen","Vitronectin","ApoA-I"][min(score, 4)]
211
  efficacy = "High" if score >= 4 else "Medium" if score >= 2 else "Low"
212
  log_entry("S1-D | S1-R6 | Corona", f"size={size},peg={peg}", f"dominant={dominant}")
213
+ return f"**Dominant corona protein:** {dominant}\n\n**Predicted efficacy:** {efficacy}\n\n**Score:** {score}/6"
 
 
214
 
215
  def predict_cancer(c1,c2,c3,c4,c5,c6,c7,c8,c9,c10):
216
+ vals = [c1,c2,c3,c4,c5,c6,c7,c8,c9,c10]
217
+ names, weights = list(BM_W.keys()), list(BM_W.values())
218
+ raw = sum(v*w for v,w in zip(vals, weights))
219
+ prob = 1 / (1 + np.exp(-raw * 2))
220
+ label = "CANCER" if prob > 0.5 else "HEALTHY"
221
+ colour = RED if prob > 0.5 else GRN
 
222
  contribs = [v*w for v,w in zip(vals, weights)]
223
+ fig, ax = plt.subplots(figsize=(6, 3.5), facecolor=CARD)
224
  ax.set_facecolor(CARD)
225
  ax.barh(names, contribs, color=[ACC if c > 0 else ACC2 for c in contribs])
226
  ax.axvline(0, color=TXT, linewidth=0.8)
227
  ax.set_xlabel("Contribution to cancer score", color=TXT)
228
  ax.tick_params(colors=TXT, labelsize=8)
229
+ for sp in ax.spines.values(): sp.set_edgecolor(BORDER)
230
  ax.set_title("Protein contributions", color=TXT, fontsize=10)
231
  plt.tight_layout()
232
  buf = BytesIO(); plt.savefig(buf, format="png", dpi=120, facecolor=CARD); plt.close(); buf.seek(0)
233
  log_entry("S1-E | S1-R9 | LiquidBiopsy", f"CTHRC1={c1},FHL2={c2}", f"{label} {prob:.2f}")
234
  return (
235
+ f"<div style=\'background:{CARD};padding:14px;border-radius:8px;font-family:sans-serif;\'>"
236
  f"<p style=\'font-size:11px;color:{DIM};margin:0 0 6px\'>S1-E · PHYLO-BIOMARKERS · S1-R9</p>"
237
+ f"<span style=\'color:{colour};font-size:24px;font-weight:bold\'>{label}</span><br>"
238
  f"<span style=\'color:{TXT};font-size:14px\'>Probability: {prob:.2f}</span></div>"
239
  ), Image.open(buf)
240
 
241
  def predict_flow(size, zeta, peg, charge, flow_rate):
242
  csi = round(min((flow_rate/40)*0.6 + (peg/5)*0.2 + (1 if charge=="Cationic" else 0)*0.2, 1.0), 3)
243
  stability = "High remodeling" if csi > 0.6 else "Medium" if csi > 0.3 else "Stable"
244
+ t = np.linspace(0, 60, 200)
245
+ kf, ks = 0.03*(1+flow_rate/40), 0.038*(1+flow_rate/40)
 
246
  fig, ax = plt.subplots(figsize=(6, 3.5), facecolor=CARD)
247
  ax.set_facecolor(CARD)
248
  ax.plot(t, 60*np.exp(-0.03*t)+20, color="#60a5fa", ls="--", label="Albumin (static)")
 
250
  ax.plot(t, 14*(1-np.exp(-0.038*t))+5, color=ACC, ls="--", label="ApoE (static)")
251
  ax.plot(t, 20*(1-np.exp(-ks*t))+5, color=ACC, label="ApoE (flow)")
252
  ax.set_xlabel("Time (min)", color=TXT); ax.set_ylabel("% Corona", color=TXT)
253
+ ax.tick_params(colors=TXT); ax.legend(fontsize=7, labelcolor=TXT, facecolor=CARD)
254
+ for sp in ax.spines.values(): sp.set_edgecolor(BORDER)
 
255
  ax.set_title("Vroman Effect — flow vs static", color=TXT, fontsize=9)
256
  plt.tight_layout()
257
  buf = BytesIO(); plt.savefig(buf, format="png", dpi=120, facecolor=CARD); plt.close(); buf.seek(0)
 
259
  return f"**Corona Shift Index: {csi}** — {stability}", Image.open(buf)
260
 
261
  def predict_bbb(smiles, pka, zeta):
262
+ logp = smiles.count("C")*0.3 - smiles.count("O")*0.5 + 1.5
263
  apoe_pct = max(0, min(40, (7.0-pka)*8 + abs(zeta)*0.5 + logp*0.8))
264
  bbb_prob = min(0.95, apoe_pct/30)
265
+ tier = "HIGH (>20%)" if apoe_pct > 20 else "MEDIUM (10-20%)" if apoe_pct > 10 else "LOW (<10%)"
266
+ cats = ["ApoE%","BBB","logP","pKa fit","Zeta"]
267
+ vals = [apoe_pct/40, bbb_prob, min(logp/5,1), (7-abs(pka-6.5))/7, (10-abs(zeta))/10]
268
+ angles = np.linspace(0, 2*np.pi, len(cats), endpoint=False).tolist()
269
+ v2, a2 = vals+[vals[0]], angles+[angles[0]]
270
+ fig, ax = plt.subplots(figsize=(5, 4), subplot_kw={"polar":True}, facecolor=CARD)
271
  ax.set_facecolor(CARD)
272
  ax.plot(a2, v2, color=ACC, linewidth=2); ax.fill(a2, v2, color=ACC, alpha=0.2)
273
  ax.set_xticks(angles); ax.set_xticklabels(cats, color=TXT, fontsize=8)
 
280
  def extract_corona(text):
281
  out = {"nanoparticle_composition":"","size_nm":None,"zeta_mv":None,"PDI":None,
282
  "protein_source":"","corona_proteins":[],"confidence":{}}
283
+ for pat, key in [(r"(\d+\.?\d*)\s*(?:nm|nanometer)","size_nm"),
284
+ (r"([+-]?\d+\.?\d*)\s*mV","zeta_mv"),
285
+ (r"PDI\s*[=:of]*\s*(\d+\.?\d*)","PDI")]:
286
+ m = re.search(pat, text, re.I)
287
+ if m: out[key] = float(m.group(1)); out["confidence"][key] = "HIGH"
 
288
  for src in ["human plasma","human serum","fetal bovine serum","FBS","PBS"]:
289
  if src.lower() in text.lower():
290
  out["protein_source"] = src; out["confidence"]["protein_source"] = "HIGH"; break
 
300
  log_entry("S1-D | S1-R10 | NLP", text[:80], f"proteins={len(out['corona_proteins'])}")
301
  return json.dumps(out, indent=2), summary
302
 
303
+ # ── HELPERS ───────────────────────────────────────────────────────────────────
304
+ def section_header(code, name, tagline, projects_html):
305
+ return (
306
+ f"<div style=\'background:{BG};border:1px solid {BORDER};padding:14px 18px;"
307
+ f"border-radius:8px;margin-bottom:12px;\'>"
308
+ f"<div style=\'display:flex;align-items:baseline;gap:10px;\'>"
309
+ f"<span style=\'color:{ACC2};font-size:16px;font-weight:700\'>{code}</span>"
310
+ f"<span style=\'color:{TXT};font-size:14px;font-weight:600\'>{name}</span>"
311
+ f"<span style=\'color:{DIM};font-size:12px\'>{tagline}</span></div>"
312
+ f"<div style=\'margin-top:8px;font-size:12px;color:{DIM}\'>{projects_html}</div>"
313
+ f"</div>"
314
+ )
315
+
316
+ def proj_badge(code, title, metric=""):
317
+ m = (f"<span style=\'background:#0f2a3f;color:{ACC2};padding:1px 7px;border-radius:3px;"
318
+ f"font-size:10px;margin-left:6px\'>{metric}</span>") if metric else ""
319
  return (
320
  f"<div style=\'background:{CARD};border-left:3px solid {ACC};"
321
+ f"padding:8px 12px;border-radius:0 6px 6px 0;margin-bottom:8px;\'>"
322
+ f"<span style=\'color:{DIM};font-size:11px\'>{code}</span>{m}<br>"
323
+ f"<span style=\'color:{TXT};font-size:14px;font-weight:600\'>{title}</span>"
 
 
324
  f"</div>"
325
  )
326
 
327
  # ── CSS ───────────────────────────────────────────────────────────────────────
328
+ css = f"""
329
+ body, .gradio-container {{ background: {BG} !important; color: {TXT} !important; }}
330
+
331
+ /* OUTER tab bar PHYLO categories */
332
+ .outer-tabs .tab-nav button {{
333
+ color: {TXT} !important;
334
+ background: {CARD} !important;
335
+ font-size: 13px !important;
336
+ font-weight: 600 !important;
337
+ padding: 8px 16px !important;
338
+ border-radius: 6px 6px 0 0 !important;
339
+ }}
340
+ .outer-tabs .tab-nav button.selected {{
341
+ border-bottom: 3px solid {ACC} !important;
342
+ color: {ACC} !important;
343
+ background: {BG} !important;
344
+ }}
345
+
346
+ /* INNER sub-tab bar — individual tools */
347
+ .inner-tabs .tab-nav button {{
348
+ color: {DIM} !important;
349
+ background: {BG} !important;
350
+ font-size: 12px !important;
351
+ font-weight: 500 !important;
352
+ padding: 5px 12px !important;
353
+ border-radius: 4px 4px 0 0 !important;
354
+ border: 1px solid {BORDER} !important;
355
+ border-bottom: none !important;
356
+ margin-right: 3px !important;
357
+ }}
358
+ .inner-tabs .tab-nav button.selected {{
359
+ color: {ACC2} !important;
360
+ background: {CARD} !important;
361
+ border-color: {ACC2} !important;
362
+ border-bottom: none !important;
363
+ }}
364
+ .inner-tabs > .tabitem {{
365
+ background: {CARD} !important;
366
+ border: 1px solid {BORDER} !important;
367
+ border-radius: 0 6px 6px 6px !important;
368
+ padding: 14px !important;
369
+ }}
370
+
371
+ h1, h2, h3 {{ color: {ACC} !important; }}
372
+ .gr-button-primary {{ background: {ACC} !important; border: none !important; }}
373
+ footer {{ display: none !important; }}
374
+ """
375
+
376
+ # ── LAB MAP HTML ──────────────────────────────────────────────────────────────
377
  MAP_HTML = f"""
378
+ <div style="background:{CARD};padding:22px;border-radius:8px;font-family:monospace;
379
+ font-size:13px;line-height:2.0;color:{TXT}">
380
 
381
+ <span style="color:{ACC};font-size:16px;font-weight:bold">K R&D Lab · S1 Biomedical</span>
382
+ <span style="color:{DIM};font-size:11px;margin-left:12px">Science Sphere sub-direction 1</span>
383
  <br><br>
384
 
385
+ <span style="color:{ACC2};font-weight:600">S1-A · PHYLO-GENOMICS</span>
386
+ <span style="color:{DIM}"> — What breaks in DNA</span><br>
387
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R1</b> &nbsp;OpenVariant
388
+ <span style="color:{GRN}"> AUC=0.939 ✅</span><br>
389
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R1b</b> Somatic classifier
390
+ <span style="color:#f59e0b"> 🔶 In progress</span><br>
391
+ &nbsp;&nbsp;&nbsp;└─ <b>S1-R12a</b> Rare variants (DIPG · UVM)
392
+ <span style="color:{DIM}"> 🔴 Planned</span><br><br>
393
+
394
+ <span style="color:{ACC2};font-weight:600">S1-B · PHYLO-RNA</span>
395
+ <span style="color:{DIM}"> — How to silence it via RNA</span><br>
396
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R2</b> &nbsp;miRNA silencing (BRCA1/2, TP53)
397
+ <span style="color:{GRN}"> ✅</span><br>
398
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R3</b> &nbsp;siRNA synthetic lethal (LUAD · BRCA · COAD)
399
+ <span style="color:{GRN}"> ✅</span><br>
400
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R4</b> &nbsp;lncRNA-TREM2 ceRNA network
401
+ <span style="color:{GRN}"> </span><br>
402
+ &nbsp;&nbsp;&nbsp;└─ <b>S1-R4b</b> ASO designer
403
+ <span style="color:{GRN}"> ✅</span><br><br>
404
+
405
+ <span style="color:{ACC2};font-weight:600">S1-C · PHYLO-DRUG</span>
406
+ <span style="color:{DIM}"> — Which molecule treats it</span><br>
407
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R5</b> &nbsp;FGFR3 RNA-directed compounds
408
+ <span style="color:{GRN}"> ✅</span><br>
409
+ &nbsp;&nbsp;&nbsp;─ <b>S1-R5b</b> Synthetic lethal drug mapping
410
+ <span style="color:#f59e0b"> 🔶</span><br>
411
+ &nbsp;&nbsp;&nbsp;└─ <b>S1-R13</b> m6A × Ferroptosis × Circadian ⭐
412
+ <span style="color:{DIM}"> 🔴 Frontier</span><br><br>
413
+
414
+ <span style="color:{ACC2};font-weight:600">S1-D · PHYLO-LNP</span>
415
+ <span style="color:{DIM}"> — How to deliver the drug</span><br>
416
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R6</b> &nbsp;LNP corona (serum)
417
+ <span style="color:{GRN}"> AUC=0.791 ✅</span><br>
418
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R7</b> &nbsp;Flow corona Vroman effect
419
+ <span style="color:{GRN}"></span><br>
420
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R8</b> &nbsp;LNP brain / BBB / ApoE
421
+ <span style="color:{GRN}"></span><br>
422
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R10</b> AutoCorona NLP
423
+ <span style="color:{GRN}"> F1=0.71 ✅</span><br>
424
+ &nbsp;&nbsp;&nbsp;└─ <b>S1-R11</b> CSF · Vitreous · Bone Marrow ⭐
425
+ <span style="color:{DIM}"> 🔴 0 prior studies</span><br><br>
426
+
427
+ <span style="color:{ACC2};font-weight:600">S1-E · PHYLO-BIOMARKERS</span>
428
+ <span style="color:{DIM}"> — Detect without biopsy</span><br>
429
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R9</b> &nbsp;Liquid Biopsy classifier
430
+ <span style="color:{GRN}"> AUC=0.992* ✅</span><br>
431
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R9b</b> Protein panel validator
432
+ <span style="color:#f59e0b"> 🔶</span><br>
433
+ &nbsp;&nbsp;&nbsp;└─ <b>S1-R9c</b> ctDNA gap analysis
434
+ <span style="color:{DIM}"> 🔴</span><br><br>
435
+
436
+ <span style="color:{ACC2};font-weight:600">S1-F · PHYLO-RARE</span>
437
+ <span style="color:{DIM}"> — Where nobody looked yet</span><br>
438
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R12b</b> DIPG toolkit (H3K27M)
439
+ <span style="color:{DIM}"> 🔴</span><br>
440
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R12c</b> UVM toolkit (GNAQ/GNA11)
441
+ <span style="color:{DIM}"> 🔴</span><br>
442
+ &nbsp;&nbsp;&nbsp;└─ <b>S1-R12d</b> pAML toolkit (FLT3-ITD)
443
+ <span style="color:{DIM}"> 🔴</span><br><br>
444
+
445
+ <span style="color:{DIM};font-size:11px">
446
  ✅ Active in this demo &nbsp;·&nbsp; 🔶 In progress &nbsp;·&nbsp; 🔴 Planned / Frontier<br>
447
+ ⭐ gap research (0–1 prior studies globally) &nbsp;·&nbsp; * tissue proxy, plasma validation pending
448
  </span>
449
  </div>
450
  """
451
 
452
+ # ── UI ────────────────────────────────────────────────────────────────────────
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
453
  with gr.Blocks(css=css, title="K R&D Lab · S1 Biomedical") as demo:
454
 
455
  gr.Markdown(
456
+ "# 🔬 K R&D Lab · Science Sphere — S1 Biomedical\n"
457
+ "**Oksana Kolisnyk** · [KOSATIKS GROUP](https://kosatiks-group.pp.ua) &nbsp;|&nbsp; "
 
 
458
  "[GitHub](https://github.com/K-RnD-Lab) &nbsp; "
459
+ "[HuggingFace](https://huggingface.co/K-RnD-Lab) &nbsp;|&nbsp; "
460
+ "*Research only. Not clinical advice.*"
461
  )
462
 
463
+ # ═══════════════════════════════════════════════════════
464
+ # OUTER TABS — one per PHYLO-* category
465
+ # ═══════════════════════════════════════════════════════
466
+ with gr.Tabs(elem_classes="outer-tabs"):
467
 
468
+ # ── 🗺️ MAP ─────────────────────────────────────────
469
  with gr.TabItem("🗺️ Lab Map"):
470
  gr.HTML(MAP_HTML)
471
 
472
+ # ── 🧬 S1-A · PHYLO-GENOMICS ───────────────────────
473
+ with gr.TabItem("🧬 PHYLO-GENOMICS"):
474
+ gr.HTML(section_header(
475
+ "S1-A", "PHYLO-GENOMICS", "— What breaks in DNA",
476
+ "S1-R1 OpenVariant ✅ &nbsp;·&nbsp; S1-R1b Somatic classifier 🔶 &nbsp;·&nbsp; S1-R12a Rare variants 🔴"
477
+ ))
478
+ with gr.Tabs(elem_classes="inner-tabs"):
479
+
480
+ with gr.TabItem("S1-R1 · OpenVariant"):
481
+ gr.HTML(proj_badge("S1-A · PHYLO-GENOMICS · S1-R1",
482
+ "OpenVariant — SNV Pathogenicity Classifier", "AUC = 0.939"))
483
+ hgvs = gr.Textbox(label="HGVS notation", placeholder="BRCA1:p.R1699Q")
484
+ gr.Markdown("**Or enter functional scores manually:**")
485
+ with gr.Row():
486
+ sift = gr.Slider(0,1,value=0.5,step=0.01,label="SIFT (0=damaging)")
487
+ pp = gr.Slider(0,1,value=0.5,step=0.01,label="PolyPhen-2")
488
+ gn = gr.Slider(0,0.01,value=0.001,step=0.0001,label="gnomAD AF")
489
+ b_v = gr.Button("Predict Pathogenicity", variant="primary")
490
+ o_v = gr.HTML()
491
+ gr.Examples([["BRCA1:p.R1699Q",0.82,0.05,0.0012],
492
+ ["TP53:p.R248W",0.00,1.00,0.0],
493
+ ["BRCA2:p.D2723A",0.01,0.98,0.0]], inputs=[hgvs,sift,pp,gn])
494
+ b_v.click(predict_variant, [hgvs,sift,pp,gn], o_v)
495
+
496
+ with gr.TabItem("S1-R1b · Somatic 🔶"):
497
+ gr.HTML(proj_badge("S1-A · PHYLO-GENOMICS · S1-R1b",
498
+ "Somatic Mutation Classifier — BRCA · LUAD panels", "🔶 In progress"))
499
+ gr.Markdown("> This module is in active development. Coming in the next release.")
500
+
501
+ # ── 🔬 S1-B · PHYLO-RNA ────────────────────────────
502
+ with gr.TabItem("🔬 PHYLO-RNA"):
503
+ gr.HTML(section_header(
504
+ "S1-B", "PHYLO-RNA", "— How to silence it via RNA",
505
+ "S1-R2 miRNA ✅ &nbsp;·&nbsp; S1-R3 siRNA ✅ &nbsp;·&nbsp; S1-R4 lncRNA ✅ &nbsp;·&nbsp; S1-R4b ASO ✅"
506
+ ))
507
+ with gr.Tabs(elem_classes="inner-tabs"):
508
+
509
+ with gr.TabItem("S1-R2 · miRNA"):
510
+ gr.HTML(proj_badge("S1-B · PHYLO-RNA · S1-R2",
511
+ "miRNA Silencing BRCA1/2 · TP53 tumor suppressors"))
512
+ g1 = gr.Dropdown(["BRCA2","BRCA1","TP53"], value="BRCA2", label="Gene")
513
+ b1 = gr.Button("Find miRNAs", variant="primary")
514
+ o1 = gr.Dataframe(label="Top 5 downregulated miRNAs")
515
+ gr.Examples([["BRCA2"],["BRCA1"],["TP53"]], inputs=[g1])
516
+ b1.click(predict_mirna, g1, o1)
517
+
518
+ with gr.TabItem("S1-R3 · siRNA"):
519
+ gr.HTML(proj_badge("S1-B · PHYLO-RNA · S1-R3",
520
+ "siRNA Synthetic Lethal — TP53-null · LUAD · BRCA · COAD"))
521
+ g2 = gr.Dropdown(["LUAD","BRCA","COAD"], value="LUAD", label="Cancer type")
522
+ b2 = gr.Button("Find Targets", variant="primary")
523
+ o2 = gr.Dataframe(label="Top 5 synthetic lethal targets")
524
+ gr.Examples([["LUAD"],["BRCA"],["COAD"]], inputs=[g2])
525
+ b2.click(predict_sirna, g2, o2)
526
+
527
+ with gr.TabItem("S1-R4 · lncRNA + ASO"):
528
+ gr.HTML(proj_badge("S1-B · PHYLO-RNA · S1-R4 + S1-R4b",
529
+ "lncRNA-TREM2 ceRNA Network + ASO Candidates · Alzheimer neuroinflammation"))
530
+ b3 = gr.Button("Load Results", variant="primary")
531
+ o3a = gr.Dataframe(label="ceRNA Network (S1-R4)")
532
+ o3b = gr.Dataframe(label="ASO Candidates (S1-R4b)")
533
+ b3.click(get_lncrna, [], [o3a, o3b])
534
+
535
+ # ── 💊 S1-C · PHYLO-DRUG ───────────────────────────
536
+ with gr.TabItem("💊 PHYLO-DRUG"):
537
+ gr.HTML(section_header(
538
+ "S1-C", "PHYLO-DRUG", "— Which molecule treats it",
539
+ "S1-R5 FGFR3 ✅ &nbsp;·&nbsp; S1-R5b SL drug mapping 🔶 &nbsp;·&nbsp; S1-R13 m6A×Ferroptosis×Circadian 🔴⭐"
540
+ ))
541
+ with gr.Tabs(elem_classes="inner-tabs"):
542
+
543
+ with gr.TabItem("S1-R5 · FGFR3"):
544
+ gr.HTML(proj_badge("S1-C · PHYLO-DRUG · S1-R5",
545
+ "FGFR3 RNA-Directed Drug Discovery · ChEMBL screen",
546
+ "top score 0.793"))
547
+ g4 = gr.Radio(["P1 (hairpin loop)","P10 (G-quadruplex)"],
548
+ value="P1 (hairpin loop)", label="Target pocket")
549
+ b4 = gr.Button("Screen Compounds", variant="primary")
550
+ o4t = gr.Dataframe(label="Top 5 candidates")
551
+ o4p = gr.Image(label="Binding scores")
552
+ gr.Examples([["P1 (hairpin loop)"],["P10 (G-quadruplex)"]], inputs=[g4])
553
+ b4.click(predict_drug, g4, [o4t, o4p])
554
+
555
+ with gr.TabItem("S1-R13 · Frontier 🔴⭐"):
556
+ gr.HTML(proj_badge("S1-C · PHYLO-DRUG · S1-R13",
557
+ "m6A × Ferroptosis × Circadian — Pan-cancer triad", "🔴 Frontier"))
558
+ gr.Markdown(
559
+ "> **Research gap:** This triple intersection has never been studied as an integrated system.\n\n"
560
+ "> **Planned datasets:** TCGA-PAAD · GEO m6A atlases · Circadian gene panels\n\n"
561
+ "> **Expected timeline:** Q3 2026"
562
+ )
563
+
564
+ # ── 🧪 S1-D · PHYLO-LNP ────────────────────────────
565
+ with gr.TabItem("🧪 PHYLO-LNP"):
566
+ gr.HTML(section_header(
567
+ "S1-D", "PHYLO-LNP", "— How to deliver the drug to the cell",
568
+ "S1-R6 Corona ✅ · S1-R7 Flow ✅ · S1-R8 Brain · S1-R10 NLP ✅ · S1-R11 CSF/BM 🔴⭐"
569
+ ))
570
+ with gr.Tabs(elem_classes="inner-tabs"):
571
+
572
+ with gr.TabItem("S1-R6 · Corona"):
573
+ gr.HTML(proj_badge("S1-D · PHYLO-LNP · S1-R6",
574
+ "LNP Protein Corona (Serum)", "AUC = 0.791"))
575
+ with gr.Row():
576
+ sz = gr.Slider(50,300,value=100,step=1,label="Size (nm)")
577
+ zt = gr.Slider(-40,10,value=-5,step=1,label="Zeta (mV)")
578
+ with gr.Row():
579
+ pg = gr.Slider(0,5,value=1.5,step=0.1,label="PEG mol%")
580
+ lp = gr.Dropdown(["Ionizable","Cationic","Anionic","Neutral"],value="Ionizable",label="Lipid type")
581
+ b6 = gr.Button("Predict", variant="primary"); o6 = gr.Markdown()
582
+ gr.Examples([[100,-5,1.5,"Ionizable"],[80,5,0.5,"Cationic"]], inputs=[sz,zt,pg,lp])
583
+ b6.click(predict_corona, [sz,zt,pg,lp], o6)
584
+
585
+ with gr.TabItem("S1-R7 · Flow"):
586
+ gr.HTML(proj_badge("S1-D · PHYLO-LNP · S1-R7",
587
+ "Flow Corona — Vroman Effect · albumin→ApoE kinetics"))
588
+ with gr.Row():
589
+ s8 = gr.Slider(50,300,value=100,step=1,label="Size (nm)")
590
+ z8 = gr.Slider(-40,10,value=-5,step=1,label="Zeta (mV)")
591
+ pg8 = gr.Slider(0,5,value=1.5,step=0.1,label="PEG mol%")
592
+ with gr.Row():
593
+ ch8 = gr.Dropdown(["Ionizable","Cationic","Anionic","Neutral"],value="Ionizable",label="Charge")
594
+ fl8 = gr.Slider(0,40,value=20,step=1,label="Flow cm/s (aorta=40)")
595
+ b8 = gr.Button("Model Vroman Effect", variant="primary")
596
+ o8t = gr.Markdown(); o8p = gr.Image(label="Kinetics")
597
+ gr.Examples([[100,-5,1.5,"Ionizable",40],[150,5,0.5,"Cationic",10]], inputs=[s8,z8,pg8,ch8,fl8])
598
+ b8.click(predict_flow, [s8,z8,pg8,ch8,fl8], [o8t,o8p])
599
+
600
+ with gr.TabItem("S1-R8 · Brain"):
601
+ gr.HTML(proj_badge("S1-D · PHYLO-LNP · S1-R8",
602
+ "LNP Brain Delivery — ApoE% + BBB probability"))
603
+ smi = gr.Textbox(label="Ionizable lipid SMILES",
604
+ value="CC(C)CC(=O)OCC(COC(=O)CC(C)C)OC(=O)CC(C)C")
605
+ with gr.Row():
606
+ pk = gr.Slider(4,8,value=6.5,step=0.1,label="pKa")
607
+ zt9 = gr.Slider(-20,10,value=-3,step=1,label="Zeta (mV)")
608
+ b9 = gr.Button("Predict BBB Crossing", variant="primary")
609
+ o9t = gr.Markdown(); o9p = gr.Image(label="Radar profile")
610
+ gr.Examples([["CC(C)CC(=O)OCC(COC(=O)CC(C)C)OC(=O)CC(C)C",6.5,-3]], inputs=[smi,pk,zt9])
611
+ b9.click(predict_bbb, [smi,pk,zt9], [o9t,o9p])
612
+
613
+ with gr.TabItem("S1-R10 · NLP"):
614
+ gr.HTML(proj_badge("S1-D · PHYLO-LNP · S1-R10",
615
+ "AutoCorona NLP structured data from PMC abstracts", "F1 = 0.71"))
616
+ txt = gr.Textbox(lines=5,label="Paper abstract",placeholder="Paste abstract here...")
617
+ b10 = gr.Button("Extract Data", variant="primary")
618
+ o10j = gr.Code(label="Extracted JSON", language="json")
619
+ o10f = gr.Textbox(label="Validation flags")
620
+ gr.Examples([[
621
+ "LNPs composed of MC3, DSPC, Cholesterol (50:10:40 mol%) with 1.5% PEG-DMG. "
622
+ "Hydrodynamic diameter was 98 nm, zeta potential -3.2 mV, PDI 0.12. "
623
+ "Incubated in human plasma. Corona: albumin, apolipoprotein E, fibrinogen."
624
+ ]], inputs=[txt])
625
+ b10.click(extract_corona, txt, [o10j, o10f])
626
+
627
+ with gr.TabItem("S1-R11 · CSF/BM 🔴⭐"):
628
+ gr.HTML(proj_badge("S1-D · PHYLO-LNP · S1-R11",
629
+ "LNP Corona in CSF · Vitreous · Bone Marrow", "🔴 0 prior studies"))
630
+ gr.Markdown(
631
+ "> **Research gap:** Protein corona has only been characterized in serum/plasma. "
632
+ "CSF, vitreous humor, and bone marrow interstitial fluid remain completely unstudied.\n\n"
633
+ "> **Target cancers:** DIPG (CSF) · UVM (vitreous) · pAML (bone marrow)\n\n"
634
+ "> **Expected timeline:** Q2–Q3 2026"
635
+ )
636
+
637
+ # ── 🩸 S1-E · PHYLO-BIOMARKERS ─────────────────────
638
+ with gr.TabItem("🩸 PHYLO-BIOMARKERS"):
639
+ gr.HTML(section_header(
640
+ "S1-E", "PHYLO-BIOMARKERS", "— Detect cancer without tissue biopsy",
641
+ "S1-R9 Liquid Biopsy ✅ &nbsp;·&nbsp; S1-R9b Panel validator 🔶 &nbsp;·&nbsp; S1-R9c ctDNA gap 🔴"
642
+ ))
643
+ with gr.Tabs(elem_classes="inner-tabs"):
644
+
645
+ with gr.TabItem("S1-R9 · Liquid Biopsy"):
646
+ gr.HTML(proj_badge("S1-E · PHYLO-BIOMARKERS · S1-R9",
647
+ "Liquid Biopsy Classifier — CTHRC1 · FHL2 · LDHA panel",
648
+ "AUC = 0.992*"))
649
+ with gr.Row():
650
+ p1=gr.Slider(-3,3,value=0,step=0.1,label="CTHRC1")
651
+ p2=gr.Slider(-3,3,value=0,step=0.1,label="FHL2")
652
+ p3=gr.Slider(-3,3,value=0,step=0.1,label="LDHA")
653
+ p4=gr.Slider(-3,3,value=0,step=0.1,label="P4HA1")
654
+ p5=gr.Slider(-3,3,value=0,step=0.1,label="SERPINH1")
655
+ with gr.Row():
656
+ p6=gr.Slider(-3,3,value=0,step=0.1,label="ABCA8")
657
+ p7=gr.Slider(-3,3,value=0,step=0.1,label="CA4")
658
+ p8=gr.Slider(-3,3,value=0,step=0.1,label="CKB")
659
+ p9=gr.Slider(-3,3,value=0,step=0.1,label="NNMT")
660
+ p10=gr.Slider(-3,3,value=0,step=0.1,label="CACNA2D2")
661
+ b7=gr.Button("Classify", variant="primary")
662
+ o7t=gr.HTML(); o7p=gr.Image(label="Feature contributions")
663
+ gr.Examples([[2,2,1.5,1.8,1.6,-1,-1.2,-0.8,1.4,-1.1],[0]*10],
664
+ inputs=[p1,p2,p3,p4,p5,p6,p7,p8,p9,p10])
665
+ b7.click(predict_cancer, [p1,p2,p3,p4,p5,p6,p7,p8,p9,p10], [o7t,o7p])
666
+
667
+ with gr.TabItem("S1-R9b · Validator 🔶"):
668
+ gr.HTML(proj_badge("S1-E · PHYLO-BIOMARKERS · S1-R9b",
669
+ "Protein Panel Validator — multi-cancer plasma validation", "🔶 In progress"))
670
+ gr.Markdown("> Coming next — validates S1-R9 results against GEO plasma proteomics datasets.")
671
+
672
+ # ── 📓 JOURNAL ──────────────────────────────────────
673
  with gr.TabItem("📓 Journal"):
674
+ gr.Markdown("### Lab Journal\nEvery tool call auto-logged with project code.")
675
  with gr.Row():
676
+ note_text = gr.Textbox(label="📝 Observation", placeholder="What did you discover?", lines=3)
 
677
  note_tab = gr.Textbox(label="Project code (e.g. S1-R1)", value="General")
678
  note_last = gr.Textbox(visible=False)
679
  save_btn = gr.Button("💾 Save", variant="primary")
 
683
  refresh_btn.click(load_journal, [], journal_df)
684
  save_btn.click(save_note, [note_text,note_tab,note_last], [save_msg,journal_df])
685
 
686
+ # ── 📚 LEARNING ─────────────────────────────────────
687
  with gr.TabItem("📚 Learning"):
688
+ gr.Markdown("""
689
+ ## 🧪 Guided Investigations — S1 Biomedical
690
+ > 🟢 Beginner 🟡 Intermediate 🔴 Advanced
691
+
692
+ ---
693
+ ### 🟢 Case 1 · S1-A · S1-R1
694
+ **Why does the same position give two different outcomes?**
695
+ 1. PHYLO-GENOMICS OpenVariant `BRCA1:p.R1699Q` Benign
696
+ 2. Enter `BRCA1:p.R1699W` Pathogenic
697
+ 3. Same position, different amino acid Q (polar) vs W (bulky-aromatic)
698
+
699
+ ---
700
+ ### 🟢 Case 2 · S1-D · S1-R6 + S1-R8
701
+ **How does PEG% control which protein coats the nanoparticle?**
702
+ 1. PHYLO-LNP Corona Ionizable, Zeta=−5, PEG=**0.5%** → note protein
703
+ 2. Change PEG=**2.5%** → compare
704
+ 3. Brain tab → pKa=6.5 → check ApoE%
705
+
706
+ ---
707
+ ### 🟡 Case 3 · S1-D · S1-R7
708
+ **Does blood flow reshape the corona over time?**
709
+ 1. PHYLO-LNP → Flow → Flow=0 → observe ApoE curve
710
+ 2. Flow=40 (arterial) → compare
711
+ 3. At what minute does ApoE dominate?
712
+
713
+ ---
714
+ ### 🟡 Case 4 · S1-B · S1-R3
715
+ **Which cancer has the most novel (undrugged) siRNA targets?**
716
+ 1. PHYLO-RNA → siRNA → LUAD → count "Novel"
717
+ 2. Repeat BRCA, COAD
718
+
719
+ ---
720
+ ### 🔴 Case 5 · S1-E · S1-R9
721
+ **Minimum protein signal that flips to CANCER?**
722
+ 1. PHYLO-BIOMARKERS → Liquid Biopsy → all=0 → HEALTHY
723
+ 2. Set CTHRC1=2.5, FHL2=2.0, LDHA=1.8 → observe
724
+ 3. Reset. Increase only CTHRC1 step by step.
725
+
726
+ ---
727
+ ### 🔴 Case 6 · S1-B + S1-C — Cross-tool convergence
728
+ 1. PHYLO-RNA → miRNA → TP53 → find top targets (BCL2, CDK6)
729
+ 2. PHYLO-DRUG → FGFR3 → check CDK6 pathway overlap
730
+ 3. PHYLO-RNA → siRNA → BRCA → does CDK6 appear?
731
+
732
+ ---
733
+ ### 📖 Tool Index
734
+ | Code | Module | Tool | Metric |
735
+ |------|--------|------|--------|
736
+ | S1-R1 | PHYLO-GENOMICS | OpenVariant | AUC=0.939 |
737
+ | S1-R2 | PHYLO-RNA | miRNA silencing | top: hsa-miR-148a |
738
+ | S1-R3 | PHYLO-RNA | siRNA SL | SPC24 top LUAD |
739
+ | S1-R4 | PHYLO-RNA | lncRNA-TREM2 | CYTOR→AKT1 |
740
+ | S1-R5 | PHYLO-DRUG | FGFR3 drug | score=0.793 |
741
+ | S1-R6 | PHYLO-LNP | Corona | AUC=0.791 |
742
+ | S1-R7 | PHYLO-LNP | Flow Vroman | 3–4× faster |
743
+ | S1-R8 | PHYLO-LNP | LNP Brain | pKa 6.2–6.8 |
744
+ | S1-R9 | PHYLO-BIOMARKERS | Liquid Biopsy | AUC=0.992* |
745
+ | S1-R10 | PHYLO-LNP | AutoCorona NLP | F1=0.71 |
746
  """)
747
 
748
  gr.Markdown(
749
+ "---\n**K R&D Lab** · Science Sphere · S1 Biomedical · "
750
+ "[GitHub](https://github.com/K-RnD-Lab) · "
751
+ "[HuggingFace](https://huggingface.co/K-RnD-Lab) · "
752
+ "[KOSATIKS GROUP 🦈](https://kosatiks-group.pp.ua) · MIT License"
 
753
  )
754
 
755
  demo.launch(server_name="0.0.0.0", server_port=7860)