TEZv commited on
Commit
beb5795
·
verified ·
1 Parent(s): 33204cb

Upload app_v5.py

Browse files
Files changed (1) hide show
  1. app_v5.py +880 -0
app_v5.py ADDED
@@ -0,0 +1,880 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import gradio as gr
2
+ import pandas as pd
3
+ import numpy as np
4
+ import json, re, csv
5
+ import matplotlib
6
+ matplotlib.use("Agg")
7
+ import matplotlib.pyplot as plt
8
+ from io import BytesIO
9
+ from PIL import Image
10
+ from datetime import datetime
11
+ from pathlib import Path
12
+
13
+ BG = "#0f172a"
14
+ CARD = "#1e293b"
15
+ ACC = "#f97316"
16
+ ACC2 = "#38bdf8"
17
+ TXT = "#f1f5f9"
18
+ GRN = "#22c55e"
19
+ RED = "#ef4444"
20
+ DIM = "#8e9bae"
21
+ BORDER = "#334155"
22
+
23
+ LOG_PATH = Path("/tmp/lab_journal.csv")
24
+
25
+ def log_entry(tab, inputs, result, note=""):
26
+ try:
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:
38
+ if not LOG_PATH.exists():
39
+ return pd.DataFrame(columns=["timestamp","tab","inputs","result","note"])
40
+ return pd.read_csv(LOG_PATH)
41
+ except Exception:
42
+ return pd.DataFrame(columns=["timestamp","tab","inputs","result","note"])
43
+
44
+ def save_note(note, tab, last_result):
45
+ log_entry(tab, "", last_result, note)
46
+ return "✅ Saved!", load_journal()
47
+
48
+ # ── DATABASES ─────────────────────────────────────────────────────────────────
49
+ MIRNA_DB = {
50
+ "BRCA2": [
51
+ {"miRNA":"hsa-miR-148a-3p","log2FC":-0.70,"padj":0.013,"targets":"DNMT1, AKT2","pathway":"Epigenetic reprogramming"},
52
+ {"miRNA":"hsa-miR-30e-5p","log2FC":-0.49,"padj":0.032,"targets":"MYC, KRAS","pathway":"Oncogene suppression"},
53
+ {"miRNA":"hsa-miR-551b-3p","log2FC":-0.59,"padj":0.048,"targets":"SMAD4, CDK6","pathway":"TGF-beta / CDK4/6"},
54
+ {"miRNA":"hsa-miR-22-3p","log2FC":-0.43,"padj":0.041,"targets":"HIF1A, PTEN","pathway":"Hypoxia / PI3K"},
55
+ {"miRNA":"hsa-miR-200c-3p","log2FC":-0.38,"padj":0.044,"targets":"ZEB1, ZEB2","pathway":"EMT suppression"},
56
+ ],
57
+ "BRCA1": [
58
+ {"miRNA":"hsa-miR-155-5p","log2FC":-0.81,"padj":0.008,"targets":"SHIP1, SOCS1","pathway":"Immune evasion"},
59
+ {"miRNA":"hsa-miR-146a-5p","log2FC":-0.65,"padj":0.019,"targets":"TRAF6, IRAK1","pathway":"NF-kB signalling"},
60
+ {"miRNA":"hsa-miR-21-5p","log2FC":-0.55,"padj":0.027,"targets":"PTEN, PDCD4","pathway":"Apoptosis"},
61
+ {"miRNA":"hsa-miR-17-5p","log2FC":-0.47,"padj":0.036,"targets":"RB1, E2F1","pathway":"Cell cycle"},
62
+ {"miRNA":"hsa-miR-34a-5p","log2FC":-0.41,"padj":0.049,"targets":"BCL2, CDK6","pathway":"p53 axis"},
63
+ ],
64
+ "TP53": [
65
+ {"miRNA":"hsa-miR-34a-5p","log2FC":-1.10,"padj":0.001,"targets":"BCL2, CDK6","pathway":"p53-miR-34 axis"},
66
+ {"miRNA":"hsa-miR-192-5p","log2FC":-0.90,"padj":0.005,"targets":"MDM2, DHFR","pathway":"p53 feedback"},
67
+ {"miRNA":"hsa-miR-145-5p","log2FC":-0.75,"padj":0.012,"targets":"MYC, EGFR","pathway":"Growth suppression"},
68
+ {"miRNA":"hsa-miR-107","log2FC":-0.62,"padj":0.023,"targets":"CDK6, HIF1B","pathway":"Hypoxia / cell cycle"},
69
+ {"miRNA":"hsa-miR-215-5p","log2FC":-0.51,"padj":0.038,"targets":"DTL, DHFR","pathway":"DNA damage response"},
70
+ ],
71
+ }
72
+ SIRNA_DB = {
73
+ "LUAD": [
74
+ {"Gene":"SPC24","dCERES":-0.175,"log2FC":1.13,"Drug_status":"Novel","siRNA":"GCAGCUGAAGAAACUGAAU"},
75
+ {"Gene":"BUB1B","dCERES":-0.119,"log2FC":1.12,"Drug_status":"Novel","siRNA":"CCAAAGAGCUGAAGAACAU"},
76
+ {"Gene":"CDC45","dCERES":-0.144,"log2FC":1.26,"Drug_status":"Novel","siRNA":"GCAUCAAGAUGAAGGAGAU"},
77
+ {"Gene":"PLK1","dCERES":-0.239,"log2FC":1.03,"Drug_status":"Clinical","siRNA":"GACGCUCAAGAUGCAGAUU"},
78
+ {"Gene":"CDK1","dCERES":-0.201,"log2FC":1.00,"Drug_status":"Clinical","siRNA":"GCAGAAGCACUGAAGAUUU"},
79
+ ],
80
+ "BRCA": [
81
+ {"Gene":"AURKA","dCERES":-0.165,"log2FC":1.20,"Drug_status":"Clinical","siRNA":"GCACUGAAGAUGCAGAAUU"},
82
+ {"Gene":"AURKB","dCERES":-0.140,"log2FC":1.15,"Drug_status":"Clinical","siRNA":"CCUGAAGACGCUCAAGGUU"},
83
+ {"Gene":"CENPW","dCERES":-0.125,"log2FC":0.95,"Drug_status":"Novel","siRNA":"GCAGAAGCACUGAAGAUUU"},
84
+ {"Gene":"RFC2","dCERES":-0.136,"log2FC":0.50,"Drug_status":"Novel","siRNA":"GCAAGAUGCAGAAGCACUU"},
85
+ {"Gene":"TYMS","dCERES":-0.131,"log2FC":0.72,"Drug_status":"Approved","siRNA":"GGACGCUCAAGAUGCAGAU"},
86
+ ],
87
+ "COAD": [
88
+ {"Gene":"KRAS","dCERES":-0.210,"log2FC":0.80,"Drug_status":"Clinical","siRNA":"GCUGGAGCUGGUGGUAGUU"},
89
+ {"Gene":"WEE1","dCERES":-0.180,"log2FC":1.05,"Drug_status":"Clinical","siRNA":"GCAGCUGAAGAAACUGAAU"},
90
+ {"Gene":"CHEK1","dCERES":-0.155,"log2FC":0.90,"Drug_status":"Clinical","siRNA":"CCAAAGAGCUGAAGAACAU"},
91
+ {"Gene":"RFC2","dCERES":-0.130,"log2FC":0.55,"Drug_status":"Novel","siRNA":"GCAUCAAGAUGAAGGAGAU"},
92
+ {"Gene":"PKMYT1","dCERES":-0.122,"log2FC":1.07,"Drug_status":"Clinical","siRNA":"GACGCUCAAGAUGCAGAUU"},
93
+ ],
94
+ }
95
+ CERNA = [
96
+ {"lncRNA":"CYTOR","miRNA":"hsa-miR-138-5p","target":"AKT1","pathway":"TREM2 core signaling"},
97
+ {"lncRNA":"CYTOR","miRNA":"hsa-miR-138-5p","target":"NFKB1","pathway":"Neuroinflammation"},
98
+ {"lncRNA":"GAS5","miRNA":"hsa-miR-21-5p","target":"PTEN","pathway":"Neuroinflammation"},
99
+ {"lncRNA":"GAS5","miRNA":"hsa-miR-222-3p","target":"IL1B","pathway":"Neuroinflammation"},
100
+ {"lncRNA":"HOTAIRM1","miRNA":"hsa-miR-9-5p","target":"TREM2","pathway":"Direct TREM2 regulation"},
101
+ ]
102
+ ASO = [
103
+ {"lncRNA":"GAS5","position":119,"accessibility":0.653,"GC_pct":50,"Tm":47.2,"priority":"HIGH"},
104
+ {"lncRNA":"CYTOR","position":507,"accessibility":0.653,"GC_pct":50,"Tm":46.8,"priority":"HIGH"},
105
+ {"lncRNA":"HOTAIRM1","position":234,"accessibility":0.621,"GC_pct":44,"Tm":44.1,"priority":"MEDIUM"},
106
+ {"lncRNA":"LINC00847","position":89,"accessibility":0.598,"GC_pct":56,"Tm":48.3,"priority":"MEDIUM"},
107
+ {"lncRNA":"ZFAS1","position":312,"accessibility":0.571,"GC_pct":48,"Tm":45.5,"priority":"MEDIUM"},
108
+ ]
109
+ FGFR3 = {
110
+ "P1 (hairpin loop)": [
111
+ {"Compound":"CHEMBL1575701","RNA_score":0.809,"Toxicity":0.01,"Final_score":0.793},
112
+ {"Compound":"CHEMBL15727","RNA_score":0.805,"Toxicity":0.00,"Final_score":0.789},
113
+ {"Compound":"Thioguanine","RNA_score":0.888,"Toxicity":32.5,"Final_score":0.742},
114
+ {"Compound":"Deazaguanine","RNA_score":0.888,"Toxicity":35.0,"Final_score":0.735},
115
+ {"Compound":"CHEMBL441","RNA_score":0.775,"Toxicity":5.2,"Final_score":0.721},
116
+ ],
117
+ "P10 (G-quadruplex)": [
118
+ {"Compound":"CHEMBL15727","RNA_score":0.805,"Toxicity":0.00,"Final_score":0.789},
119
+ {"Compound":"CHEMBL5411515","RNA_score":0.945,"Toxicity":37.1,"Final_score":0.761},
120
+ {"Compound":"CHEMBL90","RNA_score":0.760,"Toxicity":2.1,"Final_score":0.745},
121
+ {"Compound":"CHEMBL102","RNA_score":0.748,"Toxicity":8.4,"Final_score":0.712},
122
+ {"Compound":"Berberine","RNA_score":0.735,"Toxicity":3.2,"Final_score":0.708},
123
+ ],
124
+ }
125
+ VARIANT_DB = {
126
+ "BRCA1:p.R1699Q": {"score":0.03,"cls":"Benign","conf":"High"},
127
+ "BRCA1:p.R1699W": {"score":0.97,"cls":"Pathogenic","conf":"High"},
128
+ "BRCA2:p.D2723A": {"score":0.999,"cls":"Pathogenic","conf":"High"},
129
+ "TP53:p.R248W": {"score":0.998,"cls":"Pathogenic","conf":"High"},
130
+ "TP53:p.R248Q": {"score":0.995,"cls":"Pathogenic","conf":"High"},
131
+ "EGFR:p.L858R": {"score":0.96,"cls":"Pathogenic","conf":"High"},
132
+ "ALK:p.F1174L": {"score":0.94,"cls":"Pathogenic","conf":"High"},
133
+ }
134
+ PLAIN = {
135
+ "Pathogenic": "This variant is likely to cause disease. Clinical follow-up is strongly recommended.",
136
+ "Likely Pathogenic": "This variant is probably harmful. Discuss with your doctor.",
137
+ "Benign": "This variant is likely harmless. Common in the general population.",
138
+ "Likely Benign": "This variant is probably harmless. No strong reason for concern.",
139
+ }
140
+ BM_W = {
141
+ "CTHRC1":0.18,"FHL2":0.15,"LDHA":0.14,"P4HA1":0.13,
142
+ "SERPINH1":0.12,"ABCA8":-0.11,"CA4":-0.10,"CKB":-0.09,
143
+ "NNMT":0.08,"CACNA2D2":-0.07
144
+ }
145
+ PROTEINS = ["albumin","apolipoprotein","fibrinogen","vitronectin",
146
+ "clusterin","igm","iga","igg","complement","transferrin",
147
+ "alpha-2-macroglobulin"]
148
+
149
+ # ── LOGIC ─────────────────────────────────────────────────────────────────────
150
+ def predict_mirna(gene):
151
+ df = pd.DataFrame(MIRNA_DB.get(gene, []))
152
+ log_entry("S1-B | S1-R2 | miRNA", gene, f"{len(df)} miRNAs")
153
+ return df
154
+
155
+ def predict_sirna(cancer):
156
+ df = pd.DataFrame(SIRNA_DB.get(cancer, []))
157
+ log_entry("S1-B | S1-R3 | siRNA", cancer, f"{len(df)} targets")
158
+ return df
159
+
160
+ def get_lncrna():
161
+ log_entry("S1-B | S1-R4 | lncRNA", "load", "ceRNA+ASO")
162
+ return pd.DataFrame(CERNA), pd.DataFrame(ASO)
163
+
164
+ def predict_drug(pocket):
165
+ df = pd.DataFrame(FGFR3.get(pocket, []))
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)
174
+ log_entry("S1-C | S1-R5 | Drug", pocket, f"Top: {df.iloc[0]['Compound'] if len(df) else 'none'}")
175
+ return df, Image.open(buf)
176
+
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
184
+ if polyphen > 0.85: score += 0.35
185
+ if gnomad < 0.0001: score += 0.25
186
+ score = round(score, 3)
187
+ cls = "Pathogenic" if score > 0.6 else "Likely Pathogenic" if score > 0.4 else "Benign"
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):
204
+ score = 0
205
+ if lipid == "Ionizable": score += 2
206
+ elif lipid == "Cationic": score += 1
207
+ if abs(zeta) < 10: score += 1
208
+ if peg > 1.5: score += 2
209
+ if size < 100: score += 1
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)")
249
+ ax.plot(t, 60*np.exp(-kf*t)+10, color="#60a5fa", label="Albumin (flow)")
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)
258
+ log_entry("S1-D | S1-R7 | FlowCorona", f"flow={flow_rate}", f"CSI={csi}")
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)
274
+ ax.tick_params(colors=TXT)
275
+ plt.tight_layout()
276
+ buf = BytesIO(); plt.savefig(buf, format="png", dpi=120, facecolor=CARD); plt.close(); buf.seek(0)
277
+ log_entry("S1-D | S1-R8 | LNPBrain", f"pka={pka},zeta={zeta}", f"ApoE={apoe_pct:.1f}%")
278
+ return f"**Predicted ApoE:** {apoe_pct:.1f}% — {tier}\n\n**BBB Probability:** {bbb_prob:.2f}", Image.open(buf)
279
+
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
291
+ out["corona_proteins"] = [{"name":p,"confidence":"MEDIUM"} for p in PROTEINS if p in text.lower()]
292
+ for lip in ["DSPC","DOPE","MC3","DLin","cholesterol","PEG","DOTAP"]:
293
+ if lip in text: out["nanoparticle_composition"] += lip + " "
294
+ out["nanoparticle_composition"] = out["nanoparticle_composition"].strip()
295
+ flags = []
296
+ if not out["size_nm"]: flags.append("size_nm not found")
297
+ if not out["zeta_mv"]: flags.append("zeta_mv not found")
298
+ if not out["corona_proteins"]: flags.append("no proteins detected")
299
+ summary = "All key fields extracted" if not flags else " | ".join(flags)
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
+
304
+ # ── S1-F · PHYLO-RARE DATABASES ───────────────────────────────────────────────
305
+
306
+ # S1-R12b · DIPG — H3K27M + CSF LNP + Circadian
307
+ DIPG_VARIANTS = [
308
+ {"Variant":"H3K27M (H3F3A)","Freq_pct":78,"Pathway":"PRC2 inhibition → global H3K27me3 loss","Drug_status":"ONC201 (clinical)","Circadian_gene":"BMAL1 suppressed"},
309
+ {"Variant":"ACVR1 p.R206H","Freq_pct":21,"Pathway":"BMP/SMAD hyperactivation","Drug_status":"LDN-193189 (preclinical)","Circadian_gene":"PER1 disrupted"},
310
+ {"Variant":"PIK3CA p.H1047R","Freq_pct":15,"Pathway":"PI3K/AKT/mTOR","Drug_status":"Copanlisib (clinical)","Circadian_gene":"CRY1 altered"},
311
+ {"Variant":"TP53 p.R248W","Freq_pct":14,"Pathway":"DNA damage response loss","Drug_status":"APR-246 (clinical)","Circadian_gene":"p53-CLOCK axis"},
312
+ {"Variant":"PDGFRA amp","Freq_pct":13,"Pathway":"RTK/RAS signalling","Drug_status":"Avapritinib (clinical)","Circadian_gene":"REV-ERB altered"},
313
+ ]
314
+ DIPG_CSF_LNP = [
315
+ {"Formulation":"MC3-DSPC-Chol-PEG","Size_nm":92,"Zeta_mV":-4.1,"CSF_protein":"Beta2-microglobulin","ApoE_pct":12.4,"BBB_est":0.41,"Priority":"HIGH"},
316
+ {"Formulation":"DLin-KC2-DSPE-PEG","Size_nm":87,"Zeta_mV":-3.8,"CSF_protein":"Cystatin C","ApoE_pct":14.1,"BBB_est":0.47,"Priority":"HIGH"},
317
+ {"Formulation":"C12-200-DOPE-PEG","Size_nm":103,"Zeta_mV":-5.2,"CSF_protein":"Albumin (low)","ApoE_pct":9.8,"BBB_est":0.33,"Priority":"MEDIUM"},
318
+ {"Formulation":"DODAP-DSPC-Chol","Size_nm":118,"Zeta_mV":-2.1,"CSF_protein":"Transferrin","ApoE_pct":7.2,"BBB_est":0.24,"Priority":"LOW"},
319
+ ]
320
+
321
+ # S1-R12c · UVM — GNAQ/GNA11 + Vitreous corona + m6A
322
+ UVM_VARIANTS = [
323
+ {"Variant":"GNAQ p.Q209L","Freq_pct":46,"Pathway":"PLCβ → PKC → MAPK","Drug_status":"Darovasertib (clinical)","m6A_writer":"METTL3 upregulated"},
324
+ {"Variant":"GNA11 p.Q209L","Freq_pct":32,"Pathway":"PLCβ → PKC → MAPK","Drug_status":"Darovasertib (clinical)","m6A_writer":"WTAP upregulated"},
325
+ {"Variant":"BAP1 loss","Freq_pct":47,"Pathway":"Chromatin remodeling → metastasis","Drug_status":"No approved (HDAC trials)","m6A_writer":"FTO overexpressed"},
326
+ {"Variant":"SF3B1 p.R625H","Freq_pct":19,"Pathway":"Splicing alteration → neoepitopes","Drug_status":"H3B-8800 (clinical)","m6A_writer":"METTL14 altered"},
327
+ {"Variant":"EIF1AX p.A113_splice","Freq_pct":14,"Pathway":"Translation initiation","Drug_status":"Novel — no drug","m6A_writer":"YTHDF2 suppressed"},
328
+ ]
329
+ UVM_VITREOUS_LNP = [
330
+ {"Formulation":"SM-102-DSPC-Chol-PEG","Vitreal_protein":"Hyaluronan-binding","Size_nm":95,"Zeta_mV":-3.2,"Retention_h":18,"Priority":"HIGH"},
331
+ {"Formulation":"Lipid-H-DOPE-PEG","Vitreal_protein":"Vitronectin dominant","Size_nm":88,"Zeta_mV":-4.0,"Retention_h":22,"Priority":"HIGH"},
332
+ {"Formulation":"DOTAP-DSPC-PEG","Vitreal_protein":"Albumin wash-out","Size_nm":112,"Zeta_mV":+2.1,"Retention_h":6,"Priority":"LOW"},
333
+ {"Formulation":"MC3-DPPC-Chol","Vitreal_protein":"Clusterin-rich","Size_nm":101,"Zeta_mV":-2.8,"Retention_h":14,"Priority":"MEDIUM"},
334
+ ]
335
+
336
+ # S1-R12d · pAML — FLT3-ITD + BM niche corona + Ferroptosis
337
+ PAML_VARIANTS = [
338
+ {"Variant":"FLT3-ITD","Freq_pct":25,"Pathway":"RTK constitutive activation → JAK/STAT","Drug_status":"Midostaurin (approved)","Ferroptosis":"GPX4 suppressed"},
339
+ {"Variant":"NPM1 c.860_863dupTCAG","Freq_pct":30,"Pathway":"Nuclear export deregulation","Drug_status":"APR-548 combo (clinical)","Ferroptosis":"SLC7A11 upregulated"},
340
+ {"Variant":"DNMT3A p.R882H","Freq_pct":18,"Pathway":"Epigenetic dysregulation","Drug_status":"Azacitidine (approved)","Ferroptosis":"ACSL4 altered"},
341
+ {"Variant":"CEBPA biallelic","Freq_pct":8,"Pathway":"Myeloid differentiation block","Drug_status":"Novel target","Ferroptosis":"NRF2 pathway"},
342
+ {"Variant":"IDH1/2 mutation","Freq_pct":15,"Pathway":"2-HG oncometabolite → TET2 inhibition","Drug_status":"Enasidenib (approved)","Ferroptosis":"Iron metabolism disrupted"},
343
+ ]
344
+ PAML_BM_LNP = [
345
+ {"Formulation":"ALC-0315-DSPC-Chol-PEG","BM_protein":"ApoE + Clusterin","Size_nm":98,"Zeta_mV":-3.5,"Marrow_uptake_pct":34,"Priority":"HIGH"},
346
+ {"Formulation":"MC3-DOPE-Chol-PEG","BM_protein":"Fibronectin dominant","Size_nm":105,"Zeta_mV":-4.2,"Marrow_uptake_pct":28,"Priority":"HIGH"},
347
+ {"Formulation":"DLin-MC3-DPPC","BM_protein":"Vitronectin-rich","Size_nm":91,"Zeta_mV":-2.9,"Marrow_uptake_pct":19,"Priority":"MEDIUM"},
348
+ {"Formulation":"Cationic-DOTAP-Chol","BM_protein":"Opsonin-heavy","Size_nm":132,"Zeta_mV":+8.1,"Marrow_uptake_pct":8,"Priority":"LOW"},
349
+ ]
350
+
351
+ # ── S1-F · PHYLO-RARE LOGIC ───────────────────────────────────────────────────
352
+ def dipg_variants(sort_by):
353
+ df = pd.DataFrame(DIPG_VARIANTS).sort_values(
354
+ "Freq_pct" if sort_by == "Frequency" else "Drug_status", ascending=False)
355
+ log_entry("S1-F | S1-R12b | DIPG-variants", sort_by, f"{len(df)} variants")
356
+ return df
357
+
358
+ def dipg_csf(peg, size):
359
+ df = pd.DataFrame(DIPG_CSF_LNP)
360
+ df["Score"] = df["ApoE_pct"]/40 + df["BBB_est"] - abs(df["Size_nm"]-size)/200
361
+ df = df.sort_values("Score", ascending=False)
362
+ fig, ax = plt.subplots(figsize=(6, 3), facecolor=CARD)
363
+ ax.set_facecolor(CARD)
364
+ colors = [GRN if p=="HIGH" else ACC if p=="MEDIUM" else RED for p in df["Priority"]]
365
+ ax.barh(df["Formulation"], df["ApoE_pct"], color=colors)
366
+ ax.set_xlabel("ApoE% in CSF corona", color=TXT)
367
+ ax.tick_params(colors=TXT, labelsize=8)
368
+ for sp in ax.spines.values(): sp.set_edgecolor(BORDER)
369
+ ax.set_title("DIPG — CSF LNP formulations (ApoE%)", color=TXT, fontsize=9)
370
+ plt.tight_layout()
371
+ buf = BytesIO(); plt.savefig(buf, format="png", dpi=120, facecolor=CARD); plt.close(); buf.seek(0)
372
+ log_entry("S1-F | S1-R12b | DIPG-CSF", f"peg={peg},size={size}", "formulation ranking")
373
+ return df[["Formulation","Size_nm","Zeta_mV","ApoE_pct","BBB_est","Priority"]], Image.open(buf)
374
+
375
+ def uvm_variants():
376
+ df = pd.DataFrame(UVM_VARIANTS)
377
+ log_entry("S1-F | S1-R12c | UVM-variants", "load", f"{len(df)} variants")
378
+ return df
379
+
380
+ def uvm_vitreous():
381
+ df = pd.DataFrame(UVM_VITREOUS_LNP)
382
+ fig, ax = plt.subplots(figsize=(6, 3), facecolor=CARD)
383
+ ax.set_facecolor(CARD)
384
+ colors = [GRN if p=="HIGH" else ACC if p=="MEDIUM" else RED for p in df["Priority"]]
385
+ ax.barh(df["Formulation"], df["Retention_h"], color=colors)
386
+ ax.set_xlabel("Vitreous retention (hours)", color=TXT)
387
+ ax.tick_params(colors=TXT, labelsize=8)
388
+ for sp in ax.spines.values(): sp.set_edgecolor(BORDER)
389
+ ax.set_title("UVM — LNP retention in vitreous humor", color=TXT, fontsize=9)
390
+ plt.tight_layout()
391
+ buf = BytesIO(); plt.savefig(buf, format="png", dpi=120, facecolor=CARD); plt.close(); buf.seek(0)
392
+ log_entry("S1-F | S1-R12c | UVM-vitreous", "load", "vitreous LNP ranking")
393
+ return df, Image.open(buf)
394
+
395
+ def paml_ferroptosis(variant):
396
+ row = next((r for r in PAML_VARIANTS if variant in r["Variant"]), PAML_VARIANTS[0])
397
+ score = 0
398
+ ferr_map = {"GPX4 suppressed": 0.85, "SLC7A11 upregulated": 0.72,
399
+ "ACSL4 altered": 0.61, "NRF2 pathway": 0.55, "Iron metabolism disrupted": 0.78}
400
+ ferr_score = ferr_map.get(row["Ferroptosis"], 0.5)
401
+ cats = ["Ferroptosis\nsensitivity", "Drug\navailable", "BM niche\ncoverage", "Data\nmaturity", "Target\nnovelty"]
402
+ has_drug = 0.9 if row["Drug_status"] not in ["Novel target"] else 0.3
403
+ vals = [ferr_score, has_drug, 0.6, 0.55, 1-has_drug+0.2]
404
+ angles = np.linspace(0, 2*np.pi, len(cats), endpoint=False).tolist()
405
+ v2, a2 = vals+[vals[0]], angles+[angles[0]]
406
+ fig, ax = plt.subplots(figsize=(5, 4), subplot_kw={"polar":True}, facecolor=CARD)
407
+ ax.set_facecolor(CARD)
408
+ ax.plot(a2, v2, color=ACC2, linewidth=2); ax.fill(a2, v2, color=ACC2, alpha=0.2)
409
+ ax.set_xticks(angles); ax.set_xticklabels(cats, color=TXT, fontsize=8)
410
+ ax.tick_params(colors=TXT)
411
+ ax.set_title(f"pAML · {row['Variant'][:20]}", color=TXT, fontsize=9)
412
+ plt.tight_layout()
413
+ buf = BytesIO(); plt.savefig(buf, format="png", dpi=120, facecolor=CARD); plt.close(); buf.seek(0)
414
+ log_entry("S1-F | S1-R12d | pAML-ferroptosis", variant, f"ferr={ferr_score:.2f}")
415
+ summary = (
416
+ f"<div style=\'background:{CARD};padding:14px;border-radius:8px;font-family:sans-serif;\'>"
417
+ f"<p style=\'color:{DIM};font-size:11px;margin:0 0 6px\'>S1-F · PHYLO-RARE · S1-R12d · pAML</p>"
418
+ f"<b style=\'color:{ACC2};font-size:15px\'>{row[\'Variant\']}</b><br>"
419
+ f"<p style=\'color:{TXT};margin:6px 0\'><b>Pathway:</b> {row[\'Pathway\']}</p>"
420
+ f"<p style=\'color:{TXT};margin:0\'><b>Drug:</b> {row[\'Drug_status\']}</p>"
421
+ f"<p style=\'color:{TXT};margin:6px 0\'><b>Ferroptosis link:</b> {row[\'Ferroptosis\']}</p>"
422
+ f"<p style=\'color:{TXT}\'><b>Ferroptosis sensitivity score:</b> "
423
+ f"<span style=\'color:{ACC};font-size:18px\'>{ferr_score:.2f}</span></p>"
424
+ f"<p style=\'font-size:11px;color:{DIM}\'>Research only. Not clinical advice.</p></div>"
425
+ )
426
+ return summary, Image.open(buf)
427
+
428
+ # ── HELPERS ───────────────────────────────────────────────────────────────────
429
+ def section_header(code, name, tagline, projects_html):
430
+ return (
431
+ f"<div style=\'background:{BG};border:1px solid {BORDER};padding:14px 18px;"
432
+ f"border-radius:8px;margin-bottom:12px;\'>"
433
+ f"<div style=\'display:flex;align-items:baseline;gap:10px;\'>"
434
+ f"<span style=\'color:{ACC2};font-size:16px;font-weight:700\'>{code}</span>"
435
+ f"<span style=\'color:{TXT};font-size:14px;font-weight:600\'>{name}</span>"
436
+ f"<span style=\'color:{DIM};font-size:12px\'>{tagline}</span></div>"
437
+ f"<div style=\'margin-top:8px;font-size:12px;color:{DIM}\'>{projects_html}</div>"
438
+ f"</div>"
439
+ )
440
+
441
+ def proj_badge(code, title, metric=""):
442
+ m = (f"<span style=\'background:#0f2a3f;color:{ACC2};padding:1px 7px;border-radius:3px;"
443
+ f"font-size:10px;margin-left:6px\'>{metric}</span>") if metric else ""
444
+ return (
445
+ f"<div style=\'background:{CARD};border-left:3px solid {ACC};"
446
+ f"padding:8px 12px;border-radius:0 6px 6px 0;margin-bottom:8px;\'>"
447
+ f"<span style=\'color:{DIM};font-size:11px\'>{code}</span>{m}<br>"
448
+ f"<span style=\'color:{TXT};font-size:14px;font-weight:600\'>{title}</span>"
449
+ f"</div>"
450
+ )
451
+
452
+ # ── CSS ───────────────────────────────────────────────────────────────────────
453
+ css = f"""
454
+ body, .gradio-container {{ background: {BG} !important; color: {TXT} !important; }}
455
+
456
+ /* OUTER tab bar — PHYLO categories */
457
+ .outer-tabs .tab-nav button {{
458
+ color: {TXT} !important;
459
+ background: {CARD} !important;
460
+ font-size: 13px !important;
461
+ font-weight: 600 !important;
462
+ padding: 8px 16px !important;
463
+ border-radius: 6px 6px 0 0 !important;
464
+ }}
465
+ .outer-tabs .tab-nav button.selected {{
466
+ border-bottom: 3px solid {ACC} !important;
467
+ color: {ACC} !important;
468
+ background: {BG} !important;
469
+ }}
470
+
471
+ /* INNER sub-tab bar — individual tools */
472
+ .inner-tabs .tab-nav button {{
473
+ color: {DIM} !important;
474
+ background: {BG} !important;
475
+ font-size: 12px !important;
476
+ font-weight: 500 !important;
477
+ padding: 5px 12px !important;
478
+ border-radius: 4px 4px 0 0 !important;
479
+ border: 1px solid {BORDER} !important;
480
+ border-bottom: none !important;
481
+ margin-right: 3px !important;
482
+ }}
483
+ .inner-tabs .tab-nav button.selected {{
484
+ color: {ACC2} !important;
485
+ background: {CARD} !important;
486
+ border-color: {ACC2} !important;
487
+ border-bottom: none !important;
488
+ }}
489
+ .inner-tabs > .tabitem {{
490
+ background: {CARD} !important;
491
+ border: 1px solid {BORDER} !important;
492
+ border-radius: 0 6px 6px 6px !important;
493
+ padding: 14px !important;
494
+ }}
495
+
496
+ h1, h2, h3 {{ color: {ACC} !important; }}
497
+ .gr-button-primary {{ background: {ACC} !important; border: none !important; }}
498
+ footer {{ display: none !important; }}
499
+ """
500
+
501
+ # ── LAB MAP HTML ──────────────────────────────────────────────────────────────
502
+ MAP_HTML = f"""
503
+ <div style="background:{CARD};padding:22px;border-radius:8px;font-family:monospace;
504
+ font-size:13px;line-height:2.0;color:{TXT}">
505
+
506
+ <span style="color:{ACC};font-size:16px;font-weight:bold">K R&D Lab · S1 Biomedical</span>
507
+ <span style="color:{DIM};font-size:11px;margin-left:12px">Science Sphere — sub-direction 1</span>
508
+ <br><br>
509
+
510
+ <span style="color:{ACC2};font-weight:600">S1-A · PHYLO-GENOMICS</span>
511
+ <span style="color:{DIM}"> — What breaks in DNA</span><br>
512
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R1</b> &nbsp;OpenVariant
513
+ <span style="color:{GRN}"> AUC=0.939 ✅</span><br>
514
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R1b</b> Somatic classifier
515
+ <span style="color:#f59e0b"> 🔶 In progress</span><br>
516
+ &nbsp;&nbsp;&nbsp;└─ <b>S1-R12a</b> Rare variants (DIPG · UVM)
517
+ <span style="color:{DIM}"> 🔴 Planned</span><br><br>
518
+
519
+ <span style="color:{ACC2};font-weight:600">S1-B · PHYLO-RNA</span>
520
+ <span style="color:{DIM}"> — How to silence it via RNA</span><br>
521
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R2</b> &nbsp;miRNA silencing (BRCA1/2, TP53)
522
+ <span style="color:{GRN}"> ✅</span><br>
523
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R3</b> &nbsp;siRNA synthetic lethal (LUAD · BRCA · COAD)
524
+ <span style="color:{GRN}"> ✅</span><br>
525
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R4</b> &nbsp;lncRNA-TREM2 ceRNA network
526
+ <span style="color:{GRN}"> ✅</span><br>
527
+ &nbsp;&nbsp;&nbsp;└─ <b>S1-R4b</b> ASO designer
528
+ <span style="color:{GRN}"> ✅</span><br><br>
529
+
530
+ <span style="color:{ACC2};font-weight:600">S1-C · PHYLO-DRUG</span>
531
+ <span style="color:{DIM}"> — Which molecule treats it</span><br>
532
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R5</b> &nbsp;FGFR3 RNA-directed compounds
533
+ <span style="color:{GRN}"> ✅</span><br>
534
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R5b</b> Synthetic lethal drug mapping
535
+ <span style="color:#f59e0b"> 🔶</span><br>
536
+ &nbsp;&nbsp;&nbsp;└─ <b>S1-R13</b> m6A × Ferroptosis × Circadian ⭐
537
+ <span style="color:{DIM}"> 🔴 Frontier</span><br><br>
538
+
539
+ <span style="color:{ACC2};font-weight:600">S1-D · PHYLO-LNP</span>
540
+ <span style="color:{DIM}"> — How to deliver the drug</span><br>
541
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R6</b> &nbsp;LNP corona (serum)
542
+ <span style="color:{GRN}"> AUC=0.791 ✅</span><br>
543
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R7</b> &nbsp;Flow corona — Vroman effect
544
+ <span style="color:{GRN}"> ✅</span><br>
545
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R8</b> &nbsp;LNP brain / BBB / ApoE
546
+ <span style="color:{GRN}"> ✅</span><br>
547
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R10</b> AutoCorona NLP
548
+ <span style="color:{GRN}"> F1=0.71 ✅</span><br>
549
+ &nbsp;&nbsp;&nbsp;└─ <b>S1-R11</b> CSF · Vitreous · Bone Marrow ⭐
550
+ <span style="color:{DIM}"> 🔴 0 prior studies</span><br><br>
551
+
552
+ <span style="color:{ACC2};font-weight:600">S1-E · PHYLO-BIOMARKERS</span>
553
+ <span style="color:{DIM}"> — Detect without biopsy</span><br>
554
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R9</b> &nbsp;Liquid Biopsy classifier
555
+ <span style="color:{GRN}"> AUC=0.992* ✅</span><br>
556
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R9b</b> Protein panel validator
557
+ <span style="color:#f59e0b"> 🔶</span><br>
558
+ &nbsp;&nbsp;&nbsp;└─ <b>S1-R9c</b> ctDNA gap analysis
559
+ <span style="color:{DIM}"> 🔴</span><br><br>
560
+
561
+ <span style="color:{ACC2};font-weight:600">S1-F · PHYLO-RARE</span>
562
+ <span style="color:{DIM}"> — Where almost nobody has looked yet (&lt;300 cases/yr)</span><br>
563
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R12b</b> DIPG toolkit (H3K27M + CSF LNP + Circadian)
564
+ <span style="color:#f59e0b"> 🔶 In development</span><br>
565
+ &nbsp;&nbsp;&nbsp;├─ <b>S1-R12c</b> UVM toolkit (GNAQ/GNA11 + vitreous + m6A)
566
+ <span style="color:#f59e0b"> 🔶 In development</span><br>
567
+ &nbsp;&nbsp;&nbsp;└─ <b>S1-R12d</b> pAML toolkit (FLT3-ITD + BM niche + ferroptosis)
568
+ <span style="color:#f59e0b"> 🔶 In development</span><br><br>
569
+
570
+ <span style="color:{DIM};font-size:11px">
571
+ ✅ Active in this demo &nbsp;·&nbsp; 🔶 In progress &nbsp;·&nbsp; 🔴 Planned / Frontier<br>
572
+ ⭐ gap research (0–1 prior studies globally) &nbsp;·&nbsp; * tissue proxy, plasma validation pending
573
+ </span>
574
+ </div>
575
+ """
576
+
577
+ # ── UI ────────────────────────────────────────────────────────────────────────
578
+ with gr.Blocks(css=css, title="K R&D Lab · S1 Biomedical") as demo:
579
+
580
+ gr.Markdown(
581
+ "# 🔬 K R&D Lab · Science Sphere — S1 Biomedical\n"
582
+ "**Oksana Kolisnyk** · [KOSATIKS GROUP](https://kosatiks-group.pp.ua) &nbsp;|&nbsp; "
583
+ "[GitHub](https://github.com/K-RnD-Lab) &nbsp; "
584
+ "[HuggingFace](https://huggingface.co/K-RnD-Lab) &nbsp;|&nbsp; "
585
+ "*Research only. Not clinical advice.*"
586
+ )
587
+
588
+ # ═══════════════════════════════════════════════════════
589
+ # OUTER TABS — one per PHYLO-* category
590
+ # ═══════════════════════════════════════════════════════
591
+ with gr.Tabs(elem_classes="outer-tabs"):
592
+
593
+ # ── 🗺️ MAP ─────────────────────────────────────────
594
+ with gr.TabItem("🗺️ Lab Map"):
595
+ gr.HTML(MAP_HTML)
596
+
597
+ # ── 🧬 S1-A · PHYLO-GENOMICS ───────────────────────
598
+ with gr.TabItem("🧬 PHYLO-GENOMICS"):
599
+ gr.HTML(section_header(
600
+ "S1-A", "PHYLO-GENOMICS", "— What breaks in DNA",
601
+ "S1-R1 OpenVariant ✅ &nbsp;·&nbsp; S1-R1b Somatic classifier 🔶 &nbsp;·&nbsp; S1-R12a Rare variants 🔴"
602
+ ))
603
+ with gr.Tabs(elem_classes="inner-tabs"):
604
+
605
+ with gr.TabItem("S1-R1 · OpenVariant"):
606
+ gr.HTML(proj_badge("S1-A · PHYLO-GENOMICS · S1-R1",
607
+ "OpenVariant — SNV Pathogenicity Classifier", "AUC = 0.939"))
608
+ hgvs = gr.Textbox(label="HGVS notation", placeholder="BRCA1:p.R1699Q")
609
+ gr.Markdown("**Or enter functional scores manually:**")
610
+ with gr.Row():
611
+ sift = gr.Slider(0,1,value=0.5,step=0.01,label="SIFT (0=damaging)")
612
+ pp = gr.Slider(0,1,value=0.5,step=0.01,label="PolyPhen-2")
613
+ gn = gr.Slider(0,0.01,value=0.001,step=0.0001,label="gnomAD AF")
614
+ b_v = gr.Button("Predict Pathogenicity", variant="primary")
615
+ o_v = gr.HTML()
616
+ gr.Examples([["BRCA1:p.R1699Q",0.82,0.05,0.0012],
617
+ ["TP53:p.R248W",0.00,1.00,0.0],
618
+ ["BRCA2:p.D2723A",0.01,0.98,0.0]], inputs=[hgvs,sift,pp,gn])
619
+ b_v.click(predict_variant, [hgvs,sift,pp,gn], o_v)
620
+
621
+ with gr.TabItem("S1-R1b · Somatic 🔶"):
622
+ gr.HTML(proj_badge("S1-A · PHYLO-GENOMICS · S1-R1b",
623
+ "Somatic Mutation Classifier — BRCA · LUAD panels", "🔶 In progress"))
624
+ gr.Markdown("> This module is in active development. Coming in the next release.")
625
+
626
+ # ── 🔬 S1-B · PHYLO-RNA ────────────────────────────
627
+ with gr.TabItem("🔬 PHYLO-RNA"):
628
+ gr.HTML(section_header(
629
+ "S1-B", "PHYLO-RNA", "— How to silence it via RNA",
630
+ "S1-R2 miRNA ✅ &nbsp;·&nbsp; S1-R3 siRNA ✅ &nbsp;·&nbsp; S1-R4 lncRNA ✅ &nbsp;·&nbsp; S1-R4b ASO ✅"
631
+ ))
632
+ with gr.Tabs(elem_classes="inner-tabs"):
633
+
634
+ with gr.TabItem("S1-R2 · miRNA"):
635
+ gr.HTML(proj_badge("S1-B · PHYLO-RNA · S1-R2",
636
+ "miRNA Silencing — BRCA1/2 · TP53 tumor suppressors"))
637
+ g1 = gr.Dropdown(["BRCA2","BRCA1","TP53"], value="BRCA2", label="Gene")
638
+ b1 = gr.Button("Find miRNAs", variant="primary")
639
+ o1 = gr.Dataframe(label="Top 5 downregulated miRNAs")
640
+ gr.Examples([["BRCA2"],["BRCA1"],["TP53"]], inputs=[g1])
641
+ b1.click(predict_mirna, g1, o1)
642
+
643
+ with gr.TabItem("S1-R3 · siRNA"):
644
+ gr.HTML(proj_badge("S1-B · PHYLO-RNA · S1-R3",
645
+ "siRNA Synthetic Lethal — TP53-null · LUAD · BRCA · COAD"))
646
+ g2 = gr.Dropdown(["LUAD","BRCA","COAD"], value="LUAD", label="Cancer type")
647
+ b2 = gr.Button("Find Targets", variant="primary")
648
+ o2 = gr.Dataframe(label="Top 5 synthetic lethal targets")
649
+ gr.Examples([["LUAD"],["BRCA"],["COAD"]], inputs=[g2])
650
+ b2.click(predict_sirna, g2, o2)
651
+
652
+ with gr.TabItem("S1-R4 · lncRNA + ASO"):
653
+ gr.HTML(proj_badge("S1-B · PHYLO-RNA · S1-R4 + S1-R4b",
654
+ "lncRNA-TREM2 ceRNA Network + ASO Candidates · Alzheimer neuroinflammation"))
655
+ b3 = gr.Button("Load Results", variant="primary")
656
+ o3a = gr.Dataframe(label="ceRNA Network (S1-R4)")
657
+ o3b = gr.Dataframe(label="ASO Candidates (S1-R4b)")
658
+ b3.click(get_lncrna, [], [o3a, o3b])
659
+
660
+ # ── 💊 S1-C · PHYLO-DRUG ───────────────────────────
661
+ with gr.TabItem("💊 PHYLO-DRUG"):
662
+ gr.HTML(section_header(
663
+ "S1-C", "PHYLO-DRUG", "— Which molecule treats it",
664
+ "S1-R5 FGFR3 ✅ &nbsp;·&nbsp; S1-R5b SL drug mapping 🔶 &nbsp;·&nbsp; S1-R13 m6A×Ferroptosis×Circadian 🔴⭐"
665
+ ))
666
+ with gr.Tabs(elem_classes="inner-tabs"):
667
+
668
+ with gr.TabItem("S1-R5 · FGFR3"):
669
+ gr.HTML(proj_badge("S1-C · PHYLO-DRUG · S1-R5",
670
+ "FGFR3 RNA-Directed Drug Discovery · ChEMBL screen",
671
+ "top score 0.793"))
672
+ g4 = gr.Radio(["P1 (hairpin loop)","P10 (G-quadruplex)"],
673
+ value="P1 (hairpin loop)", label="Target pocket")
674
+ b4 = gr.Button("Screen Compounds", variant="primary")
675
+ o4t = gr.Dataframe(label="Top 5 candidates")
676
+ o4p = gr.Image(label="Binding scores")
677
+ gr.Examples([["P1 (hairpin loop)"],["P10 (G-quadruplex)"]], inputs=[g4])
678
+ b4.click(predict_drug, g4, [o4t, o4p])
679
+
680
+ with gr.TabItem("S1-R13 · Frontier 🔴⭐"):
681
+ gr.HTML(proj_badge("S1-C · PHYLO-DRUG · S1-R13",
682
+ "m6A × Ferroptosis × Circadian — Pan-cancer triad", "🔴 Frontier"))
683
+ gr.Markdown(
684
+ "> **Research gap:** This triple intersection has never been studied as an integrated system.\n\n"
685
+ "> **Planned datasets:** TCGA-PAAD · GEO m6A atlases · Circadian gene panels\n\n"
686
+ "> **Expected timeline:** Q3 2026"
687
+ )
688
+
689
+ # ── 🧪 S1-D · PHYLO-LNP ────────────────────────────
690
+ with gr.TabItem("🧪 PHYLO-LNP"):
691
+ gr.HTML(section_header(
692
+ "S1-D", "PHYLO-LNP", "— How to deliver the drug to the cell",
693
+ "S1-R6 Corona ✅ · S1-R7 Flow ✅ · S1-R8 Brain ✅ · S1-R10 NLP ✅ · S1-R11 CSF/BM 🔴⭐"
694
+ ))
695
+ with gr.Tabs(elem_classes="inner-tabs"):
696
+
697
+ with gr.TabItem("S1-R6 · Corona"):
698
+ gr.HTML(proj_badge("S1-D · PHYLO-LNP · S1-R6",
699
+ "LNP Protein Corona (Serum)", "AUC = 0.791"))
700
+ with gr.Row():
701
+ sz = gr.Slider(50,300,value=100,step=1,label="Size (nm)")
702
+ zt = gr.Slider(-40,10,value=-5,step=1,label="Zeta (mV)")
703
+ with gr.Row():
704
+ pg = gr.Slider(0,5,value=1.5,step=0.1,label="PEG mol%")
705
+ lp = gr.Dropdown(["Ionizable","Cationic","Anionic","Neutral"],value="Ionizable",label="Lipid type")
706
+ b6 = gr.Button("Predict", variant="primary"); o6 = gr.Markdown()
707
+ gr.Examples([[100,-5,1.5,"Ionizable"],[80,5,0.5,"Cationic"]], inputs=[sz,zt,pg,lp])
708
+ b6.click(predict_corona, [sz,zt,pg,lp], o6)
709
+
710
+ with gr.TabItem("S1-R7 · Flow"):
711
+ gr.HTML(proj_badge("S1-D · PHYLO-LNP · S1-R7",
712
+ "Flow Corona — Vroman Effect · albumin→ApoE kinetics"))
713
+ with gr.Row():
714
+ s8 = gr.Slider(50,300,value=100,step=1,label="Size (nm)")
715
+ z8 = gr.Slider(-40,10,value=-5,step=1,label="Zeta (mV)")
716
+ pg8 = gr.Slider(0,5,value=1.5,step=0.1,label="PEG mol%")
717
+ with gr.Row():
718
+ ch8 = gr.Dropdown(["Ionizable","Cationic","Anionic","Neutral"],value="Ionizable",label="Charge")
719
+ fl8 = gr.Slider(0,40,value=20,step=1,label="Flow cm/s (aorta=40)")
720
+ b8 = gr.Button("Model Vroman Effect", variant="primary")
721
+ o8t = gr.Markdown(); o8p = gr.Image(label="Kinetics")
722
+ gr.Examples([[100,-5,1.5,"Ionizable",40],[150,5,0.5,"Cationic",10]], inputs=[s8,z8,pg8,ch8,fl8])
723
+ b8.click(predict_flow, [s8,z8,pg8,ch8,fl8], [o8t,o8p])
724
+
725
+ with gr.TabItem("S1-R8 · Brain"):
726
+ gr.HTML(proj_badge("S1-D · PHYLO-LNP · S1-R8",
727
+ "LNP Brain Delivery — ApoE% + BBB probability"))
728
+ smi = gr.Textbox(label="Ionizable lipid SMILES",
729
+ value="CC(C)CC(=O)OCC(COC(=O)CC(C)C)OC(=O)CC(C)C")
730
+ with gr.Row():
731
+ pk = gr.Slider(4,8,value=6.5,step=0.1,label="pKa")
732
+ zt9 = gr.Slider(-20,10,value=-3,step=1,label="Zeta (mV)")
733
+ b9 = gr.Button("Predict BBB Crossing", variant="primary")
734
+ o9t = gr.Markdown(); o9p = gr.Image(label="Radar profile")
735
+ gr.Examples([["CC(C)CC(=O)OCC(COC(=O)CC(C)C)OC(=O)CC(C)C",6.5,-3]], inputs=[smi,pk,zt9])
736
+ b9.click(predict_bbb, [smi,pk,zt9], [o9t,o9p])
737
+
738
+ with gr.TabItem("S1-R10 · NLP"):
739
+ gr.HTML(proj_badge("S1-D · PHYLO-LNP · S1-R10",
740
+ "AutoCorona NLP — structured data from PMC abstracts", "F1 = 0.71"))
741
+ txt = gr.Textbox(lines=5,label="Paper abstract",placeholder="Paste abstract here...")
742
+ b10 = gr.Button("Extract Data", variant="primary")
743
+ o10j = gr.Code(label="Extracted JSON", language="json")
744
+ o10f = gr.Textbox(label="Validation flags")
745
+ gr.Examples([[
746
+ "LNPs composed of MC3, DSPC, Cholesterol (50:10:40 mol%) with 1.5% PEG-DMG. "
747
+ "Hydrodynamic diameter was 98 nm, zeta potential -3.2 mV, PDI 0.12. "
748
+ "Incubated in human plasma. Corona: albumin, apolipoprotein E, fibrinogen."
749
+ ]], inputs=[txt])
750
+ b10.click(extract_corona, txt, [o10j, o10f])
751
+
752
+ with gr.TabItem("S1-R11 · CSF/BM 🔴⭐"):
753
+ gr.HTML(proj_badge("S1-D · PHYLO-LNP · S1-R11",
754
+ "LNP Corona in CSF · Vitreous · Bone Marrow", "🔴 0 prior studies"))
755
+ gr.Markdown(
756
+ "> **Research gap:** Protein corona has only been characterized in serum/plasma. "
757
+ "CSF, vitreous humor, and bone marrow interstitial fluid remain completely unstudied.\n\n"
758
+ "> **Target cancers:** DIPG (CSF) · UVM (vitreous) · pAML (bone marrow)\n\n"
759
+ "> **Expected timeline:** Q2–Q3 2026"
760
+ )
761
+
762
+ # ── 🩸 S1-E · PHYLO-BIOMARKERS ─────────────────────
763
+ with gr.TabItem("🩸 PHYLO-BIOMARKERS"):
764
+ gr.HTML(section_header(
765
+ "S1-E", "PHYLO-BIOMARKERS", "— Detect cancer without tissue biopsy",
766
+ "S1-R9 Liquid Biopsy ✅ &nbsp;·&nbsp; S1-R9b Panel validator 🔶 &nbsp;·&nbsp; S1-R9c ctDNA gap 🔴"
767
+ ))
768
+ with gr.Tabs(elem_classes="inner-tabs"):
769
+
770
+ with gr.TabItem("S1-R9 · Liquid Biopsy"):
771
+ gr.HTML(proj_badge("S1-E · PHYLO-BIOMARKERS · S1-R9",
772
+ "Liquid Biopsy Classifier — CTHRC1 · FHL2 · LDHA panel",
773
+ "AUC = 0.992*"))
774
+ with gr.Row():
775
+ p1=gr.Slider(-3,3,value=0,step=0.1,label="CTHRC1")
776
+ p2=gr.Slider(-3,3,value=0,step=0.1,label="FHL2")
777
+ p3=gr.Slider(-3,3,value=0,step=0.1,label="LDHA")
778
+ p4=gr.Slider(-3,3,value=0,step=0.1,label="P4HA1")
779
+ p5=gr.Slider(-3,3,value=0,step=0.1,label="SERPINH1")
780
+ with gr.Row():
781
+ p6=gr.Slider(-3,3,value=0,step=0.1,label="ABCA8")
782
+ p7=gr.Slider(-3,3,value=0,step=0.1,label="CA4")
783
+ p8=gr.Slider(-3,3,value=0,step=0.1,label="CKB")
784
+ p9=gr.Slider(-3,3,value=0,step=0.1,label="NNMT")
785
+ p10=gr.Slider(-3,3,value=0,step=0.1,label="CACNA2D2")
786
+ b7=gr.Button("Classify", variant="primary")
787
+ o7t=gr.HTML(); o7p=gr.Image(label="Feature contributions")
788
+ gr.Examples([[2,2,1.5,1.8,1.6,-1,-1.2,-0.8,1.4,-1.1],[0]*10],
789
+ inputs=[p1,p2,p3,p4,p5,p6,p7,p8,p9,p10])
790
+ b7.click(predict_cancer, [p1,p2,p3,p4,p5,p6,p7,p8,p9,p10], [o7t,o7p])
791
+
792
+ with gr.TabItem("S1-R9b · Validator 🔶"):
793
+ gr.HTML(proj_badge("S1-E · PHYLO-BIOMARKERS · S1-R9b",
794
+ "Protein Panel Validator — multi-cancer plasma validation", "🔶 In progress"))
795
+ gr.Markdown("> Coming next — validates S1-R9 results against GEO plasma proteomics datasets.")
796
+
797
+ # ── 📓 JOURNAL ──────────────────────────────────────
798
+ with gr.TabItem("📓 Journal"):
799
+ gr.Markdown("### Lab Journal\nEvery tool call auto-logged with project code.")
800
+ with gr.Row():
801
+ note_text = gr.Textbox(label="📝 Observation", placeholder="What did you discover?", lines=3)
802
+ note_tab = gr.Textbox(label="Project code (e.g. S1-R1)", value="General")
803
+ note_last = gr.Textbox(visible=False)
804
+ save_btn = gr.Button("💾 Save", variant="primary")
805
+ save_msg = gr.Markdown()
806
+ journal_df = gr.Dataframe(label="📋 Full History", value=load_journal(), interactive=False)
807
+ refresh_btn = gr.Button("🔄 Refresh")
808
+ refresh_btn.click(load_journal, [], journal_df)
809
+ save_btn.click(save_note, [note_text,note_tab,note_last], [save_msg,journal_df])
810
+
811
+ # ── 📚 LEARNING ─────────────────────────────────────
812
+ with gr.TabItem("📚 Learning"):
813
+ gr.Markdown("""
814
+ ## 🧪 Guided Investigations — S1 Biomedical
815
+ > 🟢 Beginner → 🟡 Intermediate → 🔴 Advanced
816
+
817
+ ---
818
+ ### 🟢 Case 1 · S1-A · S1-R1
819
+ **Why does the same position give two different outcomes?**
820
+ 1. PHYLO-GENOMICS → OpenVariant → `BRCA1:p.R1699Q` → Benign
821
+ 2. Enter `BRCA1:p.R1699W` → Pathogenic
822
+ 3. Same position, different amino acid — Q (polar) vs W (bulky-aromatic)
823
+
824
+ ---
825
+ ### 🟢 Case 2 · S1-D · S1-R6 + S1-R8
826
+ **How does PEG% control which protein coats the nanoparticle?**
827
+ 1. PHYLO-LNP → Corona → Ionizable, Zeta=−5, PEG=**0.5%** → note protein
828
+ 2. Change PEG=**2.5%** → compare
829
+ 3. Brain tab → pKa=6.5 → check ApoE%
830
+
831
+ ---
832
+ ### 🟡 Case 3 · S1-D · S1-R7
833
+ **Does blood flow reshape the corona over time?**
834
+ 1. PHYLO-LNP → Flow → Flow=0 → observe ApoE curve
835
+ 2. Flow=40 (arterial) → compare
836
+ 3. At what minute does ApoE dominate?
837
+
838
+ ---
839
+ ### 🟡 Case 4 · S1-B · S1-R3
840
+ **Which cancer has the most novel (undrugged) siRNA targets?**
841
+ 1. PHYLO-RNA → siRNA → LUAD → count "Novel"
842
+ 2. Repeat BRCA, COAD
843
+
844
+ ---
845
+ ### 🔴 Case 5 · S1-E · S1-R9
846
+ **Minimum protein signal that flips to CANCER?**
847
+ 1. PHYLO-BIOMARKERS → Liquid Biopsy → all=0 → HEALTHY
848
+ 2. Set CTHRC1=2.5, FHL2=2.0, LDHA=1.8 → observe
849
+ 3. Reset. Increase only CTHRC1 step by step.
850
+
851
+ ---
852
+ ### 🔴 Case 6 · S1-B + S1-C — Cross-tool convergence
853
+ 1. PHYLO-RNA → miRNA → TP53 → find top targets (BCL2, CDK6)
854
+ 2. PHYLO-DRUG → FGFR3 → check CDK6 pathway overlap
855
+ 3. PHYLO-RNA → siRNA → BRCA → does CDK6 appear?
856
+
857
+ ---
858
+ ### 📖 Tool Index
859
+ | Code | Module | Tool | Metric |
860
+ |------|--------|------|--------|
861
+ | S1-R1 | PHYLO-GENOMICS | OpenVariant | AUC=0.939 |
862
+ | S1-R2 | PHYLO-RNA | miRNA silencing | top: hsa-miR-148a |
863
+ | S1-R3 | PHYLO-RNA | siRNA SL | SPC24 top LUAD |
864
+ | S1-R4 | PHYLO-RNA | lncRNA-TREM2 | CYTOR→AKT1 |
865
+ | S1-R5 | PHYLO-DRUG | FGFR3 drug | score=0.793 |
866
+ | S1-R6 | PHYLO-LNP | Corona | AUC=0.791 |
867
+ | S1-R7 | PHYLO-LNP | Flow Vroman | 3–4× faster |
868
+ | S1-R8 | PHYLO-LNP | LNP Brain | pKa 6.2–6.8 |
869
+ | S1-R9 | PHYLO-BIOMARKERS | Liquid Biopsy | AUC=0.992* |
870
+ | S1-R10 | PHYLO-LNP | AutoCorona NLP | F1=0.71 |
871
+ """)
872
+
873
+ gr.Markdown(
874
+ "---\n**K R&D Lab** · Science Sphere · S1 Biomedical · "
875
+ "[GitHub](https://github.com/K-RnD-Lab) · "
876
+ "[HuggingFace](https://huggingface.co/K-RnD-Lab) · "
877
+ "[KOSATIKS GROUP 🦈](https://kosatiks-group.pp.ua) · MIT License"
878
+ )
879
+
880
+ demo.launch(server_name="0.0.0.0", server_port=7860)