HugBot commited on
Commit
c872458
Β·
verified Β·
1 Parent(s): edafbb5

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +35 -36
app.py CHANGED
@@ -4,7 +4,7 @@ import numpy as np
4
  import matplotlib.pyplot as plt
5
  import gradio as gr
6
 
7
- # ── style ──────────────────────────────────────────────────────────────────
8
  BG = '#f8fafc'
9
  PANEL = '#ffffff'
10
  GRID = '#e2e8f0'
@@ -16,7 +16,7 @@ C_TEXT = '#1e293b'
16
  C_DIM = '#64748b'
17
  C_BORDER= '#cbd5e1'
18
 
19
- plt.rcParams.update({
20
  'figure.facecolor': BG, 'axes.facecolor': PANEL,
21
  'axes.edgecolor': C_BORDER, 'axes.labelcolor': C_DIM,
22
  'xtick.color': C_DIM, 'ytick.color': C_DIM,
@@ -24,44 +24,44 @@ plt.rcParams.update({
24
  'text.color': C_TEXT, 'font.family': 'monospace',
25
  })
26
 
27
- EP_RANGE = np.linspace(0, 15, 600)
28
 
29
- def calc_paf(episodes, incidence, zscore, rr):
30
- return 1 - 1 / (episodes * incidence * zscore * rr)
31
 
32
- # ── plot function ──────────────────────────────────────────────────────────
33
  def draw(ep, inc, zs, rr):
34
  paf_curve = calc_paf(EP_RANGE, inc, zs, rr) * 100
35
  cur_paf = calc_paf(ep, inc, zs, rr)
36
  exponent = ep * inc * zs * rr
37
 
38
- fig, axes = plt.subplots(1, 2, figsize=(15, 6),
39
  gridspec_kw={'width_ratios': [3, 1]})
40
  fig.patch.set_facecolor(BG)
41
 
42
- # ── left: curve ───────────────────────────────────────────────────────
43
  ax = axes[0]
44
  ax.set_facecolor(PANEL)
45
  for spine in ax.spines.values():
46
  spine.set_color(C_BORDER)
47
 
48
- # shadow + main curve
49
  ax.plot(EP_RANGE, paf_curve, color=ACCENT, linewidth=5, alpha=0.15)
50
  ax.plot(EP_RANGE, paf_curve, color=ACCENT, linewidth=2.2)
51
 
52
- # crosshairs
53
  ax.axvline(ep, color=ACCENT, linestyle='--', linewidth=1.2, alpha=0.6)
54
  ax.axhline(cur_paf*100, color=ACCENT, linestyle='--', linewidth=1.2, alpha=0.3)
55
 
56
- # dot at current point
57
  ax.scatter([ep], [cur_paf*100], color=ACCENT, s=80, zorder=5,
58
  edgecolors='white', linewidths=1.5)
59
 
60
- # shaded area under curve up to current episode
61
  mask = EP_RANGE <= ep
62
  ax.fill_between(EP_RANGE[mask], paf_curve[mask], color=ACCENT, alpha=0.08)
63
 
64
- ax.set_xlim(0, 15)
65
  ax.set_ylim(0, 102)
66
  ax.set_xlabel('Episodes', fontsize=11, labelpad=8)
67
  ax.set_ylabel('PAF (%)', fontsize=11, labelpad=8)
@@ -69,7 +69,7 @@ def draw(ep, inc, zs, rr):
69
  color=C_TEXT, fontsize=13, pad=12, fontweight='normal')
70
  ax.grid(True, linewidth=0.8)
71
 
72
- # annotation
73
  ax.annotate(
74
  f' {cur_paf*100:.1f}%',
75
  xy=(ep, cur_paf*100),
@@ -78,35 +78,35 @@ def draw(ep, inc, zs, rr):
78
  arrowprops=dict(arrowstyle='->', color=ACCENT, lw=1.2)
79
  )
80
 
81
- # formula watermark
82
  ax.text(0.98, 0.05,
83
- 'PAF = 1 βˆ’ 1/(ep Γ— inc Γ— Ξ”z Γ— RR)',
84
  transform=ax.transAxes, fontsize=11,
85
  color=C_DIM, ha='right', va='bottom')
86
 
87
- # ── right: breakdown panel ────────────────────────────────────────────
88
  ax2 = axes[1]
89
  ax2.set_facecolor('#f1f5f9')
90
  for spine in ax2.spines.values():
91
  spine.set_color(C_BORDER)
92
  ax2.set_xticks([]); ax2.set_yticks([])
93
 
94
- rows = [
95
  ('episodes', f'{ep:.2f}', ACCENT),
96
  ('incidence', f'{inc:.3f}', C_INC),
97
  ('Ξ”z / ep.', f'{zs:.3f}', C_ZS),
98
  ('RR', f'{rr:.3f}', C_RR),
99
  ('─' * 10, '─' * 6, C_BORDER),
100
- #('exponent', f'{exponent:.4f}', '#475569'),
101
- #('exp(βˆ’x)', f'{1/np.exp(exponent):.4f}', '#475569'),
102
  ('─' * 10, '─' * 6, C_BORDER),
103
  ('PAF', f'{cur_paf*100:.2f}%', ACCENT),
104
  ]
105
 
106
- ax2.text(0.5, 0.97, 'BREAKDOWN', transform=ax2.transAxes,
107
  ha='center', fontsize=13, color=ACCENT, fontweight='bold')
108
 
109
- y_start = 0.88
110
  for i, (k, v, c) in enumerate(rows):
111
  y = y_start - i * 0.095
112
  ax2.text(0.08, y, k, transform=ax2.transAxes,
@@ -114,48 +114,47 @@ def draw(ep, inc, zs, rr):
114
  ax2.text(0.92, y, v, transform=ax2.transAxes,
115
  fontsize=11, color=c, va='center', ha='right', fontweight='bold')
116
 
117
- ax2.set_title('Parameters', color=C_TEXT, fontsize=13, pad=8)
118
 
119
- plt.tight_layout(pad=1.5)
120
  return fig
121
 
122
- # ── Gradio UI ─────────────────────────────────────────────────────────────
123
  with gr.Blocks(theme=gr.themes.Soft(), title="PAF Visualizer") as demo:
124
 
125
- gr.HTML("""
126
  <div style="background:#eff6ff;border:1px solid #bfdbfe;border-radius:10px;
127
  padding:12px 20px;margin-bottom:12px;font-family:monospace;">
128
  <span style="color:#1e293b;font-size:20px;font-weight:600;">
129
  Population Attributable Fraction Visualizer
130
  </span><br>
131
  <span style="color:#64748b;font-size:13px;">
132
- PAF = 1 βˆ’ 1/(episodes Γ— incidence Γ— Ξ”z Γ— RR)
133
  </span>
134
  </div>""")
135
 
136
- with gr.Row():
137
  with gr.Column():
138
  ep = gr.Slider(0, 15, value=4.2, step=0.1, label="Episodes")
139
  inc = gr.Slider(0.01, 1, value=0.3, step=0.01, label="Pathogen Incidence")
140
  zs = gr.Slider(0.01, 2, value=0.2, step=0.01, label="Ξ”z per Episode")
141
  rr = gr.Slider(1.01, 5, value=1.5, step=0.05, label="Relative Risk (RR)")
142
 
143
- reset_btn = gr.Button("Reset Defaults", variant="secondary")
144
 
145
- plot = gr.Plot(label="")
146
 
147
- # live update on any slider change
148
  for slider in [ep, inc, zs, rr]:
149
  slider.change(fn=draw, inputs=[ep, inc, zs, rr], outputs=plot)
150
 
151
- # reset button
152
  def reset():
153
  return 5.0, 0.3, 1.2, 2.5
154
 
155
- reset_btn.click(fn=reset, outputs=[ep, inc, zs, rr])
156
 
157
- # draw on load
158
  demo.load(fn=draw, inputs=[ep, inc, zs, rr], outputs=plot)
159
 
160
- demo.launch()
161
-
 
4
  import matplotlib.pyplot as plt
5
  import gradio as gr
6
 
7
+ # ── style ──────────────────────────────────────────────────────────────────
8
  BG = '#f8fafc'
9
  PANEL = '#ffffff'
10
  GRID = '#e2e8f0'
 
16
  C_DIM = '#64748b'
17
  C_BORDER= '#cbd5e1'
18
 
19
+ plt.rcParams.update({
20
  'figure.facecolor': BG, 'axes.facecolor': PANEL,
21
  'axes.edgecolor': C_BORDER, 'axes.labelcolor': C_DIM,
22
  'xtick.color': C_DIM, 'ytick.color': C_DIM,
 
24
  'text.color': C_TEXT, 'font.family': 'monospace',
25
  })
26
 
27
+ EP_RANGE = np.linspace(0, 15, 600)
28
 
29
+ def calc_paf(episodes, incidence, zscore, rr):
30
+ return 1 - 1 / np.exp(episodes * incidence * zscore * rr)
31
 
32
+ # ── plot function ──────────────────────────────────────────────────────────
33
  def draw(ep, inc, zs, rr):
34
  paf_curve = calc_paf(EP_RANGE, inc, zs, rr) * 100
35
  cur_paf = calc_paf(ep, inc, zs, rr)
36
  exponent = ep * inc * zs * rr
37
 
38
+ fig, axes = plt.subplots(1, 2, figsize=(15, 6),
39
  gridspec_kw={'width_ratios': [3, 1]})
40
  fig.patch.set_facecolor(BG)
41
 
42
+ # ── left: curve ───────────────────────────────────────────────────────
43
  ax = axes[0]
44
  ax.set_facecolor(PANEL)
45
  for spine in ax.spines.values():
46
  spine.set_color(C_BORDER)
47
 
48
+ # shadow + main curve
49
  ax.plot(EP_RANGE, paf_curve, color=ACCENT, linewidth=5, alpha=0.15)
50
  ax.plot(EP_RANGE, paf_curve, color=ACCENT, linewidth=2.2)
51
 
52
+ # crosshairs
53
  ax.axvline(ep, color=ACCENT, linestyle='--', linewidth=1.2, alpha=0.6)
54
  ax.axhline(cur_paf*100, color=ACCENT, linestyle='--', linewidth=1.2, alpha=0.3)
55
 
56
+ # dot at current point
57
  ax.scatter([ep], [cur_paf*100], color=ACCENT, s=80, zorder=5,
58
  edgecolors='white', linewidths=1.5)
59
 
60
+ # shaded area under curve up to current episode
61
  mask = EP_RANGE <= ep
62
  ax.fill_between(EP_RANGE[mask], paf_curve[mask], color=ACCENT, alpha=0.08)
63
 
64
+ ax.set_xlim(0, 15)
65
  ax.set_ylim(0, 102)
66
  ax.set_xlabel('Episodes', fontsize=11, labelpad=8)
67
  ax.set_ylabel('PAF (%)', fontsize=11, labelpad=8)
 
69
  color=C_TEXT, fontsize=13, pad=12, fontweight='normal')
70
  ax.grid(True, linewidth=0.8)
71
 
72
+ # annotation
73
  ax.annotate(
74
  f' {cur_paf*100:.1f}%',
75
  xy=(ep, cur_paf*100),
 
78
  arrowprops=dict(arrowstyle='->', color=ACCENT, lw=1.2)
79
  )
80
 
81
+ # formula watermark
82
  ax.text(0.98, 0.05,
83
+ 'PAF = 1 βˆ’ exp(βˆ’ep Γ— inc Γ— Ξ”z Γ— RR)',
84
  transform=ax.transAxes, fontsize=11,
85
  color=C_DIM, ha='right', va='bottom')
86
 
87
+ # ── right: breakdown panel ────────────────────────────────────────────
88
  ax2 = axes[1]
89
  ax2.set_facecolor('#f1f5f9')
90
  for spine in ax2.spines.values():
91
  spine.set_color(C_BORDER)
92
  ax2.set_xticks([]); ax2.set_yticks([])
93
 
94
+ rows = [
95
  ('episodes', f'{ep:.2f}', ACCENT),
96
  ('incidence', f'{inc:.3f}', C_INC),
97
  ('Ξ”z / ep.', f'{zs:.3f}', C_ZS),
98
  ('RR', f'{rr:.3f}', C_RR),
99
  ('─' * 10, '─' * 6, C_BORDER),
100
+ ('exponent', f'{exponent:.4f}', '#475569'),
101
+ ('exp(βˆ’x)', f'{1/np.exp(exponent):.4f}', '#475569'),
102
  ('─' * 10, '─' * 6, C_BORDER),
103
  ('PAF', f'{cur_paf*100:.2f}%', ACCENT),
104
  ]
105
 
106
+ ax2.text(0.5, 0.97, 'BREAKDOWN', transform=ax2.transAxes,
107
  ha='center', fontsize=13, color=ACCENT, fontweight='bold')
108
 
109
+ y_start = 0.88
110
  for i, (k, v, c) in enumerate(rows):
111
  y = y_start - i * 0.095
112
  ax2.text(0.08, y, k, transform=ax2.transAxes,
 
114
  ax2.text(0.92, y, v, transform=ax2.transAxes,
115
  fontsize=11, color=c, va='center', ha='right', fontweight='bold')
116
 
117
+ ax2.set_title('Parameters', color=C_TEXT, fontsize=13, pad=8)
118
 
119
+ plt.tight_layout(pad=1.5)
120
  return fig
121
 
122
+ # ── Gradio UI ───────────────────────────���─────────────────────────────────
123
  with gr.Blocks(theme=gr.themes.Soft(), title="PAF Visualizer") as demo:
124
 
125
+ gr.HTML("""
126
  <div style="background:#eff6ff;border:1px solid #bfdbfe;border-radius:10px;
127
  padding:12px 20px;margin-bottom:12px;font-family:monospace;">
128
  <span style="color:#1e293b;font-size:20px;font-weight:600;">
129
  Population Attributable Fraction Visualizer
130
  </span><br>
131
  <span style="color:#64748b;font-size:13px;">
132
+ PAF = 1 βˆ’ exp(βˆ’episodes Γ— incidence Γ— Ξ”z Γ— RR)
133
  </span>
134
  </div>""")
135
 
136
+ with gr.Row():
137
  with gr.Column():
138
  ep = gr.Slider(0, 15, value=4.2, step=0.1, label="Episodes")
139
  inc = gr.Slider(0.01, 1, value=0.3, step=0.01, label="Pathogen Incidence")
140
  zs = gr.Slider(0.01, 2, value=0.2, step=0.01, label="Ξ”z per Episode")
141
  rr = gr.Slider(1.01, 5, value=1.5, step=0.05, label="Relative Risk (RR)")
142
 
143
+ reset_btn = gr.Button("Reset Defaults", variant="secondary")
144
 
145
+ plot = gr.Plot(label="")
146
 
147
+ # live update on any slider change
148
  for slider in [ep, inc, zs, rr]:
149
  slider.change(fn=draw, inputs=[ep, inc, zs, rr], outputs=plot)
150
 
151
+ # reset button
152
  def reset():
153
  return 5.0, 0.3, 1.2, 2.5
154
 
155
+ reset_btn.click(fn=reset, outputs=[ep, inc, zs, rr])
156
 
157
+ # draw on load
158
  demo.load(fn=draw, inputs=[ep, inc, zs, rr], outputs=plot)
159
 
160
+ demo.launch()