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

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +146 -42
app.py CHANGED
@@ -1,8 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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")
@@ -13,70 +99,88 @@ elm.load("elm_model1.txt")
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()
 
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")
 
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)