Sazzz02 commited on
Commit
46633ee
·
verified ·
1 Parent(s): 5925d7f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +116 -46
app.py CHANGED
@@ -2,61 +2,131 @@ import gradio as gr
2
  import numpy as np
3
  import matplotlib.pyplot as plt
4
  import pickle
 
5
 
6
- # Load model and scaler
7
  def load_model():
8
- with open("ecg_model.pkl", "rb") as f:
9
- model_data = pickle.load(f)
10
- return model_data["model"], model_data["scaler"]
 
 
 
 
 
 
 
 
11
 
 
12
  model, scaler = load_model()
13
 
14
- def analyze_manual_entry(input_str):
15
- # Parse input
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  try:
17
- voltage_list = [float(x) for x in input_str.split(",") if x.strip()]
 
18
  if len(voltage_list) < 2:
19
- return None, "Please enter at least 2 values.", ""
20
- except Exception:
21
- return None, "Invalid input. Please enter comma-separated numbers.", ""
22
- # Detect anomalies
23
- arr = np.array(voltage_list).reshape(-1, 1)
24
- arr_scaled = scaler.transform(arr)
25
- preds = model.predict(arr_scaled)
26
- scores = model.decision_function(arr_scaled)
27
- anomalies = [(i, v, s) for i, (p, v, s) in enumerate(zip(preds, voltage_list, scores)) if p == -1]
28
- # Plot
29
- plt.figure(figsize=(10, 4))
30
- plt.plot(voltage_list, label="ECG Voltage")
31
- if anomalies:
32
- idxs = [a[0] for a in anomalies]
33
- vals = [a[1] for a in anomalies]
34
- plt.scatter(idxs, vals, color="red", label="Anomaly")
35
- plt.title("ECG Anomaly Detection")
36
- plt.xlabel("Sample Index")
37
- plt.ylabel("Voltage")
38
- plt.legend()
39
- plt.tight_layout()
40
- plt.savefig("ecg_manual_plot.png")
41
- plt.close()
42
- # Prepare output
43
- if not anomalies:
44
- summary = "No anomalies detected."
45
- details = ""
46
- else:
47
- summary = f"Detected {len(anomalies)} anomalies."
48
- details = "\n".join([f"Index: {idx}, Voltage: {v:.3f}, Score: {s:.3f}" for idx, v, s in anomalies])
49
- return "ecg_manual_plot.png", summary, details
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
 
 
51
  with gr.Blocks() as demo:
52
- gr.Markdown("# 🫀 ECG Anomaly Detection (Manual Entry)")
53
- gr.Markdown("Enter comma-separated ECG voltages to detect anomalies.")
54
- manual_input = gr.Textbox(label="ECG Voltages (comma-separated)", placeholder="e.g., 3.01,3.02,2.95,4.2")
55
- manual_plot = gr.Image(label="Anomaly Plot")
56
- manual_summary = gr.Textbox(label="Summary")
57
- manual_details = gr.Textbox(label="Anomaly Details", lines=5)
58
- manual_btn = gr.Button("Analyze")
59
- manual_btn.click(analyze_manual_entry, inputs=manual_input, outputs=[manual_plot, manual_summary, manual_details])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
60
 
61
  if __name__ == "__main__":
62
  demo.launch()
 
2
  import numpy as np
3
  import matplotlib.pyplot as plt
4
  import pickle
5
+ import os
6
 
7
+ # Load model and scaler with robust error handling
8
  def load_model():
9
+ try:
10
+ with open("ecg_model.pkl", "rb") as f:
11
+ model_data = pickle.load(f)
12
+ if isinstance(model_data, dict) and 'model' in model_data and 'scaler' in model_data:
13
+ return model_data['model'], model_data['scaler']
14
+ else:
15
+ raise ValueError("Model file doesn't contain expected data structure")
16
+ except Exception as e:
17
+ print(f"Error loading model: {str(e)}")
18
+ # Return dummy model for UI to still work
19
+ return None, None
20
 
21
+ # Load the model
22
  model, scaler = load_model()
23
 
24
+ def detect_anomalies(voltage_list):
25
+ """Detect anomalies in voltage readings"""
26
+ if model is None or scaler is None:
27
+ return np.zeros(len(voltage_list)), np.zeros(len(voltage_list))
28
+
29
+ try:
30
+ voltage_arr = np.array(voltage_list).reshape(-1, 1)
31
+ voltage_scaled = scaler.transform(voltage_arr)
32
+ preds = model.predict(voltage_scaled)
33
+ scores = model.decision_function(voltage_scaled)
34
+ return preds, scores
35
+ except Exception as e:
36
+ print(f"Error in anomaly detection: {str(e)}")
37
+ return np.zeros(len(voltage_list)), np.zeros(len(voltage_list))
38
+
39
+ def analyze_ecg_data(input_str):
40
+ """Analyze manually entered ECG data"""
41
  try:
