Upload app (1).py
Browse files- app (1).py +444 -0
app (1).py
ADDED
|
@@ -0,0 +1,444 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import gradio as gr
|
| 2 |
+
import pandas as pd
|
| 3 |
+
import numpy as np
|
| 4 |
+
import json
|
| 5 |
+
import re
|
| 6 |
+
import matplotlib
|
| 7 |
+
matplotlib.use("Agg")
|
| 8 |
+
import matplotlib.pyplot as plt
|
| 9 |
+
from io import BytesIO
|
| 10 |
+
from PIL import Image
|
| 11 |
+
|
| 12 |
+
BG = "#0f172a"
|
| 13 |
+
CARD = "#1e293b"
|
| 14 |
+
ACC = "#f97316"
|
| 15 |
+
ACC2 = "#38bdf8"
|
| 16 |
+
TXT = "#f1f5f9"
|
| 17 |
+
|
| 18 |
+
# ── TAB 1 — BRCA2 miRNA ──────────────────────────────────────────────────────
|
| 19 |
+
MIRNA_DB = {
|
| 20 |
+
"BRCA2": [
|
| 21 |
+
{"miRNA":"hsa-miR-148a-3p","log2FC":-0.70,"padj":0.013,"targets":"DNMT1, AKT2","pathway":"Epigenetic reprogramming"},
|
| 22 |
+
{"miRNA":"hsa-miR-30e-5p", "log2FC":-0.49,"padj":0.032,"targets":"MYC, KRAS","pathway":"Oncogene suppression"},
|
| 23 |
+
{"miRNA":"hsa-miR-551b-3p","log2FC":-0.59,"padj":0.048,"targets":"SMAD4, CDK6","pathway":"TGF-beta / CDK4/6"},
|
| 24 |
+
{"miRNA":"hsa-miR-22-3p", "log2FC":-0.43,"padj":0.041,"targets":"HIF1A, PTEN","pathway":"Hypoxia / PI3K"},
|
| 25 |
+
{"miRNA":"hsa-miR-200c-3p","log2FC":-0.38,"padj":0.044,"targets":"ZEB1, ZEB2","pathway":"EMT suppression"},
|
| 26 |
+
],
|
| 27 |
+
"BRCA1": [
|
| 28 |
+
{"miRNA":"hsa-miR-155-5p", "log2FC":-0.81,"padj":0.008,"targets":"SHIP1, SOCS1","pathway":"Immune evasion"},
|
| 29 |
+
{"miRNA":"hsa-miR-146a-5p","log2FC":-0.65,"padj":0.019,"targets":"TRAF6, IRAK1","pathway":"NF-kB signalling"},
|
| 30 |
+
{"miRNA":"hsa-miR-21-5p", "log2FC":-0.55,"padj":0.027,"targets":"PTEN, PDCD4","pathway":"Apoptosis"},
|
| 31 |
+
{"miRNA":"hsa-miR-17-5p", "log2FC":-0.47,"padj":0.036,"targets":"RB1, E2F1","pathway":"Cell cycle"},
|
| 32 |
+
{"miRNA":"hsa-miR-34a-5p", "log2FC":-0.41,"padj":0.049,"targets":"BCL2, CDK6","pathway":"p53 axis"},
|
| 33 |
+
],
|
| 34 |
+
"TP53": [
|
| 35 |
+
{"miRNA":"hsa-miR-34a-5p", "log2FC":-1.10,"padj":0.001,"targets":"BCL2, CDK6","pathway":"p53-miR-34 axis"},
|
| 36 |
+
{"miRNA":"hsa-miR-192-5p", "log2FC":-0.90,"padj":0.005,"targets":"MDM2, DHFR","pathway":"p53 feedback"},
|
| 37 |
+
{"miRNA":"hsa-miR-145-5p", "log2FC":-0.75,"padj":0.012,"targets":"MYC, EGFR","pathway":"Growth suppression"},
|
| 38 |
+
{"miRNA":"hsa-miR-107", "log2FC":-0.62,"padj":0.023,"targets":"CDK6, HIF1B","pathway":"Hypoxia / cell cycle"},
|
| 39 |
+
{"miRNA":"hsa-miR-215-5p", "log2FC":-0.51,"padj":0.038,"targets":"DTL, DHFR","pathway":"DNA damage response"},
|
| 40 |
+
],
|
| 41 |
+
}
|
| 42 |
+
|
| 43 |
+
def predict_mirna(gene):
|
| 44 |
+
return pd.DataFrame(MIRNA_DB.get(gene, []))
|
| 45 |
+
|
| 46 |
+
# ── TAB 2 — TP53 siRNA ───────────────────────────────────────────────────────
|
| 47 |
+
SIRNA_DB = {
|
| 48 |
+
"LUAD": [
|
| 49 |
+
{"Gene":"SPC24","dCERES":-0.175,"log2FC":1.13,"Drug_status":"Novel","siRNA":"GCAGCUGAAGAAACUGAAU"},
|
| 50 |
+
{"Gene":"BUB1B","dCERES":-0.119,"log2FC":1.12,"Drug_status":"Novel","siRNA":"CCAAAGAGCUGAAGAACAU"},
|
| 51 |
+
{"Gene":"CDC45","dCERES":-0.144,"log2FC":1.26,"Drug_status":"Novel","siRNA":"GCAUCAAGAUGAAGGAGAU"},
|
| 52 |
+
{"Gene":"PLK1", "dCERES":-0.239,"log2FC":1.03,"Drug_status":"Clinical","siRNA":"GACGCUCAAGAUGCAGAUU"},
|
| 53 |
+
{"Gene":"CDK1", "dCERES":-0.201,"log2FC":1.00,"Drug_status":"Clinical","siRNA":"GCAGAAGCACUGAAGAUUU"},
|
| 54 |
+
],
|
| 55 |
+
"BRCA": [
|
| 56 |
+
{"Gene":"AURKA","dCERES":-0.165,"log2FC":1.20,"Drug_status":"Clinical","siRNA":"GCACUGAAGAUGCAGAAUU"},
|
| 57 |
+
{"Gene":"AURKB","dCERES":-0.140,"log2FC":1.15,"Drug_status":"Clinical","siRNA":"CCUGAAGACGCUCAAGGUU"},
|
| 58 |
+
{"Gene":"CENPW","dCERES":-0.125,"log2FC":0.95,"Drug_status":"Novel","siRNA":"GCAGAAGCACUGAAGAUUU"},
|
| 59 |
+
{"Gene":"RFC2", "dCERES":-0.136,"log2FC":0.50,"Drug_status":"Novel","siRNA":"GCAAGAUGCAGAAGCACUU"},
|
| 60 |
+
{"Gene":"TYMS", "dCERES":-0.131,"log2FC":0.72,"Drug_status":"Approved","siRNA":"GGACGCUCAAGAUGCAGAU"},
|
| 61 |
+
],
|
| 62 |
+
"COAD": [
|
| 63 |
+
{"Gene":"KRAS", "dCERES":-0.210,"log2FC":0.80,"Drug_status":"Clinical","siRNA":"GCUGGAGCUGGUGGUAGUU"},
|
| 64 |
+
{"Gene":"WEE1", "dCERES":-0.180,"log2FC":1.05,"Drug_status":"Clinical","siRNA":"GCAGCUGAAGAAACUGAAU"},
|
| 65 |
+
{"Gene":"CHEK1","dCERES":-0.155,"log2FC":0.90,"Drug_status":"Clinical","siRNA":"CCAAAGAGCUGAAGAACAU"},
|
| 66 |
+
{"Gene":"RFC2", "dCERES":-0.130,"log2FC":0.55,"Drug_status":"Novel","siRNA":"GCAUCAAGAUGAAGGAGAU"},
|
| 67 |
+
{"Gene":"PKMYT1","dCERES":-0.122,"log2FC":1.07,"Drug_status":"Clinical","siRNA":"GACGCUCAAGAUGCAGAUU"},
|
| 68 |
+
],
|
| 69 |
+
}
|
| 70 |
+
|
| 71 |
+
def predict_sirna(cancer):
|
| 72 |
+
return pd.DataFrame(SIRNA_DB.get(cancer, []))
|
| 73 |
+
|
| 74 |
+
# ── TAB 3 — lncRNA-TREM2 ─────────────────────────────────────────────────────
|
| 75 |
+
CERNA = [
|
| 76 |
+
{"lncRNA":"CYTOR","miRNA":"hsa-miR-138-5p","target":"AKT1","pathway":"TREM2 core signaling"},
|
| 77 |
+
{"lncRNA":"CYTOR","miRNA":"hsa-miR-138-5p","target":"NFKB1","pathway":"Neuroinflammation"},
|
| 78 |
+
{"lncRNA":"GAS5","miRNA":"hsa-miR-21-5p","target":"PTEN","pathway":"Neuroinflammation"},
|
| 79 |
+
{"lncRNA":"GAS5","miRNA":"hsa-miR-222-3p","target":"IL1B","pathway":"Neuroinflammation"},
|
| 80 |
+
{"lncRNA":"HOTAIRM1","miRNA":"hsa-miR-9-5p","target":"TREM2","pathway":"Direct TREM2 regulation"},
|
| 81 |
+
]
|
| 82 |
+
ASO = [
|
| 83 |
+
{"lncRNA":"GAS5","position":119,"accessibility":0.653,"GC_pct":50,"Tm":47.2,"priority":"HIGH"},
|
| 84 |
+
{"lncRNA":"CYTOR","position":507,"accessibility":0.653,"GC_pct":50,"Tm":46.8,"priority":"HIGH"},
|
| 85 |
+
{"lncRNA":"HOTAIRM1","position":234,"accessibility":0.621,"GC_pct":44,"Tm":44.1,"priority":"MEDIUM"},
|
| 86 |
+
{"lncRNA":"LINC00847","position":89,"accessibility":0.598,"GC_pct":56,"Tm":48.3,"priority":"MEDIUM"},
|
| 87 |
+
{"lncRNA":"ZFAS1","position":312,"accessibility":0.571,"GC_pct":48,"Tm":45.5,"priority":"MEDIUM"},
|
| 88 |
+
]
|
| 89 |
+
|
| 90 |
+
def get_lncrna():
|
| 91 |
+
return pd.DataFrame(CERNA), pd.DataFrame(ASO)
|
| 92 |
+
|
| 93 |
+
# ── TAB 4 — FGFR3 Drug ───────────────────────────────────────────────────────
|
| 94 |
+
FGFR3 = {
|
| 95 |
+
"P1 (hairpin loop)": [
|
| 96 |
+
{"Compound":"CHEMBL1575701","RNA_score":0.809,"Toxicity":0.01,"Final_score":0.793},
|
| 97 |
+
{"Compound":"CHEMBL15727", "RNA_score":0.805,"Toxicity":0.00,"Final_score":0.789},
|
| 98 |
+
{"Compound":"Thioguanine", "RNA_score":0.888,"Toxicity":32.5,"Final_score":0.742},
|
| 99 |
+
{"Compound":"Deazaguanine", "RNA_score":0.888,"Toxicity":35.0,"Final_score":0.735},
|
| 100 |
+
{"Compound":"CHEMBL441", "RNA_score":0.775,"Toxicity":5.2, "Final_score":0.721},
|
| 101 |
+
],
|
| 102 |
+
"P10 (G-quadruplex)": [
|
| 103 |
+
{"Compound":"CHEMBL15727", "RNA_score":0.805,"Toxicity":0.00,"Final_score":0.789},
|
| 104 |
+
{"Compound":"CHEMBL5411515","RNA_score":0.945,"Toxicity":37.1,"Final_score":0.761},
|
| 105 |
+
{"Compound":"CHEMBL90", "RNA_score":0.760,"Toxicity":2.1, "Final_score":0.745},
|
| 106 |
+
{"Compound":"CHEMBL102", "RNA_score":0.748,"Toxicity":8.4, "Final_score":0.712},
|
| 107 |
+
{"Compound":"Berberine", "RNA_score":0.735,"Toxicity":3.2, "Final_score":0.708},
|
| 108 |
+
],
|
| 109 |
+
}
|
| 110 |
+
|
| 111 |
+
def predict_drug(pocket):
|
| 112 |
+
df = pd.DataFrame(FGFR3.get(pocket, []))
|
| 113 |
+
fig, ax = plt.subplots(figsize=(6, 4), facecolor=CARD)
|
| 114 |
+
ax.set_facecolor(CARD)
|
| 115 |
+
ax.barh(df["Compound"], df["Final_score"], color=ACC)
|
| 116 |
+
ax.set_xlabel("Final Score", color=TXT)
|
| 117 |
+
ax.tick_params(colors=TXT)
|
| 118 |
+
for sp in ax.spines.values(): sp.set_edgecolor("#334155")
|
| 119 |
+
ax.set_title(f"Top compounds — {pocket}", color=TXT, fontsize=10)
|
| 120 |
+
plt.tight_layout()
|
| 121 |
+
buf = BytesIO(); plt.savefig(buf, format="png", dpi=120, facecolor=CARD); plt.close()
|
| 122 |
+
buf.seek(0)
|
| 123 |
+
return df, Image.open(buf)
|
| 124 |
+
|
| 125 |
+
# ── TAB 5 — OpenVariant ──────────────────────────────────────────────────────
|
| 126 |
+
VARIANT_DB = {
|
| 127 |
+
"BRCA1:p.R1699Q": {"score":0.03, "cls":"Benign", "conf":"High"},
|
| 128 |
+
"BRCA1:p.R1699W": {"score":0.97, "cls":"Pathogenic", "conf":"High"},
|
| 129 |
+
"BRCA2:p.D2723A": {"score":0.999,"cls":"Pathogenic", "conf":"High"},
|
| 130 |
+
"TP53:p.R248W": {"score":0.998,"cls":"Pathogenic", "conf":"High"},
|
| 131 |
+
"TP53:p.R248Q": {"score":0.995,"cls":"Pathogenic", "conf":"High"},
|
| 132 |
+
"EGFR:p.L858R": {"score":0.96, "cls":"Pathogenic", "conf":"High"},
|
| 133 |
+
"ALK:p.F1174L": {"score":0.94, "cls":"Pathogenic", "conf":"High"},
|
| 134 |
+
}
|
| 135 |
+
PLAIN = {
|
| 136 |
+
"Pathogenic": "This variant is likely to cause disease. Clinical follow-up is strongly recommended.",
|
| 137 |
+
"Likely Pathogenic":"This variant is probably harmful. Discuss with your doctor.",
|
| 138 |
+
"Benign": "This variant is likely harmless. Common in the general population.",
|
| 139 |
+
"Likely Benign": "This variant is probably harmless. No strong reason for concern.",
|
| 140 |
+
}
|
| 141 |
+
|
| 142 |
+
def predict_variant(hgvs, sift, polyphen, gnomad):
|
| 143 |
+
hgvs = hgvs.strip()
|
| 144 |
+
if hgvs in VARIANT_DB:
|
| 145 |
+
r = VARIANT_DB[hgvs]
|
| 146 |
+
cls, conf, score = r["cls"], r["conf"], r["score"]
|
| 147 |
+
else:
|
| 148 |
+
score = 0.0
|
| 149 |
+
if sift < 0.05: score += 0.4
|
| 150 |
+
if polyphen > 0.85: score += 0.35
|
| 151 |
+
if gnomad < 0.0001: score += 0.25
|
| 152 |
+
score = round(score, 3)
|
| 153 |
+
cls = "Pathogenic" if score > 0.6 else ("Likely Pathogenic" if score > 0.4 else "Benign")
|
| 154 |
+
conf = "High" if (sift < 0.01 or sift > 0.9) else "Moderate"
|
| 155 |
+
colour = "#ef4444" if "Pathogenic" in cls else "#22c55e"
|
| 156 |
+
icon = "WARNING" if "Pathogenic" in cls else "OK"
|
| 157 |
+
bar_w = int(score * 100)
|
| 158 |
+
explanation = PLAIN.get(cls, "")
|
| 159 |
+
html = (
|
| 160 |
+
f"<div style='background:{CARD};padding:16px;border-radius:8px;"
|
| 161 |
+
f"font-family:sans-serif;color:{TXT}'>"
|
| 162 |
+
f"<h3 style='color:{colour}'>[{icon}] {cls}</h3>"
|
| 163 |
+
f"<p>Score: <b>{score:.3f}</b> | Confidence: <b>{conf}</b></p>"
|
| 164 |
+
f"<div style='background:#334155;border-radius:4px;height:16px;width:100%'>"
|
| 165 |
+
f"<div style='background:{colour};height:16px;border-radius:4px;width:{bar_w}%'></div>"
|
| 166 |
+
f"</div>"
|
| 167 |
+
f"<p style='margin-top:12px'>{explanation}</p>"
|
| 168 |
+
f"<p style='font-size:11px;color:#64748b;margin-top:8px'>"
|
| 169 |
+
f"Research tool only. Not for clinical use.</p></div>"
|
| 170 |
+
)
|
| 171 |
+
return html
|
| 172 |
+
|
| 173 |
+
# ── TAB 6 — LNP Corona ────────────���──────────────────────────────────────────
|
| 174 |
+
def predict_corona(size, zeta, peg, lipid):
|
| 175 |
+
score = 0
|
| 176 |
+
if lipid == "Ionizable": score += 2
|
| 177 |
+
elif lipid == "Cationic": score += 1
|
| 178 |
+
if abs(zeta) < 10: score += 1
|
| 179 |
+
if peg > 1.5: score += 2
|
| 180 |
+
if size < 100: score += 1
|
| 181 |
+
proteins = ["ApoE","Albumin","Fibrinogen","Vitronectin","ApoA-I"]
|
| 182 |
+
dominant = proteins[min(score, 4)]
|
| 183 |
+
efficacy = "High" if score >= 4 else "Medium" if score >= 2 else "Low"
|
| 184 |
+
return f"**Dominant corona protein:** {dominant}\n\n**Predicted efficacy class:** {efficacy}\n\n**Composite score:** {score}/6"
|
| 185 |
+
|
| 186 |
+
# ── TAB 7 — Liquid Biopsy ────────────────────────────────────────────────────
|
| 187 |
+
BM_W = {"CTHRC1":0.18,"FHL2":0.15,"LDHA":0.14,"P4HA1":0.13,"SERPINH1":0.12,
|
| 188 |
+
"ABCA8":-0.11,"CA4":-0.10,"CKB":-0.09,"NNMT":0.08,"CACNA2D2":-0.07}
|
| 189 |
+
|
| 190 |
+
def predict_cancer(c1,c2,c3,c4,c5,c6,c7,c8,c9,c10):
|
| 191 |
+
vals = [c1,c2,c3,c4,c5,c6,c7,c8,c9,c10]
|
| 192 |
+
names = list(BM_W.keys())
|
| 193 |
+
weights = list(BM_W.values())
|
| 194 |
+
raw = sum(v*w for v,w in zip(vals,weights))
|
| 195 |
+
prob = 1 / (1 + np.exp(-raw * 2))
|
| 196 |
+
label = "CANCER" if prob > 0.5 else "HEALTHY"
|
| 197 |
+
colour = "#ef4444" if prob > 0.5 else "#22c55e"
|
| 198 |
+
contribs = [v*w for v,w in zip(vals,weights)]
|
| 199 |
+
cols = [ACC if c > 0 else ACC2 for c in contribs]
|
| 200 |
+
fig, ax = plt.subplots(figsize=(6, 3.5), facecolor=CARD)
|
| 201 |
+
ax.set_facecolor(CARD)
|
| 202 |
+
ax.barh(names, contribs, color=cols)
|
| 203 |
+
ax.axvline(0, color=TXT, linewidth=0.8)
|
| 204 |
+
ax.set_xlabel("Contribution to cancer score", color=TXT)
|
| 205 |
+
ax.tick_params(colors=TXT, labelsize=8)
|
| 206 |
+
for sp in ax.spines.values(): sp.set_edgecolor("#334155")
|
| 207 |
+
ax.set_title("Protein contributions", color=TXT, fontsize=10)
|
| 208 |
+
plt.tight_layout()
|
| 209 |
+
buf = BytesIO(); plt.savefig(buf, format="png", dpi=120, facecolor=CARD); plt.close()
|
| 210 |
+
buf.seek(0)
|
| 211 |
+
return (f"<div style='background:{CARD};padding:12px;border-radius:8px;"
|
| 212 |
+
f"color:{colour};font-size:20px;font-family:sans-serif'><b>{label}</b><br>"
|
| 213 |
+
f"<span style='color:{TXT};font-size:14px'>Probability: {prob:.2f}</span></div>"), \
|
| 214 |
+
Image.open(buf)
|
| 215 |
+
|
| 216 |
+
# ── TAB 8 — Flow Corona ──────────────────────────────────────────────────────
|
| 217 |
+
def predict_flow(size, zeta, peg, charge, flow_rate):
|
| 218 |
+
csi = (flow_rate/40)*0.6 + (peg/5)*0.2 + (1 if charge=="Cationic" else 0)*0.2
|
| 219 |
+
csi = round(min(csi, 1.0), 3)
|
| 220 |
+
stability = "High remodeling" if csi > 0.6 else "Medium" if csi > 0.3 else "Stable"
|
| 221 |
+
t = np.linspace(0, 60, 200)
|
| 222 |
+
kf = 0.03 * (1 + flow_rate/40)
|
| 223 |
+
ks = 0.005 * (1 + flow_rate/80)
|
| 224 |
+
fig, ax = plt.subplots(figsize=(6, 3.5), facecolor=CARD)
|
| 225 |
+
ax.set_facecolor(CARD)
|
| 226 |
+
ax.plot(t, 60*np.exp(-0.03*t)+20, color="#60a5fa", ls="--", label="Albumin (static)")
|
| 227 |
+
ax.plot(t, 60*np.exp(-kf*t)+10, color="#60a5fa", label="Albumin (flow)")
|
| 228 |
+
ax.plot(t, 5*(1-np.exp(-0.005*t))+5, color=ACC, ls="--", label="ApoE (static)")
|
| 229 |
+
ax.plot(t, 5*(1-np.exp(-ks*t))+10, color=ACC, label="ApoE (flow)")
|
| 230 |
+
ax.set_xlabel("Time (min)", color=TXT)
|
| 231 |
+
ax.set_ylabel("% Corona", color=TXT)
|
| 232 |
+
ax.tick_params(colors=TXT)
|
| 233 |
+
ax.legend(fontsize=7, labelcolor=TXT, facecolor=CARD)
|
| 234 |
+
for sp in ax.spines.values(): sp.set_edgecolor("#334155")
|
| 235 |
+
ax.set_title("Vroman Effect: Albumin to ApoE exchange", color=TXT, fontsize=9)
|
| 236 |
+
plt.tight_layout()
|
| 237 |
+
buf = BytesIO(); plt.savefig(buf, format="png", dpi=120, facecolor=CARD); plt.close()
|
| 238 |
+
buf.seek(0)
|
| 239 |
+
return f"**Corona Shift Index: {csi}** — {stability}", Image.open(buf)
|
| 240 |
+
|
| 241 |
+
# ── TAB 9 — LNP Brain ────────────────────────────────────────────────────────
|
| 242 |
+
def predict_bbb(smiles, pka, zeta):
|
| 243 |
+
logp = smiles.count("C")*0.3 - smiles.count("O")*0.5 + 1.5
|
| 244 |
+
apoe_pct = max(0, min(40, (7.0 - pka)*8 + abs(zeta)*0.5 + logp*0.8))
|
| 245 |
+
bbb_prob = min(0.95, apoe_pct / 30)
|
| 246 |
+
tier = "HIGH (>20%)" if apoe_pct > 20 else "MEDIUM (10-20%)" if apoe_pct > 10 else "LOW (<10%)"
|
| 247 |
+
cats = ["ApoE%","BBB","logP","pKa","Zeta"]
|
| 248 |
+
vals = [apoe_pct/40, bbb_prob, min(logp/5,1), (7-abs(pka-6.5))/7, (10-abs(zeta))/10]
|
| 249 |
+
angles = np.linspace(0, 2*np.pi, len(cats), endpoint=False).tolist()
|
| 250 |
+
v2 = vals + [vals[0]]
|
| 251 |
+
a2 = angles + [angles[0]]
|
| 252 |
+
fig, ax = plt.subplots(figsize=(5, 4), subplot_kw={"polar": True}, facecolor=CARD)
|
| 253 |
+
ax.set_facecolor(CARD)
|
| 254 |
+
ax.plot(a2, v2, color=ACC, linewidth=2)
|
| 255 |
+
ax.fill(a2, v2, color=ACC, alpha=0.2)
|
| 256 |
+
ax.set_xticks(angles); ax.set_xticklabels(cats, color=TXT, fontsize=8)
|
| 257 |
+
ax.tick_params(colors=TXT)
|
| 258 |
+
plt.tight_layout()
|
| 259 |
+
buf = BytesIO(); plt.savefig(buf, format="png", dpi=120, facecolor=CARD); plt.close()
|
| 260 |
+
buf.seek(0)
|
| 261 |
+
return f"**Predicted ApoE:** {apoe_pct:.1f}% — {tier}\n\n**BBB Probability:** {bbb_prob:.2f}", \
|
| 262 |
+
Image.open(buf)
|
| 263 |
+
|
| 264 |
+
# ── TAB 10 — AutoCorona NLP ──────────────────────────────────────────────────
|
| 265 |
+
PROTEINS = ["albumin","apolipoprotein","fibrinogen","vitronectin","clusterin",
|
| 266 |
+
"igm","iga","igg","complement","transferrin","alpha-2-macroglobulin"]
|
| 267 |
+
|
| 268 |
+
def extract_corona(text):
|
| 269 |
+
out = {"nanoparticle_composition":"","size_nm":None,"zeta_mv":None,
|
| 270 |
+
"PDI":None,"protein_source":"","corona_proteins":[],"confidence":{}}
|
| 271 |
+
m = re.search(r"(\d+\.?\d*)\s*(?:nm|nanometer)", text, re.I)
|
| 272 |
+
if m: out["size_nm"] = float(m.group(1)); out["confidence"]["size_nm"] = "HIGH"
|
| 273 |
+
m = re.search(r"([+-]?\d+\.?\d*)\s*mV", text, re.I)
|
| 274 |
+
if m: out["zeta_mv"] = float(m.group(1)); out["confidence"]["zeta_mv"] = "HIGH"
|
| 275 |
+
m = re.search(r"PDI\s*[=:of]*\s*(\d+\.?\d*)", text, re.I)
|
| 276 |
+
if m: out["PDI"] = float(m.group(1)); out["confidence"]["PDI"] = "HIGH"
|
| 277 |
+
for src in ["human plasma","human serum","fetal bovine serum","FBS","PBS"]:
|
| 278 |
+
if src.lower() in text.lower():
|
| 279 |
+
out["protein_source"] = src; out["confidence"]["protein_source"] = "HIGH"; break
|
| 280 |
+
out["corona_proteins"] = [
|
| 281 |
+
{"name":p,"confidence":"MEDIUM"} for p in PROTEINS if p in text.lower()
|
| 282 |
+
]
|
| 283 |
+
for lip in ["DSPC","DOPE","MC3","DLin","cholesterol","PEG","DOTAP"]:
|
| 284 |
+
if lip in text: out["nanoparticle_composition"] += lip + " "
|
| 285 |
+
out["nanoparticle_composition"] = out["nanoparticle_composition"].strip()
|
| 286 |
+
flags = []
|
| 287 |
+
if not out["size_nm"]: flags.append("size_nm not found")
|
| 288 |
+
if not out["zeta_mv"]: flags.append("zeta_mv not found")
|
| 289 |
+
if not out["corona_proteins"]:flags.append("no corona proteins detected")
|
| 290 |
+
summary = "All key fields extracted" if not flags else " | ".join(flags)
|
| 291 |
+
return json.dumps(out, indent=2), summary
|
| 292 |
+
|
| 293 |
+
# ── CSS & BUILD ───────────────────────────────────────────────────────────────
|
| 294 |
+
css = (
|
| 295 |
+
f"body,.gradio-container{{background:{BG}!important;color:{TXT}!important}}"
|
| 296 |
+
f".tab-nav button{{color:{TXT}!important;background:{CARD}!important}}"
|
| 297 |
+
f".tab-nav button.selected{{border-bottom:2px solid {ACC}!important;color:{ACC}!important}}"
|
| 298 |
+
f"h1,h2,h3{{color:{ACC}!important}}"
|
| 299 |
+
f".gr-button-primary{{background:{ACC}!important;border:none!important}}"
|
| 300 |
+
f"footer{{display:none!important}}"
|
| 301 |
+
)
|
| 302 |
+
|
| 303 |
+
with gr.Blocks(css=css, title="K R&D Lab") as demo:
|
| 304 |
+
gr.Markdown(
|
| 305 |
+
"# K R&D Lab — Computational Biology Suite\n"
|
| 306 |
+
"**Oksana Kolisnyk** · ML Engineer @ [FAZENA](https://fazena.org) · "
|
| 307 |
+
"[kosatiks-group.pp.ua](https://kosatiks-group.pp.ua) \n"
|
| 308 |
+
"> 10 open-source computational biology tools. Hypothesis testing across disciplines."
|
| 309 |
+
)
|
| 310 |
+
|
| 311 |
+
with gr.Tabs():
|
| 312 |
+
|
| 313 |
+
with gr.TabItem("BRCA2 miRNA"):
|
| 314 |
+
gr.Markdown("### Tumor Suppressor miRNAs\nDownregulated miRNAs as miRNA-mimic therapy candidates.")
|
| 315 |
+
g1 = gr.Dropdown(["BRCA2","BRCA1","TP53"], value="BRCA2", label="Gene")
|
| 316 |
+
b1 = gr.Button("Find miRNAs", variant="primary")
|
| 317 |
+
o1 = gr.Dataframe(label="Top 5 downregulated miRNAs")
|
| 318 |
+
gr.Examples([["BRCA2"],["TP53"]], inputs=[g1])
|
| 319 |
+
b1.click(predict_mirna, g1, o1)
|
| 320 |
+
|
| 321 |
+
with gr.TabItem("TP53 siRNA"):
|
| 322 |
+
gr.Markdown("### Synthetic Lethal siRNA Targets\nDepMap essentiality + siRNA sequences.")
|
| 323 |
+
g2 = gr.Dropdown(["LUAD","BRCA","COAD"], value="LUAD", label="Cancer type")
|
| 324 |
+
b2 = gr.Button("Find Targets", variant="primary")
|
| 325 |
+
o2 = gr.Dataframe(label="Top 5 siRNA targets")
|
| 326 |
+
gr.Examples([["LUAD"],["BRCA"]], inputs=[g2])
|
| 327 |
+
b2.click(predict_sirna, g2, o2)
|
| 328 |
+
|
| 329 |
+
with gr.TabItem("lncRNA-TREM2"):
|
| 330 |
+
gr.Markdown("### lncRNA Networks in TREM2-Dependent Inflammation\nAlzheimer's therapy: ceRNA axes and ASO design.")
|
| 331 |
+
b3 = gr.Button("Load Results", variant="primary")
|
| 332 |
+
o3a = gr.Dataframe(label="ceRNA Network")
|
| 333 |
+
o3b = gr.Dataframe(label="ASO Candidates")
|
| 334 |
+
b3.click(get_lncrna, [], [o3a, o3b])
|
| 335 |
+
|
| 336 |
+
with gr.TabItem("FGFR3 Drug"):
|
| 337 |
+
gr.Markdown("### RNA-Directed Drug Discovery: FGFR3\nSmall molecules targeting FGFR3 5'UTR for bladder cancer.")
|
| 338 |
+
g4 = gr.Radio(["P1 (hairpin loop)","P10 (G-quadruplex)"],
|
| 339 |
+
value="P1 (hairpin loop)", label="Target pocket")
|
| 340 |
+
b4 = gr.Button("Screen Compounds", variant="primary")
|
| 341 |
+
o4t = gr.Dataframe(label="Top 5 candidates")
|
| 342 |
+
o4p = gr.Image(label="Binding scores")
|
| 343 |
+
gr.Examples([["P1 (hairpin loop)"],["P10 (G-quadruplex)"]], inputs=[g4])
|
| 344 |
+
b4.click(predict_drug, g4, [o4t, o4p])
|
| 345 |
+
|
| 346 |
+
with gr.TabItem("OpenVariant"):
|
| 347 |
+
gr.Markdown("### OpenVariant — Pathogenicity Classifier\nOpen-source alternative to AlphaMissense. AUC=0.939 on ClinVar 2026.")
|
| 348 |
+
hgvs = gr.Textbox(label="HGVS notation", placeholder="BRCA1:p.R1699Q")
|
| 349 |
+
gr.Markdown("**Or enter scores manually:**")
|
| 350 |
+
with gr.Row():
|
| 351 |
+
sift = gr.Slider(0, 1, 0.5, label="SIFT (0=damaging)")
|
| 352 |
+
pp = gr.Slider(0, 1, 0.5, label="PolyPhen-2")
|
| 353 |
+
gn = gr.Slider(0, 0.01, 0.001, label="gnomAD AF", step=0.0001)
|
| 354 |
+
b5 = gr.Button("Predict Pathogenicity", variant="primary")
|
| 355 |
+
o5 = gr.HTML(label="Result")
|
| 356 |
+
gr.Examples([["BRCA1:p.R1699Q",0.82,0.05,0.0012],
|
| 357 |
+
["TP53:p.R248W",0.00,1.00,0.0],
|
| 358 |
+
["BRCA2:p.D2723A",0.01,0.98,0.0]],
|
| 359 |
+
inputs=[hgvs,sift,pp,gn])
|
| 360 |
+
b5.click(predict_variant, [hgvs,sift,pp,gn], o5)
|
| 361 |
+
|
| 362 |
+
with gr.TabItem("LNP Corona"):
|
| 363 |
+
gr.Markdown("### LNP Protein Corona Prediction\nDominant corona protein + transfection efficacy from formulation.")
|
| 364 |
+
with gr.Row():
|
| 365 |
+
sz = gr.Slider(50, 300, 100, label="Size (nm)")
|
| 366 |
+
zt = gr.Slider(-40, 10, -5, label="Zeta (mV)")
|
| 367 |
+
with gr.Row():
|
| 368 |
+
pg = gr.Slider(0, 5, 1.5, label="PEG mol%")
|
| 369 |
+
lp = gr.Dropdown(["Ionizable","Cationic","Anionic","Neutral"],
|
| 370 |
+
value="Ionizable", label="Lipid type")
|
| 371 |
+
b6 = gr.Button("Predict", variant="primary")
|
| 372 |
+
o6 = gr.Markdown()
|
| 373 |
+
gr.Examples([[100,-5,1.5,"Ionizable"],[80,5,0.5,"Cationic"]],
|
| 374 |
+
inputs=[sz,zt,pg,lp])
|
| 375 |
+
b6.click(predict_corona, [sz,zt,pg,lp], o6)
|
| 376 |
+
|
| 377 |
+
with gr.TabItem("Liquid Biopsy"):
|
| 378 |
+
gr.Markdown("### Protein Corona Cancer Diagnostics\nClassify cancer vs healthy from plasma protein z-scores.")
|
| 379 |
+
with gr.Row():
|
| 380 |
+
p1=gr.Slider(-3,3,0,label="CTHRC1"); p2=gr.Slider(-3,3,0,label="FHL2")
|
| 381 |
+
p3=gr.Slider(-3,3,0,label="LDHA"); p4=gr.Slider(-3,3,0,label="P4HA1")
|
| 382 |
+
p5=gr.Slider(-3,3,0,label="SERPINH1")
|
| 383 |
+
with gr.Row():
|
| 384 |
+
p6=gr.Slider(-3,3,0,label="ABCA8"); p7=gr.Slider(-3,3,0,label="CA4")
|
| 385 |
+
p8=gr.Slider(-3,3,0,label="CKB"); p9=gr.Slider(-3,3,0,label="NNMT")
|
| 386 |
+
p10=gr.Slider(-3,3,0,label="CACNA2D2")
|
| 387 |
+
b7 = gr.Button("Classify", variant="primary")
|
| 388 |
+
o7t = gr.HTML(); o7p = gr.Image(label="Feature contributions")
|
| 389 |
+
gr.Examples([[2,2,1.5,1.8,1.6,-1,-1.2,-0.8,1.4,-1.1],
|
| 390 |
+
[0,0,0,0,0,0,0,0,0,0]],
|
| 391 |
+
inputs=[p1,p2,p3,p4,p5,p6,p7,p8,p9,p10])
|
| 392 |
+
b7.click(predict_cancer, [p1,p2,p3,p4,p5,p6,p7,p8,p9,p10], [o7t,o7p])
|
| 393 |
+
|
| 394 |
+
with gr.TabItem("Flow Corona"):
|
| 395 |
+
gr.Markdown("### Corona Remodeling Under Blood Flow\nVroman effect model: albumin displacement by apolipoproteins.")
|
| 396 |
+
with gr.Row():
|
| 397 |
+
s8=gr.Slider(50,300,100,label="Size (nm)")
|
| 398 |
+
z8=gr.Slider(-40,10,-5,label="Zeta (mV)")
|
| 399 |
+
pg8=gr.Slider(0,5,1.5,label="PEG mol%")
|
| 400 |
+
with gr.Row():
|
| 401 |
+
ch8=gr.Dropdown(["Ionizable","Cationic","Anionic","Neutral"],
|
| 402 |
+
value="Ionizable",label="Charge type")
|
| 403 |
+
fl8=gr.Slider(0,40,20,label="Flow rate cm/s (aorta=40)")
|
| 404 |
+
b8=gr.Button("Model Vroman Effect", variant="primary")
|
| 405 |
+
o8t=gr.Markdown(); o8p=gr.Image(label="Kinetics plot")
|
| 406 |
+
gr.Examples([[100,-5,1.5,"Ionizable",40],[150,5,0.5,"Cationic",10]],
|
| 407 |
+
inputs=[s8,z8,pg8,ch8,fl8])
|
| 408 |
+
b8.click(predict_flow, [s8,z8,pg8,ch8,fl8], [o8t,o8p])
|
| 409 |
+
|
| 410 |
+
with gr.TabItem("LNP Brain"):
|
| 411 |
+
gr.Markdown("### LNP Brain Delivery Predictor\nApoE corona enrichment and BBB crossing probability for GBM.")
|
| 412 |
+
smi = gr.Textbox(label="Ionizable lipid SMILES",
|
| 413 |
+
value="CC(C)CC(=O)OCC(COC(=O)CC(C)C)OC(=O)CC(C)C")
|
| 414 |
+
with gr.Row():
|
| 415 |
+
pk = gr.Slider(4, 8, 6.5, step=0.1, label="pKa")
|
| 416 |
+
zt9 = gr.Slider(-20, 10, -3, label="Zeta (mV)")
|
| 417 |
+
b9 = gr.Button("Predict BBB Crossing", variant="primary")
|
| 418 |
+
o9t = gr.Markdown(); o9p = gr.Image(label="Radar profile")
|
| 419 |
+
gr.Examples([["CC(C)CC(=O)OCC(COC(=O)CC(C)C)OC(=O)CC(C)C", 6.5, -3]],
|
| 420 |
+
inputs=[smi,pk,zt9])
|
| 421 |
+
b9.click(predict_bbb, [smi,pk,zt9], [o9t,o9p])
|
| 422 |
+
|
| 423 |
+
with gr.TabItem("AutoCorona NLP"):
|
| 424 |
+
gr.Markdown("### AutoCorona NLP Extraction\nPaste any paper abstract to extract structured LNP corona data.")
|
| 425 |
+
txt = gr.Textbox(lines=6, label="Paper abstract or methods",
|
| 426 |
+
placeholder="Paste text here...")
|
| 427 |
+
b10 = gr.Button("Extract Data", variant="primary")
|
| 428 |
+
o10j = gr.Code(label="Extracted JSON", language="json")
|
| 429 |
+
o10f = gr.Textbox(label="Validation flags")
|
| 430 |
+
gr.Examples([[
|
| 431 |
+
"LNPs composed of MC3, DSPC, Cholesterol (50:10:40 mol%) with 1.5% PEG-DMG. "
|
| 432 |
+
"Hydrodynamic diameter was 98 nm, zeta potential -3.2 mV, PDI 0.12. "
|
| 433 |
+
"Incubated in human plasma. Corona: albumin, apolipoprotein E, fibrinogen."
|
| 434 |
+
]], inputs=[txt])
|
| 435 |
+
b10.click(extract_corona, txt, [o10j, o10f])
|
| 436 |
+
|
| 437 |
+
gr.Markdown(
|
| 438 |
+
"---\n**K R&D Lab** | Research tool only — not for clinical use | "
|
| 439 |
+
"[GitHub](https://github.com/oksana-kolisnyk/K-RnD-Lab-BIO-2026) | "
|
| 440 |
+
"[fazena.org](https://fazena.org)"
|
| 441 |
+
)
|
| 442 |
+
|
| 443 |
+
if __name__ == "__main__":
|
| 444 |
+
demo.launch()
|