Mrinal007 commited on
Commit
a68b247
ยท
verified ยท
1 Parent(s): 889ed7b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +61 -173
app.py CHANGED
@@ -1,186 +1,74 @@
1
- # import numpy as np
2
- # import gradio as gr
3
- # from tensorflow.keras.models import load_model, Model
4
- # from hpelm import ELM
5
- # import joblib
6
-
7
- # # ๐Ÿ”„ Load scaler and ELM model
8
- # scaler = joblib.load("elm_scaler1.pkl")
9
- # elm = ELM(128, 1, classification='c')
10
- # elm.load("elm_model1.txt")
11
-
12
- # # โš™๏ธ Load trained MobileNet1D and create feature extractor
13
- # mobilenet = load_model("physio_model2.h5")
14
- # feature_extractor = Model(inputs=mobilenet.input, outputs=mobilenet.get_layer("penultimate_dense").output)
15
-
16
- # # ๐Ÿ” Preprocessing
17
- # def preprocess_signal(ecg, eda, temp):
18
- # ecg = np.array(ecg).reshape(-1, 1)
19
- # eda = np.array(eda).reshape(-1, 1)
20
- # temp = np.array(temp).reshape(-1, 1)
21
- # return np.concatenate([ecg, eda, temp], axis=1)
22
-
23
- # # ๐Ÿ”ฎ Prediction
24
- # def predict_stress(ecg, eda, temp):
25
- # try:
26
- # signal = preprocess_signal(ecg, eda, temp).reshape(1, 1280, 3)
27
- # features = feature_extractor.predict(signal)
28
- # features_scaled = scaler.transform(features)
29
- # raw_pred = elm.predict(features_scaled)
30
- # raw_pred = np.clip(raw_pred, -20, 20)
31
- # prob = 1 / (1 + np.exp(-raw_pred))
32
- # label = "Stress" if prob > 0.5 else "No Stress"
33
- # return f"{label} (Confidence: {prob[0][0]:.2f})"
34
- # except Exception as e:
35
- # return f"โŒ Error: {str(e)}"
36
-
37
- # # ๐Ÿงช Parser for string inputs
38
- # def parse_and_predict(ecg_str, eda_str, temp_str):
39
- # try:
40
- # ecg = list(map(float, ecg_str.strip().split(',')))
41
- # eda = list(map(float, eda_str.strip().split(',')))
42
- # temp = list(map(float, temp_str.strip().split(',')))
43
- # if len(ecg) != 1280 or len(eda) != 1280 or len(temp) != 1280:
44
- # return "โŒ Each signal must be exactly 1280 samples long."
45
- # return predict_stress(ecg, eda, temp)
46
- # except:
47
- # return "โŒ Invalid input format. Use comma-separated float values."
48
-
49
- # # ๐Ÿ“Š Demo stress data
50
- # def generate_stress_sample():
51
- # t = np.linspace(0, 10, 1280)
52
- # ecg = 0.6 * np.sin(2 * np.pi * 1.8 * t) + 0.1 * np.random.randn(1280)
53
- # eda = np.linspace(0.5, 1.2, 1280) + 0.05 * np.random.randn(1280)
54
- # eda += np.random.choice([0, 0.3], size=1280, p=[0.95, 0.05])
55
- # temp = 36.2 + 0.01 * np.random.randn(1280) - 0.05 * np.linspace(0, 1, 1280)
56
- # return ecg, eda, temp
57
-
58
- # # ๐Ÿ‘‡ Separate into text strings
59
- # ecg_demo, eda_demo, temp_demo = generate_stress_sample()
60
- # demo_example = [
61
- # ','.join([str(round(v, 4)) for v in ecg_demo]),
62
- # ','.join([str(round(v, 4)) for v in eda_demo]),
63
- # ','.join([str(round(v, 4)) for v in temp_demo])
64
- # ]
65
-
66
- # # ๐ŸŽ›๏ธ Gradio Interface
67
- # iface = gr.Interface(
68
- # fn=parse_and_predict,
69
- # inputs=[
70
- # gr.Textbox(label="ECG Signal (1280 values, comma-separated)", lines=4),
71
- # gr.Textbox(label="EDA Signal (1280 values, comma-separated)", lines=4),
72
- # gr.Textbox(label="Temperature Signal (1280 values, comma-separated)", lines=4)
73
- # ],
74
- # outputs=gr.Textbox(label="Prediction"),
75
- # examples=[demo_example],
76
- # title="๐Ÿง  Stress Detection from Physiological Signals",
77
- # description="Enter 1280 comma-separated ECG, EDA, and Temp signal values. The model will classify stress vs no stress."
78
- # )
79
-
80
- # # ๐Ÿ Launch
81
- # if __name__ == "__main__":
82
- # iface.launch()
83
-
84
-
85
  import numpy as np
