fix: resolve broken HF Space + major enhancement to v2.0
Browse filesCRITICAL FIXES (app was not running):
- Dockerfile: fix entrypoint src/streamlit_app.py β app.py (was running
placeholder spiral demo instead of the actual VirtualGeneScope app)
- requirements.txt: replace git+https://...alphagenome.git with
alphagenome==0.6.1 (PyPI) β git installs fail silently in Docker builds
- requirements.txt: pin all dependency versions for reproducibility
- requirements.txt: add python-docx>=1.1.0 for DOCX export
- Dockerfile: use python:3.11-slim (stable LTS) instead of 3.13.5-slim
- README.md: correct sdk: streamlit β sdk: docker to match HF Space config
ENHANCEMENTS:
- Gene library expanded 14 β 16 genes: added VKORC1 (Warfarin sensitivity)
and HLA-B (Abacavir/Carbamazepine severe hypersensitivity)
- All 16 genes now have: key SNP (rsID/HLA allele), inheritance pattern,
UK-specific nursing notes, NMC platform alignment, NICE guideline links,
ClinVar + OMIM + PharmGKB external links, tissue default
- Demo mode expanded: Chromatin Accessibility and Contact Map tracks added
(in addition to RNA Expression + Splicing)
- DOCX export: download formatted gene analysis report with charts,
nursing reference card, NMC alignment, and external links
- New Nurse Reference tab: per-gene PGx alert panels (poor/normal metaboliser),
NICE/ClinVar/OMIM/PharmGKB/NHS Genomics England link buttons
- New NMC Alignment tab: full Platform 1β7 checklist, genomics nursing resources
- Session History tab: last 10 analyses in dataframe with clear button
- Clinical disclaimer: upgraded to prominent st.warning banner
- NMC proficiency mapping for all 16 genes
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- .gitignore +2 -0
- Dockerfile +4 -5
- README.md +33 -21
- app.py +469 -361
- requirements.txt +7 -6
|
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
|
|
|
| 1 |
+
._*
|
| 2 |
+
.DS_Store
|
|
@@ -1,20 +1,19 @@
|
|
| 1 |
-
FROM python:3.
|
| 2 |
|
| 3 |
WORKDIR /app
|
| 4 |
|
| 5 |
RUN apt-get update && apt-get install -y \
|
| 6 |
build-essential \
|
| 7 |
curl \
|
| 8 |
-
git \
|
| 9 |
&& rm -rf /var/lib/apt/lists/*
|
| 10 |
|
| 11 |
COPY requirements.txt ./
|
| 12 |
-
|
| 13 |
|
| 14 |
-
|
| 15 |
|
| 16 |
EXPOSE 8501
|
| 17 |
|
| 18 |
HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health
|
| 19 |
|
| 20 |
-
ENTRYPOINT ["streamlit", "run", "
|
|
|
|
| 1 |
+
FROM python:3.11-slim
|
| 2 |
|
| 3 |
WORKDIR /app
|
| 4 |
|
| 5 |
RUN apt-get update && apt-get install -y \
|
| 6 |
build-essential \
|
| 7 |
curl \
|
|
|
|
| 8 |
&& rm -rf /var/lib/apt/lists/*
|
| 9 |
|
| 10 |
COPY requirements.txt ./
|
| 11 |
+
RUN pip3 install --no-cache-dir -r requirements.txt
|
| 12 |
|
| 13 |
+
COPY app.py ./
|
| 14 |
|
| 15 |
EXPOSE 8501
|
| 16 |
|
| 17 |
HEALTHCHECK CMD curl --fail http://localhost:8501/_stcore/health
|
| 18 |
|
| 19 |
+
ENTRYPOINT ["streamlit", "run", "app.py", "--server.port=8501", "--server.address=0.0.0.0"]
|
|
@@ -1,35 +1,47 @@
|
|
| 1 |
---
|
| 2 |
-
title: Virtual Gene Scope
|
| 3 |
emoji: π§¬
|
| 4 |
-
colorFrom:
|
| 5 |
-
colorTo:
|
| 6 |
-
sdk:
|
| 7 |
-
|
| 8 |
-
app_file: app.py
|
| 9 |
pinned: false
|
|
|
|
| 10 |
tags:
|
| 11 |
- streamlit
|
| 12 |
- nursing
|
| 13 |
- genomics
|
| 14 |
- alphagenome
|
|
|
|
|
|
|
|
|
|
| 15 |
---
|
| 16 |
|
| 17 |
-
# Virtual Gene Scope
|
| 18 |
|
| 19 |
-
|
| 20 |
|
| 21 |
-
|
| 22 |
-
This application demonstrates how non-coding variants can impact gene expression, helping nurses understand complex genetic conditions beyond simple protein-coding errors.
|
| 23 |
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
- **Mutation Simulator**: Introduce variants in regulatory regions.
|
| 27 |
-
- **Visual Tracks**: See predicted changes in Promoter Activity and Splicing.
|
| 28 |
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
|
| 34 |
-
|
| 35 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
---
|
| 2 |
+
title: Virtual Gene Scope v2.0
|
| 3 |
emoji: π§¬
|
| 4 |
+
colorFrom: purple
|
| 5 |
+
colorTo: blue
|
| 6 |
+
sdk: docker
|
| 7 |
+
app_port: 8501
|
|
|
|
| 8 |
pinned: false
|
| 9 |
+
license: apache-2.0
|
| 10 |
tags:
|
| 11 |
- streamlit
|
| 12 |
- nursing
|
| 13 |
- genomics
|
| 14 |
- alphagenome
|
| 15 |
+
- pharmacogenomics
|
| 16 |
+
- uk-nursing
|
| 17 |
+
- nmc
|
| 18 |
---
|
| 19 |
|
| 20 |
+
# 𧬠Virtual Gene Scope v2.0
|
| 21 |
|
| 22 |
+
**Explore the Regulatory Genome with Google DeepMind's AlphaGenome.**
|
| 23 |
|
| 24 |
+
An educational tool for nursing students and healthcare professionals to visualise how non-coding genetic variants affect gene regulation β covering expression, splicing, chromatin accessibility, and contact maps.
|
|
|
|
| 25 |
|
| 26 |
+
> *Built by nurses who code. For nurses who care about genomics.*
|
| 27 |
+
> *Part of the [CQAI Nursing Education Toolkit](https://github.com/Clinical-Quality-Artifical-Intelligence)*
|
|
|
|
|
|
|
| 28 |
|
| 29 |
+
---
|
| 30 |
+
|
| 31 |
+
## βοΈ Clinical Disclaimer
|
| 32 |
+
|
| 33 |
+
This tool is for **educational purposes only**. It does not make clinical decisions and must not be used for patient care without independent verification by qualified healthcare professionals.
|
| 34 |
+
|
| 35 |
+
---
|
| 36 |
+
|
| 37 |
+
## β¨ Features
|
| 38 |
+
|
| 39 |
+
- π₯ **Disease Risk Mode** β Explore pathogenic variants in 8 disease-associated genes
|
| 40 |
+
- π **Drug Response Mode (PGx)** β See how variants affect drug metabolism (8 PGx genes)
|
| 41 |
+
- π§ͺ **Custom Variant Mode** β Input any variant and see predicted effects
|
| 42 |
+
- π« **Tissue Context** β Select from 10 tissue types with UBERON ontology terms
|
| 43 |
+
- π **Multi-modal Demo Tracks** β RNA expression, splicing, chromatin accessibility
|
| 44 |
+
- π©ββοΈ **Nursing Reference Cards** β NMC-aligned clinical guidance per gene
|
| 45 |
+
- π **DOCX Report Export** β Download a formatted gene analysis report
|
| 46 |
+
- π **ClinVar / PharmGKB / OMIM links** β Direct links to authoritative databases
|
| 47 |
+
- π **NMC Proficiency Map** β Standards of Proficiency alignment per gene
|
|
@@ -1,10 +1,28 @@
|
|
| 1 |
-
|
| 2 |
-
|
| 3 |
-
|
| 4 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
import os
|
| 6 |
|
| 7 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 8 |
try:
|
| 9 |
from alphagenome.models import dna_client
|
| 10 |
from alphagenome.data import genome
|
|
@@ -13,388 +31,478 @@ try:
|
|
| 13 |
except ImportError:
|
| 14 |
HAS_ALPHAGENOME = False
|
| 15 |
|
| 16 |
-
#
|
| 17 |
-
st.set_page_config(
|
| 18 |
-
page_title="Virtual Gene Scope v2.0",
|
| 19 |
-
page_icon="π§¬",
|
| 20 |
-
layout="wide"
|
| 21 |
-
)
|
| 22 |
|
| 23 |
-
# Clean Light Theme CSS
|
| 24 |
st.markdown("""
|
| 25 |
<style>
|
| 26 |
-
|
| 27 |
-
|
| 28 |
-
|
| 29 |
-
|
| 30 |
-
|
| 31 |
-
|
| 32 |
-
|
| 33 |
-
text-align: center;
|
| 34 |
-
}
|
| 35 |
-
.metric-card {
|
| 36 |
-
background: white;
|
| 37 |
-
border-radius: 15px;
|
| 38 |
-
padding: 1.5rem;
|
| 39 |
-
border: 1px solid #e0e0e0;
|
| 40 |
-
box-shadow: 0 2px 8px rgba(0,0,0,0.08);
|
| 41 |
-
margin: 0.5rem 0;
|
| 42 |
-
}
|
| 43 |
-
.gene-badge {
|
| 44 |
-
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
| 45 |
-
color: white;
|
| 46 |
-
padding: 5px 15px;
|
| 47 |
-
border-radius: 20px;
|
| 48 |
-
font-weight: bold;
|
| 49 |
-
display: inline-block;
|
| 50 |
-
}
|
| 51 |
-
.alert-box {
|
| 52 |
-
background: #fff5f5;
|
| 53 |
-
border-left: 4px solid #e53e3e;
|
| 54 |
-
padding: 1rem;
|
| 55 |
-
border-radius: 0 10px 10px 0;
|
| 56 |
-
margin: 1rem 0;
|
| 57 |
-
color: #c53030;
|
| 58 |
-
}
|
| 59 |
-
.success-box {
|
| 60 |
-
background: #f0fff4;
|
| 61 |
-
border-left: 4px solid #38a169;
|
| 62 |
-
padding: 1rem;
|
| 63 |
-
border-radius: 0 10px 10px 0;
|
| 64 |
-
margin: 1rem 0;
|
| 65 |
-
color: #276749;
|
| 66 |
-
}
|
| 67 |
</style>
|
| 68 |
""", unsafe_allow_html=True)
|
| 69 |
|
| 70 |
-
#
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
|
| 79 |
-
|
| 80 |
-
|
|
|
|
|
|
|
|
|
|
| 81 |
|
| 82 |
-
|
| 83 |
-
|
| 84 |
-
"Select Analysis Mode",
|
| 85 |
-
["π₯ Disease Risk (Pathology)", "π Drug Response (PGx)", "π§ͺ Custom Variant"],
|
| 86 |
-
index=0
|
| 87 |
-
)
|
| 88 |
|
| 89 |
-
|
| 90 |
-
|
| 91 |
-
|
|
|
|
|
|
|
|
|
|
| 92 |
|
| 93 |
-
#
|
| 94 |
-
|
| 95 |
-
|
| 96 |
-
|
| 97 |
-
|
| 98 |
-
"MMP9 (Wound Healing)": {"sym": "MMP9", "chr": "chr20", "start": 46006808, "end": 46023192, "pos": 46015000, "category": "disease"},
|
| 99 |
-
"HBB (Sickle Cell/Thalassemia)": {"sym": "HBB", "chr": "chr11", "start": 5218808, "end": 5235192, "pos": 5227000, "category": "disease"},
|
| 100 |
-
"BRCA1 (Breast Cancer)": {"sym": "BRCA1", "chr": "chr17", "start": 43054808, "end": 43071192, "pos": 43063000, "category": "disease"},
|
| 101 |
-
"LDLR (Hypercholesterolemia)": {"sym": "LDLR", "chr": "chr19", "start": 11104808, "end": 11121192, "pos": 11113000, "category": "disease"},
|
| 102 |
-
"CFTR (Cystic Fibrosis)": {"sym": "CFTR", "chr": "chr7", "start": 117472808, "end": 117489192, "pos": 117481000, "category": "disease"},
|
| 103 |
-
"DMD (Muscular Dystrophy)": {"sym": "DMD", "chr": "chrX", "start": 31119808, "end": 31136192, "pos": 31128000, "category": "disease"},
|
| 104 |
-
# PGx Genes
|
| 105 |
-
"CYP2C9 (Warfarin)": {"sym": "CYP2C9", "chr": "chr10", "start": 94981200, "end": 94997584, "pos": 94989392, "category": "pgx", "drug": "Warfarin"},
|
| 106 |
-
"CYP2C19 (Clopidogrel)": {"sym": "CYP2C19", "chr": "chr10", "start": 94775000, "end": 94791384, "pos": 94783192, "category": "pgx", "drug": "Clopidogrel"},
|
| 107 |
-
"CYP2D6 (Codeine/Tramadol)": {"sym": "CYP2D6", "chr": "chr22", "start": 42118000, "end": 42134384, "pos": 42126192, "category": "pgx", "drug": "Opioids"},
|
| 108 |
-
"SLCO1B1 (Simvastatin)": {"sym": "SLCO1B1", "chr": "chr12", "start": 21132000, "end": 21148384, "pos": 21140192, "category": "pgx", "drug": "Statins"},
|
| 109 |
-
"TPMT (6-Mercaptopurine)": {"sym": "TPMT", "chr": "chr6", "start": 18139000, "end": 18155384, "pos": 18147192, "category": "pgx", "drug": "Thiopurines"},
|
| 110 |
-
"DPYD (5-Fluorouracil)": {"sym": "DPYD", "chr": "chr1", "start": 97878000, "end": 97894384, "pos": 97886192, "category": "pgx", "drug": "Fluoropyrimidines"},
|
| 111 |
-
}
|
| 112 |
|
| 113 |
-
|
| 114 |
-
if "
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
filtered_genes = {k: v for k, v in GENE_LIBRARY.items() if v["category"] == "pgx"}
|
| 118 |
else:
|
| 119 |
-
|
| 120 |
-
|
| 121 |
-
gene_label = st.sidebar.selectbox("Select Gene", list(
|
| 122 |
-
|
| 123 |
-
gene_sym =
|
| 124 |
-
|
| 125 |
-
|
| 126 |
-
|
| 127 |
-
<
|
| 128 |
-
|
| 129 |
-
<strong>π Location:</strong> {gene_info['chr']}:{gene_info['start']:,}-{gene_info['end']:,}<br>
|
| 130 |
-
<strong>π Window:</strong> {(gene_info['end']-gene_info['start']):,} bp
|
| 131 |
-
</div>
|
| 132 |
-
""", unsafe_allow_html=True)
|
| 133 |
|
| 134 |
-
# Tissue Context Selector
|
| 135 |
st.sidebar.markdown("---")
|
| 136 |
st.sidebar.subheader("π« Tissue Context")
|
|
|
|
|
|
|
|
|
|
| 137 |
|
| 138 |
-
|
| 139 |
-
|
| 140 |
-
|
| 141 |
-
|
| 142 |
-
|
| 143 |
-
|
| 144 |
-
"
|
| 145 |
-
"
|
| 146 |
-
"
|
| 147 |
-
|
| 148 |
-
"
|
| 149 |
-
|
| 150 |
|
| 151 |
-
|
| 152 |
-
default_tissue = "Liver" if "PGx" in analysis_mode else "Blood (General)"
|
| 153 |
-
tissue_label = st.sidebar.selectbox("Select Tissue", list(TISSUE_OPTIONS.keys()),
|
| 154 |
-
index=list(TISSUE_OPTIONS.keys()).index(default_tissue))
|
| 155 |
-
ontology_term = TISSUE_OPTIONS[tissue_label]
|
| 156 |
|
| 157 |
-
# Output Modalities
|
| 158 |
st.sidebar.markdown("---")
|
| 159 |
-
st.sidebar.subheader("
|
|
|
|
| 160 |
|
| 161 |
-
|
| 162 |
-
|
| 163 |
-
|
| 164 |
-
|
| 165 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 166 |
|
| 167 |
-
|
| 168 |
-
|
| 169 |
-
|
| 170 |
-
|
| 171 |
-
|
| 172 |
-
|
| 173 |
-
|
| 174 |
-
|
| 175 |
-
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
|
| 180 |
-
|
| 181 |
-
|
| 182 |
-
|
| 183 |
-
|
| 184 |
-
|
| 185 |
-
|
| 186 |
-
|
| 187 |
-
alt_base = "C"
|
| 188 |
|
| 189 |
-
|
| 190 |
-
|
| 191 |
-
|
| 192 |
-
|
| 193 |
-
)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 194 |
|
| 195 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 196 |
st.markdown("---")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 197 |
|
| 198 |
-
|
| 199 |
-
|
| 200 |
-
|
| 201 |
-
|
| 202 |
-
st.error("β AlphaGenome library not installed. Run: `pip install alphagenome`")
|
| 203 |
-
st.stop()
|
| 204 |
-
|
| 205 |
-
if not api_key:
|
| 206 |
-
st.warning("β οΈ No API Key found in environment or secrets. Showing demonstration mode.")
|
| 207 |
-
|
| 208 |
-
# DEMO MODE with realistic mock data
|
| 209 |
-
col1, col2 = st.columns([1, 2])
|
| 210 |
-
|
| 211 |
-
with col1:
|
| 212 |
-
st.subheader("π Analysis Summary")
|
| 213 |
-
st.markdown(f"""
|
| 214 |
-
<div class="metric-card">
|
| 215 |
-
<strong>Gene:</strong> {gene_sym}<br>
|
| 216 |
-
<strong>Tissue:</strong> {tissue_label}<br>
|
| 217 |
-
<strong>Variant:</strong> {gene_info['chr']}:{variant_position} {ref_base}>{alt_base}
|
| 218 |
-
</div>
|
| 219 |
-
""", unsafe_allow_html=True)
|
| 220 |
-
|
| 221 |
-
# Clinical Implications
|
| 222 |
-
st.subheader("π©ββοΈ Clinical Implications")
|
| 223 |
-
|
| 224 |
-
if gene_info.get("category") == "pgx":
|
| 225 |
-
drug = gene_info.get("drug", "Unknown")
|
| 226 |
-
if mutation_intensity > 0.6:
|
| 227 |
-
st.markdown(f"""
|
| 228 |
-
<div class="alert-box">
|
| 229 |
-
<strong>β οΈ ADVERSE DRUG REACTION RISK</strong><br>
|
| 230 |
-
<strong>Drug:</strong> {drug}<br>
|
| 231 |
-
<strong>Phenotype:</strong> Poor Metabolizer<br>
|
| 232 |
-
<strong>Action:</strong> Consider dose reduction or alternative therapy
|
| 233 |
-
</div>
|
| 234 |
-
""", unsafe_allow_html=True)
|
| 235 |
else:
|
| 236 |
-
st.markdown(f""
|
| 237 |
-
<div class="success-box">
|
| 238 |
-
<strong>β
STANDARD DOSING</strong><br>
|
| 239 |
-
<strong>Drug:</strong> {drug}<br>
|
| 240 |
-
<strong>Phenotype:</strong> Normal Metabolizer<br>
|
| 241 |
-
<strong>Action:</strong> Standard protocol applies
|
| 242 |
-
</div>
|
| 243 |
-
""", unsafe_allow_html=True)
|
| 244 |
else:
|
| 245 |
-
|
| 246 |
-
|
| 247 |
-
|
| 248 |
-
|
| 249 |
-
"SCN9A": "Pain signaling. Changes cause **chronic pain** or **insensitivity**.",
|
| 250 |
-
"HBB": "Beta-Globin. Variants cause **Thalassemia** or **Sickle Cell**.",
|
| 251 |
-
"LDLR": "Cholesterol clearance. Low expression = **Hypercholesterolemia**.",
|
| 252 |
-
"CFTR": "Chloride channel. Variants cause **Cystic Fibrosis**.",
|
| 253 |
-
"DMD": "Muscle protein. Variants cause **Muscular Dystrophy**."
|
| 254 |
-
}
|
| 255 |
-
st.info(implications.get(gene_sym, "Regulatory variant detected."))
|
| 256 |
-
|
| 257 |
-
with col2:
|
| 258 |
-
st.subheader("π Predicted Tracks (Demo)")
|
| 259 |
-
|
| 260 |
-
# Generate mock tracks
|
| 261 |
-
x = np.linspace(0, 100, 500)
|
| 262 |
-
|
| 263 |
-
if "RNA Expression" in output_modalities:
|
| 264 |
-
fig, ax = plt.subplots(figsize=(10, 4))
|
| 265 |
-
ref_signal = np.exp(-((x - 50)**2) / 200) + np.random.normal(0, 0.02, len(x))
|
| 266 |
-
alt_signal = ref_signal * (1 - mutation_intensity * 0.6) + np.random.normal(0, 0.02, len(x))
|
| 267 |
-
|
| 268 |
-
ax.fill_between(x, ref_signal, alpha=0.4, color='#4CAF50', label='Reference')
|
| 269 |
-
ax.fill_between(x, alt_signal, alpha=0.4, color='#ff4b4b', label='Alternate')
|
| 270 |
-
ax.axvline(x=50, color='orange', linestyle='--', alpha=0.7, label='Variant')
|
| 271 |
-
ax.set_title(f'{gene_sym} RNA Expression')
|
| 272 |
-
ax.set_xlabel('Genomic Position (relative)')
|
| 273 |
-
ax.set_ylabel('Predicted Signal')
|
| 274 |
-
ax.legend()
|
| 275 |
-
ax.set_facecolor('white')
|
| 276 |
-
fig.patch.set_facecolor('white')
|
| 277 |
-
ax.spines['top'].set_visible(False)
|
| 278 |
-
ax.spines['right'].set_visible(False)
|
| 279 |
-
ax.grid(True, alpha=0.3)
|
| 280 |
-
st.pyplot(fig)
|
| 281 |
-
|
| 282 |
-
if "Splicing" in output_modalities:
|
| 283 |
-
fig2, ax2 = plt.subplots(figsize=(10, 3))
|
| 284 |
-
splice_ref = np.zeros_like(x)
|
| 285 |
-
splice_ref[150:160] = 0.9
|
| 286 |
-
splice_ref[350:360] = 0.85
|
| 287 |
-
splice_alt = splice_ref.copy()
|
| 288 |
-
splice_alt[150:160] *= (1 - mutation_intensity)
|
| 289 |
-
|
| 290 |
-
ax2.bar(x[150:160], splice_ref[150:160], width=0.5, alpha=0.6, color='#4CAF50', label='REF')
|
| 291 |
-
ax2.bar(x[150:160], splice_alt[150:160], width=0.3, alpha=0.8, color='#ff4b4b', label='ALT')
|
| 292 |
-
ax2.bar(x[350:360], splice_ref[350:360], width=0.5, alpha=0.6, color='#4CAF50')
|
| 293 |
-
ax2.bar(x[350:360], splice_alt[350:360], width=0.3, alpha=0.8, color='#ff4b4b')
|
| 294 |
-
ax2.set_title('Splice Site Usage')
|
| 295 |
-
ax2.set_facecolor('white')
|
| 296 |
-
fig2.patch.set_facecolor('white')
|
| 297 |
-
ax2.spines['top'].set_visible(False)
|
| 298 |
-
ax2.spines['right'].set_visible(False)
|
| 299 |
-
ax2.grid(True, alpha=0.3)
|
| 300 |
-
st.pyplot(fig2)
|
| 301 |
|
| 302 |
-
|
| 303 |
-
|
| 304 |
-
|
| 305 |
-
|
| 306 |
-
|
| 307 |
-
|
| 308 |
-
|
| 309 |
-
|
| 310 |
-
|
| 311 |
-
|
| 312 |
-
|
| 313 |
-
|
| 314 |
-
|
| 315 |
-
|
| 316 |
-
|
| 317 |
-
|
| 318 |
-
|
| 319 |
-
|
| 320 |
-
|
| 321 |
-
|
| 322 |
-
|
| 323 |
-
|
| 324 |
-
|
| 325 |
-
|
| 326 |
-
|
| 327 |
-
|
| 328 |
-
|
| 329 |
-
|
| 330 |
-
|
| 331 |
-
|
| 332 |
-
|
| 333 |
-
|
| 334 |
-
|
| 335 |
-
|
| 336 |
-
|
| 337 |
-
|
| 338 |
-
|
| 339 |
-
|
| 340 |
-
|
| 341 |
-
|
| 342 |
-
st.subheader("π©ββοΈ Clinical Guidance")
|
| 343 |
-
if gene_info.get("category") == "pgx":
|
| 344 |
-
drug = gene_info.get("drug", "Unknown")
|
| 345 |
-
st.warning(f"**PGx Alert**: This gene affects {drug} metabolism.")
|
| 346 |
-
else:
|
| 347 |
-
st.info("Regulatory variant analysis complete. Review tracks for impact.")
|
| 348 |
-
|
| 349 |
-
with col2:
|
| 350 |
-
st.subheader(f"π AlphaGenome Predictions ({tissue_label})")
|
| 351 |
-
|
| 352 |
-
# RNA Expression Track
|
| 353 |
-
if hasattr(outputs.reference, 'rna_seq'):
|
| 354 |
-
fig = plot_components.plot(
|
| 355 |
-
[
|
| 356 |
-
plot_components.OverlaidTracks(
|
| 357 |
-
tdata={
|
| 358 |
-
'REF': outputs.reference.rna_seq,
|
| 359 |
-
'ALT': outputs.alternate.rna_seq,
|
| 360 |
-
},
|
| 361 |
-
colors={'REF': 'dimgrey', 'ALT': '#ff4b4b'},
|
| 362 |
-
),
|
| 363 |
-
],
|
| 364 |
-
interval=outputs.reference.rna_seq.interval.resize(2**14),
|
| 365 |
-
annotations=[plot_components.VariantAnnotation([variant], alpha=0.8)],
|
| 366 |
-
)
|
| 367 |
-
st.pyplot(fig)
|
| 368 |
-
|
| 369 |
-
# Splicing Track
|
| 370 |
-
if hasattr(outputs.reference, 'splice_site'):
|
| 371 |
-
fig2 = plot_components.plot(
|
| 372 |
-
[
|
| 373 |
-
plot_components.OverlaidTracks(
|
| 374 |
-
tdata={
|
| 375 |
-
'REF': outputs.reference.splice_site,
|
| 376 |
-
'ALT': outputs.alternate.splice_site,
|
| 377 |
-
},
|
| 378 |
-
colors={'REF': 'dimgrey', 'ALT': '#ff4b4b'},
|
| 379 |
-
),
|
| 380 |
-
],
|
| 381 |
-
interval=outputs.reference.splice_site.interval.resize(2**14),
|
| 382 |
-
annotations=[plot_components.VariantAnnotation([variant], alpha=0.8)],
|
| 383 |
-
)
|
| 384 |
-
st.pyplot(fig2)
|
| 385 |
-
|
| 386 |
-
except Exception as e:
|
| 387 |
-
st.error(f"API Error: {str(e)}")
|
| 388 |
-
st.info("Please check your API key and try again.")
|
| 389 |
-
|
| 390 |
-
# Footer
|
| 391 |
-
st.markdown("---")
|
| 392 |
-
st.markdown("""
|
| 393 |
-
<div style="text-align: center; color: #718096; font-size: 0.9rem;">
|
| 394 |
-
<p><strong>Virtual Gene Scope v2.0</strong> | Powered by <strong>Google DeepMind AlphaGenome</strong></p>
|
| 395 |
-
<p>π <a href="https://www.nature.com/articles/s41586-025-10014-0" target="_blank" style="color: #667eea;">Nature Paper</a> |
|
| 396 |
-
π <a href="https://github.com/google-deepmind/alphagenome" target="_blank" style="color: #667eea;">AlphaGenome GitHub</a> |
|
| 397 |
-
π Part of the <strong>Nursing Genomics Education Toolkit</strong></p>
|
| 398 |
-
</div>
|
| 399 |
-
""", unsafe_allow_html=True)
|
| 400 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""
|
| 2 |
+
Virtual Gene Scope v2.0
|
| 3 |
+
=======================
|
| 4 |
+
Educational genomics tool for nursing students and healthcare professionals.
|
| 5 |
+
Powered by Google DeepMind's AlphaGenome.
|
| 6 |
+
|
| 7 |
+
Part of the CQAI Nursing Education Toolkit.
|
| 8 |
+
Built by Clinical Quality Artificial Intelligence β Nurse Citizen Developers.
|
| 9 |
+
"""
|
| 10 |
+
|
| 11 |
+
import io
|
| 12 |
import os
|
| 13 |
|
| 14 |
+
import matplotlib.pyplot as plt
|
| 15 |
+
import numpy as np
|
| 16 |
+
import pandas as pd
|
| 17 |
+
import streamlit as st
|
| 18 |
+
|
| 19 |
+
try:
|
| 20 |
+
from docx import Document
|
| 21 |
+
from docx.shared import RGBColor
|
| 22 |
+
HAS_DOCX = True
|
| 23 |
+
except ImportError:
|
| 24 |
+
HAS_DOCX = False
|
| 25 |
+
|
| 26 |
try:
|
| 27 |
from alphagenome.models import dna_client
|
| 28 |
from alphagenome.data import genome
|
|
|
|
| 31 |
except ImportError:
|
| 32 |
HAS_ALPHAGENOME = False
|
| 33 |
|
| 34 |
+
# ---------------------------------------------------------------------------
|
| 35 |
+
st.set_page_config(page_title="Virtual Gene Scope v2.0", page_icon="π§¬", layout="wide")
|
|
|
|
|
|
|
|
|
|
|
|
|
| 36 |
|
|
|
|
| 37 |
st.markdown("""
|
| 38 |
<style>
|
| 39 |
+
.stApp{background:#f8f9fa}
|
| 40 |
+
.main-header{color:#2c3e50;font-size:2.3rem;font-weight:700;text-align:center}
|
| 41 |
+
.metric-card{background:#fff;border-radius:12px;padding:1.2rem;border:1px solid #e0e0e0;box-shadow:0 2px 8px rgba(0,0,0,.06);margin:.4rem 0}
|
| 42 |
+
.gene-badge{background:linear-gradient(135deg,#667eea,#764ba2);color:#fff;padding:4px 14px;border-radius:20px;font-weight:700;display:inline-block}
|
| 43 |
+
.alert-box{background:#fff5f5;border-left:4px solid #e53e3e;padding:1rem;border-radius:0 10px 10px 0;margin:.8rem 0;color:#c53030}
|
| 44 |
+
.success-box{background:#f0fff4;border-left:4px solid #38a169;padding:1rem;border-radius:0 10px 10px 0;margin:.8rem 0;color:#276749}
|
| 45 |
+
.info-card{background:#ebf8ff;border-left:4px solid #3182ce;padding:1rem;border-radius:0 10px 10px 0;margin:.8rem 0;color:#2c5282}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
</style>
|
| 47 |
""", unsafe_allow_html=True)
|
| 48 |
|
| 49 |
+
# ---------------------------------------------------------------------------
|
| 50 |
+
# Gene Library β 16 genes (8 disease + 8 PGx)
|
| 51 |
+
# ---------------------------------------------------------------------------
|
| 52 |
+
GENE_LIBRARY = {
|
| 53 |
+
"INS (Diabetes β Insulin)": {
|
| 54 |
+
"sym":"INS","chr":"chr11","start":2151808,"end":2168192,"pos":2160000,
|
| 55 |
+
"category":"disease","omim":"176730","key_snp":"rs5219",
|
| 56 |
+
"inheritance":"Complex / AD (MODY10)","tissue_default":"Pancreas",
|
| 57 |
+
"condition":"Type 1 & Type 2 Diabetes, Neonatal Diabetes",
|
| 58 |
+
"clinvar":"https://www.ncbi.nlm.nih.gov/clinvar/?term=INS",
|
| 59 |
+
"nursing_note":"Variants in INS reduce or abolish insulin secretion. Monitor BM, HbA1c, and signs of DKA. Patients may need insulin therapy from birth (neonatal DM). Educate on hypoglycaemia recognition and sick-day rules.",
|
| 60 |
+
"nmc_platforms":["3 β Assessing needs and planning care","4 β Providing and evaluating care"],
|
| 61 |
+
"nice_link":"https://www.nice.org.uk/guidance/ng17","nice_label":"NICE NG17 (Type 1 Diabetes)",
|
| 62 |
+
},
|
| 63 |
+
"SCN9A (Pain Sensitivity)": {
|
| 64 |
+
"sym":"SCN9A","chr":"chr2","start":166191808,"end":166208192,"pos":166200000,
|
| 65 |
+
"category":"disease","omim":"603415","key_snp":"rs6746030",
|
| 66 |
+
"inheritance":"AD / AR","tissue_default":"Brain",
|
| 67 |
+
"condition":"Chronic pain syndromes, Congenital Insensitivity to Pain",
|
| 68 |
+
"clinvar":"https://www.ncbi.nlm.nih.gov/clinvar/?term=SCN9A",
|
| 69 |
+
"nursing_note":"Gain-of-function variants cause severe chronic pain (erythromelalgia). Loss-of-function causes insensitivity to pain β patients cannot feel injury. Assess pain carefully; standard pain scales may be unreliable.",
|
| 70 |
+
"nmc_platforms":["3 β Assessing needs and planning care","6 β Improving safety and quality"],
|
| 71 |
+
"nice_link":"https://www.nice.org.uk/guidance/ng193","nice_label":"NICE NG193 (Chronic Pain)",
|
| 72 |
+
},
|
| 73 |
+
"MMP9 (Wound Healing)": {
|
| 74 |
+
"sym":"MMP9","chr":"chr20","start":46006808,"end":46023192,"pos":46015000,
|
| 75 |
+
"category":"disease","omim":"120361","key_snp":"rs3918242",
|
| 76 |
+
"inheritance":"Complex","tissue_default":"Skin",
|
| 77 |
+
"condition":"Chronic wound risk, diabetic ulcers, keloid scarring",
|
| 78 |
+
"clinvar":"https://www.ncbi.nlm.nih.gov/clinvar/?term=MMP9",
|
| 79 |
+
"nursing_note":"MMP9 regulates extracellular matrix remodelling. Over-expression impairs wound healing. Assess using TIME/TIMPE framework. Refer to TVN for wounds not healing within 4 weeks. Apply SSKIN bundle for pressure injury prevention.",
|
| 80 |
+
"nmc_platforms":["4 β Providing and evaluating care","6 β Improving safety and quality"],
|
| 81 |
+
"nice_link":"https://www.nice.org.uk/guidance/cg179","nice_label":"NICE CG179 (Pressure Ulcers)",
|
| 82 |
+
},
|
| 83 |
+
"HBB (Sickle Cell / Thalassaemia)": {
|
| 84 |
+
"sym":"HBB","chr":"chr11","start":5218808,"end":5235192,"pos":5227000,
|
| 85 |
+
"category":"disease","omim":"141900","key_snp":"rs334",
|
| 86 |
+
"inheritance":"AR","tissue_default":"Blood (General)",
|
| 87 |
+
"condition":"Sickle Cell Disease, Ξ²-Thalassaemia",
|
| 88 |
+
"clinvar":"https://www.ncbi.nlm.nih.gov/clinvar/?term=HBB",
|
| 89 |
+
"nursing_note":"HBB c.20A>T (rs334) causes the GluβVal substitution in sickle cell disease. Monitor for vaso-occlusive crises, acute chest syndrome, and stroke. High pain, Oβ therapy, IV fluids, and hydroxyurea are pillars of care. NHS Newborn Blood Spot Screening detects this.",
|
| 90 |
+
"nmc_platforms":["3 β Assessing needs and planning care","4 β Providing and evaluating care"],
|
| 91 |
+
"nice_link":"https://www.nice.org.uk/guidance/ng143","nice_label":"NICE NG143 (Sickle Cell)",
|
| 92 |
+
},
|
| 93 |
+
"BRCA1 (Breast / Ovarian Cancer)": {
|
| 94 |
+
"sym":"BRCA1","chr":"chr17","start":43054808,"end":43071192,"pos":43063000,
|
| 95 |
+
"category":"disease","omim":"113705","key_snp":"rs28897672",
|
| 96 |
+
"inheritance":"AD","tissue_default":"Breast",
|
| 97 |
+
"condition":"Hereditary Breast and Ovarian Cancer Syndrome",
|
| 98 |
+
"clinvar":"https://www.ncbi.nlm.nih.gov/clinvar/?term=BRCA1",
|
| 99 |
+
"nursing_note":"BRCA1 pathogenic variants confer ~70% lifetime breast cancer risk. Refer to Clinical Genetics. Discuss prophylactic options sensitively. Support emotional wellbeing β diagnosis affects the whole family. Signpost to Breast Cancer Now and FORCE charity.",
|
| 100 |
+
"nmc_platforms":["2 β Promoting health and preventing ill health","3 β Assessing needs"],
|
| 101 |
+
"nice_link":"https://www.nice.org.uk/guidance/dg27","nice_label":"NICE DG27 (BRCA Testing)",
|
| 102 |
+
},
|
| 103 |
+
"LDLR (Familial Hypercholesterolaemia)": {
|
| 104 |
+
"sym":"LDLR","chr":"chr19","start":11104808,"end":11121192,"pos":11113000,
|
| 105 |
+
"category":"disease","omim":"606945","key_snp":"rs28942080",
|
| 106 |
+
"inheritance":"AD","tissue_default":"Liver",
|
| 107 |
+
"condition":"Familial Hypercholesterolaemia (FH)",
|
| 108 |
+
"clinvar":"https://www.ncbi.nlm.nih.gov/clinvar/?term=LDLR",
|
| 109 |
+
"nursing_note":"FH affects 1 in 250 people in the UK. LDLR variants impair LDL clearance causing premature atherosclerosis. Monitor lipid profile, statins are first-line. Cascade screening of family members is essential.",
|
| 110 |
+
"nmc_platforms":["2 β Promoting health and preventing ill health","4 β Providing care"],
|
| 111 |
+
"nice_link":"https://www.nice.org.uk/guidance/cg71","nice_label":"NICE CG71 (FH)",
|
| 112 |
+
},
|
| 113 |
+
"CFTR (Cystic Fibrosis)": {
|
| 114 |
+
"sym":"CFTR","chr":"chr7","start":117472808,"end":117489192,"pos":117481000,
|
| 115 |
+
"category":"disease","omim":"602421","key_snp":"rs113993960",
|
| 116 |
+
"inheritance":"AR","tissue_default":"Lung",
|
| 117 |
+
"condition":"Cystic Fibrosis",
|
| 118 |
+
"clinvar":"https://www.ncbi.nlm.nih.gov/clinvar/?term=CFTR",
|
| 119 |
+
"nursing_note":"CFTR F508del is the most common CF variant. Impaired chloride transport causes thick mucus in lungs, pancreas, and intestine. Daily physiotherapy, enzyme replacement, and CFTR modulators (e.g. Kaftrio) are transforming outcomes. NHS newborn screening via IRT/DNA test.",
|
| 120 |
+
"nmc_platforms":["3 β Assessing needs","4 β Providing and evaluating care"],
|
| 121 |
+
"nice_link":"https://www.nice.org.uk/guidance/ta398","nice_label":"NICE TA398 (Lumacaftor/Ivacaftor)",
|
| 122 |
+
},
|
| 123 |
+
"DMD (Muscular Dystrophy)": {
|
| 124 |
+
"sym":"DMD","chr":"chrX","start":31119808,"end":31136192,"pos":31128000,
|
| 125 |
+
"category":"disease","omim":"300377","key_snp":"rs137852596",
|
| 126 |
+
"inheritance":"XL recessive","tissue_default":"Muscle",
|
| 127 |
+
"condition":"Duchenne / Becker Muscular Dystrophy",
|
| 128 |
+
"clinvar":"https://www.ncbi.nlm.nih.gov/clinvar/?term=DMD",
|
| 129 |
+
"nursing_note":"DMD deletion/duplication of exons causes out-of-frame transcripts. Progressive muscle weakness; most boys need wheelchair by teen years. Monitor respiratory function (FVC), cardiac function (cardiomyopathy), and swallowing. Corticosteroids slow progression.",
|
| 130 |
+
"nmc_platforms":["3 β Assessing needs","7 β Coordinating care"],
|
| 131 |
+
"nice_link":"https://www.nice.org.uk/guidance/ng238","nice_label":"NICE NG238 (Duchenne MD)",
|
| 132 |
+
},
|
| 133 |
+
# PGx
|
| 134 |
+
"CYP2C9 (Warfarin metabolism)": {
|
| 135 |
+
"sym":"CYP2C9","chr":"chr10","start":94981200,"end":94997584,"pos":94989392,
|
| 136 |
+
"category":"pgx","drug":"Warfarin","omim":"601130",
|
| 137 |
+
"key_snp":"rs1799853 (*2), rs1057910 (*3)","inheritance":"Pharmacogenomic",
|
| 138 |
+
"tissue_default":"Liver","condition":"Altered Warfarin metabolism β bleeding or clotting risk",
|
| 139 |
+
"clinvar":"https://www.ncbi.nlm.nih.gov/clinvar/?term=CYP2C9",
|
| 140 |
+
"pharmgkb":"https://www.pharmgkb.org/gene/PA126",
|
| 141 |
+
"nursing_note":"Poor metabolisers (*2/*2, *3/*3) need lower Warfarin doses β over-anticoagulation risk. Monitor INR closely when initiating therapy. Check CYP2C9 genotype before prescribing. MHRA guidance recommends dose adjustment based on genotype.",
|
| 142 |
+
"nmc_platforms":["4 β Providing and evaluating care","6 β Improving safety"],
|
| 143 |
+
"nice_link":"https://www.nice.org.uk/guidance/ng196","nice_label":"NICE NG196 (Anticoagulation)",
|
| 144 |
+
},
|
| 145 |
+
"CYP2C19 (Clopidogrel / PPIs)": {
|
| 146 |
+
"sym":"CYP2C19","chr":"chr10","start":94775000,"end":94791384,"pos":94783192,
|
| 147 |
+
"category":"pgx","drug":"Clopidogrel / PPIs","omim":"124020",
|
| 148 |
+
"key_snp":"rs4244285 (*2), rs12248560 (*17)","inheritance":"Pharmacogenomic",
|
| 149 |
+
"tissue_default":"Liver","condition":"Clopidogrel non-response; altered PPI metabolism",
|
| 150 |
+
"clinvar":"https://www.ncbi.nlm.nih.gov/clinvar/?term=CYP2C19",
|
| 151 |
+
"pharmgkb":"https://www.pharmgkb.org/gene/PA124",
|
| 152 |
+
"nursing_note":"Poor metabolisers (*2/*2) cannot activate Clopidogrel β higher risk of MI/stroke post-PCI. Ultra-rapid metabolisers (*17) may need reduced PPI doses. Alert prescriber before dual antiplatelet therapy.",
|
| 153 |
+
"nmc_platforms":["4 β Providing and evaluating care","6 β Improving safety"],
|
| 154 |
+
"nice_link":"https://www.nice.org.uk/guidance/cg94","nice_label":"NICE CG94 (ACS)",
|
| 155 |
+
},
|
| 156 |
+
"CYP2D6 (Codeine / Opioids)": {
|
| 157 |
+
"sym":"CYP2D6","chr":"chr22","start":42118000,"end":42134384,"pos":42126192,
|
| 158 |
+
"category":"pgx","drug":"Codeine / Tramadol / Opioids","omim":"124030",
|
| 159 |
+
"key_snp":"rs3892097 (*4), rs16947 (*2)","inheritance":"Pharmacogenomic",
|
| 160 |
+
"tissue_default":"Liver","condition":"Opioid toxicity (ultra-rapid) or no analgesia (poor metaboliser)",
|
| 161 |
+
"clinvar":"https://www.ncbi.nlm.nih.gov/clinvar/?term=CYP2D6",
|
| 162 |
+
"pharmgkb":"https://www.pharmgkb.org/gene/PA128",
|
| 163 |
+
"nursing_note":"Ultra-rapid metabolisers convert Codeine to Morphine very rapidly β risk of fatal respiratory depression, especially in children. MHRA contraindicated Codeine in breastfeeding mothers (UMs). Poor metabolisers get no pain relief from Codeine. Use alternative opioids.",
|
| 164 |
+
"nmc_platforms":["4 β Providing and evaluating care","6 β Improving safety"],
|
| 165 |
+
"nice_link":"https://www.nice.org.uk/guidance/ng177","nice_label":"NICE NG177 (Chronic Pain β Opioids)",
|
| 166 |
+
},
|
| 167 |
+
"SLCO1B1 (Statin β Myopathy)": {
|
| 168 |
+
"sym":"SLCO1B1","chr":"chr12","start":21132000,"end":21148384,"pos":21140192,
|
| 169 |
+
"category":"pgx","drug":"Simvastatin / Statins","omim":"604843",
|
| 170 |
+
"key_snp":"rs4149056 (*5)","inheritance":"Pharmacogenomic",
|
| 171 |
+
"tissue_default":"Liver","condition":"Statin-induced myopathy / rhabdomyolysis",
|
| 172 |
+
"clinvar":"https://www.ncbi.nlm.nih.gov/clinvar/?term=SLCO1B1",
|
| 173 |
+
"pharmgkb":"https://www.pharmgkb.org/gene/PA134865839",
|
| 174 |
+
"nursing_note":"SLCO1B1*5 (rs4149056 C allele) reduces hepatic uptake of statins, raising plasma levels and myopathy risk. Check CK if patient reports muscle pain/weakness on statins. Consider dose reduction or switch to Rosuvastatin (less affected by SLCO1B1).",
|
| 175 |
+
"nmc_platforms":["4 β Providing and evaluating care","6 β Improving safety"],
|
| 176 |
+
"nice_link":"https://www.nice.org.uk/guidance/cg181","nice_label":"NICE CG181 (Cardiovascular Risk)",
|
| 177 |
+
},
|
| 178 |
+
"TPMT (Azathioprine / 6-MP)": {
|
| 179 |
+
"sym":"TPMT","chr":"chr6","start":18139000,"end":18155384,"pos":18147192,
|
| 180 |
+
"category":"pgx","drug":"6-Mercaptopurine / Azathioprine","omim":"187680",
|
| 181 |
+
"key_snp":"rs1800462 (*2), rs1800460 (*3B)","inheritance":"Pharmacogenomic",
|
| 182 |
+
"tissue_default":"Blood (General)","condition":"Thiopurine toxicity β bone marrow suppression",
|
| 183 |
+
"clinvar":"https://www.ncbi.nlm.nih.gov/clinvar/?term=TPMT",
|
| 184 |
+
"pharmgkb":"https://www.pharmgkb.org/gene/PA356",
|
| 185 |
+
"nursing_note":"Poor metabolisers (TPMT *3A/*3A) accumulate thioguanine nucleotides β severe myelosuppression. NICE mandates TPMT testing before azathioprine in IBD. Monitor FBC closely. Teach patients to report bruising/bleeding/fever.",
|
| 186 |
+
"nmc_platforms":["4 β Providing and evaluating care","6 β Improving safety"],
|
| 187 |
+
"nice_link":"https://www.nice.org.uk/guidance/ng129","nice_label":"NICE NG129 (IBD)",
|
| 188 |
+
},
|
| 189 |
+
"DPYD (5-Fluorouracil / Capecitabine)": {
|
| 190 |
+
"sym":"DPYD","chr":"chr1","start":97878000,"end":97894384,"pos":97886192,
|
| 191 |
+
"category":"pgx","drug":"5-Fluorouracil / Capecitabine","omim":"612779",
|
| 192 |
+
"key_snp":"rs3918290 (*2A), rs55886062 (*13)","inheritance":"Pharmacogenomic",
|
| 193 |
+
"tissue_default":"Liver","condition":"Fluoropyrimidine toxicity β mucositis, neutropenia, death",
|
| 194 |
+
"clinvar":"https://www.ncbi.nlm.nih.gov/clinvar/?term=DPYD",
|
| 195 |
+
"pharmgkb":"https://www.pharmgkb.org/gene/PA145",
|
| 196 |
+
"nursing_note":"NHS England mandates DPYD testing before 5-FU/Capecitabine. Poor metabolisers (1β3% population) accumulate toxic metabolites. Presentation: severe mucositis, diarrhoea, hand-foot syndrome. Stop treatment immediately if toxicity suspected; escalate urgently.",
|
| 197 |
+
"nmc_platforms":["4 β Providing and evaluating care","6 β Improving safety"],
|
| 198 |
+
"nice_link":"https://www.england.nhs.uk/publication/dpyd-genotyping/","nice_label":"NHS England DPYD Genotyping Mandate",
|
| 199 |
+
},
|
| 200 |
+
"VKORC1 (Warfarin sensitivity)": {
|
| 201 |
+
"sym":"VKORC1","chr":"chr16","start":31093000,"end":31109384,"pos":31101192,
|
| 202 |
+
"category":"pgx","drug":"Warfarin","omim":"608547",
|
| 203 |
+
"key_snp":"rs9923231 (-1639G>A)","inheritance":"Pharmacogenomic",
|
| 204 |
+
"tissue_default":"Liver","condition":"Increased Warfarin sensitivity β bleeding risk",
|
| 205 |
+
"clinvar":"https://www.ncbi.nlm.nih.gov/clinvar/?term=VKORC1",
|
| 206 |
+
"pharmgkb":"https://www.pharmgkb.org/gene/PA133787052",
|
| 207 |
+
"nursing_note":"VKORC1 -1639A allele reduces VKORC1 expression β increased Warfarin sensitivity. Patients need lower doses to achieve target INR. Works in combination with CYP2C9 genotype for dose prediction. Monitor INR more frequently in first weeks of therapy.",
|
| 208 |
+
"nmc_platforms":["4 β Providing and evaluating care","6 β Improving safety"],
|
| 209 |
+
"nice_link":"https://www.nice.org.uk/guidance/ng196","nice_label":"NICE NG196 (Anticoagulation)",
|
| 210 |
+
},
|
| 211 |
+
"HLA-B (Abacavir / Carbamazepine)": {
|
| 212 |
+
"sym":"HLA-B","chr":"chr6","start":31353000,"end":31369384,"pos":31361192,
|
| 213 |
+
"category":"pgx","drug":"Abacavir / Carbamazepine","omim":"142830",
|
| 214 |
+
"key_snp":"HLA-B*57:01 (Abacavir), HLA-B*15:02 (Carbamazepine)","inheritance":"Pharmacogenomic / Immunogenetic",
|
| 215 |
+
"tissue_default":"Blood (General)","condition":"Severe hypersensitivity β Stevens-Johnson syndrome risk",
|
| 216 |
+
"clinvar":"https://www.ncbi.nlm.nih.gov/clinvar/?term=HLA-B",
|
| 217 |
+
"pharmgkb":"https://www.pharmgkb.org/gene/PA35056",
|
| 218 |
+
"nursing_note":"HLA-B*57:01 β Abacavir hypersensitivity (fever, rash, GI β potentially fatal on re-challenge). NICE mandates HLA-B*57:01 screening before Abacavir. HLA-B*15:02 β Stevens-Johnson/TEN risk with Carbamazepine (mainly South/Southeast Asian populations).",
|
| 219 |
+
"nmc_platforms":["4 β Providing and evaluating care","6 β Improving safety"],
|
| 220 |
+
"nice_link":"https://www.nice.org.uk/guidance/ta91","nice_label":"NICE TA91 (Abacavir)",
|
| 221 |
+
},
|
| 222 |
+
}
|
| 223 |
|
| 224 |
+
TISSUE_OPTIONS = {
|
| 225 |
+
"Blood (General)":"UBERON:0000178","Liver":"UBERON:0002107","Skin":"UBERON:0002097",
|
| 226 |
+
"Breast":"UBERON:0000310","Brain":"UBERON:0000955","Lung":"UBERON:0002048",
|
| 227 |
+
"Heart":"UBERON:0000948","Kidney":"UBERON:0002113","Pancreas":"UBERON:0001264","Muscle":"UBERON:0002385",
|
| 228 |
+
}
|
| 229 |
|
| 230 |
+
if "history" not in st.session_state:
|
| 231 |
+
st.session_state.history = []
|
|
|
|
|
|
|
|
|
|
|
|
|
| 232 |
|
| 233 |
+
# ---------------------------------------------------------------------------
|
| 234 |
+
# Header
|
| 235 |
+
# ---------------------------------------------------------------------------
|
| 236 |
+
st.markdown('<h1 class="main-header">𧬠Virtual Gene Scope v2.0</h1>', unsafe_allow_html=True)
|
| 237 |
+
st.markdown("<p style='text-align:center;color:#4a5568;font-size:1.05rem;'>Explore the Regulatory Genome with Google DeepMind's AlphaGenome<br><em>Expression Β· Splicing Β· Chromatin Β· Contact Maps</em></p>", unsafe_allow_html=True)
|
| 238 |
+
st.warning("βοΈ **Clinical Disclaimer:** For **educational purposes only**. Does not constitute clinical advice. Always verify with ClinVar, PharmGKB, NICE guidelines, and a qualified healthcare professional.")
|
| 239 |
|
| 240 |
+
# ---------------------------------------------------------------------------
|
| 241 |
+
# Sidebar
|
| 242 |
+
# ---------------------------------------------------------------------------
|
| 243 |
+
st.sidebar.header("π¬ Analysis Settings")
|
| 244 |
+
mode = st.sidebar.radio("Analysis Mode", ["π₯ Disease Risk", "π Drug Response (PGx)", "π§ͺ Custom Variant"])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 245 |
|
| 246 |
+
if "Disease" in mode:
|
| 247 |
+
filtered = {k: v for k, v in GENE_LIBRARY.items() if v["category"] == "disease"}
|
| 248 |
+
elif "PGx" in mode:
|
| 249 |
+
filtered = {k: v for k, v in GENE_LIBRARY.items() if v["category"] == "pgx"}
|
|
|
|
| 250 |
else:
|
| 251 |
+
filtered = GENE_LIBRARY
|
| 252 |
+
|
| 253 |
+
gene_label = st.sidebar.selectbox("Select Gene", list(filtered.keys()))
|
| 254 |
+
gi = filtered[gene_label]
|
| 255 |
+
gene_sym = gi["sym"]
|
| 256 |
+
|
| 257 |
+
st.sidebar.markdown(f"""<div class="metric-card"><span class="gene-badge">{gene_sym}</span><br><br>
|
| 258 |
+
<strong>π</strong> {gi['chr']}:{gi['start']:,}β{gi['end']:,}<br>
|
| 259 |
+
<strong>𧬠Key SNP:</strong> {gi.get('key_snp','N/A')}<br>
|
| 260 |
+
<strong>π Inheritance:</strong> {gi.get('inheritance','N/A')}</div>""", unsafe_allow_html=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 261 |
|
|
|
|
| 262 |
st.sidebar.markdown("---")
|
| 263 |
st.sidebar.subheader("π« Tissue Context")
|
| 264 |
+
default_t = gi.get("tissue_default", "Blood (General)")
|
| 265 |
+
tissue = st.sidebar.selectbox("Tissue", list(TISSUE_OPTIONS.keys()), index=list(TISSUE_OPTIONS.keys()).index(default_t))
|
| 266 |
+
ont = TISSUE_OPTIONS[tissue]
|
| 267 |
|
| 268 |
+
st.sidebar.markdown("---")
|
| 269 |
+
st.sidebar.subheader("π Modalities")
|
| 270 |
+
modalities = st.sidebar.multiselect("Tracks", ["RNA Expression","Splicing","Chromatin Accessibility","Contact Map"], default=["RNA Expression","Splicing"])
|
| 271 |
+
|
| 272 |
+
vpos = gi["pos"]; ref_b, alt_b = "A", "C"
|
| 273 |
+
if "Custom" in mode:
|
| 274 |
+
st.sidebar.markdown("---")
|
| 275 |
+
st.sidebar.subheader("𧬠Variant Input")
|
| 276 |
+
vpos = st.sidebar.number_input("Position", min_value=gi["start"], max_value=gi["end"], value=gi["pos"])
|
| 277 |
+
c1, c2 = st.sidebar.columns(2)
|
| 278 |
+
ref_b = c1.selectbox("REF", ["A","T","G","C"])
|
| 279 |
+
alt_b = c2.selectbox("ALT", ["A","T","G","C"], index=2)
|
| 280 |
|
| 281 |
+
intensity = st.sidebar.slider("Mutation Impact (demo)", 0.0, 1.0, 0.5)
|
|
|
|
|
|
|
|
|
|
|
|
|
| 282 |
|
|
|
|
| 283 |
st.sidebar.markdown("---")
|
| 284 |
+
st.sidebar.subheader("π AlphaGenome API")
|
| 285 |
+
api_key = os.environ.get("ALPHAGENOME_API_KEY") or st.sidebar.text_input("API Key (optional)", type="password", help="Leave blank for demo mode.")
|
| 286 |
|
| 287 |
+
# ---------------------------------------------------------------------------
|
| 288 |
+
# Demo chart helpers
|
| 289 |
+
# ---------------------------------------------------------------------------
|
| 290 |
+
def _rna(sym, inten):
|
| 291 |
+
x = np.linspace(0,100,500); rng=np.random.default_rng(42)
|
| 292 |
+
ref = np.exp(-((x-50)**2)/200)+rng.normal(0,.02,500)
|
| 293 |
+
alt = ref*(1-inten*.65)+np.random.default_rng(7).normal(0,.02,500)
|
| 294 |
+
fig,ax = plt.subplots(figsize=(10,3))
|
| 295 |
+
ax.fill_between(x,ref,alpha=.45,color="#4CAF50",label="Reference")
|
| 296 |
+
ax.fill_between(x,alt,alpha=.45,color="#ff4b4b",label="Alternate")
|
| 297 |
+
ax.axvline(50,color="orange",linestyle="--",alpha=.7,label="Variant site")
|
| 298 |
+
ax.set_title(f"{sym} β RNA Expression (demo)",fontweight="bold"); ax.legend(fontsize=9)
|
| 299 |
+
for s in ["top","right"]: ax.spines[s].set_visible(False)
|
| 300 |
+
ax.grid(True,alpha=.25); ax.set_facecolor("white"); fig.patch.set_facecolor("white"); fig.tight_layout()
|
| 301 |
+
return fig
|
| 302 |
|
| 303 |
+
def _splice(sym, inten):
|
| 304 |
+
x = np.linspace(0,100,500); fig,ax = plt.subplots(figsize=(10,3))
|
| 305 |
+
for p in [150,350]:
|
| 306 |
+
ax.bar(x[p:p+10],[.9]*10,width=.5,alpha=.55,color="#4CAF50",label="REF" if p==150 else "")
|
| 307 |
+
ax.bar(x[p:p+10],[.9*(1-inten)]*10,width=.3,alpha=.8,color="#ff4b4b",label="ALT" if p==150 else "")
|
| 308 |
+
ax.set_title(f"{sym} β Splice Site Usage (demo)",fontweight="bold"); ax.legend(fontsize=9)
|
| 309 |
+
for s in ["top","right"]: ax.spines[s].set_visible(False)
|
| 310 |
+
ax.grid(True,alpha=.25); ax.set_facecolor("white"); fig.patch.set_facecolor("white"); fig.tight_layout()
|
| 311 |
+
return fig
|
| 312 |
+
|
| 313 |
+
def _chromatin(sym, inten):
|
| 314 |
+
x = np.linspace(0,100,500); rng=np.random.default_rng(99)
|
| 315 |
+
ref = np.abs(rng.normal(0,.3,500)); ref[200:220]=1.4; ref[280:300]=1.1
|
| 316 |
+
alt = ref*(1-inten*.4)
|
| 317 |
+
fig,ax = plt.subplots(figsize=(10,3))
|
| 318 |
+
ax.fill_between(x,ref,alpha=.45,color="#805ad5",label="REF"); ax.fill_between(x,alt,alpha=.45,color="#dd6b20",label="ALT")
|
| 319 |
+
ax.set_title(f"{sym} β Chromatin Accessibility (demo)",fontweight="bold"); ax.legend(fontsize=9)
|
| 320 |
+
for s in ["top","right"]: ax.spines[s].set_visible(False)
|
| 321 |
+
ax.grid(True,alpha=.25); ax.set_facecolor("white"); fig.patch.set_facecolor("white"); fig.tight_layout()
|
| 322 |
+
return fig
|
|
|
|
| 323 |
|
| 324 |
+
def _contact(sym, inten):
|
| 325 |
+
rng=np.random.default_rng(13); n=40; base=np.zeros((n,n))
|
| 326 |
+
for i in range(n):
|
| 327 |
+
for j in range(n): base[i,j]=np.exp(-abs(i-j)*.2)+rng.normal(0,.05)
|
| 328 |
+
alt_m = base*(1-inten*.3)
|
| 329 |
+
fig,axes = plt.subplots(1,2,figsize=(10,4))
|
| 330 |
+
for ax,data,title,cmap in zip(axes,[base,alt_m],["REF contact map","ALT contact map"],["Blues","Reds"]):
|
| 331 |
+
im=ax.imshow(data,cmap=cmap,aspect="auto",vmin=0)
|
| 332 |
+
ax.set_title(f"{sym} β {title} (demo)",fontweight="bold",fontsize=9)
|
| 333 |
+
plt.colorbar(im,ax=ax,fraction=.046,pad=.04)
|
| 334 |
+
fig.patch.set_facecolor("white"); fig.tight_layout()
|
| 335 |
+
return fig
|
| 336 |
|
| 337 |
+
def build_docx(sym, gi, tissue, vpos, rb, ab, inten, figs):
|
| 338 |
+
doc = Document()
|
| 339 |
+
doc.add_heading("Virtual Gene Scope v2.0 β Gene Analysis Report", 0)
|
| 340 |
+
p = doc.add_paragraph("EDUCATIONAL USE ONLY β not for clinical decision-making.")
|
| 341 |
+
p.runs[0].font.color.rgb = RGBColor(0xC5,0x30,0x30)
|
| 342 |
+
doc.add_heading("Gene Summary", 1)
|
| 343 |
+
t = doc.add_table(rows=1, cols=2); t.style = "Light Shading Accent 1"
|
| 344 |
+
t.rows[0].cells[0].text = "Field"; t.rows[0].cells[1].text = "Value"
|
| 345 |
+
for field, val in [
|
| 346 |
+
("Gene", sym), ("Location", f"{gi['chr']}:{gi['start']:,}β{gi['end']:,}"),
|
| 347 |
+
("Key SNP", gi.get("key_snp","N/A")), ("Inheritance", gi.get("inheritance","N/A")),
|
| 348 |
+
("Condition", gi.get("condition","N/A")), ("Tissue", tissue),
|
| 349 |
+
("Variant", f"{gi['chr']}:{vpos} {rb}>{ab}"), ("Impact", f"{inten:.0%}"),
|
| 350 |
+
]:
|
| 351 |
+
r = t.add_row().cells; r[0].text = field; r[1].text = val
|
| 352 |
+
doc.add_heading("Nursing Reference", 1); doc.add_paragraph(gi.get("nursing_note",""))
|
| 353 |
+
doc.add_heading("NMC Standards Alignment", 1)
|
| 354 |
+
for p_nmc in gi.get("nmc_platforms",[]): doc.add_paragraph(f"β’ Platform {p_nmc}", style="List Bullet")
|
| 355 |
+
if gi.get("pharmgkb"): doc.add_paragraph(f"PharmGKB: {gi['pharmgkb']}")
|
| 356 |
+
doc.add_heading("Resources", 1)
|
| 357 |
+
for label,url in [("ClinVar",gi.get("clinvar","")),("NICE",gi.get("nice_link","")),("PharmGKB",gi.get("pharmgkb",""))]:
|
| 358 |
+
if url: doc.add_paragraph(f"{label}: {url}", style="List Bullet")
|
| 359 |
+
if figs:
|
| 360 |
+
doc.add_heading("Visualisation Tracks", 1)
|
| 361 |
+
for fig in figs:
|
| 362 |
+
buf=io.BytesIO(); fig.savefig(buf,format="png",dpi=150,bbox_inches="tight"); buf.seek(0)
|
| 363 |
+
w = doc.sections[0].page_width - doc.sections[0].left_margin - doc.sections[0].right_margin
|
| 364 |
+
doc.add_picture(buf, width=w); buf.close()
|
| 365 |
+
doc.add_paragraph("Built by Clinical Quality Artificial Intelligence β Nurse Citizen Developers\nhttps://github.com/Clinical-Quality-Artifical-Intelligence\nThis tool supports but does not replace clinical judgment.")
|
| 366 |
+
out=io.BytesIO(); doc.save(out); return out.getvalue()
|
| 367 |
+
|
| 368 |
+
# ---------------------------------------------------------------------------
|
| 369 |
+
# Tabs
|
| 370 |
+
# ---------------------------------------------------------------------------
|
| 371 |
st.markdown("---")
|
| 372 |
+
tab_a, tab_r, tab_nmc, tab_hist = st.tabs(["π Analysis","π©ββοΈ Nurse Reference","π NMC Alignment","π Session History"])
|
| 373 |
+
|
| 374 |
+
with tab_a:
|
| 375 |
+
col_s, col_t = st.columns([1,2])
|
| 376 |
+
|
| 377 |
+
with col_s:
|
| 378 |
+
st.subheader("π Summary")
|
| 379 |
+
st.markdown(f"""<div class="metric-card"><span class="gene-badge">{gene_sym}</span><br><br>
|
| 380 |
+
<strong>Mode:</strong> {mode}<br><strong>Tissue:</strong> {tissue}<br>
|
| 381 |
+
<strong>Variant:</strong> <code>{gi['chr']}:{vpos} {ref_b}>{alt_b}</code><br>
|
| 382 |
+
<strong>Impact:</strong> {intensity:.0%}<br><strong>Condition:</strong> {gi.get('condition','N/A')}</div>""", unsafe_allow_html=True)
|
| 383 |
|
| 384 |
+
if gi.get("category") == "pgx":
|
| 385 |
+
drug = gi.get("drug","Unknown")
|
| 386 |
+
if intensity > 0.55:
|
| 387 |
+
st.markdown(f'<div class="alert-box"><strong>β οΈ ADVERSE DRUG REACTION RISK</strong><br><strong>Drug:</strong> {drug}<br><strong>Phenotype:</strong> Poor / Intermediate Metaboliser<br><strong>Action:</strong> Consider dose reduction or alternative agent</div>', unsafe_allow_html=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 388 |
else:
|
| 389 |
+
st.markdown(f'<div class="success-box"><strong>β
STANDARD DOSING LIKELY</strong><br><strong>Drug:</strong> {drug}<br><strong>Phenotype:</strong> Normal Metaboliser<br><strong>Action:</strong> Standard protocol applies</div>', unsafe_allow_html=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 390 |
else:
|
| 391 |
+
lvl = "High" if intensity>.65 else "Moderate" if intensity>.35 else "Low"
|
| 392 |
+
colours = {"High":("#fff5f5","#e53e3e"),"Moderate":("#fffbeb","#d69e2e"),"Low":("#f0fff4","#38a169")}
|
| 393 |
+
bg,bd = colours[lvl]
|
| 394 |
+
st.markdown(f'<div style="background:{bg};border-left:4px solid {bd};padding:1rem;border-radius:0 10px 10px 0;margin:.8rem 0;"><strong>Predicted Impact: {lvl}</strong><br>{gi.get("condition","")}</div>', unsafe_allow_html=True)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 395 |
|
| 396 |
+
st.markdown("**π Authoritative Sources**")
|
| 397 |
+
lc1, lc2 = st.columns(2)
|
| 398 |
+
btns = [("ClinVar", gi.get("clinvar","")), ("OMIM", f"https://omim.org/entry/{gi.get('omim','')}" if gi.get("omim") else ""),
|
| 399 |
+
("NICE", gi.get("nice_link","")), ("PharmGKB", gi.get("pharmgkb",""))]
|
| 400 |
+
for i,(lbl,url) in enumerate(btns):
|
| 401 |
+
if url: (lc1 if i%2==0 else lc2).link_button(lbl, url, use_container_width=True)
|
| 402 |
+
st.link_button("π₯ NHS Genomics England", f"https://www.genomicsengland.co.uk/search?q={gene_sym}", use_container_width=True)
|
| 403 |
+
|
| 404 |
+
with col_t:
|
| 405 |
+
st.subheader("π Predicted Tracks")
|
| 406 |
+
figs_out = []
|
| 407 |
+
|
| 408 |
+
if not HAS_ALPHAGENOME or not api_key:
|
| 409 |
+
st.info("π¬ **Demo Mode** β Realistic simulated tracks. Add AlphaGenome API key in sidebar for live predictions.", icon="βΉοΈ")
|
| 410 |
+
if "RNA Expression" in modalities:
|
| 411 |
+
f=_rna(gene_sym,intensity); st.pyplot(f); figs_out.append(f)
|
| 412 |
+
if "Splicing" in modalities:
|
| 413 |
+
f=_splice(gene_sym,intensity); st.pyplot(f); figs_out.append(f)
|
| 414 |
+
if "Chromatin Accessibility" in modalities:
|
| 415 |
+
f=_chromatin(gene_sym,intensity); st.pyplot(f); figs_out.append(f)
|
| 416 |
+
if "Contact Map" in modalities:
|
| 417 |
+
f=_contact(gene_sym,intensity); st.pyplot(f); figs_out.append(f)
|
| 418 |
+
else:
|
| 419 |
+
st.sidebar.success("β
AlphaGenome API connected")
|
| 420 |
+
model = dna_client.create(api_key)
|
| 421 |
+
try:
|
| 422 |
+
with st.spinner(f"Querying AlphaGenome for {gene_sym}β¦"):
|
| 423 |
+
interval = genome.Interval(chromosome=gi["chr"], start=gi["start"], end=gi["end"])
|
| 424 |
+
variant = genome.Variant(chromosome=gi["chr"], position=vpos, reference_bases=ref_b, alternate_bases=alt_b)
|
| 425 |
+
outputs = model.predict_variant(interval=interval, variant=variant, ontology_terms=[ont], requested_outputs=[dna_client.OutputType.RNA_SEQ])
|
| 426 |
+
if hasattr(outputs.reference, "rna_seq"):
|
| 427 |
+
fig = plot_components.plot(
|
| 428 |
+
[plot_components.OverlaidTracks(tdata={"REF":outputs.reference.rna_seq,"ALT":outputs.alternate.rna_seq}, colors={"REF":"dimgrey","ALT":"#ff4b4b"})],
|
| 429 |
+
interval=outputs.reference.rna_seq.interval.resize(2**14),
|
| 430 |
+
annotations=[plot_components.VariantAnnotation([variant], alpha=0.8)],
|
| 431 |
+
)
|
| 432 |
+
st.pyplot(fig); figs_out.append(fig)
|
| 433 |
+
except Exception as e:
|
| 434 |
+
st.error(f"AlphaGenome error: {e}")
|
| 435 |
+
f=_rna(gene_sym,intensity); st.pyplot(f); figs_out.append(f)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 436 |
|
| 437 |
+
if HAS_DOCX and figs_out:
|
| 438 |
+
st.markdown("---")
|
| 439 |
+
docx_bytes = build_docx(gene_sym, gi, tissue, vpos, ref_b, alt_b, intensity, figs_out)
|
| 440 |
+
st.download_button("π₯ Download Report (.docx)", data=docx_bytes,
|
| 441 |
+
file_name=f"VirtualGeneScope_{gene_sym}_{tissue.replace(' ','_')}.docx",
|
| 442 |
+
mime="application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
| 443 |
+
use_container_width=True)
|
| 444 |
+
|
| 445 |
+
entry = {"gene":gene_sym,"tissue":tissue,"mode":mode,"variant":f"{gi['chr']}:{vpos} {ref_b}>{alt_b}","impact":f"{intensity:.0%}"}
|
| 446 |
+
if not st.session_state.history or st.session_state.history[-1] != entry:
|
| 447 |
+
st.session_state.history.append(entry)
|
| 448 |
+
if len(st.session_state.history) > 10: st.session_state.history.pop(0)
|
| 449 |
+
|
| 450 |
+
with tab_r:
|
| 451 |
+
st.subheader(f"π©ββοΈ Nurse Reference β {gene_sym}")
|
| 452 |
+
st.markdown(f'<div class="info-card"><strong>π₯ Condition:</strong> {gi.get("condition","N/A")}<br><strong>𧬠Key SNP:</strong> {gi.get("key_snp","N/A")}<br><strong>π Inheritance:</strong> {gi.get("inheritance","N/A")}</div>', unsafe_allow_html=True)
|
| 453 |
+
st.markdown("#### π‘ Nursing Practice Guidance")
|
| 454 |
+
st.markdown(gi.get("nursing_note",""))
|
| 455 |
+
if gi.get("category") == "pgx":
|
| 456 |
+
st.markdown("---"); st.markdown("#### π PGx Quick Reference")
|
| 457 |
+
drug = gi.get("drug","N/A"); ca,cb = st.columns(2)
|
| 458 |
+
ca.markdown(f'<div class="alert-box"><strong>β οΈ Poor Metaboliser</strong><br>Drug: <strong>{drug}</strong><br>Accumulation β toxicity<br>Reduce dose / switch agent</div>', unsafe_allow_html=True)
|
| 459 |
+
cb.markdown(f'<div class="success-box"><strong>β
Normal Metaboliser</strong><br>Drug: <strong>{drug}</strong><br>Standard response expected<br>Standard dosing protocol</div>', unsafe_allow_html=True)
|
| 460 |
+
if gi.get("pharmgkb"): st.link_button(f"π PharmGKB β {gene_sym}", gi["pharmgkb"], use_container_width=True)
|
| 461 |
+
st.markdown("---"); st.markdown("#### π UK Clinical Guidelines")
|
| 462 |
+
if gi.get("nice_link"): st.link_button(f"π {gi.get('nice_label','NICE Guidance')}", gi["nice_link"], use_container_width=True)
|
| 463 |
+
st.link_button("π₯ NHS Genomics England", f"https://www.genomicsengland.co.uk/search?q={gene_sym}", use_container_width=True)
|
| 464 |
+
st.link_button("π¬ ClinVar", gi.get("clinvar", f"https://www.ncbi.nlm.nih.gov/clinvar/?term={gene_sym}"), use_container_width=True)
|
| 465 |
+
if gi.get("omim"): st.link_button("π OMIM", f"https://omim.org/entry/{gi['omim']}", use_container_width=True)
|
| 466 |
+
|
| 467 |
+
with tab_nmc:
|
| 468 |
+
st.subheader("π NMC Standards of Proficiency Alignment")
|
| 469 |
+
st.markdown("All CQAI tools map to the [NMC Standards of Proficiency for Registered Nurses (2018)](https://www.nmc.org.uk/standards/standards-for-nurses/standards-of-proficiency-for-registered-nurses/).")
|
| 470 |
+
st.markdown(f"**{gene_sym} β {gi.get('condition','')}**")
|
| 471 |
+
all_platforms = [
|
| 472 |
+
"Platform 1 β Being an accountable professional",
|
| 473 |
+
"Platform 2 β Promoting health and preventing ill health",
|
| 474 |
+
"Platform 3 β Assessing needs and planning care",
|
| 475 |
+
"Platform 4 β Providing and evaluating care",
|
| 476 |
+
"Platform 5 β Leading and managing nursing care",
|
| 477 |
+
"Platform 6 β Improving safety and quality of care",
|
| 478 |
+
"Platform 7 β Coordinating care",
|
| 479 |
+
]
|
| 480 |
+
for plat in all_platforms:
|
| 481 |
+
active = any(p in plat for p in gi.get("nmc_platforms",[]))
|
| 482 |
+
icon = "β
" if active else "β¬"
|
| 483 |
+
colour = "#2d6a4f" if active else "#6c757d"
|
| 484 |
+
st.markdown(f"<span style='color:{colour}'>{icon} {plat}</span>", unsafe_allow_html=True)
|
| 485 |
+
st.markdown("---"); st.markdown("#### π Genomics in Nursing β Resources")
|
| 486 |
+
for label, url in [
|
| 487 |
+
("NHS Genomics Education Programme","https://www.hee.nhs.uk/our-work/genomics"),
|
| 488 |
+
("Genomics England β NHS Genomic Medicine Service","https://www.genomicsengland.co.uk/"),
|
| 489 |
+
("RCN β Genomics for Nursing","https://www.rcn.org.uk/clinical-topics/genomics"),
|
| 490 |
+
("PharmGKB","https://www.pharmgkb.org/"),
|
| 491 |
+
("NHS England DPYD Genotyping Mandate","https://www.england.nhs.uk/publication/dpyd-genotyping/"),
|
| 492 |
+
]:
|
| 493 |
+
st.link_button(label, url, use_container_width=True)
|
| 494 |
+
|
| 495 |
+
with tab_hist:
|
| 496 |
+
st.subheader("π Session History (last 10)")
|
| 497 |
+
if not st.session_state.history:
|
| 498 |
+
st.info("No analyses run yet this session.")
|
| 499 |
+
else:
|
| 500 |
+
st.dataframe(pd.DataFrame(st.session_state.history[::-1]), use_container_width=True)
|
| 501 |
+
if st.button("ποΈ Clear History", type="secondary"): st.session_state.history=[]; st.rerun()
|
| 502 |
+
|
| 503 |
+
st.markdown("---")
|
| 504 |
+
st.markdown("""<div style='text-align:center;color:#718096;font-size:.88rem;'>
|
| 505 |
+
<strong>Virtual Gene Scope v2.0</strong> Β· Powered by <a href='https://github.com/google-deepmind/alphagenome' style='color:#667eea;'>Google DeepMind AlphaGenome</a><br>
|
| 506 |
+
Part of the <strong>CQAI Nursing Education Toolkit</strong> Β· <a href='https://github.com/Clinical-Quality-Artifical-Intelligence' style='color:#667eea;'>Clinical Quality Artificial Intelligence</a><br>
|
| 507 |
+
<em>Built by Nurse Citizen Developers π©Ί Β· This tool supports but does not replace clinical judgment.</em>
|
| 508 |
+
</div>""", unsafe_allow_html=True)
|
|
@@ -1,6 +1,7 @@
|
|
| 1 |
-
streamlit
|
| 2 |
-
pandas
|
| 3 |
-
matplotlib
|
| 4 |
-
numpy
|
| 5 |
-
huggingface_hub
|
| 6 |
-
|
|
|
|
|
|
| 1 |
+
streamlit>=1.41.0
|
| 2 |
+
pandas>=2.2.0
|
| 3 |
+
matplotlib>=3.9.0
|
| 4 |
+
numpy>=1.26.0
|
| 5 |
+
huggingface_hub>=0.27.0
|
| 6 |
+
alphagenome==0.6.1
|
| 7 |
+
python-docx>=1.1.0
|