Marcel0123 commited on
Commit
8c252bd
·
verified ·
1 Parent(s): dedc31d

Upload 2 files

Browse files
Files changed (1) hide show
  1. app.py +177 -61
app.py CHANGED
@@ -6,6 +6,7 @@ import matplotlib.pyplot as plt
6
  from sklearn import datasets
7
  from sklearn.preprocessing import StandardScaler
8
  from sklearn.decomposition import PCA
 
9
 
10
  FEATURE_LABELS = {
11
  "age": "Leeftijd",
@@ -63,7 +64,7 @@ def compute_overview_table(df: pd.DataFrame):
63
  if vals.size == 0:
64
  continue
65
  mean = float(vals.mean())
66
- pct_above = float((vals > 0).mean() * 100.0)
67
  pct_below = float((vals < 0).mean() * 100.0)
68
  rows.append({
69
  "Meting": FEATURE_LABELS.get(k, k),
@@ -72,68 +73,92 @@ def compute_overview_table(df: pd.DataFrame):
72
  "% onder gemiddelde": round(pct_below, 1),
73
  })
74
  table = pd.DataFrame(rows)
75
- note = (
76
- "Let op: waarden in deze dataset zijn **gestandaardiseerd**. "
77
- "`0` betekent ongeveer het **algemene gemiddelde**. "
78
- "Positief = hoger dan gemiddeld, negatief = lager dan gemiddeld."
79
- )
80
  return table, note
81
 
82
- def pca_biplot(color_label="BMI (Body Mass Index)", arrow_scale=2.0, point_size=32, alpha=0.85, n_components=10, standardize=True):
83
- df = load_diabetes_df()
84
- overview_df, overview_note = compute_overview_table(df)
85
-
86
- feature_keys = [c for c in df.columns if c != "target"]
87
- color_key = LABEL_TO_KEY.get(color_label, "bmi")
 
 
 
 
 
 
 
 
 
 
 
 
88
 
89
- X = df[feature_keys].values
 
 
90
  if standardize:
91
  scaler = StandardScaler(with_mean=True, with_std=True)
92
  Xs = scaler.fit_transform(X)
93
  else:
94
  Xs = X
95
-
96
  pca = PCA(n_components=min(int(n_components), Xs.shape[1]))
97
  Z = pca.fit_transform(Xs)
98
  loadings = pca.components_.T
99
  expl = pca.explained_variance_ratio_
 
100
 
101
- cvals = df[color_key].values
102
-
103
- fig1 = plt.figure(figsize=(7.8, 5.6))
104
- ax = fig1.add_subplot(111)
105
- sc = ax.scatter(Z[:, 0], Z[:, 1], c=cvals, s=point_size, alpha=alpha)
106
  cbar = plt.colorbar(sc, ax=ax, pad=0.02)
107
- cbar.set_label(f"Kleur: {FEATURE_LABELS.get(color_key, color_key)}")
108
- ax.set_xlabel("PC1")
109
- ax.set_ylabel("PC2")
110
  ax.set_title("PCA-biplot — punten (patiënten) + pijlen (belangrijkste metingen)")
111
-
112
- for i, key in enumerate(feature_keys):
113
  x_arrow = loadings[i, 0] * arrow_scale
114
  y_arrow = loadings[i, 1] * arrow_scale
115
  ax.arrow(0, 0, x_arrow, y_arrow, head_width=0.05, head_length=0.08, fc="k", ec="k", length_includes_head=True)
116
  ax.text(x_arrow * 1.08, y_arrow * 1.08, FEATURE_LABELS.get(key, key), fontsize=9, ha="center", va="center")
117
-
118
  ax.axhline(0, color="grey", linewidth=0.6, linestyle=":")
119
  ax.axvline(0, color="grey", linewidth=0.6, linestyle=":")
120
  ax.grid(True, linestyle=":", linewidth=0.6)
121
  plt.tight_layout()
 
122
 
123
- fig2 = plt.figure(figsize=(7.8, 3.8))
124
- ax2 = fig2.add_subplot(111)
 
125
  xs = np.arange(1, len(expl) + 1)
126
- ax2.bar(xs, expl, width=0.8, align="center")
127
- ax2.plot(xs, np.cumsum(expl), marker="o")
128
- ax2.set_xticks(xs)
129
- ax2.set_xlabel("Principal Component")
130
- ax2.set_ylabel("Explained variance ratio")
131
- ax2.set_title("Uitlegvariantie per component (balken) + cumulatief (lijn)")
132
- ax2.grid(True, linestyle=":", linewidth=0.6)
133
  plt.tight_layout()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
134
 
135
  load_df = pd.DataFrame({
136
- "feature_key": feature_keys,
137
  "PC1_loading": loadings[:, 0],
138
  "PC2_loading": loadings[:, 1],
139
  "PC1_abs": np.abs(loadings[:, 0]),
@@ -141,15 +166,12 @@ def pca_biplot(color_label="BMI (Body Mass Index)", arrow_scale=2.0, point_size=
141
  })
142
  load_df["Feature (PC1)"] = load_df["feature_key"].map(lambda k: FEATURE_LABELS.get(k, k))
143
  load_df["Feature (PC2)"] = load_df["feature_key"].map(lambda k: FEATURE_LABELS.get(k, k))
144
-
145
  top_pc1 = load_df.sort_values("PC1_abs", ascending=False)[["Feature (PC1)", "PC1_loading"]].head(6).reset_index(drop=True)
146
  top_pc2 = load_df.sort_values("PC2_abs", ascending=False)[["Feature (PC2)", "PC2_loading"]].head(6).reset_index(drop=True)
147
  max_len = max(len(top_pc1), len(top_pc2))
148
- top_pc1 = top_pc1.reindex(range(max_len))
149
- top_pc2 = top_pc2.reindex(range(max_len))
150
  table = pd.concat([top_pc1, top_pc2], axis=1)
151
 
152
- color_label_nl = FEATURE_LABELS.get(color_key, color_key)
153
  summary_md = f"""
154
  ### Wat zie je hier?
155
  - **Punten (patiënten)** geprojecteerd in 2D met **PCA**. Dicht bij elkaar = **lijken op elkaar** over meerdere metingen.
@@ -157,45 +179,139 @@ def pca_biplot(color_label="BMI (Body Mass Index)", arrow_scale=2.0, point_size=
157
  - **Pijlen** = bijdrage van **metingen** aan de richting van **PC1/PC2**. **Langere pijlen** wegen zwaarder.
158
  - **Balkgrafiek** = per component hoeveel variatie hij uitlegt; **lijn** = cumulatief.
159
  """
 
160
 
161
- return fig1, fig2, table, summary_md, overview_df, overview_note
 
 
 
 
 
162
 
163
- with gr.Blocks(title="PCA Biplot — Diabetes (NL labels)") as demo:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
164
  gr.HTML("""
165
  <style>
166
- .callout {padding:12px 14px; border-left:4px solid #2563eb; background:#f1f5f9; border-radius:6px; margin: 8px 0 18px;}
 
167
  .smallnote {font-size: 0.92em; opacity: 0.85;}
168
  </style>
169
  """)
170
 
171
- gr.Markdown("# PCA Biplot — Diabetes (NL labels)")
172
  gr.Markdown(MEDICAL_MD)
173
 
174
  with gr.Row():
175
  with gr.Column(scale=1):
176
- color_choices = [FEATURE_LABELS[k] for k in ["bmi","bp","s1","s2","s3","s4","s5","s6","age","sex","target"]]
177
- color_feat = gr.Dropdown(choices=color_choices, value=FEATURE_LABELS["bmi"], label="Kleur op meting")
178
- arrow_scale = gr.Slider(0.5, 5.0, value=2.0, step=0.1, label="Pijl-schaal (loadings)")
179
- point_size = gr.Slider(8, 80, value=32, step=2, label="Puntgrootte")
180
- alpha = gr.Slider(0.2, 1.0, value=0.85, step=0.05, label="Transparantie (punten)")
181
- n_components = gr.Slider(2, 10, value=10, step=1, label="Aantal PCA-componenten (voor variatieplot)")
182
- standardize = gr.Checkbox(value=True, label="Standaardiseer metingen (aanbevolen)")
183
- run_btn = gr.Button("Update visualisaties")
184
- gr.HTML('<div class="callout smallnote">💡 <b>Tip:</b> kies links een meting (bijv. BMI of cholesterol) en klik daarna op <b>Update visualisaties</b>.</div>')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
185
  with gr.Column(scale=2):
186
- plot_biplot = gr.Plot(label="PCA-biplot — punten + pijlen")
187
- plot_expl = gr.Plot(label="Uitlegvariantie per component")
188
- table = gr.Dataframe(headers=["Feature (PC1)", "Loading PC1", "Feature (PC2)", "Loading PC2"], row_count=6)
189
- summary = gr.Markdown()
190
- gr.Markdown("### Overzicht (gemiddelden & verdeling)")
191
- overview_tbl = gr.Dataframe(interactive=False)
192
- overview_note_md = gr.Markdown()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
193
 
194
  inputs = [color_feat, arrow_scale, point_size, alpha, n_components, standardize]
195
  run_btn.click(fn=pca_biplot, inputs=inputs,
196
- outputs=[plot_biplot, plot_expl, table, summary, overview_tbl, overview_note_md])
197
  demo.load(fn=pca_biplot, inputs=inputs,
198
- outputs=[plot_biplot, plot_expl, table, summary, overview_tbl, overview_note_md])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
199
 
200
  if __name__ == "__main__":
201
  demo.queue().launch(server_name="0.0.0.0", server_port=7860, ssr_mode=False, show_api=False)
 
6
  from sklearn import datasets
7
  from sklearn.preprocessing import StandardScaler
8
  from sklearn.decomposition import PCA
9
+ import os, time
10
 
11
  FEATURE_LABELS = {
12
  "age": "Leeftijd",
 
64
  if vals.size == 0:
65
  continue
66
  mean = float(vals.mean())
67
+ pct_above = float((vals > 0).mean() * 100.0) # standardized: 0 ~ mean
68
  pct_below = float((vals < 0).mean() * 100.0)
69
  rows.append({
70
  "Meting": FEATURE_LABELS.get(k, k),
 
73
  "% onder gemiddelde": round(pct_below, 1),
74
  })
75
  table = pd.DataFrame(rows)
76
+ note = ("Let op: waarden in deze dataset zijn **gestandaardiseerd**. "
77
+ "`0` betekent ongeveer het **algemene gemiddelde**. "
78
+ "Positief = hoger dan gemiddeld, negatief = lager dan gemiddeld.")
 
 
79
  return table, note
80
 
81
+ def compute_top_correlations(df: pd.DataFrame, top_n: int = 6):
82
+ feats = [c for c in df.columns if c != "target"]
83
+ corr = pd.DataFrame(df[feats]).corr()
84
+ pairs = []
85
+ for i, a in enumerate(feats):
86
+ for j, b in enumerate(feats):
87
+ if j <= i:
88
+ continue
89
+ pairs.append({
90
+ "Combinatie": f"{FEATURE_LABELS.get(a,a)} ↔ {FEATURE_LABELS.get(b,b)}",
91
+ "Correlatie": corr.loc[a, b]
92
+ })
93
+ out = pd.DataFrame(pairs)
94
+ out["Sterkte (|r|)"] = out["Correlatie"].abs()
95
+ out = out.sort_values("Sterkte (|r|)", ascending=False).head(top_n).reset_index(drop=True)
96
+ out["Correlatie"] = out["Correlatie"].round(3)
97
+ out["Sterkte (|r|)"] = out["Sterkte (|r|)"].round(3)
98
+ return out[["Combinatie", "Correlatie", "Sterkte (|r|)"]]
99
 
100
+ def compute_pca(df: pd.DataFrame, n_components: int, standardize: bool):
101
+ feats = [c for c in df.columns if c != "target"]
102
+ X = df[feats].values
103
  if standardize:
104
  scaler = StandardScaler(with_mean=True, with_std=True)
105
  Xs = scaler.fit_transform(X)
106
  else:
107
  Xs = X
 
108
  pca = PCA(n_components=min(int(n_components), Xs.shape[1]))
109
  Z = pca.fit_transform(Xs)
110
  loadings = pca.components_.T
111
  expl = pca.explained_variance_ratio_
112
+ return feats, Z, loadings, expl
113
 
114
+ def build_biplot(Z, loadings, feats, color_vals, arrow_scale, point_size, alpha, color_label_nl):
115
+ fig = plt.figure(figsize=(7.8, 5.6))
116
+ ax = fig.add_subplot(111)
117
+ sc = ax.scatter(Z[:, 0], Z[:, 1], c=color_vals, s=point_size, alpha=alpha)
 
118
  cbar = plt.colorbar(sc, ax=ax, pad=0.02)
119
+ cbar.set_label(f"Kleur: {color_label_nl}")
120
+ ax.set_xlabel("PC1"); ax.set_ylabel("PC2")
 
121
  ax.set_title("PCA-biplot — punten (patiënten) + pijlen (belangrijkste metingen)")
122
+ for i, key in enumerate(feats):
 
123
  x_arrow = loadings[i, 0] * arrow_scale
124
  y_arrow = loadings[i, 1] * arrow_scale
125
  ax.arrow(0, 0, x_arrow, y_arrow, head_width=0.05, head_length=0.08, fc="k", ec="k", length_includes_head=True)
126
  ax.text(x_arrow * 1.08, y_arrow * 1.08, FEATURE_LABELS.get(key, key), fontsize=9, ha="center", va="center")
 
127
  ax.axhline(0, color="grey", linewidth=0.6, linestyle=":")
128
  ax.axvline(0, color="grey", linewidth=0.6, linestyle=":")
129
  ax.grid(True, linestyle=":", linewidth=0.6)
130
  plt.tight_layout()
131
+ return fig
132
 
133
+ def build_variance_plot(expl):
134
+ fig = plt.figure(figsize=(7.8, 3.8))
135
+ ax = fig.add_subplot(111)
136
  xs = np.arange(1, len(expl) + 1)
137
+ ax.bar(xs, expl, width=0.8, align="center")
138
+ ax.plot(xs, np.cumsum(expl), marker="o")
139
+ ax.set_xticks(xs)
140
+ ax.set_xlabel("Principal Component")
141
+ ax.set_ylabel("Explained variance ratio")
142
+ ax.set_title("Uitlegvariantie per component (balken) + cumulatief (lijn)")
143
+ ax.grid(True, linestyle=":", linewidth=0.6)
144
  plt.tight_layout()
145
+ return fig
146
+
147
+ def pca_biplot(color_label="BMI (Body Mass Index)", arrow_scale=2.0, point_size=32, alpha=0.85, n_components=10, standardize=True):
148
+ df = load_diabetes_df()
149
+ overview_df, overview_note = compute_overview_table(df)
150
+ corr_tbl = compute_top_correlations(df)
151
+
152
+ feats, Z, loadings, expl = compute_pca(df, n_components, standardize)
153
+ color_key = LABEL_TO_KEY.get(color_label, "bmi")
154
+ color_label_nl = FEATURE_LABELS.get(color_key, color_key)
155
+ color_vals = df[color_key].values
156
+
157
+ fig1 = build_biplot(Z, loadings, feats, color_vals, arrow_scale, point_size, alpha, color_label_nl)
158
+ fig2 = build_variance_plot(expl)
159
 
160
  load_df = pd.DataFrame({
161
+ "feature_key": feats,
162
  "PC1_loading": loadings[:, 0],
163
  "PC2_loading": loadings[:, 1],
164
  "PC1_abs": np.abs(loadings[:, 0]),
 
166
  })
167
  load_df["Feature (PC1)"] = load_df["feature_key"].map(lambda k: FEATURE_LABELS.get(k, k))
168
  load_df["Feature (PC2)"] = load_df["feature_key"].map(lambda k: FEATURE_LABELS.get(k, k))
 
169
  top_pc1 = load_df.sort_values("PC1_abs", ascending=False)[["Feature (PC1)", "PC1_loading"]].head(6).reset_index(drop=True)
170
  top_pc2 = load_df.sort_values("PC2_abs", ascending=False)[["Feature (PC2)", "PC2_loading"]].head(6).reset_index(drop=True)
171
  max_len = max(len(top_pc1), len(top_pc2))
172
+ top_pc1 = top_pc1.reindex(range(max_len)); top_pc2 = top_pc2.reindex(range(max_len))
 
173
  table = pd.concat([top_pc1, top_pc2], axis=1)
174
 
 
175
  summary_md = f"""
176
  ### Wat zie je hier?
177
  - **Punten (patiënten)** geprojecteerd in 2D met **PCA**. Dicht bij elkaar = **lijken op elkaar** over meerdere metingen.
 
179
  - **Pijlen** = bijdrage van **metingen** aan de richting van **PC1/PC2**. **Langere pijlen** wegen zwaarder.
180
  - **Balkgrafiek** = per component hoeveel variatie hij uitlegt; **lijn** = cumulatief.
181
  """
182
+ return fig1, fig2, table, summary_md, overview_df, overview_note, corr_tbl
183
 
184
+ def animate_pca(color_label="BMI (Body Mass Index)", point_size=32, alpha=0.85, n_components=10, standardize=True, frames=40, pause=0.0):
185
+ df = load_diabetes_df()
186
+ feats, Z, loadings, expl = compute_pca(df, n_components, standardize)
187
+
188
+ color_key = LABEL_TO_KEY.get(color_label, "bmi")
189
+ color_vals = df[color_key].values
190
 
191
+ for i in range(frames):
192
+ t = i / max(1, frames-1) # 0..1
193
+ w1 = min(1.0, t * 2.0)
194
+ w2 = max(0.0, (t - 0.5) * 2.0)
195
+ coords = np.column_stack([Z[:, 0] * w1, Z[:, 1] * w2])
196
+
197
+ fig = plt.figure(figsize=(7.8, 5.6))
198
+ ax = fig.add_subplot(111)
199
+ ax.scatter(coords[:, 0], coords[:, 1], c=color_vals, s=point_size, alpha=alpha)
200
+ ax.set_xlabel("PC1 (opbouw)"); ax.set_ylabel("PC2 (opbouw)")
201
+ title = "PCA-projectie (animatie) — " + ("PC1 →" if w2 == 0 else "PC1 + PC2")
202
+ ax.set_title(f"{title} — frame {i+1}/{frames}")
203
+ ax.axhline(0, color="grey", linewidth=0.6, linestyle=":")
204
+ ax.axvline(0, color="grey", linewidth=0.6, linestyle=":")
205
+ ax.grid(True, linestyle=":", linewidth=0.6)
206
+ plt.tight_layout()
207
+ yield fig
208
+ if pause > 0:
209
+ time.sleep(pause)
210
+
211
+ def export_biplot_png(color_label="BMI (Body Mass Index)", arrow_scale=2.0, point_size=32, alpha=0.85, n_components=10, standardize=True):
212
+ df = load_diabetes_df()
213
+ feats, Z, loadings, expl = compute_pca(df, n_components, standardize)
214
+ color_key = LABEL_TO_KEY.get(color_label, "bmi")
215
+ color_label_nl = FEATURE_LABELS.get(color_key, color_key)
216
+ color_vals = df[color_key].values
217
+ fig = build_biplot(Z, loadings, feats, color_vals, arrow_scale, point_size, alpha, color_label_nl)
218
+ path = f"/mnt/data/biplot_{int(time.time())}.png"
219
+ fig.savefig(path, dpi=150, bbox_inches="tight")
220
+ plt.close(fig)
221
+ return path
222
+
223
+ def export_variance_png(n_components=10, standardize=True):
224
+ df = load_diabetes_df()
225
+ feats, Z, loadings, expl = compute_pca(df, n_components, standardize)
226
+ fig = build_variance_plot(expl)
227
+ path = f"/mnt/data/variance_{int(time.time())}.png"
228
+ fig.savefig(path, dpi=150, bbox_inches="tight")
229
+ plt.close(fig)
230
+ return path
231
+
232
+ with gr.Blocks(title="PCA Biplot — Diabetes (Dashboard)") as demo:
233
  gr.HTML("""
234
  <style>
235
+ .card {background:#fff; border:1px solid #e5e7eb; border-radius:12px; padding:14px; box-shadow: 0 1px 4px rgba(0,0,0,0.06);}
236
+ .callout {padding:12px 14px; border-left:4px solid #2563eb; background:#f1f5f9; border-radius:8px; margin: 8px 0 18px;}
237
  .smallnote {font-size: 0.92em; opacity: 0.85;}
238
  </style>
239
  """)
240
 
241
+ gr.Markdown("# PCA Biplot — Diabetes (Dashboard)")
242
  gr.Markdown(MEDICAL_MD)
243
 
244
  with gr.Row():
245
  with gr.Column(scale=1):
246
+ with gr.Group():
247
+ gr.Markdown("### Instellingen")
248
+ color_choices = [FEATURE_LABELS[k] for k in ["bmi","bp","s1","s2","s3","s4","s5","s6","age","sex","target"]]
249
+ color_feat = gr.Dropdown(choices=color_choices, value=FEATURE_LABELS["bmi"], label="Kleur op meting")
250
+ arrow_scale = gr.Slider(0.5, 5.0, value=2.0, step=0.1, label="Pijl-schaal (loadings)")
251
+ point_size = gr.Slider(8, 80, value=32, step=2, label="Puntgrootte")
252
+ alpha = gr.Slider(0.2, 1.0, value=0.85, step=0.05, label="Transparantie (punten)")
253
+ n_components = gr.Slider(2, 10, value=10, step=1, label="Aantal PCA-componenten")
254
+ standardize = gr.Checkbox(value=True, label="Standaardiseer metingen (aanbevolen)")
255
+ run_btn = gr.Button("Update visualisaties")
256
+ gr.HTML('<div class="callout smallnote">💡 <b>Tip:</b> Kies links een meting (bijv. BMI of cholesterol) en klik daarna op <b>Update visualisaties</b>.</div>')
257
+ with gr.Group():
258
+ gr.Markdown("### Animatie")
259
+ animate_btn = gr.Button("▶ Animate PCA (PC1 → PC2)")
260
+ anim_plot = gr.Plot(label="Animatie van projectie")
261
+
262
+ with gr.Group():
263
+ gr.Markdown("### Downloads")
264
+ dl_biplot = gr.DownloadButton("Download biplot (PNG)")
265
+ dl_var = gr.DownloadButton("Download variatieplot (PNG)")
266
+ file_biplot = gr.File(label="Biplot PNG", visible=False)
267
+ file_var = gr.File(label="Variatieplot PNG", visible=False)
268
+
269
  with gr.Column(scale=2):
270
+ with gr.Row():
271
+ with gr.Column():
272
+ gr.Markdown("### Biplot")
273
+ plot_biplot = gr.Plot()
274
+ with gr.Column():
275
+ gr.Markdown("### Uitlegvariantie")
276
+ plot_expl = gr.Plot()
277
+ with gr.Row():
278
+ with gr.Column():
279
+ gr.Markdown("### Top-features (PC1 / PC2)")
280
+ table = gr.Dataframe(headers=["Feature (PC1)", "Loading PC1", "Feature (PC2)", "Loading PC2"], row_count=6)
281
+ with gr.Column():
282
+ gr.Markdown("### Overzicht (gemiddelden & verdeling)")
283
+ overview_tbl = gr.Dataframe(interactive=False)
284
+ overview_note_md = gr.Markdown()
285
+ with gr.Row():
286
+ with gr.Column():
287
+ gr.Markdown("### Samenvatting")
288
+ summary = gr.Markdown()
289
+ with gr.Column():
290
+ gr.Markdown("### Top correlaties (features)")
291
+ topcorr_tbl = gr.Dataframe(interactive=False)
292
 
293
  inputs = [color_feat, arrow_scale, point_size, alpha, n_components, standardize]
294
  run_btn.click(fn=pca_biplot, inputs=inputs,
295
+ outputs=[plot_biplot, plot_expl, table, summary, overview_tbl, overview_note_md, topcorr_tbl])
296
  demo.load(fn=pca_biplot, inputs=inputs,
297
+ outputs=[plot_biplot, plot_expl, table, summary, overview_tbl, overview_note_md, topcorr_tbl])
298
+
299
+ animate_btn.click(fn=animate_pca,
300
+ inputs=[color_feat, point_size, alpha, n_components, standardize],
301
+ outputs=anim_plot)
302
+
303
+ dl_biplot.click(fn=export_biplot_png,
304
+ inputs=[color_feat, arrow_scale, point_size, alpha, n_components, standardize],
305
+ outputs=[dl_biplot])
306
+ dl_biplot.click(fn=export_biplot_png,
307
+ inputs=[color_feat, arrow_scale, point_size, alpha, n_components, standardize],
308
+ outputs=[file_biplot])
309
+ dl_var.click(fn=export_variance_png,
310
+ inputs=[n_components, standardize],
311
+ outputs=[dl_var])
312
+ dl_var.click(fn=export_variance_png,
313
+ inputs=[n_components, standardize],
314
+ outputs=[file_var])
315
 
316
  if __name__ == "__main__":
317
  demo.queue().launch(server_name="0.0.0.0", server_port=7860, ssr_mode=False, show_api=False)