HanningChen commited on
Commit
5ee17b1
·
1 Parent(s): 044bb04

Add bit selection

Browse files
Files changed (1) hide show
  1. webui/static/main.js +138 -253
webui/static/main.js CHANGED
@@ -1,285 +1,170 @@
1
- window.addEventListener("error", (e) => {
2
- const log = document.querySelector("#statusLog");
3
- if (log) log.textContent = "JS error: " + (e.message || e.error) + "\n" + log.textContent;
4
- });
5
-
6
- const $ = (sel) => document.querySelector(sel);
7
-
8
- const form = $("#runForm");
9
- const runBtn = $("#runBtn");
10
- const runBtnText = $("#runBtnText");
11
- const spinner = $("#spinner");
12
- const resetBtn = $("#resetBtn");
13
-
14
- const fileInput = $("#fileInput");
15
- const dropzone = $("#dropzone");
16
- const fileMeta = $("#fileMeta");
17
- const previewWrap = $("#previewWrap");
18
- const previewImg = $("#previewImg");
19
-
20
- const statusDot = $("#statusDot");
21
- const statusText = $("#statusText");
22
- const statusLog = $("#statusLog");
23
- const jobPill = $("#jobPill");
24
-
25
- const imgInput = $("#imgInput");
26
- const imgYolo = $("#imgYolo");
27
- const imgSelected = $("#imgSelected");
28
- const meta = $("#meta");
29
-
30
- const dlInput = $("#dlInput");
31
- const dlYolo = $("#dlYolo");
32
- const dlSelected = $("#dlSelected");
33
- const copyMetaBtn = $("#copyMetaBtn");
34
-
35
- function setStatus(kind, text, logLine) {
36
- // kind: idle | run | ok | bad
37
- statusDot.className = `dot ${kind}`;
38
- statusText.textContent = text;
39
- if (logLine) statusLog.textContent = logLine + "\n" + statusLog.textContent;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  }
41
 
42
- function setRunning(isRunning) {
43
- runBtn.disabled = isRunning;
44
- spinner.classList.toggle("hidden", !isRunning);
45
- runBtnText.textContent = isRunning ? "Running…" : "Run";
46
- }
47
-
48
- function clearResults() {
49
- imgInput.removeAttribute("src");
50
- imgYolo.removeAttribute("src");
51
- imgSelected.removeAttribute("src");
52
- meta.textContent = "";
53
- jobPill.textContent = "job: —";
54
 
55
- [dlInput, dlYolo, dlSelected].forEach(a => {
56
- a.classList.add("hidden");
57
- a.removeAttribute("href");
58
- });
59
- }
60
 
