mgbam commited on
Commit
a003746
·
verified ·
1 Parent(s): 3a42f68

Upload app_space.py

Browse files
Files changed (1) hide show
  1. app_space.py +39 -11
app_space.py CHANGED
@@ -2,10 +2,13 @@ import io
2
  import json
3
  import os
4
  import sys
 
5
  from typing import Any, Dict, List
6
 
7
  import gradio as gr
8
  import matplotlib.pyplot as plt
 
 
9
 
10
  # Ensure local package is importable when running in Hugging Face Spaces
11
  ROOT = os.path.dirname(os.path.abspath(__file__))
@@ -40,8 +43,11 @@ def run_infer(signal_text: str) -> Dict[str, Any]:
40
  )
41
  patient_context = {"patient_id": "demo"}
42
  rules_result = evaluate_ecg_rules(patient_context, model_output)
43
- explanations = [*(model_output.get("gating", {}).get("explanations", []) if isinstance(model_output.get("gating"), dict) else []),
44
- *rules_result.get("explanations", [])]
 
 
 
45
  return {
46
  "label": model_output.get("label"),
47
  "score": round(float(model_output.get("score", 0.0)), 3),
@@ -49,6 +55,7 @@ def run_infer(signal_text: str) -> Dict[str, Any]:
49
  "alert_level": rules_result.get("alert_level", "none"),
50
  "gated_ratio": round(model_output.get("gated_ratio", 1.0), 3),
51
  "gating": gating_meta,
 
52
  "explanations": explanations,
53
  }
54
 
@@ -66,15 +73,31 @@ def plot_gating(signal_text: str):
66
  fig.savefig(buf, format="png", dpi=120)
67
  plt.close(fig)
68
  buf.seek(0)
69
- import numpy as np
70
- import matplotlib.image as mpimg
71
- buf.seek(0)
72
  np_img = mpimg.imread(buf)
73
- return np_img
74
-
75
-
76
- demo_normal = [0.05 for _ in range(256)]
77
- demo_afib = [0.3 for _ in range(256)]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
 
79
  with gr.Blocks(title="Sundew ECG Demo") as demo:
80
  gr.Markdown("### Neurosymbolic ECG • Sundew Gating + Rules")
@@ -93,16 +116,21 @@ with gr.Blocks(title="Sundew ECG Demo") as demo:
93
  value=json.dumps(demo_afib[:128]),
94
  )
95
  img = gr.Image(type="numpy", label="Raw vs Gated")
 
 
96
  btn2 = gr.Button("Show gating")
97
- btn2.click(plot_gating, inputs=inp2, outputs=img)
98
  with gr.Tab("Demos"):
99
  out_demo = gr.JSON()
100
  btn_n = gr.Button("Normal")
101
  btn_a = gr.Button("Arrhythmia-ish")
 
102
  hidden_n = gr.Textbox(value=json.dumps(demo_normal), visible=False)
103
  hidden_a = gr.Textbox(value=json.dumps(demo_afib), visible=False)
 
104
  btn_n.click(run_infer, inputs=hidden_n, outputs=out_demo)
105
  btn_a.click(run_infer, inputs=hidden_a, outputs=out_demo)
 
106
 
107
 
108
  if __name__ == "__main__":
 
2
  import json
3
  import os
4
  import sys
5
+ import math
6
  from typing import Any, Dict, List
7
 
8
  import gradio as gr
9
  import matplotlib.pyplot as plt
10
+ import numpy as np
11
+ import matplotlib.image as mpimg
12
 
13
  # Ensure local package is importable when running in Hugging Face Spaces
14
  ROOT = os.path.dirname(os.path.abspath(__file__))
 
43
  )
44
  patient_context = {"patient_id": "demo"}
45
  rules_result = evaluate_ecg_rules(patient_context, model_output)
46
+ explanations = [
47
+ *(model_output.get("gating", {}).get("explanations", []) if isinstance(model_output.get("gating"), dict) else []),
48
+ *rules_result.get("explanations", []),
49
+ ]
50
+ summary = f"Windows kept: {gating_meta.get('selected_windows',0)}/{gating_meta.get('total_windows',0)} • ratio={gating_meta.get('ratio',1):.2f}"
51
  return {
52
  "label": model_output.get("label"),
53
  "score": round(float(model_output.get("score", 0.0)), 3),
 
55
  "alert_level": rules_result.get("alert_level", "none"),
56
  "gated_ratio": round(model_output.get("gated_ratio", 1.0), 3),
57
  "gating": gating_meta,
58
+ "gating_summary": summary,
59
  "explanations": explanations,
60
  }
61
 
 
73
  fig.savefig(buf, format="png", dpi=120)
74
  plt.close(fig)
75
  buf.seek(0)
 
 
 
76
  np_img = mpimg.imread(buf)
77
+ windows = meta.get("windows", [])
78
+ table = [
79
+ {
80
+ "start": w.get("start"),
81
+ "end": w.get("end"),
82
+ "significance": round(float(w.get("significance", 0.0)), 3),
83
+ "prob": round(float(w.get("probability", 0.0)), 3),
84
+ "selected": bool(w.get("selected")),
85
+ }
86
+ for w in windows
87
+ ]
88
+ summary = f"Windows kept: {meta.get('selected_windows',0)}/{meta.get('total_windows',0)} • ratio={meta.get('ratio',1):.2f}"
89
+ return np_img, summary, table
90
+
91
+
92
+ # Demo signals with more structure so gating can skip/keep meaningfully
93
+ demo_normal = [0.05 * math.sin(2 * math.pi * 2 * (i / 256)) for i in range(256)]
94
+ demo_afib = [
95
+ 0.25 * math.sin(2 * math.pi * 6 * (i / 256))
96
+ + 0.05 * math.sin(2 * math.pi * 15 * (i / 256))
97
+ + (0.15 if i % 40 == 0 else 0.0)
98
+ for i in range(256)
99
+ ]
100
+ demo_noise = [0.02 * math.sin(2 * math.pi * 1 * (i / 256)) + (0.01 if i % 13 == 0 else 0.0) for i in range(256)]
101
 
102
  with gr.Blocks(title="Sundew ECG Demo") as demo:
103
  gr.Markdown("### Neurosymbolic ECG • Sundew Gating + Rules")
 
116
  value=json.dumps(demo_afib[:128]),
117
  )
118
  img = gr.Image(type="numpy", label="Raw vs Gated")
119
+ summary_box = gr.Textbox(label="Gating summary")
120
+ table = gr.Dataframe(headers=["start", "end", "significance", "prob", "selected"], datatype=["number", "number", "number", "number", "bool"], wrap=True)
121
  btn2 = gr.Button("Show gating")
122
+ btn2.click(plot_gating, inputs=inp2, outputs=[img, summary_box, table])
123
  with gr.Tab("Demos"):
124
  out_demo = gr.JSON()
125
  btn_n = gr.Button("Normal")
126
  btn_a = gr.Button("Arrhythmia-ish")
127
+ btn_noise = gr.Button("Noisy baseline")
128
  hidden_n = gr.Textbox(value=json.dumps(demo_normal), visible=False)
129
  hidden_a = gr.Textbox(value=json.dumps(demo_afib), visible=False)
130
+ hidden_noise = gr.Textbox(value=json.dumps(demo_noise), visible=False)
131
  btn_n.click(run_infer, inputs=hidden_n, outputs=out_demo)
132
  btn_a.click(run_infer, inputs=hidden_a, outputs=out_demo)
133
+ btn_noise.click(run_infer, inputs=hidden_noise, outputs=out_demo)
134
 
135
 
136
  if __name__ == "__main__":