Bio-signal-chatbot / src /streamlit_app.py
niol08's picture
Update src/streamlit_app.py
fc07d9f verified
raw
history blame
5.99 kB
import os
import streamlit as st
from dotenv import load_dotenv
from model_loader import load_mitbih_model, load_pcg_model, load_emg_model, load_vag_model
from chatbot import analyze_signal
from util import analyze_pcg_signal, analyze_emg_signal, predict_vag_from_features,vag_to_features
load_dotenv()
GEMINI_API_KEY = os.getenv("GEMINI_API_KEY", "")
st.set_page_config(page_title="Biosignal Chatbot", page_icon="🩺", layout="centered")
st.title("🩺 Biosignal Diagnostic Chatbot")
MODELS = {
"ECG": load_mitbih_model(),
"PCG": load_pcg_model(),
"EMG": load_emg_model(),
"VAG": load_vag_model(),
}
FILE_TYPES = {
"ECG": ["csv", "txt"],
"EMG": ["csv", "txt"],
"VAG": ["csv", "npy", "wav"],
"PCG": ["wav"],
}
tabs = st.tabs(["ECG", "EMG", "VAG", "PCG"])
for tab, sig in zip(tabs, ["ECG", "EMG", "VAG", "PCG"]):
with tab:
st.header(f"{sig} Analysis")
if sig == "ECG":
with st.expander("📄 ECG Data Requirements"):
st.markdown(
"- Upload a `.csv` or `.txt` file containing **256 numeric values** (single row or single column).\n"
"- Example:\n"
"```csv\n0.12\n0.15\n-0.05\n...\n```"
)
elif sig == "VAG":
with st.expander("📄 VAG Data Requirements"):
st.markdown(
"- Upload a `.csv` file **with headers** containing the following 5 features:\n"
" - `rms_amplitude`\n"
" - `peak_frequency`\n"
" - `spectral_entropy`\n"
" - `zero_crossing_rate`\n"
" - `mean_frequency`\n"
"- Example file content:\n"
"```csv\n"
"rms_amplitude,peak_frequency,spectral_entropy,zero_crossing_rate,mean_frequency\n"
"1.02,20,-1890.34,0.001,39.7\n"
"```"
)
elif sig == "EMG":
with st.expander("📄 EMG Data Requirements"):
st.markdown(
"- Upload a `.txt` or `.csv` file containing **raw EMG signal samples**.\n"
"- The model expects **at least 1,000 values** (1-second window at 1 kHz sampling).\n"
"- You can provide:\n"
" - A `.txt` file with one value per line.\n"
" - A `.csv` file with a single column of numbers.\n\n"
"- Example `.txt` file:\n"
"```txt\n"
"0.034\n"
"0.056\n"
"-0.012\n"
"...\n"
"```"
)
elif sig == "PCG":
with st.expander("📄 PCG Data Requirements"):
st.markdown(
"- Upload a `.wav` file containing a **single-channel (mono) PCG signal**.\n"
"- The model expects **at least 995 audio samples** (≈0.025s of heart sound at 44.1 kHz).\n"
"- Files longer than 995 samples will be **trimmed**; shorter ones will be **zero-padded**.\n"
"- Ensure the signal is **clean and preprocessed** (no ambient noise).\n\n"
"- Example `.wav` properties:\n"
" - Mono (1 channel)\n"
" - 44.1 kHz sampling rate\n"
" - 16-bit PCM or float32\n"
"\n"
"_Note: Do not upload `.mp3`, `.flac`, or stereo files—they may fail to process properly._"
)
uploaded = st.file_uploader(
f"Upload {sig} file",
type=FILE_TYPES[sig],
key=f"upload_{sig}"
)
if sig == "ECG" and uploaded and st.button("Run Diagnostic", key=f"run_{sig}"):
label, human, conf, gnote = analyze_signal(
uploaded, MODELS["ECG"], GEMINI_API_KEY, signal_type="ECG"
)
st.success(f"**{label}{human}**\n\nConfidence: {conf:.2%}")
if gnote:
st.markdown("### 🧠 Gemini Insight")
st.write(gnote)
elif not GEMINI_API_KEY:
st.info("Gemini key missing – no explanation.")
elif sig == "PCG" and uploaded and st.button("Run Diagnostic", key=f"run_{sig}"):
label, human, conf, gnote = analyze_pcg_signal(
uploaded, MODELS["PCG"], GEMINI_API_KEY
)
st.success(f"**{label}**\n\nConfidence: {conf:.2%}")
if gnote:
st.markdown("### 🧠 Gemini Insight")
st.write(gnote)
elif not GEMINI_API_KEY:
st.info("Gemini key missing – no explanation.")
elif sig == "EMG" and uploaded and st.button("Run Diagnostic", key=f"run_{sig}"):
human, conf, gnote = analyze_emg_signal(
uploaded, MODELS["EMG"], GEMINI_API_KEY
)
st.success(f"**{human.upper()}**\n\nConfidence: {conf:.2%}")
if gnote:
st.markdown("### 🧠 Gemini Insight")
st.write(gnote)
elif not GEMINI_API_KEY:
st.info("Gemini key missing – no explanation.")
elif sig == "VAG" and uploaded and st.button("Run Diagnostic", key=f"run_{sig}"):
label, human, conf, gnote = predict_vag_from_features(
uploaded, MODELS["VAG"], GEMINI_API_KEY
)
st.success(f"**{label}**\n\nConfidence: {conf:.2%}")
if gnote:
st.markdown("### 🧠 Gemini Insight")
st.write(gnote)
elif not GEMINI_API_KEY:
st.info("Gemini key missing – no explanation.")
else:
if not uploaded:
st.info("Upload a file to begin.")
st.caption("© 2025 Biosignal Chatbot")