42
+ # Parse input
43
+ voltage_list = [float(x.strip()) for x in input_str.split(",") if x.strip()]
44
  if len(voltage_list) < 2:
45
+ return None, "Please enter at least 2 voltage readings.", ""
46
+
47
+ # Detect anomalies
48
+ preds, scores = detect_anomalies(voltage_list)
49
+ anomalies = [(i, voltage_list[i], scores[i]) for i in range(len(preds)) if preds[i] == -1]
50
+
51
+ # Create visualization
52
+ plt.figure(figsize=(10, 5))
53
+ plt.plot(voltage_list, label="ECG Voltage")
54
+
55
+ if anomalies:
56
+ anomaly_indices = [a[0] for a in anomalies]
57
+ anomaly_values = [a[1] for a in anomalies]
58
+ plt.scatter(anomaly_indices, anomaly_values, color="red", label="Anomaly")
59
+
60
+ plt.title("ECG Anomaly Detection")
61
+ plt.xlabel("Sample Index")
62
+ plt.ylabel("Voltage (mV)")
63
+ plt.legend()
64
+ plt.grid(True, linestyle='--', alpha=0.7)
65
+ plt.tight_layout()
66
+
67
+ # Save plot
68
+ plot_path = "ecg_analysis.png"
69
+ plt.savefig(plot_path)
70
+ plt.close()
71
+
72
+ # Generate report
73
+ if not anomalies:
74
+ summary = "No anomalies detected in the ECG data."
75
+ details = "All voltage readings appear normal."
76
+ else:
77
+ summary = f"Detected {len(anomalies)} anomalies in the ECG data."
78
+ details = "\n".join([
79
+ f"Index {idx}: Voltage={val:.3f}mV, Anomaly Score={score:.3f}"
80
+ for idx, val, score in anomalies
81
+ ])
82
+ details += "\n\nPossible causes of anomalies:"
83
+ details += "\n- Voltage readings below 2.8mV may indicate conduction issues"
84
+ details += "\n- Voltage readings above 3.3mV may indicate hyperexcitation"
85
+ details += "\n- Irregular patterns may indicate arrhythmia"
86
+
87
+ return plot_path, summary, details
88
+
89
+ except Exception as e:
90
+ return None, f"Error analyzing data: {str(e)}", ""
91
 
92
+ # Gradio Interface
93
  with gr.Blocks() as demo:
94
+ gr.Markdown("# 🫀 ECG Anomaly Detection")
95
+ gr.Markdown("Enter comma-separated ECG voltage readings to detect anomalies.")
96
+
97
+ with gr.Row():
98
+ with gr.Column():
99
+ input_box = gr.Textbox(
100
+ label="ECG Voltages (comma-separated)",
101
+ placeholder="e.g., 3.01,3.02,2.95,4.2,3.0,2.9,2.8,4.1,3.05,3.1",
102
+ lines=3
103
+ )
104
+ analyze_btn = gr.Button("Analyze ECG Data", variant="primary")
105
+
106
+ with gr.Column():
107
+ plot_output = gr.Image(label="ECG Analysis")
108
+ summary_output = gr.Textbox(label="Summary")
109
+ details_output = gr.Textbox(label="Detailed Findings", lines=8)
110
+
111
+ # Example data from your CSV
112
+ gr.Markdown("### Example Data")
113
+ gr.Markdown("Click to use sample data from Person_3:")
114
+ example_btn = gr.Button("Use Sample Data")
115
+
116
+ # Sample data from your CSV (Person_3)
117
+ sample_data = "3.100556,3.098563,3.103323,3.107478,3.100193,3.090881,2.809517,3.106659,3.106299,3.099496,3.095472,3.090603,3.105606,3.090809,3.101076,3.090684,2.835392,3.104057,3.105907,3.091121"
118
+
119
+ # Connect components
120
+ analyze_btn.click(
121
+ analyze_ecg_data,
122
+ inputs=input_box,
123
+ outputs=[plot_output, summary_output, details_output]
124
+ )
125
+
126
+ example_btn.click(
127
+ lambda: sample_data,
128
+ outputs=input_box
129
+ )
130
 
131
  if __name__ == "__main__":
132
  demo.launch()