61
- function setPreview(file) {
62
- if (!file) {
63
- previewWrap.classList.add("hidden");
64
- previewImg.removeAttribute("src");
65
- fileMeta.textContent = "No file selected";
66
  return;
67
  }
68
- fileMeta.textContent = `${file.name} • ${(file.size / 1024).toFixed(1)} KB`;
69
- const url = URL.createObjectURL(file);
70
- previewImg.src = url;
71
- previewWrap.classList.remove("hidden");
72
- }
73
-
74
- (function () {
75
- const noiseType = document.getElementById("noiseType");
76
- if (!noiseType) return;
77
-
78
- const panels = {
79
- none: document.getElementById("noisePanelNone"),
80
- gaussian: document.getElementById("noisePanelGaussian"),
81
- linear: document.getElementById("noisePanelLinear"),
82
- adv: document.getElementById("noisePanelAdv"),
83
- };
84
-
85
- const sliders = {
86
- gaussian: document.getElementById("noiseGaussian"),
87
- linear: document.getElementById("noiseLinear"),
88
- adv: document.getElementById("noiseAdv"),
89
- };
90
-
91
- const labels = {
92
- gaussian: document.getElementById("noiseValGaussian"),
93
- linear: document.getElementById("noiseValLinear"),
94
- adv: document.getElementById("noiseValAdv"),
95
- };
96
-
97
- const hiddenStrength = document.getElementById("noiseStrength");
98
-
99
- // Map dropdown values to ONE of the existing panel keys.
100
- function noiseFamily(val) {
101
- const t = String(val || "none").toLowerCase();
102
-
103
- if (t === "none" || t === "off") return "none";
104
-
105
- // gaussian variants
106
- if (t === "gaussian" || t.includes("gauss")) return "gaussian";
107
-
108
- // linear variants
109
- if (t === "linear" || t.includes("linear")) return "linear";
110
-
111
- // adversarial variants (covers: "simple_adversarial_noise", "fgsm", "pgd", etc.)
112
- if (
113
- t === "adv" ||
114
- t.startsWith("adv") ||
115
- t.includes("adversarial") ||
116
- t.includes("attack") ||
117
- t.includes("fgsm") ||
118
- t.includes("pgd")
119
- ) return "adv";
120
-
121
- return "none";
122
- }
123
-
124
 
125
- function updateHiddenStrength() {
126
- const fam = noiseFamily(noiseType.value);
127
- if (fam === "none") {
128
- hiddenStrength.value = "0";
129
- return;
130
- }
131
- hiddenStrength.value = String(sliders[fam]?.value ?? "0");
132
- }
133
 
134
- function showPanelForCurrentSelection() {
135
- const fam = noiseFamily(noiseType.value);
136
- Object.values(panels).forEach((p) => p && p.classList.add("hidden"));
137
- (panels[fam] || panels.none).classList.remove("hidden");
138
- updateHiddenStrength();
 
 
 
139
  }
 
140
 
141
- // Slider updates
142
- Object.keys(sliders).forEach((k) => {
143
- sliders[k]?.addEventListener("input", () => {
144
- if (labels[k]) labels[k].textContent = sliders[k].value;
145
- if (noiseFamily(noiseType.value) === k) updateHiddenStrength();
146
- });
147
- });
148
-
149
- // Dropdown updates
150
- noiseType.addEventListener("change", showPanelForCurrentSelection);
151
-
152
- // Initialize from current dropdown value (NOT hard-coded none)
153
- showPanelForCurrentSelection();
154
- })();
155
-
156
- (function () {
157
- // Tabs
158
- const tabBtns = document.querySelectorAll(".tabBtn");
159
- const panels = document.querySelectorAll(".tabPanel");
160
- tabBtns.forEach((b) => {
161
- b.addEventListener("click", () => {
162
- tabBtns.forEach((x) => x.classList.remove("active"));
163
- panels.forEach((p) => p.classList.add("hidden"));
164
- b.classList.add("active");
165
- const id = b.getAttribute("data-tab");
166
- document.getElementById(id)?.classList.remove("hidden");
167
- });
168
- });
169
-
170
- // Hardware noise sliders -> label text
171
- const w = document.getElementById("hwNoiseWidth");
172
- const s = document.getElementById("hwNoiseStrength");
173
- const wv = document.getElementById("hwNoiseWidthVal");
174
- const sv = document.getElementById("hwNoiseStrengthVal");
175
- if (w && wv) w.addEventListener("input", () => (wv.textContent = w.value));
176
- if (s && sv) s.addEventListener("input", () => (sv.textContent = s.value));
177
- })();
178
-
179
-
180
- dropzone.addEventListener("click", () => fileInput.click());
181
- dropzone.addEventListener("keydown", (e) => {
182
- if (e.key === "Enter" || e.key === " ") fileInput.click();
183
- });
184
-
185
- fileInput.addEventListener("change", () => {
186
- const file = fileInput.files && fileInput.files[0];
187
- setPreview(file);
188
- });
189
 
190
- ["dragenter", "dragover"].forEach(evt => {
191
- dropzone.addEventListener(evt, (e) => {
192
- e.preventDefault();
193
- e.stopPropagation();
194
- dropzone.classList.add("drag");
195
- });
196
- });
197
 
198
- ["dragleave", "drop"].forEach(evt => {
199
- dropzone.addEventListener(evt, (e) => {
200
- e.preventDefault();
201
- e.stopPropagation();
202
- dropzone.classList.remove("drag");
203
  });
204
  });
205
 
