TEZv commited on
Commit
f3f3bd1
·
verified ·
1 Parent(s): 0ec2eaf

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +8 -766
app.py CHANGED
@@ -1,768 +1,10 @@
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
- # ========== Кольори ==========
14
- BG = "#0f172a"
15
- CARD = "#1e293b"
16
- ACC = "#f97316"
17
- ACC2 = "#38bdf8"
18
- TXT = "#f1f5f9"
19
- GRN = "#22c55e"
20
- RED = "#ef4444"
21
- DIM = "#8e9bae"
22
- BORDER = "#334155"
23
-
24
- # ========== Логування ==========
25
- LOG_PATH = Path("/tmp/lab_journal.csv")
26
-
27
- def log_entry(tab, inputs, result, note=""):
28
- try:
29
- write_header = not LOG_PATH.exists()
30
- with open(LOG_PATH, "a", newline="", encoding="utf-8") as f:
31
- w = csv.DictWriter(f, fieldnames=["timestamp","tab","inputs","result","note"])
32
- if write_header: w.writeheader()
33
- w.writerow({"timestamp": datetime.now().strftime("%Y-%m-%d %H:%M"),
34
- "tab": tab, "inputs": str(inputs),
35
- "result": str(result)[:200], "note": note})
36
- except Exception: pass
37
-
38
- def load_journal():
39
- try:
40
- if not LOG_PATH.exists():
41
- return pd.DataFrame(columns=["timestamp","tab","inputs","result","note"])
42
- return pd.read_csv(LOG_PATH)
43
- except Exception:
44
- return pd.DataFrame(columns=["timestamp","tab","inputs","result","note"])
45
-
46
- def save_note(note, tab, last_result):
47
- log_entry(tab, "", last_result, note)
48
- return "✅ Saved!", load_journal()
49
-
50
- # ========== БАЗИ ДАНИХ ==========
51
- MIRNA_DB = {
52
- "BRCA2": [
53
- {"miRNA":"hsa-miR-148a-3p","log2FC":-0.70,"padj":0.013,"targets":"DNMT1, AKT2","pathway":"Epigenetic reprogramming"},
54
- {"miRNA":"hsa-miR-30e-5p","log2FC":-0.49,"padj":0.032,"targets":"MYC, KRAS","pathway":"Oncogene suppression"},
55
- {"miRNA":"hsa-miR-551b-3p","log2FC":-0.59,"padj":0.048,"targets":"SMAD4, CDK6","pathway":"TGF-beta / CDK4/6"},
56
- {"miRNA":"hsa-miR-22-3p","log2FC":-0.43,"padj":0.041,"targets":"HIF1A, PTEN","pathway":"Hypoxia / PI3K"},
57
- {"miRNA":"hsa-miR-200c-3p","log2FC":-0.38,"padj":0.044,"targets":"ZEB1, ZEB2","pathway":"EMT suppression"},
58
- ],
59
- "BRCA1": [
60
- {"miRNA":"hsa-miR-155-5p","log2FC":-0.81,"padj":0.008,"targets":"SHIP1, SOCS1","pathway":"Immune evasion"},
61
- {"miRNA":"hsa-miR-146a-5p","log2FC":-0.65,"padj":0.019,"targets":"TRAF6, IRAK1","pathway":"NF-kB signalling"},
62
- {"miRNA":"hsa-miR-21-5p","log2FC":-0.55,"padj":0.027,"targets":"PTEN, PDCD4","pathway":"Apoptosis"},
63
- {"miRNA":"hsa-miR-17-5p","log2FC":-0.47,"padj":0.036,"targets":"RB1, E2F1","pathway":"Cell cycle"},
64
- {"miRNA":"hsa-miR-34a-5p","log2FC":-0.41,"padj":0.049,"targets":"BCL2, CDK6","pathway":"p53 axis"},
65
- ],
66
- "TP53": [
67
- {"miRNA":"hsa-miR-34a-5p","log2FC":-1.10,"padj":0.001,"targets":"BCL2, CDK6","pathway":"p53-miR-34 axis"},
68
- {"miRNA":"hsa-miR-192-5p","log2FC":-0.90,"padj":0.005,"targets":"MDM2, DHFR","pathway":"p53 feedback"},
69
- {"miRNA":"hsa-miR-145-5p","log2FC":-0.75,"padj":0.012,"targets":"MYC, EGFR","pathway":"Growth suppression"},
70
- {"miRNA":"hsa-miR-107","log2FC":-0.62,"padj":0.023,"targets":"CDK6, HIF1B","pathway":"Hypoxia / cell cycle"},
71
- {"miRNA":"hsa-miR-215-5p","log2FC":-0.51,"padj":0.038,"targets":"DTL, DHFR","pathway":"DNA damage response"},
72
- ],
73
- }
74
- SIRNA_DB = {
75
- "LUAD": [
76
- {"Gene":"SPC24","dCERES":-0.175,"log2FC":1.13,"Drug_status":"Novel","siRNA":"GCAGCUGAAGAAACUGAAU"},
77
- {"Gene":"BUB1B","dCERES":-0.119,"log2FC":1.12,"Drug_status":"Novel","siRNA":"CCAAAGAGCUGAAGAACAU"},
78
- {"Gene":"CDC45","dCERES":-0.144,"log2FC":1.26,"Drug_status":"Novel","siRNA":"GCAUCAAGAUGAAGGAGAU"},
79
- {"Gene":"PLK1","dCERES":-0.239,"log2FC":1.03,"Drug_status":"Clinical","siRNA":"GACGCUCAAGAUGCAGAUU"},
80
- {"Gene":"CDK1","dCERES":-0.201,"log2FC":1.00,"Drug_status":"Clinical","siRNA":"GCAGAAGCACUGAAGAUUU"},
81
- ],
82
- "BRCA": [
83
- {"Gene":"AURKA","dCERES":-0.165,"log2FC":1.20,"Drug_status":"Clinical","siRNA":"GCACUGAAGAUGCAGAAUU"},
84
- {"Gene":"AURKB","dCERES":-0.140,"log2FC":1.15,"Drug_status":"Clinical","siRNA":"CCUGAAGACGCUCAAGGUU"},
85
- {"Gene":"CENPW","dCERES":-0.125,"log2FC":0.95,"Drug_status":"Novel","siRNA":"GCAGAAGCACUGAAGAUUU"},
86
- {"Gene":"RFC2","dCERES":-0.136,"log2FC":0.50,"Drug_status":"Novel","siRNA":"GCAAGAUGCAGAAGCACUU"},
87
- {"Gene":"TYMS","dCERES":-0.131,"log2FC":0.72,"Drug_status":"Approved","siRNA":"GGACGCUCAAGAUGCAGAU"},
88
- ],
89
- "COAD": [
90
- {"Gene":"KRAS","dCERES":-0.210,"log2FC":0.80,"Drug_status":"Clinical","siRNA":"GCUGGAGCUGGUGGUAGUU"},
91
- {"Gene":"WEE1","dCERES":-0.180,"log2FC":1.05,"Drug_status":"Clinical","siRNA":"GCAGCUGAAGAAACUGAAU"},
92
- {"Gene":"CHEK1","dCERES":-0.155,"log2FC":0.90,"Drug_status":"Clinical","siRNA":"CCAAAGAGCUGAAGAACAU"},
93
- {"Gene":"RFC2","dCERES":-0.130,"log2FC":0.55,"Drug_status":"Novel","siRNA":"GCAUCAAGAUGAAGGAGAU"},
94
- {"Gene":"PKMYT1","dCERES":-0.122,"log2FC":1.07,"Drug_status":"Clinical","siRNA":"GACGCUCAAGAUGCAGAUU"},
95
- ],
96
- }
97
- CERNA = [
98
- {"lncRNA":"CYTOR","miRNA":"hsa-miR-138-5p","target":"AKT1","pathway":"TREM2 core signaling"},
99
- {"lncRNA":"CYTOR","miRNA":"hsa-miR-138-5p","target":"NFKB1","pathway":"Neuroinflammation"},
100
- {"lncRNA":"GAS5","miRNA":"hsa-miR-21-5p","target":"PTEN","pathway":"Neuroinflammation"},
101
- {"lncRNA":"GAS5","miRNA":"hsa-miR-222-3p","target":"IL1B","pathway":"Neuroinflammation"},
102
- {"lncRNA":"HOTAIRM1","miRNA":"hsa-miR-9-5p","target":"TREM2","pathway":"Direct TREM2 regulation"},
103
- ]
104
- ASO = [
105
- {"lncRNA":"GAS5","position":119,"accessibility":0.653,"GC_pct":50,"Tm":47.2,"priority":"HIGH"},
106
- {"lncRNA":"CYTOR","position":507,"accessibility":0.653,"GC_pct":50,"Tm":46.8,"priority":"HIGH"},
107
- {"lncRNA":"HOTAIRM1","position":234,"accessibility":0.621,"GC_pct":44,"Tm":44.1,"priority":"MEDIUM"},
108
- {"lncRNA":"LINC00847","position":89,"accessibility":0.598,"GC_pct":56,"Tm":48.3,"priority":"MEDIUM"},
109
- {"lncRNA":"ZFAS1","position":312,"accessibility":0.571,"GC_pct":48,"Tm":45.5,"priority":"MEDIUM"},
110
- ]
111
- FGFR3 = {
112
- "P1 (hairpin loop)": [
113
- {"Compound":"CHEMBL1575701","RNA_score":0.809,"Toxicity":0.01,"Final_score":0.793},
114
- {"Compound":"CHEMBL15727","RNA_score":0.805,"Toxicity":0.00,"Final_score":0.789},
115
- {"Compound":"Thioguanine","RNA_score":0.888,"Toxicity":32.5,"Final_score":0.742},
116
- {"Compound":"Deazaguanine","RNA_score":0.888,"Toxicity":35.0,"Final_score":0.735},
117
- {"Compound":"CHEMBL441","RNA_score":0.775,"Toxicity":5.2,"Final_score":0.721},
118
- ],
119
- "P10 (G-quadruplex)": [
120
- {"Compound":"CHEMBL15727","RNA_score":0.805,"Toxicity":0.00,"Final_score":0.789},
121
- {"Compound":"CHEMBL5411515","RNA_score":0.945,"Toxicity":37.1,"Final_score":0.761},
122
- {"Compound":"CHEMBL90","RNA_score":0.760,"Toxicity":2.1,"Final_score":0.745},
123
- {"Compound":"CHEMBL102","RNA_score":0.748,"Toxicity":8.4,"Final_score":0.712},
124
- {"Compound":"Berberine","RNA_score":0.735,"Toxicity":3.2,"Final_score":0.708},
125
- ],
126
- }
127
- VARIANT_DB = {
128
- "BRCA1:p.R1699Q": {"score":0.03,"cls":"Benign","conf":"High"},
129
- "BRCA1:p.R1699W": {"score":0.97,"cls":"Pathogenic","conf":"High"},
130
- "BRCA2:p.D2723A": {"score":0.999,"cls":"Pathogenic","conf":"High"},
131
- "TP53:p.R248W": {"score":0.998,"cls":"Pathogenic","conf":"High"},
132
- "TP53:p.R248Q": {"score":0.995,"cls":"Pathogenic","conf":"High"},
133
- "EGFR:p.L858R": {"score":0.96,"cls":"Pathogenic","conf":"High"},
134
- "ALK:p.F1174L": {"score":0.94,"cls":"Pathogenic","conf":"High"},
135
- }
136
- PLAIN = {
137
- "Pathogenic": "This variant is likely to cause disease. Clinical follow-up is strongly recommended.",
138
- "Likely Pathogenic": "This variant is probably harmful. Discuss with your doctor.",
139
- "Benign": "This variant is likely harmless. Common in the general population.",
140
- "Likely Benign": "This variant is probably harmless. No strong reason for concern.",
141
- }
142
- BM_W = {
143
- "CTHRC1":0.18,"FHL2":0.15,"LDHA":0.14,"P4HA1":0.13,
144
- "SERPINH1":0.12,"ABCA8":-0.11,"CA4":-0.10,"CKB":-0.09,
145
- "NNMT":0.08,"CACNA2D2":-0.07
146
- }
147
- PROTEINS = ["albumin","apolipoprotein","fibrinogen","vitronectin",
148
- "clusterin","igm","iga","igg","complement","transferrin",
149
- "alpha-2-macroglobulin"]
150
-
151
- # ========== ФУНКЦІЇ ПРЕДИКЦІЇ ==========
152
- def predict_mirna(gene):
153
- df = pd.DataFrame(MIRNA_DB.get(gene, []))
154
- log_entry("S1-B · R1a · miRNA", gene, f"{len(df)} miRNAs")
155
- return df
156
-
157
- def predict_sirna(cancer):
158
- df = pd.DataFrame(SIRNA_DB.get(cancer, []))
159
- log_entry("S1-B · R2a · siRNA", cancer, f"{len(df)} targets")
160
- return df
161
-
162
- def get_lncrna():
163
- log_entry("S1-B · R3a · lncRNA", "load", "ceRNA")
164
- return pd.DataFrame(CERNA)
165
-
166
- def get_aso():
167
- log_entry("S1-B · R3b · ASO", "load", "ASO")
168
- return pd.DataFrame(ASO)
169
-
170
- def predict_drug(pocket):
171
- df = pd.DataFrame(FGFR3.get(pocket, []))
172
- fig, ax = plt.subplots(figsize=(6, 4), facecolor=CARD)
173
- ax.set_facecolor(CARD)
174
- ax.barh(df["Compound"], df["Final_score"], color=ACC)
175
- ax.set_xlabel("Final Score", color=TXT); ax.tick_params(colors=TXT)
176
- for sp in ax.spines.values(): sp.set_edgecolor(BORDER)
177
- ax.set_title(f"Top compounds — {pocket}", color=TXT, fontsize=10)
178
- plt.tight_layout()
179
- buf = BytesIO(); plt.savefig(buf, format="png", dpi=120, facecolor=CARD); plt.close(); buf.seek(0)
180
- log_entry("S1-C · R1a · FGFR3", pocket, f"Top: {df.iloc[0]['Compound'] if len(df) else 'none'}")
181
- return df, Image.open(buf)
182
-
183
- def predict_variant(hgvs, sift, polyphen, gnomad):
184
- hgvs = hgvs.strip()
185
- if hgvs in VARIANT_DB:
186
- r = VARIANT_DB[hgvs]; cls, conf, score = r["cls"], r["conf"], r["score"]
187
- else:
188
- score = 0.0
189
- if sift < 0.05: score += 0.4
190
- if polyphen > 0.85: score += 0.35
191
- if gnomad < 0.0001: score += 0.25
192
- score = round(score, 3)
193
- cls = "Pathogenic" if score > 0.6 else "Likely Pathogenic" if score > 0.4 else "Benign"
194
- conf = "High" if (sift < 0.01 or sift > 0.9) else "Moderate"
195
- colour = RED if "Pathogenic" in cls else GRN
196
- icon = "⚠️ WARNING" if "Pathogenic" in cls else "✅ OK"
197
- log_entry("S1-A · R1a · OpenVariant", hgvs or f"SIFT={sift}", f"{cls} score={score}")
198
- return (
199
- f"<div style=\'background:{CARD};padding:16px;border-radius:8px;font-family:sans-serif;color:{TXT}\'>"
200
- f"<p style=\'font-size:11px;color:{DIM};margin:0 0 8px\'>S1-A · R1a · OpenVariant</p>"
201
- f"<h3 style=\'color:{colour};margin:0 0 8px\'>{icon} {cls}</h3>"
202
- f"<p>Score: <b>{score:.3f}</b> &nbsp;|&nbsp; Confidence: <b>{conf}</b></p>"
203
- f"<div style=\'background:{BORDER};border-radius:4px;height:14px\'>"
204
- f"<div style=\'background:{colour};height:14px;border-radius:4px;width:{int(score*100)}%\'></div></div>"
205
- f"<p style=\'margin-top:12px\'>{PLAIN.get(cls,'')}</p>"
206
- f"<p style=\'font-size:11px;color:{DIM}\'>Research only. Not clinical advice.</p></div>"
207
- )
208
-
209
- def predict_corona(size, zeta, peg, lipid):
210
- score = 0
211
- if lipid == "Ionizable": score += 2
212
- elif lipid == "Cationic": score += 1
213
- if abs(zeta) < 10: score += 1
214
- if peg > 1.5: score += 2
215
- if size < 100: score += 1
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 · R1a · Corona", f"size={size},peg={peg}", f"dominant={dominant}")
219
- return f"**Dominant corona protein:** {dominant}\n\n**Predicted efficacy:** {efficacy}\n\n**Score:** {score}/6"
220
-
221
- def predict_cancer(c1,c2,c3,c4,c5,c6,c7,c8,c9,c10):
222
- vals = [c1,c2,c3,c4,c5,c6,c7,c8,c9,c10]
223
- names, weights = list(BM_W.keys()), list(BM_W.values())
224
- raw = sum(v*w for v,w in zip(vals, weights))
225
- prob = 1 / (1 + np.exp(-raw * 2))
226
- label = "CANCER" if prob > 0.5 else "HEALTHY"
227
- colour = RED if prob > 0.5 else GRN
228
- contribs = [v*w for v,w in zip(vals, weights)]
229
- fig, ax = plt.subplots(figsize=(6, 3.5), facecolor=CARD)
230
- ax.set_facecolor(CARD)
231
- ax.barh(names, contribs, color=[ACC if c > 0 else ACC2 for c in contribs])
232
- ax.axvline(0, color=TXT, linewidth=0.8)
233
- ax.set_xlabel("Contribution to cancer score", color=TXT)
234
- ax.tick_params(colors=TXT, labelsize=8)
235
- for sp in ax.spines.values(): sp.set_edgecolor(BORDER)
236
- ax.set_title("Protein contributions", color=TXT, fontsize=10)
237
- plt.tight_layout()
238
- buf = BytesIO(); plt.savefig(buf, format="png", dpi=120, facecolor=CARD); plt.close(); buf.seek(0)
239
- log_entry("S1-E · R1a · Liquid Biopsy", f"CTHRC1={c1},FHL2={c2}", f"{label} {prob:.2f}")
240
- return (
241
- f"<div style=\'background:{CARD};padding:14px;border-radius:8px;font-family:sans-serif;\'>"
242
- f"<p style=\'font-size:11px;color:{DIM};margin:0 0 6px\'>S1-E · R1a · Liquid Biopsy</p>"
243
- f"<span style=\'color:{colour};font-size:24px;font-weight:bold\'>{label}</span><br>"
244
- f"<span style=\'color:{TXT};font-size:14px\'>Probability: {prob:.2f}</span></div>"
245
- ), Image.open(buf)
246
-
247
- def predict_flow(size, zeta, peg, charge, flow_rate):
248
- csi = round(min((flow_rate/40)*0.6 + (peg/5)*0.2 + (1 if charge=="Cationic" else 0)*0.2, 1.0), 3)
249
- stability = "High remodeling" if csi > 0.6 else "Medium" if csi > 0.3 else "Stable"
250
- t = np.linspace(0, 60, 200)
251
- kf, ks = 0.03*(1+flow_rate/40), 0.038*(1+flow_rate/40)
252
- fig, ax = plt.subplots(figsize=(6, 3.5), facecolor=CARD)
253
- ax.set_facecolor(CARD)
254
- ax.plot(t, 60*np.exp(-0.03*t)+20, color="#60a5fa", ls="--", label="Albumin (static)")
255
- ax.plot(t, 60*np.exp(-kf*t)+10, color="#60a5fa", label="Albumin (flow)")
256
- ax.plot(t, 14*(1-np.exp(-0.038*t))+5, color=ACC, ls="--", label="ApoE (static)")
257
- ax.plot(t, 20*(1-np.exp(-ks*t))+5, color=ACC, label="ApoE (flow)")
258
- ax.set_xlabel("Time (min)", color=TXT); ax.set_ylabel("% Corona", color=TXT)
259
- ax.tick_params(colors=TXT); ax.legend(fontsize=7, labelcolor=TXT, facecolor=CARD)
260
- for sp in ax.spines.values(): sp.set_edgecolor(BORDER)
261
- ax.set_title("Vroman Effect — flow vs static", color=TXT, fontsize=9)
262
- plt.tight_layout()
263
- buf = BytesIO(); plt.savefig(buf, format="png", dpi=120, facecolor=CARD); plt.close(); buf.seek(0)
264
- log_entry("S1-D · R2a · Flow Corona", f"flow={flow_rate}", f"CSI={csi}")
265
- return f"**Corona Shift Index: {csi}** — {stability}", Image.open(buf)
266
-
267
- def predict_bbb(smiles, pka, zeta):
268
- logp = smiles.count("C")*0.3 - smiles.count("O")*0.5 + 1.5
269
- apoe_pct = max(0, min(40, (7.0-pka)*8 + abs(zeta)*0.5 + logp*0.8))
270
- bbb_prob = min(0.95, apoe_pct/30)
271
- tier = "HIGH (>20%)" if apoe_pct > 20 else "MEDIUM (10-20%)" if apoe_pct > 10 else "LOW (<10%)"
272
- cats = ["ApoE%","BBB","logP","pKa fit","Zeta"]
273
- vals = [apoe_pct/40, bbb_prob, min(logp/5,1), (7-abs(pka-6.5))/7, (10-abs(zeta))/10]
274
- angles = np.linspace(0, 2*np.pi, len(cats), endpoint=False).tolist()
275
- v2, a2 = vals+[vals[0]], angles+[angles[0]]
276
- fig, ax = plt.subplots(figsize=(5, 4), subplot_kw={"polar":True}, facecolor=CARD)
277
- ax.set_facecolor(CARD)
278
- ax.plot(a2, v2, color=ACC, linewidth=2); ax.fill(a2, v2, color=ACC, alpha=0.2)
279
- ax.set_xticks(angles); ax.set_xticklabels(cats, color=TXT, fontsize=8)
280
- ax.tick_params(colors=TXT)
281
- plt.tight_layout()
282
- buf = BytesIO(); plt.savefig(buf, format="png", dpi=120, facecolor=CARD); plt.close(); buf.seek(0)
283
- log_entry("S1-D · R3a · LNP Brain", f"pka={pka},zeta={zeta}", f"ApoE={apoe_pct:.1f}%")
284
- return f"**Predicted ApoE:** {apoe_pct:.1f}% — {tier}\n\n**BBB Probability:** {bbb_prob:.2f}", Image.open(buf)
285
-
286
- def extract_corona(text):
287
- out = {"nanoparticle_composition":"","size_nm":None,"zeta_mv":None,"PDI":None,
288
- "protein_source":"","corona_proteins":[],"confidence":{}}
289
- for pat, key in [(r"(\d+\.?\d*)\s*(?:nm|nanometer)","size_nm"),
290
- (r"([+-]?\d+\.?\d*)\s*mV","zeta_mv"),
291
- (r"PDI\s*[=:of]*\s*(\d+\.?\d*)","PDI")]:
292
- m = re.search(pat, text, re.I)
293
- if m: out[key] = float(m.group(1)); out["confidence"][key] = "HIGH"
294
- for src in ["human plasma","human serum","fetal bovine serum","FBS","PBS"]:
295
- if src.lower() in text.lower():
296
- out["protein_source"] = src; out["confidence"]["protein_source"] = "HIGH"; break
297
- out["corona_proteins"] = [{"name":p,"confidence":"MEDIUM"} for p in PROTEINS if p in text.lower()]
298
- for lip in ["DSPC","DOPE","MC3","DLin","cholesterol","PEG","DOTAP"]:
299
- if lip in text: out["nanoparticle_composition"] += lip + " "
300
- out["nanoparticle_composition"] = out["nanoparticle_composition"].strip()
301
- flags = []
302
- if not out["size_nm"]: flags.append("size_nm not found")
303
- if not out["zeta_mv"]: flags.append("zeta_mv not found")
304
- if not out["corona_proteins"]: flags.append("no proteins detected")
305
- summary = "All key fields extracted" if not flags else " | ".join(flags)
306
- log_entry("S1-D · R4a · AutoCorona NLP", text[:80], f"proteins={len(out['corona_proteins'])}")
307
- return json.dumps(out, indent=2), summary
308
-
309
- # ---------- S1-F RARE ----------
310
- DIPG_VARIANTS = [
311
- {"Variant":"H3K27M (H3F3A)","Freq_pct":78,"Pathway":"PRC2 inhibition → global H3K27me3 loss","Drug_status":"ONC201 (clinical)","Circadian_gene":"BMAL1 suppressed"},
312
- {"Variant":"ACVR1 p.R206H","Freq_pct":21,"Pathway":"BMP/SMAD hyperactivation","Drug_status":"LDN-193189 (preclinical)","Circadian_gene":"PER1 disrupted"},
313
- {"Variant":"PIK3CA p.H1047R","Freq_pct":15,"Pathway":"PI3K/AKT/mTOR","Drug_status":"Copanlisib (clinical)","Circadian_gene":"CRY1 altered"},
314
- {"Variant":"TP53 p.R248W","Freq_pct":14,"Pathway":"DNA damage response loss","Drug_status":"APR-246 (clinical)","Circadian_gene":"p53-CLOCK axis"},
315
- {"Variant":"PDGFRA amp","Freq_pct":13,"Pathway":"RTK/RAS signalling","Drug_status":"Avapritinib (clinical)","Circadian_gene":"REV-ERB altered"},
316
- ]
317
- DIPG_CSF_LNP = [
318
- {"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"},
319
- {"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"},
320
- {"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"},
321
- {"Formulation":"DODAP-DSPC-Chol","Size_nm":118,"Zeta_mV":-2.1,"CSF_protein":"Transferrin","ApoE_pct":7.2,"BBB_est":0.24,"Priority":"LOW"},
322
- ]
323
-
324
- UVM_VARIANTS = [
325
- {"Variant":"GNAQ p.Q209L","Freq_pct":46,"Pathway":"PLCβ → PKC → MAPK","Drug_status":"Darovasertib (clinical)","m6A_writer":"METTL3 upregulated"},
326
- {"Variant":"GNA11 p.Q209L","Freq_pct":32,"Pathway":"PLCβ → PKC → MAPK","Drug_status":"Darovasertib (clinical)","m6A_writer":"WTAP upregulated"},
327
- {"Variant":"BAP1 loss","Freq_pct":47,"Pathway":"Chromatin remodeling → metastasis","Drug_status":"No approved (HDAC trials)","m6A_writer":"FTO overexpressed"},
328
- {"Variant":"SF3B1 p.R625H","Freq_pct":19,"Pathway":"Splicing alteration → neoepitopes","Drug_status":"H3B-8800 (clinical)","m6A_writer":"METTL14 altered"},
329
- {"Variant":"EIF1AX p.A113_splice","Freq_pct":14,"Pathway":"Translation initiation","Drug_status":"Novel — no drug","m6A_writer":"YTHDF2 suppressed"},
330
- ]
331
- UVM_VITREOUS_LNP = [
332
- {"Formulation":"SM-102-DSPC-Chol-PEG","Vitreal_protein":"Hyaluronan-binding","Size_nm":95,"Zeta_mV":-3.2,"Retention_h":18,"Priority":"HIGH"},
333
- {"Formulation":"Lipid-H-DOPE-PEG","Vitreal_protein":"Vitronectin dominant","Size_nm":88,"Zeta_mV":-4.0,"Retention_h":22,"Priority":"HIGH"},
334
- {"Formulation":"DOTAP-DSPC-PEG","Vitreal_protein":"Albumin wash-out","Size_nm":112,"Zeta_mV":+2.1,"Retention_h":6,"Priority":"LOW"},
335
- {"Formulation":"MC3-DPPC-Chol","Vitreal_protein":"Clusterin-rich","Size_nm":101,"Zeta_mV":-2.8,"Retention_h":14,"Priority":"MEDIUM"},
336
- ]
337
-
338
- PAML_VARIANTS = [
339
- {"Variant":"FLT3-ITD","Freq_pct":25,"Pathway":"RTK constitutive activation → JAK/STAT","Drug_status":"Midostaurin (approved)","Ferroptosis":"GPX4 suppressed"},
340
- {"Variant":"NPM1 c.860_863dupTCAG","Freq_pct":30,"Pathway":"Nuclear export deregulation","Drug_status":"APR-548 combo (clinical)","Ferroptosis":"SLC7A11 upregulated"},
341
- {"Variant":"DNMT3A p.R882H","Freq_pct":18,"Pathway":"Epigenetic dysregulation","Drug_status":"Azacitidine (approved)","Ferroptosis":"ACSL4 altered"},
342
- {"Variant":"CEBPA biallelic","Freq_pct":8,"Pathway":"Myeloid differentiation block","Drug_status":"Novel target","Ferroptosis":"NRF2 pathway"},
343
- {"Variant":"IDH1/2 mutation","Freq_pct":15,"Pathway":"2-HG oncometabolite → TET2 inhibition","Drug_status":"Enasidenib (approved)","Ferroptosis":"Iron metabolism disrupted"},
344
- ]
345
- PAML_BM_LNP = [
346
- {"Formulation":"ALC-0315-DSPC-Chol-PEG","BM_protein":"ApoE + Clusterin","Size_nm":98,"Zeta_mV":-3.5,"Marrow_uptake_pct":34,"Priority":"HIGH"},
347
- {"Formulation":"MC3-DOPE-Chol-PEG","BM_protein":"Fibronectin dominant","Size_nm":105,"Zeta_mV":-4.2,"Marrow_uptake_pct":28,"Priority":"HIGH"},
348
- {"Formulation":"DLin-MC3-DPPC","BM_protein":"Vitronectin-rich","Size_nm":91,"Zeta_mV":-2.9,"Marrow_uptake_pct":19,"Priority":"MEDIUM"},
349
- {"Formulation":"Cationic-DOTAP-Chol","BM_protein":"Opsonin-heavy","Size_nm":132,"Zeta_mV":+8.1,"Marrow_uptake_pct":8,"Priority":"LOW"},
350
- ]
351
-
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 · R1a · DIPG", 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 · R1a · 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 · R2a · UVM", "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 · R2a · 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
- ferr_map = {"GPX4 suppressed": 0.85, "SLC7A11 upregulated": 0.72,
398
- "ACSL4 altered": 0.61, "NRF2 pathway": 0.55, "Iron metabolism disrupted": 0.78}
399
- ferr_score = ferr_map.get(row["Ferroptosis"], 0.5)
400
- cats = ["Ferroptosis\nsensitivity", "Drug\navailable", "BM niche\ncoverage", "Data\nmaturity", "Target\nnovelty"]
401
- has_drug = 0.9 if row["Drug_status"] not in ["Novel target"] else 0.3
402
- vals = [ferr_score, has_drug, 0.6, 0.55, 1-has_drug+0.2]
403
- angles = np.linspace(0, 2*np.pi, len(cats), endpoint=False).tolist()
404
- v2, a2 = vals+[vals[0]], angles+[angles[0]]
405
- fig, ax = plt.subplots(figsize=(5, 4), subplot_kw={"polar":True}, facecolor=CARD)
406
- ax.set_facecolor(CARD)
407
- ax.plot(a2, v2, color=ACC2, linewidth=2); ax.fill(a2, v2, color=ACC2, alpha=0.2)
408
- ax.set_xticks(angles); ax.set_xticklabels(cats, color=TXT, fontsize=8)
409
- ax.tick_params(colors=TXT)
410
- ax.set_title(f"pAML · {row['Variant'][:20]}", color=TXT, fontsize=9)
411
- plt.tight_layout()
412
- buf = BytesIO(); plt.savefig(buf, format="png", dpi=120, facecolor=CARD); plt.close(); buf.seek(0)
413
- log_entry("S1-F · R3a · pAML", variant, f"ferr={ferr_score:.2f}")
414
- _v = row["Variant"]
415
- _p = row["Pathway"]
416
- _d = row["Drug_status"]
417
- _f = row["Ferroptosis"]
418
- _fs = f"{ferr_score:.2f}"
419
- summary = (
420
- f"<div style='background:{CARD};padding:14px;border-radius:8px;font-family:sans-serif;'>"
421
- f"<p style='color:{DIM};font-size:11px;margin:0 0 6px'>S1-F · R3a · pAML</p>"
422
- f"<b style='color:{ACC2};font-size:15px'>{_v}</b><br>"
423
- f"<p style='color:{TXT};margin:6px 0'><b>Pathway:</b> {_p}</p>"
424
- f"<p style='color:{TXT};margin:0'><b>Drug:</b> {_d}</p>"
425
- f"<p style='color:{TXT};margin:6px 0'><b>Ferroptosis link:</b> {_f}</p>"
426
- f"<p style='color:{TXT}'><b>Ferroptosis sensitivity score:</b> "
427
- f"<span style='color:{ACC};font-size:18px'>{_fs}</span></p>"
428
- f"<p style='font-size:11px;color:{DIM}'>Research only. Not clinical advice.</p></div>"
429
- )
430
- return summary, Image.open(buf)
431
-
432
- # ========== ДОПОМІЖНІ ФУНКЦІЇ ==========
433
- def section_header(code, name, tagline, projects_html):
434
- return (
435
- f"<div style=\'background:{BG};border:1px solid {BORDER};padding:14px 18px;"
436
- f"border-radius:8px;margin-bottom:12px;\'>"
437
- f"<div style=\'display:flex;align-items:baseline;gap:10px;\'>"
438
- f"<span style=\'color:{ACC2};font-size:16px;font-weight:700\'>{code}</span>"
439
- f"<span style=\'color:{TXT};font-size:14px;font-weight:600\'>{name}</span>"
440
- f"<span style=\'color:{DIM};font-size:12px\'>{tagline}</span></div>"
441
- f"<div style=\'margin-top:8px;font-size:12px;color:{DIM}\'>{projects_html}</div>"
442
- f"</div>"
443
- )
444
-
445
- def proj_badge(code, title, metric=""):
446
- m = (f"<span style=\'background:#0f2a3f;color:{ACC2};padding:1px 7px;border-radius:3px;"
447
- f"font-size:10px;margin-left:6px\'>{metric}</span>") if metric else ""
448
- return (
449
- f"<div style=\'background:{CARD};border-left:3px solid {ACC};"
450
- f"padding:8px 12px;border-radius:0 6px 6px 0;margin-bottom:8px;\'>"
451
- f"<span style=\'color:{DIM};font-size:11px\'>{code}</span>{m}<br>"
452
- f"<span style=\'color:{TXT};font-size:14px;font-weight:600\'>{title}</span>"
453
- f"</div>"
454
- )
455
-
456
- # ========== CSS ==========
457
- css = f"""
458
- body, .gradio-container {{ background: {BG} !important; color: {TXT} !important; }}
459
- .outer-tabs .tab-nav button {{
460
- color: {TXT} !important;
461
- background: {CARD} !important;
462
- font-size: 13px !important;
463
- font-weight: 600 !important;
464
- padding: 8px 16px !important;
465
- border-radius: 6px 6px 0 0 !important;
466
- }}
467
- .outer-tabs .tab-nav button.selected {{
468
- border-bottom: 3px solid {ACC} !important;
469
- color: {ACC} !important;
470
- background: {BG} !important;
471
- }}
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
- h1, h2, h3 {{ color: {ACC} !important; }}
496
- .gr-button-primary {{ background: {ACC} !important; border: none !important; }}
497
- footer {{ display: none !important; }}
498
- """
499
-
500
- # ========== MAP HTML ==========
501
- MAP_HTML = f"""
502
- <div style="background:{CARD};padding:22px;border-radius:8px;font-family:monospace;font-size:13px;line-height:2.0;color:{TXT}">
503
- <span style="color:{ACC};font-size:16px;font-weight:bold">K R&D Lab · S1 Biomedical</span>
504
- <span style="color:{DIM};font-size:11px;margin-left:12px">Science Sphere — sub-direction 1</span>
505
- <br><br>
506
- <span style="color:{ACC2};font-weight:600">S1-A · PHYLO-GENOMICS</span> — What breaks in DNA<br>
507
- &nbsp;&nbsp;&nbsp;├─ <b>S1-A · R1a</b> OpenVariant <span style="color:{GRN}"> AUC=0.939 ✅</span><br>
508
- &nbsp;&nbsp;&nbsp;└─ <b>S1-A · R1b</b> Somatic classifier <span style="color:#f59e0b"> 🔶 In progress</span><br><br>
509
- <span style="color:{ACC2};font-weight:600">S1-B · PHYLO-RNA</span> — How to silence it via RNA<br>
510
- &nbsp;&nbsp;&nbsp;├─ <b>S1-B · R1a</b> miRNA silencing <span style="color:{GRN}"> ✅</span><br>
511
- &nbsp;&nbsp;&nbsp;├─ <b>S1-B · R2a</b> siRNA synthetic lethal <span style="color:{GRN}"> ✅</span><br>
512
- &nbsp;&nbsp;&nbsp;├─ <b>S1-B · R3a</b> lncRNA-TREM2 ceRNA <span style="color:{GRN}"> ✅</span><br>
513
- &nbsp;&nbsp;&nbsp;└─ <b>S1-B · R3b</b> ASO designer <span style="color:{GRN}"> ✅</span><br><br>
514
- <span style="color:{ACC2};font-weight:600">S1-C · PHYLO-DRUG</span> — Which molecule treats it<br>
515
- &nbsp;&nbsp;&nbsp;├─ <b>S1-C · R1a</b> FGFR3 RNA-directed compounds <span style="color:{GRN}"> ✅</span><br>
516
- &nbsp;&nbsp;&nbsp;├─ <b>S1-C · R1b</b> Synthetic lethal drug mapping <span style="color:#f59e0b"> 🔶</span><br>
517
- &nbsp;&nbsp;&nbsp;└─ <b>S1-C · R2a</b> m6A × Ferroptosis × Circadian <span style="color:{DIM}"> 🔴 Frontier</span><br><br>
518
- <span style="color:{ACC2};font-weight:600">S1-D · PHYLO-LNP</span> — How to deliver the drug<br>
519
- &nbsp;&nbsp;&nbsp;├─ <b>S1-D · R1a</b> LNP corona (serum) <span style="color:{GRN}"> AUC=0.791 ✅</span><br>
520
- &nbsp;&nbsp;&nbsp;├─ <b>S1-D · R2a</b> Flow corona — Vroman effect <span style="color:{GRN}"> ✅</span><br>
521
- &nbsp;&nbsp;&nbsp;├─ <b>S1-D · R3a</b> LNP brain / BBB / ApoE <span style="color:{GRN}"> ✅</span><br>
522
- &nbsp;&nbsp;&nbsp;├─ <b>S1-D · R4a</b> AutoCorona NLP <span style="color:{GRN}"> F1=0.71 ✅</span><br>
523
- &nbsp;&nbsp;&nbsp;└─ <b>S1-D · R5a</b> CSF · Vitreous · Bone Marrow <span style="color:{DIM}"> 🔴 0 prior studies</span><br><br>
524
- <span style="color:{ACC2};font-weight:600">S1-E · PHYLO-BIOMARKERS</span> — Detect without biopsy<br>
525
- &nbsp;&nbsp;&nbsp;├─ <b>S1-E · R1a</b> Liquid Biopsy classifier <span style="color:{GRN}"> AUC=0.992* ✅</span><br>
526
- &nbsp;&nbsp;&nbsp;└─ <b>S1-E · R1b</b> Protein panel validator <span style="color:#f59e0b"> 🔶</span><br><br>
527
- <span style="color:{ACC2};font-weight:600">S1-F · PHYLO-RARE</span> — Where almost nobody has looked yet<br>
528
- &nbsp;&nbsp;&nbsp;├─ <b>S1-F · R1a</b> DIPG toolkit (H3K27M + CSF LNP + Circadian) <span style="color:#f59e0b"> 🔶</span><br>
529
- &nbsp;&nbsp;&nbsp;├─ <b>S1-F · R2a</b> UVM toolkit (GNAQ/GNA11 + vitreous + m6A) <span style="color:#f59e0b"> 🔶</span><br>
530
- &nbsp;&nbsp;&nbsp;└─ <b>S1-F · R3a</b> pAML toolkit (FLT3-ITD + BM niche + ferroptosis) <span style="color:#f59e0b"> 🔶</span><br><br>
531
- <span style="color:{DIM};font-size:11px">✅ Active · 🔶 In progress · 🔴 Planned</span>
532
- </div>
533
- """
534
-
535
- # ========== ІНТЕРФЕЙС ==========
536
- with gr.Blocks(css=css, title="K R&D Lab · S1 Biomedical") as demo:
537
- gr.Markdown(
538
- "# 🔬 K R&D Lab · Science Sphere — S1 Biomedical\n"
539
- "**Oksana Kolisnyk** · [KOSATIKS GROUP](https://kosatiks-group.pp.ua) · "
540
- "*Research only. Not clinical advice.*"
541
- )
542
-
543
- with gr.Tabs(elem_classes="outer-tabs"):
544
- # 🗺️ Lab Map
545
- with gr.TabItem("🗺️ Lab Map"):
546
- gr.HTML(MAP_HTML)
547
-
548
- # 🧬 S1-A · PHYLO-GENOMICS
549
- with gr.TabItem("S1-A · R1a · OpenVariant"):
550
- gr.HTML(proj_badge("S1-A · R1a", "OpenVariant — SNV Pathogenicity Classifier", "AUC = 0.939"))
551
- hgvs = gr.Textbox(label="HGVS notation", placeholder="BRCA1:p.R1699Q")
552
- gr.Markdown("**Or enter functional scores manually:**")
553
- with gr.Row():
554
- sift = gr.Slider(0,1,value=0.5,step=0.01,label="SIFT (0=damaging)")
555
- pp = gr.Slider(0,1,value=0.5,step=0.01,label="PolyPhen-2")
556
- gn = gr.Slider(0,0.01,value=0.001,step=0.0001,label="gnomAD AF")
557
- b_v = gr.Button("Predict Pathogenicity", variant="primary")
558
- o_v = gr.HTML()
559
- gr.Examples([["BRCA1:p.R1699Q",0.82,0.05,0.0012],
560
- ["TP53:p.R248W",0.00,1.00,0.0],
561
- ["BRCA2:p.D2723A",0.01,0.98,0.0]], inputs=[hgvs,sift,pp,gn], cache_examples=False)
562
- b_v.click(predict_variant, [hgvs,sift,pp,gn], o_v)
563
-
564
- with gr.TabItem("S1-A · R1b · Somatic Classifier 🔶"):
565
- gr.HTML(proj_badge("S1-A · R1b", "Somatic Mutation Classifier", "🔶 In progress"))
566
- gr.Markdown("> This module is in active development. Coming in the next release.")
567
-
568
- # 🔬 S1-B · PHYLO-RNA
569
- with gr.TabItem("S1-B · R1a · BRCA2 miRNA"):
570
- gr.HTML(proj_badge("S1-B · R1a", "miRNA Silencing — BRCA1/2 · TP53"))
571
- g1 = gr.Dropdown(["BRCA2","BRCA1","TP53"], value="BRCA2", label="Gene")
572
- b1 = gr.Button("Find miRNAs", variant="primary")
573
- o1 = gr.Dataframe(label="Top 5 downregulated miRNAs")
574
- gr.Examples([["BRCA2"],["BRCA1"],["TP53"]], inputs=[g1])
575
- b1.click(predict_mirna, [g1], o1)
576
-
577
- with gr.TabItem("S1-B · R2a · TP53 siRNA"):
578
- gr.HTML(proj_badge("S1-B · R2a", "siRNA Synthetic Lethal — TP53-null"))
579
- g2 = gr.Dropdown(["LUAD","BRCA","COAD"], value="LUAD", label="Cancer type")
580
- b2 = gr.Button("Find Targets", variant="primary")
581
- o2 = gr.Dataframe(label="Top 5 synthetic lethal targets")
582
- gr.Examples([["LUAD"],["BRCA"],["COAD"]], inputs=[g2], cache_examples=False)
583
- b2.click(predict_sirna, [g2], o2)
584
-
585
- with gr.TabItem("S1-B · R3a · lncRNA-TREM2"):
586
- gr.HTML(proj_badge("S1-B · R3a", "lncRNA-TREM2 ceRNA Network"))
587
- b3 = gr.Button("Load Network", variant="primary")
588
- o3 = gr.Dataframe(label="ceRNA Network")
589
- b3.click(get_lncrna, [], o3)
590
-
591
- with gr.TabItem("S1-B · R3b · ASO Designer"):
592
- gr.HTML(proj_badge("S1-B · R3b", "ASO Candidates"))
593
- b4 = gr.Button("Show ASOs", variant="primary")
594
- o4 = gr.Dataframe(label="ASO Candidates")
595
- b4.click(get_aso, [], o4)
596
-
597
- # 💊 S1-C · PHYLO-DRUG
598
- with gr.TabItem("S1-C · R1a · FGFR3 RNA Drug"):
599
- gr.HTML(proj_badge("S1-C · R1a", "FGFR3 RNA-Directed Drug Discovery", "top score 0.793"))
600
- g4 = gr.Radio(["P1 (hairpin loop)","P10 (G-quadruplex)"],
601
- value="P1 (hairpin loop)", label="Target pocket")
602
- b4 = gr.Button("Screen Compounds", variant="primary")
603
- o4t = gr.Dataframe(label="Top 5 candidates")
604
- o4p = gr.Image(label="Binding scores")
605
- gr.Examples([["P1 (hairpin loop)"],["P10 (G-quadruplex)"]], inputs=[g4])
606
- b4.click(predict_drug, [g4], [o4t, o4p])
607
-
608
- with gr.TabItem("S1-C · R1b · SL Drug Mapping 🔶"):
609
- gr.HTML(proj_badge("S1-C · R1b", "Synthetic Lethal Drug Mapping", "🔶 In progress"))
610
- gr.Markdown("> Coming soon.")
611
-
612
- with gr.TabItem("S1-C · R2a · Frontier 🔴"):
613
- gr.HTML(proj_badge("S1-C · R2a", "m6A × Ferroptosis × Circadian", "🔴 Frontier"))
614
- gr.Markdown("> Planned for Q3 2026")
615
-
616
- # 🧪 S1-D · PHYLO-LNP
617
- with gr.TabItem("S1-D · R1a · LNP Corona"):
618
- gr.HTML(proj_badge("S1-D · R1a", "LNP Protein Corona (Serum)", "AUC = 0.791"))
619
- with gr.Row():
620
- sz = gr.Slider(50,300,value=100,step=1,label="Size (nm)")
621
- zt = gr.Slider(-40,10,value=-5,step=1,label="Zeta (mV)")
622
- with gr.Row():
623
- pg = gr.Slider(0,5,value=1.5,step=0.1,label="PEG mol%")
624
- lp = gr.Dropdown(["Ionizable","Cationic","Anionic","Neutral"],value="Ionizable",label="Lipid type")
625
- b6 = gr.Button("Predict", variant="primary")
626
- o6 = gr.Markdown()
627
- gr.Examples([[100,-5,1.5,"Ionizable"],[80,5,0.5,"Cationic"]], inputs=[sz,zt,pg,lp])
628
- b6.click(predict_corona, [sz,zt,pg,lp], o6)
629
-
630
- with gr.TabItem("S1-D · R2a · Flow Corona"):
631
- gr.HTML(proj_badge("S1-D · R2a", "Flow Corona — Vroman Effect"))
632
- with gr.Row():
633
- s8 = gr.Slider(50,300,value=100,step=1,label="Size (nm)")
634
- z8 = gr.Slider(-40,10,value=-5,step=1,label="Zeta (mV)")
635
- pg8 = gr.Slider(0,5,value=1.5,step=0.1,label="PEG mol%")
636
- with gr.Row():
637
- ch8 = gr.Dropdown(["Ionizable","Cationic","Anionic","Neutral"],value="Ionizable",label="Charge")
638
- fl8 = gr.Slider(0,40,value=20,step=1,label="Flow cm/s")
639
- b8 = gr.Button("Model Vroman Effect", variant="primary")
640
- o8t = gr.Markdown(); o8p = gr.Image(label="Kinetics")
641
- gr.Examples([[100,-5,1.5,"Ionizable",40],[150,5,0.5,"Cationic",10]], inputs=[s8,z8,pg8,ch8,fl8])
642
- b8.click(predict_flow, [s8,z8,pg8,ch8,fl8], [o8t,o8p])
643
-
644
- with gr.TabItem("S1-D · R3a · LNP Brain"):
645
- gr.HTML(proj_badge("S1-D · R3a", "LNP Brain Delivery — ApoE% + BBB probability"))
646
- smi = gr.Textbox(label="Ionizable lipid SMILES",
647
- value="CC(C)CC(=O)OCC(COC(=O)CC(C)C)OC(=O)CC(C)C")
648
- with gr.Row():
649
- pk = gr.Slider(4,8,value=6.5,step=0.1,label="pKa")
650
- zt9 = gr.Slider(-20,10,value=-3,step=1,label="Zeta (mV)")
651
- b9 = gr.Button("Predict BBB Crossing", variant="primary")
652
- o9t = gr.Markdown(); o9p = gr.Image(label="Radar profile")
653
- gr.Examples([["CC(C)CC(=O)OCC(COC(=O)CC(C)C)OC(=O)CC(C)C",6.5,-3]], inputs=[smi,pk,zt9])
654
- b9.click(predict_bbb, [smi,pk,zt9], [o9t,o9p])
655
-
656
- with gr.TabItem("S1-D · R4a · AutoCorona NLP"):
657
- gr.HTML(proj_badge("S1-D · R4a", "AutoCorona NLP — from abstracts", "F1 = 0.71"))
658
- txt = gr.Textbox(lines=5,label="Paper abstract",placeholder="Paste abstract here...")
659
- b10 = gr.Button("Extract Data", variant="primary")
660
- o10j = gr.Code(label="Extracted JSON", language="json")
661
- o10f = gr.Textbox(label="Validation flags")
662
- gr.Examples([["LNPs composed of MC3, DSPC, Cholesterol (50:10:40 mol%) with 1.5% PEG-DMG. Hydrodynamic diameter was 98 nm, zeta potential -3.2 mV, PDI 0.12. Incubated in human plasma. Corona: albumin, apolipoprotein E, fibrinogen."]], inputs=[txt])
663
- b10.click(extract_corona, txt, [o10j, o10f])
664
-
665
- with gr.TabItem("S1-D · R5a · CSF/BM 🔴"):
666
- gr.HTML(proj_badge("S1-D · R5a", "LNP Corona in CSF · Vitreous · Bone Marrow", "🔴 0 prior studies"))
667
- gr.Markdown("> Planned for Q2–Q3 2026")
668
-
669
- # 🩸 S1-E · PHYLO-BIOMARKERS
670
- with gr.TabItem("S1-E · R1a · Liquid Biopsy"):
671
- gr.HTML(proj_badge("S1-E · R1a", "Liquid Biopsy Classifier", "AUC = 0.992*"))
672
- with gr.Row():
673
- p1=gr.Slider(-3,3,value=0,step=0.1,label="CTHRC1")
674
- p2=gr.Slider(-3,3,value=0,step=0.1,label="FHL2")
675
- p3=gr.Slider(-3,3,value=0,step=0.1,label="LDHA")
676
- p4=gr.Slider(-3,3,value=0,step=0.1,label="P4HA1")
677
- p5=gr.Slider(-3,3,value=0,step=0.1,label="SERPINH1")
678
- with gr.Row():
679
- p6=gr.Slider(-3,3,value=0,step=0.1,label="ABCA8")
680
- p7=gr.Slider(-3,3,value=0,step=0.1,label="CA4")
681
- p8=gr.Slider(-3,3,value=0,step=0.1,label="CKB")
682
- p9=gr.Slider(-3,3,value=0,step=0.1,label="NNMT")
683
- p10=gr.Slider(-3,3,value=0,step=0.1,label="CACNA2D2")
684
- b7=gr.Button("Classify", variant="primary")
685
- o7t=gr.HTML(); o7p=gr.Image(label="Feature contributions")
686
- gr.Examples([[2,2,1.5,1.8,1.6,-1,-1.2,-0.8,1.4,-1.1],[0]*10],
687
- inputs=[p1,p2,p3,p4,p5,p6,p7,p8,p9,p10])
688
- b7.click(predict_cancer, [p1,p2,p3,p4,p5,p6,p7,p8,p9,p10], [o7t,o7p])
689
-
690
- with gr.TabItem("S1-E · R1b · Validator 🔶"):
691
- gr.HTML(proj_badge("S1-E · R1b", "Protein Panel Validator", "🔶 In progress"))
692
- gr.Markdown("> Coming next.")
693
-
694
- # 🧠 S1-F · PHYLO-RARE
695
- with gr.TabItem("S1-F · R1a · DIPG Toolkit"):
696
- gr.HTML(proj_badge("S1-F · R1a", "DIPG: H3K27M + CSF LNP + Circadian", "PBTA"))
697
- sort_d = gr.Radio(["Frequency", "Drug status"], value="Frequency", label="Sort by")
698
- b_dv = gr.Button("Load DIPG Variants", variant="primary")
699
- o_dv = gr.Dataframe(label="H3K27M co-mutations")
700
- b_dv.click(dipg_variants, [sort_d], o_dv)
701
- gr.Markdown("---")
702
- with gr.Row():
703
- d_peg = gr.Slider(0.5, 3.0, value=1.5, step=0.1, label="PEG mol%")
704
- d_size = gr.Slider(60, 150, value=90, step=5, label="Target size (nm)")
705
- b_dc = gr.Button("Rank CSF Formulations", variant="primary")
706
- o_dct = gr.Dataframe(label="CSF LNP ranking")
707
- o_dcp = gr.Image(label="ApoE% in CSF corona")
708
- b_dc.click(dipg_csf, [d_peg, d_size], [o_dct, o_dcp])
709
-
710
- with gr.TabItem("S1-F · R2a · UVM Toolkit"):
711
- gr.HTML(proj_badge("S1-F · R2a", "UVM: GNAQ/GNA11 + vitreous + m6A", "TCGA-UVM"))
712
- b_uv = gr.Button("Load UVM Variants", variant="primary")
713
- o_uv = gr.Dataframe(label="GNAQ/GNA11 map")
714
- b_uv.click(uvm_variants, [], o_uv)
715
- b_uw = gr.Button("Rank Vitreous Formulations", variant="primary")
716
- o_uwt = gr.Dataframe(label="Vitreous LNP retention ranking")
717
- o_uwp = gr.Image(label="Retention (hours)")
718
- b_uw.click(uvm_vitreous, [], [o_uwt, o_uwp])
719
-
720
- with gr.TabItem("S1-F · R3a · pAML Toolkit"):
721
- gr.HTML(proj_badge("S1-F · R3a", "pAML: FLT3-ITD + BM niche + ferroptosis", "TARGET-AML"))
722
- var_sel = gr.Dropdown(
723
- ["FLT3-ITD", "NPM1 c.860_863dupTCAG", "DNMT3A p.R882H",
724
- "CEBPA biallelic", "IDH1/2 mutation"],
725
- value="FLT3-ITD", label="Select variant"
726
- )
727
- b_pf = gr.Button("Analyze Ferroptosis Profile", variant="primary")
728
- o_pft = gr.HTML()
729
- o_pfp = gr.Image(label="Target radar")
730
- b_pf.click(paml_ferroptosis, var_sel, [o_pft, o_pfp])
731
-
732
- # 📓 Journal
733
- with gr.TabItem("📓 Journal"):
734
- gr.Markdown("### Lab Journal")
735
- with gr.Row():
736
- note_text = gr.Textbox(label="📝 Observation", placeholder="What did you discover?", lines=3)
737
- note_tab = gr.Textbox(label="Project code (e.g. S1-A·R1a)", value="General")
738
- note_last = gr.Textbox(visible=False)
739
- save_btn = gr.Button("💾 Save", variant="primary")
740
- save_msg = gr.Markdown()
741
- journal_df = gr.Dataframe(label="📋 Full History", value=load_journal(), interactive=False)
742
- refresh_btn = gr.Button("🔄 Refresh")
743
- refresh_btn.click(load_journal, [], journal_df)
744
- save_btn.click(save_note, [note_text,note_tab,note_last], [save_msg,journal_df])
745
-
746
- # 📚 Learning
747
- with gr.TabItem("📚 Learning"):
748
- gr.Markdown("""
749
- ## 🧪 Guided Investigations
750
- > 🟢 Beginner → 🟡 Intermediate → 🔴 Advanced
751
-
752
- **S1-A · R1a** OpenVariant – try BRCA1:p.R1699Q vs R1699W
753
- **S1-D · R1a** Corona – vary PEG% and observe dominant protein
754
- **S1-D · R2a** Flow Corona – compare flow 0 vs 40 cm/s
755
- **S1-B · R2a** siRNA – count "Novel" targets across cancer types
756
- **S1-E · R1a** Liquid Biopsy – find minimal signal for CANCER
757
- ... (more cases)
758
- """)
759
-
760
- gr.Markdown(
761
- "---\n**K R&D Lab** · MIT License · "
762
- "[GitHub](https://github.com/K-RnD-Lab) · "
763
- "[HuggingFace](https://huggingface.co/K-RnD-Lab) · "
764
- "[KOSATIKS GROUP](https://kosatiks-group.pp.ua)"
765
- )
766
-
767
- demo.queue()
768
  demo.launch()
 
1
  import gradio as gr
2
+ def hello(name):
3
+ return f"Hello {name}!"
4
+ with gr.Blocks() as demo:
5
+ gr.Markdown("# Test")
6
+ name = gr.Textbox()
7
+ out = gr.Textbox()
8
+ btn = gr.Button("Click")
9
+ btn.click(hello, name, out)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  demo.launch()