86
- import pandas as pd
87
  import gradio as gr
 
88
  from tensorflow.keras.models import load_model, Model
89
  from hpelm import ELM
90
  import joblib
91
- import tempfile
92
-
93
- # ๐Ÿ”„ Load scaler and ELM model
94
- scaler = joblib.load("elm_scaler1.pkl")
95
- elm = ELM(128, 1, classification='c')
96
- elm.load("elm_model1.txt")
97
-
98
- # โš™๏ธ Load trained MobileNet1D and create feature extractor
99
- mobilenet = load_model("physio_model2.h5")
100
- feature_extractor = Model(inputs=mobilenet.input, outputs=mobilenet.get_layer("penultimate_dense").output)
101
-
102
- def preprocess_signal(ecg, eda, temp):
103
- ecg = np.array(ecg).reshape(-1, 1)
104
- eda = np.array(eda).reshape(-1, 1)
105
- temp = np.array(temp).reshape(-1, 1)
106
- return np.concatenate([ecg, eda, temp], axis=1)
107
 
108
- def predict_stress(ecg, eda, temp):
109
- try:
110
- signal = preprocess_signal(ecg, eda, temp) # Shape: (1280, 3)
111
- signal = signal.reshape(1, 1280, 3)
112
 
113
- # ๐Ÿ” Feature Extraction
114
- features = feature_extractor.predict(signal)
115
-
116
- # ๐Ÿ”„ Scaling for ELM
117
- features_scaled = scaler.transform(features)
118
-
119
- # ๐Ÿ”ฎ ELM Inference
120
- raw_pred = elm.predict(features_scaled)
121
- raw_pred = np.clip(raw_pred, -20, 20)
122
- prob = 1 / (1 + np.exp(-raw_pred))
123
- label = "Stress" if prob > 0.5 else "No Stress"
124
-
125
- return f"{label} (Confidence: {prob[0][0]:.2f})"
126
-
127
- except Exception as e:
128
- return f"โŒ Error: {str(e)}"
129
 
130
- # โœ… Predict from CSV File
131
- def predict_from_csv(file_obj):
132
- try:
133
- df = pd.read_csv(file_obj.name)
134
- if df.shape != (1280, 3) or list(df.columns) != ["ECG", "EDA", "Temp"]:
135
- return "โŒ CSV must have shape (1280, 3) with columns: ECG, EDA, Temp"
136
- ecg = df["ECG"].values
137
- eda = df["EDA"].values
138
- temp = df["Temp"].values
139
- return predict_stress(ecg, eda, temp)
140
- except Exception as e:
141
- return f"โŒ Failed to read CSV: {str(e)}"
142
 
143
- # โœ… Generate deterministic synthetic stress signal (not random)
144
- def generate_stress_sample():
145
  timesteps = 1280
146
  t = np.linspace(0, 10, timesteps)
147
-
148
- # Simulated stress ECG: High-frequency sinusoid
149
- ecg = 0.6 * np.sin(2 * np.pi * 1.8 * t)
150
-
151
- # Simulated EDA: Linearly increasing with occasional burst
152
- eda = 0.5 + 0.7 * (t / t.max())
153
- eda[::256] += 0.3 # Small spikes
154
-
155
- # Simulated Temp: Slight downward trend
156
- temp = 36.4 - 0.05 * (t / t.max())
157
-
158
  return np.stack([ecg, eda, temp], axis=1)
159
 