206
- dropzone.addEventListener("drop", (e) => {
207
- const file = e.dataTransfer.files && e.dataTransfer.files[0];
208
- if (!file) return;
209
 
210
- // Set preview
211
- setPreview(file);
212
-
213
- // Safely assign to input (works across browsers)
214
- const dt = new DataTransfer();
215
- dt.items.add(file);
216
- fileInput.files = dt.files;
217
- });
218
-
219
- resetBtn.addEventListener("click", () => {
220
- form.reset();
221
- fileInput.value = "";
222
- setPreview(null);
223
- clearResults();
224
- statusLog.textContent = "Waiting for input…";
225
- setStatus("idle", "Idle", "Reset UI.");
226
- });
227
-
228
- copyMetaBtn.addEventListener("click", async () => {
229
- const text = meta.textContent || "";
230
- if (!text) return;
231
- await navigator.clipboard.writeText(text);
232
- setStatus("ok", "Done", "Copied metadata to clipboard.");
233
- });
234
 
 
 
 
235
  form.addEventListener("submit", async (e) => {
236
  e.preventDefault();
237
 
238
- const file = fileInput.files && fileInput.files[0];
239
- if (!file) {
240
- setStatus("bad", "Error", "No file selected.");
241
- return;
242
- }
243
-
244
- setRunning(true);
245
- setStatus("run", "Running", "Submitting request to /api/run …");
246
 
247
  const fd = new FormData(form);
248
 
249
- try {
250
- const resp = await fetch("/api/run", { method: "POST", body: fd });
251
- const data = await resp.json();
252
-
253
- if (!resp.ok || !data.ok) {
254
- throw new Error(data?.error || `HTTP ${resp.status}`);
255
- }
256
 
257
- jobPill.textContent = `job: ${data.job_id}`;
258
- setStatus("ok", "Done", `Inference finished. job_id=${data.job_id}`);
 
 
 
259
 
260
- // Update images (cache-bust)
261
- const bust = `t=${Date.now()}`;
262
- imgInput.src = `${data.image_urls.input}?${bust}`;
263
- imgYolo.src = `${data.image_urls.yolo}?${bust}`;
264
- imgSelected.src = `${data.image_urls.selected}?${bust}`;
265
 
266
- // Open links
267
- dlInput.href = data.image_urls.input;
268
- dlYolo.href = data.image_urls.yolo;
269
- dlSelected.href = data.image_urls.selected;
270
- [dlInput, dlYolo, dlSelected].forEach(a => a.classList.remove("hidden"));
271
 
272
- // Meta
273
- meta.textContent = JSON.stringify({
274
- task_id: data.task_id,
275
- task_name: data.task_name,
276
- selected_indices: data.selected_indices,
277
- job_id: data.job_id,
278
- }, null, 2);
279
 
 
280
  } catch (err) {
281
- setStatus("bad", "Error", String(err));
282
  } finally {
283
- setRunning(false);
 
 
284
  }
285
  });
 
 
 
 
 
 
 
 
1
+ // ==========================
2
+ // DOM helpers
3
+ // ==========================
4
+ const $ = (id) => document.getElementById(id);
5
+
6
+ // ==========================
7
+ // Elements
8
+ // ==========================
9
+ const form = $("runForm");
10
+ const runBtn = $("runBtn");
11
+ const runBtnText = $("runBtnText");
12
+ const spinner = $("spinner");
13
+
14
+ const noiseType = $("noiseType");
15
+ const noiseStrengthHidden = $("noiseStrength");
16
+
17
+ const noisePanels = {
18
+ none: $("noisePanelNone"),
19
+ gaussian: $("noisePanelGaussian"),
20
+ linear: $("noisePanelLinear"),
21
+ adv: $("noisePanelAdv"),
22
+ };
23
+
24
+ const noiseSliders = {
25
+ gaussian: $("noiseGaussian"),
26
+ linear: $("noiseLinear"),
27
+ adv: $("noiseAdv"),
28
+ };
29
+
30
+ const noiseVals = {
31
+ gaussian: $("noiseValGaussian"),
32
+ linear: $("noiseValLinear"),
33
+ adv: $("noiseValAdv"),
34
+ };
35
+
36
+ // HDC / score function
37
+ const scoreSelect = document.querySelector('select[name="score_function"]');
38
+ const hdcBitsField = $("hdcBitsField");
39
+ const hdcBitsSelect = $("hdcBits");
40
+ const hdvDimSelect = document.querySelector('select[name="hdv_dim"]');
41
+
42
+ // HW noise
43
+ const hwNoiseDist = $("hwNoiseDist");
44
+ const hwNoiseWidth = $("hwNoiseWidth");
45
+ const hwNoiseStrength = $("hwNoiseStrength");
46
+ const hwNoiseWidthVal = $("hwNoiseWidthVal");
47
+ const hwNoiseStrengthVal = $("hwNoiseStrengthVal");
48
+
49
+ // Output
50
+ const imgInput = $("imgInput");
51
+ const imgYolo = $("imgYolo");
52
+ const imgSelected = $("imgSelected");
53
+ const metaBox = $("meta");
54
+
55
+ // ==========================
56
+ // Noise helpers
57
+ // ==========================
58
+ function noiseFamily(val) {
59
+ if (!val || val === "none") return "none";
60
+ if (val === "gaussian") return "gaussian";
61
+ if (val === "linear") return "linear";
62
+ if (val.startsWith("adv")) return "adv";
63
+ return "none";
64
  }
