Sumitx369/Genome_SLM
0
1import gradio as gr2import numpy as np3import onnxruntime as ort4 5WINDOW = 1286B2I = {'A': 0, 'C': 1, 'G': 2, 'T': 3, 'N': 4}7THRESHOLD = 0.5 # set to your tuned best-F1 threshold from the notebook8 9sess = ort.InferenceSession('genome_slm.onnx') # auto-loads genome_slm.onnx.data alongside10 11# Sample 128-base reference windows for the Examples panel.12SAMPLES = [13 ['GCTAAAGACAATTACATAACATACACGTCAGCACGAAACTTGTTGGCCCAGTGTGAATCGCTTAAGGGTTAAGTAAGTGTGATGCATACGCCTTTACTTGCTGTGTCCACCCCATCGGACTGGCATTT', 'T'],14 ['TTATTACACTCAGAAACAGAACTCGGGTAATTTTGACAGGTCACGCAGAGGCGCGCCCTCCTGAAGTGCGTGGACACTCGCTATGAATCTCTGATTTACCCACTCTGCCAAACTCCAGCGCGGTCAGT', 'A'],15 ['TCCATCACCCTAAGTAACCGAATAATGCGTTCGCTCTATTGACTACGACGCGCTCATTCCCTTGTCGGAGAGTTATGGAACAAGGACGCTGTCTGAGACTAGAAGACAGATAGTGCACACGACCGGCG', 'G'],16]17 18 19def encode(seq):20 return np.array([[B2I.get(b, 4) for b in seq.upper()]], dtype=np.int64)21 22 23def predict(ref_seq, alt_base):24 ref_seq = ref_seq.upper().strip()25 if len(ref_seq) != WINDOW:26 return {'⚠️ need exactly {} bases (you gave {})'.format(WINDOW, len(ref_seq)): 1.0}27 c = WINDOW // 228 alt = list(ref_seq)29 alt[c] = (alt_base.upper().strip() or 'N')[0]30 logits = sess.run(None, {'ref': encode(ref_seq), 'alt': encode(''.join(alt))})[0][0]31 e = np.exp(logits - logits.max())32 p = e / e.sum()33 return {'pathogenic': float(p[1]), 'benign': float(p[0])}34 35 36EXPLAINER = """37---38## 🧬 What is this?39 40This tool predicts whether a single **DNA point mutation** is likely **pathogenic** (disease-causing)41or **benign** (harmless), based on the surrounding genomic sequence. You give it a stretch of reference42DNA and the new base at the center; it scores the change.43 44## 🔎 Pathogenic vs. benign — what do they mean?45 46| Term | Meaning |47|------|---------|48| **Pathogenic** | The mutation disrupts how a gene works and is linked to disease. |49| **Benign** | The mutation is tolerated — normal natural variation, no disease link. |50 51> In real clinical genetics there's also a third bucket, *Variant of Uncertain Significance (VUS)*.52> This model was trained only on confidently-labeled Pathogenic/Benign variants.53 54## 💡 Why is this useful?55 56Sequencing a single human genome turns up **millions of variants**, the vast majority harmless.57Finding the handful that might actually cause disease is a huge bottleneck for clinicians and researchers.58Models like this help **triage** — flagging which variants deserve a closer, expert look first.59 60## ⚙️ How it works (under the hood)61 62- A small Transformer **encoder**, built **from scratch** — including a **hand-written CUDA attention kernel**63 (custom softmax forward + backward), not PyTorch's built-in attention.64- **Twin-tower design**: it encodes the *reference* window and the *mutated* window separately, then65 classifies on the **difference** between them — because pathogenicity is about what the mutation *changed*.66- Trained on **ClinVar** labels with reference context from **Ensembl**, and evaluated on a67 **gene-disjoint split** (test genes never seen in training) — ROC-AUC ≈ **0.73**.68 69## ⚠️ Important caveats70 71- This is a **research / educational demo — not a clinical tool.** Do not use it for medical decisions.72- Fixed **128 bp** window, **single-base** substitutions only.73- It returns **probabilities, not certainties**. At the 0.5 threshold it catches ~50% of pathogenic74 variants, so treat a moderate score as "worth a look," not "harmless."75"""76 77with gr.Blocks(title='Genome SLM — variant pathogenicity') as demo:78 gr.Markdown('# 🧬 Genome SLM — Variant Pathogenicity Predictor')79 gr.Markdown('Paste a **128-base** reference DNA window and the **alternate base** at the center '80 'position. The model predicts whether that point mutation is pathogenic or benign.')81 82 with gr.Row():83 with gr.Column(scale=3):84 ref_in = gr.Textbox(label='Reference window (exactly 128 bases: A / C / G / T / N)',85 lines=3, placeholder='e.g. ACGTACGT... (128 characters)')86 with gr.Column(scale=1):87 alt_in = gr.Textbox(label='Alternate base (center)', max_lines=1, placeholder='A / C / G / T')88 btn = gr.Button('Predict', variant='primary')89 90 out = gr.Label(num_top_classes=2, label='Prediction')91 92 gr.Markdown('### 📋 Try a sample (click a row to load it into the inputs)')93 gr.Examples(examples=SAMPLES, inputs=[ref_in, alt_in], label='Example variants')94 95 btn.click(predict, inputs=[ref_in, alt_in], outputs=out)96 ref_in.submit(predict, inputs=[ref_in, alt_in], outputs=out)97 98 gr.Markdown(EXPLAINER)99 100if __name__ == '__main__':101 demo.launch()102 