160
- def generate_stress_sample_csv():
161
- sample = generate_stress_sample()
162
- df = pd.DataFrame(sample, columns=["ECG", "EDA", "Temp"])
163
- tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".csv")
164
- df.to_csv(tmp.name, index=False)
165
- return tmp.name
166
-
167
- # โœ… Gradio Interface
168
- with gr.Blocks() as demo:
169
- gr.Markdown("# ๐Ÿง  Stress Detection from Physiological Signals")
170
- gr.Markdown("Upload a CSV file with 1280 rows and 3 columns: **ECG**, **EDA**, **Temp**")
171
-
172
- with gr.Row():
173
- file_input = gr.File(label="๐Ÿ“ Upload CSV file", file_types=[".csv"])
174
- output = gr.Textbox(label="Prediction")
175
-
176
- file_input.change(fn=predict_from_csv, inputs=file_input, outputs=output)
177
-
178
- gr.Markdown("### Or generate a sample stressed input:")
179
- generate_btn = gr.Button("Generate Stress Sample CSV")
180
- demo_file = gr.File(label="โฌ‡๏ธ Download sample and re-upload above")
181
-
182
- generate_btn.click(fn=generate_stress_sample_csv, outputs=demo_file)
183
-
184
- # ๐Ÿ Launch
185
- if __name__ == "__main__":
186
- demo.launch(server_name="0.0.0.0", server_port=7860, share=True, show_api=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import numpy as np
 
2
  import gradio as gr
3
+ import matplotlib.pyplot as plt
4
  from tensorflow.keras.models import load_model, Model
5
  from hpelm import ELM
6
  import joblib
7
+ import io
8
+ import base64
 
 
 
 
 
 
 
 
 
 
 
 
 
 
9
 
10
+ # === Load Models ===
11
+ mobilenet_model = load_model("physio_model2.h5")
12
+ feature_model = Model(inputs=mobilenet_model.input, outputs=mobilenet_model.get_layer("penultimate_dense").output)
 
13
 
14
+ scaler = joblib.load("elm_scaler1.pkl")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
+ elm = ELM(128, 1, classification="c")
17
+ elm.load("elm_model1.txt")
 
 
 
 
 
 
 
 
 
 
18
 
19
+ # === Generate stress physiological signal ===
20
+ def generate_stress_signal():
21
  timesteps = 1280
22
  t = np.linspace(0, 10, timesteps)
23
+ ecg = 0.6 * np.sin(2 * np.pi * 1.8 * t) + 0.1 * np.random.randn(timesteps)
24
+ eda = np.linspace(0.5, 1.2, timesteps) + 0.1 * np.random.randn(timesteps)
25
+ eda += np.random.choice([0, 0.5], size=timesteps, p=[0.9, 0.1])
26
+ temp = 36.2 + 0.02 * np.random.randn(timesteps) - 0.05 * np.linspace(0, 1, timesteps)
 
 
 
 
 
 
 
27
  return np.stack([ecg, eda, temp], axis=1)
28
 
29
+ # === Prediction Function ===
30
+ def predict_from_generated():
31
+ stress_input = generate_stress_signal()
32
+ model_input = stress_input[np.newaxis, ...] # (1, 1280, 3)
33
+
34
+ features = feature_model.predict(model_input)
35
+ features_scaled = scaler.transform(features)
36
+ raw_pred = elm.predict(features_scaled)
37
+ raw_pred_clipped = np.clip(raw_pred, -20, 20)
38
+ prob_pred = 1 / (1 + np.exp(-raw_pred_clipped))
39
+ label_pred = "Stress" if prob_pred > 0.5 else "No Stress"
40
+
41
+ # Plot
42
+ fig, axs = plt.subplots(1, 3, figsize=(12, 3))
43
+ axs[0].plot(stress_input[:, 0])
44
+ axs[0].set_title("ECG")
45
+ axs[1].plot(stress_input[:, 1])
46
+ axs[1].set_title("EDA")
47
+ axs[2].plot(stress_input[:, 2])
48
+ axs[2].set_title("Temp")
49
+ plt.tight_layout()
50
+
51
+ buf = io.BytesIO()
52
+ plt.savefig(buf, format="png")
53
+ plt.close(fig)
54
+ buf.seek(0)
55
+ img_str = base64.b64encode(buf.read()).decode("utf-8")
56
+ img_data = f"data:image/png;base64,{img_str}"
57
+
58
+ prob_display = float(prob_pred[0][0])
59
+ return label_pred, f"{prob_display:.3f}", img_data
60
+
61
+ # === Gradio UI ===
62
+ iface = gr.Interface(
63
+ fn=predict_from_generated,
64
+ inputs=[],
65
+ outputs=[
66
+ gr.Textbox(label="Predicted Label"),
67
+ gr.Textbox(label="Stress Probability"),
68
+ gr.Image(label="Signal Plot")
69
+ ],
70
+ title="๐Ÿง  Stress Detection from Simulated Physiological Signal",
71
+ description="This demo generates synthetic stressed signals (ECG, EDA, Temp), extracts deep features using a pretrained MobileNet1D model, and classifies stress using ELM."
72
+ )
73
+
74
+ iface.launch()