65
 
66
+ function updateNoiseUI() {
67
+ const fam = noiseFamily(noiseType.value);
 
 
 
 
 
 
 
 
 
 
68
 
69
+ Object.values(noisePanels).forEach((p) => p.classList.add("hidden"));
70
+ noiseStrengthHidden.value = "0";
 
 
 
71
 
72
+ if (fam === "none") {
73
+ noisePanels.none.classList.remove("hidden");
 
 
 
74
  return;
75
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
76
 
77
+ noisePanels[fam].classList.remove("hidden");
78
+ const slider = noiseSliders[fam];
79
+ const val = slider.value;
80
+ noiseStrengthHidden.value = val;
81
+ noiseVals[fam].innerText = val;
82
+ }
 
 
83
 
84
+ // ==========================
85
+ // HDC helpers
86
+ // ==========================
87
+ function updateHdcBitsVisibility() {
88
+ if (scoreSelect.value === "HDC") {
89
+ hdcBitsField.style.display = "block";
90
+ } else {
91
+ hdcBitsField.style.display = "none";
92
  }
93
+ }
94
 
95
+ // ==========================
96
+ // HW noise helpers
97
+ // ==========================
98
+ function updateHwNoiseUI() {
99
+ hwNoiseWidthVal.innerText = hwNoiseWidth.value;
100
+ hwNoiseStrengthVal.innerText = hwNoiseStrength.value;
101
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
102
 
103
+ // ==========================
104
+ // Event bindings
105
+ // ==========================
106
+ noiseType.addEventListener("change", updateNoiseUI);
 
 
 
107
 
108
+ Object.keys(noiseSliders).forEach((k) => {
109
+ noiseSliders[k].addEventListener("input", () => {
110
+ noiseVals[k].innerText = noiseSliders[k].value;
111
+ noiseStrengthHidden.value = noiseSliders[k].value;
 
112
  });
113
  });
114
 
115
+ scoreSelect.addEventListener("change", updateHdcBitsVisibility);
 
 
116
 
117
+ hwNoiseWidth.addEventListener("input", updateHwNoiseUI);
118
+ hwNoiseStrength.addEventListener("input", updateHwNoiseUI);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
119
 
120
+ // ==========================
121
+ // Form submit
122
+ // ==========================
123
  form.addEventListener("submit", async (e) => {
124
  e.preventDefault();
125
 
126
+ runBtn.disabled = true;
127
+ spinner.classList.remove("hidden");
128
+ runBtnText.innerText = "Running...";
 
 
 
 
 
129
 
130
  const fd = new FormData(form);
131
 
132
+ // --- Explicit HDC bits handling (IMPORTANT) ---
133
+ if (scoreSelect.value === "HDC") {
134
+ fd.set("hdc_bits", hdcBitsSelect.value);
135
+ } else {
136
+ fd.set("hdc_bits", "32"); // backend default
137
+ }
 
138
 
139
+ try {
140
+ const res = await fetch("/api/run", {
141
+ method: "POST",
142
+ body: fd,
143
+ });
144
 
145
+ const data = await res.json();
 
 
 
 
146
 
147
+ if (!data.ok) {
148
+ throw new Error(data.error || "Unknown error");
149
+ }
 
 
150
 
151
+ imgInput.src = data.image_urls.input;
152
+ imgYolo.src = data.image_urls.yolo;
153
+ imgSelected.src = data.image_urls.selected;
 
 
 
 
154
 
155
+ metaBox.innerText = JSON.stringify(data, null, 2);
156
  } catch (err) {
157
+ alert("Error: " + err.message);
158
  } finally {
159
+ spinner.classList.add("hidden");
160
+ runBtn.disabled = false;
161
+ runBtnText.innerText = "Run";
162
  }
163
  });
164
+
165
+ // ==========================
166
+ // Init on page load
167
+ // ==========================
168
+ updateNoiseUI();
169
+ updateHdcBitsVisibility();
170
+ updateHwNoiseUI();