File size: 5,987 Bytes
486ca74
f0ce95f
486ca74
fc07d9f
f0ce95f
486ca74
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
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")